@cimplify/sdk 0.104.0 → 0.105.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/advanced.d.mts +3 -7
  2. package/dist/advanced.d.ts +3 -7
  3. package/dist/advanced.js +23 -23
  4. package/dist/advanced.mjs +4 -4
  5. package/dist/{client-BuLcOWLv.d.ts → catalogue-D1jkpGcr.d.ts} +415 -763
  6. package/dist/{client-D5AoobFc.d.mts → catalogue-DjutZ0FC.d.mts} +415 -763
  7. package/dist/{payment-g0HFkEDU.d.mts → checkout-XoV4HNg2.d.mts} +4156 -1498
  8. package/dist/{payment-g0HFkEDU.d.ts → checkout-XoV4HNg2.d.ts} +4156 -1498
  9. package/dist/{chunk-GOHSXBKW.mjs → chunk-33VCYWVL.mjs} +25 -1
  10. package/dist/{chunk-OKADBZAI.mjs → chunk-37ZZCE7P.mjs} +808 -574
  11. package/dist/{chunk-5BDYDZ4U.js → chunk-3IMPJEUI.js} +892 -657
  12. package/dist/{chunk-YVAEY3VC.js → chunk-7PMMV5X4.js} +1040 -364
  13. package/dist/{chunk-H3RATH4B.mjs → chunk-AVXA4F6G.js} +293 -2
  14. package/dist/{chunk-CNN7Z2IP.js → chunk-EV2EVOYS.js} +27 -0
  15. package/dist/{chunk-4BKOKHE3.js → chunk-NJYR6GGM.mjs} +244 -19
  16. package/dist/{chunk-DYIAX3WI.mjs → chunk-NYDVVNZI.mjs} +11 -2
  17. package/dist/{chunk-E4K2VQDD.js → chunk-PDTXSUHZ.js} +559 -16
  18. package/dist/{chunk-2WPVUIHX.mjs → chunk-Q5HX7LVE.mjs} +1036 -360
  19. package/dist/{chunk-5RT4HYMP.mjs → chunk-TINYV5E2.mjs} +542 -15
  20. package/dist/{chunk-7PDEX54K.js → chunk-UYFTOIFW.js} +13 -3
  21. package/dist/{chunk-OCCNG6MO.mjs → chunk-X7RPMALQ.mjs} +1310 -722
  22. package/dist/{chunk-IQFFSKE2.js → chunk-XHVQDEVO.js} +1345 -746
  23. package/dist/{client-BVNWjk6W.d.ts → client-BBZj15JJ.d.ts} +2 -2
  24. package/dist/{client-fM716k7G.d.mts → client-CZ8MjJ_o.d.mts} +2 -2
  25. package/dist/index-CZjNWbQf.d.ts +8 -0
  26. package/dist/index-DNxWfRHF.d.mts +8 -0
  27. package/dist/{index-BtcoqrY1.d.ts → index-DRMBo26v.d.mts} +9 -4
  28. package/dist/{index-D7Tf3v7c.d.mts → index-DweR60Cv.d.ts} +9 -4
  29. package/dist/index.d.mts +31 -14
  30. package/dist/index.d.ts +31 -14
  31. package/dist/index.js +325 -133
  32. package/dist/index.mjs +6 -6
  33. package/dist/mock/cli.mjs +1450 -386
  34. package/dist/mock/library.js +1176 -352
  35. package/dist/mock/library.mjs +1176 -352
  36. package/dist/mock/msw.js +1176 -352
  37. package/dist/mock/msw.mjs +1176 -352
  38. package/dist/{price-BLIeAb8K.d.ts → price-CUGIYRtD.d.mts} +1 -1
  39. package/dist/{price-Czq_cTC_.d.mts → price-De-sxcuj.d.ts} +1 -1
  40. package/dist/react.d.mts +10 -5
  41. package/dist/react.d.ts +10 -5
  42. package/dist/react.js +227 -197
  43. package/dist/react.mjs +90 -60
  44. package/dist/{server-DKK_D-PP.d.ts → server-Byr4d0hL.d.mts} +31 -57
  45. package/dist/{server-BkVhOIwn.d.mts → server-C_RIDnHU.d.ts} +31 -57
  46. package/dist/server.d.mts +3 -4
  47. package/dist/server.d.ts +3 -4
  48. package/dist/server.js +11 -11
  49. package/dist/server.mjs +5 -5
  50. package/dist/styles.css +2 -2
  51. package/dist/testing/msw.d.mts +2 -2
  52. package/dist/testing/msw.d.ts +2 -2
  53. package/dist/testing/msw.js +4 -4
  54. package/dist/testing/msw.mjs +3 -3
  55. package/dist/testing/suite.d.mts +5 -6
  56. package/dist/testing/suite.d.ts +5 -6
  57. package/dist/testing/suite.js +29 -28
  58. package/dist/testing/suite.mjs +10 -9
  59. package/dist/testing.d.mts +2478 -14
  60. package/dist/testing.d.ts +2478 -14
  61. package/dist/testing.js +167 -89
  62. package/dist/testing.mjs +24 -10
  63. package/dist/utils.d.mts +3 -4
  64. package/dist/utils.d.ts +3 -4
  65. package/dist/utils.js +35 -31
  66. package/dist/utils.mjs +2 -2
  67. package/package.json +9 -9
  68. package/registry/order-history.json +1 -1
  69. package/registry/order-summary.json +1 -1
  70. package/dist/link-D9iSVxt5.d.mts +0 -308
  71. package/dist/link-D9iSVxt5.d.ts +0 -308
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var chunkCNN7Z2IP_js = require('./chunk-CNN7Z2IP.js');
4
- var chunk7PDEX54K_js = require('./chunk-7PDEX54K.js');
5
- var chunk4BKOKHE3_js = require('./chunk-4BKOKHE3.js');
3
+ var chunkEV2EVOYS_js = require('./chunk-EV2EVOYS.js');
4
+ var chunkUYFTOIFW_js = require('./chunk-UYFTOIFW.js');
5
+ var chunkAVXA4F6G_js = require('./chunk-AVXA4F6G.js');
6
6
 
7
7
  // src/types/result.ts
