Stripe makes it easy to accept payments online. Stripe offers an npm package with nice documentation.
Problem with using Stripe in React Native
I added stripe to my React Native application using following command.
1npm install stripe --save
Added Stripe to the project as shown below.
1var stripe = require('stripe')('stripe API key');
And now I'm getting following error.
This's because npm package uses stripe.js and stripe.js needs http provided by Node.JS.
Our React Native code does not actually run on Node.JS. I know while building React Native we use NPM and we have a node server running in the background so it feels like we are in Node.JS land and we can use everything Node.JS has to offer. But that's not true. React Native code can't depend on Node.JS because Node.JS is not shipped with ios. It means we can't use any of Node.JS packages including http. It means we can't use stripe npm module.
Now you can remove require('stripe') line that was added in the last step.
Solution
React Native comes with Fetch api. From the documentation
The Fetch API provides a JavaScript interface for accessing an manipulating parts of the HTTP pipeline, such as requests and responses. It also provides a global fetch() method that provides an easy, logical way to fetch resources asynchronously across the network.
stripe.js is a nice wrapper around stripe api. stripe api is very well documented and is easy to use. Since we can't use stripe.js we will use stripe api.
We will use fetch to create a credit card token using api.
1return fetch("https://api.stripe.com/v1/tokens", { 2 method: "post", 3 headers: { 4 Accept: "application/json", 5 "Content-Type": "application/x-www-form-urlencoded", 6 Authorization: "Bearer " + "<YOUR-STRIPE-API-KEY>", 7 }, 8 body: formBody, 9});
Here, the header has 3 keys. Lets go through them one-by-one:
- 'Accept': 'application/json' : Designates the content to be in JSON format.
- 'Content-Type': 'application/x-www-form-urlencoded' : This tells the endpoint that the payload will be one giant query string where name and value pairs will be separated by the ampersand.
- 'Authorization': 'Bearer ' + '<YOUR-STRIPE-API-KEY>' : This key is to authorize our actions on Stripe. Here Bearer is just a prefix which we need to attach to the api-key because Stripe uses OAuth 2.0 . You can read more on the Bearer token usage here .
Payload needs to contain credit card details.
1var cardDetails = { 2 "card[number]": "1111 2222 3333 4444", 3 "card[exp_month]": "01", 4 "card[exp_year]": "2020", 5 "card[cvc]": "123", 6};
Since the Content-Type is application/x-www-form-urlencoded, the payload should be one query string. An example of this would be: city=Miami&state=Florida
Let's prepare a proper payload.
1var formBody = []; 2for (var property in cardDetails) { 3 var encodedKey = encodeURIComponent(property); 4 var encodedValue = encodeURIComponent(cardDetails[property]); 5 formBody.push(encodedKey + "=" + encodedValue); 6} 7formBody = formBody.join("&");
That's it. Now we can attach formBody to the body part of the fetch request and we are good to go.
Final solution
Here's the whole code snippet.
1"use strict"; 2 3var stripe_url = "https://api.stripe.com/v1/"; 4var secret_key = "<YOUR-STRIPE-API-KEY>"; 5 6module.exports.createCardToken = function (cardNumber, expMonth, expYear, cvc) { 7 var cardDetails = { 8 "card[number]": cardNumber, 9 "card[exp_month]": expMonth, 10 "card[exp_year]": expYear, 11 "card[cvc]": cvc, 12 }; 13 14 var formBody = []; 15 for (var property in cardDetails) { 16 var encodedKey = encodeURIComponent(property); 17 var encodedValue = encodeURIComponent(cardDetails[property]); 18 formBody.push(encodedKey + "=" + encodedValue); 19 } 20 formBody = formBody.join("&"); 21 22 return fetch(stripe_url + "tokens", { 23 method: "post", 24 headers: { 25 Accept: "application/json", 26 "Content-Type": "application/x-www-form-urlencoded", 27 Authorization: "Bearer " + secret_key, 28 }, 29 body: formBody, 30 }); 31};
This is an example of registering a credit card with stripe and getting the token. Similar implementations can be done for other API endpoints.