@miden-npm/react 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1729 -376
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -10
- package/dist/index.d.ts +4 -10
- package/dist/index.js +1728 -370
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +10 -3
package/dist/index.js
CHANGED
|
@@ -71,6 +71,14 @@ 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) => {
|
|
@@ -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 {
|
|
@@ -149,6 +397,181 @@ async function createPaymentLink(paymentObject, environment, secretKey) {
|
|
|
149
397
|
} catch (error) {
|
|
150
398
|
}
|
|
151
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`,
|
|
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(environment, formData = {}) {
|
|
478
|
+
const baseUrl = getBaseUrl(environment);
|
|
479
|
+
const key = CryptoJS.enc.Utf8.parse(baseUrl);
|
|
480
|
+
const iv = CryptoJS.enc.Utf8.parse(baseUrl);
|
|
481
|
+
const postDataObj = JSON.stringify(formData);
|
|
482
|
+
const encryptedData = CryptoJS.AES.encrypt(
|
|
483
|
+
CryptoJS.enc.Utf8.parse(postDataObj),
|
|
484
|
+
key,
|
|
485
|
+
{
|
|
486
|
+
keySize: 128 / 8,
|
|
487
|
+
iv,
|
|
488
|
+
mode: CryptoJS.mode.CBC,
|
|
489
|
+
padding: CryptoJS.pad.Pkcs7
|
|
490
|
+
}
|
|
491
|
+
);
|
|
492
|
+
return {
|
|
493
|
+
requestParam: encryptedData.toString()
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
function decryptPayload(environment, payload) {
|
|
497
|
+
const baseUrl = getBaseUrl(environment);
|
|
498
|
+
const key = CryptoJS.enc.Utf8.parse(baseUrl);
|
|
499
|
+
const iv = CryptoJS.enc.Utf8.parse(baseUrl);
|
|
500
|
+
const decryptedData = CryptoJS.AES.decrypt(payload, key, {
|
|
501
|
+
keySize: 128 / 8,
|
|
502
|
+
iv,
|
|
503
|
+
mode: CryptoJS.mode.CBC,
|
|
504
|
+
padding: CryptoJS.pad.Pkcs7
|
|
505
|
+
});
|
|
506
|
+
const decryptedText = decryptedData.toString(CryptoJS.enc.Utf8);
|
|
507
|
+
return JSON.parse(decryptedText);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// src/apis/resources.api.ts
|
|
511
|
+
async function getCountries(environment, secretKey) {
|
|
512
|
+
try {
|
|
513
|
+
const baseUrl = getBaseUrl(environment);
|
|
514
|
+
const res = await fetch(`${baseUrl}/api/v1/countries-iso`, {
|
|
515
|
+
method: "GET",
|
|
516
|
+
headers: {
|
|
517
|
+
"Content-Type": "application/json",
|
|
518
|
+
Accept: "application/json",
|
|
519
|
+
merchantId: secretKey
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
return await res.json();
|
|
523
|
+
} catch (error) {
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
async function getCountryStates(countryIso3, environment, secretKey) {
|
|
527
|
+
try {
|
|
528
|
+
const baseUrl = getBaseUrl(environment);
|
|
529
|
+
const res = await fetch(
|
|
530
|
+
`${baseUrl}/api/v1/state-by-country/${countryIso3}`,
|
|
531
|
+
{
|
|
532
|
+
method: "GET",
|
|
533
|
+
headers: {
|
|
534
|
+
"Content-Type": "application/json",
|
|
535
|
+
Accept: "application/json",
|
|
536
|
+
merchantId: secretKey
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
);
|
|
540
|
+
return await res.json();
|
|
541
|
+
} catch (error) {
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
async function getStableCoins(environment) {
|
|
545
|
+
try {
|
|
546
|
+
const baseUrl = getBaseUrl(environment);
|
|
547
|
+
const res = await fetch(`${baseUrl}/api/v1/checkout/stable-coin`, {
|
|
548
|
+
method: "GET",
|
|
549
|
+
headers: {
|
|
550
|
+
"Content-Type": "application/json",
|
|
551
|
+
Accept: "application/json"
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
return await res.json();
|
|
555
|
+
} catch (error) {
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
async function getStableCoinNetworks(environment, stableCoin) {
|
|
559
|
+
try {
|
|
560
|
+
const baseUrl = getBaseUrl(environment);
|
|
561
|
+
const res = await fetch(
|
|
562
|
+
`${baseUrl}/api/v1/checkout/networks/${stableCoin}`,
|
|
563
|
+
{
|
|
564
|
+
method: "GET",
|
|
565
|
+
headers: {
|
|
566
|
+
"Content-Type": "application/json",
|
|
567
|
+
Accept: "application/json"
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
);
|
|
571
|
+
return await res.json();
|
|
572
|
+
} catch (error) {
|
|
573
|
+
}
|
|
574
|
+
}
|
|
152
575
|
|
|
153
576
|
// src/components/base/input-error.tsx
|
|
154
577
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
@@ -800,13 +1223,33 @@ var BaseLabelInfo = ({
|
|
|
800
1223
|
|
|
801
1224
|
// src/components/base/success.tsx
|
|
802
1225
|
import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
803
|
-
var BaseSuccess = ({
|
|
1226
|
+
var BaseSuccess = ({
|
|
1227
|
+
amount,
|
|
1228
|
+
currency,
|
|
1229
|
+
redirectUrl,
|
|
1230
|
+
successObject = {
|
|
1231
|
+
paymentDate: "",
|
|
1232
|
+
paymentId: "",
|
|
1233
|
+
paymentStatus: ""
|
|
1234
|
+
}
|
|
1235
|
+
}) => {
|
|
1236
|
+
const formatAmountHandler = formatAmount(amount, currency);
|
|
1237
|
+
const goToRedirectUrl = () => {
|
|
1238
|
+
window.open(redirectUrl, "_self", "noopener,noreferrer");
|
|
1239
|
+
};
|
|
1240
|
+
const paymentDate = new Date(
|
|
1241
|
+
successObject.paymentDate ?? ""
|
|
1242
|
+
).toLocaleDateString("en-US", {
|
|
1243
|
+
year: "numeric",
|
|
1244
|
+
month: "long",
|
|
1245
|
+
day: "2-digit"
|
|
1246
|
+
});
|
|
804
1247
|
return /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-8 p-16", children: [
|
|
805
1248
|
/* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-8", children: [
|
|
806
1249
|
/* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-8", children: [
|
|
807
1250
|
/* @__PURE__ */ jsx20(IconCheckCircle, { color: "#F47A1F", className: "mx-auto" }),
|
|
808
1251
|
/* @__PURE__ */ jsxs11("div", { className: "flex flex-col text-center", style: { gap: "2px" }, children: [
|
|
809
|
-
/* @__PURE__ */ jsx20("p", { className: "text-heading-text font-medium text-header-2xl", children:
|
|
1252
|
+
/* @__PURE__ */ jsx20("p", { className: "text-heading-text font-medium text-header-2xl", children: formatAmountHandler }),
|
|
810
1253
|
/* @__PURE__ */ jsx20("p", { className: "text-sub-copy font-regular text-body-3xs", children: "Has been paid successfully" })
|
|
811
1254
|
] })
|
|
812
1255
|
] }),
|
|
@@ -816,7 +1259,7 @@ var BaseSuccess = ({}) => {
|
|
|
816
1259
|
{
|
|
817
1260
|
type: "horizontal",
|
|
818
1261
|
label: "Order ID",
|
|
819
|
-
value:
|
|
1262
|
+
value: successObject.paymentId
|
|
820
1263
|
}
|
|
821
1264
|
) }),
|
|
822
1265
|
/* @__PURE__ */ jsx20("div", { className: "py-4", children: /* @__PURE__ */ jsx20(
|
|
@@ -824,7 +1267,7 @@ var BaseSuccess = ({}) => {
|
|
|
824
1267
|
{
|
|
825
1268
|
type: "horizontal",
|
|
826
1269
|
label: "Payment date",
|
|
827
|
-
value:
|
|
1270
|
+
value: paymentDate
|
|
828
1271
|
}
|
|
829
1272
|
) })
|
|
830
1273
|
] })
|
|
@@ -834,7 +1277,8 @@ var BaseSuccess = ({}) => {
|
|
|
834
1277
|
{
|
|
835
1278
|
label: "Return to Merchant Website",
|
|
836
1279
|
type: "secondary",
|
|
837
|
-
customClass: "w-full"
|
|
1280
|
+
customClass: "w-full",
|
|
1281
|
+
onClick: goToRedirectUrl
|
|
838
1282
|
}
|
|
839
1283
|
) })
|
|
840
1284
|
] });
|
|
@@ -854,6 +1298,7 @@ var BaseSelect = ({
|
|
|
854
1298
|
value,
|
|
855
1299
|
defaultValue,
|
|
856
1300
|
onChange,
|
|
1301
|
+
onBlur,
|
|
857
1302
|
placeholder = "Select an option",
|
|
858
1303
|
hasSearch = true,
|
|
859
1304
|
disabled = false,
|
|
@@ -926,6 +1371,7 @@ var BaseSelect = ({
|
|
|
926
1371
|
const commit = (val) => {
|
|
927
1372
|
if (!isControlled) setInternalValue(val);
|
|
928
1373
|
onChange?.(val);
|
|
1374
|
+
onBlur?.(val);
|
|
929
1375
|
closeMenu();
|
|
930
1376
|
};
|
|
931
1377
|
const onSearchInput = (e) => {
|
|
@@ -1076,6 +1522,7 @@ var BaseSelect = ({
|
|
|
1076
1522
|
ref: searchRef,
|
|
1077
1523
|
type: "text",
|
|
1078
1524
|
onChange: onSearchInput,
|
|
1525
|
+
onBlur: onSearchInput,
|
|
1079
1526
|
placeholder: `Search ${label || "options"}`,
|
|
1080
1527
|
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"
|
|
1081
1528
|
}
|
|
@@ -1150,96 +1597,216 @@ var BaseCurrencyAmount = ({
|
|
|
1150
1597
|
] });
|
|
1151
1598
|
};
|
|
1152
1599
|
|
|
1153
|
-
// src/
|
|
1154
|
-
import
|
|
1155
|
-
import {
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
const
|
|
1179
|
-
const [
|
|
1180
|
-
|
|
1181
|
-
const launchIframe = useCallback2(
|
|
1182
|
-
(url2) => {
|
|
1183
|
-
if (iframeRef.current && iframeRef.current.parentNode) {
|
|
1184
|
-
iframeRef.current.parentNode.removeChild(iframeRef.current);
|
|
1185
|
-
}
|
|
1186
|
-
const iframe = document.createElement("iframe");
|
|
1187
|
-
iframe.src = url2;
|
|
1188
|
-
if (style.width) iframe.style.width = style.width;
|
|
1189
|
-
if (style.height) iframe.style.height = style.height;
|
|
1190
|
-
if (style.border) iframe.style.border = style.border;
|
|
1191
|
-
if (style.borderRadius) iframe.style.borderRadius = style.borderRadius;
|
|
1192
|
-
if (style.overflow) iframe.style.overflow = style.overflow;
|
|
1193
|
-
containerRef.current?.appendChild(iframe);
|
|
1194
|
-
iframeRef.current = iframe;
|
|
1195
|
-
},
|
|
1196
|
-
[style]
|
|
1600
|
+
// src/components/base/input.tsx
|
|
1601
|
+
import React4 from "react";
|
|
1602
|
+
import { IMaskInput } from "react-imask";
|
|
1603
|
+
import { Fragment as Fragment2, jsx as jsx24, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1604
|
+
var BaseInput = ({
|
|
1605
|
+
label = "",
|
|
1606
|
+
type = "text",
|
|
1607
|
+
mask,
|
|
1608
|
+
placeholder,
|
|
1609
|
+
validationError = "",
|
|
1610
|
+
hint = "",
|
|
1611
|
+
rules = [],
|
|
1612
|
+
isAmountInput = false,
|
|
1613
|
+
required = false,
|
|
1614
|
+
disabled = false,
|
|
1615
|
+
loading = false,
|
|
1616
|
+
showCopyIcon = false,
|
|
1617
|
+
value,
|
|
1618
|
+
defaultValue,
|
|
1619
|
+
onChange,
|
|
1620
|
+
onBlur,
|
|
1621
|
+
prefix,
|
|
1622
|
+
suffix,
|
|
1623
|
+
className = ""
|
|
1624
|
+
}) => {
|
|
1625
|
+
const isControlled = value !== void 0;
|
|
1626
|
+
const [rawValue, setRawValue] = React4.useState(
|
|
1627
|
+
defaultValue ?? value ?? ""
|
|
1197
1628
|
);
|
|
1198
|
-
const
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
if (!
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
);
|
|
1215
|
-
if (
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1629
|
+
const [localHint, setLocalHint] = React4.useState("");
|
|
1630
|
+
const [localError, setLocalError] = React4.useState("");
|
|
1631
|
+
React4.useEffect(() => {
|
|
1632
|
+
if (isControlled) setRawValue(value ?? "");
|
|
1633
|
+
}, [isControlled, value]);
|
|
1634
|
+
const formattedValue = isAmountInput ? formatAmount(rawValue.replace(/,/g, "")) : rawValue;
|
|
1635
|
+
const handleChange = (e) => {
|
|
1636
|
+
const incoming = e.target.value.replace(/,/g, "");
|
|
1637
|
+
if (!isControlled) setRawValue(incoming);
|
|
1638
|
+
onChange?.(incoming);
|
|
1639
|
+
setTimeout(() => {
|
|
1640
|
+
const el = e.target;
|
|
1641
|
+
el.selectionStart = el.selectionEnd = el.value.length;
|
|
1642
|
+
});
|
|
1643
|
+
};
|
|
1644
|
+
const handleStringChange = (e) => {
|
|
1645
|
+
const incoming = e.replace(/,/g, "");
|
|
1646
|
+
if (!isControlled) setRawValue(incoming);
|
|
1647
|
+
onChange?.(incoming);
|
|
1648
|
+
};
|
|
1649
|
+
const handleBlur = () => {
|
|
1650
|
+
onBlur?.(rawValue);
|
|
1651
|
+
};
|
|
1652
|
+
const handleKeyDown = (e) => {
|
|
1653
|
+
if (rules.includes("numeric")) restrictToNumericKeys(e);
|
|
1654
|
+
};
|
|
1655
|
+
const containerBg = disabled ? "bg-grey-50 cursor-not-allowed" : "bg-white";
|
|
1656
|
+
const containerBorder = validationError || localError ? "border-red-300 bg-red-50" : "border-grey-100";
|
|
1657
|
+
const copyToClipboard = (text) => {
|
|
1658
|
+
return navigator.clipboard.writeText(text);
|
|
1659
|
+
};
|
|
1660
|
+
const copyHandler = () => {
|
|
1661
|
+
copyToClipboard(rawValue).then(() => {
|
|
1662
|
+
setLocalHint("Text copied to clipboard");
|
|
1663
|
+
}).catch((err) => {
|
|
1664
|
+
setLocalError("Failed to copy text to clipboard");
|
|
1665
|
+
});
|
|
1666
|
+
};
|
|
1667
|
+
return /* @__PURE__ */ jsxs14("div", { className: `flex flex-col gap-2 ${className}`, children: [
|
|
1668
|
+
label ? /* @__PURE__ */ jsxs14("p", { className: "mb-0 text-body-2xs font-normal text-heading-text", children: [
|
|
1669
|
+
label,
|
|
1670
|
+
required && /* @__PURE__ */ jsx24("span", { className: "text-orange-required", children: " *" })
|
|
1671
|
+
] }) : null,
|
|
1672
|
+
/* @__PURE__ */ jsxs14(
|
|
1673
|
+
"div",
|
|
1674
|
+
{
|
|
1675
|
+
className: `border-c px-3 py-2 flex items-center justify-between rounded-md h-12 ${containerBg} ${containerBorder}`,
|
|
1676
|
+
children: [
|
|
1677
|
+
prefix,
|
|
1678
|
+
/* @__PURE__ */ jsx24(
|
|
1679
|
+
IMaskInput,
|
|
1680
|
+
{
|
|
1681
|
+
type,
|
|
1682
|
+
mask,
|
|
1683
|
+
value: formattedValue,
|
|
1684
|
+
onChange: handleChange,
|
|
1685
|
+
onBlur: handleBlur,
|
|
1686
|
+
onKeyDown: handleKeyDown,
|
|
1687
|
+
disabled,
|
|
1688
|
+
placeholder: placeholder ?? (label ? `Enter ${label.toLowerCase()}` : void 0),
|
|
1689
|
+
inputMode: isAmountInput ? "decimal" : void 0,
|
|
1690
|
+
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"
|
|
1691
|
+
}
|
|
1692
|
+
),
|
|
1693
|
+
!loading ? /* @__PURE__ */ jsxs14(Fragment2, { children: [
|
|
1694
|
+
suffix,
|
|
1695
|
+
showCopyIcon && rawValue && rawValue.trim() !== "" && /* @__PURE__ */ jsx24(
|
|
1696
|
+
BaseImage,
|
|
1697
|
+
{
|
|
1698
|
+
src: "assets/images/copyIcon.svg",
|
|
1699
|
+
alt: "copy",
|
|
1700
|
+
width: 16,
|
|
1701
|
+
height: 16,
|
|
1702
|
+
customClass: "cursor-pointer hover:opacity-70 transition-opacity",
|
|
1703
|
+
onClick: copyHandler
|
|
1704
|
+
}
|
|
1705
|
+
)
|
|
1706
|
+
] }) : (
|
|
1707
|
+
// Simple loader placeholder; swap for your icon component if desired
|
|
1708
|
+
/* @__PURE__ */ jsx24("div", { className: "animate-spin h-4 w-4 border-2 border-current border-t-transparent rounded-full" })
|
|
1709
|
+
)
|
|
1710
|
+
]
|
|
1711
|
+
}
|
|
1712
|
+
),
|
|
1713
|
+
(hint || localHint) && /* @__PURE__ */ jsx24("p", { className: "text-body-3xs text-light-copy", children: localHint || hint }),
|
|
1714
|
+
(validationError || localError) && /* @__PURE__ */ jsx24("p", { className: "text-body-3xs text-red-500", children: localError || validationError })
|
|
1715
|
+
] });
|
|
1716
|
+
};
|
|
1717
|
+
|
|
1718
|
+
// src/buzapay-checkout/checkout-iframe.tsx
|
|
1719
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useRef, useState as useState2 } from "react";
|
|
1720
|
+
import { jsx as jsx25, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1721
|
+
function BzpCheckoutIframe({
|
|
1722
|
+
style = {
|
|
1723
|
+
width: "100%",
|
|
1724
|
+
height: "100vh",
|
|
1725
|
+
border: "0",
|
|
1726
|
+
borderRadius: "6px",
|
|
1727
|
+
overflow: "hidden"
|
|
1728
|
+
},
|
|
1729
|
+
url,
|
|
1730
|
+
secretKey,
|
|
1731
|
+
environment = "sandbox",
|
|
1732
|
+
paymentObject = {
|
|
1733
|
+
merchantName: "",
|
|
1734
|
+
amount: 0,
|
|
1735
|
+
currency: "",
|
|
1736
|
+
email: "",
|
|
1737
|
+
phoneNumber: "",
|
|
1738
|
+
narration: "",
|
|
1739
|
+
redirectUrl: ""
|
|
1740
|
+
}
|
|
1741
|
+
}) {
|
|
1742
|
+
const containerRef = useRef(null);
|
|
1743
|
+
const iframeRef = useRef(null);
|
|
1744
|
+
const [message, setMessage] = useState2("");
|
|
1745
|
+
const [launchUrl, setLaunchUrl] = useState2("");
|
|
1746
|
+
const [loading, setLoading] = useState2(false);
|
|
1747
|
+
const launchIframe = useCallback2(
|
|
1748
|
+
(url2) => {
|
|
1749
|
+
if (iframeRef.current && iframeRef.current.parentNode) {
|
|
1750
|
+
iframeRef.current.parentNode.removeChild(iframeRef.current);
|
|
1751
|
+
}
|
|
1752
|
+
const iframe = document.createElement("iframe");
|
|
1753
|
+
iframe.src = url2;
|
|
1754
|
+
if (style.width) iframe.style.width = style.width;
|
|
1755
|
+
if (style.height) iframe.style.height = style.height;
|
|
1756
|
+
if (style.border) iframe.style.border = style.border;
|
|
1757
|
+
if (style.borderRadius) iframe.style.borderRadius = style.borderRadius;
|
|
1758
|
+
if (style.overflow) iframe.style.overflow = style.overflow;
|
|
1759
|
+
containerRef.current?.appendChild(iframe);
|
|
1760
|
+
iframeRef.current = iframe;
|
|
1761
|
+
},
|
|
1762
|
+
[style]
|
|
1763
|
+
);
|
|
1764
|
+
const generatePaymentLinkHandler = async () => {
|
|
1765
|
+
if (url) {
|
|
1766
|
+
launchIframe(url);
|
|
1767
|
+
return;
|
|
1768
|
+
}
|
|
1769
|
+
if (!secretKey) {
|
|
1770
|
+
return setMessage("Secret key is required.");
|
|
1771
|
+
}
|
|
1772
|
+
if (!checkObjectTruthy(paymentObject)) {
|
|
1773
|
+
return setMessage("Secret key is required.");
|
|
1774
|
+
}
|
|
1775
|
+
setLoading(true);
|
|
1776
|
+
const response = await createPaymentLink(
|
|
1777
|
+
paymentObject,
|
|
1778
|
+
environment,
|
|
1779
|
+
secretKey
|
|
1780
|
+
);
|
|
1781
|
+
if (response?.isSuccessful) {
|
|
1782
|
+
setLaunchUrl(response.launchUrl ?? "");
|
|
1783
|
+
setMessage("Payment link created successfully");
|
|
1784
|
+
if (response.launchUrl) {
|
|
1785
|
+
setLoading(false);
|
|
1786
|
+
launchIframe(response.launchUrl);
|
|
1787
|
+
}
|
|
1788
|
+
} else {
|
|
1789
|
+
setLoading(false);
|
|
1790
|
+
setMessage("Failed to create payment link");
|
|
1225
1791
|
}
|
|
1226
1792
|
};
|
|
1227
1793
|
useEffect2(() => {
|
|
1228
1794
|
if (!containerRef.current) return;
|
|
1229
1795
|
generatePaymentLinkHandler();
|
|
1230
1796
|
}, []);
|
|
1231
|
-
return /* @__PURE__ */
|
|
1232
|
-
/* @__PURE__ */
|
|
1233
|
-
loading && /* @__PURE__ */
|
|
1797
|
+
return /* @__PURE__ */ jsxs15("div", { className: "relative", style, children: [
|
|
1798
|
+
/* @__PURE__ */ jsx25("div", { ref: containerRef, className: "w-full h-full" }),
|
|
1799
|
+
loading && /* @__PURE__ */ jsx25("div", { className: "absolute inset-0 grid place-items-center bg-white/60", children: /* @__PURE__ */ jsx25(IconLoader, {}) })
|
|
1234
1800
|
] });
|
|
1235
1801
|
}
|
|
1236
1802
|
|
|
1237
1803
|
// src/buzapay-checkout/checkout-button.tsx
|
|
1238
|
-
import { jsx as
|
|
1804
|
+
import { jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1239
1805
|
function BzpCheckoutButton({
|
|
1240
1806
|
secretKey,
|
|
1241
1807
|
environment = "sandbox",
|
|
1242
1808
|
paymentObject = {
|
|
1809
|
+
merchantName: "",
|
|
1243
1810
|
amount: 0,
|
|
1244
1811
|
currency: "",
|
|
1245
1812
|
email: "",
|
|
@@ -1284,15 +1851,15 @@ function BzpCheckoutButton({
|
|
|
1284
1851
|
setLoading(false);
|
|
1285
1852
|
}
|
|
1286
1853
|
};
|
|
1287
|
-
return launchUrl && mode === "iframe" ? /* @__PURE__ */
|
|
1854
|
+
return launchUrl && mode === "iframe" ? /* @__PURE__ */ jsx26(
|
|
1288
1855
|
BzpCheckoutIframe,
|
|
1289
1856
|
{
|
|
1290
1857
|
url: launchUrl,
|
|
1291
1858
|
secretKey,
|
|
1292
1859
|
environment
|
|
1293
1860
|
}
|
|
1294
|
-
) : /* @__PURE__ */
|
|
1295
|
-
/* @__PURE__ */
|
|
1861
|
+
) : /* @__PURE__ */ jsxs16("div", { children: [
|
|
1862
|
+
/* @__PURE__ */ jsx26(
|
|
1296
1863
|
BaseButton,
|
|
1297
1864
|
{
|
|
1298
1865
|
label: "Pay",
|
|
@@ -1302,292 +1869,1034 @@ function BzpCheckoutButton({
|
|
|
1302
1869
|
onClick: generatePaymentLinkHandler
|
|
1303
1870
|
}
|
|
1304
1871
|
),
|
|
1305
|
-
/* @__PURE__ */
|
|
1872
|
+
/* @__PURE__ */ jsx26(BaseInputError, { errorMessage: message })
|
|
1306
1873
|
] });
|
|
1307
1874
|
}
|
|
1308
1875
|
|
|
1309
1876
|
// src/buzapay-checkout/checkout-card.tsx
|
|
1310
|
-
import { useEffect as
|
|
1877
|
+
import { useEffect as useEffect6, useState as useState7 } from "react";
|
|
1311
1878
|
|
|
1312
1879
|
// src/components/pay-by-card.tsx
|
|
1313
|
-
import { useState as useState4 } from "react";
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1880
|
+
import { useEffect as useEffect3, useState as useState4 } from "react";
|
|
1881
|
+
import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1882
|
+
function PayByCard({
|
|
1883
|
+
secretKey,
|
|
1884
|
+
paymentObject,
|
|
1885
|
+
environment = "sandbox",
|
|
1886
|
+
onPaymentAuthorized
|
|
1887
|
+
}) {
|
|
1888
|
+
const [formIndex, setFormIndex] = useState4(0);
|
|
1889
|
+
const [message, setMessage] = useState4("");
|
|
1890
|
+
const [isMakingPayment, setIsMakingPayment] = useState4(false);
|
|
1891
|
+
const [loading, setLoading] = useState4(false);
|
|
1892
|
+
const [cardType, setCardType] = useState4("");
|
|
1893
|
+
const [transactionReference, setTransactionReference] = useState4("");
|
|
1894
|
+
const [loadingCountries, setLoadingCountries] = useState4(false);
|
|
1895
|
+
const [loadingStates, setLoadingStates] = useState4(false);
|
|
1896
|
+
const [rawCountries, setRawCountries] = useState4([]);
|
|
1897
|
+
const [countries, setCountries] = useState4([]);
|
|
1898
|
+
const [countryStates, setCountryStates] = useState4([]);
|
|
1899
|
+
const [billingForm, setBillingForm] = useState4({
|
|
1900
|
+
address1: "",
|
|
1901
|
+
address2: "",
|
|
1902
|
+
postalCode: "",
|
|
1903
|
+
state: "",
|
|
1904
|
+
city: "",
|
|
1905
|
+
country: "",
|
|
1906
|
+
emailAddress: "",
|
|
1907
|
+
phoneNumber: ""
|
|
1908
|
+
});
|
|
1909
|
+
const [payForm, setPayForm] = useState4({
|
|
1910
|
+
customerName: "",
|
|
1911
|
+
cardNo: "",
|
|
1912
|
+
expireDate: "",
|
|
1913
|
+
cvv: "",
|
|
1914
|
+
cardPin: ""
|
|
1915
|
+
// Only required for Verve cards
|
|
1916
|
+
});
|
|
1917
|
+
const [billingErrors, setBillingErrors] = useState4(
|
|
1918
|
+
{}
|
|
1341
1919
|
);
|
|
1342
|
-
const [
|
|
1343
|
-
const
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
const el = e.target;
|
|
1354
|
-
el.selectionStart = el.selectionEnd = el.value.length;
|
|
1355
|
-
});
|
|
1920
|
+
const [payErrors, setPayErrors] = useState4({});
|
|
1921
|
+
const billingRules = {
|
|
1922
|
+
address1: "required",
|
|
1923
|
+
address2: "",
|
|
1924
|
+
// optional
|
|
1925
|
+
country: "required",
|
|
1926
|
+
state: "required",
|
|
1927
|
+
city: "required",
|
|
1928
|
+
postalCode: "required|no_special|char_length:6",
|
|
1929
|
+
emailAddress: "required|email",
|
|
1930
|
+
phoneNumber: "required"
|
|
1356
1931
|
};
|
|
1357
|
-
const
|
|
1358
|
-
|
|
1932
|
+
const payRules = {
|
|
1933
|
+
customerName: "required",
|
|
1934
|
+
cardNo: "required|num_spaces",
|
|
1935
|
+
expireDate: "required",
|
|
1936
|
+
cvv: "required|numeric",
|
|
1937
|
+
cardPin: ""
|
|
1938
|
+
// optional unless Verve
|
|
1359
1939
|
};
|
|
1360
|
-
const
|
|
1361
|
-
|
|
1940
|
+
const formatAmountHandler = formatAmount(
|
|
1941
|
+
paymentObject.amount,
|
|
1942
|
+
paymentObject.currency
|
|
1943
|
+
);
|
|
1944
|
+
const billingLabels = {
|
|
1945
|
+
address1: "Address Line 1",
|
|
1946
|
+
address2: "Address Line 2",
|
|
1947
|
+
postalCode: "Postal Code",
|
|
1948
|
+
state: "State",
|
|
1949
|
+
city: "City",
|
|
1950
|
+
country: "Country",
|
|
1951
|
+
emailAddress: "Email",
|
|
1952
|
+
phoneNumber: "Phone Number"
|
|
1362
1953
|
};
|
|
1363
|
-
const
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1954
|
+
const payLabels = {
|
|
1955
|
+
customerName: "Card Name",
|
|
1956
|
+
cardNo: "Card Number",
|
|
1957
|
+
expireDate: "Expiry Date",
|
|
1958
|
+
cvv: "CVV",
|
|
1959
|
+
cardPin: "Card PIN"
|
|
1367
1960
|
};
|
|
1368
|
-
const
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1961
|
+
const proceedHandler = async () => {
|
|
1962
|
+
if (formIndex === 0) {
|
|
1963
|
+
const errs = validateGroup(billingForm, billingRules, billingLabels);
|
|
1964
|
+
setBillingErrors(errs);
|
|
1965
|
+
if (Object.keys(errs).length === 0) {
|
|
1966
|
+
setFormIndex(1);
|
|
1967
|
+
}
|
|
1968
|
+
return;
|
|
1969
|
+
}
|
|
1970
|
+
if (formIndex === 1) {
|
|
1971
|
+
const errs = validateGroup(payForm, payRules, payLabels);
|
|
1972
|
+
setPayErrors(errs);
|
|
1973
|
+
if (Object.keys(errs).length > 0) {
|
|
1974
|
+
return;
|
|
1975
|
+
}
|
|
1976
|
+
try {
|
|
1977
|
+
setIsMakingPayment(true);
|
|
1978
|
+
setMessage("");
|
|
1979
|
+
const cardDetails = {
|
|
1980
|
+
pan: payForm.cardNo ?? "",
|
|
1981
|
+
expiryDate: payForm.expireDate ?? "",
|
|
1982
|
+
cvv: payForm.cvv ?? "",
|
|
1983
|
+
cardScheme: cardType,
|
|
1984
|
+
nameOnCard: payForm.customerName ?? "",
|
|
1985
|
+
...cardType === "Verve" && { pin: payForm.cardPin ?? "" }
|
|
1986
|
+
};
|
|
1987
|
+
const billingDetails = {
|
|
1988
|
+
address1: billingForm.address1 ?? "",
|
|
1989
|
+
address2: billingForm.address2 ?? "",
|
|
1990
|
+
postalCode: billingForm.postalCode ?? "",
|
|
1991
|
+
state: billingForm.state ?? "",
|
|
1992
|
+
city: billingForm.city ?? "",
|
|
1993
|
+
country: billingForm.country ?? "",
|
|
1994
|
+
emailAddress: billingForm.emailAddress ?? "",
|
|
1995
|
+
phoneNumber: billingForm.phoneNumber ?? ""
|
|
1996
|
+
};
|
|
1997
|
+
const encryptedCardDetails = encryptPayload(environment, cardDetails);
|
|
1998
|
+
const payload = {
|
|
1999
|
+
customerId: paymentObject?.email || payForm.customerName || "",
|
|
2000
|
+
amount: String(paymentObject?.amount ?? ""),
|
|
2001
|
+
currency: paymentObject?.currency || "USD",
|
|
2002
|
+
narration: paymentObject?.narration || "Test transaction",
|
|
2003
|
+
encryptedCardDetails: encryptedCardDetails.requestParam,
|
|
2004
|
+
billingDetails,
|
|
2005
|
+
redirectUrl: paymentObject?.redirectUrl || "",
|
|
2006
|
+
paymentReference: transactionReference,
|
|
2007
|
+
isCheckout: true
|
|
2008
|
+
};
|
|
2009
|
+
const request = { ...payload, merchantId: secretKey };
|
|
2010
|
+
let response = await authorizeCardPayment(environment, request);
|
|
2011
|
+
if (response?.responseParam) {
|
|
2012
|
+
response = decryptPayload(environment, response.responseParam);
|
|
2013
|
+
}
|
|
2014
|
+
if (response?.isSuccessful) {
|
|
2015
|
+
if (response.threeDsInteractionRequired === true) {
|
|
2016
|
+
const threeDsData = {
|
|
2017
|
+
transactionReference: response.transactionReference,
|
|
2018
|
+
threeDsHtml: response.threeDsHtml,
|
|
2019
|
+
amount: response.amount,
|
|
2020
|
+
responseMessage: response.responseMessage,
|
|
2021
|
+
paReq: response.threeDsHtml?.paReq,
|
|
2022
|
+
termUrl: response.threeDsHtml?.termUrl,
|
|
2023
|
+
action: response.threeDsHtml?.action,
|
|
2024
|
+
acsUrl: response.threeDsHtml?.acsUrl,
|
|
2025
|
+
md: response.threeDsHtml?.md
|
|
2026
|
+
};
|
|
2027
|
+
localStorage.setItem("threeDsData", JSON.stringify(threeDsData));
|
|
2028
|
+
const threeDsUrl = `${window.location.origin}/account/three-ds-confirm`;
|
|
2029
|
+
window.open(threeDsUrl, "_blank", "noopener,noreferrer");
|
|
2030
|
+
setMessage(
|
|
2031
|
+
"3D Secure authentication opened in new tab. Please complete the verification"
|
|
2032
|
+
);
|
|
2033
|
+
setIsMakingPayment(false);
|
|
2034
|
+
return;
|
|
2035
|
+
}
|
|
2036
|
+
if (response.responseMessage === "Payer Interaction Required" && response.threeDsHtml) {
|
|
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
|
+
localStorage.setItem("threeDsData", JSON.stringify(threeDsData));
|
|
2049
|
+
const threeDsUrl = `${window.location.origin}/account/three-ds-confirm`;
|
|
2050
|
+
window.open(threeDsUrl, "_blank", "noopener,noreferrer");
|
|
2051
|
+
setMessage(
|
|
2052
|
+
"3D Secure authentication opened in new tab. Please complete the verification"
|
|
2053
|
+
);
|
|
2054
|
+
setIsMakingPayment(false);
|
|
2055
|
+
return;
|
|
2056
|
+
}
|
|
2057
|
+
if (response.transactionReference?.trim()) {
|
|
2058
|
+
onPaymentAuthorized?.({
|
|
2059
|
+
paymentId: response.transactionReference,
|
|
2060
|
+
paymentDate: response?.data?.updatedAt,
|
|
2061
|
+
// optional if present
|
|
2062
|
+
paymentStatus: "Authorized"
|
|
2063
|
+
});
|
|
2064
|
+
}
|
|
2065
|
+
setMessage("Card payment authorized successfully");
|
|
2066
|
+
setIsMakingPayment(false);
|
|
2067
|
+
return;
|
|
2068
|
+
}
|
|
2069
|
+
setMessage(response?.responseMessage || "Payment failed");
|
|
2070
|
+
onPaymentAuthorized?.({
|
|
2071
|
+
paymentId: response?.transactionReference,
|
|
2072
|
+
paymentDate: response?.data?.updatedAt,
|
|
2073
|
+
paymentStatus: "Payment failed"
|
|
2074
|
+
});
|
|
2075
|
+
setIsMakingPayment(false);
|
|
2076
|
+
} catch (err) {
|
|
2077
|
+
let friendly = "Payment failed";
|
|
2078
|
+
if (err?.error?.responseParam) {
|
|
2079
|
+
try {
|
|
2080
|
+
const decryptedError = decryptPayload(
|
|
2081
|
+
environment,
|
|
2082
|
+
err.error.responseParam
|
|
2083
|
+
);
|
|
2084
|
+
friendly = decryptedError?.responseMessage || friendly;
|
|
2085
|
+
} catch {
|
|
2086
|
+
friendly = err?.error?.responseMessage || err?.error?.message || friendly;
|
|
2087
|
+
}
|
|
2088
|
+
} else {
|
|
2089
|
+
friendly = err?.error?.responseMessage || err?.error?.message || "Payment failed";
|
|
2090
|
+
}
|
|
2091
|
+
setMessage(friendly);
|
|
2092
|
+
setIsMakingPayment(false);
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
1374
2095
|
};
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
"
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
}
|
|
1399
|
-
),
|
|
1400
|
-
!loading ? /* @__PURE__ */ jsxs16(Fragment2, { children: [
|
|
1401
|
-
suffix,
|
|
1402
|
-
showCopyIcon && rawValue && rawValue.trim() !== "" && /* @__PURE__ */ jsx26(
|
|
1403
|
-
BaseImage,
|
|
1404
|
-
{
|
|
1405
|
-
src: "assets/images/copyIcon.svg",
|
|
1406
|
-
alt: "copy",
|
|
1407
|
-
width: 16,
|
|
1408
|
-
height: 16,
|
|
1409
|
-
customClass: "cursor-pointer hover:opacity-70 transition-opacity",
|
|
1410
|
-
onClick: copyHandler
|
|
1411
|
-
}
|
|
1412
|
-
)
|
|
1413
|
-
] }) : (
|
|
1414
|
-
// Simple loader placeholder; swap for your icon component if desired
|
|
1415
|
-
/* @__PURE__ */ jsx26("div", { className: "animate-spin h-4 w-4 border-2 border-current border-t-transparent rounded-full" })
|
|
1416
|
-
)
|
|
1417
|
-
]
|
|
2096
|
+
const generatePaymentLinkHandler = async () => {
|
|
2097
|
+
if (!secretKey) {
|
|
2098
|
+
setMessage("Secret key is required.");
|
|
2099
|
+
return;
|
|
2100
|
+
}
|
|
2101
|
+
if (!checkObjectTruthy(paymentObject)) {
|
|
2102
|
+
setMessage("Kindly ensure you are passing all the required data.");
|
|
2103
|
+
return;
|
|
2104
|
+
}
|
|
2105
|
+
setLoading(true);
|
|
2106
|
+
setMessage("");
|
|
2107
|
+
try {
|
|
2108
|
+
const response = await createPaymentLink(
|
|
2109
|
+
paymentObject,
|
|
2110
|
+
environment,
|
|
2111
|
+
secretKey
|
|
2112
|
+
);
|
|
2113
|
+
if (response?.isSuccessful && response.launchUrl) {
|
|
2114
|
+
const queryParams = getQueryParams(response.launchUrl);
|
|
2115
|
+
setTransactionReference(queryParams["paymentReference"]);
|
|
2116
|
+
setMessage("Payment link created successfully");
|
|
2117
|
+
} else {
|
|
2118
|
+
setMessage("Failed to create payment link");
|
|
1418
2119
|
}
|
|
1419
|
-
)
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
}
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
2120
|
+
} catch (e) {
|
|
2121
|
+
setMessage(e?.message || "Failed to create payment link");
|
|
2122
|
+
} finally {
|
|
2123
|
+
setLoading(false);
|
|
2124
|
+
}
|
|
2125
|
+
};
|
|
2126
|
+
const getAllCountries = async () => {
|
|
2127
|
+
setLoadingCountries(true);
|
|
2128
|
+
try {
|
|
2129
|
+
const response = await getCountries(
|
|
2130
|
+
environment,
|
|
2131
|
+
secretKey
|
|
2132
|
+
);
|
|
2133
|
+
if (response?.isSuccessful) {
|
|
2134
|
+
setRawCountries(response.data);
|
|
2135
|
+
setCountries(
|
|
2136
|
+
(response.data ?? []).map((c) => {
|
|
2137
|
+
return { label: c.countryName, value: c.iso2 };
|
|
2138
|
+
})
|
|
2139
|
+
);
|
|
2140
|
+
}
|
|
2141
|
+
} catch (e) {
|
|
2142
|
+
setMessage(e?.message || "Failed to get countries");
|
|
2143
|
+
} finally {
|
|
2144
|
+
setLoadingCountries(false);
|
|
2145
|
+
}
|
|
2146
|
+
};
|
|
2147
|
+
const getStates = async (countryIso2) => {
|
|
2148
|
+
const country = rawCountries.find((c) => c.iso2 === countryIso2);
|
|
2149
|
+
if (!country) return;
|
|
2150
|
+
setLoadingStates(true);
|
|
2151
|
+
try {
|
|
2152
|
+
const response = await getCountryStates(
|
|
2153
|
+
country.iso3,
|
|
2154
|
+
environment,
|
|
2155
|
+
secretKey
|
|
2156
|
+
);
|
|
2157
|
+
if (response?.isSuccessful) {
|
|
2158
|
+
setCountryStates(
|
|
2159
|
+
(response.data ?? []).map((s) => ({
|
|
2160
|
+
label: s.name,
|
|
2161
|
+
value: s.name
|
|
2162
|
+
}))
|
|
2163
|
+
);
|
|
2164
|
+
}
|
|
2165
|
+
} catch (e) {
|
|
2166
|
+
setMessage(e?.message || "Failed to get country states");
|
|
2167
|
+
} finally {
|
|
2168
|
+
setLoadingStates(false);
|
|
2169
|
+
}
|
|
2170
|
+
};
|
|
2171
|
+
const cardNumberInputHandler = (event) => {
|
|
2172
|
+
setCardType(cardTypeHandler(event));
|
|
2173
|
+
payRules.cardPin = cardType === "Verve" ? "required|numeric" : "";
|
|
2174
|
+
};
|
|
2175
|
+
useEffect3(() => {
|
|
2176
|
+
(async () => {
|
|
2177
|
+
await generatePaymentLinkHandler();
|
|
2178
|
+
await getAllCountries();
|
|
2179
|
+
})();
|
|
2180
|
+
}, []);
|
|
1429
2181
|
return /* @__PURE__ */ jsxs17("div", { className: "flex flex-col gap-6", children: [
|
|
1430
2182
|
formIndex === 0 && /* @__PURE__ */ jsxs17("div", { className: "grid grid-cols-2 gap-6 overflow-y-auto", children: [
|
|
1431
|
-
/* @__PURE__ */ jsx27(
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
2183
|
+
/* @__PURE__ */ jsx27("div", { className: "col-span-2", children: /* @__PURE__ */ jsx27(
|
|
2184
|
+
BaseInput,
|
|
2185
|
+
{
|
|
2186
|
+
label: "Address Line 1",
|
|
2187
|
+
required: true,
|
|
2188
|
+
value: billingForm.address1,
|
|
2189
|
+
onChange: (e) => {
|
|
2190
|
+
setBillingForm({ ...billingForm, address1: e });
|
|
2191
|
+
if (billingErrors.address1) {
|
|
2192
|
+
setBillingErrors((er) => ({ ...er, address1: "" }));
|
|
2193
|
+
}
|
|
2194
|
+
},
|
|
2195
|
+
validationError: billingErrors.address1 ?? ""
|
|
2196
|
+
}
|
|
2197
|
+
) }),
|
|
2198
|
+
/* @__PURE__ */ jsx27("div", { className: "col-span-2", children: /* @__PURE__ */ jsx27(
|
|
2199
|
+
BaseInput,
|
|
2200
|
+
{
|
|
2201
|
+
label: "Address Line 2",
|
|
2202
|
+
value: billingForm.address2,
|
|
2203
|
+
onChange: (e) => setBillingForm({ ...billingForm, address2: e }),
|
|
2204
|
+
validationError: billingErrors.address2 ?? ""
|
|
2205
|
+
}
|
|
2206
|
+
) }),
|
|
2207
|
+
/* @__PURE__ */ jsx27(
|
|
2208
|
+
BaseSelect,
|
|
2209
|
+
{
|
|
2210
|
+
label: "Select Country",
|
|
2211
|
+
required: true,
|
|
2212
|
+
options: countries,
|
|
2213
|
+
loading: loadingCountries,
|
|
2214
|
+
value: billingForm.country,
|
|
2215
|
+
onChange: (e) => {
|
|
2216
|
+
setBillingForm({ ...billingForm, country: e, state: "" });
|
|
2217
|
+
getStates(e);
|
|
2218
|
+
if (billingErrors.country) {
|
|
2219
|
+
setBillingErrors((er) => ({ ...er, country: "" }));
|
|
2220
|
+
}
|
|
2221
|
+
},
|
|
2222
|
+
validationError: billingErrors.country ?? ""
|
|
2223
|
+
}
|
|
2224
|
+
),
|
|
2225
|
+
/* @__PURE__ */ jsx27(
|
|
2226
|
+
BaseSelect,
|
|
2227
|
+
{
|
|
2228
|
+
label: "Select State",
|
|
2229
|
+
required: true,
|
|
2230
|
+
options: countryStates,
|
|
2231
|
+
loading: loadingStates,
|
|
2232
|
+
value: billingForm.state,
|
|
2233
|
+
onChange: (e) => {
|
|
2234
|
+
setBillingForm({ ...billingForm, state: e });
|
|
2235
|
+
if (billingErrors.state) {
|
|
2236
|
+
setBillingErrors((er) => ({ ...er, state: "" }));
|
|
2237
|
+
}
|
|
2238
|
+
},
|
|
2239
|
+
validationError: billingErrors.state ?? ""
|
|
2240
|
+
}
|
|
2241
|
+
),
|
|
2242
|
+
/* @__PURE__ */ jsx27(
|
|
2243
|
+
BaseInput,
|
|
2244
|
+
{
|
|
2245
|
+
label: "City",
|
|
2246
|
+
required: true,
|
|
2247
|
+
value: billingForm.city,
|
|
2248
|
+
onChange: (e) => {
|
|
2249
|
+
setBillingForm({ ...billingForm, city: e });
|
|
2250
|
+
if (billingErrors.city) {
|
|
2251
|
+
setBillingErrors((er) => ({ ...er, city: "" }));
|
|
2252
|
+
}
|
|
2253
|
+
},
|
|
2254
|
+
validationError: billingErrors.city ?? ""
|
|
2255
|
+
}
|
|
2256
|
+
),
|
|
2257
|
+
/* @__PURE__ */ jsx27(
|
|
2258
|
+
BaseInput,
|
|
2259
|
+
{
|
|
2260
|
+
label: "Postal Code",
|
|
2261
|
+
required: true,
|
|
2262
|
+
value: billingForm.postalCode,
|
|
2263
|
+
onChange: (e) => {
|
|
2264
|
+
setBillingForm({ ...billingForm, postalCode: e });
|
|
2265
|
+
if (billingErrors.postalCode) {
|
|
2266
|
+
setBillingErrors((er) => ({ ...er, postalCode: "" }));
|
|
2267
|
+
}
|
|
2268
|
+
},
|
|
2269
|
+
validationError: billingErrors.postalCode ?? ""
|
|
2270
|
+
}
|
|
2271
|
+
),
|
|
1435
2272
|
/* @__PURE__ */ jsx27(
|
|
1436
|
-
|
|
2273
|
+
BaseInput,
|
|
1437
2274
|
{
|
|
1438
|
-
label: "
|
|
2275
|
+
label: "Email",
|
|
1439
2276
|
required: true,
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
{
|
|
1443
|
-
|
|
1444
|
-
|
|
2277
|
+
value: billingForm.emailAddress,
|
|
2278
|
+
onChange: (e) => {
|
|
2279
|
+
setBillingForm({ ...billingForm, emailAddress: e });
|
|
2280
|
+
if (billingErrors.emailAddress) {
|
|
2281
|
+
setBillingErrors((er) => ({ ...er, emailAddress: "" }));
|
|
2282
|
+
}
|
|
2283
|
+
},
|
|
2284
|
+
validationError: billingErrors.emailAddress ?? ""
|
|
1445
2285
|
}
|
|
1446
2286
|
),
|
|
1447
2287
|
/* @__PURE__ */ jsx27(
|
|
1448
|
-
|
|
2288
|
+
BaseInput,
|
|
1449
2289
|
{
|
|
1450
|
-
label: "
|
|
2290
|
+
label: "Phone Number",
|
|
1451
2291
|
required: true,
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
{
|
|
1455
|
-
|
|
1456
|
-
|
|
2292
|
+
value: billingForm.phoneNumber,
|
|
2293
|
+
onChange: (e) => {
|
|
2294
|
+
setBillingForm({ ...billingForm, phoneNumber: e });
|
|
2295
|
+
if (billingErrors.phoneNumber) {
|
|
2296
|
+
setBillingErrors((er) => ({ ...er, phoneNumber: "" }));
|
|
2297
|
+
}
|
|
2298
|
+
},
|
|
2299
|
+
validationError: billingErrors.phoneNumber ?? ""
|
|
1457
2300
|
}
|
|
1458
|
-
)
|
|
1459
|
-
/* @__PURE__ */ jsx27(BaseInput, { label: "City", required: true }),
|
|
1460
|
-
/* @__PURE__ */ jsx27(BaseInput, { label: "Postal Code", required: true }),
|
|
1461
|
-
/* @__PURE__ */ jsx27("div", { className: "col-span-2", children: /* @__PURE__ */ jsx27(BaseInput, { label: "Street Address", required: true }) })
|
|
2301
|
+
)
|
|
1462
2302
|
] }),
|
|
1463
2303
|
formIndex === 1 && /* @__PURE__ */ jsxs17(
|
|
1464
2304
|
"div",
|
|
1465
2305
|
{
|
|
1466
2306
|
className: "grid grid-cols-2 gap-6 overflow-y-auto",
|
|
1467
|
-
style: { maxHeight:
|
|
2307
|
+
style: { maxHeight: 320 },
|
|
1468
2308
|
children: [
|
|
1469
|
-
/* @__PURE__ */ jsx27("div", { className: "col-span-2", children: /* @__PURE__ */ jsx27(
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
2309
|
+
/* @__PURE__ */ jsx27("div", { className: "col-span-2", children: /* @__PURE__ */ jsx27(
|
|
2310
|
+
BaseInput,
|
|
2311
|
+
{
|
|
2312
|
+
label: "Card Name",
|
|
2313
|
+
required: true,
|
|
2314
|
+
value: payForm.customerName,
|
|
2315
|
+
onChange: (e) => {
|
|
2316
|
+
setPayForm({ ...payForm, customerName: e });
|
|
2317
|
+
if (payErrors.customerName) {
|
|
2318
|
+
setPayErrors((er) => ({ ...er, customerName: "" }));
|
|
2319
|
+
}
|
|
2320
|
+
},
|
|
2321
|
+
validationError: payErrors.customerName ?? ""
|
|
2322
|
+
}
|
|
2323
|
+
) }),
|
|
2324
|
+
/* @__PURE__ */ jsx27("div", { className: "col-span-2", children: /* @__PURE__ */ jsx27(
|
|
2325
|
+
BaseInput,
|
|
2326
|
+
{
|
|
2327
|
+
label: "Card Number",
|
|
2328
|
+
required: true,
|
|
2329
|
+
rules: ["numeric"],
|
|
2330
|
+
mask: "0000 0000 0000 0000",
|
|
2331
|
+
placeholder: "0000 0000 0000 0000",
|
|
2332
|
+
value: payForm.cardNo,
|
|
2333
|
+
onChange: (e) => {
|
|
2334
|
+
setPayForm({ ...payForm, cardNo: e });
|
|
2335
|
+
if (payErrors.cardNo)
|
|
2336
|
+
setPayErrors((er) => ({ ...er, cardNo: "" }));
|
|
2337
|
+
cardNumberInputHandler(e);
|
|
2338
|
+
},
|
|
2339
|
+
validationError: payErrors.cardNo ?? ""
|
|
2340
|
+
}
|
|
2341
|
+
) }),
|
|
2342
|
+
/* @__PURE__ */ jsx27(
|
|
2343
|
+
BaseInput,
|
|
2344
|
+
{
|
|
2345
|
+
label: "Expiry Date",
|
|
2346
|
+
required: true,
|
|
2347
|
+
value: payForm.expireDate,
|
|
2348
|
+
mask: "00/00",
|
|
2349
|
+
placeholder: "00/00",
|
|
2350
|
+
onChange: (e) => {
|
|
2351
|
+
setPayForm({ ...payForm, expireDate: e });
|
|
2352
|
+
if (payErrors.expireDate)
|
|
2353
|
+
setPayErrors((er) => ({ ...er, expireDate: "" }));
|
|
2354
|
+
},
|
|
2355
|
+
validationError: payErrors.expireDate ?? ""
|
|
2356
|
+
}
|
|
2357
|
+
),
|
|
2358
|
+
/* @__PURE__ */ jsx27(
|
|
2359
|
+
BaseInput,
|
|
2360
|
+
{
|
|
2361
|
+
label: "CVV",
|
|
2362
|
+
required: true,
|
|
2363
|
+
rules: ["numeric"],
|
|
2364
|
+
value: payForm.cvv,
|
|
2365
|
+
mask: "000",
|
|
2366
|
+
placeholder: "000",
|
|
2367
|
+
onChange: (e) => {
|
|
2368
|
+
setPayForm({ ...payForm, cvv: e });
|
|
2369
|
+
if (payErrors.cvv) setPayErrors((er) => ({ ...er, cvv: "" }));
|
|
2370
|
+
},
|
|
2371
|
+
validationError: payErrors.cvv ?? ""
|
|
2372
|
+
}
|
|
2373
|
+
),
|
|
2374
|
+
cardType === "Verve" && /* @__PURE__ */ jsx27(
|
|
2375
|
+
BaseInput,
|
|
2376
|
+
{
|
|
2377
|
+
label: "Card Pin",
|
|
2378
|
+
required: true,
|
|
2379
|
+
rules: ["numeric"],
|
|
2380
|
+
value: payForm.cardPin,
|
|
2381
|
+
mask: "0000",
|
|
2382
|
+
placeholder: "0000",
|
|
2383
|
+
onChange: (e) => {
|
|
2384
|
+
setPayForm({ ...payForm, cardPin: e });
|
|
2385
|
+
if (payErrors.cardPin)
|
|
2386
|
+
setPayErrors((er) => ({ ...er, cardPin: "" }));
|
|
2387
|
+
},
|
|
2388
|
+
validationError: payErrors.cardPin ?? ""
|
|
2389
|
+
}
|
|
2390
|
+
)
|
|
1473
2391
|
]
|
|
1474
2392
|
}
|
|
1475
2393
|
),
|
|
1476
2394
|
/* @__PURE__ */ jsx27(
|
|
1477
2395
|
BaseButton,
|
|
1478
2396
|
{
|
|
1479
|
-
label: formIndex === 0 ? "Proceed" :
|
|
2397
|
+
label: formIndex === 0 ? "Proceed" : `Pay ${formatAmountHandler}`,
|
|
1480
2398
|
type: "primary",
|
|
1481
2399
|
customClass: "w-full",
|
|
1482
|
-
|
|
2400
|
+
loading: isMakingPayment,
|
|
2401
|
+
onClick: proceedHandler,
|
|
2402
|
+
disabled: isMakingPayment
|
|
1483
2403
|
}
|
|
1484
2404
|
)
|
|
1485
2405
|
] });
|
|
1486
2406
|
}
|
|
1487
2407
|
|
|
1488
2408
|
// src/components/pay-by-transfer.tsx
|
|
1489
|
-
import {
|
|
2409
|
+
import {
|
|
2410
|
+
useCallback as useCallback3,
|
|
2411
|
+
useEffect as useEffect4,
|
|
2412
|
+
useRef as useRef2,
|
|
2413
|
+
useState as useState5
|
|
2414
|
+
} from "react";
|
|
1490
2415
|
import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1491
2416
|
var PayByTransfer = ({
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
onConfirmPaid,
|
|
2417
|
+
secretKey,
|
|
2418
|
+
paymentObject,
|
|
2419
|
+
environment = "sandbox",
|
|
2420
|
+
onPaymentAuthorized,
|
|
1497
2421
|
onCancel
|
|
1498
2422
|
}) => {
|
|
1499
|
-
const [
|
|
2423
|
+
const [formIndex, setFormIndex] = useState5(0);
|
|
2424
|
+
const [isMakingPayment, setIsMakingPayment] = useState5(false);
|
|
2425
|
+
const [isConfirmCall, setIsConfirmCall] = useState5(false);
|
|
2426
|
+
const [isPaymentConfirmed, setIsPaymentConfirmed] = useState5(false);
|
|
2427
|
+
const [transactionReference, setTransactionReference] = useState5("");
|
|
2428
|
+
const [paymentReferenceStatus, setPaymentReferenceStatus] = useState5("");
|
|
2429
|
+
const [isFetchingPaymentDetails, setIsFetchingPaymentDetails] = useState5(false);
|
|
2430
|
+
const [paymentReferenceDetails, setPaymentReferenceDetails] = useState5(null);
|
|
2431
|
+
const [paymentAccountDetails, setPaymentAccountDetails] = useState5(null);
|
|
2432
|
+
const [paymentMade, setPaymentMade] = useState5(false);
|
|
2433
|
+
const [loading, setLoading] = useState5(false);
|
|
2434
|
+
const [message, setMessage] = useState5("");
|
|
2435
|
+
const [remainingSeconds, setRemainingSeconds] = useState5(60);
|
|
2436
|
+
const [countDownTime, setCountDownTime] = useState5("00:00");
|
|
1500
2437
|
const intervalRef = useRef2(null);
|
|
1501
|
-
const
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
2438
|
+
const [transferForm, setTransferForm] = useState5({
|
|
2439
|
+
customerName: ""
|
|
2440
|
+
});
|
|
2441
|
+
const [transferErrors, setTransferErrors] = useState5(
|
|
2442
|
+
{}
|
|
2443
|
+
);
|
|
2444
|
+
const transferRules = {
|
|
2445
|
+
customerName: "required"
|
|
2446
|
+
};
|
|
2447
|
+
const transferLabels = {
|
|
2448
|
+
customerName: "Customer Name"
|
|
2449
|
+
};
|
|
2450
|
+
const formatAmountHandler = formatAmount(
|
|
2451
|
+
paymentObject.amount,
|
|
2452
|
+
paymentObject.currency
|
|
2453
|
+
);
|
|
2454
|
+
const payHandler = async () => {
|
|
2455
|
+
if (formIndex === 0) {
|
|
2456
|
+
const errs = validateGroup(transferForm, transferRules, transferLabels);
|
|
2457
|
+
setTransferErrors(errs);
|
|
2458
|
+
if (Object.keys(errs).length === 0) {
|
|
2459
|
+
const payload = {
|
|
2460
|
+
paymentReference: transactionReference,
|
|
2461
|
+
channel: "virtual_account",
|
|
2462
|
+
customerName: transferForm.customerName ?? "",
|
|
2463
|
+
merchantId: secretKey
|
|
2464
|
+
};
|
|
2465
|
+
setIsMakingPayment(true);
|
|
2466
|
+
try {
|
|
2467
|
+
const response = await generatePaymentAccount(environment, payload);
|
|
2468
|
+
if (response?.isSuccessful) {
|
|
2469
|
+
setPaymentAccountDetails(response.data);
|
|
2470
|
+
startTimer();
|
|
2471
|
+
setMessage("Virtual account generated successfully for payment.");
|
|
2472
|
+
setIsMakingPayment(true);
|
|
2473
|
+
setFormIndex(1);
|
|
2474
|
+
}
|
|
2475
|
+
} catch (err) {
|
|
2476
|
+
setIsMakingPayment(false);
|
|
2477
|
+
setMessage(err.error.responseMessage || err.error.message);
|
|
2478
|
+
}
|
|
1515
2479
|
}
|
|
1516
|
-
|
|
2480
|
+
return;
|
|
2481
|
+
}
|
|
2482
|
+
};
|
|
2483
|
+
const getReferenceDetails = async () => {
|
|
2484
|
+
setIsFetchingPaymentDetails(true);
|
|
2485
|
+
try {
|
|
2486
|
+
const response = await getPaymentReferenceDetails(
|
|
2487
|
+
environment,
|
|
2488
|
+
transactionReference
|
|
2489
|
+
);
|
|
2490
|
+
if (response?.isSuccessful) {
|
|
2491
|
+
setPaymentReferenceDetails(response.data);
|
|
2492
|
+
const made = response.data?.paymentStatus === "Payment Received";
|
|
2493
|
+
setPaymentMade(made);
|
|
2494
|
+
const noServerStatus = response.data?.finalTransactionStatus == null || response.data?.paymentStatus == null;
|
|
2495
|
+
if (noServerStatus) {
|
|
2496
|
+
if (isConfirmCall) {
|
|
2497
|
+
setMessage("Transaction not confirmed !!");
|
|
2498
|
+
}
|
|
2499
|
+
if (!isPaymentConfirmed && !made) {
|
|
2500
|
+
setPaymentReferenceStatus("pending");
|
|
2501
|
+
onPaymentAuthorized?.({
|
|
2502
|
+
paymentId: transactionReference,
|
|
2503
|
+
paymentDate: response.data?.updatedAt,
|
|
2504
|
+
paymentStatus: "pending"
|
|
2505
|
+
});
|
|
2506
|
+
} else {
|
|
2507
|
+
setPaymentReferenceStatus("confirmed");
|
|
2508
|
+
onPaymentAuthorized?.({
|
|
2509
|
+
paymentId: transactionReference,
|
|
2510
|
+
paymentDate: response.data?.updatedAt,
|
|
2511
|
+
paymentStatus: "confirmed"
|
|
2512
|
+
});
|
|
2513
|
+
}
|
|
2514
|
+
} else if (response.data?.finalTransactionStatus === "Success" || response.data?.paymentStatus === "Received" || response.data?.paymentStatus === "Payment Received") {
|
|
2515
|
+
setPaymentReferenceStatus("confirmed");
|
|
2516
|
+
setIsPaymentConfirmed(true);
|
|
2517
|
+
setMessage("Transaction confirmed !!");
|
|
2518
|
+
onPaymentAuthorized?.({
|
|
2519
|
+
paymentId: transactionReference,
|
|
2520
|
+
paymentDate: response.data?.updatedAt,
|
|
2521
|
+
paymentStatus: "confirmed"
|
|
2522
|
+
});
|
|
2523
|
+
}
|
|
2524
|
+
} else if (!response?.isSuccessful && response?.responseCode === "119") {
|
|
2525
|
+
setPaymentReferenceStatus("used");
|
|
2526
|
+
setMessage(response.responseMessage || "");
|
|
2527
|
+
onPaymentAuthorized?.({
|
|
2528
|
+
paymentId: transactionReference,
|
|
2529
|
+
paymentDate: null,
|
|
2530
|
+
paymentStatus: "used"
|
|
2531
|
+
});
|
|
2532
|
+
}
|
|
2533
|
+
} catch (err) {
|
|
2534
|
+
setPaymentReferenceStatus("");
|
|
2535
|
+
setMessage(
|
|
2536
|
+
err?.error?.responseMessage || err?.error?.message || "Something went wrong"
|
|
2537
|
+
);
|
|
2538
|
+
} finally {
|
|
2539
|
+
setIsFetchingPaymentDetails(false);
|
|
2540
|
+
}
|
|
2541
|
+
};
|
|
2542
|
+
const generatePaymentLinkHandler = async () => {
|
|
2543
|
+
if (!secretKey) {
|
|
2544
|
+
setMessage("Secret key is required.");
|
|
2545
|
+
return;
|
|
2546
|
+
}
|
|
2547
|
+
if (!checkObjectTruthy(paymentObject)) {
|
|
2548
|
+
setMessage("Kindly ensure you are passing all the required data.");
|
|
2549
|
+
return;
|
|
2550
|
+
}
|
|
2551
|
+
setLoading(true);
|
|
2552
|
+
setMessage("");
|
|
2553
|
+
try {
|
|
2554
|
+
const response = await createPaymentLink(
|
|
2555
|
+
paymentObject,
|
|
2556
|
+
environment,
|
|
2557
|
+
secretKey
|
|
2558
|
+
);
|
|
2559
|
+
if (response?.isSuccessful && response.launchUrl) {
|
|
2560
|
+
const queryParams = getQueryParams(response.launchUrl);
|
|
2561
|
+
setTransactionReference(queryParams["paymentReference"]);
|
|
2562
|
+
setMessage("Payment link created successfully");
|
|
2563
|
+
} else {
|
|
2564
|
+
setMessage("Failed to create payment link");
|
|
2565
|
+
}
|
|
2566
|
+
} catch (e) {
|
|
2567
|
+
setMessage(e?.message || "Failed to create payment link");
|
|
2568
|
+
} finally {
|
|
2569
|
+
setLoading(false);
|
|
2570
|
+
}
|
|
2571
|
+
};
|
|
2572
|
+
const updateDisplay = useCallback3((secs) => {
|
|
2573
|
+
const minutes = String(Math.floor(secs / 60)).padStart(2, "0");
|
|
2574
|
+
const seconds = String(secs % 60).padStart(2, "0");
|
|
2575
|
+
setCountDownTime(`${minutes}:${seconds}`);
|
|
1517
2576
|
}, []);
|
|
1518
|
-
|
|
1519
|
-
if (
|
|
2577
|
+
const startTimer = useCallback3(() => {
|
|
2578
|
+
if (intervalRef.current) {
|
|
2579
|
+
clearInterval(intervalRef.current);
|
|
2580
|
+
intervalRef.current = null;
|
|
2581
|
+
}
|
|
2582
|
+
updateDisplay(remainingSeconds);
|
|
2583
|
+
intervalRef.current = setInterval(() => {
|
|
2584
|
+
setRemainingSeconds((prev) => {
|
|
2585
|
+
const next = prev - 1;
|
|
2586
|
+
if (next < 0) {
|
|
2587
|
+
if (intervalRef.current) {
|
|
2588
|
+
clearInterval(intervalRef.current);
|
|
2589
|
+
intervalRef.current = null;
|
|
2590
|
+
}
|
|
2591
|
+
setCountDownTime("00:00");
|
|
2592
|
+
return 0;
|
|
2593
|
+
}
|
|
2594
|
+
updateDisplay(next);
|
|
2595
|
+
return next;
|
|
2596
|
+
});
|
|
2597
|
+
}, 1e3);
|
|
2598
|
+
}, [remainingSeconds, updateDisplay]);
|
|
2599
|
+
const stopTimer = () => {
|
|
2600
|
+
if (intervalRef.current) {
|
|
1520
2601
|
clearInterval(intervalRef.current);
|
|
1521
2602
|
intervalRef.current = null;
|
|
1522
2603
|
}
|
|
1523
|
-
}
|
|
2604
|
+
};
|
|
2605
|
+
useEffect4(() => {
|
|
2606
|
+
(async () => {
|
|
2607
|
+
await generatePaymentLinkHandler();
|
|
2608
|
+
})();
|
|
2609
|
+
}, []);
|
|
2610
|
+
useEffect4(() => {
|
|
2611
|
+
if (remainingSeconds < 0 && intervalRef.current) {
|
|
2612
|
+
stopTimer();
|
|
2613
|
+
}
|
|
2614
|
+
}, [remainingSeconds]);
|
|
1524
2615
|
return /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-10", children: [
|
|
1525
|
-
/* @__PURE__ */ jsxs18("
|
|
1526
|
-
|
|
1527
|
-
|
|
2616
|
+
formIndex === 0 && /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-10", children: [
|
|
2617
|
+
/* @__PURE__ */ jsx28(
|
|
2618
|
+
BaseInput,
|
|
2619
|
+
{
|
|
2620
|
+
label: "Customer Name",
|
|
2621
|
+
required: true,
|
|
2622
|
+
value: transferForm.customerName,
|
|
2623
|
+
onChange: (e) => {
|
|
2624
|
+
setTransferForm({ ...transferForm, customerName: e });
|
|
2625
|
+
if (transferForm.customerName) {
|
|
2626
|
+
setTransferErrors((er) => ({ ...er, customerName: "" }));
|
|
2627
|
+
}
|
|
2628
|
+
},
|
|
2629
|
+
validationError: transferErrors.customerName ?? ""
|
|
2630
|
+
}
|
|
2631
|
+
),
|
|
2632
|
+
/* @__PURE__ */ jsx28(
|
|
2633
|
+
BaseButton,
|
|
2634
|
+
{
|
|
2635
|
+
label: `Pay ${formatAmountHandler}`,
|
|
2636
|
+
type: "primary",
|
|
2637
|
+
customClass: "w-full",
|
|
2638
|
+
loading: isMakingPayment,
|
|
2639
|
+
onClick: payHandler
|
|
2640
|
+
}
|
|
2641
|
+
)
|
|
1528
2642
|
] }),
|
|
1529
|
-
/* @__PURE__ */ jsxs18("div", { className: "
|
|
1530
|
-
/* @__PURE__ */
|
|
1531
|
-
/* @__PURE__ */ jsxs18("div", { className: "flex items-center justify-between", children: [
|
|
2643
|
+
formIndex === 1 && /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-10", children: [
|
|
2644
|
+
/* @__PURE__ */ jsxs18("div", { className: "bg-[#EFF7FF] p-4 rounded-lg flex flex-col gap-6", children: [
|
|
1532
2645
|
/* @__PURE__ */ jsx28(
|
|
1533
2646
|
BaseLabelInfo,
|
|
1534
2647
|
{
|
|
1535
|
-
label: "
|
|
1536
|
-
value:
|
|
1537
|
-
type: "horizontal"
|
|
2648
|
+
label: "Bank Name",
|
|
2649
|
+
value: `${paymentAccountDetails?.bank} ${paymentAccountDetails?.accountName}`
|
|
1538
2650
|
}
|
|
1539
2651
|
),
|
|
1540
|
-
/* @__PURE__ */
|
|
2652
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center justify-between", children: [
|
|
2653
|
+
/* @__PURE__ */ jsx28(
|
|
2654
|
+
BaseLabelInfo,
|
|
2655
|
+
{
|
|
2656
|
+
label: "Account Number",
|
|
2657
|
+
value: paymentAccountDetails?.accountNumber
|
|
2658
|
+
}
|
|
2659
|
+
),
|
|
2660
|
+
/* @__PURE__ */ jsx28(
|
|
2661
|
+
BaseCopy,
|
|
2662
|
+
{
|
|
2663
|
+
color: "#9DBFDE",
|
|
2664
|
+
copyText: paymentAccountDetails?.accountNumber ?? ""
|
|
2665
|
+
}
|
|
2666
|
+
)
|
|
2667
|
+
] }),
|
|
2668
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center justify-between", children: [
|
|
2669
|
+
/* @__PURE__ */ jsx28(BaseLabelInfo, { label: "Amount", value: formatAmountHandler }),
|
|
2670
|
+
/* @__PURE__ */ jsx28(BaseCopy, { color: "#9DBFDE", copyText: formatAmountHandler })
|
|
2671
|
+
] })
|
|
1541
2672
|
] }),
|
|
1542
|
-
/* @__PURE__ */ jsxs18("
|
|
2673
|
+
/* @__PURE__ */ jsxs18("p", { className: "w-2/3 mx-auto text-center text-body-2xs font-medium text-sub-copy", children: [
|
|
2674
|
+
"This account is for this transaction only and expires in",
|
|
2675
|
+
" ",
|
|
2676
|
+
/* @__PURE__ */ jsx28("span", { className: "text-orange-500", children: remainingSeconds >= 0 ? countDownTime : "00:00" })
|
|
2677
|
+
] }),
|
|
2678
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-4", children: [
|
|
1543
2679
|
/* @__PURE__ */ jsx28(
|
|
1544
|
-
|
|
2680
|
+
BaseButton,
|
|
1545
2681
|
{
|
|
1546
|
-
label: "
|
|
1547
|
-
|
|
1548
|
-
|
|
2682
|
+
label: "I have paid the money",
|
|
2683
|
+
type: "primary",
|
|
2684
|
+
customClass: "w-full",
|
|
2685
|
+
loading: isFetchingPaymentDetails,
|
|
2686
|
+
onClick: getReferenceDetails
|
|
1549
2687
|
}
|
|
1550
2688
|
),
|
|
1551
|
-
/* @__PURE__ */ jsx28(
|
|
2689
|
+
/* @__PURE__ */ jsx28(
|
|
2690
|
+
"button",
|
|
2691
|
+
{
|
|
2692
|
+
type: "button",
|
|
2693
|
+
onClick: onCancel,
|
|
2694
|
+
className: "text-heading-text text-body-2xs font-medium text-center py-2 cursor-pointer",
|
|
2695
|
+
children: "Cancel Payment"
|
|
2696
|
+
}
|
|
2697
|
+
)
|
|
1552
2698
|
] })
|
|
1553
|
-
] }),
|
|
1554
|
-
/* @__PURE__ */ jsxs18("p", { className: "w-2/3 mx-auto text-center text-body-2xs font-medium text-sub-copy", children: [
|
|
1555
|
-
"This account is for this transaction only and expires in",
|
|
1556
|
-
" ",
|
|
1557
|
-
/* @__PURE__ */ jsx28("span", { className: "text-orange-500", children: remaining >= 0 ? countDownTime : "00:00" })
|
|
1558
|
-
] }),
|
|
1559
|
-
/* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-4", children: [
|
|
1560
|
-
/* @__PURE__ */ jsx28(
|
|
1561
|
-
BaseButton,
|
|
1562
|
-
{
|
|
1563
|
-
label: "I have paid the money",
|
|
1564
|
-
type: "primary",
|
|
1565
|
-
customClass: "w-full",
|
|
1566
|
-
onClick: onConfirmPaid
|
|
1567
|
-
}
|
|
1568
|
-
),
|
|
1569
|
-
/* @__PURE__ */ jsx28(
|
|
1570
|
-
"button",
|
|
1571
|
-
{
|
|
1572
|
-
type: "button",
|
|
1573
|
-
onClick: onCancel,
|
|
1574
|
-
className: "text-heading-text text-body-2xs font-medium text-center py-2 cursor-pointer",
|
|
1575
|
-
children: "Cancel Payment"
|
|
1576
|
-
}
|
|
1577
|
-
)
|
|
1578
2699
|
] })
|
|
1579
2700
|
] });
|
|
1580
2701
|
};
|
|
1581
2702
|
|
|
1582
2703
|
// src/components/pay-by-stable-coin.tsx
|
|
1583
|
-
import { useState as useState6 } from "react";
|
|
2704
|
+
import { useEffect as useEffect5, useState as useState6 } from "react";
|
|
1584
2705
|
import { Fragment as Fragment3, jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1585
|
-
var PayByStableCoin = ({
|
|
2706
|
+
var PayByStableCoin = ({
|
|
2707
|
+
secretKey,
|
|
2708
|
+
paymentObject,
|
|
2709
|
+
environment = "sandbox",
|
|
2710
|
+
onPaymentAuthorized
|
|
2711
|
+
}) => {
|
|
1586
2712
|
const [formIndex, setFormIndex] = useState6(0);
|
|
1587
|
-
const
|
|
1588
|
-
|
|
1589
|
-
|
|
2713
|
+
const [message, setMessage] = useState6("");
|
|
2714
|
+
const [loading, setLoading] = useState6(false);
|
|
2715
|
+
const [generatingAddress, setGeneratingAddress] = useState6(false);
|
|
2716
|
+
const [loadingStableCoins, setLoadingStableCoins] = useState6(false);
|
|
2717
|
+
const [loadingStableCoinNetworks, setLoadingStableCoinNetworks] = useState6(false);
|
|
2718
|
+
const [transactionReference, setTransactionReference] = useState6("");
|
|
2719
|
+
const [stableCoins, setStableCoins] = useState6([]);
|
|
2720
|
+
const [networkList, setNetworkList] = useState6([]);
|
|
2721
|
+
const [addressDetails, setAddressDetails] = useState6(null);
|
|
2722
|
+
const [generateAddressPayload, setGenerateAddressPayload] = useState6(null);
|
|
2723
|
+
const [isConfirmingPayment, setIsConfirmingPayment] = useState6(false);
|
|
2724
|
+
const [paymentReferenceDetails, setPaymentReferenceDetails] = useState6(null);
|
|
2725
|
+
const [paymentReferenceStatus, setPaymentReferenceStatus] = useState6("");
|
|
2726
|
+
const [stableCoinForm, setStableCoinForm] = useState6({
|
|
2727
|
+
stableCoin: "",
|
|
2728
|
+
network: ""
|
|
2729
|
+
});
|
|
2730
|
+
const [stableCoinErrors, setStableCoinErrors] = useState6({});
|
|
2731
|
+
const stableCoinRules = {
|
|
2732
|
+
stableCoin: "required",
|
|
2733
|
+
network: "required"
|
|
2734
|
+
};
|
|
2735
|
+
const stableCoinLabels = {
|
|
2736
|
+
stableCoin: "Stable Coin",
|
|
2737
|
+
network: "Network"
|
|
2738
|
+
};
|
|
2739
|
+
const generatePaymentLinkHandler = async () => {
|
|
2740
|
+
if (!secretKey) {
|
|
2741
|
+
setMessage("Secret key is required.");
|
|
2742
|
+
return;
|
|
2743
|
+
}
|
|
2744
|
+
if (!checkObjectTruthy(paymentObject)) {
|
|
2745
|
+
setMessage("Kindly ensure you are passing all the required data.");
|
|
2746
|
+
return;
|
|
2747
|
+
}
|
|
2748
|
+
setLoading(true);
|
|
2749
|
+
setMessage("");
|
|
2750
|
+
try {
|
|
2751
|
+
const response = await createPaymentLink(
|
|
2752
|
+
paymentObject,
|
|
2753
|
+
environment,
|
|
2754
|
+
secretKey
|
|
2755
|
+
);
|
|
2756
|
+
if (response?.isSuccessful && response.launchUrl) {
|
|
2757
|
+
const queryParams = getQueryParams(response.launchUrl);
|
|
2758
|
+
setTransactionReference(queryParams["paymentReference"]);
|
|
2759
|
+
setMessage("Payment link created successfully");
|
|
2760
|
+
} else {
|
|
2761
|
+
setMessage("Failed to create payment link");
|
|
2762
|
+
}
|
|
2763
|
+
} catch (e) {
|
|
2764
|
+
setMessage(e?.message || "Failed to create payment link");
|
|
2765
|
+
} finally {
|
|
2766
|
+
setLoading(false);
|
|
2767
|
+
}
|
|
2768
|
+
};
|
|
2769
|
+
const generateAddress = async (payload) => {
|
|
2770
|
+
if (!payload) return;
|
|
2771
|
+
setGeneratingAddress(true);
|
|
2772
|
+
try {
|
|
2773
|
+
const response = await generateStableCoinAddress(
|
|
2774
|
+
environment,
|
|
2775
|
+
payload
|
|
2776
|
+
);
|
|
2777
|
+
if (response?.isSuccessful) {
|
|
2778
|
+
setAddressDetails(response.data);
|
|
2779
|
+
setFormIndex(1);
|
|
2780
|
+
}
|
|
2781
|
+
} catch (e) {
|
|
2782
|
+
setMessage(e?.message || "Failed to generate address");
|
|
2783
|
+
} finally {
|
|
2784
|
+
setGeneratingAddress(false);
|
|
2785
|
+
}
|
|
2786
|
+
};
|
|
2787
|
+
const getAllStableCoins = async () => {
|
|
2788
|
+
setLoadingStableCoins(true);
|
|
2789
|
+
try {
|
|
2790
|
+
const response = await getStableCoins(environment);
|
|
2791
|
+
if (response?.isSuccessful) {
|
|
2792
|
+
setStableCoins(
|
|
2793
|
+
response.data?.map((c) => ({
|
|
2794
|
+
label: c.name,
|
|
2795
|
+
value: c.name
|
|
2796
|
+
})) ?? []
|
|
2797
|
+
);
|
|
2798
|
+
}
|
|
2799
|
+
} catch (e) {
|
|
2800
|
+
setMessage(e?.message || "Failed to get stable coins");
|
|
2801
|
+
} finally {
|
|
2802
|
+
setLoadingStableCoins(false);
|
|
2803
|
+
}
|
|
2804
|
+
};
|
|
2805
|
+
const getAllStableCoinNetworks = async (stableCoin) => {
|
|
2806
|
+
setLoadingStableCoinNetworks(true);
|
|
2807
|
+
try {
|
|
2808
|
+
const response = await getStableCoinNetworks(
|
|
2809
|
+
environment,
|
|
2810
|
+
stableCoin
|
|
2811
|
+
);
|
|
2812
|
+
if (response?.isSuccessful) {
|
|
2813
|
+
setNetworkList(
|
|
2814
|
+
response.networks?.map((n) => ({
|
|
2815
|
+
label: n,
|
|
2816
|
+
value: n
|
|
2817
|
+
})) ?? []
|
|
2818
|
+
);
|
|
2819
|
+
}
|
|
2820
|
+
} catch (e) {
|
|
2821
|
+
setMessage(e?.message || "Failed to get stable coin networks");
|
|
2822
|
+
} finally {
|
|
2823
|
+
setLoadingStableCoinNetworks(false);
|
|
2824
|
+
}
|
|
2825
|
+
};
|
|
2826
|
+
const confirmPaymentHandler = async () => {
|
|
2827
|
+
setIsConfirmingPayment(true);
|
|
2828
|
+
try {
|
|
2829
|
+
const response = await getPaymentReferenceDetails(environment, transactionReference);
|
|
2830
|
+
if (response?.isSuccessful) {
|
|
2831
|
+
setPaymentReferenceDetails(response.data);
|
|
2832
|
+
const needsConfirm = response.data?.finalTransactionStatus == null || response.data?.paymentStatus == null;
|
|
2833
|
+
if (needsConfirm) {
|
|
2834
|
+
setMessage("Transaction not confirmed !!");
|
|
2835
|
+
setPaymentReferenceStatus("pending");
|
|
2836
|
+
onPaymentAuthorized?.({
|
|
2837
|
+
paymentId: transactionReference,
|
|
2838
|
+
paymentDate: response.data?.updatedAt ?? "",
|
|
2839
|
+
paymentStatus: "pending"
|
|
2840
|
+
});
|
|
2841
|
+
} else if (response.data?.finalTransactionStatus === "Success" || response.data?.paymentStatus === "Payment Received") {
|
|
2842
|
+
setMessage("Transaction confirmed !!");
|
|
2843
|
+
setPaymentReferenceStatus("confirmed");
|
|
2844
|
+
onPaymentAuthorized?.({
|
|
2845
|
+
paymentId: transactionReference,
|
|
2846
|
+
paymentDate: response.data?.updatedAt,
|
|
2847
|
+
paymentStatus: "confirmed"
|
|
2848
|
+
});
|
|
2849
|
+
}
|
|
2850
|
+
} else if (!response?.isSuccessful && response?.responseCode === "119") {
|
|
2851
|
+
setPaymentReferenceStatus("used");
|
|
2852
|
+
setMessage(response.responseMessage || "");
|
|
2853
|
+
onPaymentAuthorized?.({
|
|
2854
|
+
paymentId: transactionReference,
|
|
2855
|
+
paymentDate: null,
|
|
2856
|
+
paymentStatus: "used"
|
|
2857
|
+
});
|
|
2858
|
+
}
|
|
2859
|
+
} catch (err) {
|
|
2860
|
+
setPaymentReferenceStatus("");
|
|
2861
|
+
setMessage(
|
|
2862
|
+
err?.error?.responseMessage || err?.error?.message || "Something went wrong"
|
|
2863
|
+
);
|
|
2864
|
+
} finally {
|
|
2865
|
+
setIsConfirmingPayment(false);
|
|
2866
|
+
}
|
|
2867
|
+
};
|
|
2868
|
+
const formatAmountHandler = formatAmount(
|
|
2869
|
+
paymentObject.amount,
|
|
2870
|
+
paymentObject.currency
|
|
2871
|
+
);
|
|
2872
|
+
const payHandler = async () => {
|
|
2873
|
+
const errs = validateGroup(
|
|
2874
|
+
stableCoinForm,
|
|
2875
|
+
stableCoinRules,
|
|
2876
|
+
stableCoinLabels
|
|
2877
|
+
);
|
|
2878
|
+
setStableCoinErrors(errs);
|
|
2879
|
+
if (Object.keys(errs).length === 0) {
|
|
2880
|
+
const payload = {
|
|
2881
|
+
paymentReference: transactionReference,
|
|
2882
|
+
currency: stableCoinForm.stableCoin,
|
|
2883
|
+
chain: stableCoinForm.network,
|
|
2884
|
+
transactionAmount: paymentObject.amount,
|
|
2885
|
+
merchantId: secretKey
|
|
2886
|
+
};
|
|
2887
|
+
setGenerateAddressPayload(payload);
|
|
2888
|
+
await generateAddress(payload);
|
|
2889
|
+
} else {
|
|
2890
|
+
return;
|
|
2891
|
+
}
|
|
1590
2892
|
};
|
|
2893
|
+
const amountPlusNetworkFee = addressDetails ? Number(addressDetails.transactionAmount) + addressDetails.networkFee : 0;
|
|
2894
|
+
useEffect5(() => {
|
|
2895
|
+
(async () => {
|
|
2896
|
+
await generatePaymentLinkHandler();
|
|
2897
|
+
await getAllStableCoins();
|
|
2898
|
+
})();
|
|
2899
|
+
}, []);
|
|
1591
2900
|
return /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-6", children: [
|
|
1592
2901
|
formIndex === 0 && /* @__PURE__ */ jsxs19(Fragment3, { children: [
|
|
1593
2902
|
/* @__PURE__ */ jsxs19("div", { className: "grid grid-cols-1 gap-6", children: [
|
|
@@ -1596,11 +2905,17 @@ var PayByStableCoin = ({ onProceedToPay }) => {
|
|
|
1596
2905
|
{
|
|
1597
2906
|
label: "Select Crypto",
|
|
1598
2907
|
required: true,
|
|
1599
|
-
options:
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
2908
|
+
options: stableCoins,
|
|
2909
|
+
loading: loadingStableCoins,
|
|
2910
|
+
value: stableCoinForm.stableCoin,
|
|
2911
|
+
onChange: (e) => {
|
|
2912
|
+
setStableCoinForm({ ...stableCoinForm, stableCoin: e });
|
|
2913
|
+
getAllStableCoinNetworks(e);
|
|
2914
|
+
if (stableCoinErrors.stableCoin) {
|
|
2915
|
+
setStableCoinErrors((er) => ({ ...er, stableCoin: "" }));
|
|
2916
|
+
}
|
|
2917
|
+
},
|
|
2918
|
+
validationError: stableCoinErrors.stableCoin ?? ""
|
|
1604
2919
|
}
|
|
1605
2920
|
),
|
|
1606
2921
|
/* @__PURE__ */ jsx29(
|
|
@@ -1608,52 +2923,46 @@ var PayByStableCoin = ({ onProceedToPay }) => {
|
|
|
1608
2923
|
{
|
|
1609
2924
|
label: "Select Network",
|
|
1610
2925
|
required: true,
|
|
1611
|
-
options:
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
2926
|
+
options: networkList,
|
|
2927
|
+
loading: loadingStableCoinNetworks,
|
|
2928
|
+
value: stableCoinForm.network,
|
|
2929
|
+
onChange: (e) => {
|
|
2930
|
+
setStableCoinForm({ ...stableCoinForm, network: e });
|
|
2931
|
+
if (stableCoinErrors.network) {
|
|
2932
|
+
setStableCoinErrors((er) => ({ ...er, network: "" }));
|
|
2933
|
+
}
|
|
2934
|
+
},
|
|
2935
|
+
validationError: stableCoinErrors.network ?? ""
|
|
1616
2936
|
}
|
|
1617
2937
|
)
|
|
1618
2938
|
] }),
|
|
1619
2939
|
/* @__PURE__ */ jsx29(
|
|
1620
2940
|
BaseButton,
|
|
1621
2941
|
{
|
|
1622
|
-
label:
|
|
2942
|
+
label: `Pay ${formatAmountHandler}`,
|
|
1623
2943
|
type: "primary",
|
|
1624
2944
|
customClass: "w-full",
|
|
2945
|
+
loading: generatingAddress,
|
|
1625
2946
|
onClick: payHandler
|
|
1626
2947
|
}
|
|
1627
2948
|
)
|
|
1628
2949
|
] }),
|
|
1629
2950
|
formIndex === 1 && /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-6", children: [
|
|
1630
|
-
/* @__PURE__ */
|
|
1631
|
-
/* @__PURE__ */ jsx29(
|
|
1632
|
-
BaseImage,
|
|
1633
|
-
{
|
|
1634
|
-
src: "../../../assets/images/stable-coin-qr-code.png",
|
|
1635
|
-
alt: "QR Code",
|
|
1636
|
-
width: 122,
|
|
1637
|
-
height: 122,
|
|
1638
|
-
customClass: "mb-1"
|
|
1639
|
-
}
|
|
1640
|
-
),
|
|
1641
|
-
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-4xs text-light-copy font-normal text-center", children: "USDC" })
|
|
1642
|
-
] }),
|
|
2951
|
+
/* @__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 }) }),
|
|
1643
2952
|
/* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-6 border-c border-grey-100 p-4 rounded-2xl bg-light-white-50", children: [
|
|
1644
2953
|
/* @__PURE__ */ jsxs19("div", { className: "border-b border-grey-border pb-4 flex flex-col gap-2", children: [
|
|
1645
2954
|
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-3xs text-light-copy font-normal", children: "Network" }),
|
|
1646
2955
|
/* @__PURE__ */ jsxs19("div", { className: "flex justify-between", children: [
|
|
1647
2956
|
/* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-1", children: [
|
|
1648
|
-
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-2xs font-medium text-sub-copy", children:
|
|
2957
|
+
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-2xs font-medium text-sub-copy", children: addressDetails?.chain }),
|
|
1649
2958
|
/* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2", children: [
|
|
1650
2959
|
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-3xs text-light-copy font-normal", children: "*Est. arrival = 3 mins" }),
|
|
1651
2960
|
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-3xs text-light-copy font-normal", children: "|" }),
|
|
1652
2961
|
/* @__PURE__ */ jsx29(
|
|
1653
2962
|
BaseCurrencyAmount,
|
|
1654
2963
|
{
|
|
1655
|
-
currency: "
|
|
1656
|
-
amount:
|
|
2964
|
+
currency: generateAddressPayload?.currency ?? "",
|
|
2965
|
+
amount: addressDetails?.networkFee ?? 0,
|
|
1657
2966
|
textClass: "mb-0 text-body-3xs text-light-copy font-normal",
|
|
1658
2967
|
iconColorClass: "#557591",
|
|
1659
2968
|
iconWidth: 12,
|
|
@@ -1668,8 +2977,8 @@ var PayByStableCoin = ({ onProceedToPay }) => {
|
|
|
1668
2977
|
/* @__PURE__ */ jsxs19("div", { className: "pb-4 flex flex-col gap-2", children: [
|
|
1669
2978
|
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-3xs text-light-copy font-normal", children: "Deposit Address >" }),
|
|
1670
2979
|
/* @__PURE__ */ jsxs19("div", { className: "flex justify-between", children: [
|
|
1671
|
-
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-2xs font-medium text-sub-copy w-2/3 break-words", children:
|
|
1672
|
-
/* @__PURE__ */ jsx29(BaseCopy, { copyText: "
|
|
2980
|
+
/* @__PURE__ */ jsx29("p", { className: "mb-0 text-body-2xs font-medium text-sub-copy w-2/3 break-words", children: addressDetails?.walletAddress }),
|
|
2981
|
+
/* @__PURE__ */ jsx29(BaseCopy, { copyText: addressDetails?.walletAddress ?? "" })
|
|
1673
2982
|
] })
|
|
1674
2983
|
] })
|
|
1675
2984
|
] }),
|
|
@@ -1679,8 +2988,8 @@ var PayByStableCoin = ({ onProceedToPay }) => {
|
|
|
1679
2988
|
/* @__PURE__ */ jsx29(
|
|
1680
2989
|
BaseCurrencyAmount,
|
|
1681
2990
|
{
|
|
1682
|
-
currency: "
|
|
1683
|
-
amount:
|
|
2991
|
+
currency: generateAddressPayload?.currency ?? "",
|
|
2992
|
+
amount: addressDetails?.networkFee ?? 0,
|
|
1684
2993
|
textClass: "mb-0 text-body-2xs font-extrabold text-primary-black",
|
|
1685
2994
|
iconColorClass: "#231F20"
|
|
1686
2995
|
}
|
|
@@ -1691,8 +3000,8 @@ var PayByStableCoin = ({ onProceedToPay }) => {
|
|
|
1691
3000
|
/* @__PURE__ */ jsx29(
|
|
1692
3001
|
BaseCurrencyAmount,
|
|
1693
3002
|
{
|
|
1694
|
-
currency: "
|
|
1695
|
-
amount:
|
|
3003
|
+
currency: generateAddressPayload?.currency ?? "",
|
|
3004
|
+
amount: amountPlusNetworkFee,
|
|
1696
3005
|
textClass: "mb-0 text-body-lg font-extrabold text-primary-black",
|
|
1697
3006
|
iconColorClass: "#231F20",
|
|
1698
3007
|
iconWidth: 20,
|
|
@@ -1706,7 +3015,9 @@ var PayByStableCoin = ({ onProceedToPay }) => {
|
|
|
1706
3015
|
{
|
|
1707
3016
|
label: "Confirm Payment",
|
|
1708
3017
|
type: "primary",
|
|
1709
|
-
customClass: "w-full"
|
|
3018
|
+
customClass: "w-full",
|
|
3019
|
+
loading: isConfirmingPayment,
|
|
3020
|
+
onClick: confirmPaymentHandler
|
|
1710
3021
|
}
|
|
1711
3022
|
) })
|
|
1712
3023
|
] })
|
|
@@ -1716,9 +3027,11 @@ var PayByStableCoin = ({ onProceedToPay }) => {
|
|
|
1716
3027
|
// src/buzapay-checkout/checkout-card.tsx
|
|
1717
3028
|
import { jsx as jsx30, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1718
3029
|
function BzpCheckoutCard({
|
|
3030
|
+
secretKey,
|
|
1719
3031
|
options,
|
|
1720
3032
|
environment = "sandbox",
|
|
1721
3033
|
paymentObject = {
|
|
3034
|
+
merchantName: "",
|
|
1722
3035
|
amount: 0,
|
|
1723
3036
|
currency: "",
|
|
1724
3037
|
email: "",
|
|
@@ -1727,7 +3040,7 @@ function BzpCheckoutCard({
|
|
|
1727
3040
|
redirectUrl: ""
|
|
1728
3041
|
}
|
|
1729
3042
|
}) {
|
|
1730
|
-
const [checkoutState, setCheckoutState] = useState7("
|
|
3043
|
+
const [checkoutState, setCheckoutState] = useState7("PENDING");
|
|
1731
3044
|
const paymentTypeOptions = [
|
|
1732
3045
|
{ label: "Card", value: "CARD" },
|
|
1733
3046
|
{ label: "Bank Transfer", value: "BANK_TRANSFER" },
|
|
@@ -1735,10 +3048,27 @@ function BzpCheckoutCard({
|
|
|
1735
3048
|
];
|
|
1736
3049
|
const [filteredPaymentTypeOptions, setFilteredPaymentTypeOptions] = useState7([]);
|
|
1737
3050
|
const [paymentType, setPaymentType] = useState7("");
|
|
3051
|
+
const [successObject, setSuccessObject] = useState7({
|
|
3052
|
+
paymentDate: "",
|
|
3053
|
+
paymentId: "",
|
|
3054
|
+
paymentStatus: ""
|
|
3055
|
+
});
|
|
1738
3056
|
const paymentTypeHandler = (event) => {
|
|
1739
3057
|
setPaymentType(event);
|
|
1740
3058
|
};
|
|
1741
|
-
|
|
3059
|
+
const setSuccess = (event) => {
|
|
3060
|
+
setSuccessObject({ ...event });
|
|
3061
|
+
if (event.paymentStatus === "Authorized") {
|
|
3062
|
+
setCheckoutState("SUCCESS");
|
|
3063
|
+
} else if (event.paymentStatus === "Payment failed") {
|
|
3064
|
+
setCheckoutState("PENDING");
|
|
3065
|
+
} else if (event.paymentStatus === "used") {
|
|
3066
|
+
setCheckoutState("USED");
|
|
3067
|
+
} else {
|
|
3068
|
+
setCheckoutState("PENDING");
|
|
3069
|
+
}
|
|
3070
|
+
};
|
|
3071
|
+
useEffect6(() => {
|
|
1742
3072
|
let options2 = [];
|
|
1743
3073
|
if (paymentObject.currency === "USD") {
|
|
1744
3074
|
options2 = paymentTypeOptions.filter(
|
|
@@ -1751,63 +3081,91 @@ function BzpCheckoutCard({
|
|
|
1751
3081
|
}
|
|
1752
3082
|
setFilteredPaymentTypeOptions(options2);
|
|
1753
3083
|
}, [paymentObject.currency]);
|
|
1754
|
-
|
|
3084
|
+
useEffect6(() => {
|
|
1755
3085
|
if (filteredPaymentTypeOptions.length) {
|
|
1756
3086
|
setPaymentType(filteredPaymentTypeOptions[0].value);
|
|
1757
3087
|
}
|
|
1758
3088
|
}, [filteredPaymentTypeOptions]);
|
|
1759
|
-
return /* @__PURE__ */ jsx30(BaseCard, {
|
|
1760
|
-
checkoutState === "
|
|
3089
|
+
return /* @__PURE__ */ jsx30(BaseCard, { children: /* @__PURE__ */ jsxs20("div", { className: "grid grid-cols-3", children: [
|
|
3090
|
+
checkoutState === "PENDING" && /* @__PURE__ */ jsxs20("div", { className: "bg-[#EFF7FF] px-6 py-8 flex flex-col gap-5 col-span-1 rounded-l-xl", children: [
|
|
1761
3091
|
/* @__PURE__ */ jsx30("p", { className: "text-heading-text text-body-xs font-semibold", children: "Pay with" }),
|
|
1762
3092
|
/* @__PURE__ */ jsx30(
|
|
1763
3093
|
BaseRadioGroup,
|
|
1764
3094
|
{
|
|
1765
|
-
options:
|
|
3095
|
+
options: filteredPaymentTypeOptions,
|
|
1766
3096
|
selectedChange: (e) => paymentTypeHandler(e)
|
|
1767
3097
|
}
|
|
1768
3098
|
)
|
|
1769
3099
|
] }),
|
|
1770
|
-
/* @__PURE__ */ jsxs20(
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
3100
|
+
/* @__PURE__ */ jsxs20(
|
|
3101
|
+
"div",
|
|
3102
|
+
{
|
|
3103
|
+
className: checkoutState === "SUCCESS" ? "col-span-3" : "col-span-2",
|
|
3104
|
+
children: [
|
|
3105
|
+
checkoutState === "PENDING" && /* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between px-12 py-8", children: [
|
|
3106
|
+
options?.imageUrl ? /* @__PURE__ */ jsx30(
|
|
3107
|
+
BaseImage,
|
|
3108
|
+
{
|
|
3109
|
+
src: options?.imageUrl ?? "",
|
|
3110
|
+
alt: "Merchant Logo",
|
|
3111
|
+
width: 52,
|
|
3112
|
+
height: 52,
|
|
3113
|
+
customClass: "rounded-lg"
|
|
3114
|
+
}
|
|
3115
|
+
) : /* @__PURE__ */ jsx30(
|
|
3116
|
+
"div",
|
|
3117
|
+
{
|
|
3118
|
+
className: "bg-heading-text rounded flex flex-col justify-center",
|
|
3119
|
+
style: { width: "52px", height: "52px" },
|
|
3120
|
+
children: /* @__PURE__ */ jsx30("p", { className: "text-white text-center text-body-2xs font-medium", children: "Logo" })
|
|
3121
|
+
}
|
|
3122
|
+
),
|
|
3123
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex flex-col gap-1", children: [
|
|
3124
|
+
/* @__PURE__ */ jsx30("p", { className: "text-body-2xs font-regular text-sub-copy text-right", children: paymentObject.merchantName }),
|
|
3125
|
+
/* @__PURE__ */ jsxs20("p", { className: "text-body-2xs font-regular text-sub-copy text-right", children: [
|
|
3126
|
+
"Pay:",
|
|
3127
|
+
" ",
|
|
3128
|
+
/* @__PURE__ */ jsx30("span", { className: "text-orange-500 font-extrabold", children: formatAmount(paymentObject.amount, paymentObject.currency) })
|
|
3129
|
+
] })
|
|
3130
|
+
] })
|
|
3131
|
+
] }),
|
|
3132
|
+
checkoutState === "PENDING" && /* @__PURE__ */ jsx30("div", { className: "overflow-y-scroll px-10 pb-10 pt-2", children: paymentType === "CARD" ? /* @__PURE__ */ jsx30(
|
|
3133
|
+
PayByCard,
|
|
3134
|
+
{
|
|
3135
|
+
secretKey,
|
|
3136
|
+
environment,
|
|
3137
|
+
paymentObject,
|
|
3138
|
+
onPaymentAuthorized: setSuccess
|
|
3139
|
+
}
|
|
3140
|
+
) : paymentType === "BANK_TRANSFER" ? /* @__PURE__ */ jsx30(
|
|
3141
|
+
PayByTransfer,
|
|
1775
3142
|
{
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
customClass: "rounded-lg"
|
|
3143
|
+
secretKey,
|
|
3144
|
+
environment,
|
|
3145
|
+
paymentObject,
|
|
3146
|
+
onPaymentAuthorized: setSuccess
|
|
1781
3147
|
}
|
|
1782
3148
|
) : /* @__PURE__ */ jsx30(
|
|
1783
|
-
|
|
3149
|
+
PayByStableCoin,
|
|
1784
3150
|
{
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
3151
|
+
secretKey,
|
|
3152
|
+
environment,
|
|
3153
|
+
paymentObject,
|
|
3154
|
+
onPaymentAuthorized: setSuccess
|
|
1788
3155
|
}
|
|
1789
|
-
),
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
/* @__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(
|
|
1803
|
-
PayByStableCoin,
|
|
1804
|
-
{
|
|
1805
|
-
onProceedToPay: () => setCheckoutState("STABLE_COIN_PAYMENT")
|
|
1806
|
-
}
|
|
1807
|
-
) })
|
|
1808
|
-
] }),
|
|
1809
|
-
checkoutState === "SUCCESS" && /* @__PURE__ */ jsx30(BaseSuccess, {})
|
|
1810
|
-
] })
|
|
3156
|
+
) }),
|
|
3157
|
+
checkoutState === "SUCCESS" && /* @__PURE__ */ jsx30(
|
|
3158
|
+
BaseSuccess,
|
|
3159
|
+
{
|
|
3160
|
+
amount: paymentObject.amount,
|
|
3161
|
+
currency: paymentObject.currency,
|
|
3162
|
+
redirectUrl: paymentObject.redirectUrl,
|
|
3163
|
+
successObject
|
|
3164
|
+
}
|
|
3165
|
+
)
|
|
3166
|
+
]
|
|
3167
|
+
}
|
|
3168
|
+
)
|
|
1811
3169
|
] }) });
|
|
1812
3170
|
}
|
|
1813
3171
|
export {
|