About The Stripe React Native Migration Guide
If you have ever integrated payments with React Native, you may have encountered the popular community library “tipsi-stripe“. This project has been unmaintained for several years and the README now suggests migrating to the official Stripe React Native project.
To better support developers looking to migrate from “tipsi-stripe” to stripe-react-native, we’ve prepared The Stripe React Native Migration Guide to walk you through the core concepts and integration steps.
This article is the first part of the guide in which we go through the process of migrating from <rte-code>tipsi-stripe<rte-code> to <rte-code>stripe-react-native<rte-code>.
The guide is divided by 5 parts in which you'll learn about the following aspects of the migration process:
- Part 1 - How to migrate from Tipsi Stripe to the Stripe React Native SDK
- Part 2 - How to configure Stripe React Native
- Part 3 - A detailed description of Stripe React Native migration function by function (you are here)
- Part 4 - How not to break your app after migrating from Tipsi Stripe to Stripe React Native
- Part 5 - A collection of the most common questions related to Stripe React Native
This article is part 3 of our ongoing series on migrating from Tipsi-Stripe to stripe-react-native. Make sure to read the previous articles on understanding stripe react native and configuring the stripe-react-native library.
Are you migrating your app’s payments logic from <rte-code>tipsi-stripe<rte-code> to <rte-code>stripe-react-native<rte-code>? In this article, we cover how to migrate each payment type and function you might use. As you could see in the previous posts, the initial setup of <rte-code>stripe-react-native<rte-code> is simple and intuitive. Today, we will focus on each payment function in <rte-code>tipsi-stripe<rte-code> and describe how to migrate it to <rte-code>stripe-react-native<rte-code>.
- Card components
- Accepting a payment
- Future payments
- Create a token
- Apple Pay
- Google Pay
One of the essential features of using Stripe is collecting the card details in order to process a payment. Tipsi-stripe has a <rte-code>PaymentCardTextField<rte-code> component and <rte-code>onParamsChange<rte-code> prop that is used to collect card details. Collected card details have to be stored in a state in order to use them in card payment.
With <rte-code>stripe-react-native<rte-code> there is no need to collect card data manually. The library does that for you. It makes it both easy to use and much more secure. Just render CardField every time you want to use card-related payment.
In the above code examples, the placeholder information is now a single object called <rte-code>placeholder<rte-code>. In addition, basic component styles can be modified using single <rte-code>cardStyle<rte-code> prop instead of multiple ones (<rte-code>cursorColor<rte-code>, <rte-code>placeholderColor<rte-code>, etc.).
Another difference with the <rte-code>CardField<rte-code> component is the set of methods on its ref. Tipsi has <rte-code>blur<rte-code>, <rte-code>focus<rte-code>, <rte-code>isFocused<rte-code> and iOS-only <rte-code>setParams<rte-code>. First two are exactly the same in <rte-code>stripe-react-native<rte-code>. However, in order to know if card input is focused, you should use the <rte-code>onFocus<rte-code> prop and handle this information declaratively instead of calling an imperative <rte-code>isFocused<rte-code> function. Setting params are not available in <rte-code>stripe-react-native<rte-code> but we believe that since this is not supported by both platforms there is no need for that in React Native applications. This decision together with <rte-code>onCardChange<rte-code> prop which sends only the <rte-code>last four digits<rte-code> instead of the whole card number improves the security of the <rte-code>CardField<rte-code> component.
NOTE: If your app requires access to the entire card number it is still possible with <rte-code>stripe-react-native<rte-code>. You can set <rte-code>dangerouslyGetFullCardDetails<rte-code> to <rte-code>true<rte-code> in order to have a full card number returned in the <rte-code>onCardChange<rte-code> handler. Keep in mind this is not recommended since your customers' information must be protected at all costs.
Accepting a payment
With <rte-code>PaymentIntent<rte-code> API there are some significant differences between libraries. The biggest one is that in <rte-code>stripe-react-native<rte-code> for PCI compliance reasons all of the sensitive data is sent to the specific methods under the hood and you don’t need to hand it over on your own. This means that in order to proceed with a <rte-code>Card<rte-code> payment, you have to collect the data using either <rte-code>CardField<rte-code> or <rte-code>CardForm<rte-code> component provided by <rte-code>stripe-react-native<rte-code> library. In this way, the personal data is secure, as it is kept confidential from developers.
Create Payment Method
In both libraries for creating a payment method you can use <rte-code>createPaymentMethod<rte-code> function. If it comes to card payments main difference was describe above - instead of passing card details now you just have to set the <rte-code>type<rte-code> param to <rte-code>"Card"<rte-code> and be sure that <rte-code>CardField<rte-code> component is rendered on your screen.
In both libraries provide billing details using the <rte-code>billingDetails<rte-code> field which contains <rte-code>address<rte-code>, <rte-code>email<rte-code>, <rte-code>name<rte-code>, and <rte-code>phone<rte-code>. See the api reference for more details.
NOTE: If you are using <rte-code>token<rte-code> to provide card details to <rte-code>createPaymenMethod<rte-code> you can still do this. The only difference is the way of generating it. More details you will find later in this article.
Confirm payment intent (for manual payment flows)
If your payment requires confirmation, you have to call a specific function in order to launch an activity where the user can authenticate the payment. For manual payment flow, there is an <rte-code>authenticatePaymentIntent<rte-code> method in <rte-code>tipsi-stripe<rte-code> and the equivalent in <rte-code>stripe-react-native<rte-code> is handleCardAction.
In the above example, you can see that <rte-code>clientSecret<rte-code> is now a separate and the first argument of the function. This new implementation, just as in Tipsi, returns a <rte-code>Promise<rte-code> with payment intent details. In Tipsi, you could access there <rte-code>intent id<rte-code> and its status, <rte-code>stripe-react-native<rte-code> returns an error and the whole PaymentIntent object.
NOTE: It is worth mentioning that in error scenarios <rte-code>stripe-react-native<rte-code> always resolves promise and returns the error instead of rejecting it.
Confirm payment intent (for automatic payment flows)
For automatic confirmation flows, you just need to change the way you use <rte-code>confirmPaymentIntent<rte-code> method. In <rte-code>stripe-react-native<rte-code> function name was changed to <rte-code>confirmPayment<rte-code> but the main difference is that instead of passing client secret and payment details in a single object you need to pass them as two separate function arguments.
As with other payment methods, now there is no need to pass card details manually. You just need to specify the payment type and everything else will be collected automatically.
See confirmPayment for more details about possible configuration and different payment types.
In <rte-code>tipsi-stripe<rte-code> to set up recurring payments or to create one-time payments with a final amount determined later, there is a <rte-code>confirmSetupIntent<rte-code> method. <rte-code>stripe-react-native<rte-code> has the same function but with a slightly changed API. The differences here are almost the same as with <rte-code>confirmPaymentIntent<rte-code> function. Now you pass client secret as a first function argument and there is no need for card details.
Create a token
Stripe provides a way to convert information collected by card components into a single-use token that you safely pass to your server to use in an API call.
Tipsi has a <rte-code>createTokenWithCard<rte-code> function for that. It differs from the new createToken only in the way how to pass card data and the fact that it doesn't require to manually pass card details.
Remember that as with other card related functions, to use <rte-code>createToken<rte-code> function you have to render <rte-code>CardField<rte-code> component .
NOTE: <rte-code>tipsi-stripe<rte-code> provides also a way to create a bank account token using <rte-code>createTokenWithBankAccount<rte-code> function. This is not yet supported by stripe-react-native but should be ready the upcoming release. This functionality will be added as a part of <rte-code>createToken<rte-code> function.
Before displaying Apple Pay as a payment option in your app, first determine if the user’s device supports Apple Pay and that they have a card added to their wallet. In order to this <rte-code>stripe-react-native<rte-code> provides <rte-code>isApplePaySupported<rte-code> boolean value from useApplePay hook.
NOTE: If your application doesn't use functional components, as an alternative you can import <rte-code>isApplePaySupported<rte-code> method directly from the library.
Requesting payment in Tipsi can be done with <rte-code>paymentRequestWithNativePay<rte-code> function. It takes a list of items and an <rte-code>options<rte-code> object with shipping details and other properties. After migration, you should use presentApplePay function and pass all needed details as a single configuration object. Please refer to the documentation for all available properties.
<p-bg-col>Remember that the last item in items array needs to reflect the total value.<p-bg-col>
To process payment in Tipsi after requesting it, it is required to call <rte-code>completeNativePayRequest<rte-code> function. After migration there is a confirmApplePayPayment function for that. This and every other ApplePay related function you can get from <rte-code>useApplePay<rte-code> hook or import directly from the library.
As against to <rte-code>tipsi-stripe<rte-code>, <rte-code>stripe-react-native<rte-code> provides a separate API for GooglePay. In Tipsi, you could use the same functions as for ApplePay (see above) but with <rte-code>stripe-react-native<rte-code> there is a need to (first) initialize GooglePay and then (second) present it using presentGooglePay function.
In Tipsi there is a paymentRequestWithCardForm function that opens the <rte-code>Add Card<rte-code> view to accept a payment. Unfortunately this is not supported in <rte-code>stripe-react-native<rte-code>. In order to collect card details please use <rte-code>CardField<rte-code> component or confirmPaymentSheetPayment functionality for a unify Payment UI experience.
So looks like migration is not that scary anymore and it is quite doable, right? Show your work - as they say. Fortunately, I have an example and a proof for you!
Here you can find an example PR with a Tipsi to stripe-react-native migration. This is a migration of a project with:
- Card payment
- Apple Pay usage
- Google Pay usage
These migration steps described above show these two libraries are noticeable and require you to refactor your app’s code. But remember, after you start the migration process you will see that the differences are not too big. You should be able to migrate almost everything quickly.
In the upcoming articles, we will be covering the testing part and answering most common questions. Thanks for reading and stay tuned!