Skip to content

Commit

Permalink
Add Customer Session to example
Browse files Browse the repository at this point in the history
  • Loading branch information
tjclawson-stripe committed Oct 4, 2024
1 parent 8aca8f7 commit 3a3dbfd
Show file tree
Hide file tree
Showing 11 changed files with 415 additions and 219 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,9 @@ class PaymentSheetFragment(
return if (customerSessionClientSecret.isNotEmpty() && customerEphemeralKeySecret.isNotEmpty()) {
throw PaymentSheetException("`customerEphemeralKeySecret` and `customerSessionClientSecret` cannot both be set")
} else if (customerId.isNotEmpty() && customerSessionClientSecret.isNotEmpty()) {
println("YEET creating customer configuration")
println("YEET customerID: $customerId")
println("YEET customerSessionClientSecret: $customerSessionClientSecret")
PaymentSheet.CustomerConfiguration.createWithCustomerSession(
id = customerId,
clientSecret = customerSessionClientSecret
Expand Down
104 changes: 52 additions & 52 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -299,50 +299,50 @@ PODS:
- RNScreens (3.29.0):
- React-Core
- React-RCTImage
- Stripe (23.28.1):
- StripeApplePay (= 23.28.1)
- StripeCore (= 23.28.1)
- StripePayments (= 23.28.1)
- StripePaymentsUI (= 23.28.1)
- StripeUICore (= 23.28.1)
- stripe-react-native (0.38.4):
- Stripe (23.30.0):
- StripeApplePay (= 23.30.0)
- StripeCore (= 23.30.0)
- StripePayments (= 23.30.0)
- StripePaymentsUI (= 23.30.0)
- StripeUICore (= 23.30.0)
- stripe-react-native (0.38.6):
- React-Core
- Stripe (~> 23.28.0)
- StripeApplePay (~> 23.28.0)
- StripeFinancialConnections (~> 23.28.0)
- StripePayments (~> 23.28.0)
- StripePaymentSheet (~> 23.28.0)
- StripePaymentsUI (~> 23.28.0)
- stripe-react-native/Tests (0.38.4):
- Stripe (~> 23.30.0)
- StripeApplePay (~> 23.30.0)
- StripeFinancialConnections (~> 23.30.0)
- StripePayments (~> 23.30.0)
- StripePaymentSheet (~> 23.30.0)
- StripePaymentsUI (~> 23.30.0)
- stripe-react-native/Tests (0.38.6):
- React-Core
- Stripe (~> 23.28.0)
- StripeApplePay (~> 23.28.0)
- StripeFinancialConnections (~> 23.28.0)
- StripePayments (~> 23.28.0)
- StripePaymentSheet (~> 23.28.0)
- StripePaymentsUI (~> 23.28.0)
- StripeApplePay (23.28.1):
- StripeCore (= 23.28.1)
- StripeCore (23.28.1)
- StripeFinancialConnections (23.28.1):
- StripeCore (= 23.28.1)
- StripeUICore (= 23.28.1)
- StripePayments (23.28.1):
- StripeCore (= 23.28.1)
- StripePayments/Stripe3DS2 (= 23.28.1)
- StripePayments/Stripe3DS2 (23.28.1):
- StripeCore (= 23.28.1)
- StripePaymentSheet (23.28.1):
- StripeApplePay (= 23.28.1)
- StripeCore (= 23.28.1)
- StripePayments (= 23.28.1)
- StripePaymentsUI (= 23.28.1)
- StripePaymentsUI (23.28.1):
- StripeCore (= 23.28.1)
- StripePayments (= 23.28.1)
- StripeUICore (= 23.28.1)
- StripeUICore (23.28.1):
- StripeCore (= 23.28.1)
- Stripe (~> 23.30.0)
- StripeApplePay (~> 23.30.0)
- StripeFinancialConnections (~> 23.30.0)
- StripePayments (~> 23.30.0)
- StripePaymentSheet (~> 23.30.0)
- StripePaymentsUI (~> 23.30.0)
- StripeApplePay (23.30.0):
- StripeCore (= 23.30.0)
- StripeCore (23.30.0)
- StripeFinancialConnections (23.30.0):
- StripeCore (= 23.30.0)
- StripeUICore (= 23.30.0)
- StripePayments (23.30.0):
- StripeCore (= 23.30.0)
- StripePayments/Stripe3DS2 (= 23.30.0)
- StripePayments/Stripe3DS2 (23.30.0):
- StripeCore (= 23.30.0)
- StripePaymentSheet (23.30.0):
- StripeApplePay (= 23.30.0)
- StripeCore (= 23.30.0)
- StripePayments (= 23.30.0)
- StripePaymentsUI (= 23.30.0)
- StripePaymentsUI (23.30.0):
- StripeCore (= 23.30.0)
- StripePayments (= 23.30.0)
- StripeUICore (= 23.30.0)
- StripeUICore (23.30.0):
- StripeCore (= 23.30.0)
- Yoga (1.14.0)

DEPENDENCIES:
Expand Down Expand Up @@ -511,17 +511,17 @@ SPEC CHECKSUMS:
RNCMaskedView: bc0170f389056201c82a55e242e5d90070e18e5a
RNCPicker: 0bf8ef8f7800524f32d2bb2a8bcadd53eda0ecd1
RNScreens: fa9b582d85ae5d62c91c66003b5278458fed7aaa
Stripe: 20e24971647daa5750e7764faa1e8aefe4917243
stripe-react-native: 3479d62b758ac162b4465cb0aed313b525a575f3
StripeApplePay: 5b098a0ba6136f4b587e03f5a3776461b4f20dd4
StripeCore: 880a68482cf78d4745c5213c2fd3446efc73574b
StripeFinancialConnections: 49a19ca17dbb3055a8b559a1e3adfe769784a8f8
StripePayments: 3af5b03fa1831c301a4d1621eb0e790280dccb46
StripePaymentSheet: 8321efebb6d104add8fce929286d414545913114
StripePaymentsUI: 4c35e12ebcd4bd9bd21e379f03f730bee097250d
StripeUICore: 22b314dc9f7ea8814d0f9eeba0ddb5e4b77f34f3
Stripe: 9757efc154de1d9615cbea4836d590bc4034d3a4
stripe-react-native: 99b3cc2fae5a53f0ab1d9949ff19ae2aaba73641
StripeApplePay: ca33933601302742623762157d587b79b942d073
StripeCore: 2af250a2366ff2bbf64d4243c5f9bbf2a98b2aaf
StripeFinancialConnections: 3ab1ef6182ec44e71c29e9a2100b663f9713ac20
StripePayments: 658a16bd34d20c8185aa281866227b9e1743300e
StripePaymentSheet: eac031f76d7fbb4f52df9b9c39be5be671ca4c07
StripePaymentsUI: 7d7cffb2ecfc0d6b5ac3a4488c02893a5ff6cc77
StripeUICore: bb102d453b1e1a10a37f810bc0a9aa0675fb17fd
Yoga: 8a90b50af67eaa9fe94fd03e550bfeab06096873

PODFILE CHECKSUM: 7b4a5e954edfeed0967520f79be9e773f07d8266

COCOAPODS: 1.11.3
COCOAPODS: 1.15.2
17 changes: 3 additions & 14 deletions example/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -541,16 +541,6 @@ app.post('/payment-sheet', async (req, res) => {
customer_key_type?: string;
} = req.body;

if (
customer_key_type !== 'legacy_ephemeral_key' &&
customer_key_type !== 'customer_session'
) {
return res.send({
error:
'`customer_key_type` is not valid! Please pass either "customer_session" or "legacy_ephemeral_key"',
});
}

const { secret_key } = getKeys();

const stripe = new Stripe(secret_key as string, {
Expand Down Expand Up @@ -701,10 +691,9 @@ app.post('/payment-sheet-subscription', async (req, res) => {
mobile_payment_element: {
enabled: true,
features: {
payment_method_save: true,
payment_method_remove: true,
payment_method_redisplay: true,
payment_method_save_allow_redisplay_override: true,
payment_method_save: 'enabled',
payment_method_remove: 'enabled',
payment_method_redisplay: 'enabled',
payment_method_allow_redisplay_filters: [
'unspecified',
'limited',
Expand Down
39 changes: 39 additions & 0 deletions example/src/components/CustomerSessionSwitch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import {
View,
Text,
Switch,
ViewStyle,
TextStyle,
StyleProp,
} from 'react-native';

interface CustomerSessionSwitchProps {
value: boolean; // Switch value
onValueChange: (value: boolean) => void;
}

const SWITCH_CONTAINER_STYLE: StyleProp<ViewStyle> = {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
};

const SWITCH_TITLE_STYLE: StyleProp<TextStyle> = {
marginEnd: 10,
textAlignVertical: 'center',
};

const CustomerSessionSwitch: React.FC<CustomerSessionSwitchProps> = ({
value,
onValueChange,
}) => {
return (
<View style={SWITCH_CONTAINER_STYLE}>
<Text style={SWITCH_TITLE_STYLE}>Enable Customer Session</Text>
<Switch onValueChange={onValueChange} value={value} />
</View>
);
};

export default CustomerSessionSwitch;
12 changes: 12 additions & 0 deletions example/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,15 @@ export async function fetchPublishableKey(
return null;
}
}

export function getClientSecretParams(
customerKeyType: string,
remainingParams: any
): any {
return customerKeyType === 'customer_session'
? {
customerSessionClientSecret:
remainingParams.customerSessionClientSecret,
}
: { customerEphemeralKeySecret: remainingParams.ephemeralKey };
}
59 changes: 51 additions & 8 deletions example/src/screens/PaymentSheetDeferredIntentMultiStepScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import { Alert, StyleSheet, View } from 'react-native';
import {
useStripe,
Expand All @@ -11,6 +11,8 @@ import { colors } from '../colors';
import Button from '../components/Button';
import PaymentScreen from '../components/PaymentScreen';
import { API_URL } from '../Config';
import CustomerSessionSwitch from '../components/CustomerSessionSwitch';
import { getClientSecretParams } from '../helpers';

export default function PaymentSheetDeferredIntentMultiStepScreen() {
const { initPaymentSheet, presentPaymentSheet, confirmPaymentSheetPayment } =
Expand All @@ -22,25 +24,48 @@ export default function PaymentSheetDeferredIntentMultiStepScreen() {
label: string;
} | null>(null);

const fetchPaymentSheetParams = async () => {
const [customerKeyType, setCustomerKeyType] = useState<string>(
'legacy_ephemeral_key'
);

const fetchPaymentSheetParams = async (customer_key_type: string) => {
const response = await fetch(`${API_URL}/payment-sheet`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
customer_key_type,
}),
});
const { customer } = await response.json();

return {
customer,
};
if (customer_key_type === 'customer_session') {
const { customerSessionClientSecret, customer } = await response.json();
return {
customerSessionClientSecret,
customer,
};
} else {
const { ephemeralKey, customer } = await response.json();
return {
ephemeralKey,
customer,
};
}
};

const initialisePaymentSheet = async () => {
const initialisePaymentSheet = useCallback(async () => {
setLoading(true);

try {
const { customer } = await fetchPaymentSheetParams();
const { customer, ...remainingParams } = await fetchPaymentSheetParams(
customerKeyType
);

const clientSecretParams = getClientSecretParams(
customerKeyType,
remainingParams
);

const address: Address = {
city: 'San Francisco',
Expand All @@ -63,6 +88,7 @@ export default function PaymentSheetDeferredIntentMultiStepScreen() {
style: 'automatic',
returnURL: 'stripe-example://stripe-redirect',
defaultBillingDetails: billingDetails,
...clientSecretParams,
intentConfiguration: {
confirmHandler: async (
paymentMethod: PaymentMethod.Result,
Expand Down Expand Up @@ -120,8 +146,21 @@ export default function PaymentSheetDeferredIntentMultiStepScreen() {
} finally {
setLoading(false);
}
}, [customerKeyType, initPaymentSheet]);

const toggleCustomerKeyType = (value: boolean) => {
if (value) {
setCustomerKeyType('customer_session');
} else {
setCustomerKeyType('legacy_ephemeral_key');
}
};

useEffect(() => {
setPaymentSheetEnabled(false);
initialisePaymentSheet().catch((err) => console.log(err));
}, [customerKeyType, initialisePaymentSheet]);

const choosePaymentOption = async () => {
const { error, paymentOption } = await presentPaymentSheet();

Expand Down Expand Up @@ -154,6 +193,10 @@ export default function PaymentSheetDeferredIntentMultiStepScreen() {
// In your app’s checkout, make a network request to the backend and initialize PaymentSheet.
// To reduce loading time, make this request before the Checkout button is tapped, e.g. when the screen is loaded.
<PaymentScreen onInit={initialisePaymentSheet}>
<CustomerSessionSwitch
value={customerKeyType === 'customer_session'}
onValueChange={toggleCustomerKeyType}
/>
<Button
variant="primary"
loading={loading}
Expand Down
Loading

0 comments on commit 3a3dbfd

Please sign in to comment.