You have unlimited access as a PRO member
You are receiving a free preview of 3 lessons
Your free preview as expired - please upgrade to PRO
Contents
Recent Posts
- Object Oriented Programming With TypeScript
- Angular Elements Advanced Techniques
- TypeScript - the Basics
- The Real State of JavaScript 2018
- Cloud Scheduler for Firebase Functions
- Testing Firestore Security Rules With the Emulator
- How to Use Git and Github
- Infinite Virtual Scroll With the Angular CDK
- Build a Group Chat With Firestore
- Async Await Pro Tips
Stripe Subscription Payments With Firebase Cloud Functions and Angular
Episode 51 written by Jeff DelaneyUpdate! Watch the latest video and get the most up-to-date code by enrolling in the Stripe Payments Master Course on Fireship.io
In this lesson, we are going to build a recurring subscription payment system with Stripe Checkout. It will be able to handle the following tasks.
- Create a Stripe customer on signup.
- Collect credit card details.
- Create subscription and charge the customer.
- Use a Stripe webhook to update the subscription status after a recurring charge is made.
Initial Setup
You must have a basic Firebase user auth system in place and a Stripe account
I also recommend starting with the first Stripe checkout lesson, but it’s not completely necessary.
Add Stripe Checkout to tndex.html
First, add the Stripe checkout library to src/app/index.html
- it will allow us to securely collect credit card payments and transmit them back to Stripe.
<head> |
Register with TypeScript
The StripeCheckout
class is not known to TypeScript, so we need declare it in typings.d.ts
declare var StripeCheckout:any; |
Add API Key to the Angular Environment
Lastly, you should add your Stripe API keys to your environment files. Here I am adding the test key to the development environment in src/environment.ts
.
export const environment = { |
Firebase Data Structure
We are going to keep the subscription information on the /users
node in the database, but you may want to denormalize it if users can have multiple subscriptions. I also found it useful to add a /customers
node that keeps track of the Stripe customer id and the Firebase auth uid for dealing with webhooks.
users |
Subscription Management Component and Service
For simplicity, I am wrapping all subscription functionality into a single component. Optionally, all payment features can be kept in their own feature module.
ng g module payments |
Triggering the Stripe Checkout Modal
In the HTML, we only need a button to trigger the checkout modal.
<button (click)="openHandler()"> |
We can configure the openHandler()
method in the TypeScript. Notice how we are using a callback function processPayment()
from to our service. This saves the token to the db and will be defined in the next step.
import { Component, OnInit } from '@angular/core'; |
payment.service.ts
The service will save the initial token in the database (which triggers the cloud function). We also use the serives to create an Observable of the user’s membership. This will allow us to react to changes to the membership status in realtime.
import { Injectable } from '@angular/core'; |
Updated HTML
Now that we have an observable of the pro-membership, we can go back to the HTML and display the subscription button conditionally based its current status.
<div *ngIf="pmt.membership | async as pro"> |
Configuring Stripe Cloud Functions
We need 3 cloud functions to make this system work and they must be fired sequentially.
- Create stripe customer on signup
- Create the subscription after sending payment
- Update subscription status based on recurring payment webhooks.
Let’s build them step-by-step. First, initialize cloud functions and save your Stripe API key to the cloud functions environment. Sidenote: this part assumes you have Firebase Tools configured in your Angular project.
firebase init functions |
From here, you should have an index.js
to define the functions. Add the following lines to the top of it.
const functions = require('firebase-functions'); |
1. Create the Stripe Customer on Signup
Before we can create a subscription in Stripe, we need to have a customer. The most convenient way to handle this is to create the customer when the user signs up. In this function, we use an auth trigger to create the customer on stripe, then save the customerId
in the Firebase database for later use.
exports.createStripeCustomer = functions.auth.user().onCreate(event => { |
2. Stripe Subscription Cloud Function
After the user enters their card details and the token is updated in the Firebase database, the next step is to create the subscription and charge the credit card for the first payment.
exports.createSubscription = functions.database.ref('/users/{userId}/pro-membership/token').onWrite(event => { |
3. Handle Recurring Payments with Webhooks
A webhook is simply an HTTP endpoint that Stripe can send information to when something important happens. In this example, we want to know when a recurring subscription payment was made and whether it was successful or declined. Stripe will send this information to a Firebase Cloud Function that will update the database with the results.
exports.recurringPayment = functions.https.onRequest((req, res) => { |
Now we need to add this webhook to Stripe from the dashboard. This tells Stripe to send data to this URL each time a subscription charge is made on the user’s account.
Then we can tell stripe to send a test webhook to Firebase Cloud Functions. Make sure to check the function logs for debugging.
The End
There are many other considerations that you should think about to create a robust subscription management system with Stripe. Join our slack team if you want to discuss these topics with experienced developers.
- Changing credit card details.
- Multiple subscription tiers.
- Transactional email for expired or declined cards.
- Show the payment history.