@miden-npm/react 2.1.1 → 2.1.2

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
@@ -154,7 +154,15 @@ var getBaseUrl = (mode, caller) => {
154
154
  if (mode === "sandbox") {
155
155
  return caller === "buzapay" ? "https://sandbox-api.buzapay.com/payment-gateway-api" : "https://sandbox-api.midencards.io/miden-web";
156
156
  } else if (mode === "prod") {
157
- return caller === "buzapay" ? "https://api.buzapay.com/payment-gateway-api" : "https://sandbox-api.midencards.io/miden-web";
157
+ return caller === "buzapay" ? "https://api.buzapay.com/payment-gateway-api" : "https://api.midencards.io/miden-web";
158
+ }
159
+ return "";
160
+ };
161
+ var getBaseAppUrl = (mode, caller) => {
162
+ if (mode === "sandbox") {
163
+ return caller === "buzapay" ? "https://sandbox-merchant.buzapay.com" : "https://sandbox.midencards.io";
164
+ } else if (mode === "prod") {
165
+ return caller === "buzapay" ? "https://merchant.buzapay.com" : "https://midencards.io";
158
166
  }
159
167
  return "";
160
168
  };
@@ -802,6 +810,24 @@ async function generateStableCoinAddress(environment, { merchantId, ...rest }, c
802
810
  } catch (error) {
803
811
  }
804
812
  }
813
+ async function midenConfirmPayment(environment, reference, merchantId, caller) {
814
+ try {
815
+ const baseUrl = getBaseUrl(environment, caller);
816
+ const apiKey = {
817
+ miden: `api/v1/accrual/checkout/confirm-payment/${reference}`
818
+ };
819
+ const res = await fetch(`${baseUrl}/${apiKey[caller]}`, {
820
+ method: "GET",
821
+ headers: {
822
+ "Content-Type": "application/json",
823
+ Accept: "application/json",
824
+ uniqueKey: merchantId
825
+ }
826
+ });
827
+ return await res.json();
828
+ } catch (error) {
829
+ }
830
+ }
805
831
 
806
832
  // src/apis/encrypt.api.ts
807
833
  var import_crypto_js = __toESM(require("crypto-js"), 1);
