Skip to content

Latest commit

 

History

History
244 lines (158 loc) · 7.05 KB

6_subscriptions.md

File metadata and controls

244 lines (158 loc) · 7.05 KB

Subscriptions

Subscriptions are handled differently by each payment processor. Pay does its best to treat them the same.

Pay stores subscriptions in the Pay::Subscription model. Each subscription has a name that you can use to handle multiple subscriptions per customer.

Creating a Subscription

To subscribe a user, you can call the subscribe method.

@user.payment_processor.subscribe(name: "default", plan: "monthly")

You can pass additional options to go directly to the payment processor's API. For example, the quantity option to subscribe to a plan with for per-seat pricing.

@user.payment_processor.subscribe(name: "default", plan: "monthly", quantity: 3)

Subscribe takes several arguments and options:

  • name - A name for the subscription that's used internally. This allows a customer to have multiple subscriptions. Defaults to "default"
  • plan - The Plan or Price ID to subscribe to. Defaults to "default"
  • quantity - The quantity of the subscription. Defaults to 1
  • trial_period_days - Number of days for the subscription's trial.
  • Other options may be passed and will be sent directly to the payment processor's API.
Paddle Subscriptions

Paddle does not allow you to create a subscription through the API.

Instead, Pay uses webhooks to create the the subscription in the database. The Paddle passthrough parameter is required during checkout to associate the subscription with the correct Pay::Customer.

In your Javascript, include passthrough in Checkout using the Pay::Paddle.passthrough helper.

Paddle.Checkout.open({
  product: 12345,
  passthrough: "<%= Pay::Paddle.passthrough(owner: current_user) %>"
});

Or with Paddle Button Checkout:

<a href="#!" class="paddle_button" data-product="12345" data-email="<%= current_user.email %>" data-passthrough="<%= Pay::Paddle.passthrough(owner: current_user) %>"
Paddle Passthrough Helper

Pay provides a helper method for generating the passthrough JSON object to associate the purchase with the correct Rails model.

Pay::Paddle.passthrough(owner: current_user, foo: :bar)
#=> { owner_sgid: "xxxxxxxx", foo: "bar" }

# To generate manually without the helper
#=> { owner_sgid: current_user.to_sgid.to_s, foo: "bar" }.to_json

Pay uses a signed GlobalID to ensure that the subscription cannot be tampered with.

When processing Paddle webhooks, Pay parses the passthrough JSON string and verifies the owner_sgid hash in order to find the correct Pay::Customer record.

The passthrough parameter owner_sgid is only required for creating a subscription.

Retrieving a Subscription from the Database

@user.payment_processor.subscription(name: "default")

Subscription Trials

There are two types of trials for subscriptions: with or without a payment method upfront.

Stripe is the only payment processor that allows subscriptions without a payment method. Braintree and Paddle require a payment method on file to create a subscription.

Trials Without Payment Method

To create a trial without a card, we can use the Fake Processor to create a subscription with matching trial and end times.

time = 14.days.from_now
@user.set_payment_processor :fake_processor, allow_fake: true
@user.payment_processor.subscribe(trial_ends_at: time, ends_at: time)

This will create a fake subscription in our database that we can use. Once expired, the customer will need to subscribe using a real payment processor.

@user.payment_processor.on_generic_trial?
#=> true
Trials with Payment Method required

Braintree and Paddle require payment methods before creating a subscription.

@user.set_payment_processor :braintree
@user.payment_processor.payment_method_token = params[:payment_method_token]
@user.payment_processor.subscribe()

Checking Customer Subscribed Status

@user.payment_processor.subscribed?

You can also check for a specific subscription or plan:

@user.payment_processor.subscribed?(name: "default", plan: "monthly")

Checking Customer Trial Status

You can check if the user is on a trial by simply asking:

@user.payment_processor.on_trial?
#=> true or false

You can also check if the user is on a trial for a specific subscritpion name or plan.

@user.payment_processor.on_trial?(name: 'default', plan: 'plan')
#=> true or false

Checking Customer Trial Or Subscribed Status

For paid features of your app, you'll often want to check if the user is on trial OR subscribed. You can use this method to check both at once:

@user.payment_processor.on_trial_or_subscribed?

You can also check for a specific subscription or plan:

@user.payment_processor.on_trial_or_subscribed?(name: "default", plan: "annual")

Subscription API

Individual subscriptions provide similar helper methods to check their state.

Checking a Subscription's Trial Status

@user.payment_processor.subscription.on_trial? #=> true or false

Checking a Subscription's Cancellation Status

@user.payment_processor.subscription.cancelled? #=> true or false

Checking if a Subscription is on Grace Period

@user.payment_processor.subscription.on_grace_period? #=> true or false

Checking if a Subscription is Active

@user.payment_processor.subscription.active? #=> true or false

Checking if a Subscription is Paused

@user.payment_processor.subscription.paused? #=> true or false

Cancel a Subscription (At End of Billing Cycle)

@user.payment_processor.subscription.cancel
Paddle

In addition to the API, Paddle provides a subscription Cancel URL that you can redirect customers to cancel their subscription.

@user.payment_processor.subscription.paddle_cancel_url

Cancel a Subscription Immediately

@user.payment_processor.subscription.cancel_now!

Pause a Subscription (Paddle only)

@user.payment_processor.subscription.pause

Swap a Subscription to another Plan

If a user wishes to change subscription plans, you can pass in the Plan or Price ID into the swap method:

@user.payment_processor.subscription.swap("yearly")

Braintree does not allow this via their API, so we cancel and create a new subscription for you (including proration discount).

Resume a Subscription

A user may wish to resume their canceled (or paused) subscription. You can resume a subscription with:

@user.payment_processor.subscription.resume
Stripe or Braintree Subscription (on Grace Period)

With Stripe or Braintree, a subscription on grace period may be resumed:

Paddle (Paused)

With Paddle, you may resume a paused subscription:

Retrieving the raw Subscription object from the Processor

@user.payment_processor.subscription.processor_subscription
#=> #<Stripe::Subscription>

Next

See Webhooks