Adapters
chemistry
biology
finance
legal
art
climate
agent
Merge
BACCHUS45's picture
Create billing-service/index.js
b38ce6c verified
const express = require('express');
const bodyParser = require('body-parser');
const { Pool } = require('pg');
const Redis = require('ioredis');
const fetch = require('node-fetch');
const pool = new Pool({ connectionString: process.env.DATABASE_URL || 'postgresql://localhost/integral' });
const redis = new Redis(process.env.REDIS_URL || 'redis://localhost:6379');
const app = express();
app.use(bodyParser.json());
redis.subscribe('payouts:created', () => console.log('listening for payouts'));
redis.on('message', async (channel, msg) => {
if (channel !== 'payouts:created') return;
const { payoutId } = JSON.parse(msg);
console.log('handle payout', payoutId);
// naive: call settle endpoint
try {
await settlePayout(payoutId);
} catch (err) {
console.error(err);
}
});
async function settlePayout(payoutId) {
// fetch payout
const r = await pool.query('SELECT * FROM payouts WHERE id=$1 FOR UPDATE', [payoutId]);
if (r.rowCount === 0) throw new Error('payout not found');
const payout = r.rows[0];
if (payout.status !== 'created') return;
// mark queued
await pool.query('UPDATE payouts SET status=$1 WHERE id=$2', ['processing', payoutId]);
// Example: call external TMS / Accounting system / Payment Gateway
// This is a stub — replace with real API call (e.g. TMS settlement API, or bank transfer).
const remote = await fakePaymentGateway(payout);
if (remote.success) {
const txRef = remote.txRef;
await pool.query('UPDATE payouts SET status=$1, tx_ref=$2, settled_at=now() WHERE id=$3',
['settled', txRef, payoutId]);
await redis.publish('payouts:settled', JSON.stringify({ payoutId, txRef }));
} else {
await pool.query('UPDATE payouts SET status=$1 WHERE id=$2', ['failed', payoutId]);
await redis.publish('payouts:failed', JSON.stringify({ payoutId }));
}
}
async function fakePaymentGateway(payout) {
// fake delay
await new Promise(r => setTimeout(r, 600));
return { success: true, txRef: `TX-${Date.now()}-${Math.floor(Math.random()*1000)}` };
}
app.post('/settle/:payoutId', async (req, res) => {
try {
const { payoutId } = req.params;
await settlePayout(payoutId);
res.json({ success: true });
} catch (err) {
console.error(err);
res.status(500).json({ success: false, error: err.message });
}
});
app.listen(process.env.PORT || 3010, () => console.log('billing-service listening 3010'));