A Guide to Integrating Stripe into your GraphQL-based React Web App

Martin Adams
ConsciousApps
Published in
8 min readMar 1, 2017

This article is currently out of date since Graphcool introduced functions. Please read their documentation, here, until such a time that this article will be updated with the latest instructions:

https://www.graph.cool/docs/reference/functions/overview-boo6uteemo/

https://github.com/graphcool-examples/functions/tree/master/stripe-create-customer

You can follow the example code by typing in your Terminal app:
git clone https://github.com/ConsciousApps/StripeGraphQL.git
cd StripeGraphQL
atom .
(use atom or another code editor)

As someone who prefers simplicity over abstraction, I’m a fan of using advanced technologies that are simple at the same time. Thus, for developing JavaScript web apps, I eventually settled on the following technologies, which—to me—seem to be both advanced and simple enough at the same time:

  1. React (developed by Facebook) for the front-end. Because components are the future of web development, and because you can share code between web apps (React) and mobile apps (React Native).
  2. GraphQL (also developed by Facebook) for the back-end, because it is both simpler and more flexible than REST APIs.
  3. To interface between React and GraphQL, I chose the open-sourceApollo Client, since the other option—Relay (developed by Facebook)—seemed far too complex at the time of this writing.
  4. And, finally, as my GraphQL service provider I chose Graphcool for their simple yet versatile user interface, excellent customer service, supportive community, and competitive pricing model.

The current app I’m developing — the Life Purpose App — requires in-app payment. While in-app payments are being handled in the App Store and Google Play Store for native mobile apps, we have to create an in-app payment method for web apps. As payment provider, I’m choosing Stripe because of Stripe Checkout (the product speaks for itself).

So this tutorial employs all these tools and requires familiarity with React, and, to a lesser extent, GraphQL/Apollo Client. If you haven’t yet learned any of them, I highly recommend each of these tools.

Furthermore, this tutorial has been inspired by and builds upon graph.cool’s original tutorial on how to integrate Stripe Checkout into a web app. I recommend you check it out as well, with the caveat that — as of this writing — it does not use GraphQL subscriptions, which are necessary for a successful checkout process.

Let’s begin!

GraphQL Models

We need the following models in GraphQL:

  • User, a collection of app users,
  • StripeToken, a collection of Stripe tokens, related to the User model in a one-to-one relationship: one Stripe token per user, and
  • Purchase, a collection of purchases made by individual users, related to the User model in a many-to-one relationship: many purchases per user.

The three models will require the following schema:

If you want to learn more about GraphQL models, I highly recommend graph.cool’s ‘cool’ documentation.

Logic

Now, the actual logic. For security reasons, you are unable to create Stripe payment charges via your front-end app; a back-end server has to do that, since a server is designed to be inaccessible to unauthorized users. That’s why Stripe has implemented this particular logic.

I’ll be referring to the following steps throughout this tutorial in bold as well as in the actual code as Logic #1, Logic #2, etc., so be sure to reference them here later on.

  1. When the Stripe Checkout modal is loaded and user clicks “Purchase”, Stripe creates a token and sends it back to the app.
  2. Our app then creates a node (a new entry) in the StripeToken model, and assigns it the Stripe token and connects that node to the User model via the user.id.
  3. A Mutation Callback is activated once our app has created a node in the StripeToken model. This Mutation Callback sends the token to our back-end createCustomer server, which then uses Stripe’s API to create a Stripe customer using that token and our user’s data (such as email, name, etc.). Stripe will return a unique Stripe customer.id to the server.
  4. On successful creation of a Stripe customer, our createCustomer server then updates the user that made the purchase in the User model with Stripe’s customer.id and stores it in a field, for example, called stripeId.
  5. Meanwhile, our front-end web app has been listening to any updates to the stripeId of the specific user with the help of a GraphQL subscription. Once our web app realizes that the user has received a stripeId update, we move on to the next step.
  6. Once user has received a stripeId, our front-end web app creates a node in the Purchase model using a purchase description (e.g. Life Purpose App), an amount (e.g. 999 for $9.99), and a boolean isPaid set to false. This is important because the app itself hasn’t yet actually been paid for, even though we’ve already created a new purchase node in the Purchase model.
  7. A different Mutation Callback is activated once our app has created a node in the Purchase model. This Mutation Callback sends the stripeId, description, and amount to a second server, our createCharge server, which then creates a Stripe charge.
  8. On successful creation of a Stripe charge, our createCharge server then updates to true the isPaid field of the specific purchase in the Purchase model, since we’ve now received the money, honey.
  9. Meanwhile, our front-end web app has been listening to any updates to the isPaid of the specific transaction with the help of a GraphQL subscription. Once our web app realizes that the purchase we’ve been listening to via the subscription has received an isPaid is true update, we move on to the next step.
  10. Now our web app is free to implement any logic to indicate that the user has successfully upgraded, for example by setting a paid field in the User model to true.

Implementation

Now, the code.

Step #A: Create a component to interface with Stripe

  1. Create a basic React component.
  2. Add the react-stripe-checkout module.
  3. Obtain Stripe API keys and enter publishable test key into your React component.
  4. Your component could look similar to this:

