@cimplify/sdk 0.104.0 → 0.104.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/advanced.d.mts +3 -7
- package/dist/advanced.d.ts +3 -7
- package/dist/advanced.js +23 -23
- package/dist/advanced.mjs +4 -4
- package/dist/{client-BuLcOWLv.d.ts → catalogue-BlQ85Uma.d.mts} +415 -763
- package/dist/{client-D5AoobFc.d.mts → catalogue-C8TqOj9K.d.ts} +415 -763
- package/dist/{payment-g0HFkEDU.d.mts → checkout-BqK9XUz5.d.mts} +3824 -1446
- package/dist/{payment-g0HFkEDU.d.ts → checkout-BqK9XUz5.d.ts} +3824 -1446
- package/dist/{chunk-GOHSXBKW.mjs → chunk-33VCYWVL.mjs} +25 -1
- package/dist/{chunk-2WPVUIHX.mjs → chunk-6G3ANKQA.mjs} +1030 -360
- package/dist/{chunk-E4K2VQDD.js → chunk-BWEIMKLF.js} +541 -16
- package/dist/{chunk-IQFFSKE2.js → chunk-DQEXY542.js} +1345 -746
- package/dist/{chunk-CNN7Z2IP.js → chunk-EV2EVOYS.js} +27 -0
- package/dist/{chunk-YVAEY3VC.js → chunk-HYFA67A7.js} +1034 -364
- package/dist/{chunk-5RT4HYMP.mjs → chunk-L5SNEU2O.mjs} +524 -15
- package/dist/{chunk-4BKOKHE3.js → chunk-RBNBSQI7.mjs} +217 -19
- package/dist/{chunk-H3RATH4B.mjs → chunk-SFUJMS5E.js} +261 -2
- package/dist/{chunk-DYIAX3WI.mjs → chunk-U54CWUUT.mjs} +11 -2
- package/dist/{chunk-OKADBZAI.mjs → chunk-UFOWPN3D.mjs} +808 -574
- package/dist/{chunk-OCCNG6MO.mjs → chunk-V4457OKB.mjs} +1310 -722
- package/dist/{chunk-5BDYDZ4U.js → chunk-WXREIBFW.js} +892 -657
- package/dist/{chunk-7PDEX54K.js → chunk-XAUSDMMZ.js} +13 -3
- package/dist/{client-BVNWjk6W.d.ts → client-DhXeiUrf.d.ts} +2 -2
- package/dist/{client-fM716k7G.d.mts → client-mXiUrV4X.d.mts} +2 -2
- package/dist/{index-BtcoqrY1.d.ts → index-B0AdZvrM.d.mts} +9 -4
- package/dist/{index-D7Tf3v7c.d.mts → index-CK8Nk5uQ.d.ts} +9 -4
- package/dist/index-DPWI5XcU.d.ts +8 -0
- package/dist/index-DVfUh-ci.d.mts +8 -0
- package/dist/index.d.mts +31 -14
- package/dist/index.d.ts +31 -14
- package/dist/index.js +305 -133
- package/dist/index.mjs +6 -6
- package/dist/mock/cli.mjs +1442 -386
- package/dist/mock/library.js +1168 -352
- package/dist/mock/library.mjs +1168 -352
- package/dist/mock/msw.js +1168 -352
- package/dist/mock/msw.mjs +1168 -352
- package/dist/{price-BLIeAb8K.d.ts → price-6hQIIac9.d.ts} +1 -1
- package/dist/{price-Czq_cTC_.d.mts → price-BUDv1rI7.d.mts} +1 -1
- package/dist/react.d.mts +10 -5
- package/dist/react.d.ts +10 -5
- package/dist/react.js +227 -197
- package/dist/react.mjs +90 -60
- package/dist/{server-DKK_D-PP.d.ts → server-DJ0mSs9i.d.mts} +31 -57
- package/dist/{server-BkVhOIwn.d.mts → server-DSTX76Ki.d.ts} +31 -57
- package/dist/server.d.mts +3 -4
- package/dist/server.d.ts +3 -4
- package/dist/server.js +11 -11
- package/dist/server.mjs +5 -5
- package/dist/styles.css +2 -2
- package/dist/testing/msw.d.mts +2 -2
- package/dist/testing/msw.d.ts +2 -2
- package/dist/testing/msw.js +4 -4
- package/dist/testing/msw.mjs +3 -3
- package/dist/testing/suite.d.mts +5 -6
- package/dist/testing/suite.d.ts +5 -6
- package/dist/testing/suite.js +29 -28
- package/dist/testing/suite.mjs +10 -9
- package/dist/testing.d.mts +2177 -14
- package/dist/testing.d.ts +2177 -14
- package/dist/testing.js +167 -89
- package/dist/testing.mjs +24 -10
- package/dist/utils.d.mts +3 -4
- package/dist/utils.d.ts +3 -4
- package/dist/utils.js +35 -31
- package/dist/utils.mjs +2 -2
- package/package.json +9 -9
- package/registry/order-history.json +1 -1
- package/registry/order-summary.json +1 -1
- package/dist/link-D9iSVxt5.d.mts +0 -308
- package/dist/link-D9iSVxt5.d.ts +0 -308
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
3
|
+
var chunkEV2EVOYS_js = require('./chunk-EV2EVOYS.js');
|
|
4
|
+
var chunkXAUSDMMZ_js = require('./chunk-XAUSDMMZ.js');
|
|
5
|
+
var chunkSFUJMS5E_js = require('./chunk-SFUJMS5E.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
|
|
120
|
+
if (error instanceof chunkSFUJMS5E_js.CimplifyError) return chunkSFUJMS5E_js.enrichError(error);
|
|
121
121
|
if (error instanceof Error) {
|
|
122
|
-
return
|
|
122
|
+
return chunkSFUJMS5E_js.enrichError(new chunkSFUJMS5E_js.CimplifyError(chunkSFUJMS5E_js.ErrorCode.UNKNOWN_ERROR, error.message, false));
|
|
123
123
|
}
|
|
124
|
-
return
|
|
124
|
+
return chunkSFUJMS5E_js.enrichError(new chunkSFUJMS5E_js.CimplifyError(chunkSFUJMS5E_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
|
|
699
|
+
error: new chunkSFUJMS5E_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/
|
|
791
|
-
var
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
var
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
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: chunkSFUJMS5E_js.ErrorCode.PROVIDER_UNAVAILABLE,
|
|
804
|
+
SUBMISSION_UNKNOWN: "SUBMISSION_UNKNOWN",
|
|
805
|
+
CANCELLED: "CANCELLED",
|
|
806
|
+
PAYMENT_CANCELLED: chunkSFUJMS5E_js.ErrorCode.PAYMENT_CANCELLED,
|
|
807
|
+
PAYMENT_FAILED: chunkSFUJMS5E_js.ErrorCode.PAYMENT_FAILED,
|
|
808
|
+
POPUP_BLOCKED: chunkSFUJMS5E_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
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
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
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
const
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
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
|
-
|
|
867
|
-
|
|
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
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
}
|
|
875
|
-
|
|
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
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
false
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
|
|
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
|
-
|
|
933
|
-
|
|
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
|
-
|
|
936
|
-
|
|
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 (
|
|
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
|
-
|
|
944
|
-
|
|
913
|
+
status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
|
|
914
|
+
code: chunkSFUJMS5E_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 (
|
|
919
|
+
if (result.error === PAYSTACK_POPUP_ERROR.PROVIDER_UNAVAILABLE) {
|
|
948
920
|
return {
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
921
|
+
status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
|
|
922
|
+
code: chunkSFUJMS5E_js.ErrorCode.PROVIDER_UNAVAILABLE,
|
|
923
|
+
message: "Paystack is unavailable in this environment.",
|
|
924
|
+
recoverable: false
|
|
952
925
|
};
|
|
953
926
|
}
|
|
954
|
-
return {
|
|
927
|
+
return {
|
|
928
|
+
status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
|
|
929
|
+
code: chunkSFUJMS5E_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: chunkSFUJMS5E_js.ErrorCode.AUTHORIZATION_FAILED,
|
|
1028
|
+
message,
|
|
1029
|
+
recoverable: true
|
|
1030
|
+
};
|
|
955
1031
|
}
|
|
956
|
-
|
|
957
|
-
|
|
1032
|
+
return {
|
|
1033
|
+
status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
|
|
1034
|
+
code: chunkSFUJMS5E_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: chunkSFUJMS5E_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
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
false
|
|
964
|
-
)
|
|
1061
|
+
status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
|
|
1062
|
+
code: chunkSFUJMS5E_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
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
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
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
false
|
|
980
|
-
)
|
|
1072
|
+
status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
|
|
1073
|
+
code: chunkSFUJMS5E_js.ErrorCode.PROVIDER_UNAVAILABLE,
|
|
1074
|
+
message: "Stripe.js could not be loaded.",
|
|
1075
|
+
recoverable: false
|
|
981
1076
|
};
|
|
982
1077
|
}
|
|
983
|
-
const
|
|
984
|
-
if (!
|
|
1078
|
+
const modal = createStripeModal();
|
|
1079
|
+
if (!modal) {
|
|
985
1080
|
return {
|
|
986
|
-
|
|
987
|
-
|
|
1081
|
+
status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
|
|
1082
|
+
code: chunkSFUJMS5E_js.ErrorCode.PROVIDER_UNAVAILABLE,
|
|
1083
|
+
message: "Stripe Payment Element could not be mounted.",
|
|
1084
|
+
recoverable: false
|
|
988
1085
|
};
|
|
989
1086
|
}
|
|
990
|
-
let
|
|
1087
|
+
let paymentElement;
|
|
1088
|
+
let elements;
|
|
991
1089
|
try {
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
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
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
true
|
|
1013
|
-
)
|
|
1097
|
+
status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
|
|
1098
|
+
code: chunkSFUJMS5E_js.ErrorCode.PROVIDER_UNAVAILABLE,
|
|
1099
|
+
message: "Stripe Payment Element could not be initialized.",
|
|
1100
|
+
recoverable: false
|
|
1014
1101
|
};
|
|
1015
1102
|
}
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
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
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
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
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
return
|
|
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 (
|
|
1096
|
-
|
|
1158
|
+
if (settled || context.signal?.aborted) {
|
|
1159
|
+
settle({ status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.CANCELLED });
|
|
1160
|
+
return;
|
|
1097
1161
|
}
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
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
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
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
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
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
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
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: chunkSFUJMS5E_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
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
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
|
-
|
|
1142
|
-
const
|
|
1143
|
-
|
|
1144
|
-
|
|
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
|
-
|
|
1215
|
-
|
|
1216
|
-
"Payment confirmation timed out. Please retry checkout.",
|
|
1217
|
-
true
|
|
1218
|
-
);
|
|
1226
|
+
this.adapters.set(provider, adapter);
|
|
1227
|
+
return this;
|
|
1219
1228
|
}
|
|
1220
|
-
|
|
1221
|
-
|
|
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
|
-
|
|
1316
|
-
|
|
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
|
-
|
|
1342
|
-
|
|
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
|
-
|
|
1369
|
-
|
|
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
|
-
|
|
1388
|
-
|
|
1241
|
+
async authorize(action, options) {
|
|
1242
|
+
const provider = normalizeProvider(action.provider);
|
|
1243
|
+
if (!provider) {
|
|
1389
1244
|
return {
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1245
|
+
status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
|
|
1246
|
+
code: chunkSFUJMS5E_js.ErrorCode.PROVIDER_UNAVAILABLE,
|
|
1247
|
+
message: "Card authorization response did not identify a payment provider.",
|
|
1248
|
+
recoverable: false
|
|
1393
1249
|
};
|
|
1394
1250
|
}
|
|
1395
|
-
|
|
1251
|
+
const adapter = this.adapters.get(provider);
|
|
1252
|
+
if (!adapter) {
|
|
1396
1253
|
return {
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1254
|
+
status: PAYMENT_AUTHORIZATION_OUTCOME_STATUS.FAILED,
|
|
1255
|
+
code: chunkSFUJMS5E_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
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
return
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
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: chunkSFUJMS5E_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
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
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 === chunkSFUJMS5E_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 === chunkSFUJMS5E_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
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
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 === chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_METHOD.MOBILE_MONEY) {
|
|
1326
|
+
if (form.link_payment_method_id) {
|
|
1327
|
+
return {
|
|
1328
|
+
method_kind: chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_METHOD.MOBILE_MONEY,
|
|
1329
|
+
authority: {
|
|
1330
|
+
authority_kind: chunkSFUJMS5E_js.MOBILE_MONEY_TENDER_AUTHORITY_KIND.SAVED_REFERENCE,
|
|
1331
|
+
stored_instrument_id: form.link_payment_method_id
|
|
1332
|
+
}
|
|
1333
|
+
};
|
|
1428
1334
|
}
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1335
|
+
const details = form.mobile_money_details;
|
|
1336
|
+
if (!details?.phone_number || !details.provider) {
|
|
1337
|
+
throw new chunkSFUJMS5E_js.CimplifyError(
|
|
1338
|
+
chunkSFUJMS5E_js.ErrorCode.INVALID_PAYMENT_METHOD,
|
|
1339
|
+
"Mobile money requires a phone number and network.",
|
|
1340
|
+
false
|
|
1341
|
+
);
|
|
1432
1342
|
}
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1343
|
+
const network = chunkXAUSDMMZ_js.purchaseIntentMobileMoneyNetwork(details.provider);
|
|
1344
|
+
if (!network) {
|
|
1345
|
+
throw new chunkSFUJMS5E_js.CimplifyError(
|
|
1346
|
+
chunkSFUJMS5E_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
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1352
|
+
method_kind: chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_METHOD.MOBILE_MONEY,
|
|
1353
|
+
authority: {
|
|
1354
|
+
authority_kind: chunkSFUJMS5E_js.MOBILE_MONEY_TENDER_AUTHORITY_KIND.TRANSIENT,
|
|
1355
|
+
phone_number: details.phone_number,
|
|
1356
|
+
network
|
|
1450
1357
|
}
|
|
1451
1358
|
};
|
|
1452
1359
|
}
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1360
|
+
if (form.payment_method === chunkSFUJMS5E_js.LEGACY_CHECKOUT_PAYMENT_METHOD_ALIAS.CASH || form.payment_method === chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_METHOD.OFFLINE) {
|
|
1361
|
+
throw new chunkSFUJMS5E_js.CimplifyError(
|
|
1362
|
+
chunkSFUJMS5E_js.ErrorCode.INVALID_PAYMENT_METHOD,
|
|
1363
|
+
"Offline tender requires an authenticated staff checkout.",
|
|
1364
|
+
false
|
|
1365
|
+
);
|
|
1456
1366
|
}
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1367
|
+
if (form.payment_method === chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_METHOD.CARD) {
|
|
1368
|
+
return {
|
|
1369
|
+
method_kind: chunkSFUJMS5E_js.PURCHASE_INTENT_PAYMENT_METHOD.CARD,
|
|
1370
|
+
stored_instrument_id: form.link_payment_method_id
|
|
1371
|
+
};
|
|
1460
1372
|
}
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
throw createAbortError();
|
|
1464
|
-
}
|
|
1373
|
+
if (form.payment_method === chunkSFUJMS5E_js.LEGACY_CHECKOUT_PAYMENT_METHOD_ALIAS.STORE_CREDIT) {
|
|
1374
|
+
return void 0;
|
|
1465
1375
|
}
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1376
|
+
throw new chunkSFUJMS5E_js.CimplifyError(
|
|
1377
|
+
chunkSFUJMS5E_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: chunkSFUJMS5E_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 === chunkSFUJMS5E_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 === chunkSFUJMS5E_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 chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.ORDER_CREATED:
|
|
1424
|
+
return ok({
|
|
1425
|
+
...committedBase(response),
|
|
1426
|
+
payment_status: chunkSFUJMS5E_js.LEGACY_CHECKOUT_PAYMENT_STATUS.SUCCEEDED,
|
|
1427
|
+
requires_authorization: false,
|
|
1428
|
+
next_action: { type: chunkEV2EVOYS_js.CHECKOUT_NEXT_ACTION.NONE }
|
|
1429
|
+
});
|
|
1430
|
+
case chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.COLLECTION_PROCESSING:
|
|
1431
|
+
return ok({
|
|
1432
|
+
...committedBase(response),
|
|
1433
|
+
payment_status: chunkSFUJMS5E_js.LEGACY_CHECKOUT_PAYMENT_STATUS.PROCESSING,
|
|
1434
|
+
requires_authorization: false,
|
|
1435
|
+
next_action: { type: chunkEV2EVOYS_js.CHECKOUT_NEXT_ACTION.POLL }
|
|
1436
|
+
});
|
|
1437
|
+
case chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.PAYMENT_OUTCOME_UNKNOWN:
|
|
1438
|
+
return ok({
|
|
1439
|
+
...committedBase(response),
|
|
1440
|
+
payment_status: chunkSFUJMS5E_js.LEGACY_CHECKOUT_PAYMENT_STATUS.UNKNOWN,
|
|
1441
|
+
requires_authorization: false,
|
|
1442
|
+
next_action: { type: chunkEV2EVOYS_js.CHECKOUT_NEXT_ACTION.POLL }
|
|
1443
|
+
});
|
|
1444
|
+
case chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.PAYMENT_FAILED:
|
|
1445
|
+
return err(
|
|
1446
|
+
new chunkSFUJMS5E_js.CimplifyError(
|
|
1447
|
+
chunkSFUJMS5E_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 chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.REDIRECT_REQUIRED:
|
|
1453
|
+
return ok({
|
|
1454
|
+
...committedBase(response),
|
|
1455
|
+
payment_status: chunkSFUJMS5E_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
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1462
|
+
});
|
|
1463
|
+
case chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.CARD_POPUP_REQUIRED:
|
|
1464
|
+
return ok({
|
|
1465
|
+
...committedBase(response),
|
|
1466
|
+
payment_status: chunkSFUJMS5E_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 chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.AUTHORIZATION_REQUIRED:
|
|
1480
|
+
return ok({
|
|
1481
|
+
...committedBase(response),
|
|
1482
|
+
payment_status: chunkSFUJMS5E_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 chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.TERMS_CHANGED:
|
|
1493
|
+
return err(
|
|
1494
|
+
new chunkSFUJMS5E_js.CimplifyError(
|
|
1495
|
+
chunkSFUJMS5E_js.PURCHASE_INTENT_ERROR_CODE.TERMS_CHANGED,
|
|
1496
|
+
"Checkout terms changed. Review the replacement terms before confirming again.",
|
|
1497
|
+
true
|
|
1498
|
+
)
|
|
1499
|
+
);
|
|
1500
|
+
case chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.SELECTION_UNAVAILABLE:
|
|
1501
|
+
return err(
|
|
1502
|
+
new chunkSFUJMS5E_js.CimplifyError(
|
|
1503
|
+
chunkSFUJMS5E_js.PURCHASE_INTENT_ERROR_CODE.SELECTION_UNAVAILABLE,
|
|
1504
|
+
"One or more checkout selections are no longer available.",
|
|
1505
|
+
true
|
|
1506
|
+
)
|
|
1507
|
+
);
|
|
1508
|
+
case chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.OFFER_ENDED:
|
|
1509
|
+
return err(
|
|
1510
|
+
new chunkSFUJMS5E_js.CimplifyError(
|
|
1511
|
+
chunkSFUJMS5E_js.PURCHASE_INTENT_ERROR_CODE.OFFER_ENDED,
|
|
1512
|
+
"This offer has ended.",
|
|
1513
|
+
false
|
|
1514
|
+
)
|
|
1515
|
+
);
|
|
1516
|
+
case chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.SOURCE_UNAVAILABLE:
|
|
1517
|
+
return err(
|
|
1518
|
+
new chunkSFUJMS5E_js.CimplifyError(
|
|
1519
|
+
chunkSFUJMS5E_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 !== chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.CARD_POPUP_REQUIRED && response.status !== chunkSFUJMS5E_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 === chunkSFUJMS5E_js.ErrorCode.NETWORK_ERROR || error.code === chunkSFUJMS5E_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 ===
|
|
1595
|
+
return method === chunkSFUJMS5E_js.LEGACY_CHECKOUT_PAYMENT_METHOD_ALIAS.CASH || method === chunkSFUJMS5E_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
|
+
[chunkSFUJMS5E_js.PURCHASE_INTENT_RESOLVE_STATUS.CONFIRMING]: chunkEV2EVOYS_js.CHECKOUT_STATUS.PROCESSING,
|
|
1625
|
+
[chunkSFUJMS5E_js.PURCHASE_INTENT_RESOLVE_STATUS.POLLING]: chunkEV2EVOYS_js.CHECKOUT_STATUS.POLLING,
|
|
1626
|
+
[chunkSFUJMS5E_js.PURCHASE_INTENT_RESOLVE_STATUS.AWAITING_ACTION]: chunkEV2EVOYS_js.CHECKOUT_STATUS.AWAITING_AUTHORIZATION,
|
|
1627
|
+
[chunkSFUJMS5E_js.PURCHASE_INTENT_RESOLVE_STATUS.REVIEWING_TERMS]: chunkEV2EVOYS_js.CHECKOUT_STATUS.REVIEWING_TERMS,
|
|
1628
|
+
[chunkSFUJMS5E_js.PURCHASE_INTENT_RESOLVE_STATUS.COMPLETED]: chunkEV2EVOYS_js.CHECKOUT_STATUS.FINALIZING,
|
|
1629
|
+
[chunkSFUJMS5E_js.PURCHASE_INTENT_RESOLVE_STATUS.FAILED]: chunkEV2EVOYS_js.CHECKOUT_STATUS.FAILED,
|
|
1630
|
+
[chunkSFUJMS5E_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 ===
|
|
1524
|
-
if (!seen.has(
|
|
1525
|
-
seen.add(
|
|
1526
|
-
options.push({ method:
|
|
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 !==
|
|
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
|
|
1534
|
-
|
|
1654
|
+
const network = chunkXAUSDMMZ_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:
|
|
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
|
|
1548
|
-
|
|
1673
|
+
return new chunkSFUJMS5E_js.CimplifyError(
|
|
1674
|
+
chunkSFUJMS5E_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
|
|
1555
|
-
|
|
1680
|
+
return new chunkSFUJMS5E_js.CimplifyError(
|
|
1681
|
+
chunkSFUJMS5E_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 ?
|
|
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 (!
|
|
1695
|
+
if (!chunkSFUJMS5E_js.isSupportedCurrency(normalized)) {
|
|
1570
1696
|
return err(
|
|
1571
|
-
new
|
|
1572
|
-
|
|
1697
|
+
new chunkSFUJMS5E_js.CimplifyError(
|
|
1698
|
+
chunkSFUJMS5E_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
|
-
|
|
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
|
|
1587
|
-
|
|
1712
|
+
new chunkSFUJMS5E_js.CimplifyError(
|
|
1713
|
+
chunkSFUJMS5E_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
|
|
1726
|
+
async startIntentCheckout(data, options) {
|
|
1601
1727
|
const invalid = this.validateCheckoutData(data);
|
|
1602
|
-
if (invalid)
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
const
|
|
1606
|
-
|
|
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
|
-
|
|
1621
|
-
|
|
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 chunkSFUJMS5E_js.CimplifyError ? error : new chunkSFUJMS5E_js.CimplifyError(
|
|
1746
|
+
chunkSFUJMS5E_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
|
-
|
|
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 chunkSFUJMS5E_js.CimplifyError(
|
|
1766
|
+
chunkSFUJMS5E_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 chunkSFUJMS5E_js.CimplifyError ? error : new chunkSFUJMS5E_js.CimplifyError(
|
|
1778
|
+
chunkSFUJMS5E_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 chunkSFUJMS5E_js.CimplifyError(
|
|
1787
|
+
chunkSFUJMS5E_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 === chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.ORDER_CREATED || started.value.initialResponse.status === chunkSFUJMS5E_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
|
|
1631
|
-
|
|
1848
|
+
new chunkSFUJMS5E_js.CimplifyError(
|
|
1849
|
+
chunkSFUJMS5E_js.ErrorCode.NOT_IMPLEMENTED,
|
|
1632
1850
|
"initializePayment is not available in REST mode.",
|
|
1633
1851
|
false
|
|
1634
1852
|
)
|
|
1635
1853
|
);
|
|
1636
1854
|
}
|
|
1637
|
-
|
|
1638
|
-
|
|
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 chunkSFUJMS5E_js.CimplifyError(
|
|
1867
|
+
chunkSFUJMS5E_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
|
-
|
|
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(
|
|
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(
|
|
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,
|
|
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
|
-
|
|
1959
|
+
chunkSFUJMS5E_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(
|
|
1967
|
+
return ok(
|
|
1968
|
+
toTerminalFailure(
|
|
1969
|
+
chunkSFUJMS5E_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
|
-
|
|
1979
|
+
chunkSFUJMS5E_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 (!
|
|
2006
|
+
if (!chunkSFUJMS5E_js.isSupportedCurrency(rawBaseCurrency)) {
|
|
1708
2007
|
return ok(
|
|
1709
2008
|
toTerminalFailure(
|
|
1710
|
-
|
|
2009
|
+
chunkSFUJMS5E_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 && !
|
|
2017
|
+
if (payCurrency && !chunkSFUJMS5E_js.isSupportedCurrency(payCurrency)) {
|
|
1719
2018
|
return ok(
|
|
1720
2019
|
toTerminalFailure(
|
|
1721
|
-
|
|
2020
|
+
chunkSFUJMS5E_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 &&
|
|
1728
|
-
const
|
|
1729
|
-
if (
|
|
2026
|
+
const payCurrencyCode = payCurrency && chunkSFUJMS5E_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
|
+
chunkSFUJMS5E_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
|
-
|
|
2046
|
+
chunkSFUJMS5E_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,
|
|
1748
|
-
const
|
|
1749
|
-
if (!
|
|
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
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
2060
|
+
started.error.code || chunkSFUJMS5E_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 === chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.TERMS_CHANGED) {
|
|
2078
|
+
context.replacement_terms = response.replacement;
|
|
2079
|
+
context.terms_deltas = response.deltas;
|
|
2080
|
+
}
|
|
2081
|
+
if (response?.status === chunkSFUJMS5E_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 chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.CARD_POPUP_REQUIRED: {
|
|
2090
|
+
const allowPopups = data.allow_popups ?? typeof window !== "undefined";
|
|
2091
|
+
if (!allowPopups) {
|
|
2092
|
+
actionFailure = {
|
|
2093
|
+
code: chunkSFUJMS5E_js.ErrorCode.PROVIDER_UNAVAILABLE,
|
|
2094
|
+
message: "Card authorization UI is unavailable in this environment.",
|
|
2095
|
+
recoverable: false
|
|
2096
|
+
};
|
|
2097
|
+
return chunkSFUJMS5E_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 chunkSFUJMS5E_js.PURCHASE_INTENT_ACTION_DECISION.CONTINUE;
|
|
2122
|
+
}
|
|
2123
|
+
actionFailure = outcome.status === PAYMENT_AUTHORIZATION_OUTCOME_STATUS.CANCELLED ? {
|
|
2124
|
+
code: chunkSFUJMS5E_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 chunkSFUJMS5E_js.PURCHASE_INTENT_ACTION_DECISION.STOP;
|
|
2133
|
+
}
|
|
2134
|
+
case chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.REDIRECT_REQUIRED: {
|
|
2135
|
+
const authorizationUrl = chunkXAUSDMMZ_js.paymentAuthorizationUrl(action.authorization_url);
|
|
2136
|
+
if (!authorizationUrl) {
|
|
2137
|
+
actionFailure = {
|
|
2138
|
+
code: chunkSFUJMS5E_js.ErrorCode.AUTHORIZATION_FAILED,
|
|
2139
|
+
message: "The provider returned an invalid authorization URL.",
|
|
2140
|
+
recoverable: false
|
|
2141
|
+
};
|
|
2142
|
+
return chunkSFUJMS5E_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: chunkSFUJMS5E_js.ErrorCode.POPUP_BLOCKED,
|
|
2156
|
+
message: "Authorization popup was blocked.",
|
|
2157
|
+
recoverable: true
|
|
2158
|
+
};
|
|
2159
|
+
return chunkSFUJMS5E_js.PURCHASE_INTENT_ACTION_DECISION.STOP;
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
actionFailure = {
|
|
2164
|
+
code: chunkSFUJMS5E_js.ErrorCode.REDIRECT_REQUIRED,
|
|
2165
|
+
message: "Complete authorization at the payment provider, then resume checkout.",
|
|
2166
|
+
recoverable: true
|
|
2167
|
+
};
|
|
2168
|
+
return chunkSFUJMS5E_js.PURCHASE_INTENT_ACTION_DECISION.STOP;
|
|
2169
|
+
}
|
|
2170
|
+
case chunkSFUJMS5E_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: chunkSFUJMS5E_js.ErrorCode.AUTHORIZATION_REQUIRED,
|
|
2175
|
+
message: "Additional payment authorization is required.",
|
|
2176
|
+
recoverable: true
|
|
2177
|
+
};
|
|
2178
|
+
return chunkSFUJMS5E_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: chunkSFUJMS5E_js.ErrorCode.AUTHORIZATION_REQUIRED,
|
|
2188
|
+
message: "Payment authorization was not submitted.",
|
|
2189
|
+
recoverable: true
|
|
2190
|
+
};
|
|
2191
|
+
return chunkSFUJMS5E_js.PURCHASE_INTENT_ACTION_DECISION.STOP;
|
|
2192
|
+
}
|
|
2193
|
+
return {
|
|
2194
|
+
kind: chunkSFUJMS5E_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 || chunkSFUJMS5E_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 chunkSFUJMS5E_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 chunkSFUJMS5E_js.PURCHASE_INTENT_RESOLUTION_KIND.FAILED:
|
|
2235
|
+
clearIntentIdempotencyKey(started.value.confirmationScope);
|
|
2236
|
+
return ok(
|
|
2237
|
+
toTerminalFailure(
|
|
2238
|
+
chunkSFUJMS5E_js.PURCHASE_INTENT_ERROR_CODE.PAYMENT_FAILED,
|
|
2239
|
+
"Payment failed. Choose another method or retry collection.",
|
|
2240
|
+
true
|
|
2241
|
+
)
|
|
2242
|
+
);
|
|
2243
|
+
case chunkSFUJMS5E_js.PURCHASE_INTENT_RESOLUTION_KIND.OUTCOME_UNKNOWN:
|
|
2244
|
+
return ok(
|
|
2245
|
+
toTerminalFailure(
|
|
2246
|
+
chunkSFUJMS5E_js.ErrorCode.PAYMENT_OUTCOME_UNKNOWN,
|
|
2247
|
+
"Payment outcome is still unknown. Resume this intent before retrying.",
|
|
2248
|
+
true
|
|
2249
|
+
)
|
|
2250
|
+
);
|
|
2251
|
+
case chunkSFUJMS5E_js.PURCHASE_INTENT_RESOLUTION_KIND.TIMED_OUT:
|
|
2252
|
+
return ok(
|
|
2253
|
+
toTerminalFailure(
|
|
2254
|
+
chunkSFUJMS5E_js.ErrorCode.TIMEOUT,
|
|
2255
|
+
"Payment is still processing. Resume this intent to continue polling.",
|
|
2256
|
+
true
|
|
2257
|
+
)
|
|
2258
|
+
);
|
|
2259
|
+
case chunkSFUJMS5E_js.PURCHASE_INTENT_RESOLUTION_KIND.ACTION_REQUIRED:
|
|
2260
|
+
return ok(
|
|
2261
|
+
toTerminalFailure(
|
|
2262
|
+
actionFailure?.code ?? chunkSFUJMS5E_js.ErrorCode.AUTHORIZATION_REQUIRED,
|
|
2263
|
+
actionFailure?.message ?? "Checkout requires additional authorization.",
|
|
2264
|
+
actionFailure?.recoverable ?? true
|
|
2265
|
+
)
|
|
2266
|
+
);
|
|
2267
|
+
case chunkSFUJMS5E_js.PURCHASE_INTENT_RESOLUTION_KIND.REVIEW_REQUIRED: {
|
|
2268
|
+
const response = resolved.value.response;
|
|
2269
|
+
switch (response.status) {
|
|
2270
|
+
case chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.TERMS_CHANGED:
|
|
2271
|
+
return ok(
|
|
2272
|
+
toTerminalFailure(
|
|
2273
|
+
chunkSFUJMS5E_js.PURCHASE_INTENT_ERROR_CODE.TERMS_CHANGED,
|
|
2274
|
+
"Checkout terms changed and require explicit review.",
|
|
2275
|
+
true
|
|
2276
|
+
)
|
|
2277
|
+
);
|
|
2278
|
+
case chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.SELECTION_UNAVAILABLE:
|
|
2279
|
+
return ok(
|
|
2280
|
+
toTerminalFailure(
|
|
2281
|
+
chunkSFUJMS5E_js.PURCHASE_INTENT_ERROR_CODE.SELECTION_UNAVAILABLE,
|
|
2282
|
+
"One or more checkout selections are unavailable.",
|
|
2283
|
+
true
|
|
2284
|
+
)
|
|
2285
|
+
);
|
|
2286
|
+
case chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.OFFER_ENDED:
|
|
2287
|
+
return ok(
|
|
2288
|
+
toTerminalFailure(
|
|
2289
|
+
chunkSFUJMS5E_js.PURCHASE_INTENT_ERROR_CODE.OFFER_ENDED,
|
|
2290
|
+
"This offer has ended.",
|
|
2291
|
+
false
|
|
2292
|
+
)
|
|
2293
|
+
);
|
|
2294
|
+
case chunkSFUJMS5E_js.PURCHASE_INTENT_CONFIRM_STATUS.SOURCE_UNAVAILABLE:
|
|
2295
|
+
return ok(
|
|
2296
|
+
toTerminalFailure(
|
|
2297
|
+
chunkSFUJMS5E_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 ? chunkSFUJMS5E_js.ErrorCode.CANCELLED : chunkSFUJMS5E_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
|
|
2392
|
+
error: new chunkSFUJMS5E_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
|
|
2673
|
+
return err(new chunkSFUJMS5E_js.CimplifyError(chunkSFUJMS5E_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 =
|
|
3298
|
+
const hint = chunkSFUJMS5E_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
|
-
|
|
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 ||
|
|
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 ||
|
|
3524
|
+
code: result.error?.code || chunkSFUJMS5E_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(
|
|
3541
|
+
return toCheckoutError(
|
|
3542
|
+
chunkSFUJMS5E_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
|
-
|
|
3553
|
+
chunkSFUJMS5E_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
|
-
|
|
3005
|
-
"A
|
|
3563
|
+
chunkSFUJMS5E_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
|
-
|
|
3572
|
+
chunkSFUJMS5E_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
|
-
|
|
3582
|
+
chunkSFUJMS5E_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
|
-
|
|
3591
|
+
chunkSFUJMS5E_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
|
-
|
|
3603
|
+
chunkSFUJMS5E_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
|
-
|
|
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
|
-
|
|
3667
|
+
chunkSFUJMS5E_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(
|
|
3718
|
+
toCheckoutError(
|
|
3719
|
+
chunkSFUJMS5E_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(
|
|
3731
|
+
settle(toCheckoutError(chunkSFUJMS5E_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:
|
|
3970
|
+
code: chunkSFUJMS5E_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:
|
|
3994
|
+
code: chunkSFUJMS5E_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:
|
|
4021
|
+
code: chunkSFUJMS5E_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 ===
|
|
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 ===
|
|
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 ===
|
|
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:
|
|
4297
|
+
code: chunkSFUJMS5E_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;
|