@stripe/stripe-react-native 0.30.0 → 0.31.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.
Files changed (58) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/android/gradle.properties +1 -1
  3. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetAppearance.kt +41 -10
  4. package/android/src/main/java/com/reactnativestripesdk/PaymentSheetFragment.kt +10 -3
  5. package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +129 -82
  6. package/android/src/main/java/com/reactnativestripesdk/customersheet/CustomerSheetFragment.kt +329 -0
  7. package/android/src/main/java/com/reactnativestripesdk/customersheet/ReactNativeCustomerAdapter.kt +138 -0
  8. package/android/src/main/java/com/reactnativestripesdk/utils/Mappers.kt +8 -2
  9. package/ios/CustomerSheet/CustomerSheetUtils.swift +181 -0
  10. package/ios/CustomerSheet/ReactNativeCustomerAdapter.swift +173 -0
  11. package/ios/Mappers.swift +1 -1
  12. package/ios/StripeSdk+CustomerSheet.swift +166 -0
  13. package/ios/StripeSdk+PaymentSheet.swift +2 -2
  14. package/ios/StripeSdk.m +53 -0
  15. package/ios/StripeSdk.swift +14 -1
  16. package/jest/mock.js +0 -37
  17. package/lib/commonjs/NativeStripeSdk.js.map +1 -1
  18. package/lib/commonjs/components/CustomerSheet.js +2 -0
  19. package/lib/commonjs/components/CustomerSheet.js.map +1 -0
  20. package/lib/commonjs/functions.js +1 -1
  21. package/lib/commonjs/functions.js.map +1 -1
  22. package/lib/commonjs/index.js +1 -1
  23. package/lib/commonjs/index.js.map +1 -1
  24. package/lib/commonjs/types/CustomerSheet.js +2 -0
  25. package/lib/commonjs/types/CustomerSheet.js.map +1 -0
  26. package/lib/commonjs/types/Errors.js +1 -1
  27. package/lib/commonjs/types/Errors.js.map +1 -1
  28. package/lib/commonjs/types/index.js +1 -1
  29. package/lib/commonjs/types/index.js.map +1 -1
  30. package/lib/module/NativeStripeSdk.js.map +1 -1
  31. package/lib/module/components/CustomerSheet.js +2 -0
  32. package/lib/module/components/CustomerSheet.js.map +1 -0
  33. package/lib/module/functions.js +1 -1
  34. package/lib/module/functions.js.map +1 -1
  35. package/lib/module/index.js +1 -1
  36. package/lib/module/index.js.map +1 -1
  37. package/lib/module/types/CustomerSheet.js +2 -0
  38. package/lib/module/types/CustomerSheet.js.map +1 -0
  39. package/lib/module/types/Errors.js +1 -1
  40. package/lib/module/types/Errors.js.map +1 -1
  41. package/lib/module/types/index.js +1 -1
  42. package/lib/module/types/index.js.map +1 -1
  43. package/lib/typescript/src/NativeStripeSdk.d.ts +14 -1
  44. package/lib/typescript/src/components/CustomerSheet.d.ts +59 -0
  45. package/lib/typescript/src/index.d.ts +2 -0
  46. package/lib/typescript/src/types/CustomerSheet.d.ts +94 -0
  47. package/lib/typescript/src/types/Errors.d.ts +4 -0
  48. package/lib/typescript/src/types/index.d.ts +1 -0
  49. package/package.json +1 -1
  50. package/src/NativeStripeSdk.tsx +31 -0
  51. package/src/components/CustomerSheet.tsx +327 -0
  52. package/src/functions.ts +5 -0
  53. package/src/index.tsx +3 -0
  54. package/src/types/CustomerSheet.ts +111 -0
  55. package/src/types/Errors.ts +5 -0
  56. package/src/types/index.ts +1 -0
  57. package/stripe-react-native.podspec +1 -1
  58. package/android/src/main/java/com/reactnativestripesdk/GooglePayFragment.kt +0 -211
