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/dist/mmpay-sdk.js CHANGED
@@ -5,18 +5,15 @@
5
5
  })(this, (function (exports) { 'use strict';
6
6
 
7
7
  class MMPaySDK {
8
- /**
9
- * constructor
10
- * @param publishableKey
11
- * @param options
12
- */
13
8
  constructor(publishableKey, options = {}) {
14
9
  this.pollIntervalId = undefined;
10
+ this.countdownIntervalId = undefined;
15
11
  this.onCompleteCallback = null;
16
12
  this.overlayElement = null;
17
13
  this.pendingApiResponse = null;
18
14
  this.pendingPaymentPayload = null;
19
15
  this.QR_SIZE = 290;
16
+ this.TIMEOUT_SECONDS = 300;
20
17
  if (!publishableKey) {
21
18
  throw new Error("A Publishable Key is required to initialize [MMPaySDK].");
22
19
  }
@@ -26,12 +23,6 @@
26
23
  this.merchantName = options.merchantName || 'Your Merchant';
27
24
  this.POLL_INTERVAL_MS = options.pollInterval || 5000;
28
25
  }
29
- /**
30
- * _callApi
31
- * @param endpoint
32
- * @param data
33
- * @returns
34
- */
35
26
  async _callApi(endpoint, data = {}) {
36
27
  let config = {
37
28
  'Content-Type': 'application/json',
@@ -55,16 +46,6 @@
55
46
  }
56
47
  return response.json();
57
48
  }
58
- /**
59
- * _callApiTokenRequest
60
- * @param {ICreateTokenRequestParams} payload
61
- * @param {number} payload.amount
62
- * @param {string} payload.currency
63
- * @param {string} payload.orderId
64
- * @param {string} payload.nonce
65
- * @param {string} payload.callbackUrl
66
- * @returns {Promise<ICreateTokenResponse>}
67
- */
68
49
  async _callApiTokenRequest(payload) {
69
50
  try {
70
51
  const endpoint = this.environment === 'sandbox'
@@ -77,16 +58,6 @@
77
58
  throw error;
78
59
  }
79
60
  }
80
- /**
81
- * _callApiPaymentRequest
82
- * @param {ICreatePaymentRequestParams} payload
83
- * @param {number} payload.amount
84
- * @param {string} payload.currency
85
- * @param {string} payload.orderId
86
- * @param {string} payload.nonce
87
- * @param {string} payload.callbackUrl
88
- * @returns {Promise<ICreatePaymentResponse>}
89
- */
90
61
  async _callApiPaymentRequest(payload) {
91
62
  try {
92
63
  const endpoint = this.environment === 'sandbox'
@@ -99,61 +70,55 @@
99
70
  throw error;
100
71
  }
101
72
  }
102
- /**
103
- * createPayment
104
- * @param {ICorePayParams} params
105
- * @param {number} params.amount
106
- * @param {string} params.orderId
107
- * @param {string} params.callbackUrl
108
- * @returns {Promise<ICreatePaymentResponse>}
109
- */
110
73
  async createPayment(params) {
111
- const payload = {
74
+ const tokenPayload = {
75
+ amount: params.amount,
76
+ orderId: params.orderId,
77
+ nonce: new Date().getTime().toString() + '_mmp'
78
+ };
79
+ const paymentPayload = {
112
80
  amount: params.amount,
113
81
  orderId: params.orderId,
114
82
  callbackUrl: params.callbackUrl,
115
- currency: 'MMK',
83
+ customMessage: params.customMessage,
116
84
  nonce: new Date().getTime().toString() + '_mmp'
117
85
  };
118
86
  try {
119
- const tokenResponse = await this._callApiTokenRequest(payload);
87
+ const tokenResponse = await this._callApiTokenRequest(tokenPayload);
120
88
  this.tokenKey = tokenResponse.token;
121
- const apiResponse = await this._callApiPaymentRequest(payload);
122
- return apiResponse;
89
+ return await this._callApiPaymentRequest(paymentPayload);
123
90
  }
124
91
  catch (error) {
125
92
  console.error("Payment request failed:", error);
126
93
  throw error;
127
94
  }
128
95
  }
129
- /**
130
- * showPaymentModal
131
- * @param {ICorePayParams} params
132
- * @param {number} params.amount
133
- * @param {string} params.orderId
134
- * @param {string} params.callbackUrl
135
- * @param {Function} onComplete
136
- */
137
96
  async showPaymentModal(params, onComplete) {
138
97
  const initialContent = `<div class="mmpay-overlay-content"><div style="text-align: center; color: #fff;">ငွေပေးချေမှု စတင်နေသည်...</div></div>`;
139
98
  this._createAndRenderModal(initialContent, false);
140
99
  this.onCompleteCallback = onComplete;
141
- const payload = {
100
+ const tokenPayload = {
101
+ amount: params.amount,
102
+ orderId: params.orderId,
103
+ nonce: new Date().getTime().toString() + '_mmp'
104
+ };
105
+ const paymentPayload = {
142
106
  amount: params.amount,
143
107
  orderId: params.orderId,
144
108
  callbackUrl: params.callbackUrl,
145
- currency: 'MMK',
109
+ customMessage: params.customMessage,
146
110
  nonce: new Date().getTime().toString() + '_mmp'
147
111
  };
148
112
  try {
149
- const tokenResponse = await this._callApiTokenRequest(payload);
113
+ const tokenResponse = await this._callApiTokenRequest(tokenPayload);
150
114
  this.tokenKey = tokenResponse.token;
151
- const apiResponse = await this._callApiPaymentRequest(payload);
115
+ const apiResponse = await this._callApiPaymentRequest(paymentPayload);
152
116
  if (apiResponse && apiResponse.qr && apiResponse.transactionRefId) {
153
117
  this.pendingApiResponse = apiResponse;
154
- this.pendingPaymentPayload = payload;
155
- this._renderQrModalContent(apiResponse, payload, this.merchantName);
156
- this._startPolling(payload, onComplete);
118
+ this.pendingPaymentPayload = paymentPayload;
119
+ this._renderQrModalContent(apiResponse, paymentPayload, this.merchantName);
120
+ this._startPolling(paymentPayload, onComplete);
121
+ this._startCountdown(paymentPayload.orderId);
157
122
  }
158
123
  else {
159
124
  this._showTerminalMessage(apiResponse.orderId || 'N/A', 'FAILED', 'ငွေပေးချေမှု စတင်ရန် မအောင်မြင်ပါ။ QR ဒေတာ မရရှိပါ။');
@@ -161,15 +126,9 @@
161
126
  }
162
127
  catch (error) {
163
128
  this.tokenKey = null;
164
- this._showTerminalMessage(payload.orderId || 'N/A', 'FAILED', 'ငွေပေးချေမှု စတင်စဉ် အမှားအယွင်း ဖြစ်ပွားသည်။ ကွန်ဆိုးလ်တွင် ကြည့်ပါ။');
129
+ this._showTerminalMessage(paymentPayload.orderId || 'N/A', 'FAILED', 'ငွေပေးချေမှု စတင်စဉ် အမှားအယွင်း ဖြစ်ပွားသည်။ ကွန်ဆိုးလ်တွင် ကြည့်ပါ။');
165
130
  }
166
131
  }
167
- /**
168
- * _createAndRenderModal
169
- * @param {string} contentHtml
170
- * @param {boolean} isTerminal
171
- * @returns
172
- */
173
132
  _createAndRenderModal(contentHtml, isTerminal = false) {
174
133
  this._cleanupModal(false);
175
134
  const overlay = document.createElement('div');
@@ -203,7 +162,6 @@
203
162
  width: 100%;
204
163
  padding: 20px 0;
205
164
  }
206
- /* Card Base Styles */
207
165
  .mmpay-card {
208
166
  background: #ffffff;
209
167
  border-radius: 16px;
@@ -275,15 +233,9 @@
275
233
  };
276
234
  window.MMPayReRenderModal = () => this._reRenderPendingModalInstance();
277
235
  overlay.innerHTML += `<div class="mmpay-overlay-content">${contentHtml}</div>`;
278
- document.body.style.overflow = 'hidden'; // FIX: Prevent body scroll when modal is open
236
+ document.body.style.overflow = 'hidden';
279
237
  return overlay;
280
238
  }
281
- /**
282
- * _renderQrModalContent
283
- * @param {ICreatePaymentResponse} apiResponse
284
- * @param {CreatePaymentRequest} payload
285
- * @param {string} merchantName
286
- */
287
239
  _renderQrModalContent(apiResponse, payload, merchantName) {
288
240
  const qrData = apiResponse.qr;
289
241
  const amountDisplay = `${apiResponse.amount.toFixed(2)} MMK`;
@@ -310,7 +262,7 @@
310
262
  <style>
311
263
  .mmpay-card { max-width: 350px; padding: 16px; }
312
264
  .mmpay-header { color: #1f2937; font-size: 1rem; font-weight: bold; margin-bottom: 8px; }
313
- .mmpay-qr-container { padding: 0; margin: 10px auto; display: inline-block; line-height: 0; width: 300px; height: 300px; }
265
+ .mmpay-qr-container { padding: 0; margin: 5px auto 10px auto; display: inline-block; line-height: 0; width: 300px; height: 300px; }
314
266
  #${qrCanvasId} { display: block; background: white; border-radius: 8px; width: 100%; height: 100%; }
315
267
  .mmpay-amount { font-size: 1.2rem; font-weight: 800; color: #1f2937; margin: 0; }
316
268
  .mmpay-separator { border-top: 1px solid #f3f4f6; margin: 12px 0; }
@@ -319,10 +271,28 @@
319
271
  .mmpay-detail span { text-align: left; }
320
272
  .mmpay-secure-text { color: #757575; border-radius: 9999px; font-size: 0.8rem; font-weight: 600; display: inline-flex; align-items: center; justify-content: center; }
321
273
  .mmpay-warning { font-size: 0.75rem; color: #9ca3af; font-weight: 500; margin-top: 12px; line-height: 1.5; }
274
+
275
+ .mmpay-timer-badge {
276
+ background-color: #fef2f2;
277
+ color: #b91c1c;
278
+ padding: 4px 10px;
279
+ border-radius: 12px;
280
+ font-weight: 700;
281
+ font-size: 0.85rem;
282
+ display: inline-flex;
283
+ align-items: center;
284
+ gap: 5px;
285
+ margin: 8px 0;
286
+ border: 1px solid #fee2e2;
287
+ }
288
+ .mmpay-timer-icon {
289
+ width: 14px;
290
+ height: 14px;
291
+ fill: currentColor;
292
+ }
322
293
  </style>
323
294
 
324
295
  <div class="mmpay-card">
325
- <!-- Close Button - Triggers Confirmation Modal -->
326
296
  <button class="mmpay-close-btn" onclick="MMPayCloseModal(false)">
327
297
  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 16 16">
328
298
  <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"/>
@@ -337,6 +307,14 @@
337
307
  ${merchantName} သို့ပေးချေပါ
338
308
  </div>
339
309
 
310
+ <div class="mmpay-timer-badge" id="mmpay-timer-badge">
311
+ <svg class="mmpay-timer-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
312
+ <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"/>
313
+ <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"/>
314
+ </svg>
315
+ <span id="mmpay-countdown-text">05:00</span>
316
+ </div>
317
+
340
318
  <div class="mmpay-amount">${amountDisplay}</div>
341
319
 
342
320
  <div class="mmpay-qr-container">
@@ -369,17 +347,11 @@
369
347
  this._createAndRenderModal(qrContentHtml, false);
370
348
  this._injectQrScript(qrData, qrCanvasId);
371
349
  }
372
- /**
373
- * _showTerminalMessage
374
- * @param {string} orderId
375
- * @param {string} status
376
- * @param {string} message
377
- */
378
350
  _showTerminalMessage(orderId, status, message) {
379
351
  this._cleanupModal(true);
380
- const successColor = '#10b981'; // Tailwind Green 500
381
- const failureColor = '#ef4444'; // Tailwind Red 500
382
- const expiredColor = '#f59e0b'; // Tailwind Amber 500
352
+ const successColor = '#10b981';
353
+ const failureColor = '#ef4444';
354
+ const expiredColor = '#f59e0b';
383
355
  let color;
384
356
  let iconSvg;
385
357
  let statusText;
@@ -391,7 +363,6 @@
391
363
  </svg>`;
392
364
  }
393
365
  else {
394
- // Shared icon for FAILED and EXPIRED (X mark)
395
366
  color = status === 'FAILED' ? failureColor : expiredColor;
396
367
  statusText = status === 'FAILED' ? 'မအောင်မြင်' : 'သက်တမ်းကုန်';
397
368
  iconSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="${color}" viewBox="0 0 16 16">
@@ -415,16 +386,17 @@
415
386
  </button>
416
387
  </div>
417
388
  `;
418
- this._createAndRenderModal(content, true); // Set isTerminal=true so the close button always forces cleanup
389
+ this._createAndRenderModal(content, true);
419
390
  }
420
- /**
421
- * _showCancelConfirmationModal
422
- */
423
391
  _showCancelConfirmationModal() {
424
392
  if (this.pollIntervalId !== undefined) {
425
393
  window.clearInterval(this.pollIntervalId);
426
394
  this.pollIntervalId = undefined;
427
395
  }
396
+ if (this.countdownIntervalId !== undefined) {
397
+ window.clearInterval(this.countdownIntervalId);
398
+ this.countdownIntervalId = undefined;
399
+ }
428
400
  this._cleanupModal(false);
429
401
  const content = `
430
402
  <div class="mmpay-card mmpay-terminal-card" style="
@@ -446,11 +418,8 @@
446
418
  </div>
447
419
  </div>
448
420
  `;
449
- this._createAndRenderModal(content, false); // Set isTerminal=false so the close button calls MMPayCloseModal(true)
421
+ this._createAndRenderModal(content, false);
450
422
  }
451
- /**
452
- * _reRenderPendingModalInstance
453
- */
454
423
  _reRenderPendingModalInstance() {
455
424
  if (this.pendingApiResponse && this.pendingPaymentPayload && this.onCompleteCallback) {
456
425
  this._cleanupModal(true);
@@ -460,15 +429,15 @@
460
429
  this._cleanupModal(true);
461
430
  }
462
431
  }
463
- /**
464
- * Cleans up the modal and stops polling.
465
- * @param {boolean} restoreBodyScroll
466
- */
467
432
  _cleanupModal(restoreBodyScroll) {
468
433
  if (this.pollIntervalId !== undefined) {
469
434
  window.clearInterval(this.pollIntervalId);
470
435
  this.pollIntervalId = undefined;
471
436
  }
437
+ if (this.countdownIntervalId !== undefined) {
438
+ window.clearInterval(this.countdownIntervalId);
439
+ this.countdownIntervalId = undefined;
440
+ }
472
441
  if (this.overlayElement && this.overlayElement.parentNode) {
473
442
  this.overlayElement.parentNode.removeChild(this.overlayElement);
474
443
  this.overlayElement = null;
@@ -479,11 +448,6 @@
479
448
  delete window.MMPayCloseModal;
480
449
  delete window.MMPayReRenderModal;
481
450
  }
482
- /**
483
- * _injectQrScript
484
- * @param {string} qrData
485
- * @param {string} qrCanvasId
486
- */
487
451
  _injectQrScript(qrData, qrCanvasId) {
488
452
  const script = document.createElement('script');
489
453
  script.src = "https://cdn.jsdelivr.net/npm/qrious@4.0.2/dist/qrious.min.js";
@@ -506,16 +470,6 @@
506
470
  };
507
471
  document.head.appendChild(script);
508
472
  }
509
- /**
510
- * _startPolling
511
- * @param {IPollingRequest} payload
512
- * @param {number} payload.amount
513
- * @param {string} payload.currency
514
- * @param {string} payload.orderId
515
- * @param {string} payload.nonce
516
- * @param {string} payload.callbackUrl
517
- * @param {Function} onComplete
518
- */
519
473
  async _startPolling(payload, onComplete) {
520
474
  if (this.pollIntervalId !== undefined) {
521
475
  window.clearInterval(this.pollIntervalId);
@@ -549,8 +503,30 @@
549
503
  checkStatus();
550
504
  this.pollIntervalId = window.setInterval(checkStatus, this.POLL_INTERVAL_MS);
551
505
  }
506
+ _startCountdown(orderId) {
507
+ if (this.countdownIntervalId !== undefined) {
508
+ window.clearInterval(this.countdownIntervalId);
509
+ }
510
+ let remaining = this.TIMEOUT_SECONDS;
511
+ const timerElement = document.getElementById('mmpay-countdown-text');
512
+ const updateDisplay = () => {
513
+ if (!timerElement)
514
+ return;
515
+ const minutes = Math.floor(remaining / 60);
516
+ const seconds = remaining % 60;
517
+ timerElement.innerText = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
518
+ };
519
+ this.countdownIntervalId = window.setInterval(() => {
520
+ remaining--;
521
+ updateDisplay();
522
+ if (remaining <= 0) {
523
+ window.clearInterval(this.countdownIntervalId);
524
+ this.countdownIntervalId = undefined;
525
+ this._showTerminalMessage(orderId, 'EXPIRED', 'သတ်မှတ်ချိန်ကုန်သွားပါပြီ။');
526
+ }
527
+ }, 1000);
528
+ }
552
529
  }
553
- // Make the SDK class and its instance methods accessible globally
554
530
  window.MMPaySDK = MMPaySDK;
555
531
 
556
532
  exports.MMPaySDK = MMPaySDK;
@@ -1 +1 @@
1
- {"version":3,"file":"mmpay-sdk.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"mmpay-sdk.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mmpay-browser-sdk",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "JavaScript SDK for integrating the MMQR Merchant and Redirect payment gateway",
5
5
  "keywords": [
6
6
  "MMQR",