@mmpay/aya-mmqr 0.0.0-stage → 1.0.13
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 +251 -2
- package/bun.lock +23 -0
- package/dist/cjs/index.d.ts +78 -0
- package/dist/cjs/index.js +331 -0
- package/dist/cjs/types/index.d.ts +154 -0
- package/dist/cjs/types/index.js +2 -0
- package/dist/esm/index.d.ts +78 -0
- package/dist/esm/index.js +325 -0
- package/dist/esm/types/index.d.ts +154 -0
- package/dist/esm/types/index.js +1 -0
- package/package.json +53 -4
- package/src/index.ts +360 -0
- package/src/types/index.ts +156 -0
- package/test/decrypttest.js +33 -0
- package/test/test.js +65 -0
- package/tsconfig.cjs.json +8 -0
- package/tsconfig.json +19 -0
package/package.json
CHANGED
|
@@ -1,6 +1,55 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mmpay/aya-mmqr",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.13",
|
|
4
|
+
"description": "MMQR, AYA Pay - Integration Package By MyanMyanPay",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"MMQR",
|
|
7
|
+
"AYA Pay"
|
|
8
|
+
],
|
|
9
|
+
"main": "./dist/cjs/index.js",
|
|
10
|
+
"module": "./dist/esm/index.js",
|
|
11
|
+
"types": "./dist/esm/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": {
|
|
15
|
+
"types": "./dist/esm/index.d.ts",
|
|
16
|
+
"default": "./dist/esm/index.js"
|
|
17
|
+
},
|
|
18
|
+
"require": {
|
|
19
|
+
"types": "./dist/cjs/index.d.ts",
|
|
20
|
+
"default": "./dist/cjs/index.js"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/nawing/AYA-Pay-Merchant-API.git"
|
|
27
|
+
},
|
|
28
|
+
"bugs": {
|
|
29
|
+
"url": "https://github.com/nawing/AYA-Pay-Merchant-API/issues"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/nawing/AYA-Pay-Merchant-API#readme",
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": "^26.6.5",
|
|
34
|
+
"bun": ">=1.4.3"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"clean": "rm -rf dist",
|
|
38
|
+
"build:esm": "tsc -p tsconfig.json",
|
|
39
|
+
"build:cjs": "tsc -p tsconfig.cjs.json",
|
|
40
|
+
"build": "npm run clean && npm run build:esm && npm run build:cjs",
|
|
41
|
+
"test": "node --test test/test.js",
|
|
42
|
+
"test:bun": "bun test test/test.js",
|
|
43
|
+
"prepublishOnly": "npm run build"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"dotenv": "^17.2.2",
|
|
47
|
+
"typescript": "^5.4.0",
|
|
48
|
+
"@types/node": "^26.0.0"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
53
|
+
"author": "Naw Ing",
|
|
54
|
+
"license": "ISC"
|
|
55
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import {Buffer} from 'node:buffer';
|
|
2
|
+
import crypto from 'node:crypto';
|
|
3
|
+
|
|
4
|
+
import {CallbackDecoded, CallbackEncoded, getTokenResponse, loginResponse, PaymentCreateRequest, PaymentCreateResponse, PaymentStatusRequest, PaymentStatusResponse} from './types';
|
|
5
|
+
|
|
6
|
+
export {
|
|
7
|
+
CallbackDecoded, CallbackEncoded, getTokenResponse, loginResponse, PaymentCreateRequest, PaymentCreateResponse, PaymentStatusRequest, PaymentStatusResponse
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @InstanceOptions
|
|
12
|
+
*/
|
|
13
|
+
export interface InstanceOptions {
|
|
14
|
+
baseUrl: string;
|
|
15
|
+
prefixUrl: string;
|
|
16
|
+
consumerKey: string;
|
|
17
|
+
consumerSecret: string;
|
|
18
|
+
decryptionKey: string;
|
|
19
|
+
phone: string;
|
|
20
|
+
password: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @AYAPayMerchantApi
|
|
25
|
+
* @param {InstanceOptions} options
|
|
26
|
+
* @returns {AYAPayMerchantClass} A status message string.
|
|
27
|
+
*/
|
|
28
|
+
export function AYAPayMerchantApi(options: InstanceOptions): AYAPayMerchantClass {
|
|
29
|
+
return new AYAPayMerchantClass({
|
|
30
|
+
baseUrl: options.baseUrl,
|
|
31
|
+
prefixUrl: options.prefixUrl,
|
|
32
|
+
consumerKey: options.consumerKey,
|
|
33
|
+
consumerSecret: options.consumerSecret,
|
|
34
|
+
decryptionKey: options.decryptionKey,
|
|
35
|
+
phone: options.phone,
|
|
36
|
+
password: options.password,
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @AYAPayMerchantClass
|
|
42
|
+
*/
|
|
43
|
+
class AYAPayMerchantClass {
|
|
44
|
+
|
|
45
|
+
readonly #baseUrl: string;
|
|
46
|
+
readonly #prefixUrl: string;
|
|
47
|
+
readonly #consumerKey: string;
|
|
48
|
+
readonly #consumerSecret: string;
|
|
49
|
+
readonly #decryptionKey: string;
|
|
50
|
+
readonly #phone: string;
|
|
51
|
+
readonly #password: string;
|
|
52
|
+
|
|
53
|
+
#keyToken: string = '';
|
|
54
|
+
#apiToken: string = '';
|
|
55
|
+
|
|
56
|
+
constructor(options: InstanceOptions) {
|
|
57
|
+
this.#baseUrl = options.baseUrl;
|
|
58
|
+
this.#prefixUrl = options.prefixUrl;
|
|
59
|
+
this.#consumerKey = options.consumerKey;
|
|
60
|
+
this.#consumerSecret = options.consumerSecret;
|
|
61
|
+
this.#decryptionKey = options.decryptionKey;
|
|
62
|
+
this.#phone = options.phone;
|
|
63
|
+
this.#password = options.password;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* basicToken
|
|
68
|
+
* @returns
|
|
69
|
+
*/
|
|
70
|
+
private basicToken(): string {
|
|
71
|
+
const rawString = `${this.#consumerKey}:${this.#consumerSecret}`;
|
|
72
|
+
const buffer: Buffer = Buffer.from(rawString);
|
|
73
|
+
const base64String: string = buffer.toString('base64');
|
|
74
|
+
return base64String;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* getToken
|
|
79
|
+
* @returns {Promise<getTokenResponse>}
|
|
80
|
+
*/
|
|
81
|
+
private async getToken(): Promise<getTokenResponse> {
|
|
82
|
+
try {
|
|
83
|
+
const config = {
|
|
84
|
+
headers: {
|
|
85
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
86
|
+
'Authorization': `Basic ${this.basicToken()}`
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const body = {
|
|
90
|
+
grant_type: 'client_credentials'
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const formBody = new URLSearchParams();
|
|
94
|
+
Object.entries(body).forEach(([key, value]) => {
|
|
95
|
+
if (value !== undefined) formBody.append(key, String(value));
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const response = await fetch(`${this.#baseUrl}/token`, {
|
|
99
|
+
method: 'POST',
|
|
100
|
+
headers: config.headers,
|
|
101
|
+
body: formBody
|
|
102
|
+
});
|
|
103
|
+
const originResponse = (await response.json()) as {
|
|
104
|
+
access_token: string;
|
|
105
|
+
scope: string;
|
|
106
|
+
token_type: string;
|
|
107
|
+
expires_in: number;
|
|
108
|
+
}
|
|
109
|
+
const modifiedResponse: getTokenResponse = {
|
|
110
|
+
accessToken: originResponse.access_token,
|
|
111
|
+
scope: originResponse.scope,
|
|
112
|
+
tokenType: originResponse.token_type,
|
|
113
|
+
expiresIn: originResponse.expires_in,
|
|
114
|
+
}
|
|
115
|
+
this.#keyToken = modifiedResponse.accessToken;
|
|
116
|
+
return modifiedResponse;
|
|
117
|
+
} catch (error) {
|
|
118
|
+
console.error(error);
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* login
|
|
125
|
+
* @returns {Promise<loginResponse>}
|
|
126
|
+
*/
|
|
127
|
+
private async login(): Promise<loginResponse> {
|
|
128
|
+
try {
|
|
129
|
+
const config = {
|
|
130
|
+
headers: {
|
|
131
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
132
|
+
'Token': `Bearer ${this.#keyToken}`
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const body = {
|
|
136
|
+
phone: this.#phone,
|
|
137
|
+
password: this.#password,
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const formBody = new URLSearchParams();
|
|
141
|
+
Object.entries(body).forEach(([key, value]) => {
|
|
142
|
+
if (value !== undefined) formBody.append(key, String(value));
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const response = await fetch(`${this.#baseUrl}/${this.#prefixUrl}/1.0.0/thirdparty/merchant/login`, {
|
|
146
|
+
method: 'POST',
|
|
147
|
+
headers: config.headers,
|
|
148
|
+
body: formBody
|
|
149
|
+
});
|
|
150
|
+
const loginResponse = (await response.json()) as loginResponse;
|
|
151
|
+
this.#apiToken = loginResponse.token.token;
|
|
152
|
+
return loginResponse;
|
|
153
|
+
} catch (error) {
|
|
154
|
+
console.error(error);
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* authenticate
|
|
161
|
+
*/
|
|
162
|
+
public async authenticate(): Promise<void> {
|
|
163
|
+
await this.getToken()
|
|
164
|
+
await this.login()
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* requestQR
|
|
169
|
+
* @param {PaymentCreateRequest} options
|
|
170
|
+
* ...
|
|
171
|
+
* @returns {Promise<PaymentCreateResponse>}
|
|
172
|
+
*/
|
|
173
|
+
public async requestQR(options: PaymentCreateRequest): Promise<PaymentCreateResponse> {
|
|
174
|
+
try {
|
|
175
|
+
await this.authenticate();
|
|
176
|
+
const config = {
|
|
177
|
+
headers: {
|
|
178
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
179
|
+
'Token': `Bearer ${this.#keyToken}`,
|
|
180
|
+
'Authorization': `Bearer ${this.#apiToken}`,
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
const body = {
|
|
184
|
+
amount: options.amount,
|
|
185
|
+
currency: options.currency,
|
|
186
|
+
externalTransactionId: options.externalTransactionId,
|
|
187
|
+
externalAdditionalData: options.externalAdditionalData,
|
|
188
|
+
serviceCode: options.serviceCode,
|
|
189
|
+
MMQR: options.MMQR,
|
|
190
|
+
timelimit: options.timelimit,
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const formBody = new URLSearchParams();
|
|
194
|
+
Object.entries(body).forEach(([key, value]) => {
|
|
195
|
+
if (value !== undefined) formBody.append(key, String(value));
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const response = await fetch(`${this.#baseUrl}/${this.#prefixUrl}/1.0.0/thirdparty/merchant/v2/requestQRPayment`, {
|
|
199
|
+
method: 'POST',
|
|
200
|
+
headers: config.headers,
|
|
201
|
+
body: formBody
|
|
202
|
+
});
|
|
203
|
+
return (await response.json()) as PaymentCreateResponse;
|
|
204
|
+
} catch (error) {
|
|
205
|
+
console.error(error);
|
|
206
|
+
throw error;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* paymentStatusQR
|
|
212
|
+
* ...
|
|
213
|
+
*/
|
|
214
|
+
public async paymentStatusQR(options: PaymentStatusRequest): Promise<PaymentStatusResponse> {
|
|
215
|
+
try {
|
|
216
|
+
await this.authenticate();
|
|
217
|
+
const config = {
|
|
218
|
+
headers: {
|
|
219
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
220
|
+
'Token': `Bearer ${this.#keyToken}`,
|
|
221
|
+
'Authorization': `Bearer ${this.#apiToken}`,
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
const body = {
|
|
225
|
+
externalTransactionId: options.externalTransactionId,
|
|
226
|
+
referenceNumber: options.referenceNumber,
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const formBody = new URLSearchParams();
|
|
230
|
+
Object.entries(body).forEach(([key, value]) => {
|
|
231
|
+
if (value !== undefined) formBody.append(key, String(value));
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
const response = await fetch(`${this.#baseUrl}/${this.#prefixUrl}/1.0.0/thirdparty/merchant/checkQRPayment`, {
|
|
235
|
+
method: 'POST',
|
|
236
|
+
headers: config.headers,
|
|
237
|
+
body: formBody
|
|
238
|
+
});
|
|
239
|
+
return (await response.json()) as PaymentStatusResponse;
|
|
240
|
+
} catch (error) {
|
|
241
|
+
console.error(error);
|
|
242
|
+
throw error;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* requestPush
|
|
248
|
+
* ...
|
|
249
|
+
*/
|
|
250
|
+
public async requestPush(options: PaymentCreateRequest): Promise<PaymentCreateResponse> {
|
|
251
|
+
try {
|
|
252
|
+
await this.authenticate();
|
|
253
|
+
const config = {
|
|
254
|
+
headers: {
|
|
255
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
256
|
+
'Token': `Bearer ${this.#keyToken}`,
|
|
257
|
+
'Authorization': `Bearer ${this.#apiToken}`,
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
const body = {
|
|
261
|
+
amount: options.amount,
|
|
262
|
+
currency: options.currency,
|
|
263
|
+
externalTransactionId: options.externalTransactionId,
|
|
264
|
+
externalAdditionalData: options.externalAdditionalData,
|
|
265
|
+
serviceCode: options.serviceCode,
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const formBody = new URLSearchParams();
|
|
269
|
+
Object.entries(body).forEach(([key, value]) => {
|
|
270
|
+
if (value !== undefined) formBody.append(key, String(value));
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
const response = await fetch(`${this.#baseUrl}/${this.#prefixUrl}/1.0.0/thirdparty/merchant/v2/requestPushPayment`, {
|
|
274
|
+
method: 'POST',
|
|
275
|
+
headers: config.headers,
|
|
276
|
+
body: formBody
|
|
277
|
+
});
|
|
278
|
+
return (await response.json()) as PaymentCreateResponse;
|
|
279
|
+
} catch (error) {
|
|
280
|
+
console.error(error);
|
|
281
|
+
throw error;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* paymentStatusPush
|
|
287
|
+
* ...
|
|
288
|
+
*/
|
|
289
|
+
public async paymentStatusPush(options: PaymentStatusRequest): Promise<PaymentStatusResponse> {
|
|
290
|
+
try {
|
|
291
|
+
await this.authenticate();
|
|
292
|
+
const config = {
|
|
293
|
+
headers: {
|
|
294
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
295
|
+
'Token': `Bearer ${this.#keyToken}`,
|
|
296
|
+
'Authorization': `Bearer ${this.#apiToken}`,
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
const body = {
|
|
300
|
+
externalTransactionId: options.externalTransactionId,
|
|
301
|
+
referenceNumber: options.referenceNumber,
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const formBody = new URLSearchParams();
|
|
305
|
+
Object.entries(body).forEach(([key, value]) => {
|
|
306
|
+
if (value !== undefined) formBody.append(key, String(value));
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
const response = await fetch(`${this.#baseUrl}/${this.#prefixUrl}/1.0.0/thirdparty/merchant/checkRequestPayment`, {
|
|
310
|
+
method: 'POST',
|
|
311
|
+
headers: config.headers,
|
|
312
|
+
body: formBody
|
|
313
|
+
});
|
|
314
|
+
return (await response.json()) as PaymentStatusResponse;
|
|
315
|
+
} catch (error) {
|
|
316
|
+
console.error(error);
|
|
317
|
+
throw error;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* verifyCallback
|
|
323
|
+
* ...
|
|
324
|
+
*/
|
|
325
|
+
public async verifyCallback(options: CallbackEncoded): Promise<CallbackDecoded> {
|
|
326
|
+
try {
|
|
327
|
+
if (!options.paymentResult) throw new Error("paymentResult is missing or undefined");
|
|
328
|
+
const cipherRaw = Buffer.from(options.paymentResult, 'base64');
|
|
329
|
+
const key = Buffer.from(this.#decryptionKey);
|
|
330
|
+
const decipher = crypto.createDecipheriv('aes-256-ecb', key, null);
|
|
331
|
+
let decrypted = decipher.update(cipherRaw, undefined, 'utf8');
|
|
332
|
+
decrypted += decipher.final('utf8');
|
|
333
|
+
const result: CallbackDecoded = JSON.parse(decrypted) as CallbackDecoded;
|
|
334
|
+
return result;
|
|
335
|
+
} catch (error) {
|
|
336
|
+
console.error(error);
|
|
337
|
+
throw error;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* verifyCallbackRefund
|
|
343
|
+
* ...
|
|
344
|
+
*/
|
|
345
|
+
public async verifyCallbackRefund(options: CallbackEncoded): Promise<CallbackDecoded> {
|
|
346
|
+
try {
|
|
347
|
+
if (!options.refundResult) throw new Error("refundResult is missing or undefined");
|
|
348
|
+
const cipherRaw = Buffer.from(options.refundResult, 'base64');
|
|
349
|
+
const key = Buffer.from(this.#decryptionKey);
|
|
350
|
+
const decipher = crypto.createDecipheriv('aes-256-ecb', key, null);
|
|
351
|
+
let decrypted = decipher.update(cipherRaw, undefined, 'utf8');
|
|
352
|
+
decrypted += decipher.final('utf8');
|
|
353
|
+
const result: CallbackDecoded = JSON.parse(decrypted) as CallbackDecoded;
|
|
354
|
+
return result;
|
|
355
|
+
} catch (error) {
|
|
356
|
+
console.error(error);
|
|
357
|
+
throw error;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @Login
|
|
3
|
+
* @Login
|
|
4
|
+
* @Login
|
|
5
|
+
*/
|
|
6
|
+
export interface loginRequest {
|
|
7
|
+
phone: string,
|
|
8
|
+
password: string
|
|
9
|
+
}
|
|
10
|
+
export interface loginResponse {
|
|
11
|
+
err: number;
|
|
12
|
+
message: string;
|
|
13
|
+
token: {
|
|
14
|
+
token: string;
|
|
15
|
+
expiredAt: string;
|
|
16
|
+
},
|
|
17
|
+
refreshToken: {
|
|
18
|
+
token: string;
|
|
19
|
+
expiredAt: string;
|
|
20
|
+
},
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* @Token
|
|
24
|
+
* @Token
|
|
25
|
+
* @Token
|
|
26
|
+
*/
|
|
27
|
+
export interface getTokenRequest {
|
|
28
|
+
grantType: string;
|
|
29
|
+
}
|
|
30
|
+
export interface getTokenResponse {
|
|
31
|
+
accessToken: string;
|
|
32
|
+
scope: string;
|
|
33
|
+
tokenType: string;
|
|
34
|
+
expiresIn: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* @PaymentCreate
|
|
38
|
+
* @PaymentCreate
|
|
39
|
+
* @PaymentCreate
|
|
40
|
+
*/
|
|
41
|
+
export interface PaymentCreateRequest {
|
|
42
|
+
amount: number;
|
|
43
|
+
currency: string;
|
|
44
|
+
externalTransactionId: string;
|
|
45
|
+
externalAdditionalData?: string;
|
|
46
|
+
serviceCode: string;
|
|
47
|
+
MMQR: boolean;
|
|
48
|
+
timelimit: number;
|
|
49
|
+
}
|
|
50
|
+
export interface PaymentCreateResponse {
|
|
51
|
+
err: number;
|
|
52
|
+
message: string;
|
|
53
|
+
data: {
|
|
54
|
+
qrdata: string;
|
|
55
|
+
mmqrdata: string;
|
|
56
|
+
merchantId: string;
|
|
57
|
+
externalTransactionId: string;
|
|
58
|
+
referenceNumber: string;
|
|
59
|
+
amount: string;
|
|
60
|
+
fees: {
|
|
61
|
+
debitFee: number;
|
|
62
|
+
creditFee: number;
|
|
63
|
+
};
|
|
64
|
+
currency: string;
|
|
65
|
+
expiredAt: string;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* @PaymentStatus
|
|
70
|
+
* @PaymentStatus
|
|
71
|
+
* @PaymentStatus
|
|
72
|
+
*/
|
|
73
|
+
export interface PaymentStatusRequest {
|
|
74
|
+
referenceNumber: string;
|
|
75
|
+
externalTransactionId: string;
|
|
76
|
+
}
|
|
77
|
+
export interface PaymentStatusResponse {
|
|
78
|
+
err: number;
|
|
79
|
+
message: string;
|
|
80
|
+
status: string;
|
|
81
|
+
transRefId: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* @Callback
|
|
85
|
+
* @Callback
|
|
86
|
+
* @Callback
|
|
87
|
+
*/
|
|
88
|
+
export interface CallbackEncoded {
|
|
89
|
+
paymentResult?: string;
|
|
90
|
+
refundResult?: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface CallbackDecoded {
|
|
94
|
+
name: string;
|
|
95
|
+
desc: string;
|
|
96
|
+
currency: string;
|
|
97
|
+
fees: {
|
|
98
|
+
debitFee: number;
|
|
99
|
+
creditFee: number;
|
|
100
|
+
};
|
|
101
|
+
status: string;
|
|
102
|
+
createdAt: string;
|
|
103
|
+
transRefId: string;
|
|
104
|
+
code: string;
|
|
105
|
+
extMachId: string;
|
|
106
|
+
externalTransactionId: string;
|
|
107
|
+
referenceNumber: string;
|
|
108
|
+
totalAmount: number;
|
|
109
|
+
amount: number;
|
|
110
|
+
externalAdditionalData: string;
|
|
111
|
+
refFields: {
|
|
112
|
+
ENDTOENDID?: string;
|
|
113
|
+
OFFERID: string;
|
|
114
|
+
SENDERCLIENT: string;
|
|
115
|
+
SENDERID: string;
|
|
116
|
+
CURRENCY: string;
|
|
117
|
+
RECEIVERCLIENT: string;
|
|
118
|
+
TRANSACTIONID: string;
|
|
119
|
+
REFERENCENUMBER: string;
|
|
120
|
+
AMOUNT: number;
|
|
121
|
+
RECEIVERPHONE: string;
|
|
122
|
+
MESSAGE: string;
|
|
123
|
+
VOUCHER: string;
|
|
124
|
+
REQUESTID: string;
|
|
125
|
+
SERVICEID: string;
|
|
126
|
+
SUBUSERCLIENT: string;
|
|
127
|
+
SHOPID: string;
|
|
128
|
+
DEVICEID: string;
|
|
129
|
+
MACHID: string;
|
|
130
|
+
SUBUSERPHONE: string;
|
|
131
|
+
SENDERPHONE: string;
|
|
132
|
+
SENDERUSERID: string;
|
|
133
|
+
RECEIVERUSERID: string;
|
|
134
|
+
thirdpartyData: any;
|
|
135
|
+
TRANSREFID: string;
|
|
136
|
+
IP: string;
|
|
137
|
+
USERID: string;
|
|
138
|
+
CREDITORACCOUNTID?: string;
|
|
139
|
+
INVOICENUMBER?: string;
|
|
140
|
+
DEBITORNAME?: string;
|
|
141
|
+
DEBITORADDRESS?: string;
|
|
142
|
+
CREDITORNAME?: string;
|
|
143
|
+
EXTTRANSID?: string;
|
|
144
|
+
};
|
|
145
|
+
customer: {
|
|
146
|
+
id: string;
|
|
147
|
+
name: string;
|
|
148
|
+
phone: string;
|
|
149
|
+
};
|
|
150
|
+
merchant: {
|
|
151
|
+
id: string;
|
|
152
|
+
name: string;
|
|
153
|
+
phone: string;
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const { AYAPayMerchantApi } = require("../dist/cjs/index");
|
|
2
|
+
const dovenv = require("dotenv");
|
|
3
|
+
dovenv.config()
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
let callBackIncomingRequest = {
|
|
7
|
+
paymentResult: 'dnNP4EiXl/0i8fCeg27YuLF9117NTpaYK2FSzXBpGfWnZIHpoYAvIUjsOmJqjR1i+wU1Czk171RZZucGsQazZGpXr0y2DwvRJWrK/MpDgs1Ko5EeYnt/Zz/F5Fo8HLKkFPh2I5uMEWwo4pOvKtkWtyN+0RcwmlBmgze67GxjBP1HF4ElJFivvVatWqWqQokvf5G1yyMLnvJKvy+qZRZjdR4kqTzS03dZVD/wuSvt6X4VwQtd0CjYFK45U1KPUIo5+t+vwHJK1qCPKQmY7Ky8F/ql14XdbKlVu4lCM/hX/8Be+wTiK2TNntWqzZoaipy3JloB+twyEVGCleMgov0iiULSxpjKa0LyziBhakY0nCXLjPMQsGvCj09WLj9tkHYGvVqkYk1ySk2HF1Xrz5/Erzh9zuqNbFDx2lmfZMqNTYv/LVW1dCTZaqdy/Ti/9bmy8x205XRHbdH1R9pBEY6BU4tsf/gZf8Iku/40yzMeLx88nmoi5+4W7hSJE6TCaWLhCWnuoWiuyA6OUbMu/QN9i537clGJp3f7/0neSULj3pRYeETHWU3/3CthBW7sRFk6kqU22zm8zToYjbwbQDJMdO3h2SZcvPOL6HLKuS3kLLdCoylvv00/3sjmONJg+2Pho/esJLD9LiX9KuZ0U0CqXw4QZKQVJ0X7esddyWg6U0pxw5SeSzlNjoODcwfEATsTvOmWMd917gANH4rWTEOuz1T6+Z4NHltTprqWEitY9jpvONxm3KQuCuwbE2KJif9bvVqkYk1ySk2HF1Xrz5/ErwX8ZXT3NJBMaA/epwT1tlRl7mSdEJ+Br6aDwh4sJ2R2eNZJnp8c2q4u9j9bHeCsksn4MKDSD+21OKfjCjYHLabNmGQ4iowjjKHtHteYRbplidfC187gCV28e9FbuaIUtOswC6rvEFHmEvkXX2Vftz8Rrll/ZaGk3NMJ3UqmzwLGe0jQMprHPboFZWOwX+HQR4DHQX8acTAkdPU3xArf9COUYZL0TED+J6b4L8u5Go260ex1j1YI9opxRSbfocVn+8jDpgLV7Da7EVNSwKd8YC7toZe+x+N5yBob0d5qK/m7p2aSIB8hK+Dh6hRrf5N+DILApjzQkp12SlKfnSwryHPHW9Gm/e7xdmP1DmggVzgTf2j3od3fF2+Tz842Izez8t8crm7YvIM9otwOysjskNZTYC3nwebRTBXiDYhmsOhJCHoyQXP6Kl/7lOKTymfcET05FMpsF7Lmm6yC6hbq4bpr8xLOqlV8/sbiVCergsw4OyqTCKeE/p5pH2V3lWZT4Es/3yASJVF88pfFoFI7+QmQTUGNpZHhjfe0o/yBhPUys+02oYfSoXWpFfxADXp56v4xq3hWChUPhZBaiRFuYrjfS9WHDxTcKuYmzRXAUUAxo7HlGZJdscGITuv+g/BeyIBgBhx4JmqPvDrMapKUTXmFY+BYEqQmCcYHaPLG6VkcAe8ZJSZ4gEIFUF9ciBjKxKppglo0NXmFTg3JXC6y2FtwS+RaO5c/pMOvYoQOWjeLQZoiYjXzketcLdUrVrRSRjWNGNq8WEbg1pmswn0A3etZVZi6SPtAiVeiY0mJaZn6pYktfaUbb708GbWAYVxphPsepwgRSDw83twoXTkPVGW0cg4/RUbUR9RwkLBaPIK2runnRXRQJrCHJiIFcCmudAJy7hWzn8nSaHmPRZeFoY0iVGMVr4dIvi/nhrcD7wDT',
|
|
8
|
+
checksum: '34209caea8ad0825027e4b118674955cf2231abd3925fb995a2a4e91ebcc495e',
|
|
9
|
+
refundResult: '',
|
|
10
|
+
externalTransactionId: 'XX-1764916875394',
|
|
11
|
+
payByOtherPay: 'false',
|
|
12
|
+
debitorName: '',
|
|
13
|
+
mmqrRefId: '',
|
|
14
|
+
walletName: 'AYA Pay'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const AYAPay = AYAPayMerchantApi({
|
|
18
|
+
baseUrl: process.env.BASE_URL,
|
|
19
|
+
consumerKey: process.env.CONSUMER_KEY,
|
|
20
|
+
consumerSecret: process.env.CONSUMER_SECRET,
|
|
21
|
+
decryptionKey: process.env.DECRYPTION_KEY,
|
|
22
|
+
phone: process.env.MERCHANT_PHONE,
|
|
23
|
+
password: process.env.MERCHANT_PASSWORD,
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
const start = async () => {
|
|
28
|
+
const callbackDecoded = await AYAPay.verifyCallback(callBackIncomingRequest)
|
|
29
|
+
console.log(callbackDecoded)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
start()
|
package/test/test.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const { AYAPayMerchantApi } = require("../dist/cjs/index");
|
|
2
|
+
const dovenv = require("dotenv");
|
|
3
|
+
dovenv.config()
|
|
4
|
+
const { performance } = require("perf_hooks")
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const AYAPay = AYAPayMerchantApi({
|
|
8
|
+
baseUrl: process.env.BASE_URL,
|
|
9
|
+
consumerKey: process.env.CONSUMER_KEY,
|
|
10
|
+
consumerSecret: process.env.CONSUMER_SECRET,
|
|
11
|
+
decryptionKey: process.env.DECRYPTION_KEY,
|
|
12
|
+
phone: process.env.MERCHANT_PHONE,
|
|
13
|
+
password: process.env.MERCHANT_PASSWORD,
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
const start = async () => {
|
|
18
|
+
|
|
19
|
+
const startTime = performance.now();
|
|
20
|
+
|
|
21
|
+
// const tokenResponse = await AYAPay.getToken();
|
|
22
|
+
// console.log(tokenResponse)
|
|
23
|
+
// const end1Time = performance.now();
|
|
24
|
+
// const latency1Ms = (end1Time - startTime).toFixed(3);
|
|
25
|
+
// console.log(`\n--- Successful ---`);
|
|
26
|
+
// console.log(`**Network Latency: ${latency1Ms} ms**`);
|
|
27
|
+
|
|
28
|
+
// const loginResponse = await AYAPay.login({
|
|
29
|
+
// phone: process.env.MERCHANT_PHONE,
|
|
30
|
+
// password: process.env.MERCHANT_PASSWORD,
|
|
31
|
+
// });
|
|
32
|
+
// console.log(loginResponse)
|
|
33
|
+
// const end2Time = performance.now();
|
|
34
|
+
// const latency2Ms = (end2Time - startTime).toFixed(3);
|
|
35
|
+
// console.log(`\n--- Successful ---`);
|
|
36
|
+
// console.log(`**Network Latency: ${latency2Ms} ms**`);
|
|
37
|
+
|
|
38
|
+
const qrResponse = await AYAPay.requestQR({
|
|
39
|
+
amount: 5000,
|
|
40
|
+
currency: 'MMK',
|
|
41
|
+
externalTransactionId: 'ORD-' + new Date().getTime(),
|
|
42
|
+
serviceCode: 'myantel-qr',
|
|
43
|
+
MMQR: true,
|
|
44
|
+
timelimit: 5
|
|
45
|
+
})
|
|
46
|
+
console.log(qrResponse)
|
|
47
|
+
const end3Time = performance.now();
|
|
48
|
+
const latency3Ms = (end3Time - startTime).toFixed(3);
|
|
49
|
+
console.log(`\n--- Successful ---`);
|
|
50
|
+
console.log(`**Network Latency: ${latency3Ms} ms**`);
|
|
51
|
+
|
|
52
|
+
// const statusResponse = await AYAPay.paymentStatusQR({
|
|
53
|
+
// referenceNumber: qrResponse.data.referenceNumber,
|
|
54
|
+
// externalTransactionId: qrResponse.data.externalTransactionId,
|
|
55
|
+
// })
|
|
56
|
+
// console.log(statusResponse)
|
|
57
|
+
// const end4Time = performance.now();
|
|
58
|
+
// const latency4Ms = (end4Time - startTime).toFixed(3);
|
|
59
|
+
// console.log(`\n--- Successful ---`);
|
|
60
|
+
// console.log(`**Network Latency: ${latency4Ms} ms**`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
start()
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "Bundler",
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"outDir": "./dist/esm",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"types": [
|
|
13
|
+
"node"
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
"include": [
|
|
17
|
+
"src/**/*"
|
|
18
|
+
]
|
|
19
|
+
}
|