@bayarkit/testing 0.0.0 → 0.2.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 +17 -0
- package/dist/fakes/bayarcash.d.ts.map +1 -0
- package/dist/fakes/bayarcash.js +183 -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 +130 -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,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A fake Stripe API (Checkout Sessions only), built from the official docs in `gateways/stripe/spec.md` and checked
|
|
3
|
+
* against test mode 27 Oct 2026 (Malaysian account): the shapes it serves matched; one completed event per paid
|
|
4
|
+
* session, FPX included; a failed FPX payment sends no Checkout event. Change this file first when Stripe changes.
|
|
5
|
+
*
|
|
6
|
+
* What it checks, and where each rule comes from (spec sections in brackets):
|
|
7
|
+
* - auth: `Authorization: Bearer <key>` or Basic `<key>:` with the configured `sk_test_` key, else 401 [§1];
|
|
8
|
+
* - bodies are form-encoded with bracket keys; responses JSON; errors `{ error: { type, message, code? } }` [§1];
|
|
9
|
+
* - `Stripe-Version` is REQUIRED here. Real Stripe falls back to the account default [§1]; the fake is stricter on
|
|
10
|
+
* purpose so a test proves the adapter always pins the version;
|
|
11
|
+
* - under `2026-09-30.endive`, any `payment_method_types` key → 400, as the endive changelog states [§2.3];
|
|
12
|
+
* - `expires_at` must be 30 min to 24 h after creation; default 24 h [§2.1]; minimum charge 200 sen (MYR) [§5];
|
|
13
|
+
* - `Idempotency-Key`: same key + same params → the same session; same key + other params → error [§2.5];
|
|
14
|
+
* - webhooks: `Stripe-Signature: t=<unix>,v1=<hex HMAC-SHA256(whsec, "<t>.<raw body>")>` [§4].
|
|
15
|
+
*/
|
|
16
|
+
import { createHmac, randomBytes } from 'node:crypto';
|
|
17
|
+
import { createServer } from 'node:http';
|
|
18
|
+
import { flip } from './types.js';
|
|
19
|
+
export const ENDIVE = '2026-09-30.endive';
|
|
20
|
+
/** `t=<t>,v1=<hex>` exactly as Stripe builds it: HMAC-SHA256 over `${t}.${rawBody}`, key = the full `whsec_…` string. */
|
|
21
|
+
export function stripeSignature(webhookSecret, rawBody, t) {
|
|
22
|
+
return `t=${t},v1=${createHmac('sha256', webhookSecret).update(`${t}.${rawBody}`, 'utf8').digest('hex')}`;
|
|
23
|
+
}
|
|
24
|
+
const randomId = (prefix) => `${prefix}${randomBytes(12).toString('hex')}`;
|
|
25
|
+
export async function startFakeStripe(opts) {
|
|
26
|
+
const sessions = new Map();
|
|
27
|
+
const versions = new Map();
|
|
28
|
+
const idempotent = new Map();
|
|
29
|
+
const requests = [];
|
|
30
|
+
const now = () => Math.floor(Date.now() / 1000);
|
|
31
|
+
const authorised = (header) => {
|
|
32
|
+
if (!header)
|
|
33
|
+
return false;
|
|
34
|
+
if (header === `Bearer ${opts.secretKey}`)
|
|
35
|
+
return true;
|
|
36
|
+
const basic = /^Basic (.+)$/.exec(header)?.[1];
|
|
37
|
+
return !!basic && Buffer.from(basic, 'base64').toString('utf8') === `${opts.secretKey}:`;
|
|
38
|
+
};
|
|
39
|
+
const server = createServer((req, res) => {
|
|
40
|
+
let raw = '';
|
|
41
|
+
req.on('data', (d) => {
|
|
42
|
+
raw += d;
|
|
43
|
+
});
|
|
44
|
+
req.on('end', () => {
|
|
45
|
+
const form = new URLSearchParams(raw);
|
|
46
|
+
const keys = [...form.keys()];
|
|
47
|
+
const body = {};
|
|
48
|
+
for (const k of new Set(keys))
|
|
49
|
+
body[k] = form.getAll(k).join(',');
|
|
50
|
+
const path = (req.url ?? '').split('?')[0] ?? '';
|
|
51
|
+
requests.push({ method: req.method ?? '', path, body, keys, headers: req.headers });
|
|
52
|
+
const send = (status, o) => {
|
|
53
|
+
res.writeHead(status, { 'content-type': 'application/json' });
|
|
54
|
+
res.end(JSON.stringify(o));
|
|
55
|
+
};
|
|
56
|
+
const fail = (status, type, message, extra = {}) => send(status, { error: { type, message, ...extra } });
|
|
57
|
+
if (!authorised(req.headers.authorization)) {
|
|
58
|
+
return fail(401, 'invalid_request_error', 'Invalid API Key provided.');
|
|
59
|
+
}
|
|
60
|
+
const version = req.headers['stripe-version'];
|
|
61
|
+
if (typeof version !== 'string' || !version) {
|
|
62
|
+
return fail(400, 'invalid_request_error', 'fake Stripe: send a Stripe-Version header (pin the API version).');
|
|
63
|
+
}
|
|
64
|
+
if (req.method === 'POST' && path === '/v1/checkout/sessions') {
|
|
65
|
+
if (version === ENDIVE && keys.some((k) => k.startsWith('payment_method_types'))) {
|
|
66
|
+
return fail(400, 'invalid_request_error', 'You can no longer pass `payment_method_types` when you create a Checkout Session.', { param: 'payment_method_types' });
|
|
67
|
+
}
|
|
68
|
+
const key = req.headers['idempotency-key'];
|
|
69
|
+
const idemKey = typeof key === 'string' && key ? key : '';
|
|
70
|
+
if (idemKey.length > 255)
|
|
71
|
+
return fail(400, 'invalid_request_error', 'Idempotency-Key is too long.');
|
|
72
|
+
const params = JSON.stringify(keys.map((k) => [k, form.getAll(k)]));
|
|
73
|
+
const saved = idemKey ? idempotent.get(idemKey) : undefined;
|
|
74
|
+
if (saved) {
|
|
75
|
+
if (saved.params !== params) {
|
|
76
|
+
return fail(400, 'idempotency_error', 'Keys for idempotent requests can only be used with the same parameters they were first used with.');
|
|
77
|
+
}
|
|
78
|
+
return send(saved.status, saved.body);
|
|
79
|
+
}
|
|
80
|
+
const result = create(body, version);
|
|
81
|
+
// Validation failures are not saved (spec §2.5), so the caller can fix and retry with the same key.
|
|
82
|
+
if (idemKey && result.status === 200)
|
|
83
|
+
idempotent.set(idemKey, { params, status: result.status, body: result.body });
|
|
84
|
+
return send(result.status, result.body);
|
|
85
|
+
}
|
|
86
|
+
const get = /^\/v1\/checkout\/sessions\/([A-Za-z0-9_]+)$/.exec(path);
|
|
87
|
+
if (req.method === 'GET' && get) {
|
|
88
|
+
const s = sessions.get(get[1] ?? '');
|
|
89
|
+
if (!s)
|
|
90
|
+
return missing(get[1] ?? '');
|
|
91
|
+
return send(200, s);
|
|
92
|
+
}
|
|
93
|
+
const expire = /^\/v1\/checkout\/sessions\/([A-Za-z0-9_]+)\/expire$/.exec(path);
|
|
94
|
+
if (req.method === 'POST' && expire) {
|
|
95
|
+
const s = sessions.get(expire[1] ?? '');
|
|
96
|
+
if (!s)
|
|
97
|
+
return missing(expire[1] ?? '');
|
|
98
|
+
if (s.status !== 'open') {
|
|
99
|
+
return fail(400, 'invalid_request_error', `Only Checkout Sessions with a status of open can be expired.`);
|
|
100
|
+
}
|
|
101
|
+
s.status = 'expired';
|
|
102
|
+
s.url = null;
|
|
103
|
+
return send(200, s);
|
|
104
|
+
}
|
|
105
|
+
return fail(404, 'invalid_request_error', `Unrecognized request URL (${req.method}: ${path}).`);
|
|
106
|
+
function missing(id) {
|
|
107
|
+
return fail(404, 'invalid_request_error', `No such checkout.session: '${id}'`, {
|
|
108
|
+
code: 'resource_missing',
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
function create(body, version) {
|
|
114
|
+
const bad = (message, param) => ({
|
|
115
|
+
status: 400,
|
|
116
|
+
body: { error: { type: 'invalid_request_error', message, ...(param ? { param } : {}) } },
|
|
117
|
+
});
|
|
118
|
+
if (body.mode !== 'payment')
|
|
119
|
+
return bad('Missing or unsupported mode.', 'mode');
|
|
120
|
+
const currency = body['line_items[0][price_data][currency]'];
|
|
121
|
+
const unit = body['line_items[0][price_data][unit_amount]'] ?? '';
|
|
122
|
+
const name = body['line_items[0][price_data][product_data][name]'];
|
|
123
|
+
const quantity = body['line_items[0][quantity]'] ?? '';
|
|
124
|
+
if (currency !== 'myr')
|
|
125
|
+
return bad('This fake only speaks MYR (myr).', 'line_items[0][price_data][currency]');
|
|
126
|
+
if (!/^\d+$/.test(unit))
|
|
127
|
+
return bad('Invalid integer: unit_amount', 'line_items[0][price_data][unit_amount]');
|
|
128
|
+
if (!name)
|
|
129
|
+
return bad('Missing required param: product_data[name].', 'line_items[0][price_data][product_data][name]');
|
|
130
|
+
if (!/^[1-9]\d*$/.test(quantity))
|
|
131
|
+
return bad('Invalid integer: quantity', 'line_items[0][quantity]');
|
|
132
|
+
if (!body.success_url)
|
|
133
|
+
return bad('Missing required param: success_url.', 'success_url');
|
|
134
|
+
const amountTotal = Number(unit) * Number(quantity);
|
|
135
|
+
if (amountTotal < 200)
|
|
136
|
+
return bad('The Checkout Session total must be at least RM2.00 (200 sen).', 'line_items');
|
|
137
|
+
const created = now();
|
|
138
|
+
let expiresAt = created + 86_400;
|
|
139
|
+
if (body.expires_at !== undefined) {
|
|
140
|
+
const e = Number(body.expires_at);
|
|
141
|
+
if (!Number.isInteger(e) || e - created < 1800 || e - created > 86_400) {
|
|
142
|
+
return bad('expires_at must be between 30 minutes and 24 hours after creation.', 'expires_at');
|
|
143
|
+
}
|
|
144
|
+
expiresAt = e;
|
|
145
|
+
}
|
|
146
|
+
if ((body.client_reference_id ?? '').length > 200)
|
|
147
|
+
return bad('client_reference_id is too long.');
|
|
148
|
+
const allowed = body['allowed_payment_method_types[]']?.split(',');
|
|
149
|
+
const legacy = body['payment_method_types[]']?.split(',');
|
|
150
|
+
const id = randomId('cs_test_');
|
|
151
|
+
const session = {
|
|
152
|
+
id,
|
|
153
|
+
object: 'checkout.session',
|
|
154
|
+
amount_total: amountTotal,
|
|
155
|
+
cancel_url: body.cancel_url ?? null,
|
|
156
|
+
client_reference_id: body.client_reference_id ?? null,
|
|
157
|
+
created,
|
|
158
|
+
currency: 'myr',
|
|
159
|
+
customer_email: body.customer_email ?? null,
|
|
160
|
+
expires_at: expiresAt,
|
|
161
|
+
livemode: false,
|
|
162
|
+
metadata: {},
|
|
163
|
+
mode: 'payment',
|
|
164
|
+
payment_intent: null,
|
|
165
|
+
payment_method_types: allowed ?? legacy ?? ['card'],
|
|
166
|
+
payment_status: 'unpaid',
|
|
167
|
+
status: 'open',
|
|
168
|
+
success_url: body.success_url,
|
|
169
|
+
ui_mode: 'hosted_page',
|
|
170
|
+
url: `https://checkout.stripe.com/c/pay/${id}#fake`,
|
|
171
|
+
};
|
|
172
|
+
sessions.set(id, session);
|
|
173
|
+
versions.set(id, version);
|
|
174
|
+
return { status: 200, body: session };
|
|
175
|
+
}
|
|
176
|
+
await new Promise((r) => server.listen(0, '127.0.0.1', r));
|
|
177
|
+
const url = `http://127.0.0.1:${server.address().port}`;
|
|
178
|
+
const session = (id) => {
|
|
179
|
+
const s = sessions.get(id);
|
|
180
|
+
if (!s)
|
|
181
|
+
throw new Error(`fake Stripe: no checkout session ${id}`);
|
|
182
|
+
return s;
|
|
183
|
+
};
|
|
184
|
+
return {
|
|
185
|
+
url,
|
|
186
|
+
requests,
|
|
187
|
+
session: (id) => sessions.get(id),
|
|
188
|
+
markPaid(id) {
|
|
189
|
+
const s = session(id);
|
|
190
|
+
s.status = 'complete';
|
|
191
|
+
s.payment_status = 'paid';
|
|
192
|
+
s.payment_intent ??= randomId('pi_');
|
|
193
|
+
s.url = null;
|
|
194
|
+
},
|
|
195
|
+
/**
|
|
196
|
+
* A `checkout.session.completed` event claiming payment (even before `markPaid`; the fake's record stays unpaid).
|
|
197
|
+
* `override` changes fields of `data.object` before signing; the key `type` changes the event type instead.
|
|
198
|
+
*/
|
|
199
|
+
callbackFor(id, override = {}) {
|
|
200
|
+
const { type, ...fields } = override;
|
|
201
|
+
const s = session(id);
|
|
202
|
+
const event = {
|
|
203
|
+
id: randomId('evt_'),
|
|
204
|
+
object: 'event',
|
|
205
|
+
api_version: versions.get(id) ?? ENDIVE,
|
|
206
|
+
created: now(),
|
|
207
|
+
data: {
|
|
208
|
+
object: {
|
|
209
|
+
...s,
|
|
210
|
+
status: 'complete',
|
|
211
|
+
payment_status: 'paid',
|
|
212
|
+
payment_intent: s.payment_intent ?? randomId('pi_'),
|
|
213
|
+
url: null,
|
|
214
|
+
...fields,
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
livemode: false,
|
|
218
|
+
pending_webhooks: 1,
|
|
219
|
+
request: { id: null, idempotency_key: null },
|
|
220
|
+
type: type ?? 'checkout.session.completed',
|
|
221
|
+
};
|
|
222
|
+
// Indented, so a handler that re-serialises the parsed JSON gets different bytes and the signature fails.
|
|
223
|
+
const rawBody = JSON.stringify(event, null, 2);
|
|
224
|
+
return {
|
|
225
|
+
fields: {},
|
|
226
|
+
rawBody,
|
|
227
|
+
headers: {
|
|
228
|
+
'content-type': 'application/json',
|
|
229
|
+
'stripe-signature': stripeSignature(opts.webhookSecret, rawBody, now()),
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
},
|
|
233
|
+
tamper: (cb) => ({
|
|
234
|
+
...cb,
|
|
235
|
+
headers: {
|
|
236
|
+
...cb.headers,
|
|
237
|
+
'stripe-signature': (cb.headers['stripe-signature'] ?? '').replace(/v1=([0-9a-f]+)/, (_m, hex) => `v1=${flip(hex)}`),
|
|
238
|
+
},
|
|
239
|
+
}),
|
|
240
|
+
close: () => new Promise((r) => server.close(() => r())),
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=stripe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripe.js","sourceRoot":"","sources":["../../src/fakes/stripe.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type FakeGateway } from './types.js';
|
|
2
|
+
export interface FakeToyyibPay extends FakeGateway {
|
|
3
|
+
/** Every request received, for assertions (fields as posted). */
|
|
4
|
+
requests: {
|
|
5
|
+
path: string;
|
|
6
|
+
fields: Record<string, string>;
|
|
7
|
+
contentType: string | undefined;
|
|
8
|
+
}[];
|
|
9
|
+
}
|
|
10
|
+
export declare function startFakeToyyibPay(opts: {
|
|
11
|
+
secretKey: string;
|
|
12
|
+
categoryCode: string;
|
|
13
|
+
}): Promise<FakeToyyibPay>;
|
|
14
|
+
//# sourceMappingURL=toyyibpay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toyyibpay.d.ts","sourceRoot":"","sources":["../../src/fakes/toyyibpay.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,WAAW,EAAQ,MAAM,YAAY,CAAA;AAQnD,MAAM,WAAW,aAAc,SAAQ,WAAW;IAChD,iEAAiE;IACjE,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,EAAE,CAAA;CAC9F;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;CACrB,GAAG,OAAO,CAAC,aAAa,CAAC,CAoHzB"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A fake toyyibPay that answers in the shapes MEASURED on the sandbox (10 October 2026), not the documented ones:
|
|
3
|
+
* leading tabs + text/html, "No data found!" for a bill without transactions, bracketed error codes, `{CategoryName}`.
|
|
4
|
+
* A fake written from the docs passed bugs that were live in production twice in one day; keep this one honest.
|
|
5
|
+
*/
|
|
6
|
+
import { createHash } from 'node:crypto';
|
|
7
|
+
import { createServer } from 'node:http';
|
|
8
|
+
import { flip } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Fields getBillTransactions empties without the bill owner's userSecretKey. Measured on the sandbox 27 Oct 2026: the
|
|
11
|
+
* payer fields only. The API reference (23 Oct) also lists split, settlement and fee fields; the sandbox kept those.
|
|
12
|
+
*/
|
|
13
|
+
const OWNER_ONLY = ['billTo', 'billEmail', 'billPhone'];
|
|
14
|
+
export async function startFakeToyyibPay(opts) {
|
|
15
|
+
let n = 0;
|
|
16
|
+
const bills = new Map();
|
|
17
|
+
const requests = [];
|
|
18
|
+
const server = createServer((req, res) => {
|
|
19
|
+
let body = '';
|
|
20
|
+
req.on('data', (d) => {
|
|
21
|
+
body += d;
|
|
22
|
+
});
|
|
23
|
+
req.on('end', () => {
|
|
24
|
+
const fields = Object.fromEntries(new URLSearchParams(body));
|
|
25
|
+
const path = (req.url ?? '').replace('/index.php/api/', '');
|
|
26
|
+
requests.push({ path, fields, contentType: req.headers['content-type'] });
|
|
27
|
+
const text = (t) => {
|
|
28
|
+
res.writeHead(200, { 'content-type': 'text/html; charset=UTF-8' });
|
|
29
|
+
res.end(`\t\t\t\t${t}`);
|
|
30
|
+
};
|
|
31
|
+
const json = (o) => text(JSON.stringify(o));
|
|
32
|
+
if (path === 'createBill') {
|
|
33
|
+
if (fields.userSecretKey !== opts.secretKey)
|
|
34
|
+
return text('[KEY-DID-NOT-EXIST-OR-USER-IS-NOT-ACTIVE]');
|
|
35
|
+
if (fields.categoryCode !== opts.categoryCode)
|
|
36
|
+
return text('[CATEGORY-NOT-MATCH]');
|
|
37
|
+
if (fields.billPayorInfo === '1' && !fields.billEmail) {
|
|
38
|
+
return json({ status: 'error', msg: 'billEmail parameter is empty' });
|
|
39
|
+
}
|
|
40
|
+
// Message measured; envelope assumed to match the billEmail error above.
|
|
41
|
+
if (Number(fields.billAmount) < 100)
|
|
42
|
+
return json({ status: 'error', msg: 'billAmount should more than RM1.00' });
|
|
43
|
+
const code = `fk${++n}tp`;
|
|
44
|
+
bills.set(code, { fields, txs: [], inactive: false });
|
|
45
|
+
return json([{ BillCode: code }]);
|
|
46
|
+
}
|
|
47
|
+
if (path === 'getBillTransactions') {
|
|
48
|
+
// Measured on the sandbox 27 Oct 2026 (one paid bill, three requests): without userSecretKey the payer fields
|
|
49
|
+
// come back empty; with a key that is not the owner's the answer is `No data found!`, the same text as a bill
|
|
50
|
+
// with no transactions.
|
|
51
|
+
const bill = bills.get(fields.billCode ?? '');
|
|
52
|
+
if (fields.userSecretKey !== undefined && fields.userSecretKey !== opts.secretKey)
|
|
53
|
+
return text('No data found!');
|
|
54
|
+
if (!bill?.txs.length)
|
|
55
|
+
return text('No data found!');
|
|
56
|
+
if (fields.userSecretKey === opts.secretKey)
|
|
57
|
+
return json(bill.txs);
|
|
58
|
+
return json(bill.txs.map((t) => ({ ...t, ...Object.fromEntries(OWNER_ONLY.map((k) => [k, ''])) })));
|
|
59
|
+
}
|
|
60
|
+
if (path === 'inactiveBill') {
|
|
61
|
+
const bill = bills.get(fields.billCode ?? '');
|
|
62
|
+
if (fields.secretKey !== opts.secretKey || !bill)
|
|
63
|
+
return json({ status: 'error', result: 'Invalid Secret Key!' });
|
|
64
|
+
if (bill.inactive)
|
|
65
|
+
return json({ status: 'failed', result: 'Bill is inactive' });
|
|
66
|
+
bill.inactive = true;
|
|
67
|
+
return json({ status: 'success', result: 'Bill status changed to inactive' });
|
|
68
|
+
}
|
|
69
|
+
if (path === 'getCategoryDetails') {
|
|
70
|
+
if (fields.userSecretKey === opts.secretKey && fields.categoryCode === opts.categoryCode) {
|
|
71
|
+
return json({ CategoryName: 'Fake category', categoryDescription: 'x', categoryStatus: '1' });
|
|
72
|
+
}
|
|
73
|
+
return text('');
|
|
74
|
+
}
|
|
75
|
+
res.writeHead(404);
|
|
76
|
+
res.end();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
await new Promise((r) => server.listen(0, '127.0.0.1', r));
|
|
80
|
+
const url = `http://127.0.0.1:${server.address().port}`;
|
|
81
|
+
const bill = (code) => {
|
|
82
|
+
const b = bills.get(code);
|
|
83
|
+
if (!b)
|
|
84
|
+
throw new Error(`fake toyyibPay: no bill ${code}`);
|
|
85
|
+
return b;
|
|
86
|
+
};
|
|
87
|
+
return {
|
|
88
|
+
url,
|
|
89
|
+
requests,
|
|
90
|
+
markPaid(code) {
|
|
91
|
+
const b = bill(code);
|
|
92
|
+
// Shape of a real test-bank payment: the docs sample plus transactionCharge/chargeOn (measured).
|
|
93
|
+
b.txs.push({
|
|
94
|
+
billName: b.fields.billName ?? '',
|
|
95
|
+
billStatus: '0',
|
|
96
|
+
billpaymentStatus: '1',
|
|
97
|
+
billpaymentChannel: 'FPX',
|
|
98
|
+
billpaymentAmount: (Number(b.fields.billAmount) / 100).toFixed(2),
|
|
99
|
+
billpaymentInvoiceNo: `TP${Date.now()}${b.txs.length}`,
|
|
100
|
+
billPaymentDate: '10-10-2026 10:50:07',
|
|
101
|
+
billExternalReferenceNo: b.fields.billExternalReferenceNo ?? '',
|
|
102
|
+
transactionCharge: '1.00',
|
|
103
|
+
chargeOn: 'Amount',
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
callbackFor(code, override = {}) {
|
|
107
|
+
const b = bill(code);
|
|
108
|
+
const fields = {
|
|
109
|
+
refno: `TP${code}`,
|
|
110
|
+
status: '1',
|
|
111
|
+
reason: 'Approved',
|
|
112
|
+
billcode: code,
|
|
113
|
+
order_id: b.fields.billExternalReferenceNo ?? '',
|
|
114
|
+
amount: (Number(b.fields.billAmount) / 100).toFixed(2),
|
|
115
|
+
status_id: '1',
|
|
116
|
+
msg: 'ok',
|
|
117
|
+
transaction_id: `TP${code}`,
|
|
118
|
+
...override,
|
|
119
|
+
};
|
|
120
|
+
const hash = createHash('md5')
|
|
121
|
+
.update(`${opts.secretKey}${fields.status}${fields.order_id}${fields.refno}ok`)
|
|
122
|
+
.digest('hex');
|
|
123
|
+
// Measured: toyyibPay posts this as multipart/form-data; the signature is the `hash` field.
|
|
124
|
+
return { fields: { ...fields, hash: override.hash ?? hash }, rawBody: '', headers: {} };
|
|
125
|
+
},
|
|
126
|
+
tamper: (cb) => ({ ...cb, fields: { ...cb.fields, hash: flip(cb.fields.hash ?? '') } }),
|
|
127
|
+
close: () => new Promise((r) => server.close(() => r())),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=toyyibpay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toyyibpay.js","sourceRoot":"","sources":["../../src/fakes/toyyibpay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CallbackInput } from '@bayarkit/core';
|
|
2
|
+
/** What every fake gateway lets a test do, so one conformance suite can drive any adapter. */
|
|
3
|
+
export interface FakeGateway {
|
|
4
|
+
/** Base URL to pass as the adapter's `baseUrl`. */
|
|
5
|
+
url: string;
|
|
6
|
+
/** Record a successful payment for the payment created with this id. */
|
|
7
|
+
markPaid(id: string): void;
|
|
8
|
+
/**
|
|
9
|
+
* The callback exactly as the gateway would deliver it for this payment, correctly signed. It claims success even
|
|
10
|
+
* before `markPaid` (a replayed or forged-with-a-leaked-key callback); `override` changes fields BEFORE signing.
|
|
11
|
+
*/
|
|
12
|
+
callbackFor(id: string, override?: Record<string, string>): CallbackInput;
|
|
13
|
+
/** The same callback with its signature altered (wherever this gateway keeps it: a field or a header). */
|
|
14
|
+
tamper(callback: CallbackInput): CallbackInput;
|
|
15
|
+
close(): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
/** Flip the first character of a hex/base64 signature. */
|
|
18
|
+
export declare const flip: (s: string) => string;
|
|
19
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/fakes/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnD,8FAA8F;AAC9F,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAA;IACX,wEAAwE;IACxE,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B;;;OAGG;IACH,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAAA;IACzE,0GAA0G;IAC1G,MAAM,CAAC,QAAQ,EAAE,aAAa,GAAG,aAAa,CAAA;IAC9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAED,0DAA0D;AAC1D,eAAO,MAAM,IAAI,MAAO,MAAM,KAAG,MAAyD,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/fakes/types.ts"],"names":[],"mappings":"AAkBA,0DAA0D;AAC1D,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type FakeGateway } from './types.js';
|
|
2
|
+
export declare const XENDIT_API_VERSION = "2024-11-11";
|
|
3
|
+
type Session = Record<string, unknown> & {
|
|
4
|
+
payment_session_id: string;
|
|
5
|
+
status: string;
|
|
6
|
+
};
|
|
7
|
+
type PaymentRequest = Record<string, unknown> & {
|
|
8
|
+
payment_request_id: string;
|
|
9
|
+
status: string;
|
|
10
|
+
};
|
|
11
|
+
export interface FakeXendit extends FakeGateway {
|
|
12
|
+
requests: {
|
|
13
|
+
method: string;
|
|
14
|
+
path: string;
|
|
15
|
+
body: Record<string, unknown> | null;
|
|
16
|
+
headers: Record<string, string | string[] | undefined>;
|
|
17
|
+
}[];
|
|
18
|
+
/** The fake's own record of a session (what `GET /sessions/{id}` answers). */
|
|
19
|
+
session(id: string): Session | undefined;
|
|
20
|
+
/** The fake's own record of a payment request (what `GET /v3/payment_requests/{id}` answers). */
|
|
21
|
+
paymentRequest(id: string): PaymentRequest | undefined;
|
|
22
|
+
/** Move an ACTIVE session to `EXPIRED` (what Xendit does when `expires_at` passes). */
|
|
23
|
+
expire(id: string): void;
|
|
24
|
+
/**
|
|
25
|
+
* A `payment.capture` webhook for this session's payment, claiming `SUCCEEDED` even before `markPaid` (then the
|
|
26
|
+
* fake's payment request stays `REQUIRES_ACTION`). `override` changes fields of `data`; the key `event` changes the
|
|
27
|
+
* event name instead.
|
|
28
|
+
*/
|
|
29
|
+
paymentCallbackFor(sessionId: string, override?: Record<string, unknown>): ReturnType<FakeGateway['callbackFor']>;
|
|
30
|
+
}
|
|
31
|
+
export declare function startFakeXendit(opts: {
|
|
32
|
+
secretKey: string;
|
|
33
|
+
callbackToken: string;
|
|
34
|
+
}): Promise<FakeXendit>;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=xendit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xendit.d.ts","sourceRoot":"","sources":["../../src/fakes/xendit.ts"],"names":[],"mappings":"AA8BA,OAAO,EAAE,KAAK,WAAW,EAAQ,MAAM,YAAY,CAAA;AAEnD,eAAO,MAAM,kBAAkB,eAAe,CAAA;AAE9C,KAAK,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,kBAAkB,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AACvF,KAAK,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,kBAAkB,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE9F,MAAM,WAAW,UAAW,SAAQ,WAAW;IAC7C,QAAQ,EAAE;QACR,MAAM,EAAE,MAAM,CAAA;QACd,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;QACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;KACvD,EAAE,CAAA;IACH,8EAA8E;IAC9E,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;IACxC,iGAAiG;IACjG,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAA;IACtD,uFAAuF;IACvF,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;;;;OAIG;IACH,kBAAkB,CAChB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAA;CAC1C;AAKD,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;CACtB,GAAG,OAAO,CAAC,UAAU,CAAC,CAwQtB"}
|