Adapters
chemistry
biology
finance
legal
art
climate
agent
Merge
BACCHUS45 commited on
Commit
b38ce6c
·
verified ·
1 Parent(s): e7f2fbf

Create billing-service/index.js

Browse files
Files changed (1) hide show
  1. billing-service/index.js +70 -0
billing-service/index.js ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const express = require('express');
2
+ const bodyParser = require('body-parser');
3
+ const { Pool } = require('pg');
4
+ const Redis = require('ioredis');
5
+ const fetch = require('node-fetch');
6
+
7
+ const pool = new Pool({ connectionString: process.env.DATABASE_URL || 'postgresql://localhost/integral' });
8
+ const redis = new Redis(process.env.REDIS_URL || 'redis://localhost:6379');
9
+
10
+ const app = express();
11
+ app.use(bodyParser.json());
12
+
13
+ redis.subscribe('payouts:created', () => console.log('listening for payouts'));
14
+
15
+ redis.on('message', async (channel, msg) => {
16
+ if (channel !== 'payouts:created') return;
17
+ const { payoutId } = JSON.parse(msg);
18
+ console.log('handle payout', payoutId);
19
+ // naive: call settle endpoint
20
+ try {
21
+ await settlePayout(payoutId);
22
+ } catch (err) {
23
+ console.error(err);
24
+ }
25
+ });
26
+
27
+
28
+ async function settlePayout(payoutId) {
29
+ // fetch payout
30
+ const r = await pool.query('SELECT * FROM payouts WHERE id=$1 FOR UPDATE', [payoutId]);
31
+ if (r.rowCount === 0) throw new Error('payout not found');
32
+ const payout = r.rows[0];
33
+ if (payout.status !== 'created') return;
34
+
35
+ // mark queued
36
+ await pool.query('UPDATE payouts SET status=$1 WHERE id=$2', ['processing', payoutId]);
37
+
38
+ // Example: call external TMS / Accounting system / Payment Gateway
39
+ // This is a stub — replace with real API call (e.g. TMS settlement API, or bank transfer).
40
+ const remote = await fakePaymentGateway(payout);
41
+
42
+ if (remote.success) {
43
+ const txRef = remote.txRef;
44
+ await pool.query('UPDATE payouts SET status=$1, tx_ref=$2, settled_at=now() WHERE id=$3',
45
+ ['settled', txRef, payoutId]);
46
+ await redis.publish('payouts:settled', JSON.stringify({ payoutId, txRef }));
47
+ } else {
48
+ await pool.query('UPDATE payouts SET status=$1 WHERE id=$2', ['failed', payoutId]);
49
+ await redis.publish('payouts:failed', JSON.stringify({ payoutId }));
50
+ }
51
+ }
52
+
53
+ async function fakePaymentGateway(payout) {
54
+ // fake delay
55
+ await new Promise(r => setTimeout(r, 600));
56
+ return { success: true, txRef: `TX-${Date.now()}-${Math.floor(Math.random()*1000)}` };
57
+ }
58
+
59
+ app.post('/settle/:payoutId', async (req, res) => {
60
+ try {
61
+ const { payoutId } = req.params;
62
+ await settlePayout(payoutId);
63
+ res.json({ success: true });
64
+ } catch (err) {
65
+ console.error(err);
66
+ res.status(500).json({ success: false, error: err.message });
67
+ }
68
+ });
69
+
70
+ app.listen(process.env.PORT || 3010, () => console.log('billing-service listening 3010'));