A Guide to Integrating Stripe into your GraphQL-based React Web App
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
StripeGraphQL - A Guide to Integrating Stripe into your GraphQL-based React Web Appgithub.com
You can follow the example code by typing in your Terminal app:git clone https://github.com/ConsciousApps/StripeGraphQL.git (use atom or another code editor)
cd StripeGraphQL
atom .
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:
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).GraphQL(also developed by Facebook) for the back-end, because it is both simpler and more flexible thanRESTAPIs.- To interface between
ReactandGraphQL, I chose the open-sourceApollo Client, since the other option—Relay(developed by Facebook)—seemed far too complex at the time of this writing. - And, finally, as my
GraphQLservice 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 appusers,StripeToken, a collection of Stripetokens, related to theUsermodel in a one-to-one relationship: one Stripetokenperuser, andPurchase, a collection ofpurchasesmade by individualusers, related to theUsermodel in a many-to-one relationship: manypurchasesperuser.
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.
- When the
Stripe Checkoutmodal is loaded and user clicks “Purchase”, Stripe creates atokenand sends it back to the app. - Our app then creates a
node(a new entry) in theStripeTokenmodel, and assigns it the Stripetokenand connects that node to theUsermodel via theuser.id. - A
Mutation Callbackis activated once our app hascreatedanodein theStripeTokenmodel. ThisMutation Callbacksends thetokento our back-endcreateCustomerserver, which then uses Stripe’s API to create a Stripecustomerusing thattokenand ouruser’s data (such asemail,name, etc.). Stripe will return a unique Stripecustomer.idto the server. - On successful creation of a Stripe
customer, ourcreateCustomerserver thenupdatestheuserthat made the purchase in theUsermodel with Stripe’scustomer.idand stores it in a field, for example, calledstripeId. - Meanwhile, our front-end web app has been listening to any updates to the
stripeIdof the specific user with the help of a GraphQLsubscription. Once our web app realizes that theuserhas received astripeIdupdate, we move on to the next step. - Once user has received a
stripeId, our front-end web app creates anodein thePurchasemodel using a purchasedescription(e.g.“Life Purpose App”), anamount(e.g.999for $9.99), and abooleanisPaidset tofalse. This is important because the app itself hasn’t yet actually been paid for, even though we’ve already created a new purchasenodein thePurchasemodel. - A different
Mutation Callbackis activated once our app hascreatedanodein thePurchasemodel. ThisMutation Callbacksends thestripeId,description, andamountto a second server, ourcreateChargeserver, which then creates a Stripecharge. - On successful creation of a Stripe
charge, ourcreateChargeserver thenupdatestotruetheisPaidfield of the specificpurchasein thePurchasemodel, since we’ve now received the money, honey. - Meanwhile, our front-end web app has been listening to any updates to the
isPaidof the specific transaction with the help of a GraphQLsubscription. Once our web app realizes that thepurchasewe’ve been listening to via thesubscriptionhas received anisPaidistrueupdate, we move on to the next step. - Now our web app is free to implement any logic to indicate that the user has successfully upgraded, for example by setting a
paidfield in theUsermodel totrue.
Implementation
Now, the code.
Step #A: Create a component to interface with Stripe
- Create a basic
Reactcomponent. - Add the
react-stripe-checkoutmodule. - Obtain Stripe API keys and enter publishable
testkey into yourReactcomponent. - 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 yourMutation Callbackto yourcreateCustomerserver — and remember to write it down somewhere else).now secret add charge-secret XXX(a randomized number/letter combination to later securely connect yourMutation Callbackto yourchargeCustomerserver — 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 production—and 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