mmpay-browser-sdk 1.0.6 → 1.0.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/README.md +9 -2
- package/dist/cjs/index.d.ts +18 -112
- package/dist/cjs/index.js +90 -114
- package/dist/esm/index.d.ts +18 -112
- package/dist/esm/index.js +90 -114
- package/dist/mmpay-sdk.js +90 -114
- package/dist/mmpay-sdk.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +125 -142
- package/test/home.html +3 -2
package/src/index.ts
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface SDKOptions {
|
|
2
|
+
pollInterval?: number;
|
|
3
|
+
environment?: 'sandbox' | 'production';
|
|
4
|
+
baseUrl?: string;
|
|
5
|
+
merchantName?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface ICreateTokenRequestParams {
|
|
2
9
|
amount: number;
|
|
3
10
|
orderId: string;
|
|
4
|
-
|
|
11
|
+
nonce?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ICreateTokenResponse {
|
|
14
|
+
orderId: string;
|
|
15
|
+
token: string;
|
|
5
16
|
}
|
|
6
17
|
|
|
7
18
|
export interface ICreatePaymentRequestParams {
|
|
8
19
|
amount: number;
|
|
9
|
-
currency?: string;
|
|
10
20
|
orderId: string;
|
|
11
21
|
callbackUrl?: string;
|
|
12
22
|
nonce?: string;
|
|
23
|
+
customMessage?: string;
|
|
13
24
|
}
|
|
14
25
|
export interface ICreatePaymentResponse {
|
|
15
26
|
_id: string;
|
|
@@ -19,17 +30,7 @@ export interface ICreatePaymentResponse {
|
|
|
19
30
|
transactionRefId: string;
|
|
20
31
|
qr: string;
|
|
21
32
|
}
|
|
22
|
-
|
|
23
|
-
amount: number;
|
|
24
|
-
currency?: string;
|
|
25
|
-
orderId: string;
|
|
26
|
-
callbackUrl?: string;
|
|
27
|
-
nonce?: string;
|
|
28
|
-
}
|
|
29
|
-
export interface ICreateTokenResponse {
|
|
30
|
-
orderId: string;
|
|
31
|
-
token: string;
|
|
32
|
-
}
|
|
33
|
+
|
|
33
34
|
export interface IPollingRequest {
|
|
34
35
|
amount: number;
|
|
35
36
|
currency?: string;
|
|
@@ -46,12 +47,6 @@ export interface PolliongResult {
|
|
|
46
47
|
success: boolean;
|
|
47
48
|
transaction: IPollingResponse;
|
|
48
49
|
}
|
|
49
|
-
export interface SDKOptions {
|
|
50
|
-
pollInterval?: number;
|
|
51
|
-
environment?: 'sandbox' | 'production';
|
|
52
|
-
baseUrl?: string;
|
|
53
|
-
merchantName?: string;
|
|
54
|
-
}
|
|
55
50
|
|
|
56
51
|
declare const QRious: any;
|
|
57
52
|
declare const window: Window & {
|
|
@@ -71,6 +66,7 @@ export class MMPaySDK {
|
|
|
71
66
|
private merchantName: string;
|
|
72
67
|
private environment: 'sandbox' | 'production';
|
|
73
68
|
private pollIntervalId: number | undefined = undefined;
|
|
69
|
+
private countdownIntervalId: number | undefined = undefined;
|
|
74
70
|
private onCompleteCallback: ((result: PolliongResult) => void) | null = null;
|
|
75
71
|
private overlayElement: HTMLDivElement | null = null;
|
|
76
72
|
|
|
@@ -78,12 +74,8 @@ export class MMPaySDK {
|
|
|
78
74
|
private pendingPaymentPayload: ICreatePaymentRequestParams | null = null;
|
|
79
75
|
|
|
80
76
|
private readonly QR_SIZE: number = 290;
|
|
77
|
+
private readonly TIMEOUT_SECONDS: number = 300;
|
|
81
78
|
|
|
82
|
-
/**
|
|
83
|
-
* constructor
|
|
84
|
-
* @param publishableKey
|
|
85
|
-
* @param options
|
|
86
|
-
*/
|
|
87
79
|
constructor(publishableKey: string, options: SDKOptions = {}) {
|
|
88
80
|
if (!publishableKey) {
|
|
89
81
|
throw new Error("A Publishable Key is required to initialize [MMPaySDK].");
|
|
@@ -94,12 +86,7 @@ export class MMPaySDK {
|
|
|
94
86
|
this.merchantName = options.merchantName || 'Your Merchant';
|
|
95
87
|
this.POLL_INTERVAL_MS = options.pollInterval || 5000;
|
|
96
88
|
}
|
|
97
|
-
|
|
98
|
-
* _callApi
|
|
99
|
-
* @param endpoint
|
|
100
|
-
* @param data
|
|
101
|
-
* @returns
|
|
102
|
-
*/
|
|
89
|
+
|
|
103
90
|
private async _callApi<T>(endpoint: string, data: object = {}): Promise<T> {
|
|
104
91
|
let config: any = {
|
|
105
92
|
'Content-Type': 'application/json',
|
|
@@ -123,16 +110,7 @@ export class MMPaySDK {
|
|
|
123
110
|
}
|
|
124
111
|
return response.json() as Promise<T>;
|
|
125
112
|
}
|
|
126
|
-
|
|
127
|
-
* _callApiTokenRequest
|
|
128
|
-
* @param {ICreateTokenRequestParams} payload
|
|
129
|
-
* @param {number} payload.amount
|
|
130
|
-
* @param {string} payload.currency
|
|
131
|
-
* @param {string} payload.orderId
|
|
132
|
-
* @param {string} payload.nonce
|
|
133
|
-
* @param {string} payload.callbackUrl
|
|
134
|
-
* @returns {Promise<ICreateTokenResponse>}
|
|
135
|
-
*/
|
|
113
|
+
|
|
136
114
|
private async _callApiTokenRequest(payload: ICreateTokenRequestParams): Promise<ICreateTokenResponse> {
|
|
137
115
|
try {
|
|
138
116
|
const endpoint = this.environment === 'sandbox'
|
|
@@ -144,16 +122,7 @@ export class MMPaySDK {
|
|
|
144
122
|
throw error;
|
|
145
123
|
}
|
|
146
124
|
}
|
|
147
|
-
|
|
148
|
-
* _callApiPaymentRequest
|
|
149
|
-
* @param {ICreatePaymentRequestParams} payload
|
|
150
|
-
* @param {number} payload.amount
|
|
151
|
-
* @param {string} payload.currency
|
|
152
|
-
* @param {string} payload.orderId
|
|
153
|
-
* @param {string} payload.nonce
|
|
154
|
-
* @param {string} payload.callbackUrl
|
|
155
|
-
* @returns {Promise<ICreatePaymentResponse>}
|
|
156
|
-
*/
|
|
125
|
+
|
|
157
126
|
private async _callApiPaymentRequest(payload: ICreatePaymentRequestParams): Promise<ICreatePaymentResponse> {
|
|
158
127
|
try {
|
|
159
128
|
const endpoint = this.environment === 'sandbox'
|
|
@@ -166,85 +135,69 @@ export class MMPaySDK {
|
|
|
166
135
|
}
|
|
167
136
|
}
|
|
168
137
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
* @param {string} params.callbackUrl
|
|
177
|
-
* @returns {Promise<ICreatePaymentResponse>}
|
|
178
|
-
*/
|
|
179
|
-
public async createPayment(params: ICorePayParams): Promise<ICreatePaymentResponse> {
|
|
180
|
-
const payload: ICreatePaymentRequestParams = {
|
|
138
|
+
public async createPayment(params: ICreatePaymentRequestParams): Promise<ICreatePaymentResponse> {
|
|
139
|
+
const tokenPayload: ICreateTokenRequestParams = {
|
|
140
|
+
amount: params.amount,
|
|
141
|
+
orderId: params.orderId,
|
|
142
|
+
nonce: new Date().getTime().toString() + '_mmp'
|
|
143
|
+
}
|
|
144
|
+
const paymentPayload: ICreatePaymentRequestParams = {
|
|
181
145
|
amount: params.amount,
|
|
182
146
|
orderId: params.orderId,
|
|
183
147
|
callbackUrl: params.callbackUrl,
|
|
184
|
-
|
|
148
|
+
customMessage: params.customMessage,
|
|
185
149
|
nonce: new Date().getTime().toString() + '_mmp'
|
|
186
150
|
}
|
|
187
151
|
try {
|
|
188
|
-
const tokenResponse = await this._callApiTokenRequest(
|
|
152
|
+
const tokenResponse = await this._callApiTokenRequest(tokenPayload);
|
|
189
153
|
this.tokenKey = tokenResponse.token as string;
|
|
190
|
-
|
|
191
|
-
return apiResponse
|
|
154
|
+
return await this._callApiPaymentRequest(paymentPayload);
|
|
192
155
|
} catch (error) {
|
|
193
156
|
console.error("Payment request failed:", error);
|
|
194
157
|
throw error;
|
|
195
158
|
}
|
|
196
159
|
}
|
|
197
|
-
|
|
198
|
-
* showPaymentModal
|
|
199
|
-
* @param {ICorePayParams} params
|
|
200
|
-
* @param {number} params.amount
|
|
201
|
-
* @param {string} params.orderId
|
|
202
|
-
* @param {string} params.callbackUrl
|
|
203
|
-
* @param {Function} onComplete
|
|
204
|
-
*/
|
|
160
|
+
|
|
205
161
|
public async showPaymentModal(
|
|
206
|
-
params:
|
|
162
|
+
params: ICreatePaymentRequestParams,
|
|
207
163
|
onComplete: (result: PolliongResult) => void
|
|
208
164
|
): Promise<void> {
|
|
209
165
|
const initialContent = `<div class="mmpay-overlay-content"><div style="text-align: center; color: #fff;">ငွေပေးချေမှု စတင်နေသည်...</div></div>`;
|
|
210
166
|
this._createAndRenderModal(initialContent, false);
|
|
211
167
|
this.onCompleteCallback = onComplete;
|
|
212
|
-
|
|
168
|
+
|
|
169
|
+
const tokenPayload: ICreateTokenRequestParams = {
|
|
170
|
+
amount: params.amount,
|
|
171
|
+
orderId: params.orderId,
|
|
172
|
+
nonce: new Date().getTime().toString() + '_mmp'
|
|
173
|
+
}
|
|
174
|
+
const paymentPayload: ICreatePaymentRequestParams = {
|
|
213
175
|
amount: params.amount,
|
|
214
176
|
orderId: params.orderId,
|
|
215
177
|
callbackUrl: params.callbackUrl,
|
|
216
|
-
|
|
178
|
+
customMessage: params.customMessage,
|
|
217
179
|
nonce: new Date().getTime().toString() + '_mmp'
|
|
218
180
|
}
|
|
219
181
|
|
|
220
182
|
try {
|
|
221
|
-
const tokenResponse = await this._callApiTokenRequest(
|
|
183
|
+
const tokenResponse = await this._callApiTokenRequest(tokenPayload);
|
|
222
184
|
this.tokenKey = tokenResponse.token as string;
|
|
223
|
-
const apiResponse = await this._callApiPaymentRequest(
|
|
185
|
+
const apiResponse = await this._callApiPaymentRequest(paymentPayload);
|
|
224
186
|
if (apiResponse && apiResponse.qr && apiResponse.transactionRefId) {
|
|
225
187
|
this.pendingApiResponse = apiResponse;
|
|
226
|
-
this.pendingPaymentPayload =
|
|
227
|
-
this._renderQrModalContent(apiResponse,
|
|
228
|
-
this._startPolling(
|
|
188
|
+
this.pendingPaymentPayload = paymentPayload;
|
|
189
|
+
this._renderQrModalContent(apiResponse, paymentPayload, this.merchantName);
|
|
190
|
+
this._startPolling(paymentPayload, onComplete);
|
|
191
|
+
this._startCountdown(paymentPayload.orderId);
|
|
229
192
|
} else {
|
|
230
193
|
this._showTerminalMessage(apiResponse.orderId || 'N/A', 'FAILED', 'ငွေပေးချေမှု စတင်ရန် မအောင်မြင်ပါ။ QR ဒေတာ မရရှိပါ။');
|
|
231
194
|
}
|
|
232
195
|
} catch (error) {
|
|
233
196
|
this.tokenKey = null;
|
|
234
|
-
this._showTerminalMessage(
|
|
197
|
+
this._showTerminalMessage(paymentPayload.orderId || 'N/A', 'FAILED', 'ငွေပေးချေမှု စတင်စဉ် အမှားအယွင်း ဖြစ်ပွားသည်။ ကွန်ဆိုးလ်တွင် ကြည့်ပါ။');
|
|
235
198
|
}
|
|
236
199
|
}
|
|
237
200
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* _createAndRenderModal
|
|
244
|
-
* @param {string} contentHtml
|
|
245
|
-
* @param {boolean} isTerminal
|
|
246
|
-
* @returns
|
|
247
|
-
*/
|
|
248
201
|
private _createAndRenderModal(contentHtml: string, isTerminal: boolean = false): HTMLDivElement {
|
|
249
202
|
this._cleanupModal(false);
|
|
250
203
|
const overlay = document.createElement('div');
|
|
@@ -278,7 +231,6 @@ export class MMPaySDK {
|
|
|
278
231
|
width: 100%;
|
|
279
232
|
padding: 20px 0;
|
|
280
233
|
}
|
|
281
|
-
/* Card Base Styles */
|
|
282
234
|
.mmpay-card {
|
|
283
235
|
background: #ffffff;
|
|
284
236
|
border-radius: 16px;
|
|
@@ -349,15 +301,10 @@ export class MMPaySDK {
|
|
|
349
301
|
};
|
|
350
302
|
window.MMPayReRenderModal = () => this._reRenderPendingModalInstance();
|
|
351
303
|
overlay.innerHTML += `<div class="mmpay-overlay-content">${contentHtml}</div>`;
|
|
352
|
-
document.body.style.overflow = 'hidden';
|
|
304
|
+
document.body.style.overflow = 'hidden';
|
|
353
305
|
return overlay;
|
|
354
306
|
}
|
|
355
|
-
|
|
356
|
-
* _renderQrModalContent
|
|
357
|
-
* @param {ICreatePaymentResponse} apiResponse
|
|
358
|
-
* @param {CreatePaymentRequest} payload
|
|
359
|
-
* @param {string} merchantName
|
|
360
|
-
*/
|
|
307
|
+
|
|
361
308
|
private _renderQrModalContent(apiResponse: ICreatePaymentResponse, payload: ICreatePaymentRequestParams, merchantName: string): void {
|
|
362
309
|
const qrData = apiResponse.qr;
|
|
363
310
|
const amountDisplay = `${apiResponse.amount.toFixed(2)} MMK`;
|
|
@@ -382,7 +329,7 @@ export class MMPaySDK {
|
|
|
382
329
|
<style>
|
|
383
330
|
.mmpay-card { max-width: 350px; padding: 16px; }
|
|
384
331
|
.mmpay-header { color: #1f2937; font-size: 1rem; font-weight: bold; margin-bottom: 8px; }
|
|
385
|
-
.mmpay-qr-container { padding: 0; margin: 10px auto; display: inline-block; line-height: 0; width: 300px; height: 300px; }
|
|
332
|
+
.mmpay-qr-container { padding: 0; margin: 5px auto 10px auto; display: inline-block; line-height: 0; width: 300px; height: 300px; }
|
|
386
333
|
#${qrCanvasId} { display: block; background: white; border-radius: 8px; width: 100%; height: 100%; }
|
|
387
334
|
.mmpay-amount { font-size: 1.2rem; font-weight: 800; color: #1f2937; margin: 0; }
|
|
388
335
|
.mmpay-separator { border-top: 1px solid #f3f4f6; margin: 12px 0; }
|
|
@@ -391,10 +338,28 @@ export class MMPaySDK {
|
|
|
391
338
|
.mmpay-detail span { text-align: left; }
|
|
392
339
|
.mmpay-secure-text { color: #757575; border-radius: 9999px; font-size: 0.8rem; font-weight: 600; display: inline-flex; align-items: center; justify-content: center; }
|
|
393
340
|
.mmpay-warning { font-size: 0.75rem; color: #9ca3af; font-weight: 500; margin-top: 12px; line-height: 1.5; }
|
|
341
|
+
|
|
342
|
+
.mmpay-timer-badge {
|
|
343
|
+
background-color: #fef2f2;
|
|
344
|
+
color: #b91c1c;
|
|
345
|
+
padding: 4px 10px;
|
|
346
|
+
border-radius: 12px;
|
|
347
|
+
font-weight: 700;
|
|
348
|
+
font-size: 0.85rem;
|
|
349
|
+
display: inline-flex;
|
|
350
|
+
align-items: center;
|
|
351
|
+
gap: 5px;
|
|
352
|
+
margin: 8px 0;
|
|
353
|
+
border: 1px solid #fee2e2;
|
|
354
|
+
}
|
|
355
|
+
.mmpay-timer-icon {
|
|
356
|
+
width: 14px;
|
|
357
|
+
height: 14px;
|
|
358
|
+
fill: currentColor;
|
|
359
|
+
}
|
|
394
360
|
</style>
|
|
395
361
|
|
|
396
362
|
<div class="mmpay-card">
|
|
397
|
-
<!-- Close Button - Triggers Confirmation Modal -->
|
|
398
363
|
<button class="mmpay-close-btn" onclick="MMPayCloseModal(false)">
|
|
399
364
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 16 16">
|
|
400
365
|
<path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/>
|
|
@@ -409,6 +374,14 @@ export class MMPaySDK {
|
|
|
409
374
|
${merchantName} သို့ပေးချေပါ
|
|
410
375
|
</div>
|
|
411
376
|
|
|
377
|
+
<div class="mmpay-timer-badge" id="mmpay-timer-badge">
|
|
378
|
+
<svg class="mmpay-timer-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
|
379
|
+
<path d="M8 3.5a.5.5 0 0 0-1 0V9a.5.5 0 0 0 .252.434l3.5 2a.5.5 0 0 0 .496-.868L8 8.71V3.5z"/>
|
|
380
|
+
<path d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm7-8A7 7 0 1 1 1 8a7 7 0 0 1 14 0z"/>
|
|
381
|
+
</svg>
|
|
382
|
+
<span id="mmpay-countdown-text">05:00</span>
|
|
383
|
+
</div>
|
|
384
|
+
|
|
412
385
|
<div class="mmpay-amount">${amountDisplay}</div>
|
|
413
386
|
|
|
414
387
|
<div class="mmpay-qr-container">
|
|
@@ -441,17 +414,12 @@ export class MMPaySDK {
|
|
|
441
414
|
this._createAndRenderModal(qrContentHtml, false);
|
|
442
415
|
this._injectQrScript(qrData, qrCanvasId);
|
|
443
416
|
}
|
|
444
|
-
|
|
445
|
-
* _showTerminalMessage
|
|
446
|
-
* @param {string} orderId
|
|
447
|
-
* @param {string} status
|
|
448
|
-
* @param {string} message
|
|
449
|
-
*/
|
|
417
|
+
|
|
450
418
|
private _showTerminalMessage(orderId: string, status: 'SUCCESS' | 'FAILED' | 'EXPIRED', message: string): void {
|
|
451
419
|
this._cleanupModal(true);
|
|
452
|
-
const successColor = '#10b981';
|
|
453
|
-
const failureColor = '#ef4444';
|
|
454
|
-
const expiredColor = '#f59e0b';
|
|
420
|
+
const successColor = '#10b981';
|
|
421
|
+
const failureColor = '#ef4444';
|
|
422
|
+
const expiredColor = '#f59e0b';
|
|
455
423
|
let color: string;
|
|
456
424
|
let iconSvg: string;
|
|
457
425
|
let statusText: string;
|
|
@@ -462,7 +430,6 @@ export class MMPaySDK {
|
|
|
462
430
|
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022l-3.473 4.425-2.094-2.094a.75.75 0 0 0-1.06 1.06L6.92 10.865l.764.764a.75.75 0 0 0 1.06 0l4.5-5.5a.75.75 0 0 0-.01-1.05z"/>
|
|
463
431
|
</svg>`;
|
|
464
432
|
} else {
|
|
465
|
-
// Shared icon for FAILED and EXPIRED (X mark)
|
|
466
433
|
color = status === 'FAILED' ? failureColor : expiredColor;
|
|
467
434
|
statusText = status === 'FAILED' ? 'မအောင်မြင်' : 'သက်တမ်းကုန်';
|
|
468
435
|
iconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="${color}" viewBox="0 0 16 16">
|
|
@@ -487,16 +454,20 @@ export class MMPaySDK {
|
|
|
487
454
|
</button>
|
|
488
455
|
</div>
|
|
489
456
|
`;
|
|
490
|
-
this._createAndRenderModal(content, true);
|
|
457
|
+
this._createAndRenderModal(content, true);
|
|
491
458
|
}
|
|
492
|
-
|
|
493
|
-
* _showCancelConfirmationModal
|
|
494
|
-
*/
|
|
459
|
+
|
|
495
460
|
private _showCancelConfirmationModal(): void {
|
|
496
461
|
if (this.pollIntervalId !== undefined) {
|
|
497
462
|
window.clearInterval(this.pollIntervalId);
|
|
498
463
|
this.pollIntervalId = undefined;
|
|
499
464
|
}
|
|
465
|
+
|
|
466
|
+
if (this.countdownIntervalId !== undefined) {
|
|
467
|
+
window.clearInterval(this.countdownIntervalId);
|
|
468
|
+
this.countdownIntervalId = undefined;
|
|
469
|
+
}
|
|
470
|
+
|
|
500
471
|
this._cleanupModal(false);
|
|
501
472
|
const content = `
|
|
502
473
|
<div class="mmpay-card mmpay-terminal-card" style="
|
|
@@ -518,11 +489,9 @@ export class MMPaySDK {
|
|
|
518
489
|
</div>
|
|
519
490
|
</div>
|
|
520
491
|
`;
|
|
521
|
-
this._createAndRenderModal(content, false);
|
|
492
|
+
this._createAndRenderModal(content, false);
|
|
522
493
|
}
|
|
523
|
-
|
|
524
|
-
* _reRenderPendingModalInstance
|
|
525
|
-
*/
|
|
494
|
+
|
|
526
495
|
private _reRenderPendingModalInstance(): void {
|
|
527
496
|
if (this.pendingApiResponse && this.pendingPaymentPayload && this.onCompleteCallback) {
|
|
528
497
|
this._cleanupModal(true);
|
|
@@ -531,15 +500,16 @@ export class MMPaySDK {
|
|
|
531
500
|
this._cleanupModal(true);
|
|
532
501
|
}
|
|
533
502
|
}
|
|
534
|
-
|
|
535
|
-
* Cleans up the modal and stops polling.
|
|
536
|
-
* @param {boolean} restoreBodyScroll
|
|
537
|
-
*/
|
|
503
|
+
|
|
538
504
|
private _cleanupModal(restoreBodyScroll: boolean): void {
|
|
539
505
|
if (this.pollIntervalId !== undefined) {
|
|
540
506
|
window.clearInterval(this.pollIntervalId);
|
|
541
507
|
this.pollIntervalId = undefined;
|
|
542
508
|
}
|
|
509
|
+
if (this.countdownIntervalId !== undefined) {
|
|
510
|
+
window.clearInterval(this.countdownIntervalId);
|
|
511
|
+
this.countdownIntervalId = undefined;
|
|
512
|
+
}
|
|
543
513
|
if (this.overlayElement && this.overlayElement.parentNode) {
|
|
544
514
|
this.overlayElement.parentNode.removeChild(this.overlayElement);
|
|
545
515
|
this.overlayElement = null;
|
|
@@ -550,11 +520,7 @@ export class MMPaySDK {
|
|
|
550
520
|
delete window.MMPayCloseModal;
|
|
551
521
|
delete window.MMPayReRenderModal;
|
|
552
522
|
}
|
|
553
|
-
|
|
554
|
-
* _injectQrScript
|
|
555
|
-
* @param {string} qrData
|
|
556
|
-
* @param {string} qrCanvasId
|
|
557
|
-
*/
|
|
523
|
+
|
|
558
524
|
private _injectQrScript(qrData: string, qrCanvasId: string): void {
|
|
559
525
|
const script = document.createElement('script');
|
|
560
526
|
script.src = "https://cdn.jsdelivr.net/npm/qrious@4.0.2/dist/qrious.min.js";
|
|
@@ -576,16 +542,7 @@ export class MMPaySDK {
|
|
|
576
542
|
};
|
|
577
543
|
document.head.appendChild(script);
|
|
578
544
|
}
|
|
579
|
-
|
|
580
|
-
* _startPolling
|
|
581
|
-
* @param {IPollingRequest} payload
|
|
582
|
-
* @param {number} payload.amount
|
|
583
|
-
* @param {string} payload.currency
|
|
584
|
-
* @param {string} payload.orderId
|
|
585
|
-
* @param {string} payload.nonce
|
|
586
|
-
* @param {string} payload.callbackUrl
|
|
587
|
-
* @param {Function} onComplete
|
|
588
|
-
*/
|
|
545
|
+
|
|
589
546
|
private async _startPolling(payload: IPollingRequest, onComplete: (result: PolliongResult) => void): Promise<void> {
|
|
590
547
|
if (this.pollIntervalId !== undefined) {
|
|
591
548
|
window.clearInterval(this.pollIntervalId);
|
|
@@ -621,7 +578,33 @@ export class MMPaySDK {
|
|
|
621
578
|
checkStatus();
|
|
622
579
|
this.pollIntervalId = window.setInterval(checkStatus, this.POLL_INTERVAL_MS);
|
|
623
580
|
}
|
|
581
|
+
|
|
582
|
+
private _startCountdown(orderId: string): void {
|
|
583
|
+
if (this.countdownIntervalId !== undefined) {
|
|
584
|
+
window.clearInterval(this.countdownIntervalId);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
let remaining = this.TIMEOUT_SECONDS;
|
|
588
|
+
const timerElement = document.getElementById('mmpay-countdown-text');
|
|
589
|
+
|
|
590
|
+
const updateDisplay = () => {
|
|
591
|
+
if (!timerElement) return;
|
|
592
|
+
const minutes = Math.floor(remaining / 60);
|
|
593
|
+
const seconds = remaining % 60;
|
|
594
|
+
timerElement.innerText = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
this.countdownIntervalId = window.setInterval(() => {
|
|
598
|
+
remaining--;
|
|
599
|
+
updateDisplay();
|
|
600
|
+
|
|
601
|
+
if (remaining <= 0) {
|
|
602
|
+
window.clearInterval(this.countdownIntervalId);
|
|
603
|
+
this.countdownIntervalId = undefined;
|
|
604
|
+
this._showTerminalMessage(orderId, 'EXPIRED', 'သတ်မှတ်ချိန်ကုန်သွားပါပြီ။');
|
|
605
|
+
}
|
|
606
|
+
}, 1000);
|
|
607
|
+
}
|
|
624
608
|
}
|
|
625
609
|
|
|
626
|
-
// Make the SDK class and its instance methods accessible globally
|
|
627
610
|
(window as any).MMPaySDK = MMPaySDK;
|
package/test/home.html
CHANGED
|
@@ -150,7 +150,7 @@
|
|
|
150
150
|
<!-- Client-Side Application Logic -->
|
|
151
151
|
<script>
|
|
152
152
|
// --- Configuration ---
|
|
153
|
-
const PUBLISHABLE_KEY = '
|
|
153
|
+
const PUBLISHABLE_KEY = 'pk_test_75cbca18e22481d4dec91865a23fca8984d893660c7eb3c151186adbbc0315db'; // <<< REMEMBER TO REPLACE THIS KEY!
|
|
154
154
|
const CONTAINER_ID = 'payment-container';
|
|
155
155
|
const RESULT_CONTAINER_ID = 'result-container';
|
|
156
156
|
const PAY_BUTTON_ID = 'pay-button';
|
|
@@ -235,7 +235,8 @@
|
|
|
235
235
|
await sdk.showPaymentModal({
|
|
236
236
|
amount: parseFloat(finalAmount.toFixed(2)),
|
|
237
237
|
orderId: 'FSTY' + Date.now(),
|
|
238
|
-
callbackUrl: 'https://your-fastify-backend.com/api/mmpay/webhook'
|
|
238
|
+
callbackUrl: 'https://your-fastify-backend.com/api/mmpay/webhook',
|
|
239
|
+
customMessage: "Myan Myan Pay Is Good"
|
|
239
240
|
}, (result) => {
|
|
240
241
|
|
|
241
242
|
});
|