Skip to content

Latest commit

 

History

History
238 lines (174 loc) · 11.8 KB

Stripe Subscription.md

File metadata and controls

238 lines (174 loc) · 11.8 KB

Apollo Universal Starter Kit Payments Module with Stripe

The Apollo Universal Starter Kit payments module is a great starting point when you want to charge users for access to paid features or services available through your application. With the starter kit payments module, you can develop the recurring billing functionality more rapidly than if you would have started from scratch.

The payment module is based on a popular payment processor Stripe, and the module provides an example of using Stripe subscriptions in a real production application. Moreover, the payments module also implements specific functionality to help you simulate a real production-ready payment service in development mode as well thanks to stripe-local, a simple JavaScript library.

The payments module code is located under the packages/server/src/modules/payments/stripe/ directory. (When talking about the payments module files, we'll omit the long packages/server/src/modules/payments/ part for brevity, and will simply start the path with stripe/. If a path doesn't start with stripe/, you should look for a respective file or directory from the project root.)

Running the App in Development Mode

  1. Sign in to Stripe Dashboard.

  2. Enable the subscription module in config/stripe/subscription.js by setting the stripe.subscription.enable property to true:

export default {
  enabled: true,
  // other code is omitted for brevity
};
  1. Replace process.env.STRIPE_PUBLIC_KEY with your Stripe publishable key for development mode in config/stripe/subscription.js:
export default {
   enabled: true,
   publicKey: process.env.STRIPE_PUBLIC_KEY, // Set to your 'Stripe_publishable_key' for development mode
};
  1. Add your [Stripe secret key] into the packages/server/.env file:
# Stripe
STRIPE_SECRET_KEY="your_Stripe_secret_key"

NOTE: In packages/server/.env, you'll also see the STRIPE_ENDPOINT_SECRET environment variable. You don't need to set this variable to run the application in development mode. You need to specify STRIPE_ENDPOINT_SECRET only when you're deploying your Apollo Starter Kit-based application. For more information about deployment, consult the deployment section.

  1. Run yarn stripe:setup from the root project directory.

This command will create a product and plan using the Stripe API according to the default subscription plan and product configured in the config/stripe/subscription.js file.

  1. Start the application:
yarn seed && yarn watch

NOTE: If you're already using Apollo Universal Starter Kit, we recommend that you run yarn migrate instead of yarn seed. Otherwise, the data that's already stored in the database will be overwritten.

  1. Sign in to the application with the email user@example.com and password user1234.

(Apollo Universal Starter Kit provides two demo users; their login details can be found on the /login page in the application. You can also create a new user to subscribe.)

  1. Visit the /subscriber-page page and subscribe. The subscription page provides a few test credit cards that you can use to test Stripe subscription.

  2. Once the payment is processed, visit /subscriber-page again to view the secret number. The subscription information is available on the /profile page.

Implemented Stripe Subscription Features

The payments module in Apollo Universal Starter Kit provides a few features to help you build your specific payments functionality upon them for your particular application.

Currently, Apollo Universal Starter Kit includes the following payments features:

  • Subscription cancellation
  • A default monthly subscription plan
  • Editing credit card details in the user profile
  • Authentication of subscription endpoints on the server
  • Notification functionality for canceled or failed payments
  • Integration with Stripe Elements in React for the web application
  • Integration with React Native Credit Card Input for the mobile app
  • Creation of subscriptions products and plans from the command line with yarn stripe:setup
  • Integration with stripe-local to query Stripe for events and to post them to the webhook endpoint
  • Protection of application routes with SubscriptionRoute (non-subscribers are redirected to the subscription page)

Webhook

The Apollo Starter Kit payments module uses our custom webhook middleware for Express to handle requests from Stripe and to notify users about any changes to their subscription. You can have a look at the stripe/subscription/webhook.ts file for the code that manages requests and notifies users about subscription changes.

Currently, Apollo Universal Starter Kit supports two Stripe events:

  • customer.subscription.deleted. If the user exists in the database, then the application deletes the source from Stripe and updates the database. After that, an email is sent to the user to confirm the cancellation.
  • invoice.payment_failed. An email will be sent to the user if their payment failed.

Simulation of Full Subscription Functionality in Development Mode

If you've already used Stripe, you might know that Stripe doesn't allow you to get subscription information if you're running the application in development mode.

