How To Setup Stripe and Start Making Money - Startup Week 20

Masatoshi Nishimura
Kaffae
Published in
9 min readMay 24, 2020
Stripe checkout page with test account

Every side hustlers and creatives have dream of one day charging and making a living off of your baby products. Stripe has become standard today in how software engineers as well as side hustlers make money online. Their documentation is very comprehensive, and the feature offering is very robust. I tried Paypal marketplace 5 years ago, and the ease of Stripe API wins hands down.

Even though Stripe documentation is probably the best out there by far, it’s not perfect. I could not find a start-to-end complete instruction for a developer like me.

I’d like to share the pitfalls I came across while integrating their API for Kaffae’s new subscription model. The architecture should look very similar to your simple SASS websites in 2020.

Simple Requirement

The requirement was very simple. It needed 3 pages. User lands onto the premium membership description website. The website is a simple HTML page. Then they choose one of the two options either the monthly or yearly subscription, both with free trials. They then enter their credit card in the processing page, and sees the checkout complete page.

Stripe Requirement

Let’s first list out what needs to be prepared from Stripe and Stripe Dashboard.

  1. Signup
  2. Tokens
  3. Libraries
  4. IDs

Signup

Signup was very simple. You just need to connect your bank information (bank number, transit number, account number). I used my personal account for this step. In the future, when the payment starts coming, I will switch to a business account. I go with the least amount of hustle that translates no value to end users at this stage.

Tokens

There are 3 types of tokens I used: client token, backend token, and webhook token.

They are all found in Stripe Dashboard. I will be explaining where each of them is used in the process. Also keep in mind, you will be likely starting with test data. Each token is offered separately with test mode and production mode. So, you will be collecting 6 tokens altogether.

Libraries

To handle the complete checkout flow, Stripe offers a clientside library and serverside library. It makes your job much simpler. The clientside library is a simple JavaScript wrapper you can copy and paste into your HTML file. You only need to copy and paste. I believe they offer React library too.

For the serverside, Kaffae runs on NodeJS so it was a simple npm install. They offer the version for your server requirement too from Ruby and Python to Golang.

They might offer API that lets you handle everything by yourself. But I wouldn’t encourage it. You don’t want to be wasting time handling the authentication process, which offers the end user 0 value.

IDs

Stripe breaks down the shopping concept with products and pricing. Pricing belongs to a product. So each product can have multiple pricing. They each come with their own unique id.

Since it’s a SASS product, Kaffae needed only 1 type of product called subscription with 2 different pricings — monthly and yearly. I made them at the Dashboard. If you offer e-commerce with a frequent update, you want to be using their API to create products and pricing.

In the end, I only needed to reference pricing to send over Stripe. I guess they just infer the product from the pricing ids. Again these ids are different for test and production data so you’d need 4 altogether.

Flow

The workflow would follow like these 8 steps;

  1. User clicks the button “choose this plan”.
  2. JavaScript makes a call to the server
  3. Server makes a call to Stripe
  4. Stripe client library redirects the user to checkout
  5. Blackbox
  6. Stripe sends webhook for checkout information

7. Server stores useful information

8. User is redirected to the checkout complete page

Let’s dive in detail.

1. User clicks the button “choose this plan”.

For checkout to start, you need a one time session ID from Stripe. The choose-button is connected to your own function. It doesn’t involve Stripe library at this step yet.

2. JavaScript makes a call to the server

You make XML request to your own server. Your server needs to know which pricing plan the user has chosen. I simply attached a query variable to my request like pricing=monthly at the end of url.

Also, it highly depends on your business logic, but I’ve noticed Spotify and Pocket require you to login in order to get a subscription while pricing page is visible to anyone. You will be simply redirected to the login page when you choose a plan. I followed the same logic in Kaffae as well. It checks for the login status before fetching for the session id.

3. Server makes a call to Stripe

This is where Stripe server side library comes in effect. Once your API request arrives, the pricing query variable is mapped with the Stripe’s pricing id found in the Dashboard. That information is passed onto the Stripe’s library to make a session create API.

In the official checkout tutorial, the line_items parameters were used, but if you are SASS, you’d need to set subscription_data. Otherwise, your free trial information does not get processed properly.

Session checkout code for Kaffae

That call will give you session id, and you will return the user with that information.

*Keep in mind the library needs to be initiated with the serverside token from your Dashboard.

4. Stripe client library redirects user to checkout

In the HTML page, the session id will be passed onto the Stripe’s clientside library. This was very simple. Maybe too simple. It was confusing to me for a while if I needed to pass the user related meta information like client_reference_id to in the clientside or server side library. Apparently this clientside redirectToCheckout function only accepts sessionId (if you go with this checkout flow). It’ll throw an error the moment you pass on anything else.

