@mmpay/browser 0.0.0-stage → 1.3.0
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/.vscode/settings.json +33 -0
- package/README.md +471 -2
- package/dist/cjs/index.js +1770 -0
- package/dist/esm/api.d.ts +26 -0
- package/dist/esm/deprecated/api.d.ts +12 -0
- package/dist/esm/deprecated/showPaymentModal.d.ts +6 -0
- package/dist/esm/functions/api.d.ts +12 -0
- package/dist/esm/functions/showPaymentModal.d.ts +2 -0
- package/dist/esm/i18n.d.ts +13 -0
- package/dist/esm/index.d.ts +65 -0
- package/dist/esm/index.js +1768 -0
- package/dist/esm/logo.d.ts +5 -0
- package/dist/esm/stream.d.ts +46 -0
- package/dist/esm/styles.d.ts +5 -0
- package/dist/esm/templates.d.ts +6 -0
- package/dist/esm/types.d.ts +101 -0
- package/dist/esm/ui.d.ts +85 -0
- package/dist/mmpay-sdk.js +1776 -0
- package/package.json +45 -4
- package/rollup.config.ts +33 -0
- package/src/api.ts +121 -0
- package/src/i18n.ts +112 -0
- package/src/index.ts +490 -0
- package/src/logo.ts +5 -0
- package/src/stream.ts +214 -0
- package/src/styles.ts +206 -0
- package/src/types.ts +117 -0
- package/src/ui.ts +715 -0
- package/test/index.html +476 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"editor.rulers": [
|
|
3
|
+
80
|
|
4
|
+
],
|
|
5
|
+
"editor.tabCompletion": "on",
|
|
6
|
+
"editor.tabSize": 2,
|
|
7
|
+
"editor.trimAutoWhitespace": true,
|
|
8
|
+
"editor.formatOnSave": true,
|
|
9
|
+
"editor.codeActionsOnSave": {
|
|
10
|
+
"source.organizeImports": "explicit",
|
|
11
|
+
"source.fixAll.eslint": "explicit"
|
|
12
|
+
},
|
|
13
|
+
"files.exclude": {
|
|
14
|
+
"**/.DS_Store": true,
|
|
15
|
+
"**/.git": true,
|
|
16
|
+
"**/.angular": true,
|
|
17
|
+
"**/.hg": true,
|
|
18
|
+
"**/.svn": true,
|
|
19
|
+
"**/CVS": true,
|
|
20
|
+
"**/node_modules": true,
|
|
21
|
+
"**/keys": true,
|
|
22
|
+
},
|
|
23
|
+
"files.insertFinalNewline": true,
|
|
24
|
+
"files.trimTrailingWhitespace": true,
|
|
25
|
+
"typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false,
|
|
26
|
+
"typescript.preferences.quoteStyle": "single",
|
|
27
|
+
"eslint.run": "onSave",
|
|
28
|
+
"eslint.nodePath": "./node_modules",
|
|
29
|
+
"eslint.validate": [
|
|
30
|
+
"javascript",
|
|
31
|
+
"typescript"
|
|
32
|
+
]
|
|
33
|
+
}
|
package/README.md
CHANGED
|
@@ -1,3 +1,472 @@
|
|
|
1
|
-
#
|
|
1
|
+
# MyanMyanPay Browser Plugin Or No-code SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Welcome to the **MyanMyanPay Browser Plugin No Code SDK**! This library provides a secure and seamless way to integrate MMQR right into your webpages without any redirects.
|
|
4
|
+
Developed using **TypeScript**, the SDK offers a clean, type-safe interface and handles complex tasks like API communication, UI rendering, and asynchronous payment status polling automatically.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## 1: 🛠️ Plugin or SDK Installation
|
|
10
|
+
The MyanMyanPay SDK is distributed as a single JavaScript file, ready for direct inclusion.
|
|
11
|
+
Embed the following `<script>` tag into the `<head>` or before the closing `</body>` tag of your checkout page.
|
|
12
|
+
|
|
13
|
+
**Implementation**
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<script src="https://cdn.jsdelivr.net/npm/mmpay-browser-sdk@latest/dist/mmpay-sdk.js"></script>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 2: 🚀 Initialize Your App
|
|
22
|
+
The `MMPaySDK` class provides two distinct methods to suit different integration needs.
|
|
23
|
+
|
|
24
|
+
**Implementation**
|
|
25
|
+
```javascript
|
|
26
|
+
const MMPayApp = new MMPaySDK('pk_live_YOUR_KEY', {
|
|
27
|
+
merchantName: 'Your Shop Name',
|
|
28
|
+
design: {
|
|
29
|
+
mode: 'dark', // dark | dark-translucent | light | light-translucent
|
|
30
|
+
color: '#DE3163' // #color code
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
**All options**
|
|
38
|
+
|
|
39
|
+
| Option | Default | Description |
|
|
40
|
+
| :--- | :--- | :--- |
|
|
41
|
+
| `merchantName` | `'MyanMyanPay'` | Name shown above the amount. |
|
|
42
|
+
| `language` | browser language | `'en'` or `'mm'`. Language the modal opens in. If the shopper switches language in the modal, their choice is remembered and wins on the next visit. |
|
|
43
|
+
| `transport` | `'auto'` | How payment status reaches the browser. `'auto'` uses a WebSocket and falls back to HTTP polling if a socket cannot be opened. `'polling'` never opens a socket. `'websocket'` keeps retrying the socket instead of falling back after connection drops. |
|
|
44
|
+
| `timeoutSeconds` | `900` | Seconds the shopper has to pay before the modal shows Expired. 15 minutes by default, which is also the maximum; minimum 60. |
|
|
45
|
+
| `pollInterval` | `5000` | Interval of the polling fallback in milliseconds (minimum 2000). |
|
|
46
|
+
| `design.mode` | `'light'` | `light`, `dark`, `light-translucent`, `dark-translucent`, or `auto` to follow the shopper's system theme. |
|
|
47
|
+
| `design.color` | none | Colour of the main button, as a hex code, a CSS colour name, or `rgb()` / `hsl()`. |
|
|
48
|
+
| `baseUrl` | MyanMyanPay API | API base URL. The WebSocket URL is derived from it (`https` becomes `wss`). |
|
|
49
|
+
|
|
50
|
+
**Changing the language from your page**
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
MMPayApp.setLanguage('mm'); // 'en' | 'mm', works while the modal is open
|
|
54
|
+
MMPayApp.getLanguage();
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Realtime status (1.3.0+)**
|
|
58
|
+
|
|
59
|
+
Payment status is pushed over a WebSocket, so the success screen appears about a second after the shopper pays. Nothing changes in how you call `pay()` or `showPaymentModal()`. When the shopper comes back from their banking app, the status is re-checked immediately, and a dropped connection reconnects on its own.
|
|
60
|
+
|
|
61
|
+
**One unfinished order at a time (1.3.0+)**
|
|
62
|
+
|
|
63
|
+
While the shopper has an order that is not paid, cancelled or expired, `showPaymentModal()` does not create another one. It shows the unfinished order again, also after a page reload or when called with a different `orderId`, and the `created` event carries the `orderId` of the order that is actually on screen. A new order is created once the previous one is finished or the shopper stops it.
|
|
64
|
+
|
|
65
|
+
A manual test page is in `test/index.html` (run `npm run build` first). It has a built-in mock API, so it works without a server.
|
|
66
|
+
|
|
67
|
+
If your site sends a Content-Security-Policy header, allow:
|
|
68
|
+
|
|
69
|
+
| Directive | Value |
|
|
70
|
+
| :--- | :--- |
|
|
71
|
+
| `connect-src` | `https://bbapi.myanmyanpay.com wss://bbapi.myanmyanpay.com` |
|
|
72
|
+
| `script-src` | `https://cdnjs.cloudflare.com https://cdn.jsdelivr.net` (QR renderer, loaded with Subresource Integrity) |
|
|
73
|
+
| `img-src` | `https://motephoe.com` |
|
|
74
|
+
| `style-src` / `font-src` | `https://fonts.googleapis.com` / `https://fonts.gstatic.com` (Burmese font) |
|
|
75
|
+
|
|
76
|
+
The modal renders inside a shadow root and no longer uses inline event handlers or global functions on `window`.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 3: 🚀 Making Payments
|
|
81
|
+
|
|
82
|
+
##### Approach 1 [Browser Site Order Creation] `showPaymentModal()`
|
|
83
|
+
|
|
84
|
+
This function is a simple way where an MMQR Reference No and QR to be created on the browser site, but you must verify the source of truth in our webhooks to avoid payload manipulation.
|
|
85
|
+
|
|
86
|
+
**Method Signature**
|
|
87
|
+
```typescript
|
|
88
|
+
showPaymentModal({orderId: string, amount: number}, onComplete: Function ): Promise<void>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Browser Plugin Implementation**
|
|
92
|
+
```javascript
|
|
93
|
+
const MMPayApp = new MMPaySDK('pk_live_YOUR_KEY', {
|
|
94
|
+
merchantName: 'Your Shop Name',
|
|
95
|
+
design: {
|
|
96
|
+
mode: 'dark', // dark | dark-translucent | light | light-translucent
|
|
97
|
+
color: '#DE3163' // #color code
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
MMPayApp.showPaymentModal({
|
|
102
|
+
orderId: 'Order-ID-111111',
|
|
103
|
+
amount: 2800
|
|
104
|
+
}, (result) => {
|
|
105
|
+
if (result.success) {
|
|
106
|
+
console.log('Success: ' + result.orderId + ' : Transaction : ' + result.transactionId);
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Verifying Source of Truth**
|
|
112
|
+
|
|
113
|
+
Do this at your backend to verify source of truth. If there are any payload manipulation that does not match your amount, the order can be 'CANCELLED' instanly via our api.
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
// Example of callback handling in the backend
|
|
117
|
+
import { MMPaySDK } from 'mmpay-node-sdk';
|
|
118
|
+
|
|
119
|
+
const MMPay = new MMPaySDK({
|
|
120
|
+
appId: "MMxxxxxxx",
|
|
121
|
+
publishableKey: "pk_live_abcxxxxx",
|
|
122
|
+
secretKey: "sk_live_abcxxxxx",
|
|
123
|
+
apiBaseUrl: "https://xxxxxx"
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
MMPay
|
|
127
|
+
.onTxCreate((tx) => {
|
|
128
|
+
const { amount } = await DB.getOrderId(tx.orderId) // get your source of truth from your database
|
|
129
|
+
if (tx.amount !== amount ) {
|
|
130
|
+
await MMPay.cancel(tx.orderId) // cancel order
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
.onTxSuccess((tx) => console.log('Success:', tx.orderId))
|
|
134
|
+
.onTxFail((tx) => console.log('Failed:', tx.orderId))
|
|
135
|
+
.onTxRefund((tx) => console.log('Refunded:', tx.orderId))
|
|
136
|
+
.onTxCancel((tx) => console.log('Cancelled:', tx.orderId))
|
|
137
|
+
.onTxExpire((tx) => console.log('Expired:', tx.orderId))
|
|
138
|
+
.onHeartbeat((tx) => console.log('Heartbeat:', tx.orderId))
|
|
139
|
+
.on('error', (err) => console.error(err));
|
|
140
|
+
|
|
141
|
+
// Listening Callback
|
|
142
|
+
app.post('/webhooks/mmpay-callback', async (req: Request, res: Response) => {
|
|
143
|
+
const payload = JSON.stringify(req.body);
|
|
144
|
+
const nonce = req.headers['x-mmpay-nonce'] as string;
|
|
145
|
+
const signature = req.headers['x-mmpay-signature'] as string;
|
|
146
|
+
await MMPaySandbox.listen(payload, nonce, signature);
|
|
147
|
+
res.json({ received: true }); // please respond with 200 status
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
##### Approach 2 [Backend Site Order Creation] `pay()`
|
|
153
|
+
|
|
154
|
+
This function is a simple way where an MMQR Reference No and QR to be created at backend with secret key securely, and putting the order ID in our plugin to make POP UP appear in your browser.
|
|
155
|
+
|
|
156
|
+
**Method Signature**
|
|
157
|
+
```typescript
|
|
158
|
+
pay(orderId: string, onComplete: Function ): Promise<void>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**Establishing a Source of Truth**
|
|
162
|
+
|
|
163
|
+
Do this at your backend server, it is important to create a source of truth in this manner.
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
npm install mmpay-node-sdk --save
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Backend Integration**
|
|
170
|
+
```typescript
|
|
171
|
+
import { MMPaySDK } from 'mmpay-node-sdk';
|
|
172
|
+
|
|
173
|
+
const MMPay = new MMPaySDK({
|
|
174
|
+
appId: "MMxxxxxxx",
|
|
175
|
+
publishableKey: "pk_live_abcxxxxx",
|
|
176
|
+
secretKey: "sk_live_abcxxxxx",
|
|
177
|
+
apiBaseUrl: "https://xxxxxx"
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
const { qr, orderId } = await MMPay.pay({ amount, orderId });
|
|
181
|
+
// get your order Id to your browser
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Browser Plugin Implementation**
|
|
185
|
+
```javascript
|
|
186
|
+
const MMPayApp = new MMPaySDK('pk_live_YOUR_KEY', {
|
|
187
|
+
merchantName: 'Your Shop Name',
|
|
188
|
+
design: {
|
|
189
|
+
mode: 'dark', // dark | dark-translucent | light | light-translucent
|
|
190
|
+
color: '#DE3163' // #color code
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
MMPayApp.pay('Order-ID-111111', (result) => {
|
|
195
|
+
if (result.success) {
|
|
196
|
+
console.log('Success: ' + result.orderId + ' : Transaction : ' + result.transactionId);
|
|
197
|
+
}
|
|
198
|
+
})
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
## 4: All Supported Events
|
|
205
|
+
|
|
206
|
+
**Browser Plugin Implementation Display All Event Types**
|
|
207
|
+
|
|
208
|
+
```javascript
|
|
209
|
+
MMPayApp.pay('Order-ID-111111', (result) => {
|
|
210
|
+
if (result.success) {
|
|
211
|
+
console.log('Success: ' + result.orderId + ' : Transaction : ' + result.transactionId);
|
|
212
|
+
}
|
|
213
|
+
if (result.created) {
|
|
214
|
+
console.log('Created: ' + result.orderId);
|
|
215
|
+
}
|
|
216
|
+
if (result.cancelled) {
|
|
217
|
+
console.log('Cancelled: ' + result.orderId);
|
|
218
|
+
}
|
|
219
|
+
if (result.expired) {
|
|
220
|
+
console.log('Expoired: ' + result.orderId);
|
|
221
|
+
}
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
MMPayApp.showPaymentModal({ orderId, amount }, (result) => {
|
|
225
|
+
if (result.success) {
|
|
226
|
+
console.log('Success: ' + result.orderId + ' : Transaction : ' + result.transactionId);
|
|
227
|
+
}
|
|
228
|
+
if (result.created) {
|
|
229
|
+
console.log('Created: ' + result.orderId);
|
|
230
|
+
}
|
|
231
|
+
if (result.cancelled) {
|
|
232
|
+
console.log('Cancelled: ' + result.orderId);
|
|
233
|
+
}
|
|
234
|
+
if (result.expired) {
|
|
235
|
+
console.log('Expoired: ' + result.orderId);
|
|
236
|
+
}
|
|
237
|
+
})
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## 5: Error Codes
|
|
243
|
+
|
|
244
|
+
| Code | Description |
|
|
245
|
+
| :--- | :--- |
|
|
246
|
+
| **`R000`** | Internal Server Error ( Talk to our support immediately fot this ) |
|
|
247
|
+
| **`R001`** | Wrong publishable Key |
|
|
248
|
+
| **`R002`** | Key Not Live Yet |
|
|
249
|
+
| **`R003`** | Origin Whitelist Not Allowed |
|
|
250
|
+
| **`R004`** | Origin Requires SSL |
|
|
251
|
+
| **`429`** | Ratelimit hit only 1000 request / minute allowed |
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## 6: Angular Framework Implementation
|
|
256
|
+
|
|
257
|
+
**Example Implementation**
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
import {Injectable} from '@angular/core';
|
|
261
|
+
|
|
262
|
+
interface ModalResponse {
|
|
263
|
+
success: boolean,
|
|
264
|
+
created: boolean,
|
|
265
|
+
cancelled: boolean,
|
|
266
|
+
expired: boolean,
|
|
267
|
+
orderId: string;
|
|
268
|
+
transactionRefId: string;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
@Injectable({
|
|
272
|
+
providedIn: 'root'
|
|
273
|
+
})
|
|
274
|
+
export class MMPayService {
|
|
275
|
+
mmpay: any;
|
|
276
|
+
constructor() {
|
|
277
|
+
const MMPaySDK = (window as any).MMPaySDK;
|
|
278
|
+
if (!MMPaySDK) {
|
|
279
|
+
console.error('SDK not loaded attached to window');
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
this.mmpay = new MMPaySDK('pk_test_123', {
|
|
283
|
+
baseUrl: 'https://xxx.myanmyanpay.com', // Sign up with us and ask our tea
|
|
284
|
+
merchantName: 'Test Shop',
|
|
285
|
+
design: {
|
|
286
|
+
mode: 'light-translucent', // dark | dark-translucent | light | light-translucent
|
|
287
|
+
color: '#9CA6EB' // #color code
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* @param {number} amount
|
|
293
|
+
* @param {string} orderId
|
|
294
|
+
* @param {string} callbackUrl
|
|
295
|
+
* @param {string} customMessage
|
|
296
|
+
*/
|
|
297
|
+
pay(orderId: string ) {
|
|
298
|
+
this.mmpay.pay(orderId, (result: ModalResponse) => {
|
|
299
|
+
if (result.success) {
|
|
300
|
+
console.log('Success: ' + result.orderId + ' : Transaction : ' + result.transactionId);
|
|
301
|
+
}
|
|
302
|
+
if (result.created) {
|
|
303
|
+
console.log('Created: ' + result.orderId);
|
|
304
|
+
}
|
|
305
|
+
if (result.cancelled) {
|
|
306
|
+
console.log('Cancelled: ' + result.orderId);
|
|
307
|
+
}
|
|
308
|
+
if (result.expired) {
|
|
309
|
+
console.log('Expoired: ' + result.orderId);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
## 7. React Framework Implementation
|
|
320
|
+
|
|
321
|
+
**Example Implementation**
|
|
322
|
+
|
|
323
|
+
```tsx
|
|
324
|
+
import React, { useEffect, useRef } from 'react';
|
|
325
|
+
|
|
326
|
+
interface ModalResponse {
|
|
327
|
+
success: boolean,
|
|
328
|
+
created: boolean,
|
|
329
|
+
cancelled: boolean,
|
|
330
|
+
expired: boolean,
|
|
331
|
+
orderId: string;
|
|
332
|
+
transactionRefId: string;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export const useMMPay = () => {
|
|
336
|
+
const mmpayRef = useRef(null);
|
|
337
|
+
|
|
338
|
+
useEffect(() => {
|
|
339
|
+
const MMPaySDK = window.MMPaySDK;
|
|
340
|
+
|
|
341
|
+
if (!MMPaySDK) {
|
|
342
|
+
console.error('SDK not loaded attached to window');
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
mmpayRef.current = new MMPaySDK('pk_test_123', {
|
|
347
|
+
baseUrl: 'https://xxx.myanmyanpay.com',
|
|
348
|
+
merchantName: 'Test Shop',
|
|
349
|
+
design: {
|
|
350
|
+
mode: 'dark-translucent', // dark | dark-translucent | light | light-translucent
|
|
351
|
+
color: '#E1A284' // #color code
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
}, []);
|
|
355
|
+
|
|
356
|
+
const pay = (orderId: string) => {
|
|
357
|
+
if (!mmpayRef.current) return;
|
|
358
|
+
|
|
359
|
+
mmpayRef.current.pay(orderId, (result: ModalResponse) => {
|
|
360
|
+
if (result.success) {
|
|
361
|
+
console.log('Success: ' + result.orderId + ' : Transaction : ' + result.transactionId);
|
|
362
|
+
// Redirect Somewhere
|
|
363
|
+
}
|
|
364
|
+
if (result.created) {
|
|
365
|
+
console.log('Created: ' + result.orderId);
|
|
366
|
+
}
|
|
367
|
+
if (result.cancelled) {
|
|
368
|
+
console.log('Cancelled: ' + result.orderId);
|
|
369
|
+
}
|
|
370
|
+
if (result.expired) {
|
|
371
|
+
console.log('Expoired: ' + result.orderId);
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
return { pay };
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
export const Checkout = () => {
|
|
380
|
+
const { pay } = useMMPay();
|
|
381
|
+
|
|
382
|
+
const handlePayment = () => {
|
|
383
|
+
pay(`ORD-${Date.now()}`);
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
return (
|
|
387
|
+
<button onClick={handlePayment}>
|
|
388
|
+
Pay with MyanMyanPay
|
|
389
|
+
</button>
|
|
390
|
+
);
|
|
391
|
+
};
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
## 8. Vue Framework Implementation
|
|
398
|
+
|
|
399
|
+
**Example Implementation**
|
|
400
|
+
|
|
401
|
+
```vue
|
|
402
|
+
|
|
403
|
+
<script setup>
|
|
404
|
+
import { onMounted, ref } from 'vue';
|
|
405
|
+
|
|
406
|
+
interface ModalResponse {
|
|
407
|
+
success: boolean,
|
|
408
|
+
created: boolean,
|
|
409
|
+
cancelled: boolean,
|
|
410
|
+
expired: boolean,
|
|
411
|
+
orderId: string;
|
|
412
|
+
transactionRefId: string;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
const mmpay = ref(null);
|
|
416
|
+
|
|
417
|
+
onMounted(() => {
|
|
418
|
+
const MMPaySDK = window.MMPaySDK;
|
|
419
|
+
|
|
420
|
+
if (!MMPaySDK) {
|
|
421
|
+
console.error('SDK not loaded attached to window');
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
mmpay.value = new MMPaySDK('pk_test_123', {
|
|
426
|
+
baseUrl: 'https://xxx.myanmyanpay.com',
|
|
427
|
+
merchantName: 'Test Shop',
|
|
428
|
+
design: {
|
|
429
|
+
mode: 'light', // dark | dark-translucent | light | light-translucent
|
|
430
|
+
color: '#BF40BF' // #color code
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
const pay = ( orderId: string ) => {
|
|
436
|
+
if (!mmpay.value) return;
|
|
437
|
+
|
|
438
|
+
mmpay.value.pay(orderId, (result: ModalResponse) => {
|
|
439
|
+
if (result.success) {
|
|
440
|
+
console.log('Success: ' + result.orderId + ' : Transaction : ' + result.transactionId);
|
|
441
|
+
// Redirect Somewhere
|
|
442
|
+
}
|
|
443
|
+
if (result.created) {
|
|
444
|
+
console.log('Created: ' + result.orderId);
|
|
445
|
+
}
|
|
446
|
+
if (result.cancelled) {
|
|
447
|
+
console.log('Cancelled: ' + result.orderId);
|
|
448
|
+
}
|
|
449
|
+
if (result.expired) {
|
|
450
|
+
console.log('Expoired: ' + result.orderId);
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
const handlePayment = () => {
|
|
456
|
+
pay(`ORD-${Date.now()}`);
|
|
457
|
+
};
|
|
458
|
+
</script>
|
|
459
|
+
|
|
460
|
+
<template>
|
|
461
|
+
<button @click="handlePayment">
|
|
462
|
+
Pay with MyanMyanPay
|
|
463
|
+
</button>
|
|
464
|
+
</template>
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
## License
|
|
471
|
+
|
|
472
|
+
MIT
|