@funnelsgrove/payments 0.11.7 → 0.11.9
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/providers/stripe/components/SharedStripeCheckoutDialog.js +5 -2
- package/dist/providers/stripe/components/SharedStripeCheckoutV2Dialog.js +11 -3
- package/dist/providers/stripe/components/StripeCheckoutExpressCheckoutButton.js +5 -2
- package/dist/providers/stripe/components/StripeExpressCheckoutButton.js +5 -2
- package/dist/services/checkoutObservability.service.d.ts +3 -0
- package/dist/services/checkoutObservability.service.js +33 -3
- package/package.json +1 -1
|
@@ -142,7 +142,7 @@ function SharedStripeCheckoutForm({ amountCents, checkoutAnalytics, checkoutSess
|
|
|
142
142
|
!submitting;
|
|
143
143
|
const walletCheckoutAllowed = allowApplePayExpressCheckout || allowApplePayQrFallback;
|
|
144
144
|
const walletFallbackDisabled = !walletCheckoutAllowed || walletAvailable === false;
|
|
145
|
-
const setSharedError = (message, alreadyTracked = false) => {
|
|
145
|
+
const setSharedError = (message, alreadyTracked = false, providerError) => {
|
|
146
146
|
if (message && checkoutAnalytics && !alreadyTracked) {
|
|
147
147
|
trackCheckoutFailureShown({
|
|
148
148
|
analytics: checkoutAnalytics,
|
|
@@ -151,6 +151,9 @@ function SharedStripeCheckoutForm({ amountCents, checkoutAnalytics, checkoutSess
|
|
|
151
151
|
failureStage: 'card_form',
|
|
152
152
|
paymentMethod: 'card',
|
|
153
153
|
provider: 'stripe',
|
|
154
|
+
providerDeclineCode: providerError === null || providerError === void 0 ? void 0 : providerError.decline_code,
|
|
155
|
+
providerErrorCode: providerError === null || providerError === void 0 ? void 0 : providerError.code,
|
|
156
|
+
providerErrorType: providerError === null || providerError === void 0 ? void 0 : providerError.type,
|
|
154
157
|
});
|
|
155
158
|
}
|
|
156
159
|
setError(message);
|
|
@@ -216,7 +219,7 @@ function SharedStripeCheckoutForm({ amountCents, checkoutAnalytics, checkoutSess
|
|
|
216
219
|
return_url: returnUrl,
|
|
217
220
|
});
|
|
218
221
|
if (result.error) {
|
|
219
|
-
setSharedError(result.error.message || 'Payment failed.');
|
|
222
|
+
setSharedError(result.error.message || 'Payment failed.', false, result.error);
|
|
220
223
|
setSubmitting(false);
|
|
221
224
|
return;
|
|
222
225
|
}
|
|
@@ -70,6 +70,7 @@ function SharedStripeCheckoutV2CheckoutSessionForm({ amountCents, buttonColor, c
|
|
|
70
70
|
? true
|
|
71
71
|
: walletAvailable;
|
|
72
72
|
const [submitting, setSubmitting] = useState(false);
|
|
73
|
+
const [paymentElementReady, setPaymentElementReady] = useState(false);
|
|
73
74
|
const [error, setError] = useState(null);
|
|
74
75
|
const [billingCountry, setBillingCountry] = useState(null);
|
|
75
76
|
const initialCustomerEmail = (customerEmail === null || customerEmail === void 0 ? void 0 : customerEmail.trim()) || '';
|
|
@@ -152,7 +153,7 @@ function SharedStripeCheckoutV2CheckoutSessionForm({ amountCents, buttonColor, c
|
|
|
152
153
|
setError(null);
|
|
153
154
|
onInactiveCheckoutSession === null || onInactiveCheckoutSession === void 0 ? void 0 : onInactiveCheckoutSession();
|
|
154
155
|
};
|
|
155
|
-
const setSharedError = (message, alreadyTracked = false) => {
|
|
156
|
+
const setSharedError = (message, alreadyTracked = false, providerError) => {
|
|
156
157
|
if (isInactiveCheckoutSessionError(message)) {
|
|
157
158
|
handleInactiveCheckoutSession();
|
|
158
159
|
return;
|
|
@@ -165,6 +166,9 @@ function SharedStripeCheckoutV2CheckoutSessionForm({ amountCents, buttonColor, c
|
|
|
165
166
|
failureStage: 'card_form',
|
|
166
167
|
paymentMethod: 'card',
|
|
167
168
|
provider: 'stripe',
|
|
169
|
+
providerDeclineCode: providerError === null || providerError === void 0 ? void 0 : providerError.decline_code,
|
|
170
|
+
providerErrorCode: providerError === null || providerError === void 0 ? void 0 : providerError.code,
|
|
171
|
+
providerErrorType: providerError === null || providerError === void 0 ? void 0 : providerError.type,
|
|
168
172
|
});
|
|
169
173
|
}
|
|
170
174
|
setError(message);
|
|
@@ -260,6 +264,10 @@ function SharedStripeCheckoutV2CheckoutSessionForm({ amountCents, buttonColor, c
|
|
|
260
264
|
: 'Payment form is not ready yet.');
|
|
261
265
|
return;
|
|
262
266
|
}
|
|
267
|
+
if (!paymentElementReady) {
|
|
268
|
+
setSharedError('Payment form is not ready yet.', true);
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
263
271
|
setSubmitting(true);
|
|
264
272
|
setSharedError(null);
|
|
265
273
|
try {
|
|
@@ -274,7 +282,7 @@ function SharedStripeCheckoutV2CheckoutSessionForm({ amountCents, buttonColor, c
|
|
|
274
282
|
});
|
|
275
283
|
if (result.type === 'error') {
|
|
276
284
|
const message = result.error.message || 'Payment failed.';
|
|
277
|
-
setSharedError(message);
|
|
285
|
+
setSharedError(message, false, result.error);
|
|
278
286
|
setSubmitting(false);
|
|
279
287
|
return;
|
|
280
288
|
}
|
|
@@ -322,7 +330,7 @@ function SharedStripeCheckoutV2CheckoutSessionForm({ amountCents, buttonColor, c
|
|
|
322
330
|
}
|
|
323
331
|
setEmailDraft(event.target.value);
|
|
324
332
|
onCustomerEmailChange === null || onCustomerEmailChange === void 0 ? void 0 : onCustomerEmailChange(event.target.value);
|
|
325
|
-
} }) })] }), _jsx(PaymentElement, { options: paymentElementOptions, onChange: handlePaymentElementChange }), fixedBillingCountry && fixedBillingCountryLabel ? (_jsxs("label", { className: 'shared-checkout-v2-country-field', children: [_jsx("span", { className: 'shared-checkout-v2-country-label', children: "Country" }), _jsx("span", { className: 'shared-checkout-v2-country-control', children: _jsx("select", { "aria-label": 'Country', className: 'shared-checkout-v2-country-select', value: fixedBillingCountry, onChange: () => setBillingCountry(fixedBillingCountry), children: _jsx("option", { value: fixedBillingCountry, children: fixedBillingCountryLabel }) }) })] })) : null] }), visibleError ? _jsx("p", { className: 'shared-checkout-v2-error', children: visibleError }) : null, _jsxs("button", { type: 'submit', className: 'shared-checkout-v2-card-submit', disabled: submitting, children: [_jsx(SecurityLockIcon, { className: 'shared-checkout-v2-card-submit-icon' }), submitting ? processingLabel : cardSubmitLabel] }), _jsx("div", { className: 'shared-checkout-v2-card-brands', "aria-hidden": 'true', children: cardBrandLabels.map((label) => (_jsx(PaymentBrandMark, { label: label, className: 'shared-checkout-v2-card-brand' }, label))) }), _jsxs("p", { className: 'shared-checkout-v2-secure-pill shared-checkout-v2-secure-pill--card', children: [_jsx(SecurityLockIcon, { className: 'shared-checkout-v2-secure-pill-icon' }), secureLabel] })] })] })] }));
|
|
333
|
+
} }) })] }), _jsx(PaymentElement, { options: paymentElementOptions, onChange: handlePaymentElementChange, onReady: () => setPaymentElementReady(true) }), fixedBillingCountry && fixedBillingCountryLabel ? (_jsxs("label", { className: 'shared-checkout-v2-country-field', children: [_jsx("span", { className: 'shared-checkout-v2-country-label', children: "Country" }), _jsx("span", { className: 'shared-checkout-v2-country-control', children: _jsx("select", { "aria-label": 'Country', className: 'shared-checkout-v2-country-select', value: fixedBillingCountry, onChange: () => setBillingCountry(fixedBillingCountry), children: _jsx("option", { value: fixedBillingCountry, children: fixedBillingCountryLabel }) }) })] })) : null] }), visibleError ? _jsx("p", { className: 'shared-checkout-v2-error', children: visibleError }) : null, _jsxs("button", { type: 'submit', className: 'shared-checkout-v2-card-submit', disabled: submitting || !paymentElementReady, children: [_jsx(SecurityLockIcon, { className: 'shared-checkout-v2-card-submit-icon' }), submitting ? processingLabel : cardSubmitLabel] }), _jsx("div", { className: 'shared-checkout-v2-card-brands', "aria-hidden": 'true', children: cardBrandLabels.map((label) => (_jsx(PaymentBrandMark, { label: label, className: 'shared-checkout-v2-card-brand' }, label))) }), _jsxs("p", { className: 'shared-checkout-v2-secure-pill shared-checkout-v2-secure-pill--card', children: [_jsx(SecurityLockIcon, { className: 'shared-checkout-v2-secure-pill-icon' }), secureLabel] })] })] })] }));
|
|
326
334
|
}
|
|
327
335
|
function CheckoutSessionProvider({ children, clientSecret, fixedBillingCountry, stripePromise, variant, }) {
|
|
328
336
|
const providerChildren = children;
|
|
@@ -120,7 +120,7 @@ export function StripeCheckoutExpressCheckoutButton({ beforeConfirm, checkoutAna
|
|
|
120
120
|
checkoutStartSource,
|
|
121
121
|
paymentMethod }));
|
|
122
122
|
};
|
|
123
|
-
const reportFailure = (message, failureStage, paymentMethod) => {
|
|
123
|
+
const reportFailure = (message, failureStage, paymentMethod, providerError) => {
|
|
124
124
|
if (checkoutAnalytics) {
|
|
125
125
|
trackCheckoutFailureShown({
|
|
126
126
|
analytics: checkoutAnalytics,
|
|
@@ -129,6 +129,9 @@ export function StripeCheckoutExpressCheckoutButton({ beforeConfirm, checkoutAna
|
|
|
129
129
|
failureStage,
|
|
130
130
|
paymentMethod,
|
|
131
131
|
provider: 'stripe',
|
|
132
|
+
providerDeclineCode: providerError === null || providerError === void 0 ? void 0 : providerError.decline_code,
|
|
133
|
+
providerErrorCode: providerError === null || providerError === void 0 ? void 0 : providerError.code,
|
|
134
|
+
providerErrorType: providerError === null || providerError === void 0 ? void 0 : providerError.type,
|
|
132
135
|
});
|
|
133
136
|
}
|
|
134
137
|
onError === null || onError === void 0 ? void 0 : onError(message);
|
|
@@ -202,7 +205,7 @@ export function StripeCheckoutExpressCheckoutButton({ beforeConfirm, checkoutAna
|
|
|
202
205
|
: {})), { expressCheckoutConfirmEvent: event, redirect: 'if_required' }));
|
|
203
206
|
if (result.type === 'error') {
|
|
204
207
|
const message = result.error.message || 'Wallet checkout failed.';
|
|
205
|
-
reportFailure(message, 'wallet_confirmation', event.expressPaymentType);
|
|
208
|
+
reportFailure(message, 'wallet_confirmation', event.expressPaymentType, result.error);
|
|
206
209
|
event.paymentFailed({ reason: 'fail', message });
|
|
207
210
|
return;
|
|
208
211
|
}
|
|
@@ -70,7 +70,7 @@ export function StripeExpressCheckoutButton({ amountCents, beforeConfirm, checko
|
|
|
70
70
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
71
71
|
return Object.assign(Object.assign(Object.assign({}, baseOptions), (options !== null && options !== void 0 ? options : {})), { buttonTheme: Object.assign(Object.assign({}, ((_a = baseOptions.buttonTheme) !== null && _a !== void 0 ? _a : {})), ((_b = options === null || options === void 0 ? void 0 : options.buttonTheme) !== null && _b !== void 0 ? _b : {})), buttonType: Object.assign(Object.assign({}, ((_c = baseOptions.buttonType) !== null && _c !== void 0 ? _c : {})), ((_d = options === null || options === void 0 ? void 0 : options.buttonType) !== null && _d !== void 0 ? _d : {})), layout: Object.assign(Object.assign({}, ((_e = baseOptions.layout) !== null && _e !== void 0 ? _e : {})), ((_f = options === null || options === void 0 ? void 0 : options.layout) !== null && _f !== void 0 ? _f : {})), paymentMethods: Object.assign(Object.assign({}, ((_g = baseOptions.paymentMethods) !== null && _g !== void 0 ? _g : {})), ((_h = options === null || options === void 0 ? void 0 : options.paymentMethods) !== null && _h !== void 0 ? _h : {})), lineItems: (_j = options === null || options === void 0 ? void 0 : options.lineItems) !== null && _j !== void 0 ? _j : baseOptions.lineItems, paymentMethodOrder: (_k = options === null || options === void 0 ? void 0 : options.paymentMethodOrder) !== null && _k !== void 0 ? _k : baseOptions.paymentMethodOrder });
|
|
72
72
|
}, [baseOptions, options]);
|
|
73
|
-
const reportFailure = (message, failureStage, paymentMethod) => {
|
|
73
|
+
const reportFailure = (message, failureStage, paymentMethod, providerError) => {
|
|
74
74
|
if (checkoutAnalytics) {
|
|
75
75
|
trackCheckoutFailureShown({
|
|
76
76
|
analytics: checkoutAnalytics,
|
|
@@ -79,6 +79,9 @@ export function StripeExpressCheckoutButton({ amountCents, beforeConfirm, checko
|
|
|
79
79
|
failureStage,
|
|
80
80
|
paymentMethod,
|
|
81
81
|
provider: 'stripe',
|
|
82
|
+
providerDeclineCode: providerError === null || providerError === void 0 ? void 0 : providerError.decline_code,
|
|
83
|
+
providerErrorCode: providerError === null || providerError === void 0 ? void 0 : providerError.code,
|
|
84
|
+
providerErrorType: providerError === null || providerError === void 0 ? void 0 : providerError.type,
|
|
82
85
|
});
|
|
83
86
|
}
|
|
84
87
|
onError === null || onError === void 0 ? void 0 : onError(message);
|
|
@@ -150,7 +153,7 @@ export function StripeExpressCheckoutButton({ amountCents, beforeConfirm, checko
|
|
|
150
153
|
});
|
|
151
154
|
if (result.error) {
|
|
152
155
|
const message = result.error.message || 'Wallet checkout failed.';
|
|
153
|
-
reportFailure(message, 'wallet_confirmation', event.expressPaymentType);
|
|
156
|
+
reportFailure(message, 'wallet_confirmation', event.expressPaymentType, result.error);
|
|
154
157
|
event.paymentFailed({ reason: 'fail', message });
|
|
155
158
|
return;
|
|
156
159
|
}
|
|
@@ -25,6 +25,9 @@ type CheckoutObservabilityInput = {
|
|
|
25
25
|
type CheckoutFailureShownInput = CheckoutObservabilityInput & {
|
|
26
26
|
errorCode?: string | null;
|
|
27
27
|
errorMessage: string;
|
|
28
|
+
providerDeclineCode?: string | null;
|
|
29
|
+
providerErrorCode?: string | null;
|
|
30
|
+
providerErrorType?: string | null;
|
|
28
31
|
};
|
|
29
32
|
export declare const trackCheckoutFailureShown: (input: CheckoutFailureShownInput) => string | null;
|
|
30
33
|
export declare const trackCheckoutCanceled: (input: CheckoutObservabilityInput) => string | null;
|
|
@@ -26,6 +26,18 @@ export const resolveCheckoutObservabilityAnalyticsContext = (input) => {
|
|
|
26
26
|
stepContractVersion: (_x = (_w = input.analytics) === null || _w === void 0 ? void 0 : _w.stepContractVersion) !== null && _x !== void 0 ? _x : validStepContractVersion,
|
|
27
27
|
};
|
|
28
28
|
};
|
|
29
|
+
const STRIPE_PAYMENT_REJECTION_CODES = new Set([
|
|
30
|
+
'card_declined',
|
|
31
|
+
'expired_card',
|
|
32
|
+
'incorrect_cvc',
|
|
33
|
+
'incorrect_number',
|
|
34
|
+
'incorrect_zip',
|
|
35
|
+
'insufficient_funds',
|
|
36
|
+
'invalid_cvc',
|
|
37
|
+
'invalid_expiry_month',
|
|
38
|
+
'invalid_expiry_year',
|
|
39
|
+
'payment_intent_authentication_failure',
|
|
40
|
+
]);
|
|
29
41
|
const sanitizeErrorMessage = (value) => value
|
|
30
42
|
.replace(/[\r\n\t]+/g, ' ')
|
|
31
43
|
.replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, '[redacted-email]')
|
|
@@ -63,6 +75,9 @@ const reportCheckoutObservability = (input) => {
|
|
|
63
75
|
funnelVersionId: ((_g = runtimeConfig === null || runtimeConfig === void 0 ? void 0 : runtimeConfig.funnelVersionId) === null || _g === void 0 ? void 0 : _g.trim()) || FUNNEL_VERSION_ID.trim() || undefined,
|
|
64
76
|
paymentMethod: input.paymentMethod || undefined,
|
|
65
77
|
provider: input.provider,
|
|
78
|
+
providerDeclineCode: input.providerDeclineCode,
|
|
79
|
+
providerErrorCode: input.providerErrorCode,
|
|
80
|
+
providerErrorType: input.providerErrorType,
|
|
66
81
|
}),
|
|
67
82
|
keepalive: true,
|
|
68
83
|
}).then(() => undefined);
|
|
@@ -83,7 +98,7 @@ const resolveErrorCode = (message, requestedCode) => {
|
|
|
83
98
|
const emitCheckoutObservability = (eventType, input, failure) => {
|
|
84
99
|
var _a, _b;
|
|
85
100
|
const paymentMethod = toAnalyticsPaymentMethod(input.paymentMethod);
|
|
86
|
-
const metadata = Object.assign(Object.assign({}, ((_a = input.analytics.metadata) !== null && _a !== void 0 ? _a : {})), { checkout_session_id: ((_b = input.checkoutSessionId) === null || _b === void 0 ? void 0 : _b.trim()) || undefined, checkout_failure_stage: input.failureStage, payment_provider: input.provider, payment_method: paymentMethod || undefined, error_code: failure === null || failure === void 0 ? void 0 : failure.errorCode, error_message: failure === null || failure === void 0 ? void 0 : failure.errorMessage });
|
|
101
|
+
const metadata = Object.assign(Object.assign({}, ((_a = input.analytics.metadata) !== null && _a !== void 0 ? _a : {})), { checkout_session_id: ((_b = input.checkoutSessionId) === null || _b === void 0 ? void 0 : _b.trim()) || undefined, checkout_failure_stage: input.failureStage, payment_provider: input.provider, payment_method: paymentMethod || undefined, error_code: failure === null || failure === void 0 ? void 0 : failure.errorCode, error_message: failure === null || failure === void 0 ? void 0 : failure.errorMessage, provider_decline_code: failure === null || failure === void 0 ? void 0 : failure.providerDeclineCode, provider_error_code: failure === null || failure === void 0 ? void 0 : failure.providerErrorCode, provider_error_type: failure === null || failure === void 0 ? void 0 : failure.providerErrorType });
|
|
87
102
|
const eventId = publicAnalyticsSdk.track({
|
|
88
103
|
eventType,
|
|
89
104
|
environment: input.analytics.environment,
|
|
@@ -107,18 +122,33 @@ const emitCheckoutObservability = (eventType, input, failure) => {
|
|
|
107
122
|
failureStage: input.failureStage,
|
|
108
123
|
paymentMethod,
|
|
109
124
|
provider: input.provider,
|
|
125
|
+
providerDeclineCode: failure === null || failure === void 0 ? void 0 : failure.providerDeclineCode,
|
|
126
|
+
providerErrorCode: failure === null || failure === void 0 ? void 0 : failure.providerErrorCode,
|
|
127
|
+
providerErrorType: failure === null || failure === void 0 ? void 0 : failure.providerErrorType,
|
|
110
128
|
}).catch(() => undefined);
|
|
111
129
|
void publicAnalyticsSdk.flush().catch(() => 0);
|
|
112
130
|
return eventId;
|
|
113
131
|
};
|
|
114
132
|
export const trackCheckoutFailureShown = (input) => {
|
|
133
|
+
var _a, _b, _c;
|
|
115
134
|
const errorMessage = sanitizeErrorMessage(input.errorMessage);
|
|
116
135
|
if (!errorMessage) {
|
|
117
136
|
return null;
|
|
118
137
|
}
|
|
119
|
-
|
|
120
|
-
|
|
138
|
+
const providerDeclineCode = (_a = asNonEmptyString(input.providerDeclineCode)) === null || _a === void 0 ? void 0 : _a.slice(0, 120);
|
|
139
|
+
const providerErrorCode = (_b = asNonEmptyString(input.providerErrorCode)) === null || _b === void 0 ? void 0 : _b.slice(0, 120);
|
|
140
|
+
const providerErrorType = (_c = asNonEmptyString(input.providerErrorType)) === null || _c === void 0 ? void 0 : _c.slice(0, 120);
|
|
141
|
+
const paymentRejected = input.provider === 'stripe' && (Boolean(providerDeclineCode)
|
|
142
|
+
|| providerErrorType === 'card_error'
|
|
143
|
+
|| (providerErrorCode ? STRIPE_PAYMENT_REJECTION_CODES.has(providerErrorCode) : false));
|
|
144
|
+
return emitCheckoutObservability(paymentRejected ? 'checkout_payment_rejected' : 'checkout_failure_shown', input, {
|
|
145
|
+
errorCode: paymentRejected
|
|
146
|
+
? providerDeclineCode || providerErrorCode || 'payment_rejected'
|
|
147
|
+
: resolveErrorCode(errorMessage, input.errorCode),
|
|
121
148
|
errorMessage,
|
|
149
|
+
providerDeclineCode,
|
|
150
|
+
providerErrorCode,
|
|
151
|
+
providerErrorType,
|
|
122
152
|
});
|
|
123
153
|
};
|
|
124
154
|
export const trackCheckoutCanceled = (input) => emitCheckoutObservability('checkout_canceled', input);
|