Step #B. Create GraphQL code

To keep the code compartmentalized from React components, I’ll save them in a different file, for example /graphql/purchase.js and import them into components as needed. That’s why each step requires an export before the const. Read the graph.cool documentation for more background information.

Be sure to also create a userQuery to get the current user.id. I keep it in a separate file /graphql/user.js:

Step #C: Connect Component with GraphQL code

Import graphql code into component (at the top of the component).

And connect component to graphql (at the bottom of the component).

Step #D: Create your backend servers and connect them to your Mutation Callbacks

Graph.cool has a detailed overview of how to create your own server using zeit.co’ now service. Highly recommend you check it out.

1. Create an authentication token in your graph.cool console: https://console.graph.cool/YOURAPPNAME/settings/authentication

2. Install now. In your Terminal app, type in: sudo npm i -g now

3. Assign the following environment variables to your now server via the Terminal.

  • now secret add stripe-secret sk_test_XXXXXXXXXXXXXXXXXXXXXXXX (your Stripe secret key)
  • now secret add gc-pat XXX (the graph.cool auth token created in step 1)
  • now secret add endpoint https://api.graph.cool/simple/v1/PROJECTID (your graph.cool project endpoint)
  • now secret add create-secret XXX (a randomized number/letter combination to later securely connect your Mutation Callback to your createCustomer server — and remember to write it down somewhere else).
  • now secret add charge-secret XXX (a randomized number/letter combination to later securely connect your Mutation Callback to your chargeCustomer server — and remember to write it down somewhere else).
  • now secret add log XXX (a randomized number/letter combination to later securely log what’s happening during development stage—but be sure to remove logs for productionand remember to write it down somewhere else).

4. Clone the following repository: https://github.com/graphcool-examples/micro-stripe-example.git You may have to tweak some of the code in either createCustomer.js or in createCharge.js to match your unique GraphQL schema (data.createdNode returns data according to your schema naming convention).

5. From the repository’s root directory, in Terminal, launch the server that creates Stripe customers:
now -e STRIPE_SECRET=@stripe-secret -e GC_PAT=@gc-pat -e ENDPOINT=@endpoint -e TOKEN=@create-secret -e LOG=@log create/

6. now will return the URL to your newly created webhook. For example:
https://yourappname-create-customer-zftydstlej.now.sh Copy that URL and add to it your create-secret token (which you created in step #3 above), like this:
https://yourappname-create-customer-zftydstlej.now.sh?token=XXX

7. Create a new Mutation Callback in your GraphQL console. Into StripeToken is created, paste the following trigger:

8. Paste the URL from step #6 into the Mutation Callback handler created in step #7.

9. From the repository’s root directory, in Terminal, launch the server that creates Stripe charges:
now -e STRIPE_SECRET=@stripe-secret -e GC_PAT=@gc-pat -e ENDPOINT=@endpoint -e TOKEN=@charge-secret -e LOG=@log charge/

10. now will return the URL to your newly created webhook. For example:
https://yourappname-create-charge-xpibjdifiv.now.sh Copy that URL and add to it your charge-secret token (which you created in step #3 above), like this:
https://yourappname-create-charge-xpibjdifiv.now.sh?token=XXX

11. Create another Mutation Callback in your GraphQL console. Into Purchase is created, paste the following trigger:

12. Paste the URL from step #10 into the second Mutation Callback handler created in step #11.

Step #E: Implement logic into front-end component

Going back to our component, we now need to make sure Logic #1 — #10 (remember these?) are followed. But first, to make our test app work, let’s bring in the user (in your app, the user has most likely been previously called). For the sake of this example (https://github.com/ConsciousApps/StripeGraphQL.git), let’s add the user into a componentWillMount.

Into the onToken function, let’s add Logic #2 (create node in StripeToken model). So now, onToken looks like this:

Next, we’ll add Logic #5 and #6 (Logic #3 and #4 are done on the server) to componentDidUpdate.

Logic #6 should trigger Logic #7 and #8 on the server, so let’s add Logic #9 and #10 to our app. We’ll simply insert another subscription after the first one inside componentDidUpdate.

So now we have our final component:

And FINALLY…

Step #F: Set Correct Permissions in Console

To make sure that the user cannot just call updateUser with paid set to true and thereby manually skip the purchase process, be sure to only set read permission for the paid field.

Testing your App

To test your app, run your front-end component, but also consider using the logger on your now server, too, to see what happens on the back-end: Add logs to your server code, re-do steps #D5 — #D12 (no need do #D7 and #D11 again), then enter in Terminal: now-logs XXX (using the secret you added in Step #D3). Now run your front-end component and see what happens on the back-end when you go through the payment process.

So that was quite a tutorial. If you’ve made it this far, thanks for reading; I hope you get your in-app purchase to work using Stripe, and that you build apps that do good things in the world. ❤️

To learn more about the app that made me learn all this in-app purchase stuff, feel free to visit: http://LifePurposeApp.com (as of this writing, this comprehensive update is scheduled for release mid-April 2017).

Take care,

Martin Adams
GitHub | ConsciousApps.com

--

--