Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse 'customerSheetClientSecret' for Android and iOS #1744

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion android/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
StripeSdk_kotlinVersion=1.8.0
# Keep StripeSdk_stripeVersion in sync with https://github.com/stripe/stripe-identity-react-native/blob/main/android/gradle.properties
StripeSdk_stripeVersion=20.48.+
StripeSdk_stripeVersion=20.49.+
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ class PaymentSheetFragment(
return
}
val primaryButtonLabel = arguments?.getString("primaryButtonLabel")
val customerId = arguments?.getString("customerId").orEmpty()
val customerEphemeralKeySecret = arguments?.getString("customerEphemeralKeySecret").orEmpty()
val googlePayConfig = buildGooglePayConfig(arguments?.getBundle("googlePay"))
val allowsDelayedPaymentMethods = arguments?.getBoolean("allowsDelayedPaymentMethods")
val billingDetailsBundle = arguments?.getBundle("defaultBillingDetails")
Expand All @@ -86,6 +84,13 @@ class PaymentSheetFragment(
return
}

val customerConfiguration = try {
buildCustomerConfiguration(arguments)
} catch (error: PaymentSheetException) {
initPromise.resolve(createError(ErrorType.Failed.toString(), error))
return
}

val shippingDetails = arguments?.getBundle("defaultShippingDetails")?.let {
AddressSheetView.buildAddressDetails(it)
}
Expand Down Expand Up @@ -190,12 +195,7 @@ class PaymentSheetFragment(
val configurationBuilder = PaymentSheet.Configuration.Builder(merchantDisplayName)
.allowsDelayedPaymentMethods(allowsDelayedPaymentMethods ?: false)
.defaultBillingDetails(defaultBillingDetails)
.customer(
if (customerId.isNotEmpty() && customerEphemeralKeySecret.isNotEmpty()) PaymentSheet.CustomerConfiguration(
id = customerId,
ephemeralKeySecret = customerEphemeralKeySecret
) else null
)
.customer(customerConfiguration)
.googlePay(googlePayConfig)
.appearance(appearance)
.shippingDetails(shippingDetails)
Expand Down Expand Up @@ -428,6 +428,28 @@ class PaymentSheetFragment(
)
}
}

