@funnelsgrove/payments 0.14.0 → 0.15.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/providers/stripe/components/SharedStripeCheckoutV2Dialog.js +12 -6
- package/dist/providers/stripe/hooks/useStripeOneTimeCheckoutSession.js +1 -0
- package/dist/providers/stripe/hooks/useStripeSubscriptionCheckoutSession.js +2 -0
- package/dist/providers/stripe/services/stripeCheckoutFailure.d.ts +1 -0
- package/dist/providers/stripe/services/stripeCheckoutFailure.js +3 -4
- package/dist/services/checkoutObservability.service.d.ts +1 -0
- package/dist/services/checkoutObservability.service.js +6 -1
- package/package.json +3 -3
|
@@ -11,7 +11,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
return t;
|
|
12
12
|
};
|
|
13
13
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
14
|
-
import { useCallback, useEffect, useMemo, useState, } from 'react';
|
|
14
|
+
import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
|
|
15
15
|
import { CheckoutProvider, PaymentElement, useCheckout, } from '@stripe/react-stripe-js/checkout';
|
|
16
16
|
import { PaymentBrandMark, SecurityLockIcon } from './CheckoutBrandAssets.js';
|
|
17
17
|
import { StripeCheckoutExpressCheckoutButton } from './StripeCheckoutExpressCheckoutButton.js';
|
|
@@ -70,6 +70,7 @@ function SharedStripeCheckoutV2CheckoutSessionForm({ amountCents, buttonColor, c
|
|
|
70
70
|
? true
|
|
71
71
|
: walletAvailable;
|
|
72
72
|
const [submitting, setSubmitting] = useState(false);
|
|
73
|
+
const submitInFlightRef = useRef(false);
|
|
73
74
|
const [paymentElementReady, setPaymentElementReady] = useState(false);
|
|
74
75
|
const [error, setError] = useState(null);
|
|
75
76
|
const [billingCountry, setBillingCountry] = useState(null);
|
|
@@ -250,7 +251,7 @@ function SharedStripeCheckoutV2CheckoutSessionForm({ amountCents, buttonColor, c
|
|
|
250
251
|
};
|
|
251
252
|
const handleSubmit = async (event) => {
|
|
252
253
|
event.preventDefault();
|
|
253
|
-
if (
|
|
254
|
+
if (submitInFlightRef.current) {
|
|
254
255
|
return;
|
|
255
256
|
}
|
|
256
257
|
const billingCountryError = getBillingCountryError(billingCountry !== null && billingCountry !== void 0 ? billingCountry : fixedBillingCountry);
|
|
@@ -268,12 +269,17 @@ function SharedStripeCheckoutV2CheckoutSessionForm({ amountCents, buttonColor, c
|
|
|
268
269
|
setSharedError('Payment form is not ready yet.', true);
|
|
269
270
|
return;
|
|
270
271
|
}
|
|
272
|
+
submitInFlightRef.current = true;
|
|
271
273
|
setSubmitting(true);
|
|
272
274
|
setSharedError(null);
|
|
275
|
+
const finishSubmitting = () => {
|
|
276
|
+
submitInFlightRef.current = false;
|
|
277
|
+
setSubmitting(false);
|
|
278
|
+
};
|
|
273
279
|
try {
|
|
274
280
|
const syncedEmail = await ensureCustomerEmail();
|
|
275
281
|
if (!syncedEmail) {
|
|
276
|
-
|
|
282
|
+
finishSubmitting();
|
|
277
283
|
return;
|
|
278
284
|
}
|
|
279
285
|
await trackPaymentInfoSubmitted();
|
|
@@ -283,7 +289,7 @@ function SharedStripeCheckoutV2CheckoutSessionForm({ amountCents, buttonColor, c
|
|
|
283
289
|
if (result.type === 'error') {
|
|
284
290
|
const message = result.error.message || 'Payment failed.';
|
|
285
291
|
setSharedError(message, false, result.error);
|
|
286
|
-
|
|
292
|
+
finishSubmitting();
|
|
287
293
|
return;
|
|
288
294
|
}
|
|
289
295
|
if (typeof window !== 'undefined') {
|
|
@@ -291,11 +297,11 @@ function SharedStripeCheckoutV2CheckoutSessionForm({ amountCents, buttonColor, c
|
|
|
291
297
|
window.location.assign(returnUrl);
|
|
292
298
|
return;
|
|
293
299
|
}
|
|
294
|
-
|
|
300
|
+
finishSubmitting();
|
|
295
301
|
}
|
|
296
302
|
catch (submitError) {
|
|
297
303
|
setSharedError(getFriendlyCardErrorMessage(submitError));
|
|
298
|
-
|
|
304
|
+
finishSubmitting();
|
|
299
305
|
}
|
|
300
306
|
};
|
|
301
307
|
const visibleError = error;
|
|
@@ -239,6 +239,7 @@ export function useStripeOneTimeCheckoutSession({ runtimeConfigRevisionId, payme
|
|
|
239
239
|
paymentMethod: options.paymentMethod,
|
|
240
240
|
provider: 'stripe',
|
|
241
241
|
providerErrorCode: failure.providerErrorCode,
|
|
242
|
+
checkoutRequestId: failure.checkoutRequestId,
|
|
242
243
|
});
|
|
243
244
|
}
|
|
244
245
|
setError(message);
|
|
@@ -259,6 +259,7 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, analyticsMe
|
|
|
259
259
|
paymentMethod: options.paymentMethod,
|
|
260
260
|
provider: 'stripe',
|
|
261
261
|
providerErrorCode: failure.providerErrorCode,
|
|
262
|
+
checkoutRequestId: failure.checkoutRequestId,
|
|
262
263
|
});
|
|
263
264
|
}
|
|
264
265
|
setError(message);
|
|
@@ -380,6 +381,7 @@ export function useStripeSubscriptionCheckoutSession({ checkoutMode, analyticsMe
|
|
|
380
381
|
failureStage: 'checkout_session_update',
|
|
381
382
|
provider: 'stripe',
|
|
382
383
|
providerErrorCode: failure.providerErrorCode,
|
|
384
|
+
checkoutRequestId: failure.checkoutRequestId,
|
|
383
385
|
});
|
|
384
386
|
}
|
|
385
387
|
setError(message);
|
|
@@ -14,9 +14,8 @@ export const describeStripeCheckoutFailure = (error) => {
|
|
|
14
14
|
: rawMessage === 'Internal server error'
|
|
15
15
|
? 'Unable to initialize checkout. Stripe settings may be missing for this funnel.'
|
|
16
16
|
: rawMessage;
|
|
17
|
-
return {
|
|
18
|
-
errorCode,
|
|
17
|
+
return Object.assign(Object.assign({}, (error instanceof FunnelSdkHttpError && error.checkoutRequestId
|
|
18
|
+
? { checkoutRequestId: error.checkoutRequestId } : {})), { errorCode,
|
|
19
19
|
message,
|
|
20
|
-
providerErrorCode
|
|
21
|
-
};
|
|
20
|
+
providerErrorCode });
|
|
22
21
|
};
|
|
@@ -23,6 +23,7 @@ type CheckoutObservabilityInput = {
|
|
|
23
23
|
provider: 'solidgate' | 'stripe';
|
|
24
24
|
};
|
|
25
25
|
type CheckoutFailureShownInput = CheckoutObservabilityInput & {
|
|
26
|
+
checkoutRequestId?: string;
|
|
26
27
|
errorCode?: string | null;
|
|
27
28
|
errorMessage: string;
|
|
28
29
|
providerDeclineCode?: string | null;
|
|
@@ -96,6 +96,7 @@ const reportCheckoutObservability = (input) => {
|
|
|
96
96
|
: buildSdkHeaders({ 'Content-Type': 'application/json' }),
|
|
97
97
|
body: JSON.stringify({
|
|
98
98
|
checkoutSessionId: input.checkoutSessionId || undefined,
|
|
99
|
+
checkoutRequestId: input.checkoutRequestId,
|
|
99
100
|
environment,
|
|
100
101
|
errorCode: input.errorCode,
|
|
101
102
|
errorMessage: input.errorMessage,
|
|
@@ -134,7 +135,7 @@ const resolveErrorCode = (message, requestedCode) => {
|
|
|
134
135
|
const emitCheckoutObservability = (eventType, input, failure) => {
|
|
135
136
|
var _a, _b, _c, _d;
|
|
136
137
|
const paymentMethod = toAnalyticsPaymentMethod(input.paymentMethod);
|
|
137
|
-
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, checkout_failure_category: (_c = failure === null || failure === void 0 ? void 0 : failure.failureCategory) !== null && _c !== void 0 ? _c : (eventType === 'checkout_canceled' ? 'user_canceled' : undefined), 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 });
|
|
138
|
+
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_request_id: failure === null || failure === void 0 ? void 0 : failure.checkoutRequestId, 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, checkout_failure_category: (_c = failure === null || failure === void 0 ? void 0 : failure.failureCategory) !== null && _c !== void 0 ? _c : (eventType === 'checkout_canceled' ? 'user_canceled' : undefined), 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 });
|
|
138
139
|
const eventId = publicAnalyticsSdk.track({
|
|
139
140
|
eventType,
|
|
140
141
|
environment: input.analytics.environment,
|
|
@@ -151,6 +152,7 @@ const emitCheckoutObservability = (eventType, input, failure) => {
|
|
|
151
152
|
void reportCheckoutObservability({
|
|
152
153
|
analytics: input.analytics,
|
|
153
154
|
checkoutSessionId: input.checkoutSessionId,
|
|
155
|
+
checkoutRequestId: failure === null || failure === void 0 ? void 0 : failure.checkoutRequestId,
|
|
154
156
|
errorCode: failure === null || failure === void 0 ? void 0 : failure.errorCode,
|
|
155
157
|
errorMessage: failure === null || failure === void 0 ? void 0 : failure.errorMessage,
|
|
156
158
|
failureCategory: (_d = failure === null || failure === void 0 ? void 0 : failure.failureCategory) !== null && _d !== void 0 ? _d : (eventType === 'checkout_canceled' ? 'user_canceled' : undefined),
|
|
@@ -184,6 +186,9 @@ export const trackCheckoutFailureShown = (input) => {
|
|
|
184
186
|
});
|
|
185
187
|
const paymentRejected = failureCategory === 'payment_rejection';
|
|
186
188
|
return emitCheckoutObservability(paymentRejected ? 'checkout_payment_rejected' : 'checkout_failure_shown', input, {
|
|
189
|
+
checkoutRequestId: input.checkoutRequestId
|
|
190
|
+
&& /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(input.checkoutRequestId)
|
|
191
|
+
? input.checkoutRequestId : undefined,
|
|
187
192
|
errorCode: paymentRejected
|
|
188
193
|
? providerDeclineCode || providerErrorCode || 'payment_rejected'
|
|
189
194
|
: resolveErrorCode(errorMessage, input.errorCode),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@funnelsgrove/payments",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/The-Solid-Grove/funnelsgrove.git",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"test:run": "vitest run --passWithNoTests"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@funnelsgrove/analytics": "^0.1.
|
|
36
|
-
"@funnelsgrove/runtime": "^0.13.
|
|
35
|
+
"@funnelsgrove/analytics": "^0.1.99",
|
|
36
|
+
"@funnelsgrove/runtime": "^0.13.1",
|
|
37
37
|
"@solidgate/react-sdk": "1.34.0",
|
|
38
38
|
"@stripe/react-stripe-js": "^5.6.0",
|
|
39
39
|
"@stripe/stripe-js": "^8.7.0",
|