In a production application, upon any changes of the subscription status, Stripe sends requests to the endpoint – a webhook – that you registered with Stripe. These requests typically contain data about the subscription cancellation or payment failure, and you need to handle these events in your production application.

The described flow, however, is only possible in a production application with a real domain.

When you work on your application in development mode, Stripe simply can't send any data to localhost:port (in fact, Stripe still sends requests to the webhook that you registered, but the requests will never reach your application).

Therefore, in order to get full subscription functionality – to be able to test various payment problems in development mode – we integrated a small library stripe-local into the Apollo Starter Kit payments module.

stripe-local sends requests to Stripe every 15 seconds to verify if any new events were registered when you tried to subscribe in development mode. If there are any new events, stripe-local will get them and send them to your application on localhost:port. Simply put, you can consider stripe-local as a proxy between your application and Stripe.

Notification flow between Stripe and your application in development flow with the stripe-local library

Configuring stripe-local

You can change the stripe-local options in the stripe/subscription/index.ts file. As shown in the example below, you can add the stripe-local properties to the object attribute passed to stripeLocal():

// Other code is omitted
import stripeLocal from 'stripe-local';

if (__DEV__ && enabled && process.env.STRIPE_SECRET_KEY) {
  log.debug('Starting stripe-local proxy');
  stripeLocal({
    secretKey: process.env.STRIPE_SECRET_KEY,
    webhookUrl: `http://localhost:${__SERVER_PORT__}${webhookUrl}`
  });
}
// Other code is omitted

Subscription Module Settings

To use the payments module, you need to add your Stripe keys into the packages/server/.env file and configure the module in the config/stripe/subscription.js file.

First, add your Stripe secret and endpoint keys to the packages/server/.env file:

# Stripe API keys
STRIPE_SECRET_KEY=
STRIPE_ENDPOINT_SECRET=

To configure the payments module, you can change the settings listed in the table below in config/stripe/subscription.js:

Property Value Purpose
enabled Boolean Enables or disables the payments module. Defaults to false
webhookUrl String Stores the URL for the webhook that you registered with Stripe
publicKey String Stores the publishable key generated by Stripe for your application
product Object Stores the product properties. Consult Stripe documentation for product
plan Object Stores the subscription plan. Consult Stripe documentation for plan

Deployment with Apollo Starter Kit Payments Module

  1. Create a webhook endpoint in the Stripe dashboard. The webhook URLs that are set in the Stripe dashboard and in the config/stripe/subscription.js file must be the same.

By default, webhookUrl is set to /stripe/webhook in config/stripe/subscription.js, therefore, in the Stripe dashboard you need to set the webhook endpoint to https://your-website-name.com/stripe/webhook. Otherwise, use your own URLs.

  1. Add your live publishable key from Stripe into config/stripe/subscription.js.

  2. Add your live secret key from Stripe into packages/server/.env.

  3. Add the Stripe secret endpoint key from your Stripe webhook (webhook signatures) in packages/server/.env to prevent fraudulent webhooks from being processed.

  4. Run yarn stripe:setup from the root directory of Apollo Starter kit to create a subscription plan and product. The default plan and product are configured in the config/stripe/subscription.js file.

  5. Deploy your application.

Deployment to Heroku

  1. Create a webhook endpoint in Stripe Dashboard. The webhook URLs that are set in the Stripe dashboard and the config/stripe/subscription.js file must be the same.

By default, webhookUrl is set to /stripe/webhook in config/stripe/subscription.js. Therefore, in the Stripe dashboard you need to set the webhook endpoint to https://your-website-name.com/stripe/webhook. Otherwise, use your own URLs.

  1. Add your live publishable key, secret key, and secret endpoint key from Stripe to your deployment configuration variables in Heroku Dashboard.
Variable Value
STRIPE_PUBLIC_KEY 'your_public_key'
STRIPE_SECRET_KEY 'your_secret_key'
STRIPE_ENDPOINT_SECRET 'your_secret_endpoint_key'

STRIPE_ENDPOINT_SECRET is the secret endpoint key that's necessary to prevent fraudulent webhooks from being processed. You can consult webhook signatures for more information about the secret endpoint key.

NOTE: The command yarn stripe:setup will be run automatically by Heroku to create a subscription plan and product using the Stripe API. The default plan and product are configured in the config/stripe/subscription.js file.

  1. Deploy your application.