@asteby/storefront-react 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -0
- package/dist/account.cjs +114 -0
- package/dist/account.cjs.map +1 -1
- package/dist/account.d.cts +60 -4
- package/dist/account.d.ts +60 -4
- package/dist/account.js +113 -1
- package/dist/account.js.map +1 -1
- package/dist/checkout.cjs +65 -14
- package/dist/checkout.cjs.map +1 -1
- package/dist/checkout.d.cts +7 -0
- package/dist/checkout.d.ts +7 -0
- package/dist/checkout.js +65 -14
- package/dist/checkout.js.map +1 -1
- package/dist/payments.cjs +86 -15
- package/dist/payments.cjs.map +1 -1
- package/dist/payments.css +65 -0
- package/dist/payments.d.cts +24 -3
- package/dist/payments.d.ts +24 -3
- package/dist/payments.js +86 -15
- package/dist/payments.js.map +1 -1
- package/package.json +2 -2
package/dist/payments.cjs
CHANGED
|
@@ -146,6 +146,7 @@ function sanitizeMercadoPagoFormData(data) {
|
|
|
146
146
|
function mercadoPagoBricksAdapter(options = {}) {
|
|
147
147
|
const allowed = options.allowedSdkOrigins ?? ["https://sdk.mercadopago.com"];
|
|
148
148
|
const getSdk = options.getSdk ?? (() => typeof window !== "undefined" ? window.MercadoPago : void 0);
|
|
149
|
+
const retryDelay = options.collectRetryDelayMs ?? 400;
|
|
149
150
|
const getDevice = options.getDeviceSessionId ?? (() => typeof window !== "undefined" ? window.MP_DEVICE_SESSION_ID : void 0);
|
|
150
151
|
return {
|
|
151
152
|
kind: MERCADOPAGO_BRICKS_KIND,
|
|
@@ -187,9 +188,21 @@ function mercadoPagoBricksAdapter(options = {}) {
|
|
|
187
188
|
return {
|
|
188
189
|
async collect() {
|
|
189
190
|
if (gone) throw new Error("payment form is unmounted");
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
191
|
+
const read = async () => {
|
|
192
|
+
const raw = await controller.getFormData();
|
|
193
|
+
const data = sanitizeMercadoPagoFormData(raw);
|
|
194
|
+
if (!data.token) throw new Error("payment form incomplete");
|
|
195
|
+
return data;
|
|
196
|
+
};
|
|
197
|
+
let provider_data;
|
|
198
|
+
try {
|
|
199
|
+
provider_data = await read();
|
|
200
|
+
} catch (first) {
|
|
201
|
+
if (gone) throw first;
|
|
202
|
+
await new Promise((r) => setTimeout(r, retryDelay));
|
|
203
|
+
if (gone) throw first;
|
|
204
|
+
provider_data = await read();
|
|
205
|
+
}
|
|
193
206
|
const device = getDevice();
|
|
194
207
|
return { provider_data, ...typeof device === "string" && device ? { device_session_id: device } : {} };
|
|
195
208
|
},
|
|
@@ -621,7 +634,7 @@ function useEmbeddedPayment(options) {
|
|
|
621
634
|
autoRetries = 2,
|
|
622
635
|
retryDelayMs = 600,
|
|
623
636
|
pollIntervalMs = 2e3,
|
|
624
|
-
pollTimeoutMs =
|
|
637
|
+
pollTimeoutMs = 3e5,
|
|
625
638
|
verifyTimeoutMs = 12e4,
|
|
626
639
|
verifyIntervalMs = 2e3,
|
|
627
640
|
scope = "default"
|
|
@@ -650,6 +663,7 @@ function useEmbeddedPayment(options) {
|
|
|
650
663
|
const alive = react.useRef(true);
|
|
651
664
|
const generation = react.useRef(0);
|
|
652
665
|
const statusRef = react.useRef("idle");
|
|
666
|
+
const leftChallenge = react.useRef(false);
|
|
653
667
|
statusRef.current = status;
|
|
654
668
|
errorRef.current = error;
|
|
655
669
|
const amountKey = `${amount.amount}|${amount.currency_code}`;
|
|
@@ -833,6 +847,7 @@ function useEmbeddedPayment(options) {
|
|
|
833
847
|
(result) => {
|
|
834
848
|
const o = storefront.paymentOutcome(result, live.current.locale, live.current.messages);
|
|
835
849
|
pendingData.current = null;
|
|
850
|
+
leftChallenge.current = false;
|
|
836
851
|
setOutcome(o);
|
|
837
852
|
setError(null);
|
|
838
853
|
setAttemptsLeft(o.attempts_left);
|
|
@@ -917,15 +932,21 @@ function useEmbeddedPayment(options) {
|
|
|
917
932
|
setError(null);
|
|
918
933
|
setOutcome(null);
|
|
919
934
|
emit({ type: "submit" });
|
|
935
|
+
const withdrawn = () => !alive.current || form.current !== m;
|
|
936
|
+
const settle = () => {
|
|
937
|
+
if (alive.current) setStatus((s) => s === "processing" ? "idle" : s);
|
|
938
|
+
};
|
|
920
939
|
let data;
|
|
921
940
|
try {
|
|
922
941
|
data = await m.collect();
|
|
923
942
|
} catch {
|
|
943
|
+
if (withdrawn()) return settle();
|
|
924
944
|
emit({ type: "tokenize_error" });
|
|
925
945
|
setError({ kind: "generic", message: live.current.msgs["error.card_data"], retrySameAttempt: false, canRetry: true });
|
|
926
946
|
setStatus("ready");
|
|
927
947
|
return;
|
|
928
948
|
}
|
|
949
|
+
if (withdrawn()) return settle();
|
|
929
950
|
const attempt = readAttempt();
|
|
930
951
|
setAttemptId(attempt);
|
|
931
952
|
await send(data, attempt, total);
|
|
@@ -993,7 +1014,7 @@ function useEmbeddedPayment(options) {
|
|
|
993
1014
|
}
|
|
994
1015
|
let stop = false;
|
|
995
1016
|
const ctl = new AbortController();
|
|
996
|
-
const until = Date.now() + verifyTimeoutMs;
|
|
1017
|
+
const until = Date.now() + (leftChallenge.current ? Math.max(verifyTimeoutMs, pollTimeoutMs) : verifyTimeoutMs);
|
|
997
1018
|
setVerifying(true);
|
|
998
1019
|
(async () => {
|
|
999
1020
|
let wait = verifyIntervalMs;
|
|
@@ -1005,6 +1026,8 @@ function useEmbeddedPayment(options) {
|
|
|
1005
1026
|
const r = await transport.refresh({ signal: ctl.signal });
|
|
1006
1027
|
if (stop || !alive.current) return;
|
|
1007
1028
|
if (isResolvedAttempt(r)) {
|
|
1029
|
+
const settled = r.payment.status === "paid" || r.payment.status === "failed" || r.payment.status === "expired" || r.payment.status === "cancelled";
|
|
1030
|
+
if (leftChallenge.current && !settled && r.payment.action?.type === "challenge") continue;
|
|
1008
1031
|
setVerifying(false);
|
|
1009
1032
|
finish(r);
|
|
1010
1033
|
return;
|
|
@@ -1019,11 +1042,18 @@ function useEmbeddedPayment(options) {
|
|
|
1019
1042
|
ctl.abort();
|
|
1020
1043
|
setVerifying(false);
|
|
1021
1044
|
};
|
|
1022
|
-
}, [unknownOutcome, transport, verifyTimeoutMs, verifyIntervalMs, finish]);
|
|
1045
|
+
}, [unknownOutcome, transport, verifyTimeoutMs, verifyIntervalMs, pollTimeoutMs, finish]);
|
|
1023
1046
|
const dismiss = react.useCallback(() => {
|
|
1024
1047
|
setError(null);
|
|
1025
1048
|
setOutcome((o) => o?.kind === "rejected" ? null : o);
|
|
1026
1049
|
}, []);
|
|
1050
|
+
const cancelChallenge = react.useCallback(() => {
|
|
1051
|
+
if (statusRef.current !== "challenge") return;
|
|
1052
|
+
leftChallenge.current = true;
|
|
1053
|
+
setOutcome(null);
|
|
1054
|
+
setError({ kind: "payment_in_progress", message: live.current.msgs["challenge.left"], retrySameAttempt: false, canRetry: false });
|
|
1055
|
+
setStatus("blocked");
|
|
1056
|
+
}, []);
|
|
1027
1057
|
const message = status === "processing" ? msgs["state.processing"] : status === "fallback" ? msgs["state.fallback"] : error?.message ?? outcome?.message ?? (status === "loading" ? msgs["state.loading"] : null);
|
|
1028
1058
|
return {
|
|
1029
1059
|
status,
|
|
@@ -1039,7 +1069,8 @@ function useEmbeddedPayment(options) {
|
|
|
1039
1069
|
containerId,
|
|
1040
1070
|
submit,
|
|
1041
1071
|
retry,
|
|
1042
|
-
dismiss
|
|
1072
|
+
dismiss,
|
|
1073
|
+
cancelChallenge
|
|
1043
1074
|
};
|
|
1044
1075
|
}
|
|
1045
1076
|
function VoucherCard({ outcome, locale, messages, className }) {
|
|
@@ -1076,15 +1107,55 @@ function VoucherCard({ outcome, locale, messages, className }) {
|
|
|
1076
1107
|
/* @__PURE__ */ jsxRuntime.jsx("p", { children: m["voucher.email"] })
|
|
1077
1108
|
] });
|
|
1078
1109
|
}
|
|
1079
|
-
function PaymentChallenge({ outcome, locale, messages, render, onCancel }) {
|
|
1110
|
+
function PaymentChallenge({ outcome, locale, messages, render, onCancel, escapeAfterMs = 12e4 }) {
|
|
1080
1111
|
const m = storefront.paymentMessages(locale, messages);
|
|
1081
|
-
const { ref } = useModalDialog({ open: true, onClose: () =>
|
|
1112
|
+
const { ref } = useModalDialog({ open: true, onClose: () => {
|
|
1113
|
+
} });
|
|
1114
|
+
const [canEscape, setCanEscape] = react.useState(false);
|
|
1115
|
+
const [closed, setClosed] = react.useState(false);
|
|
1116
|
+
const cancelRef = react.useRef(onCancel);
|
|
1117
|
+
cancelRef.current = onCancel;
|
|
1118
|
+
const hasCancel = !!onCancel;
|
|
1119
|
+
react.useEffect(() => {
|
|
1120
|
+
if (!hasCancel) return;
|
|
1121
|
+
const t = setTimeout(() => setCanEscape(true), escapeAfterMs);
|
|
1122
|
+
return () => clearTimeout(t);
|
|
1123
|
+
}, [hasCancel, escapeAfterMs]);
|
|
1124
|
+
react.useEffect(() => {
|
|
1125
|
+
const el = ref.current;
|
|
1126
|
+
if (!el) return;
|
|
1127
|
+
const onClosed = () => setClosed(true);
|
|
1128
|
+
el.addEventListener("close", onClosed);
|
|
1129
|
+
return () => el.removeEventListener("close", onClosed);
|
|
1130
|
+
}, [ref]);
|
|
1131
|
+
const reopen = () => {
|
|
1132
|
+
const el = ref.current;
|
|
1133
|
+
if (!el) return;
|
|
1134
|
+
try {
|
|
1135
|
+
if (typeof el.showModal === "function") el.showModal();
|
|
1136
|
+
else el.setAttribute("open", "");
|
|
1137
|
+
} catch {
|
|
1138
|
+
el.setAttribute("open", "");
|
|
1139
|
+
}
|
|
1140
|
+
setClosed(false);
|
|
1141
|
+
el.querySelector("[data-sf-autofocus]")?.focus({ preventScroll: true });
|
|
1142
|
+
};
|
|
1082
1143
|
const url = outcome.challenge?.url;
|
|
1083
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
1084
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1144
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1145
|
+
closed && /* @__PURE__ */ jsxRuntime.jsxs("p", { role: "status", "data-sf-challenge-closed": true, children: [
|
|
1146
|
+
m["state.challenge"],
|
|
1147
|
+
" ",
|
|
1148
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: reopen, "data-sf-challenge-reopen": true, style: { minWidth: 44, minHeight: 44 }, children: m["challenge.title"] })
|
|
1149
|
+
] }),
|
|
1150
|
+
/* @__PURE__ */ jsxRuntime.jsx("dialog", { ref, "aria-labelledby": "sf-challenge-title", "data-sf-challenge": true, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-sf-challenge-body": true, children: [
|
|
1151
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { id: "sf-challenge-title", "data-sf-autofocus": true, tabIndex: -1, children: m["challenge.title"] }),
|
|
1152
|
+
render ? render(outcome) : url ? /* @__PURE__ */ jsxRuntime.jsx("iframe", { src: url, title: m["challenge.title"], "data-sf-challenge-frame": true, style: { width: "100%", minHeight: 420, border: 0 } }) : /* @__PURE__ */ jsxRuntime.jsx("p", { children: m["state.challenge"] }),
|
|
1153
|
+
hasCancel && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-sf-challenge-escape": true, "aria-live": "polite", children: canEscape && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1154
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: m["challenge.escape_hint"] }),
|
|
1155
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => cancelRef.current?.(), style: { minWidth: 44, minHeight: 44 }, children: m["challenge.escape"] })
|
|
1156
|
+
] }) })
|
|
1157
|
+
] }) })
|
|
1158
|
+
] });
|
|
1088
1159
|
}
|
|
1089
1160
|
var PaymentBrick = react.forwardRef(function PaymentBrick2(props, ref) {
|
|
1090
1161
|
const { submitLabel, hideAmountInButton, renderVoucher, renderChallenge, minHeight = 360, className, style, ...hookOptions } = props;
|
|
@@ -1122,7 +1193,7 @@ var PaymentBrick = react.forwardRef(function PaymentBrick2(props, ref) {
|
|
|
1122
1193
|
state.status === "network_error" && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void state.retry(), style: { minHeight: 44 }, children: m["action.retry"] })
|
|
1123
1194
|
] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { role: "status", "aria-live": "polite", "data-sf-pay-message": true, children: state.message }),
|
|
1124
1195
|
outcome?.kind === "voucher" && (renderVoucher ? renderVoucher(outcome) : /* @__PURE__ */ jsxRuntime.jsx(VoucherCard, { outcome, locale, ...props.messages ? { messages: props.messages } : {} })),
|
|
1125
|
-
outcome?.kind === "challenge" && /* @__PURE__ */ jsxRuntime.jsx(PaymentChallenge, { outcome, locale, ...props.messages ? { messages: props.messages } : {}, ...renderChallenge ? { render: renderChallenge } : {} }),
|
|
1196
|
+
outcome?.kind === "challenge" && /* @__PURE__ */ jsxRuntime.jsx(PaymentChallenge, { outcome, locale, onCancel: state.cancelChallenge, ...props.messages ? { messages: props.messages } : {}, ...renderChallenge ? { render: renderChallenge } : {} }),
|
|
1126
1197
|
submitLabel !== void 0 && showForm && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1127
1198
|
"button",
|
|
1128
1199
|
{
|