Developing Stripe Payment and Subscription Service for React Native App with NodeJS

Summary

This is a personal development note and review for writing Node with Stripe API and Firebase for a React Native application. Key takeaways and learning points are:

  • Integrate DevOps with development as much as possible to avoid simple mistakes in productions (i.e deploying the wrong key). Let one developer deploy it through production and a separate DevOps / QA to check it’s implemented properly instead.

Context

I worked as a remote backend programmer in a startup for about a year. The startup needed to integrate payment into the app for receiving one-off donations, and potentially implementing subscription services in the future.

Identifying business needs and limits

The first task I had to do was to research on regulations, security rules around online payments.

Apart from the fact that this is my first experience dealing with payments, there was a technical challenge particular to mobile payments.

  • Online payments need to follow PCI-DSS guideline, important key points being that payment processors must abide by strict guidelines (laid out in some 20+ pages) to protect consumer’s data privacy and security. As such, it is difficult and highly unrecommended for companies to store customer’s credit card information in their database, let alone caches in mobile apps. Well-known services that alleviate this burden are Paypal and Stripe.

Solution

The backend solution

In the NodeJS app, we need to write a stripeController.js and stripeRoutes.js for handling all stripe payments, userController.js and userRoutes.js for retrieving user subscription expiry date from Firebase.

We assume that the front end browser will send API request to NodeJS server in the form of /donate?uid=???&amount=???, and subscribe .

I’ve uploaded NodeJS code to https://github.com/0xckylee/rn-node-firebase_stripe-payment-subscription for those looking for code below.

stripeController.js
stripeRoutes.js
userController.js
userRoutes.js

Remember to add config.js for sensitive keys and firebase.js for starting Firebase app. See here for Node JS app Firebase setup.

As the existing NodeJS app was using ejs to render web pages, I had to adapt to using ejs, and the following solution worked. Whatever rendering engine you decide to use, hope the this will still guide you through loading Stripes Elements on the server-side.

Part of the folder structure

First, you need a folder named public with nested CSS, image (if needed), and js folders. I named files donation.css, donation.js within those folders for loading Stripe Elements.

donation.css
donation.js — Take note of that red rectangle box. That later becomes the source of production screw up.
view/donation.ejs

The Firebase DB will look like this in the end:

The frontend solution

While building backend we assumed the user would have to open a default browser on their phone to fill in credit card information. But the business side pushed for the best possible user experience (meaning, whatever it takes, find an in-app solution).

So I found a way: in-app pop up browsers. In expo, there’s a WebBrowser component.

Then call this _handlePressButtonAsync from Button component

The F@#!@ning

There’s always these production disaster episodes in dev communities. Here’s how we lost about USD 150 for donation: not swapping test key to prod key.

It’s such a dumb mistake that took hours of digging through Stripe logs because….

  • development was separated from DevOps

DevOps / deployment was handled by a senior engineer, which I thought was a good practice because I was afraid to break things in production. What happened instead was:

  • I left a Stripe test key in one of the files so that the NodeJS app would run. Should have left it empty instead to throw an error on purpose.

Big thank you to Stripe team that foresaw these mistakes and kindly logged what keys were used in the API logs.

r&d blog on architecture, software engineering and inspirations