@@ -0,0 +1,94 @@
1
+ import type { PaymentSheet, StripeError, CustomerSheetError, BillingDetails, PaymentMethod } from '../types';
2
+ export declare type CustomerSheetInitParams = {
3
+ /** The color styling to use for PaymentSheet UI. Defaults to 'automatic'. iOS only. */
4
+ style?: 'alwaysLight' | 'alwaysDark' | 'automatic';
5
+ /** Configuration for the look and feel of the UI. */
6
+ appearance?: PaymentSheet.AppearanceParams;
7
+ /** Optional but recommended for cards, required for other payment methods. The SetupIntent client secret that will be used to confirm a new payment method. If this is missing, you will only be able to add cards without authentication steps. */
8
+ setupIntentClientSecret?: string;
9
+ /** The identifier of the Stripe Customer object. See https://stripe.com/docs/api/customers/object#customer_object-id */
10
+ customerId: string;
11
+ /** A short-lived token that allows the SDK to access a Customer's payment methods. */
12
+ customerEphemeralKeySecret: string;
13
+ /** Your customer-facing business name. The default value is the name of your app. */
14
+ merchantDisplayName?: string;
15
+ /** Optional configuration for setting the header text of the Payment Method selection screen */
16
+ headerTextForSelectionScreen?: string;
17
+ /** CustomerSheet pre-populates fields with the values provided. If `billingDetailsCollectionConfiguration.attachDefaultsToPaymentMethod` is `true`, these values will be attached to the payment method even if they are not collected by the CustomerSheet UI. */
18
+ defaultBillingDetails?: BillingDetails;
19
+ /** Describes how billing details should be collected. All values default to `AUTOMATIC`. If `NEVER` is used for a required field for the Payment Method, you must provide an appropriate value as part of `defaultBillingDetails`. */
20
+ billingDetailsCollectionConfiguration?: PaymentSheet.BillingDetailsCollectionConfiguration;
21
+ /** A URL that redirects back to your app that CustomerSheet can use to auto-dismiss web views used for additional authentication, e.g. 3DS2 */
22
+ returnURL?: string;
23
+ /** Optional configuration to display a custom message when a saved payment method is removed. iOS only. */
24
+ removeSavedPaymentMethodMessage?: string;
25
+ /** Whether to show Apple Pay as an option. Defaults to false. */
26
+ applePayEnabled?: boolean;
27
+ /** Whether to show Google Pay as an option. Defaults to false. */
28
+ googlePayEnabled?: boolean;
29
+ /** Optional override. It is generally recommended to rely on the default behavior, but- provide a CustomerAdapter here if
30
+ * you would prefer retrieving and updating your Stripe customer object via your own backend instead.
31
+ * WARNING: When implementing your own CustomerAdapter, ensure your application complies with all applicable laws and regulations, including data privacy and consumer protection.
32
+ */
33
+ customerAdapter?: CustomerAdapter;
34
+ };
35
+ export declare type CustomerSheetPresentParams = {
36
+ /** Controls how the modal is presented (after animation). iOS only. Defaults to `popover`. */
37
+ presentationStyle?: 'fullscreen' | 'popover';
38
+ /** Controls how the modal animates. iOS only. */
39
+ animationStyle?: 'flip' | 'curl' | 'slide' | 'dissolve';
40
+ /** Time (in milliseconds) before the Customer Sheet will automatically dismiss. */
41
+ timeout?: number;
42
+ };
43
+ export declare type CustomerSheetResult = {
44
+ /** The users selected payment option, if one exists. */
45
+ paymentOption?: PaymentSheet.PaymentOption;
46
+ /** The Stripe PaymentMethod associated with the paymentOption, if it exists. */
47
+ paymentMethod?: PaymentMethod.Result;
48
+ /** The error that occurred. */
49
+ error?: StripeError<CustomerSheetError>;
50
+ };
51
+ export interface CustomerAdapter {
52
+ /** Retrieves a list of Payment Methods attached to a customer.
53
+ * If you are implementing your own CustomerAdapter:
54
+ * Call the list method ( https://stripe.com/docs/api/payment_methods/list )
55
+ * with the Stripe customer. Return the list of payment methods in JSON format.
56
+ */
57
+ fetchPaymentMethods?(): Promise<Array<object>>;
58
+ /** Adds a Payment Method to a customer.
59
+ * If you are implementing your own CustomerAdapter:
60
+ * On your backend, retrieve the Stripe customer associated with your logged-in user.
61
+ * Then, call the Attach method on the Payment Method with that customer's ID
62
+ * ( https://stripe.com/docs/api/payment_methods/attach ).
63
+ * - Parameters:
64
+ * - paymentMethod: A valid Stripe Payment Method ID
65
+ * Return the payment method in JSON format.
66
+ */
67
+ attachPaymentMethod?(paymentMethodId: string): Promise<object>;
68
+ /** Deletes the given Payment Method from the customer.
69
+ * If you are implementing your own CustomerAdapter:
70
+ * Call the Detach method ( https://stripe.com/docs/api/payment_methods/detach )
71
+ * on the Payment Method.
72
+ * - Parameters:
73
+ * - paymentMethod: The Stripe Payment Method ID to delete from the customer
74
+ * Return the payment method in JSON format.
75
+ */
76
+ detachPaymentMethod?(paymentMethodId: String): Promise<object>;
77
+ /** Set the last selected payment method for the customer.
78
+ * To unset the default payment method, `null` is passed as the `paymentOption`.
79
+ * If you are implementing your own CustomerAdapter:
80
+ * Save a representation of the passed `paymentOption` as the customer's default payment method.
81
+ */
82
+ setSelectedPaymentOption?(paymentOption: CustomerPaymentOption | null): Promise<void>;
83
+ /** Retrieve the last selected payment method for the customer.
84
+ * If you are implementing your own CustomerAdapter:
85
+ * Return a CustomerPaymentOption for the customer's default selected payment method.
86
+ * If no default payment method is selected, return null.
87
+ */
88
+ fetchSelectedPaymentOption?(): Promise<CustomerPaymentOption | null>;
89
+ /** Creates a SetupIntent configured to attach a new payment method to a customer,
90
+ * then returns the client secret for the created SetupIntent.
91
+ */
92
+ setupIntentClientSecretForCustomerAttach?(): Promise<String>;
93
+ }
94
+ export declare type CustomerPaymentOption = 'apple_pay' | 'google_pay' | 'link' | string;
@@ -67,6 +67,10 @@ export declare enum AddressSheetError {
67
67
  Failed = "Failed",
68
68
  Canceled = "Canceled"
69
69
  }
