Simplifying payment methods code in our new API version

2023-08-17
Simplifying payment methods code in our new API version

The landscape of payment methods is changing quickly. Buy now, pay later methods, little-known less than a decade ago, now account for more than $300 billion in transactions worldwide.1 Mobile wallets accounted for roughly half of global ecommerce payment transactions last year.2 And while we at Stripe love nothing more than keeping up with emerging payments trends, we realize most developers don’t want to constantly refactor and tweak their Stripe integration. So we’ve been thinking hard about the right set of tools to help you continuously offer the payment methods your customers want while minimizing engineering overhead. 

The problem with specifying configurable properties in code 

Writing code for a payments interface typically requires you to specify three types of properties: the capabilities of your payments integration (e.g., whether your application can support redirects), the variable properties of a given payment (e.g., amount or currency), and numerous configurable properties (e.g., do not show Affirm for transactions less than $50). These configurable properties, which are typically hard-coded in a parameter like , can cause land mines that result in payment failures and errors that are hard to debug. 

This is because payment methods have nuanced limitations that impact whether they can be used for a given transaction—whether it’s transaction minimums and maximums, currency limitations, merchant category restrictions, or differences in recurring payment support. Implementing a new payment method means you need to 1) know all the specific limitations for that payment method and 2) encode complex logic to hide or display that payment method based on those limitations for each transaction. Doing either of these wrong means risking payment failures and disputes, leading to lots of time and effort to ship new changes.

Making dynamic payment methods the default in the API

Requiring a code change to modify configurable properties is the type of high-toil engineering work you’ve consistently told us you want to eliminate. So today, we’re changing the default behavior of the PaymentIntents and SetupIntents API. Instead of individually specifying in code, you can now configure payment method settings from the Dashboard—no code required. We call this integration path dynamic payment methods. 

When you use dynamic payment methods with our prebuilt UIs like the Payment Element or Checkout, Stripe handles the logic for displaying eligible payment methods in your frontend for each transaction—removing the need to know and encode specific eligibility requirements. We then dynamically order all of your eligible payment methods to maximize for conversion based on factors including the customer’s device, location, and local currency. If you want to change your payment methods configuration later, you can do so directly from the Dashboard. For example, if you want to offer different payment methods for one-time versus recurring payment flows, or if you want to hide high-risk payment methods on high-AOV transactions, you can set these rules from the Dashboard, rather than writing complex error-prone code. Your integration becomes simpler, safer, and more future-proof.

Before

app.post("/create-payment-intent", async (req, res) => { const { items } = req.body; const orderAmount = calculateOrderAmount(items) const orderCurrency = calculateOrderCurrency(items) let paymentMethodTypes = ["card"]; // Add specific payment methods based on currency and amount switch(orderCurrency) { case "eur": paymentMethodTypes.push("giropay"); break; case "gbp": paymentMethodTypes.push("klarna"); if (orderAmount >= 100 && orderAmount <= 100000) { paymentMethodTypes.push("afterpay_clearpay"); } break; case "usd": paymentMethodTypes.push("paypal"); break; default: } // Create PaymentIntent with payment_method_types const paymentIntent = await stripe.paymentIntents.create({ amount: orderAmount, currency: orderCurrency, payment_method_types: paymentMethodTypes, }); res.send({ clientSecret: paymentIntent.client_secret, }); });

After

app.post("/create-payment-intent", async (req, res) => { const { items } = req.body; const orderAmount = calculateOrderAmount(items) const orderCurrency = calculateOrderCurrency(items) // Create PaymentIntent with dynamic payment methods by default const paymentIntent = await stripe.paymentIntents.create({ amount: orderAmount, currency: orderCurrency }); res.send({ clientSecret: paymentIntent.client_secret, }); });

We’ve paired this API change with tools to give you confidence that your integration is working as expected and to determine why certain payment methods aren’t available for a given transaction. From the Dashboard, you can enter a PaymentIntent ID or Checkout Session for more information on which payment methods were enabled for the transaction and why certain options were not eligible. You can also simulate which payment methods will be displayed when changing factors such as amount, currency, capture method, and future usage.

And we’re not stopping here. Since it no longer takes a code change to configure payment methods, you can rely on Stripe to tackle all kinds of checkout optimizations that previously required nontrivial engineering effort. You can use Dashboard controls to run A/B tests on payment methods, configure payment methods for different checkout scenarios, and set custom targeting rules. To take advantage of these new features, upgrade to the latest API version today.