@nile-squad/nylonpay-ts 1.0.0 → 1.0.1
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 +3 -4
- package/dist/index.cjs +223 -223
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +223 -223
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,14 +35,13 @@ payment.on("failed", ({ error }) => notifyCustomer(error));
|
|
|
35
35
|
|
|
36
36
|
## Configuration
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
> providers, a live key processes real money. There is no `environment` option.
|
|
38
|
+
Use your test keys to work in sandbox, or your production keys to go live. There is no separate `environment` option — the key determines the mode.
|
|
40
39
|
|
|
41
40
|
| Option | Required | Default | Description |
|
|
42
41
|
|---|---|---|---|
|
|
43
42
|
| `apiKey` | Yes | | Must start with `npk_` |
|
|
44
43
|
| `apiSecret` | Yes | | Must start with `nps_` |
|
|
45
|
-
| `baseUrl` | No |
|
|
44
|
+
| `baseUrl` | No | Default is used | Override only if self-hosting |
|
|
46
45
|
| `timeoutMs` | No | `30000` | Request timeout in milliseconds |
|
|
47
46
|
| `maxRetries` | No | `3` | Retry count for failed requests |
|
|
48
47
|
| `maxPollIntervalMs` | No | `2000` | Polling interval for async payments |
|
|
@@ -170,7 +169,7 @@ app.post("/webhooks", (req, res) => {
|
|
|
170
169
|
const isValid = nylonpay.verifyWebhookSignature({
|
|
171
170
|
payload: req.rawBody,
|
|
172
171
|
signature: req.headers["x-nylon-signature"],
|
|
173
|
-
secret:
|
|
172
|
+
secret: "nps_...",
|
|
174
173
|
});
|
|
175
174
|
|
|
176
175
|
if (!isValid) return res.status(401).send("Invalid signature");
|
package/dist/index.cjs
CHANGED
|
@@ -15,7 +15,7 @@ function createEmitter() {
|
|
|
15
15
|
if (!state.listeners.has(event)) {
|
|
16
16
|
state.listeners.set(event, /* @__PURE__ */ new Set());
|
|
17
17
|
}
|
|
18
|
-
state.listeners.get(event)
|
|
18
|
+
state.listeners.get(event)?.add(handler);
|
|
19
19
|
return () => off(event, handler);
|
|
20
20
|
}
|
|
21
21
|
function once(event, handler) {
|
|
@@ -55,217 +55,24 @@ function createEmitter() {
|
|
|
55
55
|
const emitter = { on, once, off, emit, clear, listenerCount };
|
|
56
56
|
return emitter;
|
|
57
57
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
58
|
+
function generateFingerprint() {
|
|
59
|
+
const components = [
|
|
60
|
+
`type:${os.type()}`,
|
|
61
|
+
`platform:${os.platform()}`,
|
|
62
|
+
`arch:${os.arch()}`,
|
|
63
|
+
`release:${os.release()}`,
|
|
64
|
+
`hostname:${os.hostname()}`,
|
|
65
|
+
`node:${process.versions.node}`,
|
|
66
|
+
`v8:${process.versions.v8}`
|
|
67
|
+
].join("|");
|
|
68
|
+
return crypto.createHash("sha256").update(components).digest("hex");
|
|
68
69
|
}
|
|
69
|
-
|
|
70
|
-
"
|
|
71
|
-
"failed",
|
|
72
|
-
"cancelled"
|
|
73
|
-
]);
|
|
74
|
-
function createPaymentInstance(initialResponse, deps) {
|
|
75
|
-
const state = {
|
|
76
|
-
reference: initialResponse.reference,
|
|
77
|
-
status: initialResponse.status,
|
|
78
|
-
transaction: null,
|
|
79
|
-
pollingTimer: null,
|
|
80
|
-
resolved: false,
|
|
81
|
-
pollAttempts: 0,
|
|
82
|
-
pollStartTime: Date.now(),
|
|
83
|
-
emitter: createEmitter(),
|
|
84
|
-
fetchStatus: deps.fetchStatus,
|
|
85
|
-
fetchTransaction: deps.fetchTransaction,
|
|
86
|
-
pollIntervalMs: deps.pollIntervalMs ?? 2e3,
|
|
87
|
-
maxPollDuration: deps.maxPollDuration ?? 3e5,
|
|
88
|
-
maxPollAttempts: deps.maxPollAttempts ?? 150
|
|
89
|
-
};
|
|
90
|
-
function resolveWithError(error) {
|
|
91
|
-
state.resolved = true;
|
|
92
|
-
stopPolling();
|
|
93
|
-
emitEvent("error", error);
|
|
94
|
-
}
|
|
95
|
-
function emitEvent(event, error) {
|
|
96
|
-
const data = {
|
|
97
|
-
event,
|
|
98
|
-
transaction: state.transaction ?? void 0,
|
|
99
|
-
error,
|
|
100
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
101
|
-
};
|
|
102
|
-
state.emitter.emit(event, data);
|
|
103
|
-
}
|
|
104
|
-
async function handleTerminalState(status) {
|
|
105
|
-
const txResult = await state.fetchTransaction({
|
|
106
|
-
reference: state.reference
|
|
107
|
-
});
|
|
108
|
-
if (txResult.isOk) {
|
|
109
|
-
state.transaction = txResult.value;
|
|
110
|
-
const event = statusToEvent(status);
|
|
111
|
-
if (event) {
|
|
112
|
-
emitEvent(event);
|
|
113
|
-
}
|
|
114
|
-
} else {
|
|
115
|
-
emitEvent("error", `Failed to fetch transaction: ${txResult.error}`);
|
|
116
|
-
}
|
|
117
|
-
state.resolved = true;
|
|
118
|
-
stopPolling();
|
|
119
|
-
}
|
|
120
|
-
async function handleStatusUpdate(response) {
|
|
121
|
-
if (response.reference !== state.reference) {
|
|
122
|
-
resolveWithError(
|
|
123
|
-
`Reference mismatch: expected ${state.reference} but got ${response.reference}`
|
|
124
|
-
);
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
const newStatus = response.status;
|
|
128
|
-
const oldStatus = state.status;
|
|
129
|
-
state.status = newStatus;
|
|
130
|
-
if (newStatus !== oldStatus) {
|
|
131
|
-
const event = statusToEvent(newStatus);
|
|
132
|
-
if (event) {
|
|
133
|
-
if (TERMINAL_STATES.has(newStatus)) {
|
|
134
|
-
await handleTerminalState(newStatus);
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
emitEvent(event);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
function handlePollError(error) {
|
|
142
|
-
const isNotFound = error.includes("not found") || error.includes("NOT_FOUND");
|
|
143
|
-
if (isNotFound) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
emitEvent("error", error);
|
|
147
|
-
state.resolved = true;
|
|
148
|
-
stopPolling();
|
|
149
|
-
}
|
|
150
|
-
function scheduleNextPoll() {
|
|
151
|
-
if (state.resolved || state.pollingTimer) {
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
state.pollingTimer = setTimeout(() => {
|
|
155
|
-
state.pollingTimer = null;
|
|
156
|
-
void pollStatus();
|
|
157
|
-
}, state.pollIntervalMs);
|
|
158
|
-
}
|
|
159
|
-
async function pollStatus() {
|
|
160
|
-
if (state.resolved) {
|
|
161
|
-
stopPolling();
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
if (state.pollAttempts >= state.maxPollAttempts) {
|
|
165
|
-
resolveWithError("Polling timeout: exceeded maximum attempts");
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
if (Date.now() - state.pollStartTime >= state.maxPollDuration) {
|
|
169
|
-
resolveWithError("Polling timeout: exceeded maximum duration");
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
state.pollAttempts += 1;
|
|
173
|
-
const result = await state.fetchStatus({ reference: state.reference });
|
|
174
|
-
if (result.isOk) {
|
|
175
|
-
await handleStatusUpdate(result.value);
|
|
176
|
-
} else {
|
|
177
|
-
handlePollError(result.error);
|
|
178
|
-
}
|
|
179
|
-
if (state.resolved) {
|
|
180
|
-
stopPolling();
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
scheduleNextPoll();
|
|
184
|
-
}
|
|
185
|
-
function startPolling() {
|
|
186
|
-
scheduleNextPoll();
|
|
187
|
-
}
|
|
188
|
-
function stopPolling() {
|
|
189
|
-
if (state.pollingTimer) {
|
|
190
|
-
clearTimeout(state.pollingTimer);
|
|
191
|
-
state.pollingTimer = null;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
function on(event, handler) {
|
|
195
|
-
state.emitter.on(event, handler);
|
|
196
|
-
return paymentInstance;
|
|
197
|
-
}
|
|
198
|
-
function off(event, handler) {
|
|
199
|
-
state.emitter.off(event, handler);
|
|
200
|
-
return paymentInstance;
|
|
201
|
-
}
|
|
202
|
-
function once(event, handler) {
|
|
203
|
-
state.emitter.once(event, handler);
|
|
204
|
-
return paymentInstance;
|
|
205
|
-
}
|
|
206
|
-
function wait() {
|
|
207
|
-
return new Promise((resolve, reject) => {
|
|
208
|
-
if (state.resolved) {
|
|
209
|
-
if (state.status === "successful" && state.transaction) {
|
|
210
|
-
resolve(state.transaction);
|
|
211
|
-
} else {
|
|
212
|
-
reject(new Error(`Payment ${state.status ?? "error"}`));
|
|
213
|
-
}
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
function onSuccess() {
|
|
217
|
-
cleanup();
|
|
218
|
-
if (state.transaction) {
|
|
219
|
-
resolve(state.transaction);
|
|
220
|
-
} else {
|
|
221
|
-
reject(
|
|
222
|
-
new Error("Payment successful but transaction data unavailable")
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
function onFailed() {
|
|
227
|
-
cleanup();
|
|
228
|
-
reject(new Error("Payment failed"));
|
|
229
|
-
}
|
|
230
|
-
function onCancelled() {
|
|
231
|
-
cleanup();
|
|
232
|
-
reject(new Error("Payment cancelled"));
|
|
233
|
-
}
|
|
234
|
-
function onError(data) {
|
|
235
|
-
cleanup();
|
|
236
|
-
const eventData = data;
|
|
237
|
-
reject(new Error(eventData.error ?? "Payment error"));
|
|
238
|
-
}
|
|
239
|
-
function cleanup() {
|
|
240
|
-
state.emitter.off("success", onSuccess);
|
|
241
|
-
state.emitter.off("failed", onFailed);
|
|
242
|
-
state.emitter.off("cancelled", onCancelled);
|
|
243
|
-
state.emitter.off("error", onError);
|
|
244
|
-
}
|
|
245
|
-
state.emitter.on("success", onSuccess);
|
|
246
|
-
state.emitter.on("failed", onFailed);
|
|
247
|
-
state.emitter.on("cancelled", onCancelled);
|
|
248
|
-
state.emitter.on("error", onError);
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
const paymentInstance = {
|
|
252
|
-
get reference() {
|
|
253
|
-
return state.reference;
|
|
254
|
-
},
|
|
255
|
-
get status() {
|
|
256
|
-
return state.status;
|
|
257
|
-
},
|
|
258
|
-
on,
|
|
259
|
-
once,
|
|
260
|
-
off,
|
|
261
|
-
wait
|
|
262
|
-
};
|
|
263
|
-
startPolling();
|
|
264
|
-
return paymentInstance;
|
|
70
|
+
function generateNonce(length = 16) {
|
|
71
|
+
return crypto.randomBytes(length).toString("hex");
|
|
265
72
|
}
|
|
266
73
|
|
|
267
74
|
// src/sdk.config.ts
|
|
268
|
-
var DEFAULT_BASE_URL = "https://api.nylonpay.
|
|
75
|
+
var DEFAULT_BASE_URL = "https://api.nylonpay.nilesquad.com/api/services";
|
|
269
76
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
270
77
|
var DEFAULT_MAX_RETRIES = 3;
|
|
271
78
|
var DEFAULT_MAX_POLL_INTERVAL_MS = 2e3;
|
|
@@ -283,21 +90,6 @@ var SDK_ACTIONS = {
|
|
|
283
90
|
createInvoice: "sdk-create-invoice"
|
|
284
91
|
};
|
|
285
92
|
var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([408, 429, 500, 502, 503, 504]);
|
|
286
|
-
function generateFingerprint() {
|
|
287
|
-
const components = [
|
|
288
|
-
`type:${os.type()}`,
|
|
289
|
-
`platform:${os.platform()}`,
|
|
290
|
-
`arch:${os.arch()}`,
|
|
291
|
-
`release:${os.release()}`,
|
|
292
|
-
`hostname:${os.hostname()}`,
|
|
293
|
-
`node:${process.versions.node}`,
|
|
294
|
-
`v8:${process.versions.v8}`
|
|
295
|
-
].join("|");
|
|
296
|
-
return crypto.createHash("sha256").update(components).digest("hex");
|
|
297
|
-
}
|
|
298
|
-
function generateNonce(length = 16) {
|
|
299
|
-
return crypto.randomBytes(length).toString("hex");
|
|
300
|
-
}
|
|
301
93
|
function sortValue(value) {
|
|
302
94
|
if (Array.isArray(value)) {
|
|
303
95
|
return value.map((entry) => sortValue(entry));
|
|
@@ -517,6 +309,214 @@ function parseError(error) {
|
|
|
517
309
|
}
|
|
518
310
|
return { code: "UNKNOWN", message: error };
|
|
519
311
|
}
|
|
312
|
+
|
|
313
|
+
// src/payment.ts
|
|
314
|
+
var STATUS_TO_EVENT = {
|
|
315
|
+
successful: "success",
|
|
316
|
+
failed: "failed",
|
|
317
|
+
processing: "processing",
|
|
318
|
+
cancelled: "cancelled"
|
|
319
|
+
};
|
|
320
|
+
function statusToEvent(status) {
|
|
321
|
+
return STATUS_TO_EVENT[status] ?? null;
|
|
322
|
+
}
|
|
323
|
+
var TERMINAL_STATES = /* @__PURE__ */ new Set([
|
|
324
|
+
"successful",
|
|
325
|
+
"failed",
|
|
326
|
+
"cancelled"
|
|
327
|
+
]);
|
|
328
|
+
function createPaymentInstance(initialResponse, deps) {
|
|
329
|
+
const state = {
|
|
330
|
+
reference: initialResponse.reference,
|
|
331
|
+
status: initialResponse.status,
|
|
332
|
+
transaction: null,
|
|
333
|
+
pollingTimer: null,
|
|
334
|
+
resolved: false,
|
|
335
|
+
pollAttempts: 0,
|
|
336
|
+
pollStartTime: Date.now(),
|
|
337
|
+
emitter: createEmitter(),
|
|
338
|
+
fetchStatus: deps.fetchStatus,
|
|
339
|
+
fetchTransaction: deps.fetchTransaction,
|
|
340
|
+
pollIntervalMs: deps.pollIntervalMs ?? 2e3,
|
|
341
|
+
maxPollDuration: deps.maxPollDuration ?? 3e5,
|
|
342
|
+
maxPollAttempts: deps.maxPollAttempts ?? 150
|
|
343
|
+
};
|
|
344
|
+
function resolveWithError(error) {
|
|
345
|
+
state.resolved = true;
|
|
346
|
+
stopPolling();
|
|
347
|
+
emitEvent("error", parseError(error).message);
|
|
348
|
+
}
|
|
349
|
+
function emitEvent(event, error) {
|
|
350
|
+
const data = {
|
|
351
|
+
event,
|
|
352
|
+
transaction: state.transaction ?? void 0,
|
|
353
|
+
error,
|
|
354
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
355
|
+
};
|
|
356
|
+
state.emitter.emit(event, data);
|
|
357
|
+
}
|
|
358
|
+
async function handleTerminalState(status) {
|
|
359
|
+
const txResult = await state.fetchTransaction({
|
|
360
|
+
reference: state.reference
|
|
361
|
+
});
|
|
362
|
+
if (txResult.isOk) {
|
|
363
|
+
state.transaction = txResult.value;
|
|
364
|
+
const event = statusToEvent(status);
|
|
365
|
+
if (event) {
|
|
366
|
+
emitEvent(event);
|
|
367
|
+
}
|
|
368
|
+
} else {
|
|
369
|
+
emitEvent("error", `Failed to fetch transaction: ${txResult.error}`);
|
|
370
|
+
}
|
|
371
|
+
state.resolved = true;
|
|
372
|
+
stopPolling();
|
|
373
|
+
}
|
|
374
|
+
async function handleStatusUpdate(response) {
|
|
375
|
+
if (response.reference !== state.reference) {
|
|
376
|
+
resolveWithError(
|
|
377
|
+
`Reference mismatch: expected ${state.reference} but got ${response.reference}`
|
|
378
|
+
);
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
const newStatus = response.status;
|
|
382
|
+
const oldStatus = state.status;
|
|
383
|
+
state.status = newStatus;
|
|
384
|
+
if (newStatus !== oldStatus) {
|
|
385
|
+
const event = statusToEvent(newStatus);
|
|
386
|
+
if (event) {
|
|
387
|
+
if (TERMINAL_STATES.has(newStatus)) {
|
|
388
|
+
await handleTerminalState(newStatus);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
emitEvent(event);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
function handlePollError(error) {
|
|
396
|
+
const isNotFound = error.includes("not found") || error.includes("NOT_FOUND");
|
|
397
|
+
if (isNotFound) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
emitEvent("error", parseError(error).message);
|
|
401
|
+
state.resolved = true;
|
|
402
|
+
stopPolling();
|
|
403
|
+
}
|
|
404
|
+
function scheduleNextPoll() {
|
|
405
|
+
if (state.resolved || state.pollingTimer) {
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
state.pollingTimer = setTimeout(() => {
|
|
409
|
+
state.pollingTimer = null;
|
|
410
|
+
void pollStatus();
|
|
411
|
+
}, state.pollIntervalMs);
|
|
412
|
+
}
|
|
413
|
+
async function pollStatus() {
|
|
414
|
+
if (state.resolved) {
|
|
415
|
+
stopPolling();
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
if (state.pollAttempts >= state.maxPollAttempts) {
|
|
419
|
+
resolveWithError("Polling timeout: exceeded maximum attempts");
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
if (Date.now() - state.pollStartTime >= state.maxPollDuration) {
|
|
423
|
+
resolveWithError("Polling timeout: exceeded maximum duration");
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
state.pollAttempts += 1;
|
|
427
|
+
const result = await state.fetchStatus({ reference: state.reference });
|
|
428
|
+
if (result.isOk) {
|
|
429
|
+
await handleStatusUpdate(result.value);
|
|
430
|
+
} else {
|
|
431
|
+
handlePollError(result.error);
|
|
432
|
+
}
|
|
433
|
+
if (state.resolved) {
|
|
434
|
+
stopPolling();
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
scheduleNextPoll();
|
|
438
|
+
}
|
|
439
|
+
function startPolling() {
|
|
440
|
+
scheduleNextPoll();
|
|
441
|
+
}
|
|
442
|
+
function stopPolling() {
|
|
443
|
+
if (state.pollingTimer) {
|
|
444
|
+
clearTimeout(state.pollingTimer);
|
|
445
|
+
state.pollingTimer = null;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
function on(event, handler) {
|
|
449
|
+
state.emitter.on(event, handler);
|
|
450
|
+
return paymentInstance;
|
|
451
|
+
}
|
|
452
|
+
function off(event, handler) {
|
|
453
|
+
state.emitter.off(event, handler);
|
|
454
|
+
return paymentInstance;
|
|
455
|
+
}
|
|
456
|
+
function once(event, handler) {
|
|
457
|
+
state.emitter.once(event, handler);
|
|
458
|
+
return paymentInstance;
|
|
459
|
+
}
|
|
460
|
+
function wait() {
|
|
461
|
+
return new Promise((resolve, reject) => {
|
|
462
|
+
if (state.resolved) {
|
|
463
|
+
if (state.status === "successful" && state.transaction) {
|
|
464
|
+
resolve(state.transaction);
|
|
465
|
+
} else {
|
|
466
|
+
reject(new Error(`Payment ${state.status ?? "error"}`));
|
|
467
|
+
}
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
function onSuccess() {
|
|
471
|
+
cleanup();
|
|
472
|
+
if (state.transaction) {
|
|
473
|
+
resolve(state.transaction);
|
|
474
|
+
} else {
|
|
475
|
+
reject(
|
|
476
|
+
new Error("Payment successful but transaction data unavailable")
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
function onFailed() {
|
|
481
|
+
cleanup();
|
|
482
|
+
reject(new Error("Payment failed"));
|
|
483
|
+
}
|
|
484
|
+
function onCancelled() {
|
|
485
|
+
cleanup();
|
|
486
|
+
reject(new Error("Payment cancelled"));
|
|
487
|
+
}
|
|
488
|
+
function onError(data) {
|
|
489
|
+
cleanup();
|
|
490
|
+
const eventData = data;
|
|
491
|
+
reject(new Error(eventData.error ?? "Payment error"));
|
|
492
|
+
}
|
|
493
|
+
function cleanup() {
|
|
494
|
+
state.emitter.off("success", onSuccess);
|
|
495
|
+
state.emitter.off("failed", onFailed);
|
|
496
|
+
state.emitter.off("cancelled", onCancelled);
|
|
497
|
+
state.emitter.off("error", onError);
|
|
498
|
+
}
|
|
499
|
+
state.emitter.on("success", onSuccess);
|
|
500
|
+
state.emitter.on("failed", onFailed);
|
|
501
|
+
state.emitter.on("cancelled", onCancelled);
|
|
502
|
+
state.emitter.on("error", onError);
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
const paymentInstance = {
|
|
506
|
+
get reference() {
|
|
507
|
+
return state.reference;
|
|
508
|
+
},
|
|
509
|
+
get status() {
|
|
510
|
+
return state.status;
|
|
511
|
+
},
|
|
512
|
+
on,
|
|
513
|
+
once,
|
|
514
|
+
off,
|
|
515
|
+
wait
|
|
516
|
+
};
|
|
517
|
+
startPolling();
|
|
518
|
+
return paymentInstance;
|
|
519
|
+
}
|
|
520
520
|
function verifyWebhookSignature(input) {
|
|
521
521
|
const payloadBytes = typeof input.payload === "string" ? Buffer.from(input.payload, "utf8") : Buffer.from(input.payload);
|
|
522
522
|
const expectedSignature = crypto.createHmac("sha256", input.secret).update(payloadBytes).digest("hex");
|