@tineon/t9n 0.1.7 → 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 +107 -42
- 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,47 +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);
|
|
191
|
-
|
|
192
|
-
this.
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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
|
+
}
|
|
206
251
|
this.modal?.showResult("failed", "No payment detected yet. Please try again.");
|
|
207
252
|
this.lastResultFailed = true;
|
|
208
253
|
this.modal?.setConfirmLabel("Retry check");
|
|
209
254
|
this.emitFailOnce({ sessionId: this.sessionId || undefined, error: "payment not detected" });
|
|
210
|
-
return;
|
|
211
255
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
this.modal?.showResult("
|
|
215
|
-
this.lastResultFailed = false;
|
|
216
|
-
this.emitSuccessOnce({ sessionId: this.sessionId, status: payload.status });
|
|
217
|
-
}
|
|
218
|
-
if (payload.status === "expired") {
|
|
219
|
-
this.modal?.showResult("failed", "This session has expired.");
|
|
256
|
+
catch (err) {
|
|
257
|
+
this.modal?.setConfirmPending(false);
|
|
258
|
+
this.modal?.showResult("failed", "Verification failed. Please try again.");
|
|
220
259
|
this.lastResultFailed = true;
|
|
221
|
-
this.
|
|
260
|
+
this.modal?.setConfirmLabel("Retry check");
|
|
261
|
+
this.emitStatus("failed");
|
|
262
|
+
this.emitFailOnce({
|
|
263
|
+
sessionId: this.sessionId || undefined,
|
|
264
|
+
error: err?.message || "confirm request failed",
|
|
265
|
+
});
|
|
222
266
|
}
|
|
223
267
|
}
|
|
224
268
|
startTimer() {
|
|
@@ -228,8 +272,14 @@ export class T9nCheckout {
|
|
|
228
272
|
const ms = this.expiresAt.getTime() - Date.now();
|
|
229
273
|
if (ms <= 0) {
|
|
230
274
|
this.modal?.setTimer("00:00");
|
|
231
|
-
this.
|
|
232
|
-
|
|
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();
|
|
233
283
|
return;
|
|
234
284
|
}
|
|
235
285
|
const minutes = Math.floor(ms / 60000)
|
|
@@ -282,12 +332,13 @@ export class T9nCheckout {
|
|
|
282
332
|
}
|
|
283
333
|
if (payload.status === "expired") {
|
|
284
334
|
this.modal?.showResult("failed", "This session has expired.");
|
|
285
|
-
this.lastResultFailed =
|
|
335
|
+
this.lastResultFailed = false;
|
|
286
336
|
if (this.intervalId)
|
|
287
337
|
window.clearInterval(this.intervalId);
|
|
288
338
|
if (this.statusPollId)
|
|
289
339
|
window.clearInterval(this.statusPollId);
|
|
290
340
|
this.emitFailOnce({ sessionId: this.sessionId, error: "checkout expired" });
|
|
341
|
+
this.scheduleAutoClose();
|
|
291
342
|
}
|
|
292
343
|
}
|
|
293
344
|
catch (_) {
|
|
@@ -399,6 +450,16 @@ export class T9nCheckout {
|
|
|
399
450
|
break;
|
|
400
451
|
}
|
|
401
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
|
+
}
|
|
402
463
|
normalizeStatus(value) {
|
|
403
464
|
switch (value) {
|
|
404
465
|
case "created":
|
|
@@ -406,6 +467,10 @@ export class T9nCheckout {
|
|
|
406
467
|
return "awaiting_payment";
|
|
407
468
|
case "awaiting_payment":
|
|
408
469
|
case "pending_confirmation":
|
|
470
|
+
return value;
|
|
471
|
+
case "pending":
|
|
472
|
+
case "processing":
|
|
473
|
+
return "pending_confirmation";
|
|
409
474
|
case "closed":
|
|
410
475
|
case "expired":
|
|
411
476
|
case "settled":
|