@miden-npm/react 0.1.0 → 1.0.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/dist/index.cjs +1825 -378
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -14
- package/dist/index.d.ts +21 -14
- package/dist/index.js +1847 -395
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -0
- package/package.json +13 -10
package/dist/index.js
CHANGED
|
@@ -71,10 +71,18 @@ var checkObjectTruthy = (obj) => {
|
|
|
71
71
|
if (obj == null || typeof obj !== "object") return false;
|
|
72
72
|
return Object.values(obj).every(Boolean);
|
|
73
73
|
};
|
|
74
|
+
var getQueryParams = (url) => {
|
|
75
|
+
const params = {};
|
|
76
|
+
const searchParams = new URL(url).searchParams;
|
|
77
|
+
searchParams.forEach((value, key) => {
|
|
78
|
+
params[key] = value;
|
|
79
|
+
});
|
|
80
|
+
return params;
|
|
81
|
+
};
|
|
74
82
|
|
|
75
83
|
// src/utils/api.util.ts
|
|
76
84
|
var getBaseUrl = (mode) => {
|
|
77
|
-
return mode === "sandbox" ? "https://sandbox-api.
|
|
85
|
+
return mode === "sandbox" ? "https://sandbox-api.buzapay.com/payment-gateway-api" : "";
|
|
78
86
|
};
|
|
79
87
|
|
|
80
88
|
// src/utils/string.util.ts
|
|
@@ -126,6 +134,246 @@ var restrictToNumericKeys = (event) => {
|
|
|
126
134
|
}
|
|
127
135
|
};
|
|
128
136
|
|
|
137
|
+
// src/utils/error.util.ts
|
|
138
|
+
var validateRegex = (value, regex) => regex.test(value);
|
|
139
|
+
function parseRules(rules) {
|
|
140
|
+
if (!rules) return [];
|
|
141
|
+
return rules.split("|").map((chunk) => {
|
|
142
|
+
const [rule, val] = chunk.split(":");
|
|
143
|
+
return { rule, value: val };
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
function getValidationErrorMessage(rulesStr, inputValue, label) {
|
|
147
|
+
const errors = [];
|
|
148
|
+
const rules = parseRules(rulesStr);
|
|
149
|
+
const lowerLabel = (label || "This field").toLowerCase();
|
|
150
|
+
const v = inputValue ?? "";
|
|
151
|
+
const num = Number(v);
|
|
152
|
+
const hasNum = !Number.isNaN(num);
|
|
153
|
+
for (const r of rules) {
|
|
154
|
+
switch (r.rule) {
|
|
155
|
+
case "required":
|
|
156
|
+
if (!v) errors.push(`The ${lowerLabel} field is required`);
|
|
157
|
+
break;
|
|
158
|
+
case "alpha":
|
|
159
|
+
if (!validateRegex(v, /^[a-zA-Z]+$/))
|
|
160
|
+
errors.push(
|
|
161
|
+
`The ${lowerLabel} field must only contain alphabetic characters`
|
|
162
|
+
);
|
|
163
|
+
break;
|
|
164
|
+
case "at_least_one_uppercase":
|
|
165
|
+
if (!validateRegex(v, /.*[A-Z].*/))
|
|
166
|
+
errors.push(
|
|
167
|
+
`The ${lowerLabel} field must contain at least one uppercase character`
|
|
168
|
+
);
|
|
169
|
+
break;
|
|
170
|
+
case "at_least_one_lowercase":
|
|
171
|
+
if (!validateRegex(v, /.*[a-z].*/))
|
|
172
|
+
errors.push(
|
|
173
|
+
`The ${lowerLabel} field must contain at least one lowercase character`
|
|
174
|
+
);
|
|
175
|
+
break;
|
|
176
|
+
case "at_least_one_number":
|
|
177
|
+
if (!validateRegex(v, /.*\d.*/))
|
|
178
|
+
errors.push(
|
|
179
|
+
`The ${lowerLabel} field must contain at least one number`
|
|
180
|
+
);
|
|
181
|
+
break;
|
|
182
|
+
case "alpha_num":
|
|
183
|
+
if (!validateRegex(v, /^[a-z0-9]+$/i))
|
|
184
|
+
errors.push(
|
|
185
|
+
`The ${lowerLabel} field must only contain alphabetic characters and numbers`
|
|
186
|
+
);
|
|
187
|
+
break;
|
|
188
|
+
case "num_spaces":
|
|
189
|
+
if (!validateRegex(v, /^[0-9\s]+$/i))
|
|
190
|
+
errors.push(
|
|
191
|
+
`The ${lowerLabel} field must only contain space and numbers`
|
|
192
|
+
);
|
|
193
|
+
break;
|
|
194
|
+
case "alpha_spaces":
|
|
195
|
+
if (!validateRegex(v, /^[A-Za-z\s]*$/))
|
|
196
|
+
errors.push(
|
|
197
|
+
`The ${lowerLabel} field must only contain alphabetic characters and spaces`
|
|
198
|
+
);
|
|
199
|
+
break;
|
|
200
|
+
case "numeric":
|
|
201
|
+
if (!validateRegex(v, /^\d+$/))
|
|
202
|
+
errors.push(`The ${lowerLabel} field must only contain numbers`);
|
|
203
|
+
break;
|
|
204
|
+
case "no_special":
|
|
205
|
+
if (validateRegex(v, /[^a-zA-Z0-9\s]/))
|
|
206
|
+
errors.push(
|
|
207
|
+
`The ${lowerLabel} field must not contain special characters`
|
|
208
|
+
);
|
|
209
|
+
break;
|
|
210
|
+
case "at_least_one_special":
|
|
211
|
+
if (!validateRegex(v, /[^a-zA-Z0-9\s]/))
|
|
212
|
+
errors.push(
|
|
213
|
+
`The ${lowerLabel} field must contain at least one special character`
|
|
214
|
+
);
|
|
215
|
+
break;
|
|
216
|
+
case "email":
|
|
217
|
+
if (!validateRegex(v, /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,})+$/)) {
|
|
218
|
+
errors.push("Please enter a valid email address");
|
|
219
|
+
}
|
|
220
|
+
break;
|
|
221
|
+
case "is":
|
|
222
|
+
if (r.value !== v) errors.push(`Value entered must be ${r.value}`);
|
|
223
|
+
break;
|
|
224
|
+
case "is_not":
|
|
225
|
+
if (r.value === v) errors.push(`Value entered must not be ${r.value}`);
|
|
226
|
+
break;
|
|
227
|
+
case "char_length":
|
|
228
|
+
if (v.length !== Number(r.value))
|
|
229
|
+
errors.push(
|
|
230
|
+
`The ${lowerLabel} field must be ${r.value} characters long`
|
|
231
|
+
);
|
|
232
|
+
break;
|
|
233
|
+
case "min_char_length":
|
|
234
|
+
if (v.length < Number(r.value))
|
|
235
|
+
errors.push(
|
|
236
|
+
`The ${lowerLabel} field must not be less than ${r.value} characters long`
|
|
237
|
+
);
|
|
238
|
+
break;
|
|
239
|
+
case "max_char_length":
|
|
240
|
+
if (v.length > Number(r.value))
|
|
241
|
+
errors.push(
|
|
242
|
+
`The ${lowerLabel} field must not be greater than ${r.value} characters long`
|
|
243
|
+
);
|
|
244
|
+
break;
|
|
245
|
+
// Age rules treat the value as a number (strict numeric compare)
|
|
246
|
+
case "age":
|
|
247
|
+
if (!hasNum || num !== Number(r.value))
|
|
248
|
+
errors.push(`Age entered must be ${r.value}`);
|
|
249
|
+
break;
|
|
250
|
+
case "min_age":
|
|
251
|
+
if (!hasNum || num < Number(r.value))
|
|
252
|
+
errors.push(`Age entered must not be less than ${r.value}`);
|
|
253
|
+
break;
|
|
254
|
+
case "max_age":
|
|
255
|
+
if (!hasNum || num > Number(r.value))
|
|
256
|
+
errors.push(`Age entered must not be greater than ${r.value}`);
|
|
257
|
+
break;
|
|
258
|
+
// Numeric value rules (general numbers)
|
|
259
|
+
case "num_is":
|
|
260
|
+
if (!hasNum || num !== Number(r.value))
|
|
261
|
+
errors.push(`Number entered must be ${r.value}`);
|
|
262
|
+
break;
|
|
263
|
+
case "num_is_not":
|
|
264
|
+
if (hasNum && num === Number(r.value))
|
|
265
|
+
errors.push(`Number entered must not be ${r.value}`);
|
|
266
|
+
break;
|
|
267
|
+
case "min_number":
|
|
268
|
+
if (!hasNum || num < Number(r.value))
|
|
269
|
+
errors.push(`Number entered must not be less than ${r.value}`);
|
|
270
|
+
break;
|
|
271
|
+
case "max_number":
|
|
272
|
+
if (!hasNum || num > Number(r.value))
|
|
273
|
+
errors.push(`Number entered must not be greater than ${r.value}`);
|
|
274
|
+
break;
|
|
275
|
+
default:
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return errors.length > 0 ? errors[0] : null;
|
|
280
|
+
}
|
|
281
|
+
var validateGroup = (values, rulesMap, prettyLabels) => {
|
|
282
|
+
const out = {};
|
|
283
|
+
for (const [field, rules] of Object.entries(rulesMap)) {
|
|
284
|
+
if (!rules) continue;
|
|
285
|
+
const label = prettyLabels?.[field] ?? field;
|
|
286
|
+
const err = getValidationErrorMessage(rules, values[field] ?? "", label);
|
|
287
|
+
if (err) out[field] = err;
|
|
288
|
+
}
|
|
289
|
+
return out;
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
// src/utils/card-scheme.util.ts
|
|
293
|
+
var CardSchemes = /* @__PURE__ */ ((CardSchemes2) => {
|
|
294
|
+
CardSchemes2[CardSchemes2["Visa"] = 1] = "Visa";
|
|
295
|
+
CardSchemes2[CardSchemes2["MasterCard"] = 2] = "MasterCard";
|
|
296
|
+
CardSchemes2[CardSchemes2["Verve"] = 3] = "Verve";
|
|
297
|
+
CardSchemes2[CardSchemes2["MastercardAndVisa"] = 4] = "MastercardAndVisa";
|
|
298
|
+
CardSchemes2[CardSchemes2["AmericanExpress"] = 5] = "AmericanExpress";
|
|
299
|
+
CardSchemes2[CardSchemes2["Discover"] = 6] = "Discover";
|
|
300
|
+
CardSchemes2[CardSchemes2["JCB"] = 7] = "JCB";
|
|
301
|
+
CardSchemes2[CardSchemes2["DinersClub"] = 8] = "DinersClub";
|
|
302
|
+
CardSchemes2[CardSchemes2["Maestro"] = 9] = "Maestro";
|
|
303
|
+
CardSchemes2[CardSchemes2["UnionPay"] = 10] = "UnionPay";
|
|
304
|
+
CardSchemes2[CardSchemes2["UnionPay3DS"] = 11] = "UnionPay3DS";
|
|
305
|
+
CardSchemes2[CardSchemes2["UnionPayNon3DS"] = 12] = "UnionPayNon3DS";
|
|
306
|
+
CardSchemes2[CardSchemes2["UATP"] = 13] = "UATP";
|
|
307
|
+
CardSchemes2[CardSchemes2["PayPak"] = 14] = "PayPak";
|
|
308
|
+
CardSchemes2[CardSchemes2["Jaywan"] = 15] = "Jaywan";
|
|
309
|
+
CardSchemes2[CardSchemes2["Mada"] = 16] = "Mada";
|
|
310
|
+
CardSchemes2[CardSchemes2["MadaVisa"] = 17] = "MadaVisa";
|
|
311
|
+
CardSchemes2[CardSchemes2["MadaMastercard"] = 18] = "MadaMastercard";
|
|
312
|
+
CardSchemes2[CardSchemes2["Unknown"] = 19] = "Unknown";
|
|
313
|
+
return CardSchemes2;
|
|
314
|
+
})(CardSchemes || {});
|
|
315
|
+
var VISA_RE = /^4\d{12}(\d{3}){0,2}$/;
|
|
316
|
+
var MC_RE = /^(?:5[1-5]\d{14}|2(?:2(?:2[1-9]|[3-9]\d)|[3-6]\d{2}|7(?:[01]\d|20))\d{12})(?:\d{0,3})?$/;
|
|
317
|
+
var AMEX_RE = /^(34|37)\d{13}$/;
|
|
318
|
+
var DISCOVER_RE = /^(?:6011|65|64[4-9]|622(?:12[6-9]|1[3-9]\d|[2-8]\d{2}|9(?:0\d|1\d|2[0-5])))\d{12,15}$/;
|
|
319
|
+
var JCB_RE = /^(?:35(?:2[8-9]|[3-8]\d))\d{12,15}$/;
|
|
320
|
+
var DINERS_RE = /^(?:3(?:0[0-5]\d|095|6\d|[89]\d))\d{11,13}$/;
|
|
321
|
+
var MAESTRO_RE = /^(?:50|5[6-9]|6[0-9])\d{10,17}$/;
|
|
322
|
+
var UNIONPAY_RE = /^62\d{14,17}$/;
|
|
323
|
+
var UATP_RE = /^1\d{14}$/;
|
|
324
|
+
var VERVE_BIN6_RANGES = [
|
|
325
|
+
[506099, 506198],
|
|
326
|
+
[650002, 650027]
|
|
327
|
+
];
|
|
328
|
+
var VERVE_BIN6_SINGLES = /* @__PURE__ */ new Set([507865, 507866]);
|
|
329
|
+
var PAYPAK_BIN6 = /* @__PURE__ */ new Set([220545, 220543]);
|
|
330
|
+
var JAYWAN_BIN7 = /* @__PURE__ */ new Set([6690109]);
|
|
331
|
+
var MADA_ONLY_BIN6 = /* @__PURE__ */ new Set([968209, 873646]);
|
|
332
|
+
var MADA_VISA_BIN6 = /* @__PURE__ */ new Set([422818, 486094]);
|
|
333
|
+
var MADA_MC_BIN6 = /* @__PURE__ */ new Set([529741, 543357]);
|
|
334
|
+
var UNIONPAY_3DS_BIN6 = /* @__PURE__ */ new Set([620108]);
|
|
335
|
+
var UNIONPAY_NON3DS_BIN6 = /* @__PURE__ */ new Set([621423]);
|
|
336
|
+
function cardTypeHandler(cardNumber) {
|
|
337
|
+
const scheme = detect(cardNumber);
|
|
338
|
+
return CardSchemes[scheme];
|
|
339
|
+
}
|
|
340
|
+
function detect(cardNumber) {
|
|
341
|
+
if (!cardNumber || !cardNumber.trim()) return 19 /* Unknown */;
|
|
342
|
+
const digits = cardNumber.replace(/\D/g, "");
|
|
343
|
+
if (digits.length < 12 || digits.length > 19) return 19 /* Unknown */;
|
|
344
|
+
if (digits.length >= 6) {
|
|
345
|
+
const bin6 = parseInt(digits.slice(0, 6), 10);
|
|
346
|
+
if (MADA_ONLY_BIN6.has(bin6) && digits.length >= 16 && digits.length <= 19)
|
|
347
|
+
return 16 /* Mada */;
|
|
348
|
+
if (MADA_VISA_BIN6.has(bin6) && VISA_RE.test(digits)) return 17 /* MadaVisa */;
|
|
349
|
+
if (MADA_MC_BIN6.has(bin6) && MC_RE.test(digits)) return 18 /* MadaMastercard */;
|
|
350
|
+
if (PAYPAK_BIN6.has(bin6) && digits.length === 16) return 14 /* PayPak */;
|
|
351
|
+
if (UNIONPAY_3DS_BIN6.has(bin6) && UNIONPAY_RE.test(digits)) return 11 /* UnionPay3DS */;
|
|
352
|
+
if (UNIONPAY_NON3DS_BIN6.has(bin6) && UNIONPAY_RE.test(digits))
|
|
353
|
+
return 12 /* UnionPayNon3DS */;
|
|
354
|
+
if (isVerve(bin6, digits.length)) return 3 /* Verve */;
|
|
355
|
+
}
|
|
356
|
+
if (digits.length >= 7) {
|
|
357
|
+
const bin7 = parseInt(digits.slice(0, 7), 10);
|
|
358
|
+
if (JAYWAN_BIN7.has(bin7) && digits.length === 16) return 15 /* Jaywan */;
|
|
359
|
+
}
|
|
360
|
+
if (UATP_RE.test(digits)) return 13 /* UATP */;
|
|
361
|
+
if (AMEX_RE.test(digits)) return 5 /* AmericanExpress */;
|
|
362
|
+
if (DISCOVER_RE.test(digits)) return 6 /* Discover */;
|
|
363
|
+
if (JCB_RE.test(digits)) return 7 /* JCB */;
|
|
364
|
+
if (DINERS_RE.test(digits)) return 8 /* DinersClub */;
|
|
365
|
+
if (MC_RE.test(digits)) return 2 /* MasterCard */;
|
|
366
|
+
if (VISA_RE.test(digits)) return 1 /* Visa */;
|
|
367
|
+
if (UNIONPAY_RE.test(digits)) return 10 /* UnionPay */;
|
|
368
|
+
if (MAESTRO_RE.test(digits)) return 9 /* Maestro */;
|
|
369
|
+
return 19 /* Unknown */;
|
|
370
|
+
}
|
|
371
|
+
function isVerve(bin6, length) {
|
|
372
|
+
if (length < 16 || length > 19) return false;
|
|
373
|
+
const inRange = VERVE_BIN6_RANGES.some(([start, end]) => bin6 >= start && bin6 <= end);
|
|
374
|
+
return inRange || VERVE_BIN6_SINGLES.has(bin6);
|
|
375
|
+
}
|
|
376
|
+
|
|
129
377
|
// src/apis/checkout.api.ts
|
|
130
378
|
async function createPaymentLink(paymentObject, environment, secretKey) {
|
|
131
379
|
try {
|
|
@@ -139,7 +387,189 @@ async function createPaymentLink(paymentObject, environment, secretKey) {
|
|
|
139
387
|
Accept: "application/json",
|
|
140
388
|
merchantId: secretKey
|
|
141
389
|
},
|
|
142
|
-
body: JSON.stringify(
|
|
390
|
+
body: JSON.stringify({
|
|
391
|
+
...paymentObject,
|
|
392
|
+
LinkName: `${Date.now()}-Link`
|
|
393
|
+
})
|
|
394
|
+
}
|
|
395
|
+
);
|
|
396
|
+
return await res.json();
|
|
397
|
+
} catch (error) {
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
async function authorizeCardPayment(environment, { merchantId, ...rest }) {
|
|
401
|
+
try {
|
|
402
|
+
const baseUrl = getBaseUrl(environment);
|
|
403
|
+
const res = await fetch(
|
|
404
|
+
`${baseUrl}/api/v1/checkout/authorize-card-3ds-payment-sdk`,
|
|
405
|
+
{
|
|
406
|
+
method: "POST",
|
|
407
|
+
headers: {
|
|
408
|
+
"Content-Type": "application/json",
|
|
409
|
+
Accept: "application/json",
|
|
410
|
+
merchantId
|
|
411
|
+
},
|
|
412
|
+
body: JSON.stringify(rest)
|
|
413
|
+
}
|
|
414
|
+
);
|
|
415
|
+
return await res.json();
|
|
416
|
+
} catch (error) {
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
async function getPaymentReferenceDetails(environment, paymentReference) {
|
|
420
|
+
try {
|
|
421
|
+
const baseUrl = getBaseUrl(environment);
|
|
422
|
+
const res = await fetch(
|
|
423
|
+
`${baseUrl}/api/v1/checkout/details/${paymentReference}`,
|
|
424
|
+
{
|
|
425
|
+
method: "GET",
|
|
426
|
+
headers: {
|
|
427
|
+
"Content-Type": "application/json",
|
|
428
|
+
Accept: "application/json"
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
);
|
|
432
|
+
return await res.json();
|
|
433
|
+
} catch (error) {
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
async function generatePaymentAccount(environment, { merchantId, ...rest }) {
|
|
437
|
+
try {
|
|
438
|
+
const baseUrl = getBaseUrl(environment);
|
|
439
|
+
const res = await fetch(
|
|
440
|
+
`${baseUrl}/api/v1/checkout/generate-payment-account`,
|
|
441
|
+
{
|
|
442
|
+
method: "POST",
|
|
443
|
+
headers: {
|
|
444
|
+
"Content-Type": "application/json",
|
|
445
|
+
Accept: "application/json",
|
|
446
|
+
merchantId
|
|
447
|
+
},
|
|
448
|
+
body: JSON.stringify(rest)
|
|
449
|
+
}
|
|
450
|
+
);
|
|
451
|
+
return await res.json();
|
|
452
|
+
} catch (error) {
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
async function generateStableCoinAddress(environment, { merchantId, ...rest }) {
|
|
456
|
+
try {
|
|
457
|
+
const baseUrl = getBaseUrl(environment);
|
|
458
|
+
const res = await fetch(
|
|
459
|
+
`${baseUrl}/api/v1/checkout/generate-payment-walletaddress`,
|
|
460
|
+
{
|
|
461
|
+
method: "POST",
|
|
462
|
+
headers: {
|
|
463
|
+
"Content-Type": "application/json",
|
|
464
|
+
Accept: "application/json",
|
|
465
|
+
merchantId
|
|
466
|
+
},
|
|
467
|
+
body: JSON.stringify(rest)
|
|
468
|
+
}
|
|
469
|
+
);
|
|
470
|
+
return await res.json();
|
|
471
|
+
} catch (error) {
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// src/apis/encrypt.api.ts
|
|
476
|
+
import CryptoJS from "crypto-js";
|
|
477
|
+
function encryptPayload(merchantId, formData = {}) {
|
|
478
|
+
const merchId = merchantId.replace(/-/g, "");
|
|
479
|
+
const first16Key = merchId.slice(0, 16);
|
|
480
|
+
const last16Iv = merchId.slice(-16);
|
|
481
|
+
const key = CryptoJS.enc.Utf8.parse(first16Key);
|
|
482
|
+
const iv = CryptoJS.enc.Utf8.parse(last16Iv);
|
|
483
|
+
const postDataObj = JSON.stringify(formData);
|
|
484
|
+
const encryptedData = CryptoJS.AES.encrypt(
|
|
485
|
+
CryptoJS.enc.Utf8.parse(postDataObj),
|
|
486
|
+
key,
|
|
487
|
+
{
|
|
488
|
+
keySize: 128 / 8,
|
|
489
|
+
iv,
|
|
490
|
+
mode: CryptoJS.mode.CBC,
|
|
491
|
+
padding: CryptoJS.pad.Pkcs7
|
|
492
|
+
}
|
|
493
|
+
);
|
|
494
|
+
return {
|
|
495
|
+
requestParam: encryptedData.toString()
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
function decryptPayload(merchantId, payload) {
|
|
499
|
+
const merchId = merchantId.replace(/-/g, "");
|
|
500
|
+
const first16Key = merchId.slice(0, 16);
|
|
501
|
+
const last16Iv = merchId.slice(-16);
|
|
502
|
+
const key = CryptoJS.enc.Utf8.parse(first16Key);
|
|
503
|
+
const iv = CryptoJS.enc.Utf8.parse(last16Iv);
|
|
504
|
+
const decryptedData = CryptoJS.AES.decrypt(payload, key, {
|
|
505
|
+
keySize: 128 / 8,
|
|
506
|
+
iv,
|
|
507
|
+
mode: CryptoJS.mode.CBC,
|
|
508
|
+
padding: CryptoJS.pad.Pkcs7
|
|
509
|
+
});
|
|
510
|
+
const decryptedText = decryptedData.toString(CryptoJS.enc.Utf8);
|
|
511
|
+
return JSON.parse(decryptedText);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// src/apis/resources.api.ts
|
|
515
|
+
async function getCountries(environment, secretKey) {
|
|
516
|
+
try {
|
|
517
|
+
const baseUrl = getBaseUrl(environment);
|
|
518
|
+
const res = await fetch(`${baseUrl}/api/v1/countries-iso`, {
|
|
519
|
+
method: "GET",
|
|
520
|
+
headers: {
|
|
521
|
+
"Content-Type": "application/json",
|
|
522
|
+
Accept: "application/json",
|
|
523
|
+
merchantId: secretKey
|
|
524
|
+
}
|
|
525
|
+
});
|
|
526
|
+
return await res.json();
|
|
527
|
+
} catch (error) {
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
async function getCountryStates(countryIso3, environment, secretKey) {
|
|
531
|
+
try {
|
|
532
|
+
const baseUrl = getBaseUrl(environment);
|
|
533
|
+
const res = await fetch(
|
|
534
|
+
`${baseUrl}/api/v1/state-by-country/${countryIso3}`,
|
|
535
|
+
{
|
|
536
|
+
method: "GET",
|
|
537
|
+
headers: {
|
|
538
|
+
"Content-Type": "application/json",
|
|
539
|
+
Accept: "application/json",
|
|
540
|
+
merchantId: secretKey
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
);
|
|
544
|
+
return await res.json();
|
|
545
|
+
} catch (error) {
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
async function getStableCoins(environment) {
|
|
549
|
+
try {
|
|
550
|
+
const baseUrl = getBaseUrl(environment);
|
|
551
|
+
const res = await fetch(`${baseUrl}/api/v1/checkout/stable-coin`, {
|
|
552
|
+
method: "GET",
|
|
553
|
+
headers: {
|
|
554
|
+
"Content-Type": "application/json",
|
|
555
|
+
Accept: "application/json"
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
return await res.json();
|
|
559
|
+
} catch (error) {
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
async function getStableCoinNetworks(environment, stableCoin) {
|
|
563
|
+
try {
|
|
564
|
+
const baseUrl = getBaseUrl(environment);
|
|
565
|
+
const res = await fetch(
|
|
566
|
+
`${baseUrl}/api/v1/checkout/networks/${stableCoin}`,
|
|
567
|
+
{
|
|
568
|
+
method: "GET",
|
|
569
|
+
headers: {
|
|
570
|
+
"Content-Type": "application/json",
|
|
571
|
+
Accept: "application/json"
|
|
572
|
+
}
|
|
143
573
|
}
|
|
144
574
|
);
|
|
145
575
|
return await res.json();
|
|
@@ -797,13 +1227,33 @@ var BaseLabelInfo = ({
|
|
|
797
1227
|
|
|
798
1228
|
// src/components/base/success.tsx
|
|
799
1229
|
import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
800
|
-
var BaseSuccess = ({
|
|
1230
|
+
var BaseSuccess = ({
|
|
1231
|
+
amount,
|
|
1232
|
+
currency,
|
|
1233
|
+
redirectUrl,
|
|
1234
|
+
successObject = {
|
|
1235
|
+
paymentDate: "",
|
|
1236
|
+
paymentId: "",
|
|
1237
|
+
paymentStatus: ""
|
|
1238
|
+
}
|
|
1239
|
+
}) => {
|
|
1240
|
+
const formatAmountHandler = formatAmount(amount, currency);
|
|
1241
|
+
const goToRedirectUrl = () => {
|
|
1242
|
+
window.open(redirectUrl, "_self", "noopener,noreferrer");
|
|
1243
|
+
};
|
|
1244
|
+
const paymentDate = new Date(
|
|
1245
|
+
successObject.paymentDate ?? ""
|
|
1246
|
+
).toLocaleDateString("en-US", {
|
|
1247
|
+
year: "numeric",
|
|
1248
|
+
month: "long",
|
|
1249
|
+
day: "2-digit"
|
|
1250
|
+
});
|
|
801
1251
|
return /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-8 p-16", children: [
|
|
802
1252
|
/* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-8", children: [
|
|
803
1253
|
/* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-8", children: [
|
|
804
1254
|
/* @__PURE__ */ jsx20(IconCheckCircle, { color: "#F47A1F", className: "mx-auto" }),
|
|
805
1255
|
/* @__PURE__ */ jsxs11("div", { className: "flex flex-col text-center", style: { gap: "2px" }, children: [
|
|
806
|
-
/* @__PURE__ */ jsx20("p", { className: "text-heading-text font-medium text-header-2xl", children:
|
|
1256
|
+
/* @__PURE__ */ jsx20("p", { className: "text-heading-text font-medium text-header-2xl", children: formatAmountHandler }),
|
|
807
1257
|
/* @__PURE__ */ jsx20("p", { className: "text-sub-copy font-regular text-body-3xs", children: "Has been paid successfully" })
|
|
808
1258
|
] })
|
|
809
1259
|
] }),
|
|
@@ -813,7 +1263,7 @@ var BaseSuccess = ({}) => {
|
|
|
813
1263
|
{
|
|
814
1264
|
type: "horizontal",
|
|
815
1265
|
label: "Order ID",
|
|
816
|
-
value:
|
|
1266
|
+
value: successObject.paymentId
|
|
817
1267
|
}
|
|
818
1268
|
) }),
|
|
819
1269
|
/* @__PURE__ */ jsx20("div", { className: "py-4", children: /* @__PURE__ */ jsx20(
|
|
@@ -821,7 +1271,7 @@ var BaseSuccess = ({}) => {
|
|
|
821
1271
|
{
|
|
822
1272
|
type: "horizontal",
|
|
823
1273
|
label: "Payment date",
|
|
824
|
-
value:
|
|
1274
|
+
value: paymentDate
|
|
825
1275
|
}
|
|
826
1276
|
) })
|
|
827
1277
|
] })
|
|
@@ -831,7 +1281,8 @@ var BaseSuccess = ({}) => {
|
|
|
831
1281
|
{
|
|
832
1282
|
label: "Return to Merchant Website",
|
|
833
1283
|
type: "secondary",
|
|
834
|
-
customClass: "w-full"
|
|
1284
|
+
customClass: "w-full",
|
|
1285
|
+
onClick: goToRedirectUrl
|
|
835
1286
|
}
|
|
836
1287
|
) })
|
|
837
1288
|
] });
|
|
@@ -851,6 +1302,7 @@ var BaseSelect = ({
|
|
|
851
1302
|
value,
|
|
852
1303
|
defaultValue,
|
|
853
1304
|
onChange,
|
|
1305
|
+
onBlur,
|
|
854
1306
|
placeholder = "Select an option",
|
|
855
1307
|
hasSearch = true,
|
|
856
1308
|
disabled = false,
|
|
@@ -923,6 +1375,7 @@ var BaseSelect = ({
|
|
|
923
1375
|
const commit = (val) => {
|
|
924
1376
|
if (!isControlled) setInternalValue(val);
|
|
925
1377
|
onChange?.(val);
|
|
1378
|
+
onBlur?.(val);
|
|
926
1379
|
closeMenu();
|
|
927
1380
|
};
|
|
928
1381
|
const onSearchInput = (e) => {
|
|
@@ -1073,6 +1526,7 @@ var BaseSelect = ({
|
|
|
1073
1526
|
ref: searchRef,
|
|
1074
1527
|
type: "text",
|
|
1075
1528
|
onChange: onSearchInput,
|
|
1529
|
+
onBlur: onSearchInput,
|
|
1076
1530
|
placeholder: `Search ${label || "options"}`,
|
|
1077
1531
|
className: "bg-transparent outline-none border-b pb-2 w-full focus:outline-none focus:ring-0 text-body-2xs text-light-copy font-normal"
|
|
1078
1532
|
}
|
|
@@ -1147,104 +1601,239 @@ var BaseCurrencyAmount = ({
|
|
|
1147
1601
|
] });
|
|
1148
1602
|
};
|
|
1149
1603
|
|
|
1150
|
-
// src/
|
|
1151
|
-
import
|
|
1152
|
-
import {
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
const
|
|
1177
|
-
const [
|
|
1178
|
-
|
|
1179
|
-
(url2) => {
|
|
1180
|
-
if (!containerRef.current) return;
|
|
1181
|
-
if (iframeRef.current && iframeRef.current.parentNode) {
|
|
1182
|
-
iframeRef.current.parentNode.removeChild(iframeRef.current);
|
|
1183
|
-
}
|
|
1184
|
-
const iframe = document.createElement("iframe");
|
|
1185
|
-
iframe.src = url2;
|
|
1186
|
-
if (style.width) iframe.style.width = style.width;
|
|
1187
|
-
if (style.height) iframe.style.height = style.height;
|
|
1188
|
-
if (style.border) iframe.style.border = style.border;
|
|
1189
|
-
if (style.borderRadius) iframe.style.borderRadius = style.borderRadius;
|
|
1190
|
-
if (style.overflow) iframe.style.overflow = style.overflow;
|
|
1191
|
-
containerRef.current.appendChild(iframe);
|
|
1192
|
-
iframeRef.current = iframe;
|
|
1193
|
-
},
|
|
1194
|
-
[style]
|
|
1604
|
+
// src/components/base/input.tsx
|
|
1605
|
+
import React4 from "react";
|
|
1606
|
+
import { IMaskInput } from "react-imask";
|
|
1607
|
+
import { Fragment as Fragment2, jsx as jsx24, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1608
|
+
var BaseInput = ({
|
|
1609
|
+
label = "",
|
|
1610
|
+
type = "text",
|
|
1611
|
+
mask,
|
|
1612
|
+
placeholder,
|
|
1613
|
+
validationError = "",
|
|
1614
|
+
hint = "",
|
|
1615
|
+
rules = [],
|
|
1616
|
+
isAmountInput = false,
|
|
1617
|
+
required = false,
|
|
1618
|
+
disabled = false,
|
|
1619
|
+
loading = false,
|
|
1620
|
+
showCopyIcon = false,
|
|
1621
|
+
preventPaste = false,
|
|
1622
|
+
value,
|
|
1623
|
+
defaultValue,
|
|
1624
|
+
onChange,
|
|
1625
|
+
onBlur,
|
|
1626
|
+
prefix,
|
|
1627
|
+
suffix,
|
|
1628
|
+
className = ""
|
|
1629
|
+
}) => {
|
|
1630
|
+
const isControlled = value !== void 0;
|
|
1631
|
+
const [rawValue, setRawValue] = React4.useState(
|
|
1632
|
+
defaultValue ?? value ?? ""
|
|
1195
1633
|
);
|
|
1196
|
-
const
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1634
|
+
const [localHint, setLocalHint] = React4.useState("");
|
|
1635
|
+
const [localError, setLocalError] = React4.useState("");
|
|
1636
|
+
React4.useEffect(() => {
|
|
1637
|
+
if (isControlled) setRawValue(value ?? "");
|
|
1638
|
+
}, [isControlled, value]);
|
|
1639
|
+
const formattedValue = isAmountInput ? formatAmount(rawValue.replace(/,/g, "")) : rawValue;
|
|
1640
|
+
const handleChange = (e) => {
|
|
1641
|
+
const incoming = e.target.value.replace(/,/g, "");
|
|
1642
|
+
if (!isControlled) setRawValue(incoming);
|
|
1643
|
+
onChange?.(incoming);
|
|
1644
|
+
setTimeout(() => {
|
|
1645
|
+
const el = e.target;
|
|
1646
|
+
el.selectionStart = el.selectionEnd = el.value.length;
|
|
1647
|
+
});
|
|
1648
|
+
};
|
|
1649
|
+
const handleBlur = () => {
|
|
1650
|
+
onBlur?.(rawValue);
|
|
1651
|
+
};
|
|
1652
|
+
const handleKeyDown = (e) => {
|
|
1653
|
+
if (rules.includes("numeric")) restrictToNumericKeys(e);
|
|
1654
|
+
};
|
|
1655
|
+
const handlePaste = (e) => {
|
|
1656
|
+
if (preventPaste) {
|
|
1657
|
+
e.preventDefault();
|
|
1658
|
+
setLocalError("Pasting is disabled for this input");
|
|
1203
1659
|
}
|
|
1204
|
-
|
|
1660
|
+
};
|
|
1661
|
+
const containerBg = disabled ? "bg-grey-50 cursor-not-allowed" : "bg-white";
|
|
1662
|
+
const containerBorder = validationError || localError ? "border-red-300 bg-red-50" : "border-grey-100";
|
|
1663
|
+
const copyToClipboard = (text) => {
|
|
1664
|
+
return navigator.clipboard.writeText(text);
|
|
1665
|
+
};
|
|
1666
|
+
const copyHandler = () => {
|
|
1667
|
+
copyToClipboard(rawValue).then(() => {
|
|
1668
|
+
setLocalHint("Text copied to clipboard");
|
|
1669
|
+
}).catch(() => {
|
|
1670
|
+
setLocalError("Failed to copy text to clipboard");
|
|
1671
|
+
});
|
|
1672
|
+
};
|
|
1673
|
+
return /* @__PURE__ */ jsxs14("div", { className: `flex flex-col gap-2 ${className}`, children: [
|
|
1674
|
+
label ? /* @__PURE__ */ jsxs14("p", { className: "mb-0 text-body-2xs font-normal text-heading-text", children: [
|
|
1675
|
+
label,
|
|
1676
|
+
required && /* @__PURE__ */ jsx24("span", { className: "text-orange-required", children: " *" })
|
|
1677
|
+
] }) : null,
|
|
1678
|
+
/* @__PURE__ */ jsxs14(
|
|
1679
|
+
"div",
|
|
1680
|
+
{
|
|
1681
|
+
className: `border-c px-3 py-2 flex items-center justify-between rounded-md h-12 ${containerBg} ${containerBorder}`,
|
|
1682
|
+
children: [
|
|
1683
|
+
prefix,
|
|
1684
|
+
/* @__PURE__ */ jsx24(
|
|
1685
|
+
IMaskInput,
|
|
1686
|
+
{
|
|
1687
|
+
type,
|
|
1688
|
+
mask,
|
|
1689
|
+
value: formattedValue,
|
|
1690
|
+
onChange: handleChange,
|
|
1691
|
+
onBlur: handleBlur,
|
|
1692
|
+
onKeyDown: handleKeyDown,
|
|
1693
|
+
onPaste: handlePaste,
|
|
1694
|
+
disabled,
|
|
1695
|
+
placeholder: placeholder ?? (label ? `Enter ${label.toLowerCase()}` : void 0),
|
|
1696
|
+
inputMode: isAmountInput ? "decimal" : void 0,
|
|
1697
|
+
className: "search-input bg-transparent outline-none border-none focus:outline-none focus:ring-0 text-body-2xs text-light-copy font-normal w-full"
|
|
1698
|
+
}
|
|
1699
|
+
),
|
|
1700
|
+
!loading ? /* @__PURE__ */ jsxs14(Fragment2, { children: [
|
|
1701
|
+
suffix,
|
|
1702
|
+
showCopyIcon && rawValue && rawValue.trim() !== "" && /* @__PURE__ */ jsx24(
|
|
1703
|
+
BaseImage,
|
|
1704
|
+
{
|
|
1705
|
+
src: "assets/images/copyIcon.svg",
|
|
1706
|
+
alt: "copy",
|
|
1707
|
+
width: 16,
|
|
1708
|
+
height: 16,
|
|
1709
|
+
customClass: "cursor-pointer hover:opacity-70 transition-opacity",
|
|
1710
|
+
onClick: copyHandler
|
|
1711
|
+
}
|
|
1712
|
+
)
|
|
1713
|
+
] }) : /* @__PURE__ */ jsx24("div", { className: "animate-spin h-4 w-4 border-2 border-current border-t-transparent rounded-full" })
|
|
1714
|
+
]
|
|
1715
|
+
}
|
|
1716
|
+
),
|
|
1717
|
+
(hint || localHint) && /* @__PURE__ */ jsx24("p", { className: "text-body-3xs text-light-copy", children: localHint || hint }),
|
|
1718
|
+
(validationError || localError) && /* @__PURE__ */ jsx24("p", { className: "text-body-3xs text-red-500", children: localError || validationError })
|
|
1719
|
+
] });
|
|
1720
|
+
};
|
|
1721
|
+
|
|
1722
|
+
// src/buzapay-checkout/checkout-iframe.tsx
|
|
1723
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useRef, useState as useState2 } from "react";
|
|
1724
|
+
import { jsx as jsx25, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1725
|
+
function BzpCheckoutIframe({
|
|
1726
|
+
style = {
|
|
1727
|
+
width: "100%",
|
|
1728
|
+
height: "100vh",
|
|
1729
|
+
border: "0",
|
|
1730
|
+
borderRadius: "6px",
|
|
1731
|
+
overflow: "hidden"
|
|
1732
|
+
},
|
|
1733
|
+
url,
|
|
1734
|
+
secretKey,
|
|
1735
|
+
environment = "sandbox",
|
|
1736
|
+
paymentObject = {
|
|
1737
|
+
merchantName: "",
|
|
1738
|
+
amount: 0,
|
|
1739
|
+
currency: "",
|
|
1740
|
+
email: "",
|
|
1741
|
+
phoneNumber: "",
|
|
1742
|
+
narration: "",
|
|
1743
|
+
redirectUrl: "https://sandbox-merchant.buzapay.com/account/three-ds-status"
|
|
1744
|
+
},
|
|
1745
|
+
onError
|
|
1746
|
+
}) {
|
|
1747
|
+
const containerRef = useRef(null);
|
|
1748
|
+
const iframeRef = useRef(null);
|
|
1749
|
+
const [message, setMessage] = useState2("");
|
|
1750
|
+
const [launchUrl, setLaunchUrl] = useState2("");
|
|
1751
|
+
const [loading, setLoading] = useState2(false);
|
|
1752
|
+
const launchIframe = useCallback2(
|
|
1753
|
+
(url2) => {
|
|
1754
|
+
if (iframeRef.current && iframeRef.current.parentNode) {
|
|
1755
|
+
iframeRef.current.parentNode.removeChild(iframeRef.current);
|
|
1756
|
+
}
|
|
1757
|
+
const iframe = document.createElement("iframe");
|
|
1758
|
+
iframe.src = url2;
|
|
1759
|
+
if (style.width) iframe.style.width = style.width;
|
|
1760
|
+
if (style.height) iframe.style.height = style.height;
|
|
1761
|
+
if (style.border) iframe.style.border = style.border;
|
|
1762
|
+
if (style.borderRadius) iframe.style.borderRadius = style.borderRadius;
|
|
1763
|
+
if (style.overflow) iframe.style.overflow = style.overflow;
|
|
1764
|
+
containerRef.current?.appendChild(iframe);
|
|
1765
|
+
iframeRef.current = iframe;
|
|
1766
|
+
},
|
|
1767
|
+
[style]
|
|
1768
|
+
);
|
|
1769
|
+
const generatePaymentLinkHandler = async () => {
|
|
1770
|
+
if (url) {
|
|
1771
|
+
launchIframe(url);
|
|
1772
|
+
return;
|
|
1773
|
+
}
|
|
1774
|
+
if (!secretKey) {
|
|
1775
|
+
return setMessage("Secret key is required.");
|
|
1776
|
+
}
|
|
1777
|
+
if (!checkObjectTruthy(paymentObject)) {
|
|
1205
1778
|
return setMessage("Secret key is required.");
|
|
1206
1779
|
}
|
|
1207
1780
|
setLoading(true);
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1781
|
+
try {
|
|
1782
|
+
const response = await createPaymentLink(
|
|
1783
|
+
paymentObject,
|
|
1784
|
+
environment,
|
|
1785
|
+
secretKey
|
|
1786
|
+
);
|
|
1787
|
+
if (response?.isSuccessful) {
|
|
1788
|
+
setLaunchUrl(response.launchUrl ?? "");
|
|
1789
|
+
setMessage("Payment link created successfully");
|
|
1790
|
+
if (response.launchUrl) {
|
|
1791
|
+
setLoading(false);
|
|
1792
|
+
launchIframe(`${response.launchUrl}&merchantId=${btoa(secretKey)}`);
|
|
1793
|
+
}
|
|
1794
|
+
} else {
|
|
1795
|
+
setLoading(false);
|
|
1796
|
+
setMessage("Failed to create payment link");
|
|
1218
1797
|
}
|
|
1219
|
-
}
|
|
1220
|
-
setMessage("Failed to create payment link");
|
|
1798
|
+
} catch (e) {
|
|
1799
|
+
setMessage(e?.message || "Failed to create payment link");
|
|
1800
|
+
onError?.({
|
|
1801
|
+
errorMessage: message
|
|
1802
|
+
});
|
|
1803
|
+
} finally {
|
|
1804
|
+
setLoading(false);
|
|
1221
1805
|
}
|
|
1222
1806
|
};
|
|
1223
1807
|
useEffect2(() => {
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
})();
|
|
1808
|
+
if (!containerRef.current) return;
|
|
1809
|
+
generatePaymentLinkHandler();
|
|
1227
1810
|
}, []);
|
|
1228
|
-
return
|
|
1811
|
+
return /* @__PURE__ */ jsxs15("div", { className: "relative", style, children: [
|
|
1812
|
+
/* @__PURE__ */ jsx25("div", { ref: containerRef, className: "w-full h-full" }),
|
|
1813
|
+
loading && /* @__PURE__ */ jsx25("div", { className: "absolute inset-0 grid place-items-center bg-white/60", children: /* @__PURE__ */ jsx25(IconLoader, {}) })
|
|
1814
|
+
] });
|
|
1229
1815
|
}
|
|
1230
1816
|
|
|
1231
1817
|
// src/buzapay-checkout/checkout-button.tsx
|
|
1232
|
-
import { jsx as
|
|
1818
|
+
import { jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1233
1819
|
function BzpCheckoutButton({
|
|
1234
1820
|
secretKey,
|
|
1235
1821
|
environment = "sandbox",
|
|
1236
1822
|
paymentObject = {
|
|
1823
|
+
merchantName: "",
|
|
1237
1824
|
amount: 0,
|
|
1238
1825
|
currency: "",
|
|
1239
1826
|
email: "",
|
|
1240
1827
|
phoneNumber: "",
|
|
1241
1828
|
narration: "",
|
|
1242
|
-
redirectUrl: ""
|
|
1829
|
+
redirectUrl: "https://sandbox-merchant.buzapay.com/account/three-ds-status"
|
|
1243
1830
|
},
|
|
1244
|
-
mode = "redirect"
|
|
1831
|
+
mode = "redirect",
|
|
1832
|
+
onError
|
|
1245
1833
|
}) {
|
|
1246
1834
|
const [message, setMessage] = useState3("");
|
|
1247
1835
|
const [launchUrl, setLaunchUrl] = useState3("");
|
|
1836
|
+
const [urlLaunchUrl, setUrlLaunchUrl] = useState3("");
|
|
1248
1837
|
const [loading, setLoading] = useState3(false);
|
|
1249
1838
|
const generatePaymentLinkHandler = async () => {
|
|
1250
1839
|
if (!secretKey) {
|
|
@@ -1265,6 +1854,7 @@ function BzpCheckoutButton({
|
|
|
1265
1854
|
);
|
|
1266
1855
|
if (response?.isSuccessful && response.launchUrl) {
|
|
1267
1856
|
setLaunchUrl(response.launchUrl);
|
|
1857
|
+
setUrlLaunchUrl(`${response.launchUrl}&merchantId=${btoa(secretKey)}`);
|
|
1268
1858
|
setMessage("Payment link created successfully");
|
|
1269
1859
|
if (mode === "redirect") {
|
|
1270
1860
|
window.open(response.launchUrl, "_blank", "noopener,noreferrer");
|
|
@@ -1274,19 +1864,22 @@ function BzpCheckoutButton({
|
|
|
1274
1864
|
}
|
|
1275
1865
|
} catch (e) {
|
|
1276
1866
|
setMessage(e?.message || "Failed to create payment link");
|
|
1867
|
+
onError?.({
|
|
1868
|
+
errorMessage: message
|
|
1869
|
+
});
|
|
1277
1870
|
} finally {
|
|
1278
1871
|
setLoading(false);
|
|
1279
1872
|
}
|
|
1280
1873
|
};
|
|
1281
|
-
return
|
|
1874
|
+
return urlLaunchUrl && mode === "iframe" ? /* @__PURE__ */ jsx26(
|
|
1282
1875
|
BzpCheckoutIframe,
|
|
1283
1876
|
{
|
|
1284
|
-
url:
|
|
1877
|
+
url: urlLaunchUrl,
|
|
1285
1878
|
secretKey,
|
|
1286
1879
|
environment
|
|
1287
1880
|
}
|
|
1288
|
-
) : /* @__PURE__ */
|
|
1289
|
-
/* @__PURE__ */
|
|
1881
|
+
) : /* @__PURE__ */ jsxs16("div", { children: [
|
|
1882
|
+
/* @__PURE__ */ jsx26(
|
|
1290
1883
|
BaseButton,
|
|
1291
1884
|
{
|
|
1292
1885
|
label: "Pay",
|
|
@@ -1296,146 +1889,376 @@ function BzpCheckoutButton({
|
|
|
1296
1889
|
onClick: generatePaymentLinkHandler
|
|
1297
1890
|
}
|
|
1298
1891
|
),
|
|
1299
|
-
/* @__PURE__ */
|
|
1892
|
+
/* @__PURE__ */ jsx26(BaseInputError, { errorMessage: message })
|
|
1300
1893
|
] });
|
|
1301
1894
|
}
|
|
1302
1895
|
|
|
1303
1896
|
// src/buzapay-checkout/checkout-card.tsx
|
|
1304
|
-
import { useEffect as
|
|
1897
|
+
import { useEffect as useEffect6, useState as useState7 } from "react";
|
|
1305
1898
|
|
|
1306
1899
|
// src/components/pay-by-card.tsx
|
|
1307
|
-
import { useState as useState4 } from "react";
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1900
|
+
import { useEffect as useEffect3, useState as useState4 } from "react";
|
|
1901
|
+
import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1902
|
+
function PayByCard({
|
|
1903
|
+
secretKey,
|
|
1904
|
+
paymentObject,
|
|
1905
|
+
environment = "sandbox",
|
|
1906
|
+
onPaymentAuthorized,
|
|
1907
|
+
onError
|
|
1908
|
+
}) {
|
|
1909
|
+
const [formIndex, setFormIndex] = useState4(0);
|
|
1910
|
+
const [message, setMessage] = useState4("");
|
|
1911
|
+
const [isMakingPayment, setIsMakingPayment] = useState4(false);
|
|
1912
|
+
const [loading, setLoading] = useState4(false);
|
|
1913
|
+
const [cardType, setCardType] = useState4("");
|
|
1914
|
+
const [transactionReference, setTransactionReference] = useState4("");
|
|
1915
|
+
const [loadingCountries, setLoadingCountries] = useState4(false);
|
|
1916
|
+
const [loadingStates, setLoadingStates] = useState4(false);
|
|
1917
|
+
const [rawCountries, setRawCountries] = useState4([]);
|
|
1918
|
+
const [countries, setCountries] = useState4([]);
|
|
1919
|
+
const [countryStates, setCountryStates] = useState4([]);
|
|
1920
|
+
const [billingForm, setBillingForm] = useState4({
|
|
1921
|
+
address1: "",
|
|
1922
|
+
address2: "",
|
|
1923
|
+
postalCode: "",
|
|
1924
|
+
state: "",
|
|
1925
|
+
city: "",
|
|
1926
|
+
country: "",
|
|
1927
|
+
emailAddress: "",
|
|
1928
|
+
phoneNumber: ""
|
|
1929
|
+
});
|
|
1930
|
+
const [payForm, setPayForm] = useState4({
|
|
1931
|
+
customerName: "",
|
|
1932
|
+
cardNo: "",
|
|
1933
|
+
expireDate: "",
|
|
1934
|
+
cvv: "",
|
|
1935
|
+
cardPin: ""
|
|
1936
|
+
// Only required for Verve cards
|
|
1937
|
+
});
|
|
1938
|
+
const [billingErrors, setBillingErrors] = useState4(
|
|
1939
|
+
{}
|
|
1335
1940
|
);
|
|
1336
|
-
const [
|
|
1337
|
-
const
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
const el = e.target;
|
|
1348
|
-
el.selectionStart = el.selectionEnd = el.value.length;
|
|
1349
|
-
});
|
|
1941
|
+
const [payErrors, setPayErrors] = useState4({});
|
|
1942
|
+
const billingRules = {
|
|
1943
|
+
address1: "required",
|
|
1944
|
+
address2: "",
|
|
1945
|
+
// optional
|
|
1946
|
+
country: "required",
|
|
1947
|
+
state: "required",
|
|
1948
|
+
city: "required",
|
|
1949
|
+
postalCode: "required|no_special|char_length:6",
|
|
1950
|
+
emailAddress: "required|email",
|
|
1951
|
+
phoneNumber: "required"
|
|
1350
1952
|
};
|
|
1351
|
-
const
|
|
1352
|
-
|
|
1953
|
+
const payRules = {
|
|
1954
|
+
customerName: "required",
|
|
1955
|
+
cardNo: "required|num_spaces",
|
|
1956
|
+
expireDate: "required",
|
|
1957
|
+
cvv: "required|numeric",
|
|
1958
|
+
cardPin: ""
|
|
1959
|
+
// optional unless Verve
|
|
1353
1960
|
};
|
|
1354
|
-
const
|
|
1355
|
-
|
|
1961
|
+
const formatAmountHandler = formatAmount(
|
|
1962
|
+
paymentObject.amount,
|
|
1963
|
+
paymentObject.currency
|
|
1964
|
+
);
|
|
1965
|
+
const billingLabels = {
|
|
1966
|
+
address1: "Address Line 1",
|
|
1967
|
+
address2: "Address Line 2",
|
|
1968
|
+
postalCode: "Postal Code",
|
|
1969
|
+
state: "State",
|
|
1970
|
+
city: "City",
|
|
1971
|
+
country: "Country",
|
|
1972
|
+
emailAddress: "Email",
|
|
1973
|
+
phoneNumber: "Phone Number"
|
|
1356
1974
|
};
|
|
1357
|
-
const
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1975
|
+
const payLabels = {
|
|
1976
|
+
customerName: "Card Name",
|
|
1977
|
+
cardNo: "Card Number",
|
|
1978
|
+
expireDate: "Expiry Date",
|
|
1979
|
+
cvv: "CVV",
|
|
1980
|
+
cardPin: "Card PIN"
|
|
1361
1981
|
};
|
|
1362
|
-
const
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1982
|
+
const proceedHandler = async () => {
|
|
1983
|
+
if (formIndex === 0) {
|
|
1984
|
+
const errs = validateGroup(billingForm, billingRules, billingLabels);
|
|
1985
|
+
setBillingErrors(errs);
|
|
1986
|
+
if (Object.keys(errs).length === 0) {
|
|
1987
|
+
setFormIndex(1);
|
|
1988
|
+
}
|
|
1989
|
+
return;
|
|
1990
|
+
}
|
|
1991
|
+
if (formIndex === 1) {
|
|
1992
|
+
const errs = validateGroup(payForm, payRules, payLabels);
|
|
1993
|
+
setPayErrors(errs);
|
|
1994
|
+
if (Object.keys(errs).length > 0) {
|
|
1995
|
+
return;
|
|
1996
|
+
}
|
|
1997
|
+
try {
|
|
1998
|
+
setIsMakingPayment(true);
|
|
1999
|
+
setMessage("");
|
|
2000
|
+
const cardDetails = {
|
|
2001
|
+
pan: payForm.cardNo ?? "",
|
|
2002
|
+
expiryDate: payForm.expireDate ?? "",
|
|
2003
|
+
cvv: payForm.cvv ?? "",
|
|
2004
|
+
cardScheme: cardType,
|
|
2005
|
+
nameOnCard: payForm.customerName ?? "",
|
|
2006
|
+
...cardType === "Verve" && { pin: payForm.cardPin ?? "" }
|
|
2007
|
+
};
|
|
2008
|
+
const billingDetails = {
|
|
2009
|
+
address1: billingForm.address1 ?? "",
|
|
2010
|
+
address2: billingForm.address2 ?? "",
|
|
2011
|
+
postalCode: billingForm.postalCode ?? "",
|
|
2012
|
+
state: billingForm.state ?? "",
|
|
2013
|
+
city: billingForm.city ?? "",
|
|
2014
|
+
country: billingForm.country ?? "",
|
|
2015
|
+
emailAddress: billingForm.emailAddress ?? "",
|
|
2016
|
+
phoneNumber: billingForm.phoneNumber ?? ""
|
|
2017
|
+
};
|
|
2018
|
+
const encryptedCardDetails = encryptPayload(secretKey, cardDetails);
|
|
2019
|
+
const payload = {
|
|
2020
|
+
customerId: paymentObject?.email || payForm.customerName || "",
|
|
2021
|
+
amount: String(paymentObject?.amount ?? ""),
|
|
2022
|
+
currency: paymentObject?.currency || "USD",
|
|
2023
|
+
narration: paymentObject?.narration || "Test transaction",
|
|
2024
|
+
encryptedCardDetails: encryptedCardDetails.requestParam,
|
|
2025
|
+
billingDetails,
|
|
2026
|
+
redirectUrl: paymentObject?.redirectUrl || "",
|
|
2027
|
+
paymentReference: transactionReference,
|
|
2028
|
+
isCheckout: true
|
|
2029
|
+
};
|
|
2030
|
+
const request = { ...payload, merchantId: secretKey };
|
|
2031
|
+
let response = await authorizeCardPayment(environment, request);
|
|
2032
|
+
if (response?.responseParam) {
|
|
2033
|
+
response = decryptPayload(environment, response.responseParam);
|
|
2034
|
+
}
|
|
2035
|
+
if (response?.isSuccessful) {
|
|
2036
|
+
if (response.threeDsInteractionRequired === true) {
|
|
2037
|
+
const threeDsData = {
|
|
2038
|
+
transactionReference: response.transactionReference,
|
|
2039
|
+
threeDsHtml: response.threeDsHtml,
|
|
2040
|
+
amount: response.amount,
|
|
2041
|
+
responseMessage: response.responseMessage,
|
|
2042
|
+
paReq: response.threeDsHtml?.paReq,
|
|
2043
|
+
termUrl: response.threeDsHtml?.termUrl,
|
|
2044
|
+
action: response.threeDsHtml?.action,
|
|
2045
|
+
acsUrl: response.threeDsHtml?.acsUrl,
|
|
2046
|
+
md: response.threeDsHtml?.md
|
|
2047
|
+
};
|
|
2048
|
+
const stringifiedThreeDsData = btoa(JSON.stringify(threeDsData));
|
|
2049
|
+
const threeDsUrl = `https://sandbox-merchant.buzapay.com/account/three-ds-confirm?threeDsData=${encodeURIComponent(
|
|
2050
|
+
stringifiedThreeDsData
|
|
2051
|
+
)}&paymentReference=${response.transactionReference}`;
|
|
2052
|
+
window.open(threeDsUrl, "_self", "noopener,noreferrer");
|
|
2053
|
+
setMessage(
|
|
2054
|
+
"3D Secure authentication opened in new tab. Please complete the verification"
|
|
2055
|
+
);
|
|
2056
|
+
setIsMakingPayment(false);
|
|
2057
|
+
return;
|
|
2058
|
+
}
|
|
2059
|
+
if (response.responseMessage === "Payer Interaction Required" && response.threeDsHtml) {
|
|
2060
|
+
const threeDsData = {
|
|
2061
|
+
transactionReference: response.transactionReference,
|
|
2062
|
+
threeDsHtml: response.threeDsHtml,
|
|
2063
|
+
amount: response.amount,
|
|
2064
|
+
responseMessage: response.responseMessage,
|
|
2065
|
+
paReq: response.threeDsHtml?.paReq,
|
|
2066
|
+
termUrl: response.threeDsHtml?.termUrl,
|
|
2067
|
+
action: response.threeDsHtml?.action,
|
|
2068
|
+
acsUrl: response.threeDsHtml?.acsUrl,
|
|
2069
|
+
md: response.threeDsHtml?.md
|
|
2070
|
+
};
|
|
2071
|
+
const stringifiedThreeDsData = btoa(JSON.stringify(threeDsData));
|
|
2072
|
+
const threeDsUrl = `https://sandbox-merchant.buzapay.com/account/three-ds-confirm?threeDsData=${encodeURIComponent(
|
|
2073
|
+
stringifiedThreeDsData
|
|
2074
|
+
)}&paymentReference=${response.transactionReference}`;
|
|
2075
|
+
window.open(threeDsUrl, "_self", "noopener,noreferrer");
|
|
2076
|
+
setMessage(
|
|
2077
|
+
"3D Secure authentication opened in new tab. Please complete the verification"
|
|
2078
|
+
);
|
|
2079
|
+
setIsMakingPayment(false);
|
|
2080
|
+
return;
|
|
2081
|
+
}
|
|
2082
|
+
if (response.transactionReference?.trim()) {
|
|
2083
|
+
onPaymentAuthorized?.({
|
|
2084
|
+
paymentId: response.transactionReference,
|
|
2085
|
+
paymentDate: response?.data?.updatedAt,
|
|
2086
|
+
// optional if present
|
|
2087
|
+
paymentStatus: "authorized",
|
|
2088
|
+
message
|
|
2089
|
+
});
|
|
2090
|
+
}
|
|
2091
|
+
setMessage("Card payment authorized successfully");
|
|
2092
|
+
setIsMakingPayment(false);
|
|
2093
|
+
return;
|
|
2094
|
+
}
|
|
2095
|
+
setMessage(response?.responseMessage || "Payment failed");
|
|
2096
|
+
onPaymentAuthorized?.({
|
|
2097
|
+
paymentId: response?.transactionReference,
|
|
2098
|
+
paymentDate: response?.data?.updatedAt,
|
|
2099
|
+
paymentStatus: "payment failed",
|
|
2100
|
+
message
|
|
2101
|
+
});
|
|
2102
|
+
setIsMakingPayment(false);
|
|
2103
|
+
} catch (err) {
|
|
2104
|
+
let friendly = "Payment failed";
|
|
2105
|
+
if (err?.error?.responseParam) {
|
|
2106
|
+
try {
|
|
2107
|
+
const decryptedError = decryptPayload(
|
|
2108
|
+
environment,
|
|
2109
|
+
err.error.responseParam
|
|
2110
|
+
);
|
|
2111
|
+
friendly = decryptedError?.responseMessage || friendly;
|
|
2112
|
+
} catch {
|
|
2113
|
+
friendly = err?.error?.responseMessage || err?.error?.message || friendly;
|
|
2114
|
+
}
|
|
2115
|
+
} else {
|
|
2116
|
+
friendly = err?.error?.responseMessage || err?.error?.message || "Payment failed";
|
|
2117
|
+
}
|
|
2118
|
+
setMessage(friendly);
|
|
2119
|
+
setIsMakingPayment(false);
|
|
2120
|
+
onError?.({
|
|
2121
|
+
errorMessage: message
|
|
2122
|
+
});
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
1368
2125
|
};
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
"
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
}
|
|
1393
|
-
),
|
|
1394
|
-
!loading ? /* @__PURE__ */ jsxs15(Fragment2, { children: [
|
|
1395
|
-
suffix,
|
|
1396
|
-
showCopyIcon && rawValue && rawValue.trim() !== "" && /* @__PURE__ */ jsx26(
|
|
1397
|
-
BaseImage,
|
|
1398
|
-
{
|
|
1399
|
-
src: "assets/images/copyIcon.svg",
|
|
1400
|
-
alt: "copy",
|
|
1401
|
-
width: 16,
|
|
1402
|
-
height: 16,
|
|
1403
|
-
customClass: "cursor-pointer hover:opacity-70 transition-opacity",
|
|
1404
|
-
onClick: copyHandler
|
|
1405
|
-
}
|
|
1406
|
-
)
|
|
1407
|
-
] }) : (
|
|
1408
|
-
// Simple loader placeholder; swap for your icon component if desired
|
|
1409
|
-
/* @__PURE__ */ jsx26("div", { className: "animate-spin h-4 w-4 border-2 border-current border-t-transparent rounded-full" })
|
|
1410
|
-
)
|
|
1411
|
-
]
|
|
2126
|
+
const generatePaymentLinkHandler = async () => {
|
|
2127
|
+
if (!secretKey) {
|
|
2128
|
+
setMessage("Secret key is required.");
|
|
2129
|
+
return;
|
|
2130
|
+
}
|
|
2131
|
+
if (!checkObjectTruthy(paymentObject)) {
|
|
2132
|
+
setMessage("Kindly ensure you are passing all the required data.");
|
|
2133
|
+
return;
|
|
2134
|
+
}
|
|
2135
|
+
setLoading(true);
|
|
2136
|
+
setMessage("");
|
|
2137
|
+
try {
|
|
2138
|
+
const response = await createPaymentLink(
|
|
2139
|
+
paymentObject,
|
|
2140
|
+
environment,
|
|
2141
|
+
secretKey
|
|
2142
|
+
);
|
|
2143
|
+
if (response?.isSuccessful && response.launchUrl) {
|
|
2144
|
+
const queryParams = getQueryParams(response.launchUrl);
|
|
2145
|
+
setTransactionReference(queryParams["paymentReference"]);
|
|
2146
|
+
setMessage("Payment link created successfully");
|
|
2147
|
+
} else {
|
|
2148
|
+
setMessage("Failed to create payment link");
|
|
1412
2149
|
}
|
|
1413
|
-
)
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
};
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
const
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
2150
|
+
} catch (e) {
|
|
2151
|
+
setMessage(e?.message || "Failed to create payment link");
|
|
2152
|
+
onError?.({
|
|
2153
|
+
errorMessage: message
|
|
2154
|
+
});
|
|
2155
|
+
} finally {
|
|
2156
|
+
setLoading(false);
|
|
2157
|
+
}
|
|
2158
|
+
};
|
|
2159
|
+
const getAllCountries = async () => {
|
|
2160
|
+
setLoadingCountries(true);
|
|
2161
|
+
try {
|
|
2162
|
+
const response = await getCountries(
|
|
2163
|
+
environment,
|
|
2164
|
+
secretKey
|
|
2165
|
+
);
|
|
2166
|
+
if (response?.isSuccessful) {
|
|
2167
|
+
setRawCountries(response.data);
|
|
2168
|
+
setCountries(
|
|
2169
|
+
(response.data ?? []).map((c) => {
|
|
2170
|
+
return { label: c.countryName, value: c.iso2 };
|
|
2171
|
+
})
|
|
2172
|
+
);
|
|
2173
|
+
}
|
|
2174
|
+
} catch (e) {
|
|
2175
|
+
setMessage(e?.message || "Failed to get countries");
|
|
2176
|
+
onError?.({
|
|
2177
|
+
errorMessage: message
|
|
2178
|
+
});
|
|
2179
|
+
} finally {
|
|
2180
|
+
setLoadingCountries(false);
|
|
2181
|
+
}
|
|
2182
|
+
};
|
|
2183
|
+
const getStates = async (countryIso2) => {
|
|
2184
|
+
const country = rawCountries.find((c) => c.iso2 === countryIso2);
|
|
2185
|
+
if (!country) return;
|
|
2186
|
+
setLoadingStates(true);
|
|
2187
|
+
try {
|
|
2188
|
+
const response = await getCountryStates(
|
|
2189
|
+
country.iso3,
|
|
2190
|
+
environment,
|
|
2191
|
+
secretKey
|
|
2192
|
+
);
|
|
2193
|
+
if (response?.isSuccessful) {
|
|
2194
|
+
setCountryStates(
|
|
2195
|
+
(response.data ?? []).map((s) => ({
|
|
2196
|
+
label: s.name,
|
|
2197
|
+
value: s.name
|
|
2198
|
+
}))
|
|
2199
|
+
);
|
|
2200
|
+
}
|
|
2201
|
+
} catch (e) {
|
|
2202
|
+
setMessage(e?.message || "Failed to get country states");
|
|
2203
|
+
onError?.({
|
|
2204
|
+
errorMessage: message
|
|
2205
|
+
});
|
|
2206
|
+
} finally {
|
|
2207
|
+
setLoadingStates(false);
|
|
2208
|
+
}
|
|
2209
|
+
};
|
|
2210
|
+
const cardNumberInputHandler = (event) => {
|
|
2211
|
+
setCardType(cardTypeHandler(event));
|
|
2212
|
+
payRules.cardPin = cardType === "Verve" ? "required|numeric" : "";
|
|
2213
|
+
};
|
|
2214
|
+
useEffect3(() => {
|
|
2215
|
+
(async () => {
|
|
2216
|
+
await generatePaymentLinkHandler();
|
|
2217
|
+
await getAllCountries();
|
|
2218
|
+
})();
|
|
2219
|
+
}, []);
|
|
2220
|
+
return /* @__PURE__ */ jsxs17("div", { className: "flex flex-col gap-6", children: [
|
|
2221
|
+
formIndex === 0 && /* @__PURE__ */ jsxs17("div", { className: "grid grid-cols-2 gap-6 overflow-y-auto", children: [
|
|
2222
|
+
/* @__PURE__ */ jsx27("div", { className: "col-span-2", children: /* @__PURE__ */ jsx27(
|
|
2223
|
+
BaseInput,
|
|
2224
|
+
{
|
|
2225
|
+
label: "Address Line 1",
|
|
2226
|
+
required: true,
|
|
2227
|
+
value: billingForm.address1,
|
|
2228
|
+
onChange: (e) => {
|
|
2229
|
+
setBillingForm({ ...billingForm, address1: e });
|
|
2230
|
+
if (billingErrors.address1) {
|
|
2231
|
+
setBillingErrors((er) => ({ ...er, address1: "" }));
|
|
2232
|
+
}
|
|
2233
|
+
},
|
|
2234
|
+
validationError: billingErrors.address1 ?? ""
|
|
2235
|
+
}
|
|
2236
|
+
) }),
|
|
2237
|
+
/* @__PURE__ */ jsx27("div", { className: "col-span-2", children: /* @__PURE__ */ jsx27(
|
|
2238
|
+
BaseInput,
|
|
2239
|
+
{
|
|
2240
|
+
label: "Address Line 2",
|
|
2241
|
+
value: billingForm.address2,
|
|
2242
|
+
onChange: (e) => setBillingForm({ ...billingForm, address2: e }),
|
|
2243
|
+
validationError: billingErrors.address2 ?? ""
|
|
2244
|
+
}
|
|
2245
|
+
) }),
|
|
1429
2246
|
/* @__PURE__ */ jsx27(
|
|
1430
2247
|
BaseSelect,
|
|
1431
2248
|
{
|
|
1432
2249
|
label: "Select Country",
|
|
1433
2250
|
required: true,
|
|
1434
|
-
options:
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
2251
|
+
options: countries,
|
|
2252
|
+
loading: loadingCountries,
|
|
2253
|
+
value: billingForm.country,
|
|
2254
|
+
onChange: (e) => {
|
|
2255
|
+
setBillingForm({ ...billingForm, country: e, state: "" });
|
|
2256
|
+
getStates(e);
|
|
2257
|
+
if (billingErrors.country) {
|
|
2258
|
+
setBillingErrors((er) => ({ ...er, country: "" }));
|
|
2259
|
+
}
|
|
2260
|
+
},
|
|
2261
|
+
validationError: billingErrors.country ?? ""
|
|
1439
2262
|
}
|
|
1440
2263
|
),
|
|
1441
2264
|
/* @__PURE__ */ jsx27(
|
|
@@ -1443,158 +2266,729 @@ function PayByCard({}) {
|
|
|
1443
2266
|
{
|
|
1444
2267
|
label: "Select State",
|
|
1445
2268
|
required: true,
|
|
1446
|
-
options:
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
2269
|
+
options: countryStates,
|
|
2270
|
+
loading: loadingStates,
|
|
2271
|
+
value: billingForm.state,
|
|
2272
|
+
onChange: (e) => {
|
|
2273
|
+
setBillingForm({ ...billingForm, state: e });
|
|
2274
|
+
if (billingErrors.state) {
|
|
2275
|
+
setBillingErrors((er) => ({ ...er, state: "" }));
|
|
2276
|
+
}
|
|
2277
|
+
},
|
|
2278
|
+
validationError: billingErrors.state ?? ""
|
|
2279
|
+
}
|
|
2280
|
+
),
|
|
2281
|
+
/* @__PURE__ */ jsx27(
|
|
2282
|
+
BaseInput,
|
|
2283
|
+
{
|
|
2284
|
+
label: "City",
|
|
2285
|
+
required: true,
|
|
2286
|
+
value: billingForm.city,
|
|
2287
|
+
onChange: (e) => {
|
|
2288
|
+
setBillingForm({ ...billingForm, city: e });
|
|
2289
|
+
if (billingErrors.city) {
|
|
2290
|
+
setBillingErrors((er) => ({ ...er, city: "" }));
|
|
2291
|
+
}
|
|
2292
|
+
},
|
|
2293
|
+
validationError: billingErrors.city ?? ""
|
|
2294
|
+
}
|
|
2295
|
+
),
|
|
2296
|
+
/* @__PURE__ */ jsx27(
|
|
2297
|
+
BaseInput,
|
|
2298
|
+
{
|
|
2299
|
+
label: "Postal Code",
|
|
2300
|
+
required: true,
|
|
2301
|
+
value: billingForm.postalCode,
|
|
2302
|
+
onChange: (e) => {
|
|
2303
|
+
setBillingForm({ ...billingForm, postalCode: e });
|
|
2304
|
+
if (billingErrors.postalCode) {
|
|
2305
|
+
setBillingErrors((er) => ({ ...er, postalCode: "" }));
|
|
2306
|
+
}
|
|
2307
|
+
},
|
|
2308
|
+
validationError: billingErrors.postalCode ?? ""
|
|
1451
2309
|
}
|
|
1452
2310
|
),
|
|
1453
|
-
/* @__PURE__ */ jsx27(
|
|
1454
|
-
|
|
1455
|
-
|
|
2311
|
+
/* @__PURE__ */ jsx27(
|
|
2312
|
+
BaseInput,
|
|
2313
|
+
{
|
|
2314
|
+
label: "Email",
|
|
2315
|
+
required: true,
|
|
2316
|
+
value: billingForm.emailAddress,
|
|
2317
|
+
onChange: (e) => {
|
|
2318
|
+
setBillingForm({ ...billingForm, emailAddress: e });
|
|
2319
|
+
if (billingErrors.emailAddress) {
|
|
2320
|
+
setBillingErrors((er) => ({ ...er, emailAddress: "" }));
|
|
2321
|
+
}
|
|
2322
|
+
},
|
|
2323
|
+
validationError: billingErrors.emailAddress ?? ""
|
|
2324
|
+
}
|
|
2325
|
+
),
|
|
2326
|
+
/* @__PURE__ */ jsx27(
|
|
2327
|
+
BaseInput,
|
|
2328
|
+
{
|
|
2329
|
+
label: "Phone Number",
|
|
2330
|
+
required: true,
|
|
2331
|
+
value: billingForm.phoneNumber,
|
|
2332
|
+
onChange: (e) => {
|
|
2333
|
+
setBillingForm({ ...billingForm, phoneNumber: e });
|
|
2334
|
+
if (billingErrors.phoneNumber) {
|
|
2335
|
+
setBillingErrors((er) => ({ ...er, phoneNumber: "" }));
|
|
2336
|
+
}
|
|
2337
|
+
},
|
|
2338
|
+
validationError: billingErrors.phoneNumber ?? ""
|
|
2339
|
+
}
|
|
2340
|
+
)
|
|
1456
2341
|
] }),
|
|
1457
|
-
formIndex === 1 && /* @__PURE__ */
|
|
2342
|
+
formIndex === 1 && /* @__PURE__ */ jsxs17(
|
|
1458
2343
|
"div",
|
|
1459
2344
|
{
|
|
1460
2345
|
className: "grid grid-cols-2 gap-6 overflow-y-auto",
|
|
1461
|
-
style: { maxHeight:
|
|
2346
|
+
style: { maxHeight: 320 },
|
|
1462
2347
|
children: [
|
|
1463
|
-
/* @__PURE__ */ jsx27("div", { className: "col-span-2", children: /* @__PURE__ */ jsx27(
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
2348
|
+
/* @__PURE__ */ jsx27("div", { className: "col-span-2", children: /* @__PURE__ */ jsx27(
|
|
2349
|
+
BaseInput,
|
|
2350
|
+
{
|
|
2351
|
+
label: "Card Name",
|
|
2352
|
+
required: true,
|
|
2353
|
+
value: payForm.customerName,
|
|
2354
|
+
onChange: (e) => {
|
|
2355
|
+
setPayForm({ ...payForm, customerName: e });
|
|
2356
|
+
if (payErrors.customerName) {
|
|
2357
|
+
setPayErrors((er) => ({ ...er, customerName: "" }));
|
|
2358
|
+
}
|
|
2359
|
+
},
|
|
2360
|
+
validationError: payErrors.customerName ?? ""
|
|
2361
|
+
}
|
|
2362
|
+
) }),
|
|
2363
|
+
/* @__PURE__ */ jsx27("div", { className: "col-span-2", children: /* @__PURE__ */ jsx27(
|
|
2364
|
+
BaseInput,
|
|
2365
|
+
{
|
|
2366
|
+
label: "Card Number",
|
|
2367
|
+
required: true,
|
|
2368
|
+
rules: ["numeric"],
|
|
2369
|
+
mask: "0000 0000 0000 0000",
|
|
2370
|
+
placeholder: "0000 0000 0000 0000",
|
|
2371
|
+
value: payForm.cardNo,
|
|
2372
|
+
preventPaste: true,
|
|
2373
|
+
onChange: (e) => {
|
|
2374
|
+
setPayForm({ ...payForm, cardNo: e });
|
|
2375
|
+
if (payErrors.cardNo)
|
|
2376
|
+
setPayErrors((er) => ({ ...er, cardNo: "" }));
|
|
2377
|
+
cardNumberInputHandler(e);
|
|
2378
|
+
},
|
|
2379
|
+
validationError: payErrors.cardNo ?? ""
|
|
2380
|
+
}
|
|
2381
|
+
) }),
|
|
2382
|
+
/* @__PURE__ */ jsx27(
|
|
2383
|
+
BaseInput,
|
|
2384
|
+
{
|
|
2385
|
+
label: "Expiry Date",
|
|
2386
|
+
required: true,
|
|
2387
|
+
value: payForm.expireDate,
|
|
2388
|
+
mask: "00/00",
|
|
2389
|
+
placeholder: "00/00",
|
|
2390
|
+
onChange: (e) => {
|
|
2391
|
+
setPayForm({ ...payForm, expireDate: e });
|
|
2392
|
+
if (payErrors.expireDate)
|
|
2393
|
+
setPayErrors((er) => ({ ...er, expireDate: "" }));
|
|
2394
|
+
},
|
|
2395
|
+
validationError: payErrors.expireDate ?? ""
|
|
2396
|
+
}
|
|
2397
|
+
),
|
|
2398
|
+
/* @__PURE__ */ jsx27(
|
|
2399
|
+
BaseInput,
|
|
2400
|
+
{
|
|
2401
|
+
label: "CVV",
|
|
2402
|
+
required: true,
|
|
2403
|
+
rules: ["numeric"],
|
|
2404
|
+
value: payForm.cvv,
|
|
2405
|
+
mask: "000",
|
|
2406
|
+
placeholder: "000",
|
|
2407
|
+
onChange: (e) => {
|
|
2408
|
+
setPayForm({ ...payForm, cvv: e });
|
|
2409
|
+
if (payErrors.cvv) setPayErrors((er) => ({ ...er, cvv: "" }));
|
|
2410
|
+
},
|
|
2411
|
+
validationError: payErrors.cvv ?? ""
|
|
2412
|
+
}
|
|
2413
|
+
),
|
|
2414
|
+
cardType === "Verve" && /* @__PURE__ */ jsx27(
|
|
2415
|
+
BaseInput,
|
|
2416
|
+
{
|
|
2417
|
+
label: "Card Pin",
|
|
2418
|
+
required: true,
|
|
2419
|
+
rules: ["numeric"],
|
|
2420
|
+
value: payForm.cardPin,
|
|
2421
|
+
mask: "0000",
|
|
2422
|
+
placeholder: "0000",
|
|
2423
|
+
onChange: (e) => {
|
|
2424
|
+
setPayForm({ ...payForm, cardPin: e });
|
|
2425
|
+
if (payErrors.cardPin)
|
|
2426
|
+
setPayErrors((er) => ({ ...er, cardPin: "" }));
|
|
2427
|
+
},
|
|
2428
|
+
validationError: payErrors.cardPin ?? ""
|
|
2429
|
+
}
|
|
2430
|
+
)
|
|
1467
2431
|
]
|
|
1468
2432
|
}
|
|
1469
2433
|
),
|
|
1470
2434
|
/* @__PURE__ */ jsx27(
|
|
1471
2435
|
BaseButton,
|
|
1472
2436
|
{
|
|
1473
|
-
label: formIndex === 0 ? "Proceed" :
|
|
2437
|
+
label: formIndex === 0 ? "Proceed" : `Pay ${formatAmountHandler}`,
|
|
1474
2438
|
type: "primary",
|
|
1475
2439
|
customClass: "w-full",
|
|
1476
|
-
|
|
2440
|
+
loading: isMakingPayment,
|
|
2441
|
+
onClick: proceedHandler,
|
|
2442
|
+
disabled: isMakingPayment
|
|
1477
2443
|
}
|
|
1478
2444
|
)
|
|
1479
2445
|
] });
|
|
1480
2446
|
}
|
|
1481
2447
|
|
|
1482
2448
|
// src/components/pay-by-transfer.tsx
|
|
1483
|
-
import {
|
|
1484
|
-
|
|
2449
|
+
import {
|
|
2450
|
+
useCallback as useCallback3,
|
|
2451
|
+
useEffect as useEffect4,
|
|
2452
|
+
useRef as useRef2,
|
|
2453
|
+
useState as useState5
|
|
2454
|
+
} from "react";
|
|
2455
|
+
import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1485
2456
|
var PayByTransfer = ({
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
2457
|
+
secretKey,
|
|
2458
|
+
paymentObject,
|
|
2459
|
+
environment = "sandbox",
|
|
2460
|
+
onPaymentAuthorized,
|
|
2461
|
+
onCancel,
|
|
2462
|
+
onError
|
|
1492
2463
|
}) => {
|
|
1493
|
-
const [
|
|
2464
|
+
const [formIndex, setFormIndex] = useState5(0);
|
|
2465
|
+
const [isMakingPayment, setIsMakingPayment] = useState5(false);
|
|
2466
|
+
const [isConfirmCall, setIsConfirmCall] = useState5(false);
|
|
2467
|
+
const [isPaymentConfirmed, setIsPaymentConfirmed] = useState5(false);
|
|
2468
|
+
const [transactionReference, setTransactionReference] = useState5("");
|
|
2469
|
+
const [paymentReferenceStatus, setPaymentReferenceStatus] = useState5("");
|
|
2470
|
+
const [isFetchingPaymentDetails, setIsFetchingPaymentDetails] = useState5(false);
|
|
2471
|
+
const [paymentReferenceDetails, setPaymentReferenceDetails] = useState5(null);
|
|
2472
|
+
const [paymentAccountDetails, setPaymentAccountDetails] = useState5(null);
|
|
2473
|
+
const [paymentMade, setPaymentMade] = useState5(false);
|
|
2474
|
+
const [loading, setLoading] = useState5(false);
|
|
2475
|
+
const [message, setMessage] = useState5("");
|
|
2476
|
+
const [remainingSeconds, setRemainingSeconds] = useState5(60);
|
|
2477
|
+
const [countDownTime, setCountDownTime] = useState5("00:00");
|
|
1494
2478
|
const intervalRef = useRef2(null);
|
|
1495
|
-
const
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
2479
|
+
const [transferForm, setTransferForm] = useState5({
|
|
2480
|
+
customerName: ""
|
|
2481
|
+
});
|
|
2482
|
+
const [transferErrors, setTransferErrors] = useState5(
|
|
2483
|
+
{}
|
|
2484
|
+
);
|
|
2485
|
+
const transferRules = {
|
|
2486
|
+
customerName: "required"
|
|
2487
|
+
};
|
|
2488
|
+
const transferLabels = {
|
|
2489
|
+
customerName: "Customer Name"
|
|
2490
|
+
};
|
|
2491
|
+
const formatAmountHandler = formatAmount(
|
|
2492
|
+
paymentObject.amount,
|
|
2493
|
+
paymentObject.currency
|
|
2494
|
+
);
|
|
2495
|
+
const payHandler = async () => {
|
|
2496
|
+
if (formIndex === 0) {
|
|
2497
|
+
const errs = validateGroup(transferForm, transferRules, transferLabels);
|
|
2498
|
+
setTransferErrors(errs);
|
|
2499
|
+
if (Object.keys(errs).length === 0) {
|
|
2500
|
+
const payload = {
|
|
2501
|
+
paymentReference: transactionReference,
|
|
2502
|
+
channel: "virtual_account",
|
|
2503
|
+
customerName: transferForm.customerName ?? "",
|
|
2504
|
+
merchantId: secretKey
|
|
2505
|
+
};
|
|
2506
|
+
setIsMakingPayment(true);
|
|
2507
|
+
try {
|
|
2508
|
+
const response = await generatePaymentAccount(environment, payload);
|
|
2509
|
+
if (response?.isSuccessful) {
|
|
2510
|
+
setPaymentAccountDetails(response.data);
|
|
2511
|
+
startTimer();
|
|
2512
|
+
setMessage("Virtual account generated successfully for payment.");
|
|
2513
|
+
setIsMakingPayment(true);
|
|
2514
|
+
setFormIndex(1);
|
|
2515
|
+
}
|
|
2516
|
+
} catch (err) {
|
|
2517
|
+
setIsMakingPayment(false);
|
|
2518
|
+
setMessage(err.error.responseMessage || err.error.message);
|
|
2519
|
+
onError?.({
|
|
2520
|
+
errorMessage: message
|
|
2521
|
+
});
|
|
2522
|
+
}
|
|
1509
2523
|
}
|
|
1510
|
-
|
|
2524
|
+
return;
|
|
2525
|
+
}
|
|
2526
|
+
};
|
|
2527
|
+
const getReferenceDetails = async () => {
|
|
2528
|
+
setIsFetchingPaymentDetails(true);
|
|
2529
|
+
try {
|
|
2530
|
+
const response = await getPaymentReferenceDetails(
|
|
2531
|
+
environment,
|
|
2532
|
+
transactionReference
|
|
2533
|
+
);
|
|
2534
|
+
if (response?.isSuccessful) {
|
|
2535
|
+
setPaymentReferenceDetails(response.data);
|
|
2536
|
+
const made = response.data?.paymentStatus === "Payment Received";
|
|
2537
|
+
setPaymentMade(made);
|
|
2538
|
+
const noServerStatus = response.data?.finalTransactionStatus == null || response.data?.paymentStatus == null;
|
|
2539
|
+
if (noServerStatus) {
|
|
2540
|
+
if (isConfirmCall) {
|
|
2541
|
+
setMessage("Transaction not confirmed !!");
|
|
2542
|
+
}
|
|
2543
|
+
if (!isPaymentConfirmed && !made) {
|
|
2544
|
+
setPaymentReferenceStatus("pending");
|
|
2545
|
+
onPaymentAuthorized?.({
|
|
2546
|
+
paymentId: transactionReference,
|
|
2547
|
+
paymentDate: response.data?.updatedAt,
|
|
2548
|
+
paymentStatus: "pending",
|
|
2549
|
+
message
|
|
2550
|
+
});
|
|
2551
|
+
} else {
|
|
2552
|
+
setPaymentReferenceStatus("confirmed");
|
|
2553
|
+
onPaymentAuthorized?.({
|
|
2554
|
+
paymentId: transactionReference,
|
|
2555
|
+
paymentDate: response.data?.updatedAt,
|
|
2556
|
+
paymentStatus: "confirmed",
|
|
2557
|
+
message
|
|
2558
|
+
});
|
|
2559
|
+
}
|
|
2560
|
+
} else if (response.data?.finalTransactionStatus === "Success" || response.data?.paymentStatus === "Received" || response.data?.paymentStatus === "Payment Received") {
|
|
2561
|
+
setPaymentReferenceStatus("confirmed");
|
|
2562
|
+
setIsPaymentConfirmed(true);
|
|
2563
|
+
setMessage("Transaction confirmed !!");
|
|
2564
|
+
onPaymentAuthorized?.({
|
|
2565
|
+
paymentId: transactionReference,
|
|
2566
|
+
paymentDate: response.data?.updatedAt,
|
|
2567
|
+
paymentStatus: "confirmed",
|
|
2568
|
+
message
|
|
2569
|
+
});
|
|
2570
|
+
}
|
|
2571
|
+
} else if (!response?.isSuccessful && response?.responseCode === "119") {
|
|
2572
|
+
setPaymentReferenceStatus("used");
|
|
2573
|
+
setMessage(response.responseMessage || "");
|
|
2574
|
+
onPaymentAuthorized?.({
|
|
2575
|
+
paymentId: transactionReference,
|
|
2576
|
+
paymentDate: null,
|
|
2577
|
+
paymentStatus: "used",
|
|
2578
|
+
message
|
|
2579
|
+
});
|
|
2580
|
+
}
|
|
2581
|
+
} catch (err) {
|
|
2582
|
+
setPaymentReferenceStatus("");
|
|
2583
|
+
setMessage(
|
|
2584
|
+
err?.error?.responseMessage || err?.error?.message || "Something went wrong"
|
|
2585
|
+
);
|
|
2586
|
+
onError?.({
|
|
2587
|
+
errorMessage: message
|
|
2588
|
+
});
|
|
2589
|
+
} finally {
|
|
2590
|
+
setIsFetchingPaymentDetails(false);
|
|
2591
|
+
}
|
|
2592
|
+
};
|
|
2593
|
+
const generatePaymentLinkHandler = async () => {
|
|
2594
|
+
if (!secretKey) {
|
|
2595
|
+
setMessage("Secret key is required.");
|
|
2596
|
+
return;
|
|
2597
|
+
}
|
|
2598
|
+
if (!checkObjectTruthy(paymentObject)) {
|
|
2599
|
+
setMessage("Kindly ensure you are passing all the required data.");
|
|
2600
|
+
return;
|
|
2601
|
+
}
|
|
2602
|
+
setLoading(true);
|
|
2603
|
+
setMessage("");
|
|
2604
|
+
try {
|
|
2605
|
+
const response = await createPaymentLink(
|
|
2606
|
+
paymentObject,
|
|
2607
|
+
environment,
|
|
2608
|
+
secretKey
|
|
2609
|
+
);
|
|
2610
|
+
if (response?.isSuccessful && response.launchUrl) {
|
|
2611
|
+
const queryParams = getQueryParams(response.launchUrl);
|
|
2612
|
+
setTransactionReference(queryParams["paymentReference"]);
|
|
2613
|
+
setMessage("Payment link created successfully");
|
|
2614
|
+
} else {
|
|
2615
|
+
setMessage("Failed to create payment link");
|
|
2616
|
+
}
|
|
2617
|
+
} catch (e) {
|
|
2618
|
+
setMessage(e?.message || "Failed to create payment link");
|
|
2619
|
+
onError?.({
|
|
2620
|
+
errorMessage: message
|
|
2621
|
+
});
|
|
2622
|
+
} finally {
|
|
2623
|
+
setLoading(false);
|
|
2624
|
+
}
|
|
2625
|
+
};
|
|
2626
|
+
const updateDisplay = useCallback3((secs) => {
|
|
2627
|
+
const minutes = String(Math.floor(secs / 60)).padStart(2, "0");
|
|
2628
|
+
const seconds = String(secs % 60).padStart(2, "0");
|
|
2629
|
+
setCountDownTime(`${minutes}:${seconds}`);
|
|
1511
2630
|
}, []);
|
|
1512
|
-
|
|
1513
|
-
if (
|
|
2631
|
+
const startTimer = useCallback3(() => {
|
|
2632
|
+
if (intervalRef.current) {
|
|
2633
|
+
clearInterval(intervalRef.current);
|
|
2634
|
+
intervalRef.current = null;
|
|
2635
|
+
}
|
|
2636
|
+
updateDisplay(remainingSeconds);
|
|
2637
|
+
intervalRef.current = setInterval(() => {
|
|
2638
|
+
setRemainingSeconds((prev) => {
|
|
2639
|
+
const next = prev - 1;
|
|
2640
|
+
if (next < 0) {
|
|
2641
|
+
if (intervalRef.current) {
|
|
2642
|
+
clearInterval(intervalRef.current);
|
|
2643
|
+
intervalRef.current = null;
|
|
2644
|
+
}
|
|
2645
|
+
setCountDownTime("00:00");
|
|
2646
|
+
return 0;
|
|
2647
|
+
}
|
|
2648
|
+
updateDisplay(next);
|
|
2649
|
+
return next;
|
|
2650
|
+
});
|
|
2651
|
+
}, 1e3);
|
|
2652
|
+
}, [remainingSeconds, updateDisplay]);
|
|
2653
|
+
const stopTimer = () => {
|
|
2654
|
+
if (intervalRef.current) {
|
|
1514
2655
|
clearInterval(intervalRef.current);
|
|
1515
2656
|
intervalRef.current = null;
|
|
1516
2657
|
}
|
|
1517
|
-
}
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
2658
|
+
};
|
|
2659
|
+
useEffect4(() => {
|
|
2660
|
+
(async () => {
|
|
2661
|
+
await generatePaymentLinkHandler();
|
|
2662
|
+
})();
|
|
2663
|
+
}, []);
|
|
2664
|
+
useEffect4(() => {
|
|
2665
|
+
if (remainingSeconds < 0 && intervalRef.current) {
|
|
2666
|
+
stopTimer();
|
|
2667
|
+
}
|
|
2668
|
+
}, [remainingSeconds]);
|
|
2669
|
+
return /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-10", children: [
|
|
2670
|
+
formIndex === 0 && /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-10", children: [
|
|
2671
|
+
/* @__PURE__ */ jsx28(
|
|
2672
|
+
BaseInput,
|
|
2673
|
+
{
|
|
2674
|
+
label: "Customer Name",
|
|
2675
|
+
required: true,
|
|
2676
|
+
value: transferForm.customerName,
|
|
2677
|
+
onChange: (e) => {
|
|
2678
|
+
setTransferForm({ ...transferForm, customerName: e });
|
|
2679
|
+
if (transferForm.customerName) {
|
|
2680
|
+
setTransferErrors((er) => ({ ...er, customerName: "" }));
|
|
2681
|
+
}
|
|
2682
|
+
},
|
|
2683
|
+
validationError: transferErrors.customerName ?? ""
|
|
2684
|
+
}
|
|
2685
|
+
),
|
|
2686
|
+
/* @__PURE__ */ jsx28(
|
|
2687
|
+
BaseButton,
|
|
2688
|
+
{
|
|
2689
|
+
label: `Pay ${formatAmountHandler}`,
|
|
2690
|
+
type: "primary",
|
|
2691
|
+
customClass: "w-full",
|
|
2692
|
+
loading: isMakingPayment,
|
|
2693
|
+
onClick: payHandler
|
|
2694
|
+
}
|
|
2695
|
+
)
|
|
1522
2696
|
] }),
|
|
1523
|
-
/* @__PURE__ */
|
|
1524
|
-
/* @__PURE__ */
|
|
1525
|
-
/* @__PURE__ */ jsxs17("div", { className: "flex items-center justify-between", children: [
|
|
2697
|
+
formIndex === 1 && /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-10", children: [
|
|
2698
|
+
/* @__PURE__ */ jsxs18("div", { className: "bg-[#EFF7FF] p-4 rounded-lg flex flex-col gap-6", children: [
|
|
1526
2699
|
/* @__PURE__ */ jsx28(
|
|
1527
2700
|
BaseLabelInfo,
|
|
1528
2701
|
{
|
|
1529
|
-
label: "
|
|
1530
|
-
value:
|
|
1531
|
-
type: "horizontal"
|
|
2702
|
+
label: "Bank Name",
|
|
2703
|
+
value: `${paymentAccountDetails?.bank} ${paymentAccountDetails?.accountName}`
|
|
1532
2704
|
}
|
|
1533
2705
|
),
|
|
1534
|
-
/* @__PURE__ */
|
|
2706
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center justify-between", children: [
|
|
2707
|
+
/* @__PURE__ */ jsx28(
|
|
2708
|
+
BaseLabelInfo,
|
|
2709
|
+
{
|
|
2710
|
+
label: "Account Number",
|
|
2711
|
+
value: paymentAccountDetails?.accountNumber
|
|
2712
|
+
}
|
|
2713
|
+
),
|
|
2714
|
+
/* @__PURE__ */ jsx28(
|
|
2715
|
+
BaseCopy,
|
|
2716
|
+
{
|
|
2717
|
+
color: "#9DBFDE",
|
|
2718
|
+
copyText: paymentAccountDetails?.accountNumber ?? ""
|
|
2719
|
+
}
|
|
2720
|
+
)
|
|
2721
|
+
] }),
|
|
2722
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center justify-between", children: [
|
|
2723
|
+
/* @__PURE__ */ jsx28(BaseLabelInfo, { label: "Amount", value: formatAmountHandler }),
|
|
2724
|
+
/* @__PURE__ */ jsx28(BaseCopy, { color: "#9DBFDE", copyText: formatAmountHandler })
|
|
2725
|
+
] })
|
|
2726
|
+
] }),
|
|
2727
|
+
/* @__PURE__ */ jsxs18("p", { className: "w-2/3 mx-auto text-center text-body-2xs font-medium text-sub-copy", children: [
|
|
2728
|
+
"This account is for this transaction only and expires in",
|
|
2729
|
+
" ",
|
|
2730
|
+
/* @__PURE__ */ jsx28("span", { className: "text-orange-500", children: remainingSeconds >= 0 ? countDownTime : "00:00" })
|
|
1535
2731
|
] }),
|
|
1536
|
-
/* @__PURE__ */
|
|
2732
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-4", children: [
|
|
1537
2733
|
/* @__PURE__ */ jsx28(
|
|
1538
|
-
|
|
2734
|
+
BaseButton,
|
|
1539
2735
|
{
|
|
1540
|
-
label: "
|
|
1541
|
-
|
|
1542
|
-
|
|
2736
|
+
label: "I have paid the money",
|
|
2737
|
+
type: "primary",
|
|
2738
|
+
customClass: "w-full",
|
|
2739
|
+
loading: isFetchingPaymentDetails,
|
|
2740
|
+
onClick: getReferenceDetails
|
|
1543
2741
|
}
|
|
1544
2742
|
),
|
|
1545
|
-
/* @__PURE__ */ jsx28(
|
|
2743
|
+
/* @__PURE__ */ jsx28(
|
|
2744
|
+
"button",
|
|
2745
|
+
{
|
|
2746
|
+
type: "button",
|
|
2747
|
+
onClick: onCancel,
|
|
2748
|
+
className: "text-heading-text text-body-2xs font-medium text-center py-2 cursor-pointer",
|
|
2749
|
+
children: "Cancel Payment"
|
|
2750
|
+
}
|
|
2751
|
+
)
|
|
1546
2752
|
] })
|
|
1547
|
-
] }),
|
|
1548
|
-
/* @__PURE__ */ jsxs17("p", { className: "w-2/3 mx-auto text-center text-body-2xs font-medium text-sub-copy", children: [
|
|
1549
|
-
"This account is for this transaction only and expires in",
|
|
1550
|
-
" ",
|
|
1551
|
-
/* @__PURE__ */ jsx28("span", { className: "text-orange-500", children: remaining >= 0 ? countDownTime : "00:00" })
|
|
1552
|
-
] }),
|
|
1553
|
-
/* @__PURE__ */ jsxs17("div", { className: "flex flex-col gap-4", children: [
|
|
1554
|
-
/* @__PURE__ */ jsx28(
|
|
1555
|
-
BaseButton,
|
|
1556
|
-
{
|
|
1557
|
-
label: "I have paid the money",
|
|
1558
|
-
type: "primary",
|
|
1559
|
-
customClass: "w-full",
|
|
1560
|
-
onClick: onConfirmPaid
|
|
1561
|
-
}
|
|
1562
|
-
),
|
|
1563
|
-
/* @__PURE__ */ jsx28(
|
|
1564
|
-
"button",
|
|
1565
|
-
{
|
|
1566
|
-
type: "button",
|
|
1567
|
-
onClick: onCancel,
|
|
1568
|
-
className: "text-heading-text text-body-2xs font-medium text-center py-2 cursor-pointer",
|
|
1569
|
-
children: "Cancel Payment"
|
|
1570
|
-
}
|
|
1571
|
-
)
|
|
1572
2753
|
] })
|
|
1573
2754
|
] });
|
|
1574
2755
|
};
|
|
1575
2756
|
|
|
1576
2757
|
// src/components/pay-by-stable-coin.tsx
|
|
1577
|
-
import { useState as useState6 } from "react";
|
|
1578
|
-
import { Fragment as Fragment3, jsx as jsx29, jsxs as
|
|
1579
|
-
var PayByStableCoin = ({
|
|
2758
|
+
import { useEffect as useEffect5, useState as useState6 } from "react";
|
|
2759
|
+
import { Fragment as Fragment3, jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
2760
|
+
var PayByStableCoin = ({
|
|
2761
|
+
secretKey,
|
|
2762
|
+
paymentObject,
|
|
2763
|
+
environment = "sandbox",
|
|
2764
|
+
onPaymentAuthorized,
|
|
2765
|
+
onError
|
|
2766
|
+
}) => {
|
|
1580
2767
|
const [formIndex, setFormIndex] = useState6(0);
|
|
1581
|
-
const
|
|
1582
|
-
|
|
1583
|
-
|
|
2768
|
+
const [message, setMessage] = useState6("");
|
|
2769
|
+
const [loading, setLoading] = useState6(false);
|
|
2770
|
+
const [generatingAddress, setGeneratingAddress] = useState6(false);
|
|
2771
|
+
const [loadingStableCoins, setLoadingStableCoins] = useState6(false);
|
|
2772
|
+
const [loadingStableCoinNetworks, setLoadingStableCoinNetworks] = useState6(false);
|
|
2773
|
+
const [transactionReference, setTransactionReference] = useState6("");
|
|
2774
|
+
const [stableCoins, setStableCoins] = useState6([]);
|
|
2775
|
+
const [networkList, setNetworkList] = useState6([]);
|
|
2776
|
+
const [addressDetails, setAddressDetails] = useState6(null);
|
|
2777
|
+
const [generateAddressPayload, setGenerateAddressPayload] = useState6(null);
|
|
2778
|
+
const [isConfirmingPayment, setIsConfirmingPayment] = useState6(false);
|
|
2779
|
+
const [paymentReferenceDetails, setPaymentReferenceDetails] = useState6(null);
|
|
2780
|
+
const [paymentReferenceStatus, setPaymentReferenceStatus] = useState6("");
|
|
2781
|
+
const [stableCoinForm, setStableCoinForm] = useState6({
|
|
2782
|
+
stableCoin: "",
|
|
2783
|
+
network: ""
|
|
2784
|
+
});
|
|
2785
|
+
const [stableCoinErrors, setStableCoinErrors] = useState6({});
|
|
2786
|
+
const stableCoinRules = {
|
|
2787
|
+
stableCoin: "required",
|
|
2788
|
+
network: "required"
|
|
2789
|
+
};
|
|
2790
|
+
const stableCoinLabels = {
|
|
2791
|
+
stableCoin: "Stable Coin",
|
|
2792
|
+
network: "Network"
|
|
2793
|
+
};
|
|
2794
|
+
const generatePaymentLinkHandler = async () => {
|
|
2795
|
+
if (!secretKey) {
|
|
2796
|
+
setMessage("Secret key is required.");
|
|
2797
|
+
return;
|
|
2798
|
+
}
|
|
2799
|
+
if (!checkObjectTruthy(paymentObject)) {
|
|
2800
|
+
setMessage("Kindly ensure you are passing all the required data.");
|
|
2801
|
+
return;
|
|
2802
|
+
}
|
|
2803
|
+
setLoading(true);
|
|
2804
|
+
setMessage("");
|
|
2805
|
+
try {
|
|
2806
|
+
const response = await createPaymentLink(
|
|
2807
|
+
paymentObject,
|
|
2808
|
+
environment,
|
|
2809
|
+
secretKey
|
|
2810
|
+
);
|
|
2811
|
+
if (response?.isSuccessful && response.launchUrl) {
|
|
2812
|
+
const queryParams = getQueryParams(response.launchUrl);
|
|
2813
|
+
setTransactionReference(queryParams["paymentReference"]);
|
|
2814
|
+
setMessage("Payment link created successfully");
|
|
2815
|
+
} else {
|
|
2816
|
+
setMessage("Failed to create payment link");
|
|
2817
|
+
}
|
|
2818
|
+
} catch (e) {
|
|
2819
|
+
setMessage(e?.message || "Failed to create payment link");
|
|
2820
|
+
onError?.({
|
|
2821
|
+
errorMessage: message
|
|
2822
|
+
});
|
|
2823
|
+
} finally {
|
|
2824
|
+
setLoading(false);
|
|
2825
|
+
}
|
|
2826
|
+
};
|
|
2827
|
+
const generateAddress = async (payload) => {
|
|
2828
|
+
if (!payload) return;
|
|
2829
|
+
setGeneratingAddress(true);
|
|
2830
|
+
try {
|
|
2831
|
+
const response = await generateStableCoinAddress(
|
|
2832
|
+
environment,
|
|
2833
|
+
payload
|
|
2834
|
+
);
|
|
2835
|
+
if (response?.isSuccessful) {
|
|
2836
|
+
setAddressDetails(response.data);
|
|
2837
|
+
setFormIndex(1);
|
|
2838
|
+
}
|
|
2839
|
+
} catch (e) {
|
|
2840
|
+
setMessage(e?.message || "Failed to generate address");
|
|
2841
|
+
onError?.({
|
|
2842
|
+
errorMessage: message
|
|
2843
|
+
});
|
|
2844
|
+
} finally {
|
|
2845
|
+
setGeneratingAddress(false);
|
|
2846
|
+
}
|
|
2847
|
+
};
|
|
2848
|
+
const getAllStableCoins = async () => {
|
|
2849
|
+
setLoadingStableCoins(true);
|
|
2850
|
+
try {
|
|
2851
|
+
const response = await getStableCoins(environment);
|
|
2852
|
+
if (response?.isSuccessful) {
|
|
2853
|
+
setStableCoins(
|
|
2854
|
+
response.data?.map((c) => ({
|
|
2855
|
+
label: c.name,
|
|
2856
|
+
value: c.name
|
|
2857
|
+
})) ?? []
|
|
2858
|
+
);
|
|
2859
|
+
}
|
|
2860
|
+
} catch (e) {
|
|
2861
|
+
setMessage(e?.message || "Failed to get stable coins");
|
|
2862
|
+
onError?.({
|
|
2863
|
+
errorMessage: message
|
|
2864
|
+
});
|
|
2865
|
+
} finally {
|
|
2866
|
+
setLoadingStableCoins(false);
|
|
2867
|
+
}
|
|
2868
|
+
};
|
|
2869
|
+
const getAllStableCoinNetworks = async (stableCoin) => {
|
|
2870
|
+
setLoadingStableCoinNetworks(true);
|
|
2871
|
+
try {
|
|
2872
|
+
const response = await getStableCoinNetworks(
|
|
2873
|
+
environment,
|
|
2874
|
+
stableCoin
|
|
2875
|
+
);
|
|
2876
|
+
if (response?.isSuccessful) {
|
|
2877
|
+
setNetworkList(
|
|
2878
|
+
response.networks?.map((n) => ({
|
|
2879
|
+
label: n,
|
|
2880
|
+
value: n
|
|
2881
|
+
})) ?? []
|
|
2882
|
+
);
|
|
2883
|
+
}
|
|
2884
|
+
} catch (e) {
|
|
2885
|
+
setMessage(e?.message || "Failed to get stable coin networks");
|
|
2886
|
+
onError?.({
|
|
2887
|
+
errorMessage: message
|
|
2888
|
+
});
|
|
2889
|
+
} finally {
|
|
2890
|
+
setLoadingStableCoinNetworks(false);
|
|
2891
|
+
}
|
|
2892
|
+
};
|
|
2893
|
+
const confirmPaymentHandler = async () => {
|
|
2894
|
+
setIsConfirmingPayment(true);
|
|
2895
|
+
try {
|
|
2896
|
+
const response = await getPaymentReferenceDetails(environment, transactionReference);
|
|
2897
|
+
if (response?.isSuccessful) {
|
|
2898
|
+
setPaymentReferenceDetails(response.data);
|
|
2899
|
+
const needsConfirm = response.data?.finalTransactionStatus == null || response.data?.paymentStatus == null;
|
|
2900
|
+
if (needsConfirm) {
|
|
2901
|
+
setMessage("Transaction not confirmed !!");
|
|
2902
|
+
setPaymentReferenceStatus("pending");
|
|
2903
|
+
onPaymentAuthorized?.({
|
|
2904
|
+
paymentId: transactionReference,
|
|
2905
|
+
paymentDate: response.data?.updatedAt ?? "",
|
|
2906
|
+
paymentStatus: "pending",
|
|
2907
|
+
message
|
|
2908
|
+
});
|
|
2909
|
+
} else if (response.data?.finalTransactionStatus === "Success" || response.data?.paymentStatus === "Payment Received") {
|
|
2910
|
+
setMessage("Transaction confirmed !!");
|
|
2911
|
+
setPaymentReferenceStatus("confirmed");
|
|
2912
|
+
onPaymentAuthorized?.({
|
|
2913
|
+
paymentId: transactionReference,
|
|
2914
|
+
paymentDate: response.data?.updatedAt,
|
|
2915
|
+
paymentStatus: "confirmed",
|
|
2916
|
+
message
|
|
2917
|
+
});
|
|
2918
|
+
}
|
|
2919
|
+
} else if (!response?.isSuccessful && response?.responseCode === "119") {
|
|
2920
|
+
setPaymentReferenceStatus("used");
|
|
2921
|
+
setMessage(response.responseMessage || "");
|
|
2922
|
+
onPaymentAuthorized?.({
|
|
2923
|
+
paymentId: transactionReference,
|
|
2924
|
+
paymentDate: null,
|
|
2925
|
+
paymentStatus: "used",
|
|
2926
|
+
message
|
|
2927
|
+
});
|
|
2928
|
+
}
|
|
2929
|
+
} catch (err) {
|
|
2930
|
+
setPaymentReferenceStatus("");
|
|
2931
|
+
setMessage(
|
|
2932
|
+
err?.error?.responseMessage || err?.error?.message || "Something went wrong"
|
|
2933
|
+
);
|
|
2934
|
+
onError?.({
|
|
2935
|
+
errorMessage: message
|
|
2936
|
+
});
|
|
2937
|
+
} finally {
|
|
2938
|
+
setIsConfirmingPayment(false);
|
|
2939
|
+
}
|
|
2940
|
+
};
|
|
2941
|
+
const formatAmountHandler = formatAmount(
|
|
2942
|
+
paymentObject.amount,
|
|
2943
|
+
paymentObject.currency
|
|
2944
|
+
);
|
|
2945
|
+
const payHandler = async () => {
|
|
2946
|
+
const errs = validateGroup(
|
|
2947
|
+
stableCoinForm,
|
|
2948
|
+
stableCoinRules,
|
|
2949
|
+
stableCoinLabels
|
|
2950
|
+
);
|
|
2951
|
+
setStableCoinErrors(errs);
|
|
2952
|
+
if (Object.keys(errs).length === 0) {
|
|
2953
|
+
const payload = {
|
|
2954
|
+
paymentReference: transactionReference,
|
|
2955
|
+
currency: stableCoinForm.stableCoin,
|
|
2956
|
+
chain: stableCoinForm.network,
|
|
2957
|
+
transactionAmount: paymentObject.amount,
|
|
2958
|
+
merchantId: secretKey
|
|
2959
|
+
};
|
|
2960
|
+
setGenerateAddressPayload(payload);
|
|
2961
|
+
await generateAddress(payload);
|
|
2962
|
+
} else {
|
|
2963
|
+
return;
|
|
2964
|
+
}
|
|
1584
2965
|
};
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
2966
|
+
const amountPlusNetworkFee = addressDetails ? Number(addressDetails.transactionAmount) + addressDetails.networkFee : 0;
|
|
2967
|
+
useEffect5(() => {
|
|
2968
|
+
(async () => {
|
|
2969
|
+
await generatePaymentLinkHandler();
|
|
2970
|
+
await getAllStableCoins();
|
|
2971
|
+
})();
|
|
2972
|
+
}, []);
|
|
2973
|
+
return /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-6", children: [
|
|
2974
|
+
formIndex === 0 && /* @__PURE__ */ jsxs19(Fragment3, { children: [
|
|
2975
|
+
/* @__PURE__ */ jsxs19("div", { className: "grid grid-cols-1 gap-6", children: [
|
|
1588
2976
|
/* @__PURE__ */ jsx29(
|
|
1589
2977
|
BaseSelect,
|
|
1590
2978
|
{
|
|
1591
2979
|
label: "Select Crypto",
|
|
1592
2980
|
required: true,
|
|
1593
|
-
options:
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
2981
|
+
options: stableCoins,
|
|
2982
|
+
loading: loadingStableCoins,
|
|
2983
|
+
value: stableCoinForm.stableCoin,
|
|
2984
|
+
onChange: (e) => {
|
|
2985
|
+
setStableCoinForm({ ...stableCoinForm, stableCoin: e });
|
|
2986
|
+
getAllStableCoinNetworks(e);
|
|
2987
|
+
if (stableCoinErrors.stableCoin) {
|
|
2988
|
+
setStableCoinErrors((er) => ({ ...er, stableCoin: "" }));
|
|
2989
|
+
}
|
|
2990
|
+
},
|
|
2991
|
+
validationError: stableCoinErrors.stableCoin ?? ""
|
|
1598
2992
|
}
|
|
1599
2993
|
),
|
|
1600
2994
|
/* @__PURE__ */ jsx29(
|
|
@@ -1602,52 +2996,46 @@ var PayByStableCoin = ({ onProceedToPay }) => {
|
|
|
1602
2996
|
{
|
|
1603
2997
|
label: "Select Network",
|
|
1604
2998
|
required: true,
|
|
1605
|
-
options:
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
2999
|
+
options: networkList,
|
|
3000
|
+
loading: loadingStableCoinNetworks,
|
|
3001
|
+
value: stableCoinForm.network,
|
|
3002
|
+
onChange: (e) => {
|
|
3003
|
+
setStableCoinForm({ ...stableCoinForm, network: e });
|
|
3004
|
+
if (stableCoinErrors.network) {
|
|
3005
|
+
setStableCoinErrors((er) => ({ ...er, network: "" }));
|
|
3006
|
+
}
|
|
3007
|
+
},
|
|
3008
|
+
validationError: stableCoinErrors.network ?? ""
|
|
1610
3009
|
}
|
|
1611
3010
|
)
|
|
1612
3011
|
] }),
|
|
1613
3012
|
/* @__PURE__ */ jsx29(
|
|
1614
3013
|
BaseButton,
|
|
1615
3014
|
{
|
|
1616
|
-
label:
|
|
3015
|
+
label: `Pay ${formatAmountHandler}`,
|
|
1617
3016
|
type: "primary",
|
|
1618
3017
|
customClass: "w-full",
|
|
3018
|
+
loading: generatingAddress,
|
|
1619
3019
|
onClick: payHandler
|
|
1620
3020
|
}
|
|
1621
3021
|
)
|
|
1622
3022
|
] }),
|
|
1623
|
-
formIndex === 1 && /* @__PURE__ */
|
|
1624
|
-
/* @__PURE__ */
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
{
|
|
1628
|
-
src: "../../../assets/images/stable-coin-qr-code.png",
|
|
1629
|
-
alt: "QR Code",
|
|
1630
|
-
width: 122,
|
|
1631
|
-
height: 122,
|
|
1632
|
-
customClass: "mb-1"
|
|
1633
|
-
}
|
|
1634
|
-
),
|
|
1635
|
-
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-4xs text-light-copy font-normal text-center", children: "USDC" })
|
|
1636
|
-
] }),
|
|
1637
|
-
/* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-6 border-c border-grey-100 p-4 rounded-2xl bg-light-white-50", children: [
|
|
1638
|
-
/* @__PURE__ */ jsxs18("div", { className: "border-b border-grey-border pb-4 flex flex-col gap-2", children: [
|
|
3023
|
+
formIndex === 1 && /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-6", children: [
|
|
3024
|
+
/* @__PURE__ */ jsx29("div", { className: "mx-auto", children: /* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-4xs text-light-copy font-normal text-center", children: generateAddressPayload?.currency }) }),
|
|
3025
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-6 border-c border-grey-100 p-4 rounded-2xl bg-light-white-50", children: [
|
|
3026
|
+
/* @__PURE__ */ jsxs19("div", { className: "border-b border-grey-border pb-4 flex flex-col gap-2", children: [
|
|
1639
3027
|
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-3xs text-light-copy font-normal", children: "Network" }),
|
|
1640
|
-
/* @__PURE__ */
|
|
1641
|
-
/* @__PURE__ */
|
|
1642
|
-
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-2xs font-medium text-sub-copy", children:
|
|
1643
|
-
/* @__PURE__ */
|
|
3028
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex justify-between", children: [
|
|
3029
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-1", children: [
|
|
3030
|
+
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-2xs font-medium text-sub-copy", children: addressDetails?.chain }),
|
|
3031
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2", children: [
|
|
1644
3032
|
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-3xs text-light-copy font-normal", children: "*Est. arrival = 3 mins" }),
|
|
1645
3033
|
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-3xs text-light-copy font-normal", children: "|" }),
|
|
1646
3034
|
/* @__PURE__ */ jsx29(
|
|
1647
3035
|
BaseCurrencyAmount,
|
|
1648
3036
|
{
|
|
1649
|
-
currency: "
|
|
1650
|
-
amount:
|
|
3037
|
+
currency: generateAddressPayload?.currency ?? "",
|
|
3038
|
+
amount: addressDetails?.networkFee ?? 0,
|
|
1651
3039
|
textClass: "mb-0 text-body-3xs text-light-copy font-normal",
|
|
1652
3040
|
iconColorClass: "#557591",
|
|
1653
3041
|
iconWidth: 12,
|
|
@@ -1659,34 +3047,34 @@ var PayByStableCoin = ({ onProceedToPay }) => {
|
|
|
1659
3047
|
/* @__PURE__ */ jsx29(IconArrowSwap, {})
|
|
1660
3048
|
] })
|
|
1661
3049
|
] }),
|
|
1662
|
-
/* @__PURE__ */
|
|
3050
|
+
/* @__PURE__ */ jsxs19("div", { className: "pb-4 flex flex-col gap-2", children: [
|
|
1663
3051
|
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-3xs text-light-copy font-normal", children: "Deposit Address >" }),
|
|
1664
|
-
/* @__PURE__ */
|
|
1665
|
-
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-2xs font-medium text-sub-copy w-2/3 break-words", children:
|
|
1666
|
-
/* @__PURE__ */ jsx29(BaseCopy, { copyText: "
|
|
3052
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex justify-between", children: [
|
|
3053
|
+
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-2xs font-medium text-sub-copy w-2/3 break-words", children: addressDetails?.walletAddress }),
|
|
3054
|
+
/* @__PURE__ */ jsx29(BaseCopy, { copyText: addressDetails?.walletAddress ?? "" })
|
|
1667
3055
|
] })
|
|
1668
3056
|
] })
|
|
1669
3057
|
] }),
|
|
1670
|
-
/* @__PURE__ */
|
|
1671
|
-
/* @__PURE__ */
|
|
3058
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-2", children: [
|
|
3059
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-between border-b border-grey-border py-3", children: [
|
|
1672
3060
|
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-2xs font-medium text-primary-black", children: "Network fee" }),
|
|
1673
3061
|
/* @__PURE__ */ jsx29(
|
|
1674
3062
|
BaseCurrencyAmount,
|
|
1675
3063
|
{
|
|
1676
|
-
currency: "
|
|
1677
|
-
amount:
|
|
3064
|
+
currency: generateAddressPayload?.currency ?? "",
|
|
3065
|
+
amount: addressDetails?.networkFee ?? 0,
|
|
1678
3066
|
textClass: "mb-0 text-body-2xs font-extrabold text-primary-black",
|
|
1679
3067
|
iconColorClass: "#231F20"
|
|
1680
3068
|
}
|
|
1681
3069
|
)
|
|
1682
3070
|
] }),
|
|
1683
|
-
/* @__PURE__ */
|
|
3071
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-between py-4", children: [
|
|
1684
3072
|
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-lg font-semibold text-primary-black", children: "Pay" }),
|
|
1685
3073
|
/* @__PURE__ */ jsx29(
|
|
1686
3074
|
BaseCurrencyAmount,
|
|
1687
3075
|
{
|
|
1688
|
-
currency: "
|
|
1689
|
-
amount:
|
|
3076
|
+
currency: generateAddressPayload?.currency ?? "",
|
|
3077
|
+
amount: amountPlusNetworkFee,
|
|
1690
3078
|
textClass: "mb-0 text-body-lg font-extrabold text-primary-black",
|
|
1691
3079
|
iconColorClass: "#231F20",
|
|
1692
3080
|
iconWidth: 20,
|
|
@@ -1700,7 +3088,9 @@ var PayByStableCoin = ({ onProceedToPay }) => {
|
|
|
1700
3088
|
{
|
|
1701
3089
|
label: "Confirm Payment",
|
|
1702
3090
|
type: "primary",
|
|
1703
|
-
customClass: "w-full"
|
|
3091
|
+
customClass: "w-full",
|
|
3092
|
+
loading: isConfirmingPayment,
|
|
3093
|
+
onClick: confirmPaymentHandler
|
|
1704
3094
|
}
|
|
1705
3095
|
) })
|
|
1706
3096
|
] })
|
|
@@ -1708,97 +3098,159 @@ var PayByStableCoin = ({ onProceedToPay }) => {
|
|
|
1708
3098
|
};
|
|
1709
3099
|
|
|
1710
3100
|
// src/buzapay-checkout/checkout-card.tsx
|
|
1711
|
-
import { jsx as jsx30, jsxs as
|
|
3101
|
+
import { jsx as jsx30, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1712
3102
|
function BzpCheckoutCard({
|
|
3103
|
+
secretKey,
|
|
1713
3104
|
options,
|
|
1714
3105
|
environment = "sandbox",
|
|
1715
3106
|
paymentObject = {
|
|
3107
|
+
merchantName: "",
|
|
1716
3108
|
amount: 0,
|
|
1717
3109
|
currency: "",
|
|
1718
3110
|
email: "",
|
|
1719
3111
|
phoneNumber: "",
|
|
1720
3112
|
narration: "",
|
|
1721
|
-
redirectUrl: ""
|
|
1722
|
-
}
|
|
3113
|
+
redirectUrl: "https://sandbox-merchant.buzapay.com/account/three-ds-status"
|
|
3114
|
+
},
|
|
3115
|
+
onPaymentAuthorized,
|
|
3116
|
+
onError
|
|
1723
3117
|
}) {
|
|
1724
|
-
const [checkoutState, setCheckoutState] = useState7("
|
|
3118
|
+
const [checkoutState, setCheckoutState] = useState7("PENDING");
|
|
1725
3119
|
const paymentTypeOptions = [
|
|
1726
3120
|
{ label: "Card", value: "CARD" },
|
|
1727
3121
|
{ label: "Bank Transfer", value: "BANK_TRANSFER" },
|
|
1728
3122
|
{ label: "Stable Coin", value: "STABLE_COIN" }
|
|
1729
3123
|
];
|
|
1730
3124
|
const [filteredPaymentTypeOptions, setFilteredPaymentTypeOptions] = useState7([]);
|
|
1731
|
-
const [paymentType, setPaymentType] = useState7(
|
|
1732
|
-
|
|
1733
|
-
|
|
3125
|
+
const [paymentType, setPaymentType] = useState7("");
|
|
3126
|
+
const [successObject, setSuccessObject] = useState7({
|
|
3127
|
+
paymentDate: "",
|
|
3128
|
+
paymentId: "",
|
|
3129
|
+
paymentStatus: ""
|
|
3130
|
+
});
|
|
1734
3131
|
const paymentTypeHandler = (event) => {
|
|
1735
3132
|
setPaymentType(event);
|
|
1736
3133
|
};
|
|
1737
|
-
|
|
3134
|
+
const setSuccess = (event) => {
|
|
3135
|
+
setSuccessObject({ ...event });
|
|
3136
|
+
if (event.paymentStatus === "Authorized") {
|
|
3137
|
+
setCheckoutState("SUCCESS");
|
|
3138
|
+
} else if (event.paymentStatus === "Payment failed") {
|
|
3139
|
+
setCheckoutState("PENDING");
|
|
3140
|
+
} else if (event.paymentStatus === "used") {
|
|
3141
|
+
setCheckoutState("USED");
|
|
3142
|
+
} else {
|
|
3143
|
+
setCheckoutState("PENDING");
|
|
3144
|
+
}
|
|
3145
|
+
onPaymentAuthorized?.(event);
|
|
3146
|
+
};
|
|
3147
|
+
useEffect6(() => {
|
|
1738
3148
|
let options2 = [];
|
|
1739
3149
|
if (paymentObject.currency === "USD") {
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
3150
|
+
if (paymentObject.amount < 50) {
|
|
3151
|
+
options2 = paymentTypeOptions.filter(
|
|
3152
|
+
(option) => option.value !== "BANK_TRANSFER" && option.value !== "STABLE_COIN"
|
|
3153
|
+
);
|
|
3154
|
+
} else {
|
|
3155
|
+
options2 = paymentTypeOptions.filter(
|
|
3156
|
+
(option) => option.value !== "BANK_TRANSFER"
|
|
3157
|
+
);
|
|
3158
|
+
}
|
|
1743
3159
|
} else {
|
|
1744
3160
|
options2 = paymentTypeOptions.filter(
|
|
1745
3161
|
(option) => option.value !== "STABLE_COIN"
|
|
1746
3162
|
);
|
|
1747
3163
|
}
|
|
1748
3164
|
setFilteredPaymentTypeOptions(options2);
|
|
1749
|
-
}, [paymentObject.currency]);
|
|
1750
|
-
|
|
1751
|
-
|
|
3165
|
+
}, [paymentObject.currency, paymentObject.amount]);
|
|
3166
|
+
useEffect6(() => {
|
|
3167
|
+
if (filteredPaymentTypeOptions.length) {
|
|
3168
|
+
setPaymentType(filteredPaymentTypeOptions[0].value);
|
|
3169
|
+
}
|
|
3170
|
+
}, [filteredPaymentTypeOptions]);
|
|
3171
|
+
return /* @__PURE__ */ jsx30(BaseCard, { children: /* @__PURE__ */ jsxs20("div", { className: "grid grid-cols-3", children: [
|
|
3172
|
+
checkoutState === "PENDING" && /* @__PURE__ */ jsxs20("div", { className: "bg-[#EFF7FF] px-6 py-8 flex flex-col gap-5 col-span-1 rounded-l-xl", children: [
|
|
1752
3173
|
/* @__PURE__ */ jsx30("p", { className: "text-heading-text text-body-xs font-semibold", children: "Pay with" }),
|
|
1753
3174
|
/* @__PURE__ */ jsx30(
|
|
1754
3175
|
BaseRadioGroup,
|
|
1755
3176
|
{
|
|
1756
|
-
options:
|
|
3177
|
+
options: filteredPaymentTypeOptions,
|
|
1757
3178
|
selectedChange: (e) => paymentTypeHandler(e)
|
|
1758
3179
|
}
|
|
1759
3180
|
)
|
|
1760
3181
|
] }),
|
|
1761
|
-
/* @__PURE__ */
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
3182
|
+
/* @__PURE__ */ jsxs20(
|
|
3183
|
+
"div",
|
|
3184
|
+
{
|
|
3185
|
+
className: checkoutState === "SUCCESS" ? "col-span-3" : "col-span-2",
|
|
3186
|
+
children: [
|
|
3187
|
+
checkoutState === "PENDING" && /* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between px-12 py-8", children: [
|
|
3188
|
+
options?.imageUrl ? /* @__PURE__ */ jsx30(
|
|
3189
|
+
BaseImage,
|
|
3190
|
+
{
|
|
3191
|
+
src: options?.imageUrl ?? "",
|
|
3192
|
+
alt: "Merchant Logo",
|
|
3193
|
+
width: 52,
|
|
3194
|
+
height: 52,
|
|
3195
|
+
customClass: "rounded-lg"
|
|
3196
|
+
}
|
|
3197
|
+
) : /* @__PURE__ */ jsx30(
|
|
3198
|
+
"div",
|
|
3199
|
+
{
|
|
3200
|
+
className: "bg-heading-text rounded flex flex-col justify-center",
|
|
3201
|
+
style: { width: "52px", height: "52px" },
|
|
3202
|
+
children: /* @__PURE__ */ jsx30("p", { className: "text-white text-center text-body-2xs font-medium", children: "Logo" })
|
|
3203
|
+
}
|
|
3204
|
+
),
|
|
3205
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex flex-col gap-1", children: [
|
|
3206
|
+
/* @__PURE__ */ jsx30("p", { className: "text-body-2xs font-regular text-sub-copy text-right", children: paymentObject.merchantName }),
|
|
3207
|
+
/* @__PURE__ */ jsxs20("p", { className: "text-body-2xs font-regular text-sub-copy text-right", children: [
|
|
3208
|
+
"Pay:",
|
|
3209
|
+
" ",
|
|
3210
|
+
/* @__PURE__ */ jsx30("span", { className: "text-orange-500 font-extrabold", children: formatAmount(paymentObject.amount, paymentObject.currency) })
|
|
3211
|
+
] })
|
|
3212
|
+
] })
|
|
3213
|
+
] }),
|
|
3214
|
+
checkoutState === "PENDING" && /* @__PURE__ */ jsx30("div", { className: "overflow-y-scroll px-10 pb-10 pt-2", children: paymentType === "CARD" ? /* @__PURE__ */ jsx30(
|
|
3215
|
+
PayByCard,
|
|
3216
|
+
{
|
|
3217
|
+
secretKey,
|
|
3218
|
+
environment,
|
|
3219
|
+
paymentObject,
|
|
3220
|
+
onPaymentAuthorized: setSuccess,
|
|
3221
|
+
onError
|
|
3222
|
+
}
|
|
3223
|
+
) : paymentType === "BANK_TRANSFER" ? /* @__PURE__ */ jsx30(
|
|
3224
|
+
PayByTransfer,
|
|
1766
3225
|
{
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
3226
|
+
secretKey,
|
|
3227
|
+
environment,
|
|
3228
|
+
paymentObject,
|
|
3229
|
+
onPaymentAuthorized: setSuccess,
|
|
3230
|
+
onError
|
|
1772
3231
|
}
|
|
1773
3232
|
) : /* @__PURE__ */ jsx30(
|
|
1774
|
-
|
|
3233
|
+
PayByStableCoin,
|
|
1775
3234
|
{
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
3235
|
+
secretKey,
|
|
3236
|
+
environment,
|
|
3237
|
+
paymentObject,
|
|
3238
|
+
onPaymentAuthorized: setSuccess,
|
|
3239
|
+
onError
|
|
1779
3240
|
}
|
|
1780
|
-
),
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
/* @__PURE__ */ jsx30("div", { className: "overflow-y-scroll px-10 pb-10 pt-2", children: paymentType === "CARD" ? /* @__PURE__ */ jsx30(PayByCard, {}) : paymentType === "BANK_TRANSFER" ? /* @__PURE__ */ jsx30(PayByTransfer, {}) : /* @__PURE__ */ jsx30(
|
|
1794
|
-
PayByStableCoin,
|
|
1795
|
-
{
|
|
1796
|
-
onProceedToPay: () => setCheckoutState("STABLE_COIN_PAYMENT")
|
|
1797
|
-
}
|
|
1798
|
-
) })
|
|
1799
|
-
] }),
|
|
1800
|
-
checkoutState === "SUCCESS" && /* @__PURE__ */ jsx30(BaseSuccess, {})
|
|
1801
|
-
] })
|
|
3241
|
+
) }),
|
|
3242
|
+
checkoutState === "SUCCESS" && /* @__PURE__ */ jsx30(
|
|
3243
|
+
BaseSuccess,
|
|
3244
|
+
{
|
|
3245
|
+
amount: paymentObject.amount,
|
|
3246
|
+
currency: paymentObject.currency,
|
|
3247
|
+
redirectUrl: paymentObject.redirectUrl ?? "",
|
|
3248
|
+
successObject
|
|
3249
|
+
}
|
|
3250
|
+
)
|
|
3251
|
+
]
|
|
3252
|
+
}
|
|
3253
|
+
)
|
|
1802
3254
|
] }) });
|
|
1803
3255
|
}
|
|
1804
3256
|
export {
|