@miden-npm/react 0.0.5 → 0.0.7

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