8
8
  function ok(value) {
@@ -117,11 +117,11 @@ function clearIntentIdempotencyKey(scope, storage = sessionStorageOrNull()) {
117
117
 
118
118
  // src/internal/safe.ts
119
119
  function toCimplifyError(error) {
120
- if (error instanceof chunk4BKOKHE3_js.CimplifyError) return chunk4BKOKHE3_js.enrichError(error);
120
+ if (error instanceof chunkAVXA4F6G_js.CimplifyError) return chunkAVXA4F6G_js.enrichError(error);
121
121
  if (error instanceof Error) {
122
- return chunk4BKOKHE3_js.enrichError(new chunk4BKOKHE3_js.CimplifyError(chunk4BKOKHE3_js.ErrorCode.UNKNOWN_ERROR, error.message, false));
122
+ return chunkAVXA4F6G_js.enrichError(new chunkAVXA4F6G_js.CimplifyError(chunkAVXA4F6G_js.ErrorCode.UNKNOWN_ERROR, error.message, false));
123
123
  }
124
- return chunk4BKOKHE3_js.enrichError(new chunk4BKOKHE3_js.CimplifyError(chunk4BKOKHE3_js.ErrorCode.UNKNOWN_ERROR, String(error), false));
124
+ return chunkAVXA4F6G_js.enrichError(new chunkAVXA4F6G_js.CimplifyError(chunkAVXA4F6G_js.ErrorCode.UNKNOWN_ERROR, String(error), false));
125
125
  }
126
126
  async function safe(promise) {
127
127
  try {
@@ -696,7 +696,7 @@ var CartOperations = class {
696
696
  if (typeof updates.quantity !== "number") {
697
697
  return {
698
698
  ok: false,
699
- error: new chunk4BKOKHE3_js.CimplifyError(
699
+ error: new chunkAVXA4F6G_js.CimplifyError(
700
700
  "VALIDATION_ERROR",
701
701
  "updateItem requires a quantity; richer mid-cart edits are not supported"
702
702
  )
@@ -787,703 +787,796 @@ var CartOperations = class {
787
787
  }
788
788
  };
789
789
 
790
- // src/utils/checkout-resolver.ts
791
- var DEFAULT_POLL_INTERVAL_MS = 3e3;
792
- var DEFAULT_MAX_POLL_ATTEMPTS = 60;
793
- var MAX_CONSECUTIVE_NETWORK_ERRORS = 5;
794
- var NEXT_ACTION_NONE = "none";
795
- var NEXT_ACTION_CARD_POPUP = "card_popup";
796
- var NEXT_ACTION_REDIRECT = "redirect";
797
- var NEXT_ACTION_AUTHORIZATION = "authorization";
798
- var NEXT_ACTION_POLL = "poll";
799
- var VALID_MOBILE_MONEY_PROVIDERS = new Set(Object.values(chunkCNN7Z2IP_js.MOBILE_MONEY_PROVIDER));
800
- function isValidMobileMoneyProvider(value) {
801
- return VALID_MOBILE_MONEY_PROVIDERS.has(value);
802
- }
803
- function normalizeAuthorizationType(value) {
804
- if (value && typeof value === "object" && "address" in value) {
805
- return "address";
806
- }
807
- if (typeof value !== "string") return void 0;
808
- const normalized = value.trim().toLowerCase().replace(/[\s-]+/g, "_");
809
- if (normalized === "otp" || normalized === "pin") return normalized;
810
- if (normalized === "phone" || normalized === "birthday" || normalized === "address") {
811
- return normalized;
790
+ // src/payment-authorization/types.ts
791
+ var PAYMENT_AUTHORIZATION_OUTCOME_STATUS = {
792
+ SUBMITTED: "submitted",
793
+ CANCELLED: "cancelled",
794
+ FAILED: "failed"
795
+ };
796
+ var PAYMENT_AUTHORIZATION_PROVIDER = {
797
+ PAYSTACK: "paystack",
798
+ STRIPE: "stripe"
799
+ };
800
+
801
+ // src/payment-authorization/providers/paystack.ts
802
+ var PAYSTACK_POPUP_ERROR = {
803
+ PROVIDER_UNAVAILABLE: chunkAVXA4F6G_js.ErrorCode.PROVIDER_UNAVAILABLE,
804
+ SUBMISSION_UNKNOWN: "SUBMISSION_UNKNOWN",
805
+ CANCELLED: "CANCELLED",
806
+ PAYMENT_CANCELLED: chunkAVXA4F6G_js.ErrorCode.PAYMENT_CANCELLED,
807
+ PAYMENT_FAILED: chunkAVXA4F6G_js.ErrorCode.PAYMENT_FAILED,
808
+ POPUP_BLOCKED: chunkAVXA4F6G_js.ErrorCode.POPUP_BLOCKED
809
+ };
810
+ async function openPaystackPopup(options, signal) {
811
+ if (typeof window === "undefined") {
812
+ return { success: false, error: PAYSTACK_POPUP_ERROR.PROVIDER_UNAVAILABLE };
812
813
  }
813
- return void 0;
814
- }
815
- function normalizeAuthorizationSubmission(expectedType, submission) {
816
- if (!submission || submission.type !== expectedType) {
817
- throw new Error(`Expected ${expectedType} authorization details.`);
814
+ let PaystackPop;
815
+ try {
816
+ const imported = await import('@paystack/inline-js');
817
+ PaystackPop = imported.default;
818
+ } catch {
819
+ return { success: false, error: PAYSTACK_POPUP_ERROR.PROVIDER_UNAVAILABLE };
818
820
  }
819
- if (submission.type === "address") {
820
- const address = submission.address.trim();
821
- const city = submission.city.trim();
822
- const state = submission.state.trim();
823
- const zipCode = submission.zip_code.trim();
824
- if (!address || !city || !state || !zipCode) {
825
- throw new Error("Complete all authorization address fields.");
826
- }
827
- return {
828
- type: "address",
829
- address,
830
- city,
831
- state,
832
- zip_code: zipCode
821
+ return new Promise((resolve) => {
822
+ let settled = false;
823
+ let providerStarted = false;
824
+ const resolveOnce = (result) => {
825
+ if (settled) {
826
+ return;
827
+ }
828
+ settled = true;
829
+ if (signal) {
830
+ signal.removeEventListener("abort", onAbort);
831
+ }
832
+ resolve(result);
833
833
  };
834
- }
835
- const value = submission.value.trim();
836
- if (!value) {
837
- throw new Error("Authorization value is required.");
838
- }
839
- return { type: submission.type, value };
840
- }
841
- function formatMoney(value) {
842
- if (typeof value === "number" && Number.isFinite(value)) {
843
- return value.toFixed(2);
844
- }
845
- if (typeof value === "string" && value.trim().length > 0) {
846
- return value;
847
- }
848
- return "0.00";
849
- }
850
- function createAbortError() {
851
- const error = new Error("CANCELLED");
852
- error.name = "AbortError";
853
- return error;
854
- }
855
- function isAbortError(error) {
856
- if (error instanceof DOMException && error.name === "AbortError") {
857
- return true;
858
- }
859
- return error instanceof Error && (error.name === "AbortError" || error.message === "CANCELLED");
860
- }
861
- function waitForAbortable(promise, signal) {
862
- if (!signal) return promise;
863
- if (signal.aborted) return Promise.reject(createAbortError());
864
- return new Promise((resolve, reject) => {
865
834
  const onAbort = () => {
866
- signal.removeEventListener("abort", onAbort);
867
- reject(createAbortError());
835
+ resolveOnce({
836
+ success: false,
837
+ // Once Paystack owns the transaction, cancellation is ambiguous. The
838
+ // adapter converts this into submitted so Cimplify polling decides.
839
+ error: providerStarted ? PAYSTACK_POPUP_ERROR.SUBMISSION_UNKNOWN : PAYSTACK_POPUP_ERROR.CANCELLED
840
+ });
868
841
  };
869
- signal.addEventListener("abort", onAbort, { once: true });
870
- promise.then(
871
- (value) => {
872
- signal.removeEventListener("abort", onAbort);
873
- resolve(value);
874
- },
875
- (error) => {
876
- signal.removeEventListener("abort", onAbort);
877
- reject(error);
878
- }
879
- );
880
- });
881
- }
882
- var CheckoutResolver = class {
883
- constructor(options) {
884
- this.client = options.client;
885
- this.checkoutData = options.checkoutData;
886
- this.pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
887
- this.maxPollAttempts = options.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS;
888
- this.onStatusChange = options.onStatusChange;
889
- this.onAuthorizationUiChange = options.onAuthorizationUiChange;
890
- this.onAuthorizationRequired = options.onAuthorizationRequired;
891
- this.signal = options.signal;
892
- this.returnUrl = options.returnUrl;
893
- this.enrollInLink = options.enrollInLink !== false;
894
- this.businessId = options.businessId;
895
- this.addressData = options.addressData;
896
- this.paymentData = options.paymentData;
897
- this.orderType = options.orderType;
898
- this.cartTotal = options.cartTotal;
899
- this.cartCurrency = options.cartCurrency;
900
- this.allowPopups = options.allowPopups ?? typeof window !== "undefined";
901
- }
902
- async resolve(checkoutResult) {
842
+ if (signal?.aborted) {
843
+ resolveOnce({ success: false, error: PAYSTACK_POPUP_ERROR.CANCELLED });
844
+ return;
845
+ }
846
+ if (signal) {
847
+ signal.addEventListener("abort", onAbort, { once: true });
848
+ }
903
849
  try {
904
- this.ensureNotAborted();
905
- if (!checkoutResult.order_id) {
906
- return this.fail("CHECKOUT_FAILED", "Checkout did not return an order ID.", false);
907
- }
908
- if (this.isSuccessfulStatus(checkoutResult.payment_status)) {
909
- return this.finalizeSuccess(checkoutResult);
910
- }
911
- if (this.isFailureStatus(checkoutResult.payment_status)) {
912
- const normalized = chunk7PDEX54K_js.normalizeStatusResponse({
913
- status: checkoutResult.payment_status,
914
- paid: false
915
- });
916
- return this.fail(
917
- normalized.status.toUpperCase(),
918
- checkoutResult.display_text || "Payment failed before confirmation.",
919
- false
920
- );
921
- }
922
- const nextAction = checkoutResult.next_action ?? this.deriveLegacyNextAction(checkoutResult);
923
- return this.resolveNextAction({ ...checkoutResult, next_action: nextAction });
924
- } catch (error) {
925
- if (isAbortError(error)) {
926
- return this.fail("CANCELLED", "Checkout was cancelled.", true);
927
- }
928
- const message = error instanceof Error ? error.message : "Checkout failed unexpectedly.";
929
- return this.fail("CHECKOUT_FAILED", message, true);
850
+ const popup = new PaystackPop();
851
+ popup.newTransaction({
852
+ key: options.key,
853
+ email: options.email,
854
+ amount: options.amount,
855
+ currency: options.currency,
856
+ reference: options.reference,
857
+ accessCode: options.accessCode,
858
+ onSuccess: (transaction) => {
859
+ resolveOnce({
860
+ success: true,
861
+ reference: transaction.reference ?? options.reference
862
+ });
863
+ },
864
+ onCancel: () => {
865
+ resolveOnce({ success: false, error: PAYSTACK_POPUP_ERROR.PAYMENT_CANCELLED });
866
+ },
867
+ onError: (error) => {
868
+ resolveOnce({
869
+ success: false,
870
+ error: error?.message || PAYSTACK_POPUP_ERROR.PAYMENT_FAILED
871
+ });
872
+ }
873
+ });
874
+ providerStarted = true;
875
+ } catch {
876
+ resolveOnce({ success: false, error: PAYSTACK_POPUP_ERROR.POPUP_BLOCKED });
930
877
  }
878
+ });
879
+ }
880
+ var PaystackAuthorizationAdapter = class {
881
+ constructor(openPopup = openPaystackPopup) {
882
+ this.openPopup = openPopup;
883
+ this.provider = PAYMENT_AUTHORIZATION_PROVIDER.PAYSTACK;
931
884
  }
932
- deriveLegacyNextAction(checkoutResult) {
933
- if (checkoutResult.client_secret && checkoutResult.public_key) {
885
+ async authorize(context) {
886
+ const result = await this.openPopup(
887
+ {
888
+ key: context.action.public_key,
889
+ email: context.email,
890
+ accessCode: context.action.client_secret,
891
+ reference: context.reference || context.action.client_secret,
892
+ currency: context.currency
893
+ },
894
+ context.signal
895
+ );
896
+ if (result.success) {
897
+ return {
898
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.SUBMITTED,
899
+ reference: result.reference || context.reference
900
+ };
901
+ }
902
+ if (result.error === PAYSTACK_POPUP_ERROR.SUBMISSION_UNKNOWN) {
934
903
  return {
935
- type: NEXT_ACTION_CARD_POPUP,
936
- provider: checkoutResult.provider?.trim().toLowerCase() || "",
937
- client_secret: checkoutResult.client_secret,
938
- public_key: checkoutResult.public_key
904
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.SUBMITTED,
905
+ reference: context.reference
939
906
  };
940
907
  }
941
- if (checkoutResult.authorization_url) {
908
+ if (!result.error || result.error === PAYSTACK_POPUP_ERROR.CANCELLED || result.error === PAYSTACK_POPUP_ERROR.PAYMENT_CANCELLED) {
909
+ return { status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.CANCELLED };
910
+ }
911
+ if (result.error === PAYSTACK_POPUP_ERROR.POPUP_BLOCKED) {
942
912
  return {
943
- type: NEXT_ACTION_REDIRECT,
944
- authorization_url: checkoutResult.authorization_url
913
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
914
+ code: chunkAVXA4F6G_js.ErrorCode.POPUP_BLOCKED,
915
+ message: "Unable to open the Paystack payment popup. Please allow popups and try again.",
916
+ recoverable: true
945
917
  };
946
918
  }
947
- if (checkoutResult.requires_authorization && checkoutResult.authorization_type) {
919
+ if (result.error === PAYSTACK_POPUP_ERROR.PROVIDER_UNAVAILABLE) {
948
920
  return {
949
- type: NEXT_ACTION_AUTHORIZATION,
950
- authorization_type: checkoutResult.authorization_type,
951
- display_text: checkoutResult.display_text
921
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
922
+ code: chunkAVXA4F6G_js.ErrorCode.PROVIDER_UNAVAILABLE,
923
+ message: "Paystack is unavailable in this environment.",
924
+ recoverable: false
952
925
  };
953
926
  }
954
- return { type: NEXT_ACTION_POLL };
927
+ return {
928
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
929
+ code: chunkAVXA4F6G_js.ErrorCode.PAYMENT_FAILED,
930
+ message: result.error || "Paystack payment could not be submitted.",
931
+ recoverable: true
932
+ };
933
+ }
934
+ };
935
+
936
+ // src/payment-authorization/providers/stripe.ts
937
+ var STRIPE_REDIRECT_MODE = "if_required";
938
+ var STRIPE_PAYMENT_ELEMENT_TYPE = "payment";
939
+ async function loadStripeFromPeer(publicKey, options) {
940
+ try {
941
+ const imported = await import('@stripe/stripe-js');
942
+ return imported.loadStripe ? imported.loadStripe(publicKey, options) : null;
943
+ } catch {
944
+ return null;
945
+ }
946
+ }
947
+ function createStripeModal() {
948
+ if (typeof document === "undefined" || !document.body) return null;
949
+ const previousFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;
950
+ const root = document.createElement("div");
951
+ root.setAttribute("role", "dialog");
952
+ root.setAttribute("aria-modal", "true");
953
+ root.setAttribute("aria-label", "Secure card payment");
954
+ Object.assign(root.style, {
955
+ position: "fixed",
956
+ inset: "0",
957
+ zIndex: "2147483647",
958
+ display: "grid",
959
+ placeItems: "center",
960
+ padding: "16px",
961
+ background: "rgba(15, 23, 42, 0.58)"
962
+ });
963
+ const form = document.createElement("form");
964
+ Object.assign(form.style, {
965
+ width: "min(100%, 480px)",
966
+ maxHeight: "calc(100vh - 32px)",
967
+ overflow: "auto",
968
+ borderRadius: "12px",
969
+ padding: "24px",
970
+ background: "#fff",
971
+ boxShadow: "0 24px 80px rgba(15, 23, 42, 0.32)"
972
+ });
973
+ const title = document.createElement("h2");
974
+ title.textContent = "Complete card payment";
975
+ Object.assign(title.style, { margin: "0 0 18px", font: "600 18px/1.4 system-ui" });
976
+ const paymentMount = document.createElement("div");
977
+ paymentMount.setAttribute("data-cimplify-stripe-payment-element", "");
978
+ const error = document.createElement("p");
979
+ error.setAttribute("role", "alert");
980
+ Object.assign(error.style, {
981
+ minHeight: "20px",
982
+ margin: "14px 0 0",
983
+ color: "#b91c1c",
984
+ font: "14px/1.4 system-ui"
985
+ });
986
+ const actions = document.createElement("div");
987
+ Object.assign(actions.style, {
988
+ display: "flex",
989
+ justifyContent: "flex-end",
990
+ gap: "10px",
991
+ marginTop: "18px"
992
+ });
993
+ const cancelButton = document.createElement("button");
994
+ cancelButton.type = "button";
995
+ cancelButton.textContent = "Cancel";
996
+ Object.assign(cancelButton.style, {
997
+ border: "1px solid #cbd5e1",
998
+ borderRadius: "8px",
999
+ padding: "10px 16px",
1000
+ background: "#fff",
1001
+ color: "#0f172a",
1002
+ cursor: "pointer"
1003
+ });
1004
+ const submitButton = document.createElement("button");
1005
+ submitButton.type = "submit";
1006
+ submitButton.textContent = "Pay securely";
1007
+ Object.assign(submitButton.style, {
1008
+ border: "0",
1009
+ borderRadius: "8px",
1010
+ padding: "10px 16px",
1011
+ background: "#0f172a",
1012
+ color: "#fff",
1013
+ cursor: "pointer"
1014
+ });
1015
+ actions.append(cancelButton, submitButton);
1016
+ form.append(title, paymentMount, error, actions);
1017
+ root.append(form);
1018
+ document.body.append(root);
1019
+ cancelButton.focus();
1020
+ return { root, form, paymentMount, submitButton, cancelButton, error, previousFocus };
1021
+ }
1022
+ function stripeFailure(error) {
1023
+ const message = error?.message || "Stripe could not authorize this payment.";
1024
+ if (error?.code === "payment_intent_authentication_failure" || error?.type === "invalid_request_error") {
1025
+ return {
1026
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
1027
+ code: chunkAVXA4F6G_js.ErrorCode.AUTHORIZATION_FAILED,
1028
+ message,
1029
+ recoverable: true
1030
+ };
955
1031
  }
956
- async runCardPopup(action, checkoutResult) {
957
- if (typeof action.provider !== "string" || !action.provider.trim() || typeof action.client_secret !== "string" || !action.client_secret.trim() || typeof action.public_key !== "string" || !action.public_key.trim()) {
1032
+ return {
1033
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
1034
+ code: chunkAVXA4F6G_js.ErrorCode.PAYMENT_FAILED,
1035
+ message,
1036
+ recoverable: true
1037
+ };
1038
+ }
1039
+ var StripeAuthorizationAdapter = class {
1040
+ constructor(loadStripe = loadStripeFromPeer) {
1041
+ this.loadStripe = loadStripe;
1042
+ this.provider = PAYMENT_AUTHORIZATION_PROVIDER.STRIPE;
1043
+ }
1044
+ async authorize(context) {
1045
+ if (typeof window === "undefined" || typeof document === "undefined" || context.signal?.aborted) {
1046
+ return context.signal?.aborted ? { status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.CANCELLED } : {
1047
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
1048
+ code: chunkAVXA4F6G_js.ErrorCode.PROVIDER_UNAVAILABLE,
1049
+ message: "Stripe Payment Element is unavailable in this environment.",
1050
+ recoverable: false
1051
+ };
1052
+ }
1053
+ let stripe;
1054
+ try {
1055
+ stripe = await this.loadStripe(
1056
+ context.action.public_key,
1057
+ context.action.provider_account_id ? { stripeAccount: context.action.provider_account_id } : void 0
1058
+ );
1059
+ } catch (error) {
958
1060
  return {
959
- ok: false,
960
- result: this.fail(
961
- "INVALID_CARD_AUTHORIZATION",
962
- "The payment provider returned an incomplete card authorization response.",
963
- false
964
- )
1061
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
1062
+ code: chunkAVXA4F6G_js.ErrorCode.PROVIDER_UNAVAILABLE,
1063
+ message: error instanceof Error ? error.message : "Stripe.js could not be loaded.",
1064
+ recoverable: true
965
1065
  };
966
1066
  }
967
- this.emit("awaiting_authorization", {
968
- display_text: "Complete payment in the card authorization window.",
969
- order_id: checkoutResult.order_id,
970
- order_number: checkoutResult.order_number,
971
- provider: action.provider
972
- });
973
- if (!this.allowPopups) {
1067
+ if (context.signal?.aborted) {
1068
+ return { status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.CANCELLED };
1069
+ }
1070
+ if (!stripe) {
974
1071
  return {
975
- ok: false,
976
- result: this.fail(
977
- "PROVIDER_UNAVAILABLE",
978
- "Card authorization UI is unavailable in this environment.",
979
- false
980
- )
1072
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
1073
+ code: chunkAVXA4F6G_js.ErrorCode.PROVIDER_UNAVAILABLE,
1074
+ message: "Stripe.js could not be loaded.",
1075
+ recoverable: false
981
1076
  };
982
1077
  }
983
- const currency = this.getOrderCurrency(checkoutResult);
984
- if (!currency) {
1078
+ const modal = createStripeModal();
1079
+ if (!modal) {
985
1080
  return {
986
- ok: false,
987
- result: this.fail("INVALID_CURRENCY", "Payment currency is missing or unsupported.", false)
1081
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
1082
+ code: chunkAVXA4F6G_js.ErrorCode.PROVIDER_UNAVAILABLE,
1083
+ message: "Stripe Payment Element could not be mounted.",
1084
+ recoverable: false
988
1085
  };
989
1086
  }
990
- let outcome;
1087
+ let paymentElement;
1088
+ let elements;
991
1089
  try {
992
- this.notifyAuthorizationUiChange(true);
993
- outcome = await this.client.checkout.authorizeCardPopup(action, {
994
- email: this.checkoutData.customer.email || "customer@cimplify.io",
995
- currency,
996
- reference: checkoutResult.payment_reference,
997
- returnUrl: this.returnUrl,
998
- signal: this.signal
999
- });
1000
- } finally {
1001
- this.notifyAuthorizationUiChange(false);
1002
- }
1003
- if (outcome.status === "submitted") {
1004
- return { ok: true, reference: outcome.reference };
1005
- }
1006
- if (outcome.status === "cancelled") {
1090
+ elements = stripe.elements({ clientSecret: context.action.client_secret });
1091
+ paymentElement = elements.create(STRIPE_PAYMENT_ELEMENT_TYPE);
1092
+ paymentElement.mount(modal.paymentMount);
1093
+ } catch {
1094
+ modal.root.remove();
1095
+ modal.previousFocus?.focus();
1007
1096
  return {
1008
- ok: false,
1009
- result: this.fail(
1010
- "PAYMENT_CANCELLED",
1011
- "Card payment was cancelled before submission.",
1012
- true
1013
- )
1097
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
1098
+ code: chunkAVXA4F6G_js.ErrorCode.PROVIDER_UNAVAILABLE,
1099
+ message: "Stripe Payment Element could not be initialized.",
1100
+ recoverable: false
1014
1101
  };
1015
1102
  }
1016
- return {
1017
- ok: false,
1018
- result: this.fail(outcome.code, outcome.message, outcome.recoverable)
1019
- };
1020
- }
1021
- async resolveNextAction(checkoutResult, resolutionState = {
1022
- authorizationSteps: 0,
1023
- pollAttempts: 0,
1024
- consecutivePollErrors: 0
1025
- }) {
1026
- if (this.isSuccessfulStatus(checkoutResult.payment_status)) {
1027
- return this.finalizeSuccess(checkoutResult);
1028
- }
1029
- let latestCheckoutResult = checkoutResult;
1030
- let paymentReference = checkoutResult.payment_reference;
1031
- let action = checkoutResult.next_action;
1032
- actionLoop: while (true) {
1033
- this.ensureNotAborted();
1034
- switch (action.type) {
1035
- case NEXT_ACTION_NONE:
1036
- break actionLoop;
1037
- case NEXT_ACTION_CARD_POPUP: {
1038
- const limitFailure = this.consumeAuthorizationStep(resolutionState);
1039
- if (limitFailure) return limitFailure;
1040
- const popup = await this.runCardPopup(action, latestCheckoutResult);
1041
- if (!popup.ok) return popup.result;
1042
- paymentReference = popup.reference || paymentReference;
1043
- break actionLoop;
1103
+ if (context.signal?.aborted) {
1104
+ if (paymentElement.destroy) paymentElement.destroy();
1105
+ else paymentElement.unmount?.();
1106
+ modal.root.remove();
1107
+ modal.previousFocus?.focus();
1108
+ return { status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.CANCELLED };
1109
+ }
1110
+ return new Promise((resolve) => {
1111
+ let settled = false;
1112
+ let submitting = false;
1113
+ let confirmationStarted = false;
1114
+ const cleanup = () => {
1115
+ context.signal?.removeEventListener("abort", onAbort);
1116
+ modal.form.removeEventListener("submit", onSubmit);
1117
+ modal.cancelButton.removeEventListener("click", onCancel);
1118
+ if (paymentElement.destroy) paymentElement.destroy();
1119
+ else paymentElement.unmount?.();
1120
+ modal.root.remove();
1121
+ modal.previousFocus?.focus();
1122
+ };
1123
+ const settle = (outcome) => {
1124
+ if (settled) return;
1125
+ settled = true;
1126
+ cleanup();
1127
+ resolve(outcome);
1128
+ };
1129
+ const onAbort = () => {
1130
+ if (confirmationStarted) {
1131
+ settle({
1132
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.SUBMITTED,
1133
+ reference: context.reference
1134
+ });
1135
+ return;
1044
1136
  }
1045
- case NEXT_ACTION_REDIRECT: {
1046
- const limitFailure = this.consumeAuthorizationStep(resolutionState);
1047
- if (limitFailure) return limitFailure;
1048
- const authorizationUrl = chunk7PDEX54K_js.paymentAuthorizationUrl(action.authorization_url);
1049
- if (!authorizationUrl) {
1050
- return this.fail(
1051
- "INVALID_REDIRECT_AUTHORIZATION",
1052
- "The payment provider returned an invalid authorization URL.",
1053
- false
1054
- );
1055
- }
1056
- if (typeof window !== "undefined" && this.returnUrl) {
1057
- window.location.assign(authorizationUrl);
1058
- return this.fail(
1059
- "REDIRECT_REQUIRED",
1060
- "Redirecting to complete payment authorization.",
1061
- true
1062
- );
1063
- }
1064
- if (typeof window !== "undefined") {
1065
- const popup = window.open(
1066
- authorizationUrl,
1067
- "cimplify-auth",
1068
- "width=520,height=760,noopener,noreferrer"
1069
- );
1070
- if (!popup) {
1071
- return this.fail(
1072
- "POPUP_BLOCKED",
1073
- "Authorization popup was blocked. Please allow popups and retry.",
1074
- true
1075
- );
1076
- }
1077
- }
1078
- break actionLoop;
1137
+ settle({ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.CANCELLED });
1138
+ };
1139
+ const onCancel = () => {
1140
+ if (!confirmationStarted) {
1141
+ settle({ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.CANCELLED });
1079
1142
  }
1080
- case NEXT_ACTION_AUTHORIZATION: {
1081
- const limitFailure = this.consumeAuthorizationStep(resolutionState);
1082
- if (limitFailure) return limitFailure;
1083
- const authType = normalizeAuthorizationType(action.authorization_type);
1084
- const authorization = await this.handleAuthorization({
1085
- authorizationType: authType,
1086
- paymentId: latestCheckoutResult.payment_id,
1087
- displayText: action.display_text,
1088
- provider: latestCheckoutResult.provider,
1089
- orderId: latestCheckoutResult.order_id,
1090
- orderNumber: latestCheckoutResult.order_number
1091
- });
1092
- if (!authorization.ok) {
1093
- return authorization.result;
1143
+ };
1144
+ const onSubmit = async (event) => {
1145
+ event.preventDefault();
1146
+ if (submitting || settled) return;
1147
+ submitting = true;
1148
+ modal.submitButton.disabled = true;
1149
+ modal.error.textContent = "";
1150
+ try {
1151
+ const validation = elements.submit ? await elements.submit() : {};
1152
+ if (validation.error) {
1153
+ modal.error.textContent = validation.error.message || "Check your payment details.";
1154
+ submitting = false;
1155
+ modal.submitButton.disabled = false;
1156
+ return;
1094
1157
  }
1095
- if (!authorization.value) {
1096
- break actionLoop;
1158
+ if (settled || context.signal?.aborted) {
1159
+ settle({ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.CANCELLED });
1160
+ return;
1097
1161
  }
1098
- latestCheckoutResult = authorization.value;
1099
- paymentReference = authorization.value.payment_reference || paymentReference;
1100
- if (this.isSuccessfulStatus(authorization.value.payment_status)) {
1101
- return this.finalizeSuccess(authorization.value);
1162
+ confirmationStarted = true;
1163
+ modal.cancelButton.disabled = true;
1164
+ const confirmation = await stripe.confirmPayment({
1165
+ elements,
1166
+ confirmParams: { return_url: context.returnUrl || window.location.href },
1167
+ redirect: STRIPE_REDIRECT_MODE
1168
+ });
1169
+ if (settled) return;
1170
+ if (confirmation.error) {
1171
+ settle(stripeFailure(confirmation.error));
1172
+ return;
1102
1173
  }
1103
- if (this.isFailureStatus(authorization.value.payment_status)) {
1104
- return this.fail(
1105
- "AUTHORIZATION_FAILED",
1106
- authorization.value.display_text || "Payment authorization failed.",
1107
- false
1108
- );
1174
+ settle({
1175
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.SUBMITTED,
1176
+ reference: confirmation.paymentIntent?.id || context.reference
1177
+ });
1178
+ } catch (error) {
1179
+ if (confirmationStarted) {
1180
+ settle({
1181
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.SUBMITTED,
1182
+ reference: context.reference
1183
+ });
1184
+ return;
1109
1185
  }
1110
- action = authorization.value.next_action ?? this.deriveLegacyNextAction(authorization.value);
1111
- continue actionLoop;
1112
- }
1113
- case NEXT_ACTION_POLL:
1114
- break actionLoop;
1115
- default:
1116
- return this.fail(
1117
- "UNSUPPORTED_NEXT_ACTION",
1118
- "The payment provider requested an unsupported authorization action.",
1119
- false
1186
+ settle(
1187
+ stripeFailure({
1188
+ message: error instanceof Error ? error.message : "Stripe confirmation failed."
1189
+ })
1120
1190
  );
1121
- }
1122
- }
1123
- return this.pollUntilTerminal({
1124
- orderId: latestCheckoutResult.order_id,
1125
- latestCheckoutResult,
1126
- paymentReference,
1127
- resolutionState
1191
+ }
1192
+ };
1193
+ modal.form.addEventListener("submit", onSubmit);
1194
+ modal.cancelButton.addEventListener("click", onCancel);
1195
+ context.signal?.addEventListener("abort", onAbort, { once: true });
1196
+ paymentElement.on?.("escape", onCancel);
1197
+ paymentElement.on?.("loaderror", (event) => {
1198
+ if (confirmationStarted) return;
1199
+ settle({
1200
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
1201
+ code: chunkAVXA4F6G_js.ErrorCode.PROVIDER_UNAVAILABLE,
1202
+ message: event?.error?.message || "Stripe Payment Element failed to load.",
1203
+ recoverable: true
1204
+ });
1205
+ });
1128
1206
  });
1129
1207
  }
1130
- consumeAuthorizationStep(resolutionState) {
1131
- if (resolutionState.authorizationSteps >= chunkCNN7Z2IP_js.MAX_PAYMENT_AUTHORIZATION_STEPS) {
1132
- return this.fail(
1133
- "AUTHORIZATION_LIMIT_EXCEEDED",
1134
- "The payment provider requested too many authorization steps.",
1135
- false
1136
- );
1208
+ };
1209
+
1210
+ // src/payment-authorization/registry.ts
1211
+ function normalizeProvider(provider) {
1212
+ return typeof provider === "string" ? provider.trim().toLowerCase() : "";
1213
+ }
1214
+ var PaymentAuthorizationAdapterRegistry = class {
1215
+ constructor(adapters = []) {
1216
+ this.adapters = /* @__PURE__ */ new Map();
1217
+ for (const adapter of adapters) {
1218
+ this.register(adapter);
1137
1219
  }
1138
- resolutionState.authorizationSteps += 1;
1139
- return void 0;
1140
1220
  }
1141
- async pollUntilTerminal(input) {
1142
- const latestCheckoutResult = input.latestCheckoutResult;
1143
- let paymentReference = input.paymentReference;
1144
- const { resolutionState } = input;
1145
- while (resolutionState.pollAttempts < this.maxPollAttempts) {
1146
- this.ensureNotAborted();
1147
- const attempt = resolutionState.pollAttempts;
1148
- resolutionState.pollAttempts += 1;
1149
- this.emit("polling", {
1150
- poll_attempt: attempt,
1151
- max_poll_attempts: this.maxPollAttempts,
1152
- order_id: input.orderId,
1153
- order_number: latestCheckoutResult.order_number
1154
- });
1155
- const statusResult = await this.client.checkout.pollPaymentStatus(input.orderId);
1156
- if (!statusResult.ok) {
1157
- resolutionState.consecutivePollErrors += 1;
1158
- if (resolutionState.consecutivePollErrors >= MAX_CONSECUTIVE_NETWORK_ERRORS) {
1159
- return this.fail(
1160
- "NETWORK_ERROR",
1161
- "Unable to confirm payment due to repeated network errors.",
1162
- true
1163
- );
1164
- }
1165
- await this.wait(this.pollIntervalMs);
1166
- continue;
1167
- }
1168
- resolutionState.consecutivePollErrors = 0;
1169
- if (statusResult.value.reference) {
1170
- paymentReference = statusResult.value.reference;
1171
- }
1172
- const normalized = chunk7PDEX54K_js.normalizeStatusResponse(statusResult.value);
1173
- if (normalized.paid || chunk7PDEX54K_js.isPaymentStatusSuccess(normalized.status)) {
1174
- return this.finalizeSuccess({
1175
- ...latestCheckoutResult,
1176
- payment_status: normalized.status,
1177
- payment_reference: paymentReference || latestCheckoutResult.payment_reference
1178
- });
1179
- }
1180
- if (chunk7PDEX54K_js.isPaymentStatusFailure(normalized.status)) {
1181
- return this.fail(
1182
- normalized.status ? normalized.status.toUpperCase() : "PAYMENT_FAILED",
1183
- normalized.message || "Payment failed during confirmation.",
1184
- false
1185
- );
1186
- }
1187
- if (chunk7PDEX54K_js.isPaymentStatusRequiresAction(normalized.status)) {
1188
- const authorizationType = latestCheckoutResult.authorization_type;
1189
- const paymentId = latestCheckoutResult.payment_id;
1190
- if (!authorizationType || !normalizeAuthorizationType(authorizationType) || !paymentId) {
1191
- return this.fail(
1192
- "INVALID_AUTHORIZATION_RESPONSE",
1193
- "The payment provider returned an incomplete authorization response.",
1194
- false
1195
- );
1196
- }
1197
- return this.resolveNextAction(
1198
- {
1199
- ...latestCheckoutResult,
1200
- payment_status: normalized.status,
1201
- payment_reference: paymentReference,
1202
- display_text: normalized.message || latestCheckoutResult.display_text,
1203
- next_action: {
1204
- type: NEXT_ACTION_AUTHORIZATION,
1205
- authorization_type: authorizationType,
1206
- display_text: normalized.message || latestCheckoutResult.display_text
1207
- }
1208
- },
1209
- resolutionState
1210
- );
1211
- }
1212
- await this.wait(this.pollIntervalMs);
1221
+ register(adapter) {
1222
+ const provider = normalizeProvider(adapter.provider);
1223
+ if (!provider) {
1224
+ throw new TypeError("Payment authorization adapter provider cannot be empty.");
1213
1225
  }
1214
- return this.fail(
1215
- "PAYMENT_TIMEOUT",
1216
- "Payment confirmation timed out. Please retry checkout.",
1217
- true
1218
- );
1226
+ this.adapters.set(provider, adapter);
1227
+ return this;
1219
1228
  }
1220
- async handleAuthorization(input) {
1221
- const authorizationType = input.authorizationType;
1222
- const paymentId = input.paymentId;
1223
- if (!authorizationType || !paymentId) {
1224
- return {
1225
- ok: false,
1226
- result: this.fail(
1227
- "INVALID_AUTHORIZATION_RESPONSE",
1228
- "The payment provider returned an incomplete authorization response.",
1229
- false
1230
- )
1231
- };
1232
- }
1233
- this.emit("awaiting_authorization", {
1234
- authorization_type: authorizationType,
1235
- display_text: input.displayText,
1236
- provider: input.provider,
1237
- order_id: input.orderId,
1238
- order_number: input.orderNumber
1239
- });
1240
- let authorizationRequest;
1241
- const submit = (authorization) => {
1242
- this.ensureNotAborted();
1243
- let normalizedAuthorization;
1244
- try {
1245
- normalizedAuthorization = normalizeAuthorizationSubmission(
1246
- authorizationType,
1247
- authorization
1248
- );
1249
- } catch (error) {
1250
- return Promise.reject(error);
1251
- }
1252
- if (!authorizationRequest) {
1253
- const request = this.client.checkout.submitAuthorization({
1254
- payment_id: paymentId,
1255
- authorization: normalizedAuthorization
1256
- }).then((submitResult) => {
1257
- if (!submitResult.ok) {
1258
- throw new Error(submitResult.error.message || "Authorization failed.");
1259
- }
1260
- return submitResult.value;
1261
- });
1262
- authorizationRequest = request;
1263
- void request.catch(() => {
1264
- if (authorizationRequest === request) {
1265
- authorizationRequest = void 0;
1266
- }
1267
- });
1268
- }
1269
- return authorizationRequest.then(() => void 0);
1270
- };
1271
- try {
1272
- if (this.onAuthorizationRequired) {
1273
- await waitForAbortable(
1274
- Promise.resolve(this.onAuthorizationRequired(authorizationType, submit)),
1275
- this.signal
1276
- );
1277
- } else {
1278
- return {
1279
- ok: false,
1280
- result: this.fail(
1281
- "AUTHORIZATION_REQUIRED",
1282
- "Authorization callback is required in headless checkout mode.",
1283
- false
1284
- )
1285
- };
1286
- }
1287
- if (!authorizationRequest) {
1288
- return {
1289
- ok: false,
1290
- result: this.fail(
1291
- "AUTHORIZATION_NOT_SUBMITTED",
1292
- "The authorization callback returned without submitting a value.",
1293
- true
1294
- )
1295
- };
1296
- }
1297
- return {
1298
- ok: true,
1299
- value: await waitForAbortable(authorizationRequest, this.signal)
1300
- };
1301
- } catch (error) {
1302
- if (isAbortError(error)) {
1303
- return {
1304
- ok: false,
1305
- result: this.fail("CANCELLED", "Checkout was cancelled.", true)
1306
- };
1307
- }
1308
- const message = error instanceof Error ? error.message : "Payment authorization failed.";
1309
- return {
1310
- ok: false,
1311
- result: this.fail("AUTHORIZATION_FAILED", message, true)
1312
- };
1313
- }
1229
+ unregister(provider) {
1230
+ return this.adapters.delete(normalizeProvider(provider));
1314
1231
  }
1315
- async finalizeSuccess(checkoutResult) {
1316
- const currency = this.getOrderCurrency(checkoutResult);
1317
- if (!currency) {
1318
- return this.fail("INVALID_CURRENCY", "Payment currency is missing or unsupported.", false);
1319
- }
1320
- this.emit("finalizing", {
1321
- order_id: checkoutResult.order_id,
1322
- order_number: checkoutResult.order_number
1323
- });
1324
- const enrolledInLink = await this.maybeEnrollInLink(checkoutResult.order_id);
1325
- this.emit("success", {
1326
- order_id: checkoutResult.order_id,
1327
- order_number: checkoutResult.order_number
1328
- });
1329
- return {
1330
- success: true,
1331
- order: {
1332
- id: checkoutResult.order_id,
1333
- order_number: checkoutResult.order_number || checkoutResult.order_id,
1334
- status: checkoutResult.payment_status || "paid",
1335
- total: this.getOrderTotal(checkoutResult),
1336
- currency
1337
- },
1338
- enrolled_in_link: enrolledInLink
1339
- };
1232
+ get(provider) {
1233
+ return this.adapters.get(normalizeProvider(provider));
1340
1234
  }
1341
- async maybeEnrollInLink(orderId) {
1342
- if (!this.enrollInLink || !orderId) {
1343
- return false;
1344
- }
1345
- let businessId = this.businessId;
1346
- if (!businessId) {
1347
- const businessResult = await this.client.business.getInfo();
1348
- if (!businessResult.ok || !businessResult.value?.id) {
1349
- return false;
1350
- }
1351
- businessId = businessResult.value.id;
1352
- }
1353
- const address = this.getEnrollmentAddress();
1354
- const mobileMoney = this.getEnrollmentMobileMoney();
1355
- try {
1356
- const enrollment = await this.client.link.enrollAndLinkOrder({
1357
- order_id: orderId,
1358
- business_id: businessId,
1359
- order_type: this.orderType || this.checkoutData.order_type,
1360
- address,
1361
- mobile_money: mobileMoney
1362
- });
1363
- return enrollment.ok && enrollment.value.success;
1364
- } catch {
1365
- return false;
1366
- }
1235
+ supports(provider) {
1236
+ return this.adapters.has(normalizeProvider(provider));
1367
1237
  }
1368
- getEnrollmentAddress() {
1369
- const source = this.addressData ?? this.checkoutData.address_info;
1370
- if (!source?.street_address) {
1371
- return void 0;
1372
- }
1373
- return {
1374
- label: "Default",
1375
- street_address: source.street_address,
1376
- apartment: source.apartment || void 0,
1377
- city: source.city || "",
1378
- region: source.region || "",
1379
- postal_code: source.postal_code || void 0,
1380
- country: source.country || void 0,
1381
- delivery_instructions: source.delivery_instructions || void 0,
1382
- phone_for_delivery: source.phone_for_delivery || void 0,
1383
- latitude: source.latitude,
1384
- longitude: source.longitude
1385
- };
1238
+ providers() {
1239
+ return [...this.adapters.keys()];
1386
1240
  }
1387
- getEnrollmentMobileMoney() {
1388
- if (this.paymentData?.type === chunkCNN7Z2IP_js.PAYMENT_METHOD.MOBILE_MONEY && this.paymentData.phone_number && this.paymentData.provider && isValidMobileMoneyProvider(this.paymentData.provider)) {
1241
+ async authorize(action, options) {
1242
+ const provider = normalizeProvider(action.provider);
1243
+ if (!provider) {
1389
1244
  return {
1390
- phone_number: this.paymentData.phone_number,
1391
- provider: this.paymentData.provider,
1392
- label: this.paymentData.label || "Mobile Money"
1245
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
1246
+ code: chunkAVXA4F6G_js.ErrorCode.PROVIDER_UNAVAILABLE,
1247
+ message: "Card authorization response did not identify a payment provider.",
1248
+ recoverable: false
1393
1249
  };
1394
1250
  }
1395
- if (this.checkoutData.mobile_money_details?.phone_number) {
1251
+ const adapter = this.adapters.get(provider);
1252
+ if (!adapter) {
1396
1253
  return {
1397
- phone_number: this.checkoutData.mobile_money_details.phone_number,
1398
- provider: this.checkoutData.mobile_money_details.provider,
1399
- label: "Mobile Money"
1254
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
1255
+ code: chunkAVXA4F6G_js.ErrorCode.PROVIDER_UNAVAILABLE,
1256
+ message: `Card authorization provider '${provider}' is not supported by this SDK client.`,
1257
+ recoverable: false
1400
1258
  };
1401
1259
  }
1402
- return void 0;
1403
- }
1404
- getOrderTotal(checkoutResult) {
1405
- if (checkoutResult.fx?.pay_amount !== void 0) {
1406
- return formatMoney(checkoutResult.fx.pay_amount);
1407
- }
1408
- if (this.cartTotal !== void 0) {
1409
- return formatMoney(this.cartTotal);
1260
+ try {
1261
+ const normalizedAction = action.provider === provider ? action : { ...action, provider };
1262
+ return await adapter.authorize({ ...options, action: normalizedAction });
1263
+ } catch (error) {
1264
+ return {
1265
+ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
1266
+ code: chunkAVXA4F6G_js.ErrorCode.PAYMENT_FAILED,
1267
+ message: error instanceof Error ? error.message : `Card authorization provider '${provider}' failed unexpectedly.`,
1268
+ recoverable: true
1269
+ };
1410
1270
  }
1411
- return "0.00";
1412
1271
  }
1413
- getOrderCurrency(checkoutResult) {
1414
- if (checkoutResult.fx?.pay_currency) {
1415
- const currency2 = checkoutResult.fx.pay_currency.trim().toUpperCase();
1416
- return chunk4BKOKHE3_js.isSupportedCurrency(currency2) ? currency2 : void 0;
1417
- }
1418
- if (this.checkoutData.pay_currency) {
1419
- const currency2 = this.checkoutData.pay_currency.trim().toUpperCase();
1420
- return chunk4BKOKHE3_js.isSupportedCurrency(currency2) ? currency2 : void 0;
1421
- }
1422
- const currency = this.cartCurrency.trim().toUpperCase();
1423
- return chunk4BKOKHE3_js.isSupportedCurrency(currency) ? currency : void 0;
1272
+ };
1273
+ function createDefaultPaymentAuthorizationAdapterRegistry() {
1274
+ return new PaymentAuthorizationAdapterRegistry([
1275
+ new PaystackAuthorizationAdapter(),
1276
+ new StripeAuthorizationAdapter()
1277
+ ]);
1278
+ }
1279
+
1280
+ // src/utils/purchase-intent-confirmation.ts
1281
+ var EXACT_ZERO_MONEY = /^[+-]?0+(?:\.0+)?(?:[eE][+-]?\d+)?$/;
1282
+ function isExactlyZeroMoney(value) {
1283
+ if (typeof value === "number") return Object.is(value, 0) || Object.is(value, -0);
1284
+ return EXACT_ZERO_MONEY.test(value.trim());
1285
+ }
1286
+ function selectPurchaseIntentPaymentOption(terms, selection) {
1287
+ return terms.payment_options.filter((option) => option.status === chunkAVXA4F6G_js.PAYMENT_OPTION_STATUS.ELIGIBLE).sort((left, right) => left.rank - right.rank).find(
1288
+ (option) => option.method_kind === selection.method_kind && (selection.payment_option_id === void 0 || option.id === selection.payment_option_id)
1289
+ );
1290
+ }
1291
+ function createPurchaseIntentConfirmation(terms, paymentOption, idempotencyKey) {
1292
+ const normalizedKey = idempotencyKey.trim();
1293
+ if (!normalizedKey) throw new TypeError("idempotencyKey must not be empty");
1294
+ const requiresOption = purchaseIntentRequiresPaymentOption(terms);
1295
+ if (!paymentOption && requiresOption) {
1296
+ throw new TypeError("Nonzero rail terms require an eligible payment option");
1297
+ }
1298
+ if (paymentOption && !requiresOption) {
1299
+ throw new TypeError("Zero-rail terms must not name a payment option");
1300
+ }
1301
+ const authoritativeOption = paymentOption ? terms.payment_options.find(
1302
+ (candidate) => candidate.id === paymentOption.id && candidate.status === chunkAVXA4F6G_js.PAYMENT_OPTION_STATUS.ELIGIBLE
1303
+ ) : void 0;
1304
+ if (paymentOption && !authoritativeOption) {
1305
+ throw new TypeError("Payment option is not eligible for these checkout terms");
1424
1306
  }
1425
- emit(status, context = {}) {
1426
- if (!this.onStatusChange) {
1427
- return;
1307
+ return {
1308
+ accepted_intent_revision: terms.intent_revision,
1309
+ accepted_terms_version: terms.terms_version,
1310
+ accepted_due_now: terms.money.due_now,
1311
+ // Rail fees and routes may differ by option. Consent is to the exact
1312
+ // server-issued buyer debit, never an ambiguous principal/fee aggregate.
1313
+ accepted_customer_debit_amount: authoritativeOption?.customer_debit_amount ?? terms.money.rail_amount,
1314
+ currency: terms.money.currency,
1315
+ payment_option_id: authoritativeOption?.id ?? null,
1316
+ idempotency_key: normalizedKey
1317
+ };
1318
+ }
1319
+ function purchaseIntentRequiresPaymentOption(terms) {
1320
+ return terms.payment_options.length > 0 || !isExactlyZeroMoney(terms.money.rail_amount);
1321
+ }
1322
+
1323
+ // src/utils/purchase-intent-adapter.ts
1324
+ function tenderPreference(form) {
1325
+ if (form.payment_method === chunkAVXA4F6G_js.PURCHASE_INTENT_PAYMENT_METHOD.MOBILE_MONEY) {
1326
+ if (form.link_payment_method_id) {
1327
+ return {
1328
+ method_kind: chunkAVXA4F6G_js.PURCHASE_INTENT_PAYMENT_METHOD.MOBILE_MONEY,
1329
+ authority: {
1330
+ authority_kind: chunkAVXA4F6G_js.MOBILE_MONEY_TENDER_AUTHORITY_KIND.SAVED_REFERENCE,
1331
+ stored_instrument_id: form.link_payment_method_id
1332
+ }
1333
+ };
1428
1334
  }
1429
- try {
1430
- this.onStatusChange(status, context);
1431
- } catch {
1335
+ const details = form.mobile_money_details;
1336
+ if (!details?.phone_number || !details.provider) {
1337
+ throw new chunkAVXA4F6G_js.CimplifyError(
1338
+ chunkAVXA4F6G_js.ErrorCode.INVALID_PAYMENT_METHOD,
1339
+ "Mobile money requires a phone number and network.",
1340
+ false
1341
+ );
1432
1342
  }
1433
- }
1434
- notifyAuthorizationUiChange(open) {
1435
- try {
1436
- this.onAuthorizationUiChange?.(open);
1437
- } catch {
1343
+ const network = chunkUYFTOIFW_js.purchaseIntentMobileMoneyNetwork(details.provider);
1344
+ if (!network) {
1345
+ throw new chunkAVXA4F6G_js.CimplifyError(
1346
+ chunkAVXA4F6G_js.ErrorCode.INVALID_PAYMENT_METHOD,
1347
+ "That mobile money network is not available for PurchaseIntent checkout.",
1348
+ false
1349
+ );
1438
1350
  }
1439
- }
1440
- fail(code, message, recoverable) {
1441
- this.emit("failed", {
1442
- display_text: message
1443
- });
1444
1351
  return {
1445
- success: false,
1446
- error: {
1447
- code,
1448
- message,
1449
- recoverable
1352
+ method_kind: chunkAVXA4F6G_js.PURCHASE_INTENT_PAYMENT_METHOD.MOBILE_MONEY,
1353
+ authority: {
1354
+ authority_kind: chunkAVXA4F6G_js.MOBILE_MONEY_TENDER_AUTHORITY_KIND.TRANSIENT,
1355
+ phone_number: details.phone_number,
1356
+ network
1450
1357
  }
1451
1358
  };
1452
1359
  }
1453
- isSuccessfulStatus(status) {
1454
- const normalized = chunk7PDEX54K_js.normalizeStatusResponse({ status, paid: false });
1455
- return normalized.paid || chunk7PDEX54K_js.isPaymentStatusSuccess(normalized.status);
1360
+ if (form.payment_method === chunkAVXA4F6G_js.LEGACY_CHECKOUT_PAYMENT_METHOD_ALIAS.CASH || form.payment_method === chunkAVXA4F6G_js.PURCHASE_INTENT_PAYMENT_METHOD.OFFLINE) {
1361
+ throw new chunkAVXA4F6G_js.CimplifyError(
1362
+ chunkAVXA4F6G_js.ErrorCode.INVALID_PAYMENT_METHOD,
1363
+ "Offline tender requires an authenticated staff checkout.",
1364
+ false
1365
+ );
1456
1366
  }
1457
- isFailureStatus(status) {
1458
- const normalized = chunk7PDEX54K_js.normalizeStatusResponse({ status, paid: false });
1459
- return chunk7PDEX54K_js.isPaymentStatusFailure(normalized.status);
1367
+ if (form.payment_method === chunkAVXA4F6G_js.PURCHASE_INTENT_PAYMENT_METHOD.CARD) {
1368
+ return {
1369
+ method_kind: chunkAVXA4F6G_js.PURCHASE_INTENT_PAYMENT_METHOD.CARD,
1370
+ stored_instrument_id: form.link_payment_method_id
1371
+ };
1460
1372
  }
1461
- ensureNotAborted() {
1462
- if (this.signal?.aborted) {
1463
- throw createAbortError();
1464
- }
1373
+ if (form.payment_method === chunkAVXA4F6G_js.LEGACY_CHECKOUT_PAYMENT_METHOD_ALIAS.STORE_CREDIT) {
1374
+ return void 0;
1465
1375
  }
1466
- wait(ms) {
1467
- this.ensureNotAborted();
1468
- return new Promise((resolve, reject) => {
1469
- const timer = setTimeout(() => {
1470
- if (this.signal) {
1471
- this.signal.removeEventListener("abort", onAbort);
1376
+ throw new chunkAVXA4F6G_js.CimplifyError(
1377
+ chunkAVXA4F6G_js.ErrorCode.INVALID_PAYMENT_METHOD,
1378
+ "Checkout payment method is not supported.",
1379
+ false
1380
+ );
1381
+ }
1382
+ function checkoutFormToIntentRequest(form, clientIntentKey) {
1383
+ return {
1384
+ client_intent_key: clientIntentKey,
1385
+ source: { kind: chunkAVXA4F6G_js.PURCHASE_INTENT_SOURCE_KIND.CART, cart_id: form.cart_id },
1386
+ checkout: {
1387
+ customer: form.customer,
1388
+ order_type: form.order_type,
1389
+ address_info: form.address_info,
1390
+ location_id: form.location_id,
1391
+ delivery_rate_id: form.delivery_rate_id,
1392
+ special_instructions: form.special_instructions,
1393
+ link_address_id: form.link_address_id,
1394
+ metadata: form.metadata,
1395
+ pay_currency: form.pay_currency,
1396
+ fx_quote_id: form.fx_quote_id,
1397
+ use_store_credit: form.use_store_credit || form.payment_method === chunkAVXA4F6G_js.LEGACY_CHECKOUT_PAYMENT_METHOD_ALIAS.STORE_CREDIT,
1398
+ voucher_code: form.voucher_code,
1399
+ pay_deposit: form.pay_deposit,
1400
+ tender_preference: tenderPreference(form)
1401
+ }
1402
+ };
1403
+ }
1404
+ function selectCheckoutPaymentOption(terms, form) {
1405
+ const preference = tenderPreference(form);
1406
+ if (!preference) return void 0;
1407
+ return terms.payment_options.filter((option) => option.status === chunkAVXA4F6G_js.PAYMENT_OPTION_STATUS.ELIGIBLE).sort((left, right) => left.rank - right.rank).find((option) => option.method_kind === preference.method_kind);
1408
+ }
1409
+ function checkoutFormToConfirmation(_form, terms, paymentOption, idempotencyKey) {
1410
+ return createPurchaseIntentConfirmation(terms, paymentOption, idempotencyKey);
1411
+ }
1412
+ function committedBase(response) {
1413
+ return {
1414
+ intent_id: response.intent_id,
1415
+ attempt_id: response.attempt_id,
1416
+ order_id: response.order_id,
1417
+ order_number: response.order_number || response.order_id,
1418
+ payment_id: response.payment_id
1419
+ };
1420
+ }
1421
+ function confirmationToCheckoutResult(response) {
1422
+ switch (response.status) {
1423
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.ORDER_CREATED:
1424
+ return ok({
1425
+ ...committedBase(response),
1426
+ payment_status: chunkAVXA4F6G_js.LEGACY_CHECKOUT_PAYMENT_STATUS.SUCCEEDED,
1427
+ requires_authorization: false,
1428
+ next_action: { type: chunkEV2EVOYS_js.CHECKOUT_NEXT_ACTION.NONE }
1429
+ });
1430
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.COLLECTION_PROCESSING:
1431
+ return ok({
1432
+ ...committedBase(response),
1433
+ payment_status: chunkAVXA4F6G_js.LEGACY_CHECKOUT_PAYMENT_STATUS.PROCESSING,
1434
+ requires_authorization: false,
1435
+ next_action: { type: chunkEV2EVOYS_js.CHECKOUT_NEXT_ACTION.POLL }
1436
+ });
1437
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.PAYMENT_OUTCOME_UNKNOWN:
1438
+ return ok({
1439
+ ...committedBase(response),
1440
+ payment_status: chunkAVXA4F6G_js.LEGACY_CHECKOUT_PAYMENT_STATUS.UNKNOWN,
1441
+ requires_authorization: false,
1442
+ next_action: { type: chunkEV2EVOYS_js.CHECKOUT_NEXT_ACTION.POLL }
1443
+ });
1444
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.PAYMENT_FAILED:
1445
+ return err(
1446
+ new chunkAVXA4F6G_js.CimplifyError(
1447
+ chunkAVXA4F6G_js.PURCHASE_INTENT_ERROR_CODE.PAYMENT_FAILED,
1448
+ "Payment failed. The order remains recorded, but collection did not succeed.",
1449
+ true
1450
+ )
1451
+ );
1452
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.REDIRECT_REQUIRED:
1453
+ return ok({
1454
+ ...committedBase(response),
1455
+ payment_status: chunkAVXA4F6G_js.LEGACY_CHECKOUT_PAYMENT_STATUS.REQUIRES_ACTION,
1456
+ requires_authorization: false,
1457
+ authorization_url: response.authorization_url,
1458
+ next_action: {
1459
+ type: chunkEV2EVOYS_js.CHECKOUT_NEXT_ACTION.REDIRECT,
1460
+ authorization_url: response.authorization_url
1472
1461
  }
1473
- resolve();
1474
- }, ms);
1475
- const onAbort = () => {
1476
- clearTimeout(timer);
1477
- reject(createAbortError());
1478
- };
1479
- if (this.signal) {
1480
- this.signal.addEventListener("abort", onAbort, { once: true });
1481
- }
1482
- });
1462
+ });
1463
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.CARD_POPUP_REQUIRED:
1464
+ return ok({
1465
+ ...committedBase(response),
1466
+ payment_status: chunkAVXA4F6G_js.LEGACY_CHECKOUT_PAYMENT_STATUS.REQUIRES_ACTION,
1467
+ requires_authorization: false,
1468
+ provider: response.provider,
1469
+ client_secret: response.client_secret,
1470
+ public_key: response.public_key,
1471
+ next_action: {
1472
+ type: chunkEV2EVOYS_js.CHECKOUT_NEXT_ACTION.CARD_POPUP,
1473
+ provider: response.provider,
1474
+ client_secret: response.client_secret,
1475
+ public_key: response.public_key,
1476
+ provider_account_id: response.provider_account_id ?? void 0
1477
+ }
1478
+ });
1479
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.AUTHORIZATION_REQUIRED:
1480
+ return ok({
1481
+ ...committedBase(response),
1482
+ payment_status: chunkAVXA4F6G_js.LEGACY_CHECKOUT_PAYMENT_STATUS.REQUIRES_ACTION,
1483
+ requires_authorization: true,
1484
+ authorization_type: response.authorization_type,
1485
+ display_text: response.display_text,
1486
+ next_action: {
1487
+ type: chunkEV2EVOYS_js.CHECKOUT_NEXT_ACTION.AUTHORIZATION,
1488
+ authorization_type: response.authorization_type,
1489
+ display_text: response.display_text
1490
+ }
1491
+ });
1492
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.TERMS_CHANGED:
1493
+ return err(
1494
+ new chunkAVXA4F6G_js.CimplifyError(
1495
+ chunkAVXA4F6G_js.PURCHASE_INTENT_ERROR_CODE.TERMS_CHANGED,
1496
+ "Checkout terms changed. Review the replacement terms before confirming again.",
1497
+ true
1498
+ )
1499
+ );
1500
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.SELECTION_UNAVAILABLE:
1501
+ return err(
1502
+ new chunkAVXA4F6G_js.CimplifyError(
1503
+ chunkAVXA4F6G_js.PURCHASE_INTENT_ERROR_CODE.SELECTION_UNAVAILABLE,
1504
+ "One or more checkout selections are no longer available.",
1505
+ true
1506
+ )
1507
+ );
1508
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.OFFER_ENDED:
1509
+ return err(
1510
+ new chunkAVXA4F6G_js.CimplifyError(
1511
+ chunkAVXA4F6G_js.PURCHASE_INTENT_ERROR_CODE.OFFER_ENDED,
1512
+ "This offer has ended.",
1513
+ false
1514
+ )
1515
+ );
1516
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.SOURCE_UNAVAILABLE:
1517
+ return err(
1518
+ new chunkAVXA4F6G_js.CimplifyError(
1519
+ chunkAVXA4F6G_js.PURCHASE_INTENT_ERROR_CODE.SOURCE_UNAVAILABLE,
1520
+ "This purchase source is unavailable.",
1521
+ false
1522
+ )
1523
+ );
1483
1524
  }
1484
- };
1525
+ }
1485
1526
 
1486
1527
  // src/checkout.ts
1528
+ function checkoutActionAuthority(response) {
1529
+ if (response.status !== chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.CARD_POPUP_REQUIRED && response.status !== chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.AUTHORIZATION_REQUIRED) {
1530
+ return null;
1531
+ }
1532
+ const paymentId = response.payment_id?.trim();
1533
+ return paymentId ? {
1534
+ intentId: response.intent_id,
1535
+ attemptId: response.attempt_id,
1536
+ paymentId
1537
+ } : null;
1538
+ }
1539
+ function isAmbiguousCheckoutError(error) {
1540
+ return error.code === chunkAVXA4F6G_js.ErrorCode.NETWORK_ERROR || error.code === chunkAVXA4F6G_js.ErrorCode.TIMEOUT;
1541
+ }
1542
+ function authorizationKind(value) {
1543
+ if (value && typeof value === "object" && chunkEV2EVOYS_js.AUTHORIZATION_TYPE.ADDRESS in value) {
1544
+ return chunkEV2EVOYS_js.AUTHORIZATION_TYPE.ADDRESS;
1545
+ }
1546
+ if (value === chunkEV2EVOYS_js.AUTHORIZATION_TYPE.OTP || value === chunkEV2EVOYS_js.AUTHORIZATION_TYPE.PIN || value === chunkEV2EVOYS_js.AUTHORIZATION_TYPE.PHONE || value === chunkEV2EVOYS_js.AUTHORIZATION_TYPE.BIRTHDAY) {
1547
+ return value;
1548
+ }
1549
+ return void 0;
1550
+ }
1551
+ function normalizeAuthorizationSubmission(expected, submission) {
1552
+ if (submission.type !== expected) throw new Error(`Expected ${expected} authorization details.`);
1553
+ if (submission.type === chunkEV2EVOYS_js.AUTHORIZATION_TYPE.ADDRESS) {
1554
+ const address = submission.address.trim();
1555
+ const city = submission.city.trim();
1556
+ const state = submission.state.trim();
1557
+ const zipCode = submission.zip_code.trim();
1558
+ if (!address || !city || !state || !zipCode) {
1559
+ throw new Error("Complete all authorization address fields.");
1560
+ }
1561
+ return { type: chunkEV2EVOYS_js.AUTHORIZATION_TYPE.ADDRESS, address, city, state, zip_code: zipCode };
1562
+ }
1563
+ const value = submission.value.trim();
1564
+ if (!value) throw new Error("Authorization value is required.");
1565
+ return { type: submission.type, value };
1566
+ }
1567
+ var DECIMAL_WIRE_VALUE = /^([+-]?)(\d+)(?:\.(\d+))?(?:[eE][+-]?\d+)?$/;
1568
+ function decimalSign(value) {
1569
+ if (typeof value === "number") {
1570
+ if (!Number.isFinite(value)) return null;
1571
+ if (Object.is(value, 0) || Object.is(value, -0)) return 0;
1572
+ return value > 0 ? 1 : -1;
1573
+ }
1574
+ const match = DECIMAL_WIRE_VALUE.exec(value.trim());
1575
+ if (!match) return null;
1576
+ const nonzero = [...match[2], ...match[3] ?? ""].some((digit) => digit !== "0");
1577
+ if (!nonzero) return 0;
1578
+ return match[1] === "-" ? -1 : 1;
1579
+ }
1487
1580
  function toTerminalFailure(code, message, recoverable) {
1488
1581
  return {
1489
1582
  success: false,
@@ -1499,7 +1592,7 @@ function isValidCustomerName(name) {
1499
1592
  return trimmed.length >= 2 && /\p{L}/u.test(trimmed);
1500
1593
  }
1501
1594
  function isOfflinePaymentMethod(method) {
1502
- return method === "cash" || method === "offline";
1595
+ return method === chunkAVXA4F6G_js.LEGACY_CHECKOUT_PAYMENT_METHOD_ALIAS.CASH || method === chunkAVXA4F6G_js.PURCHASE_INTENT_PAYMENT_METHOD.OFFLINE;
1503
1596
  }
1504
1597
  function notifyCheckoutStatus(observer, status, context = {}) {
1505
1598
  try {
@@ -1507,7 +1600,35 @@ function notifyCheckoutStatus(observer, status, context = {}) {
1507
1600
  } catch {
1508
1601
  }
1509
1602
  }
1603
+ function notifyAuthorizationUi(observer, open) {
1604
+ try {
1605
+ observer?.(open);
1606
+ } catch {
1607
+ }
1608
+ }
1510
1609
  var MAX_STOREFRONT_COLLECTION_OPTIONS = 32;
1610
+ var CHECKOUT_INTENT_SCOPE_PREFIX = "checkout:";
1611
+ var CHECKOUT_CONFIRMATION_SCOPE_PREFIX = "checkout-confirm:";
1612
+ var CHECKOUT_INTENT_RECOVERY_FINGERPRINT = "cart-intent-v1";
1613
+ var ABORT_ERROR_NAME = "AbortError";
1614
+ var AUTHORIZATION_POPUP_NAME = "cimplify-auth";
1615
+ var AUTHORIZATION_POPUP_FEATURES = "width=520,height=760,noopener,noreferrer";
1616
+ var ORDER_TOKEN_QUERY_PARAMETER = "token";
1617
+ var CHECKOUT_API_ROUTE = {
1618
+ COLLECTION_OPTIONS: "/api/v1/payments/collection-options",
1619
+ paymentStatus: (orderId) => `/api/v1/orders/${orderId}/payment-status`,
1620
+ updateCustomer: (orderId) => `/api/v1/orders/${orderId}/customer`,
1621
+ verifyPayment: (orderId) => `/api/v1/orders/${orderId}/verify-payment`
1622
+ };
1623
+ var CHECKOUT_STATUS_BY_PURCHASE_INTENT_RESOLVE_STATUS = {
1624
+ [chunkAVXA4F6G_js.PURCHASE_INTENT_RESOLVE_STATUS.CONFIRMING]: chunkEV2EVOYS_js.CHECKOUT_STATUS.PROCESSING,
1625
+ [chunkAVXA4F6G_js.PURCHASE_INTENT_RESOLVE_STATUS.POLLING]: chunkEV2EVOYS_js.CHECKOUT_STATUS.POLLING,
1626
+ [chunkAVXA4F6G_js.PURCHASE_INTENT_RESOLVE_STATUS.AWAITING_ACTION]: chunkEV2EVOYS_js.CHECKOUT_STATUS.AWAITING_AUTHORIZATION,
1627
+ [chunkAVXA4F6G_js.PURCHASE_INTENT_RESOLVE_STATUS.REVIEWING_TERMS]: chunkEV2EVOYS_js.CHECKOUT_STATUS.REVIEWING_TERMS,
1628
+ [chunkAVXA4F6G_js.PURCHASE_INTENT_RESOLVE_STATUS.COMPLETED]: chunkEV2EVOYS_js.CHECKOUT_STATUS.FINALIZING,
1629
+ [chunkAVXA4F6G_js.PURCHASE_INTENT_RESOLVE_STATUS.FAILED]: chunkEV2EVOYS_js.CHECKOUT_STATUS.FAILED,
1630
+ [chunkAVXA4F6G_js.PURCHASE_INTENT_RESOLVE_STATUS.OUTCOME_UNKNOWN]: chunkEV2EVOYS_js.CHECKOUT_STATUS.RECOVERING
1631
+ };
1511
1632
  function normalizeCollectionOptions(value, expectedCurrency) {
1512
1633
  if (!value || typeof value !== "object") return null;
1513
1634
  const response = value;
@@ -1520,39 +1641,44 @@ function normalizeCollectionOptions(value, expectedCurrency) {
1520
1641
  for (const candidate of response.options) {
1521
1642
  if (!candidate || typeof candidate !== "object") continue;
1522
1643
  const option = candidate;
1523
- if (option.method === chunkCNN7Z2IP_js.PAYMENT_METHOD.CARD && option.network == null) {
1524
- if (!seen.has(chunkCNN7Z2IP_js.PAYMENT_METHOD.CARD)) {
1525
- seen.add(chunkCNN7Z2IP_js.PAYMENT_METHOD.CARD);
1526
- options.push({ method: chunkCNN7Z2IP_js.PAYMENT_METHOD.CARD, network: null });
1644
+ if (option.method === chunkEV2EVOYS_js.PAYMENT_METHOD.CARD && option.network == null) {
1645
+ if (!seen.has(chunkEV2EVOYS_js.PAYMENT_METHOD.CARD)) {
1646
+ seen.add(chunkEV2EVOYS_js.PAYMENT_METHOD.CARD);
1647
+ options.push({ method: chunkEV2EVOYS_js.PAYMENT_METHOD.CARD, network: null });
1527
1648
  }
1528
1649
  continue;
1529
1650
  }
1530
- if (option.method !== chunkCNN7Z2IP_js.PAYMENT_METHOD.MOBILE_MONEY || typeof option.network !== "string" || !option.network.trim()) {
1651
+ if (option.method !== chunkEV2EVOYS_js.PAYMENT_METHOD.MOBILE_MONEY || typeof option.network !== "string" || !option.network.trim()) {
1531
1652
  continue;
1532
1653
  }
1533
- const network = option.network.trim().toLowerCase();
1534
- const key = `${chunkCNN7Z2IP_js.PAYMENT_METHOD.MOBILE_MONEY}:${network}`;
1654
+ const network = chunkUYFTOIFW_js.purchaseIntentMobileMoneyNetwork(option.network);
1655
+ if (!network) continue;
1656
+ const key = `${chunkEV2EVOYS_js.PAYMENT_METHOD.MOBILE_MONEY}:${network}`;
1535
1657
  if (seen.has(key)) continue;
1536
1658
  seen.add(key);
1537
- options.push({ method: chunkCNN7Z2IP_js.PAYMENT_METHOD.MOBILE_MONEY, network });
1659
+ options.push({ method: chunkEV2EVOYS_js.PAYMENT_METHOD.MOBILE_MONEY, network });
1538
1660
  }
1539
1661
  return { presentment_currency: expectedCurrency, options };
1540
1662
  }
1541
1663
  var CheckoutService = class {
1542
1664
  constructor(client) {
1543
1665
  this.client = client;
1666
+ /** Raw checkout material is component-lifetime only, never browser storage. */
1667
+ this.intentCommands = /* @__PURE__ */ new Map();
1668
+ /** Opaque owner/attempt authority for deprecated action submission. */
1669
+ this.actionAuthorities = /* @__PURE__ */ new Map();
1544
1670
  }
1545
1671
  validateCheckoutData(data) {
1546
1672
  if (isOfflinePaymentMethod(data.payment_method)) {
1547
- return new chunk4BKOKHE3_js.CimplifyError(
1548
- "INVALID_PAYMENT_METHOD",
1673
+ return new chunkAVXA4F6G_js.CimplifyError(
1674
+ chunkAVXA4F6G_js.ErrorCode.INVALID_PAYMENT_METHOD,
1549
1675
  "Offline payment isn't available for online checkout. Please pay by card or mobile money.",
1550
1676
  false
1551
1677
  );
1552
1678
  }
1553
1679
  if (!isValidCustomerName(data.customer?.name)) {
1554
- return new chunk4BKOKHE3_js.CimplifyError(
1555
- "INVALID_CUSTOMER_NAME",
1680
+ return new chunkAVXA4F6G_js.CimplifyError(
1681
+ chunkAVXA4F6G_js.ErrorCode.INVALID_CUSTOMER_NAME,
1556
1682
  "Enter your name, not a phone number.",
1557
1683
  false
1558
1684
  );
@@ -1561,15 +1687,15 @@ var CheckoutService = class {
1561
1687
  }
1562
1688
  orderTokenParam(orderId) {
1563
1689
  const token = this.client.getOrderToken(orderId);
1564
- return token ? `?token=${encodeURIComponent(token)}` : "";
1690
+ return token ? `?${ORDER_TOKEN_QUERY_PARAMETER}=${encodeURIComponent(token)}` : "";
1565
1691
  }
1566
1692
  /** Available storefront collection methods for one presentment currency. */
1567
1693
  async collectionOptions(currency) {
1568
1694
  const normalized = currency.trim().toUpperCase();
1569
- if (!chunk4BKOKHE3_js.isSupportedCurrency(normalized)) {
1695
+ if (!chunkAVXA4F6G_js.isSupportedCurrency(normalized)) {
1570
1696
  return err(
1571
- new chunk4BKOKHE3_js.CimplifyError(
1572
- chunk4BKOKHE3_js.ErrorCode.UNSUPPORTED_CURRENCY,
1697
+ new chunkAVXA4F6G_js.CimplifyError(
1698
+ chunkAVXA4F6G_js.ErrorCode.UNSUPPORTED_CURRENCY,
1573
1699
  "No online payment method is available for this currency.",
1574
1700
  false
1575
1701
  )
@@ -1577,14 +1703,14 @@ var CheckoutService = class {
1577
1703
  }
1578
1704
  const response = await safe(
1579
1705
  this.client.get(
1580
- `/api/v1/payments/collection-options?currency=${encodeURIComponent(normalized)}`
1706
+ `${CHECKOUT_API_ROUTE.COLLECTION_OPTIONS}?currency=${encodeURIComponent(normalized)}`
1581
1707
  )
1582
1708
  );
1583
1709
  if (!response.ok) return response;
1584
1710
  const options = normalizeCollectionOptions(response.value, normalized);
1585
1711
  return options ? ok(options) : err(
1586
- new chunk4BKOKHE3_js.CimplifyError(
1587
- chunk4BKOKHE3_js.ErrorCode.PAYMENT_CAPABILITY_MISMATCH,
1712
+ new chunkAVXA4F6G_js.CimplifyError(
1713
+ chunkAVXA4F6G_js.ErrorCode.PAYMENT_CAPABILITY_MISMATCH,
1588
1714
  "Payment methods could not be verified for this currency.",
1589
1715
  false
1590
1716
  )
@@ -1597,52 +1723,181 @@ var CheckoutService = class {
1597
1723
  authorizeCardPopup(action, options) {
1598
1724
  return this.client.authorizationAdapters.authorize(action, options);
1599
1725
  }
1600
- async process(data) {
1726
+ async startIntentCheckout(data, options) {
1601
1727
  const invalid = this.validateCheckoutData(data);
1602
- if (invalid) {
1603
- return err(invalid);
1604
- }
1605
- const intentScope = `checkout:${data.cart_id}`;
1606
- const intentFingerprint = JSON.stringify([
1607
- data.payment_method,
1608
- data.mobile_money_details,
1609
- data.pay_currency,
1610
- data.voucher_code,
1611
- data.pay_deposit
1612
- ]);
1613
- const checkoutData = {
1614
- ...data,
1615
- idempotency_key: data.idempotency_key || intentIdempotencyKey(intentScope, intentFingerprint)
1616
- };
1617
- const result = await safe(this.client.post("/api/v1/checkout", checkoutData));
1618
- if (result.ok) {
1728
+ if (invalid) return err(invalid);
1729
+ const intentScope = `${CHECKOUT_INTENT_SCOPE_PREFIX}${data.cart_id}`;
1730
+ const inMemoryCommand = JSON.stringify(data);
1731
+ const previousCommand = this.intentCommands.get(intentScope);
1732
+ if (previousCommand !== void 0 && previousCommand !== inMemoryCommand) {
1619
1733
  clearIntentIdempotencyKey(intentScope);
1620
- if (result.value.bill_token) {
1621
- this.client.setOrderToken(result.value.order_id, result.value.bill_token);
1734
+ }
1735
+ this.intentCommands.set(intentScope, inMemoryCommand);
1736
+ const clientIntentKey = data.idempotency_key || intentIdempotencyKey(intentScope, CHECKOUT_INTENT_RECOVERY_FINGERPRINT);
1737
+ const checkoutData = { ...data, idempotency_key: clientIntentKey };
1738
+ let mintRequest;
1739
+ try {
1740
+ mintRequest = checkoutFormToIntentRequest(checkoutData, clientIntentKey);
1741
+ } catch (error) {
1742
+ clearIntentIdempotencyKey(intentScope);
1743
+ this.intentCommands.delete(intentScope);
1744
+ return err(
1745
+ error instanceof chunkAVXA4F6G_js.CimplifyError ? error : new chunkAVXA4F6G_js.CimplifyError(
1746
+ chunkAVXA4F6G_js.ErrorCode.CHECKOUT_VALIDATION_FAILED,
1747
+ "Checkout details are invalid.",
1748
+ false
1749
+ )
1750
+ );
1751
+ }
1752
+ const minted = await this.client.purchaseIntents.mint(mintRequest, options);
1753
+ if (!minted.ok) {
1754
+ if (!isAmbiguousCheckoutError(minted.error)) {
1755
+ clearIntentIdempotencyKey(intentScope);
1756
+ this.intentCommands.delete(intentScope);
1622
1757
  }
1623
- } else if (result.error.code !== chunk4BKOKHE3_js.ErrorCode.NETWORK_ERROR && result.error.code !== chunk4BKOKHE3_js.ErrorCode.TIMEOUT) {
1758
+ return minted;
1759
+ }
1760
+ const terms = minted.value.current_terms;
1761
+ if (!terms) {
1624
1762
  clearIntentIdempotencyKey(intentScope);
1763
+ this.intentCommands.delete(intentScope);
1764
+ return err(
1765
+ new chunkAVXA4F6G_js.CimplifyError(
1766
+ chunkAVXA4F6G_js.ErrorCode.CHECKOUT_TERMS_UNAVAILABLE,
1767
+ "Checkout terms are not available for this purchase intent.",
1768
+ true
1769
+ )
1770
+ );
1771
+ }
1772
+ let paymentOption;
1773
+ try {
1774
+ paymentOption = selectCheckoutPaymentOption(terms, checkoutData);
1775
+ } catch (error) {
1776
+ return err(
1777
+ error instanceof chunkAVXA4F6G_js.CimplifyError ? error : new chunkAVXA4F6G_js.CimplifyError(
1778
+ chunkAVXA4F6G_js.ErrorCode.INVALID_PAYMENT_METHOD,
1779
+ "Payment details are invalid.",
1780
+ false
1781
+ )
1782
+ );
1783
+ }
1784
+ if (!paymentOption && purchaseIntentRequiresPaymentOption(terms)) {
1785
+ return err(
1786
+ new chunkAVXA4F6G_js.CimplifyError(
1787
+ chunkAVXA4F6G_js.ErrorCode.PAYMENT_CAPABILITY_MISMATCH,
1788
+ "The selected payment method is not eligible for these checkout terms.",
1789
+ true
1790
+ )
1791
+ );
1792
+ }
1793
+ const confirmationScope = `${CHECKOUT_CONFIRMATION_SCOPE_PREFIX}${minted.value.id}`;
1794
+ const confirmationFingerprint = JSON.stringify([
1795
+ terms.intent_revision,
1796
+ terms.terms_version,
1797
+ terms.terms_digest,
1798
+ paymentOption?.id ?? null,
1799
+ terms.money.due_now,
1800
+ paymentOption?.customer_debit_amount ?? terms.money.rail_amount,
1801
+ terms.money.currency
1802
+ ]);
1803
+ const confirmationKey = intentIdempotencyKey(
1804
+ confirmationScope,
1805
+ confirmationFingerprint
1806
+ );
1807
+ const confirmation = checkoutFormToConfirmation(
1808
+ checkoutData,
1809
+ terms,
1810
+ paymentOption,
1811
+ confirmationKey
1812
+ );
1813
+ const confirmed = await this.client.purchaseIntents.confirm(
1814
+ minted.value.id,
1815
+ confirmation,
1816
+ options
1817
+ );
1818
+ if (!confirmed.ok) {
1819
+ if (!isAmbiguousCheckoutError(confirmed.error)) {
1820
+ clearIntentIdempotencyKey(confirmationScope);
1821
+ }
1822
+ return confirmed;
1823
+ }
1824
+ return ok({
1825
+ intentId: minted.value.id,
1826
+ intentScope,
1827
+ confirmationScope,
1828
+ confirmation,
1829
+ initialResponse: confirmed.value,
1830
+ terms
1831
+ });
1832
+ }
1833
+ /** @deprecated Use `client.purchaseIntents.mint()` then `confirm()`. */
1834
+ async process(data, options) {
1835
+ const started = await this.startIntentCheckout(data, options);
1836
+ if (!started.ok) return started;
1837
+ this.reconcileActionAuthority(started.value.initialResponse);
1838
+ const result = confirmationToCheckoutResult(started.value.initialResponse);
1839
+ if (started.value.initialResponse.status === chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.ORDER_CREATED || started.value.initialResponse.status === chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.PAYMENT_FAILED) {
1840
+ clearIntentIdempotencyKey(started.value.intentScope);
1841
+ clearIntentIdempotencyKey(started.value.confirmationScope);
1842
+ this.intentCommands.delete(started.value.intentScope);
1625
1843
  }
1626
1844
  return result;
1627
1845
  }
1628
1846
  async initializePayment(_orderId, _method) {
1629
1847
  return err(
1630
- new chunk4BKOKHE3_js.CimplifyError(
1631
- "NOT_IMPLEMENTED",
1848
+ new chunkAVXA4F6G_js.CimplifyError(
1849
+ chunkAVXA4F6G_js.ErrorCode.NOT_IMPLEMENTED,
1632
1850
  "initializePayment is not available in REST mode.",
1633
1851
  false
1634
1852
  )
1635
1853
  );
1636
1854
  }
1637
- async submitAuthorization(input) {
1638
- return safe(this.client.post("/api/v1/payments/authorization", input));
1855
+ /**
1856
+ * @deprecated Use `client.purchaseIntents.submitAction()`. This adapter works
1857
+ * only while this CheckoutService instance retains the opaque authority
1858
+ * returned by its own `process()` call; it never falls back to a payment-id
1859
+ * mutation.
1860
+ */
1861
+ async submitAuthorization(input, options) {
1862
+ const paymentId = input.payment_id.trim();
1863
+ const authority = this.actionAuthorities.get(paymentId);
1864
+ if (!authority) {
1865
+ return err(
1866
+ new chunkAVXA4F6G_js.CimplifyError(
1867
+ chunkAVXA4F6G_js.ErrorCode.CHECKOUT_AUTHORITY_REQUIRED,
1868
+ "The purchase-intent action authority is unavailable. Restart checkout before submitting authorization.",
1869
+ false
1870
+ )
1871
+ );
1872
+ }
1873
+ const submitted = await this.client.purchaseIntents.submitAction(
1874
+ authority.intentId,
1875
+ authority.attemptId,
1876
+ { authorization: input.authorization },
1877
+ {
1878
+ signal: options?.signal,
1879
+ timeoutMs: options?.timeoutMs
1880
+ }
1881
+ );
1882
+ if (!submitted.ok) return submitted;
1883
+ this.reconcileActionAuthority(submitted.value, paymentId);
1884
+ return confirmationToCheckoutResult(submitted.value);
1885
+ }
1886
+ reconcileActionAuthority(response, previousPaymentId) {
1887
+ if (previousPaymentId) this.actionAuthorities.delete(previousPaymentId);
1888
+ if ("payment_id" in response && typeof response.payment_id === "string" && response.payment_id.trim()) {
1889
+ this.actionAuthorities.delete(response.payment_id.trim());
1890
+ }
1891
+ const authority = checkoutActionAuthority(response);
1892
+ if (authority) this.actionAuthorities.set(authority.paymentId, authority);
1639
1893
  }
1640
- async pollPaymentStatus(orderId) {
1894
+ async pollPaymentStatus(orderId, options) {
1641
1895
  const encodedId = encodeURIComponent(orderId);
1642
1896
  const tokenParam = this.orderTokenParam(orderId);
1643
1897
  return safe(
1644
1898
  this.client.get(
1645
- `/api/v1/orders/${encodedId}/payment-status${tokenParam}`
1899
+ `${CHECKOUT_API_ROUTE.paymentStatus(encodedId)}${tokenParam}`,
1900
+ options
1646
1901
  )
1647
1902
  );
1648
1903
  }
@@ -1650,20 +1905,58 @@ var CheckoutService = class {
1650
1905
  const encodedId = encodeURIComponent(orderId);
1651
1906
  const tokenParam = this.orderTokenParam(orderId);
1652
1907
  return safe(
1653
- this.client.post(`/api/v1/orders/${encodedId}/customer${tokenParam}`, customer)
1908
+ this.client.post(`${CHECKOUT_API_ROUTE.updateCustomer(encodedId)}${tokenParam}`, customer)
1654
1909
  );
1655
1910
  }
1656
1911
  async verifyPayment(orderId) {
1657
1912
  const encodedId = encodeURIComponent(orderId);
1658
1913
  const tokenParam = this.orderTokenParam(orderId);
1659
- return safe(this.client.post(`/api/v1/orders/${encodedId}/verify-payment${tokenParam}`));
1914
+ return safe(
1915
+ this.client.post(`${CHECKOUT_API_ROUTE.verifyPayment(encodedId)}${tokenParam}`)
1916
+ );
1660
1917
  }
1918
+ async maybeEnrollResolvedOrder(orderId, data) {
1919
+ if (data.enroll_in_link === false) return false;
1920
+ const business = await safe(this.client.resolveBusinessId());
1921
+ if (!business.ok) return false;
1922
+ const address = data.address_info.street_address ? {
1923
+ label: "Default",
1924
+ street_address: data.address_info.street_address,
1925
+ apartment: data.address_info.apartment,
1926
+ city: data.address_info.city ?? "",
1927
+ region: data.address_info.region ?? "",
1928
+ postal_code: data.address_info.postal_code,
1929
+ country: data.address_info.country,
1930
+ delivery_instructions: data.address_info.delivery_instructions,
1931
+ phone_for_delivery: data.address_info.phone_for_delivery,
1932
+ latitude: data.address_info.latitude,
1933
+ longitude: data.address_info.longitude
1934
+ } : void 0;
1935
+ const mobileMoney = data.payment_method === chunkEV2EVOYS_js.PAYMENT_METHOD.MOBILE_MONEY && data.mobile_money_details ? {
1936
+ phone_number: data.mobile_money_details.phone_number,
1937
+ provider: data.mobile_money_details.provider,
1938
+ label: "Mobile Money"
1939
+ } : void 0;
1940
+ try {
1941
+ const enrollment = await this.client.link.enrollAndLinkOrder({
1942
+ order_id: orderId,
1943
+ business_id: business.value,
1944
+ order_type: data.order_type,
1945
+ address,
1946
+ mobile_money: mobileMoney
1947
+ });
1948
+ return enrollment.ok && enrollment.value.success;
1949
+ } catch {
1950
+ return false;
1951
+ }
1952
+ }
1953
+ /** @deprecated Use `client.purchaseIntents.resolve()`. */
1661
1954
  async processAndResolve(data) {
1662
- notifyCheckoutStatus(data.on_status_change, "preparing");
1955
+ notifyCheckoutStatus(data.on_status_change, chunkEV2EVOYS_js.CHECKOUT_STATUS.PREPARING);
1663
1956
  if (!data.cart_id) {
1664
1957
  return ok(
1665
1958
  toTerminalFailure(
1666
- "INVALID_CART",
1959
+ chunkAVXA4F6G_js.ErrorCode.INVALID_CART,
1667
1960
  "A valid cart is required before checkout can start.",
1668
1961
  false
1669
1962
  )
@@ -1671,13 +1964,19 @@ var CheckoutService = class {
1671
1964
  }
1672
1965
  const cartResult = await this.client.cart.get();
1673
1966
  if (!cartResult.ok || !cartResult.value?.id) {
1674
- return ok(toTerminalFailure("INVALID_CART", "Unable to load cart for checkout.", false));
1967
+ return ok(
1968
+ toTerminalFailure(
1969
+ chunkAVXA4F6G_js.ErrorCode.INVALID_CART,
1970
+ "Unable to load cart for checkout.",
1971
+ false
1972
+ )
1973
+ );
1675
1974
  }
1676
1975
  const cart = cartResult.value;
1677
1976
  if (cart.id !== data.cart_id || cart.items.length === 0) {
1678
1977
  return ok(
1679
1978
  toTerminalFailure(
1680
- "INVALID_CART",
1979
+ chunkAVXA4F6G_js.ErrorCode.INVALID_CART,
1681
1980
  "Cart is empty or no longer valid. Please refresh and try again.",
1682
1981
  false
1683
1982
  )
@@ -1704,10 +2003,10 @@ var CheckoutService = class {
1704
2003
  pay_deposit: data.pay_deposit
1705
2004
  };
1706
2005
  const rawBaseCurrency = typeof cart.pricing.currency === "string" ? cart.pricing.currency.trim().toUpperCase() : "";
1707
- if (!chunk4BKOKHE3_js.isSupportedCurrency(rawBaseCurrency)) {
2006
+ if (!chunkAVXA4F6G_js.isSupportedCurrency(rawBaseCurrency)) {
1708
2007
  return ok(
1709
2008
  toTerminalFailure(
1710
- "INVALID_CURRENCY",
2009
+ chunkAVXA4F6G_js.ErrorCode.UNSUPPORTED_CURRENCY,
1711
2010
  "Cart currency is missing or unsupported. Refresh the cart before checkout.",
1712
2011
  false
1713
2012
  )
@@ -1715,18 +2014,27 @@ var CheckoutService = class {
1715
2014
  }
1716
2015
  const baseCurrency = rawBaseCurrency;
1717
2016
  const payCurrency = data.pay_currency?.trim().toUpperCase();
1718
- if (payCurrency && !chunk4BKOKHE3_js.isSupportedCurrency(payCurrency)) {
2017
+ if (payCurrency && !chunkAVXA4F6G_js.isSupportedCurrency(payCurrency)) {
1719
2018
  return ok(
1720
2019
  toTerminalFailure(
1721
- "INVALID_CURRENCY",
2020
+ chunkAVXA4F6G_js.ErrorCode.UNSUPPORTED_CURRENCY,
1722
2021
  "Payment currency is unsupported for checkout.",
1723
2022
  false
1724
2023
  )
1725
2024
  );
1726
2025
  }
1727
- const payCurrencyCode = payCurrency && chunk4BKOKHE3_js.isSupportedCurrency(payCurrency) ? payCurrency : void 0;
1728
- const cartTotalAmount = typeof cart.pricing.total_price === "number" ? cart.pricing.total_price : Number.parseFloat(cart.pricing.total_price || "0");
1729
- if (payCurrencyCode && payCurrencyCode !== baseCurrency && !checkoutData.fx_quote_id && Number.isFinite(cartTotalAmount) && cartTotalAmount > 0) {
2026
+ const payCurrencyCode = payCurrency && chunkAVXA4F6G_js.isSupportedCurrency(payCurrency) ? payCurrency : void 0;
2027
+ const cartTotalSign = decimalSign(cart.pricing.total_price);
2028
+ if (cartTotalSign === null || cartTotalSign < 0) {
2029
+ return ok(
2030
+ toTerminalFailure(
2031
+ chunkAVXA4F6G_js.ErrorCode.CHECKOUT_VALIDATION_FAILED,
2032
+ "Cart total is not a valid non-negative decimal amount.",
2033
+ false
2034
+ )
2035
+ );
2036
+ }
2037
+ if (payCurrencyCode && payCurrencyCode !== baseCurrency && !checkoutData.fx_quote_id && cartTotalSign > 0) {
1730
2038
  const fxQuoteResult = await this.client.fx.lockQuote({
1731
2039
  from: baseCurrency,
1732
2040
  to: payCurrencyCode,
@@ -1735,7 +2043,7 @@ var CheckoutService = class {
1735
2043
  if (!fxQuoteResult.ok) {
1736
2044
  return ok(
1737
2045
  toTerminalFailure(
1738
- "FX_QUOTE_FAILED",
2046
+ chunkAVXA4F6G_js.ErrorCode.FX_QUOTE_FAILED,
1739
2047
  fxQuoteResult.error.message || "Unable to lock FX quote for checkout.",
1740
2048
  true
1741
2049
  )
@@ -1744,35 +2052,266 @@ var CheckoutService = class {
1744
2052
  checkoutData.pay_currency = payCurrencyCode;
1745
2053
  checkoutData.fx_quote_id = fxQuoteResult.value.id;
1746
2054
  }
1747
- notifyCheckoutStatus(data.on_status_change, "processing");
1748
- const processResult = await this.process(checkoutData);
1749
- if (!processResult.ok) {
2055
+ notifyCheckoutStatus(data.on_status_change, chunkEV2EVOYS_js.CHECKOUT_STATUS.PROCESSING);
2056
+ const started = await this.startIntentCheckout(checkoutData, { signal: data.signal });
2057
+ if (!started.ok) {
1750
2058
  return ok(
1751
2059
  toTerminalFailure(
1752
- processResult.error.code || "CHECKOUT_FAILED",
1753
- processResult.error.message || "Unable to process checkout.",
1754
- processResult.error.retryable ?? true
2060
+ started.error.code || chunkAVXA4F6G_js.ErrorCode.CHECKOUT_FAILED,
2061
+ started.error.message || "Unable to process checkout.",
2062
+ started.error.retryable ?? true
2063
+ )
2064
+ );
2065
+ }
2066
+ let actionFailure;
2067
+ try {
2068
+ const resolved = await this.client.purchaseIntents.resolve(started.value.intentId, {
2069
+ confirmation: started.value.confirmation,
2070
+ initialResponse: started.value.initialResponse,
2071
+ pollIntervalMs: data.poll_interval_ms,
2072
+ maxPollAttempts: data.max_poll_attempts,
2073
+ signal: data.signal,
2074
+ onStatusChange: (status, response) => {
2075
+ const context = {};
2076
+ if (response && "order_id" in response) context.order_id = response.order_id;
2077
+ if (response?.status === chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.TERMS_CHANGED) {
2078
+ context.replacement_terms = response.replacement;
2079
+ context.terms_deltas = response.deltas;
2080
+ }
2081
+ if (response?.status === chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.SELECTION_UNAVAILABLE) {
2082
+ context.unavailable_lines = response.lines;
2083
+ }
2084
+ const checkoutStatus = CHECKOUT_STATUS_BY_PURCHASE_INTENT_RESOLVE_STATUS[status];
2085
+ notifyCheckoutStatus(data.on_status_change, checkoutStatus, context);
2086
+ },
2087
+ onActionRequired: async (action) => {
2088
+ switch (action.status) {
2089
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.CARD_POPUP_REQUIRED: {
2090
+ const allowPopups = data.allow_popups ?? typeof window !== "undefined";
2091
+ if (!allowPopups) {
2092
+ actionFailure = {
2093
+ code: chunkAVXA4F6G_js.ErrorCode.PROVIDER_UNAVAILABLE,
2094
+ message: "Card authorization UI is unavailable in this environment.",
2095
+ recoverable: false
2096
+ };
2097
+ return chunkAVXA4F6G_js.PURCHASE_INTENT_ACTION_DECISION.STOP;
2098
+ }
2099
+ let outcome;
2100
+ try {
2101
+ notifyAuthorizationUi(data.on_authorization_ui_change, true);
2102
+ outcome = await this.authorizeCardPopup(
2103
+ {
2104
+ type: chunkEV2EVOYS_js.CHECKOUT_NEXT_ACTION.CARD_POPUP,
2105
+ provider: action.provider,
2106
+ client_secret: action.client_secret,
2107
+ public_key: action.public_key,
2108
+ provider_account_id: action.provider_account_id ?? void 0
2109
+ },
2110
+ {
2111
+ email: checkoutData.customer.email,
2112
+ currency: started.value.terms.money.currency,
2113
+ returnUrl: data.return_url,
2114
+ signal: data.signal
2115
+ }
2116
+ );
2117
+ } finally {
2118
+ notifyAuthorizationUi(data.on_authorization_ui_change, false);
2119
+ }
2120
+ if (outcome.status === PAYMENT_AUTHORIZATION_OUTCOME_STATUS.SUBMITTED) {
2121
+ return chunkAVXA4F6G_js.PURCHASE_INTENT_ACTION_DECISION.CONTINUE;
2122
+ }
2123
+ actionFailure = outcome.status === PAYMENT_AUTHORIZATION_OUTCOME_STATUS.CANCELLED ? {
2124
+ code: chunkAVXA4F6G_js.ErrorCode.PAYMENT_CANCELLED,
2125
+ message: "Card payment was cancelled before submission.",
2126
+ recoverable: true
2127
+ } : {
2128
+ code: outcome.code,
2129
+ message: outcome.message,
2130
+ recoverable: outcome.recoverable
2131
+ };
2132
+ return chunkAVXA4F6G_js.PURCHASE_INTENT_ACTION_DECISION.STOP;
2133
+ }
2134
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.REDIRECT_REQUIRED: {
2135
+ const authorizationUrl = chunkUYFTOIFW_js.paymentAuthorizationUrl(action.authorization_url);
2136
+ if (!authorizationUrl) {
2137
+ actionFailure = {
2138
+ code: chunkAVXA4F6G_js.ErrorCode.AUTHORIZATION_FAILED,
2139
+ message: "The provider returned an invalid authorization URL.",
2140
+ recoverable: false
2141
+ };
2142
+ return chunkAVXA4F6G_js.PURCHASE_INTENT_ACTION_DECISION.STOP;
2143
+ }
2144
+ if (typeof window !== "undefined") {
2145
+ if (data.allow_popups === false) {
2146
+ window.location.assign(authorizationUrl);
2147
+ } else {
2148
+ const popup = window.open(
2149
+ authorizationUrl,
2150
+ AUTHORIZATION_POPUP_NAME,
2151
+ AUTHORIZATION_POPUP_FEATURES
2152
+ );
2153
+ if (!popup) {
2154
+ actionFailure = {
2155
+ code: chunkAVXA4F6G_js.ErrorCode.POPUP_BLOCKED,
2156
+ message: "Authorization popup was blocked.",
2157
+ recoverable: true
2158
+ };
2159
+ return chunkAVXA4F6G_js.PURCHASE_INTENT_ACTION_DECISION.STOP;
2160
+ }
2161
+ }
2162
+ }
2163
+ actionFailure = {
2164
+ code: chunkAVXA4F6G_js.ErrorCode.REDIRECT_REQUIRED,
2165
+ message: "Complete authorization at the payment provider, then resume checkout.",
2166
+ recoverable: true
2167
+ };
2168
+ return chunkAVXA4F6G_js.PURCHASE_INTENT_ACTION_DECISION.STOP;
2169
+ }
2170
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.AUTHORIZATION_REQUIRED: {
2171
+ const expected = authorizationKind(action.authorization_type);
2172
+ if (!expected || !data.on_authorization_required) {
2173
+ actionFailure = {
2174
+ code: chunkAVXA4F6G_js.ErrorCode.AUTHORIZATION_REQUIRED,
2175
+ message: "Additional payment authorization is required.",
2176
+ recoverable: true
2177
+ };
2178
+ return chunkAVXA4F6G_js.PURCHASE_INTENT_ACTION_DECISION.STOP;
2179
+ }
2180
+ let submission;
2181
+ await data.on_authorization_required(expected, async (candidate) => {
2182
+ if (submission) throw new Error("Authorization was already submitted.");
2183
+ submission = normalizeAuthorizationSubmission(expected, candidate);
2184
+ });
2185
+ if (!submission) {
2186
+ actionFailure = {
2187
+ code: chunkAVXA4F6G_js.ErrorCode.AUTHORIZATION_REQUIRED,
2188
+ message: "Payment authorization was not submitted.",
2189
+ recoverable: true
2190
+ };
2191
+ return chunkAVXA4F6G_js.PURCHASE_INTENT_ACTION_DECISION.STOP;
2192
+ }
2193
+ return {
2194
+ kind: chunkAVXA4F6G_js.PURCHASE_INTENT_ACTION_DECISION.SUBMIT,
2195
+ request: { authorization: submission }
2196
+ };
2197
+ }
2198
+ }
2199
+ }
2200
+ });
2201
+ if (!resolved.ok) {
2202
+ return ok(
2203
+ toTerminalFailure(
2204
+ resolved.error.code || chunkAVXA4F6G_js.ErrorCode.CHECKOUT_FAILED,
2205
+ resolved.error.message || "Unable to resolve checkout.",
2206
+ resolved.error.retryable ?? true
2207
+ )
2208
+ );
2209
+ }
2210
+ switch (resolved.value.kind) {
2211
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_RESOLUTION_KIND.COMPLETED: {
2212
+ clearIntentIdempotencyKey(started.value.intentScope);
2213
+ clearIntentIdempotencyKey(started.value.confirmationScope);
2214
+ const response = resolved.value.response;
2215
+ notifyCheckoutStatus(data.on_status_change, chunkEV2EVOYS_js.CHECKOUT_STATUS.FINALIZING, {
2216
+ order_id: response.order_id
2217
+ });
2218
+ const enrolledInLink = await this.maybeEnrollResolvedOrder(response.order_id, data);
2219
+ notifyCheckoutStatus(data.on_status_change, chunkEV2EVOYS_js.CHECKOUT_STATUS.SUCCESS, {
2220
+ order_id: response.order_id
2221
+ });
2222
+ return ok({
2223
+ success: true,
2224
+ order: {
2225
+ id: response.order_id,
2226
+ order_number: response.order_number ?? response.order_id,
2227
+ status: chunkEV2EVOYS_js.CHECKOUT_ORDER_RESULT_STATUS.CONFIRMED,
2228
+ total: String(cart.pricing.total_price),
2229
+ currency: started.value.terms.money.currency
2230
+ },
2231
+ enrolled_in_link: enrolledInLink
2232
+ });
2233
+ }
2234
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_RESOLUTION_KIND.FAILED:
2235
+ clearIntentIdempotencyKey(started.value.confirmationScope);
2236
+ return ok(
2237
+ toTerminalFailure(
2238
+ chunkAVXA4F6G_js.PURCHASE_INTENT_ERROR_CODE.PAYMENT_FAILED,
2239
+ "Payment failed. Choose another method or retry collection.",
2240
+ true
2241
+ )
2242
+ );
2243
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_RESOLUTION_KIND.OUTCOME_UNKNOWN:
2244
+ return ok(
2245
+ toTerminalFailure(
2246
+ chunkAVXA4F6G_js.ErrorCode.PAYMENT_OUTCOME_UNKNOWN,
2247
+ "Payment outcome is still unknown. Resume this intent before retrying.",
2248
+ true
2249
+ )
2250
+ );
2251
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_RESOLUTION_KIND.TIMED_OUT:
2252
+ return ok(
2253
+ toTerminalFailure(
2254
+ chunkAVXA4F6G_js.ErrorCode.TIMEOUT,
2255
+ "Payment is still processing. Resume this intent to continue polling.",
2256
+ true
2257
+ )
2258
+ );
2259
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_RESOLUTION_KIND.ACTION_REQUIRED:
2260
+ return ok(
2261
+ toTerminalFailure(
2262
+ actionFailure?.code ?? chunkAVXA4F6G_js.ErrorCode.AUTHORIZATION_REQUIRED,
2263
+ actionFailure?.message ?? "Checkout requires additional authorization.",
2264
+ actionFailure?.recoverable ?? true
2265
+ )
2266
+ );
2267
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_RESOLUTION_KIND.REVIEW_REQUIRED: {
2268
+ const response = resolved.value.response;
2269
+ switch (response.status) {
2270
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.TERMS_CHANGED:
2271
+ return ok(
2272
+ toTerminalFailure(
2273
+ chunkAVXA4F6G_js.PURCHASE_INTENT_ERROR_CODE.TERMS_CHANGED,
2274
+ "Checkout terms changed and require explicit review.",
2275
+ true
2276
+ )
2277
+ );
2278
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.SELECTION_UNAVAILABLE:
2279
+ return ok(
2280
+ toTerminalFailure(
2281
+ chunkAVXA4F6G_js.PURCHASE_INTENT_ERROR_CODE.SELECTION_UNAVAILABLE,
2282
+ "One or more checkout selections are unavailable.",
2283
+ true
2284
+ )
2285
+ );
2286
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.OFFER_ENDED:
2287
+ return ok(
2288
+ toTerminalFailure(
2289
+ chunkAVXA4F6G_js.PURCHASE_INTENT_ERROR_CODE.OFFER_ENDED,
2290
+ "This offer has ended.",
2291
+ false
2292
+ )
2293
+ );
2294
+ case chunkAVXA4F6G_js.PURCHASE_INTENT_CONFIRM_STATUS.SOURCE_UNAVAILABLE:
2295
+ return ok(
2296
+ toTerminalFailure(
2297
+ chunkAVXA4F6G_js.PURCHASE_INTENT_ERROR_CODE.SOURCE_UNAVAILABLE,
2298
+ "This purchase source is unavailable.",
2299
+ false
2300
+ )
2301
+ );
2302
+ }
2303
+ }
2304
+ }
2305
+ } catch (error) {
2306
+ const cancelled = data.signal?.aborted || error instanceof Error && error.name === ABORT_ERROR_NAME;
2307
+ return ok(
2308
+ toTerminalFailure(
2309
+ cancelled ? chunkAVXA4F6G_js.ErrorCode.CANCELLED : chunkAVXA4F6G_js.ErrorCode.AUTHORIZATION_FAILED,
2310
+ cancelled ? "Checkout was cancelled." : error instanceof Error ? error.message : "Checkout authorization failed.",
2311
+ true
1755
2312
  )
1756
2313
  );
1757
2314
  }
1758
- const resolver = new CheckoutResolver({
1759
- client: this.client,
1760
- checkoutData,
1761
- pollIntervalMs: data.poll_interval_ms,
1762
- maxPollAttempts: data.max_poll_attempts,
1763
- onStatusChange: data.on_status_change,
1764
- onAuthorizationUiChange: data.on_authorization_ui_change,
1765
- onAuthorizationRequired: data.on_authorization_required,
1766
- signal: data.signal,
1767
- returnUrl: data.return_url,
1768
- enrollInLink: data.enroll_in_link,
1769
- cartTotal: cart.pricing.total_price,
1770
- cartCurrency: checkoutData.pay_currency || baseCurrency,
1771
- orderType: checkoutData.order_type,
1772
- allowPopups: data.allow_popups
1773
- });
1774
- const resolved = await resolver.resolve(processResult.value);
1775
- return ok(resolved);
1776
2315
  }
1777
2316
  };
1778
2317
 
@@ -1850,7 +2389,7 @@ var LinkService = class {
1850
2389
  supersededActivation() {
1851
2390
  return {
1852
2391
  ok: false,
1853
- error: new chunk4BKOKHE3_js.CimplifyError(
2392
+ error: new chunkAVXA4F6G_js.CimplifyError(
1854
2393
  "session_superseded",
1855
2394
  "A newer authentication session replaced this one"
1856
2395
  )
@@ -2131,7 +2670,7 @@ var BusinessService = class {
2131
2670
  if (!result.ok) return err(result.error);
2132
2671
  const location = result.value.find((item) => item.id === locationId);
2133
2672
  if (!location) {
2134
- return err(new chunk4BKOKHE3_js.CimplifyError(chunk4BKOKHE3_js.ErrorCode.NOT_FOUND, `Location not found: ${locationId}`, false));
2673
+ return err(new chunkAVXA4F6G_js.CimplifyError(chunkAVXA4F6G_js.ErrorCode.NOT_FOUND, `Location not found: ${locationId}`, false));
2135
2674
  }
2136
2675
  return ok(location);
2137
2676
  }
@@ -2407,6 +2946,8 @@ var MESSAGE_TYPES = {
2407
2946
  CONTACT_PROVIDED: "contact_provided",
2408
2947
  CHECKOUT_STATUS: "checkout_status",
2409
2948
  CHECKOUT_COMPLETE: "checkout_complete",
2949
+ TERMS_CHANGED: "terms_changed",
2950
+ SELECTION_UNAVAILABLE: "selection_unavailable",
2410
2951
  ORDER_TYPE_CHANGED: "order_type_changed",
2411
2952
  REQUEST_SUBMIT: "request_submit"
2412
2953
  };
@@ -2754,7 +3295,7 @@ function startRedirectSignIn(opts, authorizeEndpoint, pkce, state) {
2754
3295
 
2755
3296
  // src/elements.ts
2756
3297
  function toCheckoutError(code, message, recoverable) {
2757
- const hint = chunk4BKOKHE3_js.getErrorHint(code);
3298
+ const hint = chunkAVXA4F6G_js.getErrorHint(code);
2758
3299
  return {
2759
3300
  success: false,
2760
3301
  error: {
@@ -2827,6 +3368,8 @@ var KNOWN_IFRAME_TYPES = /* @__PURE__ */ new Set([
2827
3368
  MESSAGE_TYPES.LOGOUT_COMPLETE,
2828
3369
  MESSAGE_TYPES.CHECKOUT_STATUS,
2829
3370
  MESSAGE_TYPES.CHECKOUT_COMPLETE,
3371
+ MESSAGE_TYPES.TERMS_CHANGED,
3372
+ MESSAGE_TYPES.SELECTION_UNAVAILABLE,
2830
3373
  MESSAGE_TYPES.ORDER_TYPE_CHANGED,
2831
3374
  MESSAGE_TYPES.REQUEST_SUBMIT
2832
3375
  ]);
@@ -2876,6 +3419,13 @@ function parseIframeMessage(data) {
2876
3419
  if (typeof record.status !== "string" || !record.context || typeof record.context !== "object")
2877
3420
  return null;
2878
3421
  break;
3422
+ case MESSAGE_TYPES.TERMS_CHANGED:
3423
+ if (typeof record.intent_id !== "string" || !record.replacement || typeof record.replacement !== "object" || !Array.isArray(record.deltas))
3424
+ return null;
3425
+ break;
3426
+ case MESSAGE_TYPES.SELECTION_UNAVAILABLE:
3427
+ if (typeof record.intent_id !== "string" || !Array.isArray(record.lines)) return null;
3428
+ break;
2879
3429
  case MESSAGE_TYPES.READY:
2880
3430
  case MESSAGE_TYPES.HEIGHT_CHANGE:
2881
3431
  if (typeof record.height !== "number") return null;
@@ -2948,7 +3498,10 @@ var CimplifyElements = class {
2948
3498
  async submitCheckout(data) {
2949
3499
  const result = await this.processCheckout({
2950
3500
  cart_id: data.cart_id,
2951
- order_type: data.order_type ?? "delivery",
3501
+ intent_id: data.intent_id,
3502
+ hosted_session_id: data.hosted_session_id,
3503
+ initial_terms: data.initial_terms,
3504
+ order_type: data.order_type ?? chunkEV2EVOYS_js.ORDER_TYPE.DELIVERY,
2952
3505
  location_id: data.location_id,
2953
3506
  notes: data.notes,
2954
3507
  scheduled_time: data.scheduled_time,
@@ -2960,7 +3513,7 @@ var CimplifyElements = class {
2960
3513
  success: true,
2961
3514
  order: {
2962
3515
  id: result.order?.id || "",
2963
- status: result.order?.status || "unknown",
3516
+ status: result.order?.status || chunkEV2EVOYS_js.CHECKOUT_ORDER_RESULT_STATUS.UNKNOWN,
2964
3517
  total: result.order?.total || ""
2965
3518
  }
2966
3519
  };
@@ -2968,7 +3521,7 @@ var CimplifyElements = class {
2968
3521
  return {
2969
3522
  success: false,
2970
3523
  error: {
2971
- code: result.error?.code || "CHECKOUT_FAILED",
3524
+ code: result.error?.code || chunkAVXA4F6G_js.ErrorCode.CHECKOUT_FAILED,
2972
3525
  message: result.error?.message || "Checkout failed"
2973
3526
  }
2974
3527
  };
@@ -2978,12 +3531,18 @@ var CimplifyElements = class {
2978
3531
  const task = (async () => {
2979
3532
  this.debug("[cimplify:checkout] processCheckout called", {
2980
3533
  cart_id: options.cart_id,
3534
+ intent_id: options.intent_id,
3535
+ hosted_session_id: options.hosted_session_id,
2981
3536
  order_type: options.order_type,
2982
3537
  location_id: options.location_id
2983
3538
  });
2984
3539
  if (this.checkoutInProgress) {
2985
3540
  this.debug("[cimplify:checkout] BLOCKED: already processing");
2986
- return toCheckoutError("ALREADY_PROCESSING", "Checkout is already in progress.", false);
3541
+ return toCheckoutError(
3542
+ chunkAVXA4F6G_js.ErrorCode.ALREADY_PROCESSING,
3543
+ "Checkout is already in progress.",
3544
+ false
3545
+ );
2987
3546
  }
2988
3547
  this.checkoutInProgress = true;
2989
3548
  if (this.authEstablishmentInProgress) {
@@ -2991,18 +3550,18 @@ var CimplifyElements = class {
2991
3550
  if (this.authEstablishmentInProgress) {
2992
3551
  this.checkoutInProgress = false;
2993
3552
  return toCheckoutError(
2994
- "AUTH_INCOMPLETE",
3553
+ chunkAVXA4F6G_js.ErrorCode.AUTH_INCOMPLETE,
2995
3554
  "Authentication must finish establishing the checkout session.",
2996
3555
  true
2997
3556
  );
2998
3557
  }
2999
3558
  }
3000
- if (!options.cart_id) {
3001
- this.debug("[cimplify:checkout] BLOCKED: no cart_id");
3559
+ if (!options.cart_id && !options.intent_id) {
3560
+ this.debug("[cimplify:checkout] BLOCKED: no cart_id or intent_id");
3002
3561
  this.checkoutInProgress = false;
3003
3562
  return toCheckoutError(
3004
- "INVALID_CART",
3005
- "A valid cart is required before checkout can start.",
3563
+ chunkAVXA4F6G_js.ErrorCode.CHECKOUT_AUTHORITY_REQUIRED,
3564
+ "A cart or existing purchase intent is required before checkout can start.",
3006
3565
  false
3007
3566
  );
3008
3567
  }
@@ -3010,7 +3569,7 @@ var CimplifyElements = class {
3010
3569
  this.debug("[cimplify:checkout] BLOCKED: no order_type");
3011
3570
  this.checkoutInProgress = false;
3012
3571
  return toCheckoutError(
3013
- "ORDER_TYPE_REQUIRED",
3572
+ chunkAVXA4F6G_js.ErrorCode.ORDER_TYPE_REQUIRED,
3014
3573
  "Order type is required before checkout can start.",
3015
3574
  false
3016
3575
  );
@@ -3020,7 +3579,7 @@ var CimplifyElements = class {
3020
3579
  this.debug("[cimplify:checkout] BLOCKED: no checkout element");
3021
3580
  this.checkoutInProgress = false;
3022
3581
  return toCheckoutError(
3023
- "NO_PAYMENT_ELEMENT",
3582
+ chunkAVXA4F6G_js.ErrorCode.NO_PAYMENT_ELEMENT,
3024
3583
  "Checkout element must be mounted before checkout.",
3025
3584
  false
3026
3585
  );
@@ -3029,7 +3588,7 @@ var CimplifyElements = class {
3029
3588
  this.debug("[cimplify:checkout] BLOCKED: checkout element not mounted");
3030
3589
  this.checkoutInProgress = false;
3031
3590
  return toCheckoutError(
3032
- "PAYMENT_NOT_MOUNTED",
3591
+ chunkAVXA4F6G_js.ErrorCode.PAYMENT_NOT_MOUNTED,
3033
3592
  "Checkout element must be mounted before checkout.",
3034
3593
  false
3035
3594
  );
@@ -3041,7 +3600,7 @@ var CimplifyElements = class {
3041
3600
  this.debug("[cimplify:checkout] BLOCKED: auth incomplete");
3042
3601
  this.checkoutInProgress = false;
3043
3602
  return toCheckoutError(
3044
- "AUTH_INCOMPLETE",
3603
+ chunkAVXA4F6G_js.ErrorCode.AUTH_INCOMPLETE,
3045
3604
  "Authentication must complete before checkout can start.",
3046
3605
  true
3047
3606
  );
@@ -3061,7 +3620,12 @@ var CimplifyElements = class {
3061
3620
  });
3062
3621
  const processMessage = {
3063
3622
  type: MESSAGE_TYPES.PROCESS_CHECKOUT,
3064
- cart_id: options.cart_id,
3623
+ // Existing intent authority wins if a compatibility caller supplied
3624
+ // both values; the iframe must never mint a replacement.
3625
+ cart_id: options.intent_id ? void 0 : options.cart_id,
3626
+ intent_id: options.intent_id,
3627
+ hosted_session_id: options.hosted_session_id,
3628
+ initial_terms: options.intent_id ? options.initial_terms : void 0,
3065
3629
  order_type: options.order_type,
3066
3630
  location_id: options.location_id,
3067
3631
  notes: options.notes,
@@ -3100,7 +3664,7 @@ var CimplifyElements = class {
3100
3664
  const timeout = setTimeout(() => {
3101
3665
  settle(
3102
3666
  toCheckoutError(
3103
- "TIMEOUT",
3667
+ chunkAVXA4F6G_js.ErrorCode.TIMEOUT,
3104
3668
  "Checkout timed out before receiving a terminal response.",
3105
3669
  true
3106
3670
  )
@@ -3121,6 +3685,21 @@ var CimplifyElements = class {
3121
3685
  options.on_status_change?.(message.status, message.context);
3122
3686
  return;
3123
3687
  }
3688
+ if (message.type === MESSAGE_TYPES.TERMS_CHANGED) {
3689
+ options.on_status_change?.(chunkEV2EVOYS_js.CHECKOUT_STATUS.REVIEWING_TERMS, {
3690
+ intent_id: message.intent_id,
3691
+ replacement_terms: message.replacement,
3692
+ terms_deltas: message.deltas
3693
+ });
3694
+ return;
3695
+ }
3696
+ if (message.type === MESSAGE_TYPES.SELECTION_UNAVAILABLE) {
3697
+ options.on_status_change?.(chunkEV2EVOYS_js.CHECKOUT_STATUS.REVIEWING_TERMS, {
3698
+ intent_id: message.intent_id,
3699
+ unavailable_lines: message.lines
3700
+ });
3701
+ return;
3702
+ }
3124
3703
  if (message.type === MESSAGE_TYPES.CHECKOUT_COMPLETE) {
3125
3704
  this.debug("[cimplify:checkout] received checkout_complete", {
3126
3705
  success: message.success,
@@ -3136,7 +3715,11 @@ var CimplifyElements = class {
3136
3715
  if (message.type === MESSAGE_TYPES.LOGOUT_COMPLETE) {
3137
3716
  checkoutElement.sendMessage({ type: MESSAGE_TYPES.ABORT_CHECKOUT });
3138
3717
  settle(
3139
- toCheckoutError("AUTH_LOST", "Authentication was cleared during checkout.", true)
3718
+ toCheckoutError(
3719
+ chunkAVXA4F6G_js.ErrorCode.AUTH_LOST,
3720
+ "Authentication was cleared during checkout.",
3721
+ true
3722
+ )
3140
3723
  );
3141
3724
  }
3142
3725
  };
@@ -3145,11 +3728,13 @@ var CimplifyElements = class {
3145
3728
  }
3146
3729
  abortFn = () => {
3147
3730
  checkoutElement.sendMessage({ type: MESSAGE_TYPES.ABORT_CHECKOUT });
3148
- settle(toCheckoutError("CANCELLED", "Checkout was cancelled.", true));
3731
+ settle(toCheckoutError(chunkAVXA4F6G_js.ErrorCode.CANCELLED, "Checkout was cancelled.", true));
3149
3732
  };
3150
3733
  this.activeCheckoutAbort = abortFn;
3151
3734
  this.debug("[cimplify:checkout] sending process_checkout to checkout iframe", {
3152
3735
  cart_id: processMessage.cart_id,
3736
+ intent_id: processMessage.intent_id,
3737
+ hosted_session_id: processMessage.hosted_session_id,
3153
3738
  order_type: processMessage.order_type,
3154
3739
  hasCustomer: !!processMessage.customer,
3155
3740
  hasAddress: !!processMessage.address,
@@ -3382,7 +3967,7 @@ var CimplifyElements = class {
3382
3967
  const redirectUri = auth.redirectUri ?? readPublicEnv("NEXT_PUBLIC_CIMPLIFY_REDIRECT_URI");
3383
3968
  if (!clientId || !redirectUri) {
3384
3969
  sourceElement._emitError({
3385
- code: "AUTH_CONFIG_REQUIRED",
3970
+ code: chunkAVXA4F6G_js.ErrorCode.AUTH_CONFIG_REQUIRED,
3386
3971
  message: "Cimplify OAuth clientId and redirectUri are required."
3387
3972
  });
3388
3973
  return;
@@ -3406,7 +3991,7 @@ var CimplifyElements = class {
3406
3991
  this.authInProgress = false;
3407
3992
  if (!accessToken) {
3408
3993
  sourceElement._emitError({
3409
- code: "AUTH_CALLBACK_MISSING_TOKEN",
3994
+ code: chunkAVXA4F6G_js.ErrorCode.AUTH_CALLBACK_MISSING_TOKEN,
3410
3995
  message: "Sign-in callback did not return an access token."
3411
3996
  });
3412
3997
  return;
@@ -3433,7 +4018,7 @@ var CimplifyElements = class {
3433
4018
  if (this.authGeneration !== generation) return;
3434
4019
  this.authInProgress = false;
3435
4020
  sourceElement._emitError({
3436
- code: "AUTH_START_FAILED",
4021
+ code: chunkAVXA4F6G_js.ErrorCode.AUTH_START_FAILED,
3437
4022
  message: error instanceof Error ? error.message : "Unable to start sign-in."
3438
4023
  });
3439
4024
  });
@@ -3486,7 +4071,7 @@ var CimplifyElements = class {
3486
4071
  if (!this.customerData) {
3487
4072
  this.customerData = { name: "", email: null, phone: null };
3488
4073
  }
3489
- if (message.contactType === "email") {
4074
+ if (message.contactType === ELEMENTS_AUTH_CONTACT_TYPES.EMAIL) {
3490
4075
  this.customerData.email = message.contact;
3491
4076
  } else {
3492
4077
  this.customerData.phone = message.contact;
@@ -3510,7 +4095,7 @@ var CimplifyElements = class {
3510
4095
  this.client.setAccessToken(null);
3511
4096
  }
3512
4097
  this.broadcastClearedSession();
3513
- if (message.contactType === "email") {
4098
+ if (message.contactType === ELEMENTS_AUTH_CONTACT_TYPES.EMAIL) {
3514
4099
  this.customerData.email = message.contact;
3515
4100
  } else {
3516
4101
  this.customerData.phone = message.contact;
@@ -3546,7 +4131,7 @@ var CimplifyElements = class {
3546
4131
  if (!this.customerData) {
3547
4132
  this.customerData = { name: "", email: null, phone: null };
3548
4133
  }
3549
- if (contactType === "email") {
4134
+ if (contactType === ELEMENTS_AUTH_CONTACT_TYPES.EMAIL) {
3550
4135
  this.customerData.email = contact;
3551
4136
  } else {
3552
4137
  this.customerData.phone = contact;
@@ -3709,7 +4294,7 @@ var CimplifyElement = class {
3709
4294
  if (!resolvedBusinessId || !this.container || !this.mounted) {
3710
4295
  console.error("Unable to mount element without a resolved business ID");
3711
4296
  this.emit(EVENT_TYPES.ERROR, {
3712
- code: "BUSINESS_ID_REQUIRED",
4297
+ code: chunkAVXA4F6G_js.ErrorCode.BUSINESS_ID_REQUIRED,
3713
4298
  message: "Unable to initialize checkout without a business ID."
3714
4299
  });
3715
4300
  return;
@@ -3764,7 +4349,10 @@ var CimplifyElement = class {
3764
4349
  orderTypes: this.options.orderTypes,
3765
4350
  defaultOrderType: this.options.defaultOrderType,
3766
4351
  renderSubmitButton: true,
3767
- submitLabel: this.options.submitLabel
4352
+ submitLabel: this.options.submitLabel,
4353
+ intentId: this.options.intentId,
4354
+ hostedSessionId: this.options.hostedSessionId,
4355
+ initialTerms: this.options.initialTerms
3768
4356
  });
3769
4357
  const token = this.parent.getAccessToken();
3770
4358
  const sessionToken = this.parent.getSessionToken();
@@ -3841,12 +4429,20 @@ exports.LinkService = LinkService;
3841
4429
  exports.LiteService = LiteService;
3842
4430
  exports.MESSAGE_TYPES = MESSAGE_TYPES;
3843
4431
  exports.OrderQueries = OrderQueries;
4432
+ exports.PAYMENT_AUTHORIZATION_OUTCOME_STATUS = PAYMENT_AUTHORIZATION_OUTCOME_STATUS;
4433
+ exports.PAYMENT_AUTHORIZATION_PROVIDER = PAYMENT_AUTHORIZATION_PROVIDER;
3844
4434
  exports.PKCE_COOKIE = PKCE_COOKIE;
3845
4435
  exports.PKCE_COOKIE_PATH = PKCE_COOKIE_PATH;
4436
+ exports.PaymentAuthorizationAdapterRegistry = PaymentAuthorizationAdapterRegistry;
4437
+ exports.PaystackAuthorizationAdapter = PaystackAuthorizationAdapter;
3846
4438
  exports.SchedulingService = SchedulingService;
4439
+ exports.StripeAuthorizationAdapter = StripeAuthorizationAdapter;
4440
+ exports.clearIntentIdempotencyKey = clearIntentIdempotencyKey;
3847
4441
  exports.combine = combine;
3848
4442
  exports.combineObject = combineObject;
4443
+ exports.createDefaultPaymentAuthorizationAdapterRegistry = createDefaultPaymentAuthorizationAdapterRegistry;
3849
4444
  exports.createElements = createElements;
4445
+ exports.createPurchaseIntentConfirmation = createPurchaseIntentConfirmation;
3850
4446
  exports.decodePkceState = decodePkceState;
3851
4447
  exports.err = err;
3852
4448
  exports.flatMap = flatMap;
@@ -3856,12 +4452,15 @@ exports.generatePkce = generatePkce;
3856
4452
  exports.generateState = generateState;
3857
4453
  exports.getAuthorizationEndpoint = getAuthorizationEndpoint;
3858
4454
  exports.getOrElse = getOrElse;
4455
+ exports.intentIdempotencyKey = intentIdempotencyKey;
3859
4456
  exports.isErr = isErr;
3860
4457
  exports.isOk = isOk;
3861
4458
  exports.mapError = mapError;
3862
4459
  exports.mapResult = mapResult;
3863
4460
  exports.ok = ok;
4461
+ exports.purchaseIntentRequiresPaymentOption = purchaseIntentRequiresPaymentOption;
3864
4462
  exports.safe = safe;
4463
+ exports.selectPurchaseIntentPaymentOption = selectPurchaseIntentPaymentOption;
3865
4464
  exports.startSignIn = startSignIn;
3866
4465
  exports.toNullable = toNullable;
3867
4466
  exports.tryCatch = tryCatch;