@bayarkit/testing 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -1
- package/dist/cli/2c2p.d.ts +4 -0
- package/dist/cli/2c2p.d.ts.map +1 -0
- package/dist/cli/2c2p.js +7 -0
- package/dist/cli/2c2p.js.map +1 -0
- package/dist/cli/bayarcash.d.ts +4 -0
- package/dist/cli/bayarcash.d.ts.map +1 -0
- package/dist/cli/bayarcash.js +11 -0
- package/dist/cli/bayarcash.js.map +1 -0
- package/dist/cli/billplz.d.ts +4 -0
- package/dist/cli/billplz.d.ts.map +1 -0
- package/dist/cli/billplz.js +11 -0
- package/dist/cli/billplz.js.map +1 -0
- package/dist/cli/chip.d.ts +4 -0
- package/dist/cli/chip.d.ts.map +1 -0
- package/dist/cli/chip.js +7 -0
- package/dist/cli/chip.js.map +1 -0
- package/dist/cli/curlec.d.ts +4 -0
- package/dist/cli/curlec.d.ts.map +1 -0
- package/dist/cli/curlec.js +11 -0
- package/dist/cli/curlec.js.map +1 -0
- package/dist/cli/eghl.d.ts +4 -0
- package/dist/cli/eghl.d.ts.map +1 -0
- package/dist/cli/eghl.js +7 -0
- package/dist/cli/eghl.js.map +1 -0
- package/dist/cli/fiuu.d.ts +4 -0
- package/dist/cli/fiuu.d.ts.map +1 -0
- package/dist/cli/fiuu.js +17 -0
- package/dist/cli/fiuu.js.map +1 -0
- package/dist/cli/gkash.d.ts +4 -0
- package/dist/cli/gkash.d.ts.map +1 -0
- package/dist/cli/gkash.js +7 -0
- package/dist/cli/gkash.js.map +1 -0
- package/dist/cli/hitpay.d.ts +4 -0
- package/dist/cli/hitpay.d.ts.map +1 -0
- package/dist/cli/hitpay.js +7 -0
- package/dist/cli/hitpay.js.map +1 -0
- package/dist/cli/ipay88.d.ts +4 -0
- package/dist/cli/ipay88.d.ts.map +1 -0
- package/dist/cli/ipay88.js +7 -0
- package/dist/cli/ipay88.js.map +1 -0
- package/dist/cli/senangpay.d.ts +4 -0
- package/dist/cli/senangpay.d.ts.map +1 -0
- package/dist/cli/senangpay.js +17 -0
- package/dist/cli/senangpay.js.map +1 -0
- package/dist/cli/stripe.d.ts +4 -0
- package/dist/cli/stripe.d.ts.map +1 -0
- package/dist/cli/stripe.js +7 -0
- package/dist/cli/stripe.js.map +1 -0
- package/dist/cli/toyyibpay.d.ts +4 -0
- package/dist/cli/toyyibpay.d.ts.map +1 -0
- package/dist/cli/toyyibpay.js +7 -0
- package/dist/cli/toyyibpay.js.map +1 -0
- package/dist/cli/types.d.ts +7 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +2 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/cli/xendit.d.ts +4 -0
- package/dist/cli/xendit.d.ts.map +1 -0
- package/dist/cli/xendit.js +7 -0
- package/dist/cli/xendit.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +46 -0
- package/dist/cli.js.map +1 -0
- package/dist/conformance.d.ts +13 -0
- package/dist/conformance.d.ts.map +1 -0
- package/dist/conformance.js +166 -0
- package/dist/conformance.js.map +1 -0
- package/dist/control.d.ts +6 -0
- package/dist/control.d.ts.map +1 -0
- package/dist/control.js +46 -0
- package/dist/control.js.map +1 -0
- package/dist/fakes/2c2p.d.ts +21 -0
- package/dist/fakes/2c2p.d.ts.map +1 -0
- package/dist/fakes/2c2p.js +287 -0
- package/dist/fakes/2c2p.js.map +1 -0
- package/dist/fakes/bayarcash.d.ts +15 -0
- package/dist/fakes/bayarcash.d.ts.map +1 -0
- package/dist/fakes/bayarcash.js +133 -0
- package/dist/fakes/bayarcash.js.map +1 -0
- package/dist/fakes/billplz.d.ts +20 -0
- package/dist/fakes/billplz.d.ts.map +1 -0
- package/dist/fakes/billplz.js +233 -0
- package/dist/fakes/billplz.js.map +1 -0
- package/dist/fakes/chip.d.ts +18 -0
- package/dist/fakes/chip.d.ts.map +1 -0
- package/dist/fakes/chip.js +227 -0
- package/dist/fakes/chip.js.map +1 -0
- package/dist/fakes/curlec.d.ts +30 -0
- package/dist/fakes/curlec.d.ts.map +1 -0
- package/dist/fakes/curlec.js +396 -0
- package/dist/fakes/curlec.js.map +1 -0
- package/dist/fakes/eghl.d.ts +36 -0
- package/dist/fakes/eghl.d.ts.map +1 -0
- package/dist/fakes/eghl.js +267 -0
- package/dist/fakes/eghl.js.map +1 -0
- package/dist/fakes/fiuu.d.ts +27 -0
- package/dist/fakes/fiuu.d.ts.map +1 -0
- package/dist/fakes/fiuu.js +230 -0
- package/dist/fakes/fiuu.js.map +1 -0
- package/dist/fakes/gkash.d.ts +18 -0
- package/dist/fakes/gkash.d.ts.map +1 -0
- package/dist/fakes/gkash.js +193 -0
- package/dist/fakes/gkash.js.map +1 -0
- package/dist/fakes/hitpay.d.ts +36 -0
- package/dist/fakes/hitpay.d.ts.map +1 -0
- package/dist/fakes/hitpay.js +233 -0
- package/dist/fakes/hitpay.js.map +1 -0
- package/dist/fakes/ipay88.d.ts +16 -0
- package/dist/fakes/ipay88.d.ts.map +1 -0
- package/dist/fakes/ipay88.js +195 -0
- package/dist/fakes/ipay88.js.map +1 -0
- package/dist/fakes/senangpay.d.ts +51 -0
- package/dist/fakes/senangpay.d.ts.map +1 -0
- package/dist/fakes/senangpay.js +255 -0
- package/dist/fakes/senangpay.js.map +1 -0
- package/dist/fakes/stripe.d.ts +26 -0
- package/dist/fakes/stripe.d.ts.map +1 -0
- package/dist/fakes/stripe.js +243 -0
- package/dist/fakes/stripe.js.map +1 -0
- package/dist/fakes/toyyibpay.d.ts +14 -0
- package/dist/fakes/toyyibpay.d.ts.map +1 -0
- package/dist/fakes/toyyibpay.js +138 -0
- package/dist/fakes/toyyibpay.js.map +1 -0
- package/dist/fakes/types.d.ts +19 -0
- package/dist/fakes/types.d.ts.map +1 -0
- package/dist/fakes/types.js +3 -0
- package/dist/fakes/types.js.map +1 -0
- package/dist/fakes/xendit.d.ts +36 -0
- package/dist/fakes/xendit.d.ts.map +1 -0
- package/dist/fakes/xendit.js +300 -0
- package/dist/fakes/xendit.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/package.json +66 -2
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A fake Bayarcash API v3, built from the official documentation and PHP SDK (not yet measured against the sandbox).
|
|
3
|
+
* When someone measures the sandbox, change this file first so it answers like the real thing, then the adapter.
|
|
4
|
+
*/
|
|
5
|
+
import { createHmac } from 'node:crypto';
|
|
6
|
+
import { createServer } from 'node:http';
|
|
7
|
+
import { flip } from './types.js';
|
|
8
|
+
const sign = (secret, fields) => createHmac('sha256', secret)
|
|
9
|
+
.update(Object.keys(fields)
|
|
10
|
+
.sort()
|
|
11
|
+
.map((k) => fields[k] ?? '')
|
|
12
|
+
.join('|'))
|
|
13
|
+
.digest('hex');
|
|
14
|
+
export async function startFakeBayarcash(opts) {
|
|
15
|
+
let n = 0;
|
|
16
|
+
const intents = new Map();
|
|
17
|
+
const transactions = new Map();
|
|
18
|
+
const requests = [];
|
|
19
|
+
const server = createServer((req, res) => {
|
|
20
|
+
let raw = '';
|
|
21
|
+
req.on('data', (d) => {
|
|
22
|
+
raw += d;
|
|
23
|
+
});
|
|
24
|
+
req.on('end', () => {
|
|
25
|
+
let body = {};
|
|
26
|
+
try {
|
|
27
|
+
body = raw ? JSON.parse(raw) : {};
|
|
28
|
+
}
|
|
29
|
+
catch { }
|
|
30
|
+
const path = req.url ?? '';
|
|
31
|
+
requests.push({ method: req.method ?? '', path, body, headers: req.headers });
|
|
32
|
+
const send = (status, o) => {
|
|
33
|
+
res.writeHead(status, { 'content-type': 'application/json' });
|
|
34
|
+
res.end(JSON.stringify(o));
|
|
35
|
+
};
|
|
36
|
+
if (req.headers.authorization !== `Bearer ${opts.token}`)
|
|
37
|
+
return send(401, { message: 'Unauthenticated.' });
|
|
38
|
+
if (req.method === 'POST' && path === '/payment-intents') {
|
|
39
|
+
const channels = Array.isArray(body.payment_channel)
|
|
40
|
+
? body.payment_channel.join(',')
|
|
41
|
+
: String(body.payment_channel);
|
|
42
|
+
const expected = sign(opts.secretKey, {
|
|
43
|
+
payment_channel: channels,
|
|
44
|
+
order_number: String(body.order_number ?? ''),
|
|
45
|
+
amount: String(body.amount ?? ''),
|
|
46
|
+
payer_name: String(body.payer_name ?? ''),
|
|
47
|
+
payer_email: String(body.payer_email ?? ''),
|
|
48
|
+
});
|
|
49
|
+
if (body.checksum !== expected)
|
|
50
|
+
return send(422, { message: 'Invalid checksum.' });
|
|
51
|
+
if (body.portal_key !== opts.portalKey)
|
|
52
|
+
return send(422, { message: 'Invalid portal key.' });
|
|
53
|
+
const id = `pi_fake${++n}`;
|
|
54
|
+
intents.set(id, { id, body });
|
|
55
|
+
return send(200, { id, url: `https://fake.bayarcash.test/pay/${id}` });
|
|
56
|
+
}
|
|
57
|
+
const tx = /^\/transactions\/([A-Za-z0-9_-]+)$/.exec(path);
|
|
58
|
+
if (req.method === 'GET' && tx) {
|
|
59
|
+
const t = transactions.get(tx[1] ?? '');
|
|
60
|
+
if (!t)
|
|
61
|
+
return send(404, { message: 'Not found.' });
|
|
62
|
+
return send(200, { ...t, id: t.transaction_id, amount: Number(t.amount) });
|
|
63
|
+
}
|
|
64
|
+
if (req.method === 'GET' && path === '/portals') {
|
|
65
|
+
return send(200, {
|
|
66
|
+
data: [
|
|
67
|
+
{
|
|
68
|
+
portal_key: opts.portalKey,
|
|
69
|
+
portal_name: 'Fake portal',
|
|
70
|
+
payment_channels: [{ id: 1, name: 'FPX' }],
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
send(404, { message: 'Not found.' });
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
await new Promise((r) => server.listen(0, '127.0.0.1', r));
|
|
79
|
+
const url = `http://127.0.0.1:${server.address().port}`;
|
|
80
|
+
const intent = (id) => {
|
|
81
|
+
const i = intents.get(id);
|
|
82
|
+
if (!i)
|
|
83
|
+
throw new Error(`fake Bayarcash: no payment intent ${id}`);
|
|
84
|
+
return i;
|
|
85
|
+
};
|
|
86
|
+
const transaction = (i, status) => {
|
|
87
|
+
i.transactionId ??= `trx_${i.id}`;
|
|
88
|
+
const t = {
|
|
89
|
+
record_type: 'transaction',
|
|
90
|
+
transaction_id: i.transactionId,
|
|
91
|
+
exchange_reference_number: `1-${i.id}`,
|
|
92
|
+
exchange_transaction_id: `FPX${i.id}`,
|
|
93
|
+
order_number: String(i.body.order_number ?? ''),
|
|
94
|
+
currency: 'MYR',
|
|
95
|
+
amount: String(i.body.amount ?? ''),
|
|
96
|
+
payer_name: String(i.body.payer_name ?? ''),
|
|
97
|
+
payer_email: String(i.body.payer_email ?? ''),
|
|
98
|
+
payer_bank_name: 'Test Bank',
|
|
99
|
+
status,
|
|
100
|
+
status_description: status === '3' ? 'Approved' : 'Pending',
|
|
101
|
+
datetime: '2026-10-23 10:00:00',
|
|
102
|
+
};
|
|
103
|
+
transactions.set(i.transactionId, t);
|
|
104
|
+
return t;
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
url,
|
|
108
|
+
requests,
|
|
109
|
+
markPaid(id) {
|
|
110
|
+
transaction(intent(id), '3');
|
|
111
|
+
},
|
|
112
|
+
callbackFor(id, override = {}) {
|
|
113
|
+
const i = intent(id);
|
|
114
|
+
// A callback before payment: the gateway's own record stays pending, the callback still claims success.
|
|
115
|
+
const base = transactions.get(i.transactionId ?? '') ?? transaction(i, '1');
|
|
116
|
+
const fields = {
|
|
117
|
+
...base,
|
|
118
|
+
status: '3',
|
|
119
|
+
status_description: 'Approved',
|
|
120
|
+
...override,
|
|
121
|
+
};
|
|
122
|
+
const { checksum, ...signed } = fields;
|
|
123
|
+
return {
|
|
124
|
+
fields: { ...signed, checksum: checksum ?? sign(opts.secretKey, signed) },
|
|
125
|
+
rawBody: '',
|
|
126
|
+
headers: {},
|
|
127
|
+
};
|
|
128
|
+
},
|
|
129
|
+
tamper: (cb) => ({ ...cb, fields: { ...cb.fields, checksum: flip(cb.fields.checksum ?? '') } }),
|
|
130
|
+
close: () => new Promise((r) => server.close(() => r())),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=bayarcash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bayarcash.js","sourceRoot":"","sources":["../../src/fakes/bayarcash.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CallbackInput } from '@bayarkit/core';
|
|
2
|
+
import { type FakeGateway } from './types.js';
|
|
3
|
+
export interface FakeBillplz extends FakeGateway {
|
|
4
|
+
/** Every request received: body fields as posted (form or JSON), and headers. */
|
|
5
|
+
requests: {
|
|
6
|
+
method: string;
|
|
7
|
+
path: string;
|
|
8
|
+
body: Record<string, unknown>;
|
|
9
|
+
contentType: string | undefined;
|
|
10
|
+
headers: Record<string, string | string[] | undefined>;
|
|
11
|
+
}[];
|
|
12
|
+
/** The redirect query (`billplz[id]`, `billplz[paid]`, `billplz[paid_at]`, `billplz[x_signature]`) as decoded fields. */
|
|
13
|
+
redirectFor(id: string, override?: Record<string, string>): CallbackInput;
|
|
14
|
+
}
|
|
15
|
+
export declare function startFakeBillplz(opts: {
|
|
16
|
+
secretKey: string;
|
|
17
|
+
xSignatureKey: string;
|
|
18
|
+
collectionId: string;
|
|
19
|
+
}): Promise<FakeBillplz>;
|
|
20
|
+
//# sourceMappingURL=billplz.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"billplz.d.ts","sourceRoot":"","sources":["../../src/fakes/billplz.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,EAAE,KAAK,WAAW,EAAQ,MAAM,YAAY,CAAA;AA4CnD,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC9C,iFAAiF;IACjF,QAAQ,EAAE;QACR,MAAM,EAAE,MAAM,CAAA;QACd,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC7B,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;QAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;KACvD,EAAE,CAAA;IACH,yHAAyH;IACzH,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAAA;CAC1E;AAgBD,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;CACrB,GAAG,OAAO,CAAC,WAAW,CAAC,CAiLvB"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A fake Billplz API (V3 Bills), built from the official documentation (support.billplz.com/api) and the official
|
|
3
|
+
* WooCommerce plugin's signing code — see gateways/billplz/spec.md. NOT yet measured against the sandbox: when someone
|
|
4
|
+
* does, change this file first so it answers like the real thing, then the adapter.
|
|
5
|
+
*
|
|
6
|
+
* Where the docs are silent this fake picks one shape and says so (marked ASSUMED below); the adapter must not depend on
|
|
7
|
+
* those shapes beyond "an error is an error".
|
|
8
|
+
*/
|
|
9
|
+
import { createHmac } from 'node:crypto';
|
|
10
|
+
import { createServer } from 'node:http';
|
|
11
|
+
import { flip } from './types.js';
|
|
12
|
+
/**
|
|
13
|
+
* X Signature, written independently of the adapter (spec §5.1): one `key+value` string per parameter except
|
|
14
|
+
* `x_signature` (nested keys flattened, `billplz[id]` → `billplzid`), sort those STRINGS ascending case-insensitively,
|
|
15
|
+
* join with `|`, HMAC-SHA256 with the X Signature key, lowercase hex.
|
|
16
|
+
*/
|
|
17
|
+
const sign = (key, fields) => {
|
|
18
|
+
const parts = [];
|
|
19
|
+
for (const [k, v] of Object.entries(fields)) {
|
|
20
|
+
const flat = k.replaceAll('[', '').replaceAll(']', '');
|
|
21
|
+
if (flat === 'x_signature' || flat === 'billplzx_signature')
|
|
22
|
+
continue;
|
|
23
|
+
parts.push(`${flat}${v}`);
|
|
24
|
+
}
|
|
25
|
+
parts.sort((a, b) => {
|
|
26
|
+
const x = a.toLowerCase();
|
|
27
|
+
const y = b.toLowerCase();
|
|
28
|
+
return x < y ? -1 : x > y ? 1 : a < b ? -1 : a > b ? 1 : 0;
|
|
29
|
+
});
|
|
30
|
+
return createHmac('sha256', key).update(parts.join('|')).digest('hex');
|
|
31
|
+
};
|
|
32
|
+
const MY_OFFSET_MS = 8 * 3600_000;
|
|
33
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
34
|
+
const myNow = () => new Date(Date.now() + MY_OFFSET_MS);
|
|
35
|
+
/** Doc examples show due_at NOT zero-padded ("2018-9-27"). */
|
|
36
|
+
const dueToday = () => {
|
|
37
|
+
const d = myNow();
|
|
38
|
+
return `${d.getUTCFullYear()}-${d.getUTCMonth() + 1}-${d.getUTCDate()}`;
|
|
39
|
+
};
|
|
40
|
+
/** Callback/redirect format: "2018-09-27 15:15:09 +0800". */
|
|
41
|
+
const paidNow = () => {
|
|
42
|
+
const d = myNow();
|
|
43
|
+
return `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())} ${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())} +0800`;
|
|
44
|
+
};
|
|
45
|
+
export async function startFakeBillplz(opts) {
|
|
46
|
+
let n = 0;
|
|
47
|
+
const bills = new Map();
|
|
48
|
+
const requests = [];
|
|
49
|
+
const expectedAuth = `Basic ${Buffer.from(`${opts.secretKey}:`).toString('base64')}`;
|
|
50
|
+
let origin = '';
|
|
51
|
+
const server = createServer((req, res) => {
|
|
52
|
+
let raw = '';
|
|
53
|
+
req.on('data', (d) => {
|
|
54
|
+
raw += d;
|
|
55
|
+
});
|
|
56
|
+
req.on('end', () => {
|
|
57
|
+
const contentType = req.headers['content-type'];
|
|
58
|
+
let body = {};
|
|
59
|
+
if (contentType?.includes('application/json')) {
|
|
60
|
+
try {
|
|
61
|
+
const j = raw ? JSON.parse(raw) : {};
|
|
62
|
+
if (j && typeof j === 'object' && !Array.isArray(j))
|
|
63
|
+
body = j;
|
|
64
|
+
}
|
|
65
|
+
catch { }
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
body = Object.fromEntries(new URLSearchParams(raw));
|
|
69
|
+
}
|
|
70
|
+
const path = req.url ?? '';
|
|
71
|
+
requests.push({ method: req.method ?? '', path, body, contentType, headers: req.headers });
|
|
72
|
+
const send = (status, o) => {
|
|
73
|
+
res.writeHead(status, { 'content-type': 'application/json' });
|
|
74
|
+
res.end(JSON.stringify(o));
|
|
75
|
+
};
|
|
76
|
+
// ASSUMED: the docs give the error body only for 429 (`{"error":{"type","message":[…]}}`); other codes reuse it.
|
|
77
|
+
const error = (status, type, message) => send(status, { error: { type, message: [message] } });
|
|
78
|
+
// Docs: HTTP Basic, secret key as username, empty password; a wrong key (or the other environment's) → 401.
|
|
79
|
+
if (req.headers.authorization !== expectedAuth)
|
|
80
|
+
return error(401, 'Unauthorized', 'Invalid access token');
|
|
81
|
+
if (req.method === 'POST' && path === '/api/v3/bills') {
|
|
82
|
+
const s = (k) => (body[k] == null ? '' : String(body[k]).trim());
|
|
83
|
+
const problems = [];
|
|
84
|
+
if (!s('collection_id'))
|
|
85
|
+
problems.push('Collection is required');
|
|
86
|
+
else if (s('collection_id') !== opts.collectionId)
|
|
87
|
+
problems.push('Collection not found'); // ASSUMED code 422
|
|
88
|
+
if (!s('email') && !s('mobile'))
|
|
89
|
+
problems.push('Email or mobile is required');
|
|
90
|
+
if (s('mobile') && !/^\+?\d+$/.test(s('mobile')))
|
|
91
|
+
problems.push('Mobile is invalid');
|
|
92
|
+
if (!s('name'))
|
|
93
|
+
problems.push('Name is required');
|
|
94
|
+
else if ([...s('name')].length > 255)
|
|
95
|
+
problems.push('Name is too long (maximum is 255 characters)');
|
|
96
|
+
const amount = body.amount;
|
|
97
|
+
const amountOk = (typeof amount === 'number' && Number.isInteger(amount) && amount > 0) ||
|
|
98
|
+
(typeof amount === 'string' && /^[1-9]\d*$/.test(amount));
|
|
99
|
+
if (!amountOk)
|
|
100
|
+
problems.push('Amount must be a positive integer');
|
|
101
|
+
if (!s('callback_url'))
|
|
102
|
+
problems.push('Callback url is required');
|
|
103
|
+
if (!s('description'))
|
|
104
|
+
problems.push('Description is required');
|
|
105
|
+
else if ([...s('description')].length > 200)
|
|
106
|
+
problems.push('Description is too long (maximum is 200 characters)');
|
|
107
|
+
for (const k of ['reference_1_label', 'reference_2_label'])
|
|
108
|
+
if ([...s(k)].length > 20)
|
|
109
|
+
problems.push(`${k} is too long (maximum is 20 characters)`);
|
|
110
|
+
for (const k of ['reference_1', 'reference_2'])
|
|
111
|
+
if ([...s(k)].length > 120)
|
|
112
|
+
problems.push(`${k} is too long (maximum is 120 characters)`);
|
|
113
|
+
if (problems.length)
|
|
114
|
+
return send(422, { error: { type: 'Unprocessable', message: problems } });
|
|
115
|
+
n += 1;
|
|
116
|
+
const id = `fk${String(n).padStart(6, '0')}`;
|
|
117
|
+
const bill = {
|
|
118
|
+
id,
|
|
119
|
+
collection_id: s('collection_id'),
|
|
120
|
+
paid: false,
|
|
121
|
+
state: 'due',
|
|
122
|
+
amount: Number(amount),
|
|
123
|
+
paid_amount: 0,
|
|
124
|
+
due_at: s('due_at') || dueToday(),
|
|
125
|
+
email: s('email') || null,
|
|
126
|
+
mobile: s('mobile') || null,
|
|
127
|
+
name: s('name'),
|
|
128
|
+
url: `${origin}/bills/${id}`,
|
|
129
|
+
reference_1_label: s('reference_1_label') || 'Reference 1',
|
|
130
|
+
reference_1: s('reference_1') || null,
|
|
131
|
+
reference_2_label: s('reference_2_label') || 'Reference 2',
|
|
132
|
+
reference_2: s('reference_2') || null,
|
|
133
|
+
redirect_url: s('redirect_url') || null,
|
|
134
|
+
callback_url: s('callback_url'),
|
|
135
|
+
description: s('description'),
|
|
136
|
+
paid_at: null,
|
|
137
|
+
};
|
|
138
|
+
bills.set(id, bill);
|
|
139
|
+
const { paid_at: _omit, ...created } = bill;
|
|
140
|
+
return send(200, created);
|
|
141
|
+
}
|
|
142
|
+
const one = /^\/api\/v3\/bills\/([A-Za-z0-9]+)$/.exec(path);
|
|
143
|
+
if (one) {
|
|
144
|
+
const bill = bills.get(one[1] ?? '');
|
|
145
|
+
if (!bill)
|
|
146
|
+
return error(404, 'RecordNotFound', 'The requested bill does not exist');
|
|
147
|
+
if (req.method === 'GET') {
|
|
148
|
+
// Doc examples: the name comes back upper-cased; `paid_at` is absent from Get-a-Bill examples (UNCONFIRMED).
|
|
149
|
+
const { paid_at: _omit, ...shown } = bill;
|
|
150
|
+
return send(200, { ...shown, name: bill.name.toUpperCase() });
|
|
151
|
+
}
|
|
152
|
+
if (req.method === 'DELETE') {
|
|
153
|
+
// Docs: only due bills can be deleted; a paid bill → 422. ASSUMED: deleting a deleted bill is also 422.
|
|
154
|
+
if (bill.state !== 'due')
|
|
155
|
+
return error(422, 'Unprocessable', `Bill is ${bill.state}`);
|
|
156
|
+
bill.state = 'deleted';
|
|
157
|
+
return send(200, {});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
error(404, 'RecordNotFound', 'Not found');
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
await new Promise((r) => server.listen(0, '127.0.0.1', r));
|
|
164
|
+
origin = `http://127.0.0.1:${server.address().port}`;
|
|
165
|
+
const bill = (id) => {
|
|
166
|
+
const b = bills.get(id);
|
|
167
|
+
if (!b)
|
|
168
|
+
throw new Error(`fake Billplz: no bill ${id}`);
|
|
169
|
+
return b;
|
|
170
|
+
};
|
|
171
|
+
return {
|
|
172
|
+
url: `${origin}/api`,
|
|
173
|
+
requests,
|
|
174
|
+
markPaid(id) {
|
|
175
|
+
// Docs: a deleted bill comes back when a payment already in flight completes.
|
|
176
|
+
const b = bill(id);
|
|
177
|
+
b.paid = true;
|
|
178
|
+
b.state = 'paid';
|
|
179
|
+
b.paid_amount = b.amount;
|
|
180
|
+
b.paid_at = paidNow();
|
|
181
|
+
},
|
|
182
|
+
callbackFor(id, override = {}) {
|
|
183
|
+
const b = bill(id);
|
|
184
|
+
// Flat fields exactly as Billplz posts them (spec §5.2), form-encoded; null becomes "". It claims a successful
|
|
185
|
+
// payment even before markPaid (a replayed or forged-with-a-leaked-key callback).
|
|
186
|
+
const fields = {
|
|
187
|
+
id: b.id,
|
|
188
|
+
collection_id: b.collection_id,
|
|
189
|
+
paid: 'true',
|
|
190
|
+
state: 'paid',
|
|
191
|
+
amount: String(b.amount),
|
|
192
|
+
paid_amount: String(b.amount),
|
|
193
|
+
due_at: b.due_at,
|
|
194
|
+
email: b.email ?? '',
|
|
195
|
+
mobile: b.mobile ?? '',
|
|
196
|
+
name: b.name.toUpperCase(),
|
|
197
|
+
url: b.url,
|
|
198
|
+
paid_at: b.paid_at ?? paidNow(),
|
|
199
|
+
...override,
|
|
200
|
+
};
|
|
201
|
+
const { x_signature, ...signed } = fields;
|
|
202
|
+
const posted = { ...signed, x_signature: x_signature ?? sign(opts.xSignatureKey, signed) };
|
|
203
|
+
return {
|
|
204
|
+
fields: posted,
|
|
205
|
+
rawBody: new URLSearchParams(posted).toString(),
|
|
206
|
+
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
207
|
+
};
|
|
208
|
+
},
|
|
209
|
+
redirectFor(id, override = {}) {
|
|
210
|
+
const b = bill(id);
|
|
211
|
+
const fields = {
|
|
212
|
+
'billplz[id]': b.id,
|
|
213
|
+
'billplz[paid]': 'true',
|
|
214
|
+
'billplz[paid_at]': b.paid_at ?? paidNow(),
|
|
215
|
+
...override,
|
|
216
|
+
};
|
|
217
|
+
const { 'billplz[x_signature]': given, ...signed } = fields;
|
|
218
|
+
return {
|
|
219
|
+
fields: { ...signed, 'billplz[x_signature]': given ?? sign(opts.xSignatureKey, signed) },
|
|
220
|
+
rawBody: '',
|
|
221
|
+
headers: {},
|
|
222
|
+
};
|
|
223
|
+
},
|
|
224
|
+
tamper: (cb) => {
|
|
225
|
+
const k = 'billplz[x_signature]' in cb.fields ? 'billplz[x_signature]' : 'x_signature';
|
|
226
|
+
const fields = { ...cb.fields, [k]: flip(cb.fields[k] ?? '') };
|
|
227
|
+
// The body must say what the fields say: a real tampered POST carries the altered value in its bytes too.
|
|
228
|
+
return { ...cb, fields, rawBody: cb.rawBody ? new URLSearchParams(fields).toString() : '' };
|
|
229
|
+
},
|
|
230
|
+
close: () => new Promise((r) => server.close(() => r())),
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=billplz.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"billplz.js","sourceRoot":"","sources":["../../src/fakes/billplz.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type FakeGateway } from './types.js';
|
|
2
|
+
export interface FakeChip extends FakeGateway {
|
|
3
|
+
/** The PEM public key that signs this fake's callbacks (what `GET /public_key/` returns, JSON-decoded). */
|
|
4
|
+
publicKey: string;
|
|
5
|
+
requests: {
|
|
6
|
+
method: string;
|
|
7
|
+
path: string;
|
|
8
|
+
body: unknown;
|
|
9
|
+
headers: Record<string, string | string[] | undefined>;
|
|
10
|
+
}[];
|
|
11
|
+
}
|
|
12
|
+
export declare function startFakeChip(opts: {
|
|
13
|
+
secretKey: string;
|
|
14
|
+
brandId: string;
|
|
15
|
+
/** `is_test` on every purchase; CHIP sets it from the key's mode. Default true (test keys). */
|
|
16
|
+
isTest?: boolean;
|
|
17
|
+
}): Promise<FakeChip>;
|
|
18
|
+
//# sourceMappingURL=chip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chip.d.ts","sourceRoot":"","sources":["../../src/fakes/chip.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,KAAK,WAAW,EAAQ,MAAM,YAAY,CAAA;AAuBnD,MAAM,WAAW,QAAS,SAAQ,WAAW;IAC3C,2GAA2G;IAC3G,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE;QACR,MAAM,EAAE,MAAM,CAAA;QACd,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,OAAO,CAAA;QACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;KACvD,EAAE,CAAA;CACJ;AAKD,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,+FAA+F;IAC/F,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,GAAG,OAAO,CAAC,QAAQ,CAAC,CA8LpB"}
|