@tineon/t9n 0.1.6 → 0.1.8
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/dist/index.d.ts +3 -0
- package/dist/index.js +108 -41
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -6,10 +6,12 @@ export declare class T9nCheckout {
|
|
|
6
6
|
private sessionId;
|
|
7
7
|
private intervalId?;
|
|
8
8
|
private statusPollId?;
|
|
9
|
+
private closeTimeoutId?;
|
|
9
10
|
private expiresAt?;
|
|
10
11
|
private isOpen;
|
|
11
12
|
private lastResultFailed;
|
|
12
13
|
private hasAttemptedConfirm;
|
|
14
|
+
private skipCloseMark;
|
|
13
15
|
private successNotified;
|
|
14
16
|
private failureNotified;
|
|
15
17
|
constructor(config: CheckoutConfig);
|
|
@@ -29,6 +31,7 @@ export declare class T9nCheckout {
|
|
|
29
31
|
private assertSecureConfig;
|
|
30
32
|
private applyButtonStyle;
|
|
31
33
|
private applyButtonTheme;
|
|
34
|
+
private scheduleAutoClose;
|
|
32
35
|
private normalizeStatus;
|
|
33
36
|
private markFailed;
|
|
34
37
|
private markClosed;
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export class T9nCheckout {
|
|
|
8
8
|
this.isOpen = false;
|
|
9
9
|
this.lastResultFailed = false;
|
|
10
10
|
this.hasAttemptedConfirm = false;
|
|
11
|
+
this.skipCloseMark = false;
|
|
11
12
|
this.successNotified = false;
|
|
12
13
|
this.failureNotified = false;
|
|
13
14
|
this.cfg = checkoutConfigSchema.parse(config);
|
|
@@ -73,16 +74,23 @@ export class T9nCheckout {
|
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
76
|
close() {
|
|
77
|
+
if (this.closeTimeoutId) {
|
|
78
|
+
window.clearTimeout(this.closeTimeoutId);
|
|
79
|
+
this.closeTimeoutId = undefined;
|
|
80
|
+
}
|
|
76
81
|
if (this.intervalId)
|
|
77
82
|
window.clearInterval(this.intervalId);
|
|
78
83
|
if (this.statusPollId)
|
|
79
84
|
window.clearInterval(this.statusPollId);
|
|
80
|
-
if (this.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
if (!this.skipCloseMark) {
|
|
86
|
+
if (this.lastResultFailed && this.sessionId) {
|
|
87
|
+
void this.markFailed();
|
|
88
|
+
}
|
|
89
|
+
else if (!this.hasAttemptedConfirm && this.sessionId) {
|
|
90
|
+
void this.markClosed();
|
|
91
|
+
}
|
|
85
92
|
}
|
|
93
|
+
this.skipCloseMark = false;
|
|
86
94
|
this.modal?.close();
|
|
87
95
|
this.modal = undefined;
|
|
88
96
|
this.sessionId = "";
|
|
@@ -178,46 +186,83 @@ export class T9nCheckout {
|
|
|
178
186
|
async confirmPayment() {
|
|
179
187
|
this.hasAttemptedConfirm = true;
|
|
180
188
|
this.modal?.setConfirmPending(true);
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
189
|
+
try {
|
|
190
|
+
const res = await this.fetchWithTimeout(`${this.getApiBaseUrl()}/api/merchant/checkout/sessions/${this.sessionId}/confirm-payment`, {
|
|
191
|
+
method: "POST",
|
|
192
|
+
headers: {
|
|
193
|
+
"Content-Type": "application/json",
|
|
194
|
+
"x-public-key": this.cfg.publicKey,
|
|
195
|
+
},
|
|
196
|
+
body: "{}",
|
|
197
|
+
});
|
|
198
|
+
if (!res.ok) {
|
|
199
|
+
this.modal?.setConfirmPending(false);
|
|
200
|
+
this.modal?.showResult("failed", "Verification failed. Please try again.");
|
|
201
|
+
this.lastResultFailed = true;
|
|
202
|
+
this.modal?.setConfirmLabel("Retry check");
|
|
203
|
+
this.emitStatus("failed");
|
|
204
|
+
this.emitFailOnce({ sessionId: this.sessionId || undefined, error: "confirm request failed" });
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
let payload = {};
|
|
208
|
+
try {
|
|
209
|
+
payload = (await res.json());
|
|
210
|
+
}
|
|
211
|
+
catch (_) {
|
|
212
|
+
this.modal?.setConfirmPending(false);
|
|
213
|
+
this.modal?.showResult("failed", "Verification failed. Please try again.");
|
|
214
|
+
this.lastResultFailed = true;
|
|
215
|
+
this.modal?.setConfirmLabel("Retry check");
|
|
216
|
+
this.emitStatus("failed");
|
|
217
|
+
this.emitFailOnce({ sessionId: this.sessionId || undefined, error: "invalid confirm response" });
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
190
220
|
this.modal?.setConfirmPending(false);
|
|
221
|
+
const normalized = this.normalizeStatus(payload.status || "");
|
|
222
|
+
this.emitStatus(normalized);
|
|
223
|
+
if (normalized === "settled") {
|
|
224
|
+
this.modal?.setConfirmLabel("I have made the payment");
|
|
225
|
+
this.modal?.showResult("success", "Payment received successfully.");
|
|
226
|
+
this.lastResultFailed = false;
|
|
227
|
+
this.emitSuccessOnce({ sessionId: this.sessionId, status: payload.status || "settled" });
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
if (normalized === "expired") {
|
|
231
|
+
this.modal?.showResult("failed", "This session has expired.");
|
|
232
|
+
this.lastResultFailed = false;
|
|
233
|
+
this.emitFailOnce({ sessionId: this.sessionId, error: "checkout expired" });
|
|
234
|
+
this.scheduleAutoClose();
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (normalized === "failed") {
|
|
238
|
+
this.modal?.showResult("failed", "Payment failed. Please try again.");
|
|
239
|
+
this.lastResultFailed = true;
|
|
240
|
+
this.modal?.setConfirmLabel("Retry check");
|
|
241
|
+
this.emitFailOnce({ sessionId: this.sessionId || undefined, error: "checkout failed" });
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (normalized === "closed") {
|
|
245
|
+
this.modal?.showResult("failed", "Checkout was closed. Please try again.");
|
|
246
|
+
this.lastResultFailed = true;
|
|
247
|
+
this.modal?.setConfirmLabel("Retry check");
|
|
248
|
+
this.emitFailOnce({ sessionId: this.sessionId || undefined, error: "checkout closed" });
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
191
251
|
this.modal?.showResult("failed", "No payment detected yet. Please try again.");
|
|
192
252
|
this.lastResultFailed = true;
|
|
193
253
|
this.modal?.setConfirmLabel("Retry check");
|
|
194
|
-
this.
|
|
195
|
-
this.emitFailOnce({ sessionId: this.sessionId || undefined, error: "confirm request failed" });
|
|
196
|
-
throw new Error("T9N: failed to confirm payment");
|
|
254
|
+
this.emitFailOnce({ sessionId: this.sessionId || undefined, error: "payment not detected" });
|
|
197
255
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
this.emitStatus(normalized);
|
|
202
|
-
if (payload.status === "pending" ||
|
|
203
|
-
payload.status === "processing" ||
|
|
204
|
-
normalized === "pending_confirmation" ||
|
|
205
|
-
normalized === "awaiting_payment") {
|
|
206
|
-
this.modal?.showResult("failed", "No payment detected yet. Please try again.");
|
|
256
|
+
catch (err) {
|
|
257
|
+
this.modal?.setConfirmPending(false);
|
|
258
|
+
this.modal?.showResult("failed", "Verification failed. Please try again.");
|
|
207
259
|
this.lastResultFailed = true;
|
|
208
260
|
this.modal?.setConfirmLabel("Retry check");
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
this.lastResultFailed = false;
|
|
215
|
-
this.emitSuccessOnce({ sessionId: this.sessionId, status: payload.status });
|
|
216
|
-
}
|
|
217
|
-
if (payload.status === "expired") {
|
|
218
|
-
this.modal?.showResult("failed", "This session has expired.");
|
|
219
|
-
this.lastResultFailed = true;
|
|
220
|
-
this.emitFailOnce({ sessionId: this.sessionId, error: "checkout expired" });
|
|
261
|
+
this.emitStatus("failed");
|
|
262
|
+
this.emitFailOnce({
|
|
263
|
+
sessionId: this.sessionId || undefined,
|
|
264
|
+
error: err?.message || "confirm request failed",
|
|
265
|
+
});
|
|
221
266
|
}
|
|
222
267
|
}
|
|
223
268
|
startTimer() {
|
|
@@ -227,8 +272,14 @@ export class T9nCheckout {
|
|
|
227
272
|
const ms = this.expiresAt.getTime() - Date.now();
|
|
228
273
|
if (ms <= 0) {
|
|
229
274
|
this.modal?.setTimer("00:00");
|
|
230
|
-
this.
|
|
231
|
-
|
|
275
|
+
if (this.intervalId)
|
|
276
|
+
window.clearInterval(this.intervalId);
|
|
277
|
+
if (this.statusPollId)
|
|
278
|
+
window.clearInterval(this.statusPollId);
|
|
279
|
+
this.modal?.showResult("failed", "This session has expired.");
|
|
280
|
+
this.lastResultFailed = false;
|
|
281
|
+
this.emitFailOnce({ sessionId: this.sessionId || undefined, error: "checkout expired" });
|
|
282
|
+
this.scheduleAutoClose();
|
|
232
283
|
return;
|
|
233
284
|
}
|
|
234
285
|
const minutes = Math.floor(ms / 60000)
|
|
@@ -275,17 +326,19 @@ export class T9nCheckout {
|
|
|
275
326
|
if (this.hasAttemptedConfirm) {
|
|
276
327
|
this.modal?.showResult("failed", "No payment detected yet. Please try again.");
|
|
277
328
|
this.lastResultFailed = true;
|
|
329
|
+
this.emitFailOnce({ sessionId: this.sessionId || undefined, error: "payment not detected" });
|
|
278
330
|
}
|
|
279
331
|
}
|
|
280
332
|
}
|
|
281
333
|
if (payload.status === "expired") {
|
|
282
334
|
this.modal?.showResult("failed", "This session has expired.");
|
|
283
|
-
this.lastResultFailed =
|
|
335
|
+
this.lastResultFailed = false;
|
|
284
336
|
if (this.intervalId)
|
|
285
337
|
window.clearInterval(this.intervalId);
|
|
286
338
|
if (this.statusPollId)
|
|
287
339
|
window.clearInterval(this.statusPollId);
|
|
288
340
|
this.emitFailOnce({ sessionId: this.sessionId, error: "checkout expired" });
|
|
341
|
+
this.scheduleAutoClose();
|
|
289
342
|
}
|
|
290
343
|
}
|
|
291
344
|
catch (_) {
|
|
@@ -397,6 +450,16 @@ export class T9nCheckout {
|
|
|
397
450
|
break;
|
|
398
451
|
}
|
|
399
452
|
}
|
|
453
|
+
scheduleAutoClose(delayMs = 1200) {
|
|
454
|
+
this.skipCloseMark = true;
|
|
455
|
+
if (this.closeTimeoutId) {
|
|
456
|
+
window.clearTimeout(this.closeTimeoutId);
|
|
457
|
+
}
|
|
458
|
+
this.closeTimeoutId = window.setTimeout(() => {
|
|
459
|
+
if (this.isOpen)
|
|
460
|
+
this.close();
|
|
461
|
+
}, delayMs);
|
|
462
|
+
}
|
|
400
463
|
normalizeStatus(value) {
|
|
401
464
|
switch (value) {
|
|
402
465
|
case "created":
|
|
@@ -404,6 +467,10 @@ export class T9nCheckout {
|
|
|
404
467
|
return "awaiting_payment";
|
|
405
468
|
case "awaiting_payment":
|
|
406
469
|
case "pending_confirmation":
|
|
470
|
+
return value;
|
|
471
|
+
case "pending":
|
|
472
|
+
case "processing":
|
|
473
|
+
return "pending_confirmation";
|
|
407
474
|
case "closed":
|
|
408
475
|
case "expired":
|
|
409
476
|
case "settled":
|