@OptIn(ExperimentalCustomerSessionApi::class)
@Throws(PaymentSheetException::class)
private fun buildCustomerConfiguration(bundle: Bundle?): PaymentSheet.CustomerConfiguration? {
val customerId = bundle?.getString("customerId").orEmpty()
val customerEphemeralKeySecret = bundle?.getString("customerEphemeralKeySecret").orEmpty()
val customerSessionClientSecret = bundle?.getString("customerSessionClientSecret").orEmpty()
return if (customerSessionClientSecret.isNotEmpty() && customerEphemeralKeySecret.isNotEmpty()) {
throw PaymentSheetException("`customerEphemeralKeySecret` and `customerSessionClientSecret` cannot both be set")
} else if (customerId.isNotEmpty() && customerSessionClientSecret.isNotEmpty()) {
PaymentSheet.CustomerConfiguration.createWithCustomerSession(
id = customerId,
clientSecret = customerSessionClientSecret
)
}
else if (customerId.isNotEmpty() && customerEphemeralKeySecret.isNotEmpty()) {
PaymentSheet.CustomerConfiguration(
id = customerId,
ephemeralKeySecret = customerEphemeralKeySecret
)
} else null
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"nodemon": "^2.0.19",
"path": "^0.12.7",
"react-test-renderer": "18.0.0",
"stripe": "^11.0.0",
"stripe": "^14.18.0",
"typescript": "^4.5.5"
}
}
170 changes: 135 additions & 35 deletions example/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ app.post(
const { secret_key } = getKeys(payment_method_types[0]);

const stripe = new Stripe(secret_key as string, {
apiVersion: '2022-11-15',
apiVersion: '2023-10-16',
typescript: true,
});

Expand Down Expand Up @@ -177,7 +177,7 @@ app.post(
const { secret_key } = getKeys();

const stripe = new Stripe(secret_key as string, {
apiVersion: '2022-11-15',
apiVersion: '2023-10-16',
typescript: true,
});
const customers = await stripe.customers.list({
Expand Down Expand Up @@ -255,7 +255,7 @@ app.post(
const { secret_key } = getKeys();

const stripe = new Stripe(secret_key as string, {
apiVersion: '2022-11-15',
apiVersion: '2023-10-16',
typescript: true,
});

Expand Down Expand Up @@ -344,7 +344,7 @@ app.post('/create-setup-intent', async (req, res) => {
const { secret_key } = getKeys(payment_method_types[0]);

const stripe = new Stripe(secret_key as string, {
apiVersion: '2022-11-15',
apiVersion: '2023-10-16',
typescript: true,
});
const customer = await stripe.customers.create({ email });
Expand Down Expand Up @@ -401,7 +401,7 @@ app.post(
const { secret_key } = getKeys();

const stripe = new Stripe(secret_key as string, {
apiVersion: '2022-11-15',
apiVersion: '2023-10-16',
typescript: true,
});
// console.log('webhook!', req);
Expand Down Expand Up @@ -464,7 +464,7 @@ app.post('/charge-card-off-session', async (req, res) => {
const { secret_key } = getKeys();

const stripe = new Stripe(secret_key as string, {
apiVersion: '2022-11-15',
apiVersion: '2023-10-16',
typescript: true,
});

Expand Down Expand Up @@ -534,11 +534,27 @@ app.post('/charge-card-off-session', async (req, res) => {
// This example sets up an endpoint using the Express framework.
// Watch this video to get started: https://youtu.be/rPR2aJ6XnAc.

app.post('/payment-sheet', async (_, res) => {
app.post('/payment-sheet', async (req, res) => {
const {
customer_key_type,
}: {
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, {
apiVersion: '2022-11-15',
apiVersion: '2023-10-16',
typescript: true,
});

Expand All @@ -553,10 +569,6 @@ app.post('/payment-sheet', async (_, res) => {
});
}

const ephemeralKey = await stripe.ephemeralKeys.create(
{ customer: customer.id },
{ apiVersion: '2022-11-15' }
);
const paymentIntent = await stripe.paymentIntents.create({
amount: 5099,
currency: 'usd',
Expand All @@ -577,18 +589,72 @@ app.post('/payment-sheet', async (_, res) => {
// 'us_bank_account',
],
});
return res.json({
paymentIntent: paymentIntent.client_secret,
ephemeralKey: ephemeralKey.secret,
customer: customer.id,
});

if (customer_key_type === 'legacy_ephemeral_key') {
const ephemeralKey = await stripe.ephemeralKeys.create(
{ customer: customer.id },
{ apiVersion: '2023-10-16' }
);

return res.json({
paymentIntent: paymentIntent.client_secret,
ephemeralKey: ephemeralKey.secret,
customer: customer.id,
});
} else {
const customerSessionClientSecret = await stripe.customerSessions.create(
{
customer: customer.id,
components: {
// This needs to be ignored because `mobile_payment_element` is not specified as a type in `stripe-node` yet.
// @ts-ignore
mobile_payment_element: {
enabled: true,
features: {
payment_method_save: 'disabled',
payment_method_remove: 'enabled',
payment_method_redisplay: 'enabled',
payment_method_allow_redisplay_filters: [
'unspecified',
'limited',
'always',
],
},
},
},
},
{ apiVersion: '2023-10-16' }
);

return res.json({
paymentIntent: paymentIntent.client_secret,
customerSessionClientSecret: customerSessionClientSecret.client_secret,
customer: customer.id,
});
}
});

app.post('/payment-sheet-subscription', async (_, res) => {
app.post('/payment-sheet-subscription', async (req, res) => {
const {
customer_key_type,
}: {
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, {
apiVersion: '2022-11-15',
apiVersion: '2023-10-16',
typescript: true,
});

Expand All @@ -603,10 +669,6 @@ app.post('/payment-sheet-subscription', async (_, res) => {
});
}

const ephemeralKey = await stripe.ephemeralKeys.create(
{ customer: customer.id },
{ apiVersion: '2022-11-15' }
);
const subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [{ price: 'price_1L3hcFLu5o3P18Zp9GDQEnqe' }],
Expand All @@ -618,11 +680,49 @@ app.post('/payment-sheet-subscription', async (_, res) => {
subscription.pending_setup_intent
);

return res.json({
setupIntent: setupIntent.client_secret,
ephemeralKey: ephemeralKey.secret,
customer: customer.id,
});
if (customer_key_type === 'legacy_ephemeral_key') {
const ephemeralKey = await stripe.ephemeralKeys.create(
{ customer: customer.id },
{ apiVersion: '2023-10-16' }
);

return res.json({
setupIntent: setupIntent.client_secret,
ephemeralKey: ephemeralKey.secret,
customer: customer.id,
});
} else {
const customerSessionClientSecret = await stripe.customerSessions.create(
{
customer: customer.id,
components: {
// This needs to be ignored because `mobile_payment_element` is not specified as a type in `stripe-node` yet.
// @ts-ignore
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_allow_redisplay_filters: [
'unspecified',
'limited',
'always',
],
},
},
},
},
{ apiVersion: '2023-10-16' }
);

return res.json({
setupIntent: setupIntent.client_secret,
customerSessionClientSecret: customerSessionClientSecret.client_secret,
customer: customer.id,
});
}
} else {
throw new Error(
'Expected response type string, but received: ' +
Expand Down Expand Up @@ -655,7 +755,7 @@ app.post('/issuing-card-details', async (req, res) => {
const { secret_key } = getKeys();

const stripe = new Stripe(secret_key as string, {
apiVersion: '2022-11-15',
apiVersion: '2023-10-16',
typescript: true,
});

Expand All @@ -678,7 +778,7 @@ app.post('/financial-connections-sheet', async (_, res) => {
const { secret_key } = getKeys();

const stripe = new Stripe(secret_key as string, {
apiVersion: '2022-11-15',
apiVersion: '2023-10-16',
typescript: true,
});

Expand All @@ -704,7 +804,7 @@ app.post('/payment-intent-for-payment-sheet', async (req, res) => {
const { secret_key } = getKeys();

const stripe = new Stripe(secret_key as string, {
apiVersion: '2022-11-15',
apiVersion: '2023-10-16',
typescript: true,
});

Expand All @@ -726,7 +826,7 @@ app.post('/customer-sheet', async (_, res) => {
const { secret_key } = getKeys();

const stripe = new Stripe(secret_key as string, {
apiVersion: '2022-11-15',
apiVersion: '2023-10-16',
typescript: true,
});

Expand Down Expand Up @@ -754,7 +854,7 @@ app.post('/fetch-payment-methods', async (req, res) => {
const { secret_key } = getKeys();

const stripe = new Stripe(secret_key as string, {
apiVersion: '2022-11-15',
apiVersion: '2023-10-16',
typescript: true,
});

Expand All @@ -771,7 +871,7 @@ app.post('/attach-payment-method', async (req, res) => {
const { secret_key } = getKeys();

const stripe = new Stripe(secret_key as string, {
apiVersion: '2022-11-15',
apiVersion: '2023-10-16',
typescript: true,
});
console.log({ customer: req.body.customerId });
Expand All @@ -789,7 +889,7 @@ app.post('/detach-payment-method', async (req, res) => {
const { secret_key } = getKeys();

const stripe = new Stripe(secret_key as string, {
apiVersion: '2022-11-15',
apiVersion: '2023-10-16',
typescript: true,
});

Expand Down
Loading
Loading