Jumpstart docs logo Back to the app

Billing

Jumpstart uses the Pay gem for handling payments and billing.

Accepting Payments

Jumpstart Pro supports using Stripe, Braintree, or a combination of the two for payments and is configured for monthly and yearly subscriptions out of the box. PayPal is supported through the Braintree integration and may be used entirely on its own or in combination with the Braintree credit card form.

Each subscription is attached to a Account, which allows us to offer multiple subscriptions like GitHub, should you wish to use that.

You may also use the payments functionality in Jumpstart Pro to process one-time payments instead. In fact, that's what we're using on our website to sell Jumpstart Pro!

Strong Customer Authentication (SCA)

Jumpstart and the Pay gem payments using Stripe are Strong Customer Authentication (SCA) compatible. We provide authentication for setting up new cards and will email customers when a subscription payment requires additional authentication.

We use the Stripe CLI to use webhooks to keep subscriptions and payments up-to-date in our application now. This is required to handle SCA payments that require authentication.

Subscriptions

Subscriptions in Jumpstart Pro are billed against a Account, not a User. This allows you to handle various different billing situations.

To subscribe an individual, they just need to be logged in as their personal account and the subscription will be billed to them.

Account billing allows you to share resources and billing functionality with the entire account and allows any member to manage the subscription. It's much easier to start with account billing support than adding it later, so we've got you covered even if you don't need it right away.

For more information on how accounts work in Jumpstart Pro, check out the Accounts documentation.

Defining Plans

Plans can be defined in the Plans Admin and allows for changes without deploying code. Each plan should be defined with the price amount in cents.

The Stripe and Braintree IDs are used to subscribe the user to the matching plan defined inside Stripe or Braintree.

Stripe IDs may either be a Plan ID or a Price ID.

Free Plans

There are two types of "free" plans:

  1. Users who don't pay for your app
  2. Users who get free access to paid features

For users who use your app for free, they don't need a plan or a subscription. These are just regular users of your app. If they're subscribed, they can access the premium features. If not, they can have access to any free features you want. Technically, they're not subscribed to a "free plan", but you can make the app look and feel like it.

For users who get free access to paid features, you can assign them a subscription to a free plan. Jumpstart Pro comes with a free plan that can be used for this purpose and is applied automatically to Admin users who are created in the Jumpstart Config area.

# Ensure Jumpstart free plan exists for admin users
  Plan.where(name: "Free").first_or_create(hidden: true, amount: 0, currency: :usd, interval: :month, trial_period_days: 0, fake_processor_id: :free)

  # Create a fake subscription for the admin user so they have access to everything by default
  account = user.accounts.first
  account.set_payment_processor :fake_processor, allow_fake: true
  account.payment_processor.subscribe

Trials

Generic trials are trials without a card or subscription plan. These can be configured in app/models/account.rb by uncommenting the before_create block. You can check if an account is on generic trial with account.on_generic_trial?.

Subscription trials are trials that require both a card upfront and a subscription plan selected. You can simply add trial_period_days when creating a Plan in the admin. When the subscription is created, the trial_period_days will be passed along to Stripe and Braintree for adding a trial to the subscription.

Require a subscription

require_subscription! is a method defined within the SubscriptionStatus module under the Accounts module. This method is intended to be used as a before_action filter in Rails controllers to ensure that only subscribed users can access certain actions.

When require_subscription! is called, it checks whether the current user is signed in and whether they are subscribed. If the user is not subscribed, they will be redirected to the pricing page.

In this example, the premium_features action can only be accessed by users who are subscribed. If a user who is not subscribed tries to access this action, they will be redirected to the pricing page.

    
      class ProductsController < ApplicationController
        before_action :require_subscription!, only: [:premium_features]

        def index
          # ...
        end

        def premium_features
          # Only accessible by subscribed users
        end

        # ...
      end
    
  

Stripe

Processing payments with Stripe is as simple as adding your Stripe credentials, enabling the Stripe configuration, and adding plans with Stripe IDs on them.

Stripe Webhooks

The /webhooks/stripe endpoint is available in your application for handling webhooks from Stripe. You can add the webhook to Stripe to have it process activity from your Stripe account.

Stripe CLI

Jumpstart now requires webhooks to support SCA. You must use the Stripe CLI to forward webhooks to your local Rails server to process subscriptions and payments with SCA.

stripe login
stripe listen --forward-to localhost:5000/webhooks/stripe

Once stripe CLI is running it should display your signing secret. Add it to your credentials to make sure your server can receive stripe events.

Alternatively, you can use ngrok or localtunnel to expose your Rails server to the internet so it can receive webhooks.

Braintree

Processing payments with Braintree is as simple as adding your Braintree credentials, enabling the Braintree configuration, and adding plans with the Braintree IDs on them. We handle all the heavy lifting such as calculation proration discounts to allow users to swap between monthly and yearly plans which Braintree does not support out of the box.

Plan Credit Discount

Before using Braintree, you will need to define a plan-credit discount in your Braintree control panel. This discount will be used to properly prorate subscriptions that change from yearly to monthly billing, or from monthly to yearly billing.

The discount amount configured in the Braintree control panel can be any value you wish, as Pay will override the defined amount with our own custom amount each time we apply the coupon. This coupon is needed since Braintree does not natively support prorating subscriptions across subscription frequencies.

Braintree Webhooks

The /webhooks/braintree endpoint is available in your application for handling webhooks from Braintree. You can add the webhook to Braintree to have it

PayPal

PayPal is supported out of the box using Braintree for processing.

To enable PayPal in Jumpstart, you'll first need to enable it in your Braintree account under the Processing Options section.

Jumpstart supports two PayPal configurations:

  1. PayPal inside Braintree's Drop-In UI
  2. Standalone PayPal button

The Braintree Drop-In UI is a widget like Stripe elements that handles all the various enabled payment options. If you wish to process both credit cards and PayPal through Braintree, this is the best option.

The Standalone PayPal button is designed for users who want to use PayPal with Stripe or by itself. This embeds a PayPal checkout button in the form without using the Braintree Drop-In UI. It still uses the Braintree Javascript to do this, but without the credit card form.

One-time Payments

If you want to sell products that are one-time purchases, you can use the payment forms from Jumpstart Pro to do this.

The easiest way to do this is to have a user put their card in first and then show them the checkout form.

An example from the Jumpstart Pro website when purchasing a license: We check if the current account has a card on file, if so we let you purchase a license. If not, we display the card form.

<% if !current_account.payment_processor&.default_payment_method %>
  <p>First, add a payment method to your account:

<%= render 'payment_methods/forms/stripe' if Jumpstart.config.stripe? %> <%= render 'payment_methods/forms/braintree' if Jumpstart.config.braintree? %> <%= render 'payment_methods/forms/paypal' if Jumpstart.config.paypal? %> <% else %> <%= render 'form', license: @license %> <% end %>

Then on the LicenseController create action, we use current_account.charge(amount) from Pay to issue the charge before creating the license.

Switching Payment Processors

A user cannot switch payment processors during their subscription. For example, switching from Stripe to Braintree. They must cancel and resubscribe to switch payment providers.