tf-checkout-react 1.7.32-beta.0 → 1.7.32-beta.3

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/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.7.32-beta.0",
2
+ "version": "1.7.32-beta.3",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -1,8 +1,16 @@
1
1
  import { FormikHelpers } from 'formik'
2
+ import _get from 'lodash/get'
2
3
  import _identity from 'lodash/identity'
3
4
 
4
5
  import { handlePaymentMiddleWare } from '../../paymentContainer/handlePayment'
5
6
 
7
+ const SUCCESSFUL_INTENT_STATUSES = ['succeeded', 'processing', 'requires_capture']
8
+ const PAYMENT_FAILED_MESSAGE =
9
+ 'Your payment was not completed. Please try again or use another payment method.'
10
+ const PAYMENT_RECEIVED_MESSAGE =
11
+ 'Your payment was received and we are confirming your order. ' +
12
+ 'Please check your email for your tickets before trying again.'
13
+
6
14
  interface PaymentData {
7
15
  attributes: any
8
16
  isFreeTickets: boolean
@@ -74,43 +82,70 @@ export const useStripePayment = ({
74
82
  billing_details: { phone: e164Phone },
75
83
  }
76
84
  }
77
- const { error: confirmError } = await stripeRef.current.confirmPayment({
78
- clientSecret:
79
- paymentDataResponse.data.attributes.payment_method.stripe_client_secret,
80
- elements: elementsRef.current,
81
- confirmParams,
82
- redirect: 'if_required',
83
- })
85
+ let confirmResult
86
+ try {
87
+ confirmResult = await stripeRef.current.confirmPayment({
88
+ clientSecret:
89
+ paymentDataResponse.data.attributes.payment_method.stripe_client_secret,
90
+ elements: elementsRef.current,
91
+ confirmParams,
92
+ redirect: 'if_required',
93
+ })
94
+ } catch (e) {
95
+ // Stripe.js throws (instead of returning { error }) on integration errors
96
+ setError(_get(e, 'message') || PAYMENT_FAILED_MESSAGE)
97
+ return null
98
+ }
84
99
 
100
+ const { error: confirmError, paymentIntent } = confirmResult
85
101
  if (confirmError) {
86
102
  setError('' + confirmError?.message)
87
103
  return null
88
104
  }
105
+
106
+ // Asynchronous failures (e.g. MB WAY declined, expired or number not registered)
107
+ // resolve without `error`, so the PaymentIntent status must be checked
108
+ if (paymentIntent && !SUCCESSFUL_INTENT_STATUSES.includes(paymentIntent.status)) {
109
+ setError(
110
+ _get(paymentIntent, 'last_payment_error.message') || PAYMENT_FAILED_MESSAGE
111
+ )
112
+ return null
113
+ }
89
114
  }
90
115
 
91
116
  // Handle payment middleware for non-redirect payments
92
117
  let paymentResponse = null
93
- await handlePaymentMiddleWare(
94
- null,
95
- {},
96
- {
97
- reviewData: attributes,
98
- isFreeTickets,
99
- paymentPlanIsAvailable: false,
100
- showPaymentPlanSection: false,
101
- handlePayment: (data: any) => {
102
- paymentResponse = data
103
- },
104
- setPaymentIsLoading: _identity,
105
- setError: _identity,
106
- orderData: updatedOrderData,
107
- eventId,
108
- isBrowser,
109
- onPaymentError: (error: any) => {
110
- throw error
111
- },
112
- }
113
- )
118
+ try {
119
+ await handlePaymentMiddleWare(
120
+ null,
121
+ {},
122
+ {
123
+ reviewData: attributes,
124
+ isFreeTickets,
125
+ paymentPlanIsAvailable: false,
126
+ showPaymentPlanSection: false,
127
+ handlePayment: (data: any) => {
128
+ paymentResponse = data
129
+ },
130
+ setPaymentIsLoading: _identity,
131
+ setError: (message: string | null) => {
132
+ if (message && isFreeTickets) setError(message)
133
+ },
134
+ orderData: updatedOrderData,
135
+ eventId,
136
+ isBrowser,
137
+ onPaymentError: (error: any) => {
138
+ throw error
139
+ },
140
+ }
141
+ )
142
+ } catch (e) {
143
+ if (isFreeTickets) throw e
144
+ // Stripe has already taken the payment and the webhook will still settle the order,
145
+ // so never invite a retry (double charge) whatever the backend error looks like
146
+ setError(PAYMENT_RECEIVED_MESSAGE)
147
+ return null
148
+ }
114
149
 
115
150
  return paymentResponse
116
151
  }
@@ -796,6 +796,13 @@ const BillingInfoContainer = React.memo(
796
796
  if (!_isEmpty(holderDataCapture)) {
797
797
  holder.ticket_data_capture = holderDataCapture
798
798
  }
799
+
800
+ // on-checkout only skips required fields scoped to other ticket types when the
801
+ // holder carries its ticket type; without it every ticket field is required.
802
+ const holderTicketTypeId = holderTicketTypeIds[+holderIndex]
803
+ if (holderTicketTypeId) {
804
+ holder.ticket_type_id = holderTicketTypeId
805
+ }
799
806
  })
800
807
 
801
808
  // Collect add_on_data_capture for Add-on Custom Fields