@@ -2805,6 +2831,7 @@ var BasePhoneNumberInput = ({
2805
2831
  };
2806
2832
 
2807
2833
  // src/components/pay-by-card.tsx
2834
+ var import_react_hot_toast = __toESM(require("react-hot-toast"), 1);
2808
2835
  var import_jsx_runtime36 = require("react/jsx-runtime");
2809
2836
  function PayByCard({
2810
2837
  secretKey,
@@ -2829,6 +2856,7 @@ function PayByCard({
2829
2856
  const [phoneCodeOptions, setPhoneCodeOptions] = (0, import_react10.useState)(
2830
2857
  []
2831
2858
  );
2859
+ const baseAppUrl = getBaseAppUrl(environment, caller);
2832
2860
  const [billingForm, setBillingForm] = (0, import_react10.useState)({
2833
2861
  address1: "",
2834
2862
  address2: "",
@@ -2892,6 +2920,99 @@ function PayByCard({
2892
2920
  cvv: "CVV",
2893
2921
  cardPin: "Card PIN"
2894
2922
  };
2923
+ const [threeDSOpen, setThreeDSOpen] = (0, import_react10.useState)(false);
2924
+ const [threeDSIframeSrc, setThreeDSIframeSrc] = (0, import_react10.useState)("");
2925
+ const messageListenerRef = (0, import_react10.useRef)();
2926
+ const midenThreeDSChallenge = (url, value) => {
2927
+ if (!url || !value) {
2928
+ setMessage("3DS challenge could not be started (missing stepUpUrl/JWT).");
2929
+ return;
2930
+ }
2931
+ const html = `<!doctype html>
2932
+ <html>
2933
+ <head><meta charset="utf-8" /></head>
2934
+ <body onload="document.forms[0].submit()">
2935
+ <form method="POST" action="${url}">
2936
+ <input type="hidden" name="JWT" value="${value}" />
2937
+ </form>
2938
+ </body>
2939
+ </html>`;
2940
+ const dataUrl = `data:text/html;charset=utf-8,${encodeURIComponent(html)}`;
2941
+ setThreeDSIframeSrc(dataUrl);
2942
+ setThreeDSOpen(true);
2943
+ const listener = (event) => {
2944
+ if (event?.data === "challenge_success" || event?.data?.status === "success") {
2945
+ setThreeDSOpen(false);
2946
+ setThreeDSIframeSrc("");
2947
+ handleMidenProceed();
2948
+ }
2949
+ if (event?.data === "challenge_failed" || event?.data?.status === "failed") {
2950
+ setThreeDSOpen(false);
2951
+ setThreeDSIframeSrc("");
2952
+ setMessage("3D Secure verification failed.");
2953
+ setIsMakingPayment(false);
2954
+ }
2955
+ };
2956
+ if (messageListenerRef.current) {
2957
+ window.removeEventListener("message", messageListenerRef.current);
2958
+ }
2959
+ messageListenerRef.current = listener;
2960
+ window.addEventListener("message", listener);
2961
+ };
2962
+ (0, import_react10.useEffect)(() => {
2963
+ return () => {
2964
+ if (messageListenerRef.current) {
2965
+ window.removeEventListener("message", messageListenerRef.current);
2966
+ }
2967
+ };
2968
+ }, []);
2969
+ const handleMidenProceed = async () => {
2970
+ try {
2971
+ setIsMakingPayment(true);
2972
+ const result = await await midenConfirmPayment(
2973
+ environment,
2974
+ transactionReference,
2975
+ secretKey,
2976
+ "miden"
2977
+ );
2978
+ if (result?.isSuccessful) {
2979
+ setMessage("Payment authorization successful.");
2980
+ import_react_hot_toast.default.success("Payment authorization successful.");
2981
+ setIsMakingPayment(false);
2982
+ onPaymentAuthorized?.({
2983
+ paymentId: transactionReference,
2984
+ paymentDate: (/* @__PURE__ */ new Date()).toISOString(),
2985
+ paymentStatus: "authorized",
2986
+ message: "Payment authorization successful."
2987
+ });
2988
+ } else {
2989
+ import_react_hot_toast.default.success("Payment authorization successful.");
2990
+ setIsMakingPayment(false);
2991
+ }
2992
+ } catch (err) {
2993
+ const status = err?.status ?? err?.response?.status;
2994
+ if ([500, 501, 502, 503].includes(status)) {
2995
+ setIsMakingPayment(false);
2996
+ setMessage("Temporary server error. Please try again.");
2997
+ return;
2998
+ }
2999
+ const responseMessage = err?.error?.responseMessage || err?.responseMessage || err?.message || "Payment confirmation failed.";
3000
+ setIsMakingPayment(false);
3001
+ setMessage(responseMessage);
3002
+ import_react_hot_toast.default.error(responseMessage);
3003
+ onError?.({ errorMessage: responseMessage });
3004
+ }
3005
+ };
3006
+ const handleMidenCard = (data) => {
3007
+ const threeDsRequired = data?.threeDsInteractionRequired;
3008
+ if (threeDsRequired) {
3009
+ const url = data?.threeDsHtml?.stepUpUrl;
3010
+ const cred = data?.threeDsHtml?.accessToken;
3011
+ midenThreeDSChallenge(url, cred);
3012
+ } else {
3013
+ handleMidenProceed();
3014
+ }
3015
+ };
2895
3016
  const proceedHandler = async () => {
2896
3017
  if (formIndex === 0) {
2897
3018
  const errs = validateGroup(billingForm, billingRules, billingLabels);
@@ -2939,7 +3060,7 @@ function PayByCard({
2939
3060
  narration: paymentObject?.narration || "Test transaction",
2940
3061
  encryptedCardDetails: encryptedCardDetails.requestParam,
2941
3062
  billingDetails,
2942
- redirectUrl: paymentObject?.redirectUrl || "https://sandbox-merchant.buzapay.com/account/three-ds-status",
3063
+ redirectUrl: paymentObject?.redirectUrl || `${baseAppUrl}/account/three-ds-status`,
2943
3064
  paymentReference: transactionReference,
2944
3065
  isCheckout: true
2945
3066
  };
@@ -2952,7 +3073,7 @@ function PayByCard({
2952
3073
  narration: paymentObject?.narration || "Test transaction",
2953
3074
  encryptedCardDetails: encryptedCardDetails.requestParam,
2954
3075
  billingDetails,
2955
- redirectUrl: paymentObject?.redirectUrl || "",
3076
+ redirectUrl: paymentObject?.redirectUrl || `${baseAppUrl}/pay/verification`,
2956
3077
  paymentReference: transactionReference,
2957
3078
  isCheckout: true,
2958
3079
  postBackUrl: "",
@@ -2966,6 +3087,10 @@ function PayByCard({
2966
3087
  response = decryptPayload(environment, response.responseParam);
2967
3088
  }
2968
3089
  if (response?.isSuccessful) {
3090
+ if (caller === "miden") {
3091
+ handleMidenCard(response);
3092
+ return;
3093
+ }
2969
3094
  if (response.threeDsInteractionRequired === true) {
2970
3095
  const threeDsData = {
2971
3096
  transactionReference: response.transactionReference,
@@ -2979,7 +3104,7 @@ function PayByCard({
2979
3104
  md: response.threeDsHtml?.md
2980
3105
  };
2981
3106
  const stringifiedThreeDsData = btoa(JSON.stringify(threeDsData));
2982
- const threeDsUrl = `https://sandbox-merchant.buzapay.com/account/three-ds-confirm?threeDsData=${encodeURIComponent(
3107
+ const threeDsUrl = `${baseAppUrl}/account/three-ds-confirm?threeDsData=${encodeURIComponent(
2983
3108
  stringifiedThreeDsData
2984
3109
  )}&paymentReference=${response.transactionReference}`;
2985
3110
  window.open(threeDsUrl, "_self", "noopener,noreferrer");
@@ -3002,7 +3127,7 @@ function PayByCard({
3002
3127
  md: response.threeDsHtml?.md
3003
3128
  };
3004
3129
  const stringifiedThreeDsData = btoa(JSON.stringify(threeDsData));
3005
- const threeDsUrl = `https://sandbox-merchant.buzapay.com/account/three-ds-confirm?threeDsData=${encodeURIComponent(
3130
+ const threeDsUrl = `${baseAppUrl}/account/three-ds-confirm?threeDsData=${encodeURIComponent(
3006
3131
  stringifiedThreeDsData
3007
3132
  )}&paymentReference=${response.transactionReference}`;
3008
3133
  window.open(threeDsUrl, "_self", "noopener,noreferrer");
@@ -3164,7 +3289,15 @@ function PayByCard({
3164
3289
  setPhoneCodeOptions(codeOptions);
3165
3290
  })();
3166
3291
  }, []);
3167
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex flex-col gap-6", children: [
3292
+ return threeDSOpen ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-white p-4", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
3293
+ "iframe",
3294
+ {
3295
+ title: "Miden 3DS",
3296
+ src: threeDSIframeSrc,
3297
+ className: "w-full h-full",
3298
+ sandbox: "allow-forms allow-scripts allow-same-origin allow-top-navigation"
3299
+ }
3300
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex flex-col gap-6", children: [
3168
3301
  formIndex === 0 && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "grid grid-cols-2 gap-6 overflow-y-auto", children: [
3169
3302
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "col-span-2", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
3170
3303
  BaseInput,
@@ -4196,7 +4329,7 @@ var PayByStableCoin = ({
4196
4329
  };
4197
4330
 
4198
4331
  // src/buzapay-checkout/checkout-card.tsx
4199
- var import_react_hot_toast = __toESM(require("react-hot-toast"), 1);
4332
+ var import_react_hot_toast2 = __toESM(require("react-hot-toast"), 1);
4200
4333
  var import_jsx_runtime39 = require("react/jsx-runtime");
4201
4334
  function BzpCheckoutCard({
4202
4335
  secretKey,
@@ -4232,25 +4365,23 @@ function BzpCheckoutCard({
4232
4365
  setSuccessObject({ ...event });
4233
4366
  if (event.paymentStatus === "authorized") {
4234
4367
  setCheckoutState("SUCCESS");
4235
- console.log("checkout state", checkoutState);
4236
- debugger;
4237
- import_react_hot_toast.default.success("Payment authorization successful.", toastConfig);
4368
+ import_react_hot_toast2.default.success("Payment authorization successful.", toastConfig);
4238
4369
  } else if (event.paymentStatus === "confirmed") {
4239
4370
  setCheckoutState("SUCCESS");
4240
- import_react_hot_toast.default.success("Payment confirmed.", toastConfig);
4371
+ import_react_hot_toast2.default.success("Payment confirmed.", toastConfig);
4241
4372
  } else if (event.paymentStatus === "payment failed") {
4242
4373
  setCheckoutState("PENDING");
4243
- import_react_hot_toast.default.error("Payment pending.", toastConfig);
4374
+ import_react_hot_toast2.default.error("Payment pending.", toastConfig);
4244
4375
  } else if (event.paymentStatus === "used") {
4245
4376
  setCheckoutState("USED");
4246
4377
  } else {
4247
4378
  setCheckoutState("PENDING");
4248
- import_react_hot_toast.default.error("Payment pending.", toastConfig);
4379
+ import_react_hot_toast2.default.error("Payment pending.", toastConfig);
4249
4380
  }
4250
4381
  onPaymentAuthorized?.(event);
4251
4382
  };
4252
4383
  const onErrorHandler = (error) => {
4253
- import_react_hot_toast.default.error(error.errorMessage ?? "Payment failed.", toastConfig);
4384
+ import_react_hot_toast2.default.error(error.errorMessage ?? "Payment failed.", toastConfig);
4254
4385
  onError?.(error);
4255
4386
  };
4256
4387
  (0, import_react13.useEffect)(() => {
@@ -4278,7 +4409,7 @@ function BzpCheckoutCard({
4278
4409
  }
4279
4410
  }, [filteredPaymentTypeOptions]);
4280
4411
  return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(BaseCard, { children: [
4281
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_react_hot_toast.Toaster, {}),
4412
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_react_hot_toast2.Toaster, {}),
4282
4413
  /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "grid grid-cols-3", children: [
4283
4414
  checkoutState === "PENDING" && /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "bg-[#EFF7FF] px-6 py-8 flex flex-col gap-5 col-span-1 rounded-l-xl", children: [
4284
4415
  /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-heading-text text-body-xs font-semibold", children: "Pay with" }),
@@ -4548,7 +4679,7 @@ function MidenCheckoutButton({
4548
4679
 
4549
4680
  // src/miden-checkout/checkout-card.tsx
4550
4681
  var import_react16 = require("react");
4551
- var import_react_hot_toast2 = __toESM(require("react-hot-toast"), 1);
4682
+ var import_react_hot_toast3 = __toESM(require("react-hot-toast"), 1);
4552
4683
  var import_jsx_runtime42 = require("react/jsx-runtime");
4553
4684
  function MidenCheckoutCard({
4554
4685
  secretKey,
@@ -4585,23 +4716,23 @@ function MidenCheckoutCard({
4585
4716
  setSuccessObject({ ...event });
4586
4717
  if (event.paymentStatus === "authorized") {
4587
4718
  setCheckoutState("SUCCESS");
4588
- import_react_hot_toast2.default.success("Payment authorization successful.", toastConfig);
4719
+ import_react_hot_toast3.default.success("Payment authorization successful.", toastConfig);
4589
4720
  } else if (event.paymentStatus === "confirmed") {
4590
4721
  setCheckoutState("SUCCESS");
4591
- import_react_hot_toast2.default.success("Payment confirmed.", toastConfig);
4722
+ import_react_hot_toast3.default.success("Payment confirmed.", toastConfig);
4592
4723
  } else if (event.paymentStatus === "payment failed") {
4593
4724
  setCheckoutState("PENDING");
4594
- import_react_hot_toast2.default.error("Payment pending.", toastConfig);
4725
+ import_react_hot_toast3.default.error("Payment pending.", toastConfig);
4595
4726
  } else if (event.paymentStatus === "used") {
4596
4727
  setCheckoutState("USED");
4597
4728
  } else {
4598
4729
  setCheckoutState("PENDING");
4599
- import_react_hot_toast2.default.error("Payment pending.", toastConfig);
4730
+ import_react_hot_toast3.default.error("Payment pending.", toastConfig);
4600
4731
  }
4601
4732
  onPaymentAuthorized?.(event);
4602
4733
  };
4603
4734
  const onErrorHandler = (error) => {
4604
- import_react_hot_toast2.default.error(error.errorMessage ?? "Payment failed.", toastConfig);
4735
+ import_react_hot_toast3.default.error(error.errorMessage ?? "Payment failed.", toastConfig);
4605
4736
  onError?.(error);
4606
4737
  };
4607
4738
  const formatAmountHandler = () => {
@@ -4635,7 +4766,7 @@ function MidenCheckoutCard({
4635
4766
  }
4636
4767
  }, [filteredPaymentTypeOptions]);
4637
4768
  return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(BaseCard, { caller: "miden", children: [
4638
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_react_hot_toast2.Toaster, {}),
4769
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_react_hot_toast3.Toaster, {}),
4639
4770
  /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "grid grid-cols-3", children: [
4640
4771
  checkoutState === "PENDING" && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "bg-[#0A0032] py-6 flex flex-col gap-5 col-span-1 rounded-l-xl", children: [
4641
4772
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-white text-body-xs font-semibold px-6", children: "Pay with" }),