70
+ export declare enum CustomerSheetError {
71
+ Failed = "Failed",
72
+ Canceled = "Canceled"
73
+ }
70
74
  export declare enum PlatformPayError {
71
75
  Canceled = "Canceled",
72
76
  Failed = "Failed",
@@ -14,6 +14,7 @@ import * as PlatformPay from './PlatformPay';
14
14
  export { ApplePay, PaymentIntent, PaymentMethod, PaymentSheet, SetupIntent, ThreeDSecure, AuBECSDebitFormComponent, CardFieldInput, CardFormView, Token, FinancialConnections, PlatformPay, };
15
15
  export * from './PushProvisioning';
16
16
  export * from './Errors';
17
+ export * from './CustomerSheet';
17
18
  export type { Address, BillingDetails, AddressDetails } from './Common';
18
19
  /**
19
20
  * @ignore
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stripe/stripe-react-native",
3
- "version": "0.30.0",
3
+ "version": "0.31.1",
4
4
  "author": "Stripe",
5
5
  "description": "Stripe SDK for React Native",
6
6
  "main": "lib/commonjs/index",
@@ -25,6 +25,13 @@ import type {
25
25
  CanAddCardToWalletParams,
26
26
  CanAddCardToWalletResult,
27
27
  FinancialConnections,
28
+ CustomerSheetInitParams,
29
+ CustomerSheetPresentParams,
30
+ CustomerSheetResult,
31
+ CustomerSheetError,
32
+ StripeError,
33
+ CustomerPaymentOption,
34
+ CustomerAdapter,
28
35
  } from './types';
29
36
 
30
37
  type NativeStripeSdkType = {
@@ -119,6 +126,30 @@ type NativeStripeSdkType = {
119
126
  webServiceUrl: string,
120
127
  authenticationToken: string
121
128
  ): Promise<void>;
129
+ initCustomerSheet(
130
+ params: CustomerSheetInitParams,
131
+ customerAdapterOverrides: { [Property in keyof CustomerAdapter]: boolean }
132
+ ): Promise<{ error?: StripeError<CustomerSheetError> }>;
133
+ presentCustomerSheet(
134
+ params: CustomerSheetPresentParams
135
+ ): Promise<CustomerSheetResult>;
136
+ retrieveCustomerSheetPaymentOptionSelection(): Promise<CustomerSheetResult>;
137
+ customerAdapterFetchPaymentMethodsCallback(
138
+ paymentMethods: Array<object>
139
+ ): Promise<void>;
140
+ customerAdapterAttachPaymentMethodCallback(
141
+ paymentMethod: object
142
+ ): Promise<void>;
143
+ customerAdapterDetachPaymentMethodCallback(
144
+ paymentMethod: object
145
+ ): Promise<void>;
146
+ customerAdapterSetSelectedPaymentOptionCallback(): Promise<void>;
147
+ customerAdapterFetchSelectedPaymentOptionCallback(
148
+ paymentOption: CustomerPaymentOption | null
149
+ ): Promise<void>;
150
+ customerAdapterSetupIntentClientSecretForCustomerAttachCallback(
151
+ clientSecret: String
152
+ ): Promise<void>;
122
153
  };
123
154
 
124
155
  const { StripeSdk } = NativeModules;
@@ -0,0 +1,327 @@
1
+ import React from 'react';
2
+ import {
3
+ NativeEventEmitter,
4
+ NativeModules,
5
+ EmitterSubscription,
6
+ } from 'react-native';
7
+ import NativeStripeSdk from '../NativeStripeSdk';
8
+ import type {
9
+ CustomerSheetInitParams,
10
+ CustomerSheetPresentParams,
11
+ CustomerSheetResult,
12
+ CustomerSheetError,
13
+ StripeError,
14
+ CustomerAdapter,
15
+ } from '../types';
16
+
17
+ const eventEmitter = new NativeEventEmitter(NativeModules.StripeSdk);
18
+ let fetchPaymentMethodsCallback: EmitterSubscription | null = null;
19
+ let attachPaymentMethodCallback: EmitterSubscription | null = null;
20
+ let detachPaymentMethodCallback: EmitterSubscription | null = null;
21
+ let setSelectedPaymentOptionCallback: EmitterSubscription | null = null;
22
+ let fetchSelectedPaymentOptionCallback: EmitterSubscription | null = null;
23
+ let setupIntentClientSecretForCustomerAttachCallback: EmitterSubscription | null =
24
+ null;
25
+
26
+ /** Initialize an instance of Customer Sheet with your desired configuration. */
27
+ const initialize = async (
28
+ params: CustomerSheetInitParams
29
+ ): Promise<{ error?: StripeError<CustomerSheetError> }> => {
30
+ let customerAdapterOverrides = {};
31
+ if (params.customerAdapter) {
32
+ customerAdapterOverrides = configureCustomerAdapterEventListeners(
33
+ params.customerAdapter
34
+ );
35
+ }
36
+
37
+ try {
38
+ const { error } = await NativeStripeSdk.initCustomerSheet(
39
+ params,
40
+ customerAdapterOverrides
41
+ );
42
+ if (error) {
43
+ return { error };
44
+ }
45
+ return {};
46
+ } catch (error: any) {
47
+ return {
48
+ error,
49
+ };
50
+ }
51
+ };
52
+
53
+ const configureCustomerAdapterEventListeners = (
54
+ customerAdapter: CustomerAdapter
55
+ ): { [Property in keyof CustomerAdapter]: boolean } => {
56
+ if (customerAdapter.fetchPaymentMethods) {
57
+ fetchPaymentMethodsCallback?.remove();
58
+ fetchPaymentMethodsCallback = eventEmitter.addListener(
59
+ 'onCustomerAdapterFetchPaymentMethodsCallback',
60
+ async () => {
61
+ if (customerAdapter.fetchPaymentMethods) {
62
+ const paymentMethods = await customerAdapter.fetchPaymentMethods();
63
+ await NativeStripeSdk.customerAdapterFetchPaymentMethodsCallback(
64
+ paymentMethods
65
+ );
66
+ } else {
67
+ throw new Error(
68
+ '[@stripe/stripe-react-native] Tried to call `fetchPaymentMethods` on your CustomerAdapter, but no matching method was found.'
69
+ );
70
+ }
71
+ }
72
+ );
73
+ }
74
+
75
+ if (customerAdapter.attachPaymentMethod) {
76
+ attachPaymentMethodCallback?.remove();
77
+ attachPaymentMethodCallback = eventEmitter.addListener(
78
+ 'onCustomerAdapterAttachPaymentMethodCallback',
79
+ async ({ paymentMethodId }: { paymentMethodId: string }) => {
80
+ if (customerAdapter.attachPaymentMethod) {
81
+ const paymentMethod = await customerAdapter.attachPaymentMethod(
82
+ paymentMethodId
83
+ );
84
+ await NativeStripeSdk.customerAdapterAttachPaymentMethodCallback(
85
+ paymentMethod
86
+ );
87
+ } else {
88
+ throw new Error(
89
+ '[@stripe/stripe-react-native] Tried to call `attachPaymentMethod` on your CustomerAdapter, but no matching method was found.'
90
+ );
91
+ }
92
+ }
93
+ );
94
+ }
95
+
96
+ if (customerAdapter.detachPaymentMethod) {
97
+ detachPaymentMethodCallback?.remove();
98
+ detachPaymentMethodCallback = eventEmitter.addListener(
99
+ 'onCustomerAdapterDetachPaymentMethodCallback',
100
+ async ({ paymentMethodId }: { paymentMethodId: string }) => {
101
+ if (customerAdapter.detachPaymentMethod) {
102
+ const paymentMethod = await customerAdapter.detachPaymentMethod(
103
+ paymentMethodId
104
+ );
105
+ await NativeStripeSdk.customerAdapterDetachPaymentMethodCallback(
106
+ paymentMethod
107
+ );
108
+ } else {
109
+ throw new Error(
110
+ '[@stripe/stripe-react-native] Tried to call `detachPaymentMethod` on your CustomerAdapter, but no matching method was found.'
111
+ );
112
+ }
113
+ }
114
+ );
115
+ }
116
+
117
+ if (customerAdapter.setSelectedPaymentOption) {
118
+ setSelectedPaymentOptionCallback?.remove();
119
+ setSelectedPaymentOptionCallback = eventEmitter.addListener(
120
+ 'onCustomerAdapterSetSelectedPaymentOptionCallback',
121
+ async ({ paymentOption }: { paymentOption: string }) => {
122
+ if (customerAdapter.setSelectedPaymentOption) {
123
+ await customerAdapter.setSelectedPaymentOption(paymentOption);
124
+ await NativeStripeSdk.customerAdapterSetSelectedPaymentOptionCallback();
125
+ } else {
126
+ throw new Error(
127
+ '[@stripe/stripe-react-native] Tried to call `setSelectedPaymentOption` on your CustomerAdapter, but no matching method was found.'
128
+ );
129
+ }
130
+ }
131
+ );
132
+ }
133
+
134
+ if (customerAdapter.fetchSelectedPaymentOption) {
135
+ fetchSelectedPaymentOptionCallback?.remove();
136
+ fetchSelectedPaymentOptionCallback = eventEmitter.addListener(
137
+ 'onCustomerAdapterFetchSelectedPaymentOptionCallback',
138
+ async () => {
139
+ if (customerAdapter.fetchSelectedPaymentOption) {
140
+ const paymentOption =
141
+ await customerAdapter.fetchSelectedPaymentOption();
142
+ await NativeStripeSdk.customerAdapterFetchSelectedPaymentOptionCallback(
143
+ paymentOption
144
+ );
145
+ } else {
146
+ throw new Error(
147
+ '[@stripe/stripe-react-native] Tried to call `fetchSelectedPaymentOption` on your CustomerAdapter, but no matching method was found.'
148
+ );
149
+ }
150
+ }
151
+ );
152
+ }
153
+
154
+ if (customerAdapter.setupIntentClientSecretForCustomerAttach) {
155
+ setupIntentClientSecretForCustomerAttachCallback?.remove();
156
+ setupIntentClientSecretForCustomerAttachCallback = eventEmitter.addListener(
157
+ 'onCustomerAdapterSetupIntentClientSecretForCustomerAttachCallback',
158
+ async () => {
159
+ if (customerAdapter.setupIntentClientSecretForCustomerAttach) {
160
+ const clientSecret =
161
+ await customerAdapter.setupIntentClientSecretForCustomerAttach();
162
+ await NativeStripeSdk.customerAdapterSetupIntentClientSecretForCustomerAttachCallback(
163
+ clientSecret
164
+ );
165
+ } else {
166
+ throw new Error(
167
+ '[@stripe/stripe-react-native] Tried to call `setupIntentClientSecretForCustomerAttach` on your CustomerAdapter, but no matching method was found.'
168
+ );
169
+ }
170
+ }
171
+ );
172
+ }
173
+
174
+ return {
175
+ fetchPaymentMethods: !!customerAdapter.fetchPaymentMethods,
176
+ attachPaymentMethod: !!customerAdapter.attachPaymentMethod,
177
+ detachPaymentMethod: !!customerAdapter.detachPaymentMethod,
178
+ setSelectedPaymentOption: !!customerAdapter.setSelectedPaymentOption,
179
+ fetchSelectedPaymentOption: !!customerAdapter.fetchSelectedPaymentOption,
180
+ setupIntentClientSecretForCustomerAttach:
181
+ !!customerAdapter.setupIntentClientSecretForCustomerAttach,
182
+ };
183
+ };
184
+
185
+ /** Launches the Customer Sheet UI. */
186
+ const present = async (
187
+ params: CustomerSheetPresentParams = {}
188
+ ): Promise<CustomerSheetResult> => {
189
+ try {
190
+ return await NativeStripeSdk.presentCustomerSheet(params);
191
+ } catch (error: any) {
192
+ return {
193
+ error,
194
+ };
195
+ }
196
+ };
197
+
198
+ /**
199
+ * You can use this to obtain the selected payment method without presenting the CustomerSheet.
200
+ * This will return an error if you have not called `.initialize`
201
+ */
202
+ const retrievePaymentOptionSelection =
203
+ async (): Promise<CustomerSheetResult> => {
204
+ try {
205
+ return await NativeStripeSdk.retrieveCustomerSheetPaymentOptionSelection();
206
+ } catch (error: any) {
207
+ return {
208
+ error,
209
+ };
210
+ }
211
+ };
212
+
213
+ /**
214
+ * Props
215
+ */
216
+ export type Props = {
217
+ /** Whether the sheet is visible. Defaults to false. */
218
+ visible: boolean;
219
+ /** Called when the user submits, dismisses, or cancels the sheet, or when an error occurs. */
220
+ onResult: (result: CustomerSheetResult) => void;
221
+ } & CustomerSheetInitParams &
222
+ CustomerSheetPresentParams;
223
+
224
+ /**
225
+ * A component wrapper around the Customer Sheet functions. Upon passing `true` to the `visible` prop,
226
+ * Customer Sheet will call `initialize` and `present`, and the result(s) will be passed through to the
227
+ * onResult callback.
228
+ *
229
+ * @example
230
+ * ```ts
231
+ * const [selectedPaymentOption, setSelectedPaymentOption] = React.useState(null);
232
+ * const [customerSheetVisible, setCustomerSheetVisible] = React.useState(false);
233
+ *
234
+ * return (
235
+ * <CustomerSheet
236
+ * visible={customerSheetVisible}
237
+ * customerEphemeralKeySecret={ephemeralKeySecret}
238
+ * customerId={customer}
239
+ * returnURL={'stripe-example://stripe-redirect'}
240
+ * onResult={({ error, paymentOption, paymentMethod }) => {
241
+ * setCustomerSheetVisible(false);
242
+ * if (error) {
243
+ * Alert.alert(error.code, error.localizedMessage);
244
+ * }
245
+ * if (paymentOption) {
246
+ * setSelectedPaymentOption(paymentOption);
247
+ * console.log(JSON.stringify(paymentOption, null, 2));
248
+ * }
249
+ * if (paymentMethod) {
250
+ * console.log(JSON.stringify(paymentMethod, null, 2));
251
+ * }
252
+ * }}
253
+ * />
254
+ * );
255
+ * ```
256
+ * @param __namedParameters Props
257
+ * @returns JSX.Element
258
+ * @category ReactComponents
259
+ */
260
+ function CustomerSheet({
261
+ visible,
262
+ presentationStyle,
263
+ animationStyle,
264
+ style,
265
+ appearance,
266
+ setupIntentClientSecret,
267
+ customerId,
268
+ customerEphemeralKeySecret,
269
+ merchantDisplayName,
270
+ headerTextForSelectionScreen,
271
+ defaultBillingDetails,
272
+ billingDetailsCollectionConfiguration,
273
+ returnURL,
274
+ removeSavedPaymentMethodMessage,
275
+ applePayEnabled,
276
+ googlePayEnabled,
277
+ timeout,
278
+ onResult,
279
+ customerAdapter,
280
+ }: Props) {
281
+ React.useEffect(() => {
282
+ if (visible) {
283
+ initialize({
284
+ style,
285
+ appearance,
286
+ setupIntentClientSecret,
287
+ customerId,
288
+ customerEphemeralKeySecret,
289
+ merchantDisplayName,
290
+ headerTextForSelectionScreen,
291
+ defaultBillingDetails,
292
+ billingDetailsCollectionConfiguration,
293
+ returnURL,
294
+ removeSavedPaymentMethodMessage,
295
+ applePayEnabled,
296
+ googlePayEnabled,
297
+ customerAdapter,
298
+ }).then((initResult) => {
299
+ if (initResult.error) {
300
+ onResult(initResult);
301
+ } else {
302
+ present({
303
+ timeout,
304
+ presentationStyle,
305
+ animationStyle,
306
+ }).then((presentResult) => {
307
+ onResult(presentResult);
308
+ });
309
+ }
310
+ });
311
+ }
312
+ // Only run this hook when visible prop changes
313
+ // eslint-disable-next-line react-hooks/exhaustive-deps
314
+ }, [visible]);
315
+
316
+ return null;
317
+ }
318
+
319
+ /**
320
+ * The Customer Sheet is a prebuilt UI component that lets your customers manage their saved payment methods.
321
+ */
322
+ export const CustomerSheetBeta = {
323
+ CustomerSheet,
324
+ initialize,
325
+ present,
326
+ retrievePaymentOptionSelection,
327
+ };
package/src/functions.ts CHANGED
@@ -394,6 +394,11 @@ export const initPaymentSheet = async (
394
394
  }
395
395
 
396
396
  try {
397
+ if (Platform.OS === 'ios' && !params.returnURL) {
398
+ console.warn(
399
+ `[@stripe/stripe-react-native] You have not provided the 'returnURL' field to 'initPaymentSheet', so payment methods that require redirects will not be shown in your iOS Payment Sheet. Visit https://stripe.com/docs/payments/accept-a-payment?platform=react-native&ui=payment-sheet#react-native-set-up-return-url to learn more.`
400
+ );
401
+ }
397
402
  result = await NativeStripeSdk.initPaymentSheet(params);
398
403
 
399
404
  if (result.error) {
package/src/index.tsx CHANGED
@@ -27,3 +27,6 @@ export type { Props as PlatformPayButtonProps } from './components/PlatformPayBu
27
27
  export * from './functions';
28
28
 
29
29
  export * from './types/index';
30
+
31
+ export * from './components/CustomerSheet';
32
+ export type { Props as CustomerSheetProps } from './components/CustomerSheet';
@@ -0,0 +1,111 @@
1
+ import type {
2
+ PaymentSheet,
3
+ StripeError,
4
+ CustomerSheetError,
5
+ BillingDetails,
6
+ PaymentMethod,
7
+ } from '../types';
8
+
9
+ export type CustomerSheetInitParams = {
10
+ /** The color styling to use for PaymentSheet UI. Defaults to 'automatic'. iOS only. */
11
+ style?: 'alwaysLight' | 'alwaysDark' | 'automatic';
12
+ /** Configuration for the look and feel of the UI. */
13
+ appearance?: PaymentSheet.AppearanceParams;
14
+ /** Optional but recommended for cards, required for other payment methods. The SetupIntent client secret that will be used to confirm a new payment method. If this is missing, you will only be able to add cards without authentication steps. */
15
+ setupIntentClientSecret?: string;
16
+ /** The identifier of the Stripe Customer object. See https://stripe.com/docs/api/customers/object#customer_object-id */
17
+ customerId: string;
18
+ /** A short-lived token that allows the SDK to access a Customer's payment methods. */
19
+ customerEphemeralKeySecret: string;
20
+ /** Your customer-facing business name. The default value is the name of your app. */
21
+ merchantDisplayName?: string;
22
+ /** Optional configuration for setting the header text of the Payment Method selection screen */
23
+ headerTextForSelectionScreen?: string;
24
+ /** CustomerSheet pre-populates fields with the values provided. If `billingDetailsCollectionConfiguration.attachDefaultsToPaymentMethod` is `true`, these values will be attached to the payment method even if they are not collected by the CustomerSheet UI. */
25
+ defaultBillingDetails?: BillingDetails;
26
+ /** Describes how billing details should be collected. All values default to `AUTOMATIC`. If `NEVER` is used for a required field for the Payment Method, you must provide an appropriate value as part of `defaultBillingDetails`. */
27
+ billingDetailsCollectionConfiguration?: PaymentSheet.BillingDetailsCollectionConfiguration;
28
+ /** A URL that redirects back to your app that CustomerSheet can use to auto-dismiss web views used for additional authentication, e.g. 3DS2 */
29
+ returnURL?: string;
30
+ /** Optional configuration to display a custom message when a saved payment method is removed. iOS only. */
31
+ removeSavedPaymentMethodMessage?: string;
32
+ /** Whether to show Apple Pay as an option. Defaults to false. */
33
+ applePayEnabled?: boolean;
34
+ /** Whether to show Google Pay as an option. Defaults to false. */
35
+ googlePayEnabled?: boolean;
36
+ /** Optional override. It is generally recommended to rely on the default behavior, but- provide a CustomerAdapter here if
37
+ * you would prefer retrieving and updating your Stripe customer object via your own backend instead.
38
+ * WARNING: When implementing your own CustomerAdapter, ensure your application complies with all applicable laws and regulations, including data privacy and consumer protection.
39
+ */
40
+ customerAdapter?: CustomerAdapter;
41
+ };
42
+
43
+ export type CustomerSheetPresentParams = {
44
+ /** Controls how the modal is presented (after animation). iOS only. Defaults to `popover`. */
45
+ presentationStyle?: 'fullscreen' | 'popover';
46
+ /** Controls how the modal animates. iOS only. */
47
+ animationStyle?: 'flip' | 'curl' | 'slide' | 'dissolve';
48
+ /** Time (in milliseconds) before the Customer Sheet will automatically dismiss. */
49
+ timeout?: number;
50
+ };
51
+
52
+ export type CustomerSheetResult = {
53
+ /** The users selected payment option, if one exists. */
54
+ paymentOption?: PaymentSheet.PaymentOption;
55
+ /** The Stripe PaymentMethod associated with the paymentOption, if it exists. */
56
+ paymentMethod?: PaymentMethod.Result;
57
+ /** The error that occurred. */
58
+ error?: StripeError<CustomerSheetError>;
59
+ };
60
+
61
+ export interface CustomerAdapter {
62
+ /** Retrieves a list of Payment Methods attached to a customer.
63
+ * If you are implementing your own CustomerAdapter:
64
+ * Call the list method ( https://stripe.com/docs/api/payment_methods/list )
65
+ * with the Stripe customer. Return the list of payment methods in JSON format.
66
+ */
67
+ fetchPaymentMethods?(): Promise<Array<object>>;
68
+ /** Adds a Payment Method to a customer.
69
+ * If you are implementing your own CustomerAdapter:
70
+ * On your backend, retrieve the Stripe customer associated with your logged-in user.
71
+ * Then, call the Attach method on the Payment Method with that customer's ID
72
+ * ( https://stripe.com/docs/api/payment_methods/attach ).
73
+ * - Parameters:
74
+ * - paymentMethod: A valid Stripe Payment Method ID
75
+ * Return the payment method in JSON format.
76
+ */
77
+ attachPaymentMethod?(paymentMethodId: string): Promise<object>;
78
+ /** Deletes the given Payment Method from the customer.
79
+ * If you are implementing your own CustomerAdapter:
80
+ * Call the Detach method ( https://stripe.com/docs/api/payment_methods/detach )
81
+ * on the Payment Method.
82
+ * - Parameters:
83
+ * - paymentMethod: The Stripe Payment Method ID to delete from the customer
84
+ * Return the payment method in JSON format.
85
+ */
86
+ detachPaymentMethod?(paymentMethodId: String): Promise<object>;
87
+ /** Set the last selected payment method for the customer.
88
+ * To unset the default payment method, `null` is passed as the `paymentOption`.
89
+ * If you are implementing your own CustomerAdapter:
90
+ * Save a representation of the passed `paymentOption` as the customer's default payment method.
91
+ */
92
+ setSelectedPaymentOption?(
93
+ paymentOption: CustomerPaymentOption | null
94
+ ): Promise<void>;
95
+ /** Retrieve the last selected payment method for the customer.
96
+ * If you are implementing your own CustomerAdapter:
97
+ * Return a CustomerPaymentOption for the customer's default selected payment method.
98
+ * If no default payment method is selected, return null.
99
+ */
100
+ fetchSelectedPaymentOption?(): Promise<CustomerPaymentOption | null>;
101
+ /** Creates a SetupIntent configured to attach a new payment method to a customer,
102
+ * then returns the client secret for the created SetupIntent.
103
+ */
104
+ setupIntentClientSecretForCustomerAttach?(): Promise<String>;
105
+ }
106
+
107
+ export type CustomerPaymentOption =
108
+ | 'apple_pay'
109
+ | 'google_pay'
110
+ | 'link'
111
+ | string;
@@ -91,6 +91,11 @@ export enum AddressSheetError {
91
91
  Canceled = 'Canceled',
92
92
  }
93
93
 
94
+ export enum CustomerSheetError {
95
+ Failed = 'Failed',
96
+ Canceled = 'Canceled',
97
+ }
98
+
94
99
  export enum PlatformPayError {
95
100
  Canceled = 'Canceled',
96
101
  Failed = 'Failed',
@@ -43,6 +43,7 @@ export {
43
43
 
44
44
  export * from './PushProvisioning';
45
45
  export * from './Errors';
46
+ export * from './CustomerSheet';
46
47
  export type { Address, BillingDetails, AddressDetails } from './Common';
47
48
 
48
49
  /**
@@ -2,7 +2,7 @@ require 'json'
2
2
 
3
3
  package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
4
  # Keep stripe_version in sync with https://github.com/stripe/stripe-identity-react-native/blob/main/stripe-identity-react-native.podspec
5
- stripe_version = '~> 23.12.0'
5
+ stripe_version = '~> 23.15.0'
6
6
 
7
7
  Pod::Spec.new do |s|
8
8
  s.name = 'stripe-react-native'