@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.
- package/CHANGELOG.md +11 -0
- package/android/gradle.properties +1 -1
- package/android/src/main/java/com/reactnativestripesdk/PaymentSheetAppearance.kt +41 -10
- package/android/src/main/java/com/reactnativestripesdk/PaymentSheetFragment.kt +10 -3
- package/android/src/main/java/com/reactnativestripesdk/StripeSdkModule.kt +129 -82
- package/android/src/main/java/com/reactnativestripesdk/customersheet/CustomerSheetFragment.kt +329 -0
- package/android/src/main/java/com/reactnativestripesdk/customersheet/ReactNativeCustomerAdapter.kt +138 -0
- package/android/src/main/java/com/reactnativestripesdk/utils/Mappers.kt +8 -2
- package/ios/CustomerSheet/CustomerSheetUtils.swift +181 -0
- package/ios/CustomerSheet/ReactNativeCustomerAdapter.swift +173 -0
- package/ios/Mappers.swift +1 -1
- package/ios/StripeSdk+CustomerSheet.swift +166 -0
- package/ios/StripeSdk+PaymentSheet.swift +2 -2
- package/ios/StripeSdk.m +53 -0
- package/ios/StripeSdk.swift +14 -1
- package/jest/mock.js +0 -37
- package/lib/commonjs/NativeStripeSdk.js.map +1 -1
- package/lib/commonjs/components/CustomerSheet.js +2 -0
- package/lib/commonjs/components/CustomerSheet.js.map +1 -0
- package/lib/commonjs/functions.js +1 -1
- package/lib/commonjs/functions.js.map +1 -1
- package/lib/commonjs/index.js +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/types/CustomerSheet.js +2 -0
- package/lib/commonjs/types/CustomerSheet.js.map +1 -0
- package/lib/commonjs/types/Errors.js +1 -1
- package/lib/commonjs/types/Errors.js.map +1 -1
- package/lib/commonjs/types/index.js +1 -1
- package/lib/commonjs/types/index.js.map +1 -1
- package/lib/module/NativeStripeSdk.js.map +1 -1
- package/lib/module/components/CustomerSheet.js +2 -0
- package/lib/module/components/CustomerSheet.js.map +1 -0
- package/lib/module/functions.js +1 -1
- package/lib/module/functions.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/types/CustomerSheet.js +2 -0
- package/lib/module/types/CustomerSheet.js.map +1 -0
- package/lib/module/types/Errors.js +1 -1
- package/lib/module/types/Errors.js.map +1 -1
- package/lib/module/types/index.js +1 -1
- package/lib/module/types/index.js.map +1 -1
- package/lib/typescript/src/NativeStripeSdk.d.ts +14 -1
- package/lib/typescript/src/components/CustomerSheet.d.ts +59 -0
- package/lib/typescript/src/index.d.ts +2 -0
- package/lib/typescript/src/types/CustomerSheet.d.ts +94 -0
- package/lib/typescript/src/types/Errors.d.ts +4 -0
- package/lib/typescript/src/types/index.d.ts +1 -0
- package/package.json +1 -1
- package/src/NativeStripeSdk.tsx +31 -0
- package/src/components/CustomerSheet.tsx +327 -0
- package/src/functions.ts +5 -0
- package/src/index.tsx +3 -0
- package/src/types/CustomerSheet.ts +111 -0
- package/src/types/Errors.ts +5 -0
- package/src/types/index.ts +1 -0
- package/stripe-react-native.podspec +1 -1
- 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
package/src/NativeStripeSdk.tsx
CHANGED
|
@@ -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;
|
package/src/types/Errors.ts
CHANGED
package/src/types/index.ts
CHANGED
|
@@ -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.
|
|
5
|
+
stripe_version = '~> 23.15.0'
|
|
6
6
|
|
|
7
7
|
Pod::Spec.new do |s|
|
|
8
8
|
s.name = 'stripe-react-native'
|