This function will automatically take the user away from your website to Stripe’s.

Stripe redirect checkout. The error message is kept the same from the tutorial.

5. Blackbox

Your user is going through the checkout entering the credit card information. Basically, you have no control of what information gets displayed or what is happening here at all.

Stripe displays your product info, logo, and customer email (which I decided to prefill by providing customer_email in step 3).

I set my country as Canada, and it always asked for my Postal Code (Zipcode). I don’t think that’s a standard practice in Canadian ecommerce, but I couldn’t find a way to turn it off.

Stripe checkout page from the test account

I was disappointed Stripe coudn’t even handle plural check for “1 days”. (In reality, Kaffae offers 3 day free trial). But I’m overall happy it handles the trial end date and when the user gets actually charged clearly in the bottom of the checkout.

6. Stripe sends webhook for checkout information

This is where things get ugly. Stripe gives you a webhook API calls when the session completes.

Preconfiguration

You need to preconfigure them in your Dashboard beforehand of which endpoint Stripe should call. That part is straightforward. You just enter your URL. Then you need to use the webhook token found from the webhook dashboard page to validate the header authorization information, using the Stripe library. I notice you can still read the request’s body text as normal, but it’s still a good idea to authenticate the origin to stay away from the hackers messing with your payment system in the future.

What I didn’t like was Stripe library accepted only raw request body to validate incoming information. Kaffae’s backend uses Express and it is configured to parse every request with json type. If you know Express, it doesn’t like custom endpoint that doesn’t use middleware. In other words, it processes all incoming traffic with JSON first before it gets to each API endpoint. To fix it, I needed to set a weird exception when the HTTP header contains stripe related information very up in the middleware stream to attach raw body arbitrarily to the request object.

Stripe webhook authentication with their webhook token

2 Types of Webooks

At the end of Stripe checkout, Stripe makes 2 calls to your server: session complete and invoice complete. Session complete is guaranteed to be called before the user is redirected back to the checkout complete page. So it’d have been ideal to use that as a flag for payment complete. However, it turned out session complete endpoint carries far little information compared to the invoice. Most of all, it doesn’t contain the invoice number.

Displaying a reference ID seems such a no brainer practice to any modern e-commerce experience to me.

At the same time, while the invoice webhook carried far richer information, it did not have user id information. Without it, there is no way internally to reference this user. What a cumbersome divide.

7. Server stores useful information

After going through annoying timing issues of callbacks, I ended up storing both incoming calls to database and manage each state. One is called subscription that is more stateful and keeps track of user status like trial, active, and canceled. And the other called invoice that is stateless and transactional (it simply logs incoming webhook).

What made it insanely tedious was those 2 APIs come at different timings. While the session complete is guaranteed to be called before the user is redirected back, the invoice complete might come before the session complete is called. As I mentioned, only the session complete has a reference to the actual user. So, I ended up making some wait mechanism until the session complete arrives.

8. User is redirected to the checkout complete page

The user is redirected to the redirect URL you’ve set when creating session id in the step 3. In the redirect URL, you can either set it so that the server endpoint receives the callback and configure information, and redirect the user, or set it to the fronted page and let it handle populating the necessary information with XML request. I did not want to hack the endpoint params and user session just like oauth. So I decided to go with the latter.

At this point, the page should display the reference id, trial period, and product information. I decided to use the invoice number as a reference id as that is how it is referenced in Stripe Dashboard.

It’d have been such a straightforward integration experience, if there was a way to pass invoice related information in success URL as query parameters.

As mentioned in the step 6, the user is redirected back after the session complete is called. It does not care if the invoice has arrived in the server. I ended up making a continuous pull mechanism here too until the invoice arrives in the serverside.

That’s it!

After that, Stripe takes care of trial ending and automatic recurring billing. You can check the user payment status in their dashboard. As much as there’s room for improvement, Stripe offers a very easy experience of implementing subscription model to your apps.

I didn’t write about failure or cancelation in this post. Cancelation was very easy to setup. Failure was just about listening to webhook invoice failed, which in reality I’m skeptical how big of that issue comes for a small SASS product.

From the start to finish, it took me 4 days to test and move Kaffae payment system to production. I’ve tested with my personal credit card, and confirmed it’s working (I gave Stripe the previous 50 cents transaction fee). In such a short period, you can set up a payment accepting website with free trial.

The next challenge would be how to set up the app’s feature so that the users can flawlessly navigate and upgrade to the premium membership.

--

--

Masatoshi Nishimura
Kaffae
Editor for

Maker of Kaffae — remember more from articles you read. NLP enthusiast. UofT grad. Toronto. https://kaffae.com