Skip to content
This repository has been archived by the owner on Oct 16, 2018. It is now read-only.

Subscriptions

Pete Keen edited this page Feb 1, 2015 · 44 revisions

Installation

Add Payola to your Gemfile:

gem 'payola-payments'

Run the installer and install the migrations:

$ rails g payola:install
$ rake db:migrate

To create a subscription you first need a SubscriptionPlan model:

$ rails g model SubscriptionPlan \
      amount:integer \
      interval:string \
      stripe_id:string \
      name:string

Make sure you include Payola::Plan:

class SubscriptionPlan < ActiveRecord::Base
  include Payola::Plan
end

A plan model requires a few attributes and has some more optional ones:

  • amount:integer, (attribute) an amount in the format that Stripe expects. For USD this is cents.
  • interval:string, (attribute) one of 'day','week','month', or 'year'
  • stripe_id:string, (attribute) a unique identifier used at Stripe to identify this plan
  • name:string, (attribute) a name describing this plan that will appear on customer invoices
  • interval_count:integer, (attribute) optional the number of intervals between each subscription
  • trial_period_days:integer, (attribute) optional the number of days for the trial period on this plan

Forms

Currently we only support custom forms and the checkout button. Here's an example of a custom subscription form:

 <!-- this header can go in <head> or at the bottom of <body> -->
<%= render 'payola/transactions/stripe_header' %>

<%= form_for @object, url: '/some/controller', method: :post, html: {
      class: 'payola-onestep-subscription-form',
      'data-payola-base-path' => '/payola',
      'data-payola-plan-type' => @plan.plan_class,
      'data-payola-plan-id' => @plan.id
  } do |f| %>
  <span class="payola-payment-error"></span>
  Email:<br>
  <input type="email" name="stripeEmail" data-payola="email"></input><br>
  Card Number<br>
  <input type="text" data-stripe="number"></input><br>
  Exp Month<br>
  <input type="text" data-stripe="exp_month"></input><br>
  Exp Year<br>
  <input type="text" data-stripe="exp_year"></input><br>
  CVC<br>
  <input type="text" data-stripe="cvc"></input><br>
  <input type="submit"></input>
<% end %>

Payola's subscription behavior is triggered by the class payola-onestep-subscription-form on the form and configured with data attributes. There are currently three data attributes that all must be present:

  • payola-base-path is the path where you've mounted Payola in your routes, which is usually /payola.
  • payola-plan-type is the value returned by plan_type on the object that includes Payola::Plan.
  • payola-plan-id is the value returned by id on the object that includes Payola::Plan.

When the customer fills out this form and hits the submit button, Payola will:

  1. Contact Stripe to get a token from the credit card information
  2. POST your form asynchronously (see below for an example controller)
  3. Creates the Stripe::Subscription record asynchronously
  4. On the client, waits for subscription processing to finish before redirecting to the URL specified by SubscriptionPlan#redirect_path. Here's what that should look like:
class SubscriptionPlan < ActiveRecord::Base
  include Payola::Plan

  def redirect_path(subscription)
    # you can return any path here, possibly referencing the given subscription
    '/'
  end
end

Here's what the create action in your subscription controller should look like:

class SubscriptionsController < ApplicationController
  # bring in the `render_payola_status` helper.
  include Payola::StatusBehavior

  def create
    # do any required setup here, including finding or creating the owner object
    owner = current_user # this is just an example for Devise

    # set your plan in the params hash
    params[:plan] = SubscriptionPlan.find_by(id: params[:plan_id])

    # call Payola::CreateSubscription
    subscription = Payola::CreateSubscription.call(params, owner)

    # Render the status json that Payola's javascript expects
    render_payola_status(subscription)
  end
end

Make sure to add it to your config/routes.rb as well:

resources :subscriptions

Checkout Button

To subscribe using the checkout button, use the checkout partial like this:

<%= render 'payola/subscriptions/checkout', plan: YourSubscriptionPlanClass.first %>

This will insert a Stripe Checkout button. The checkout partial has a bunch of options:

  • plan: The plan to subscribe to. Required.
  • button_text: What to put on the button. Defaults to "Subscribe Now"
  • button_class: What class to put on the actual button. Defaults to "stripe-button-el".
  • quantity: The quantity of this subscription. Defaults to 1. (see this and this)
  • name: What to put at the top of the Checkout popup. Defaults to plan.name.
  • description: What to show as the description in the popup. Defaults to plan name + ((the formatted price * quantity) per month).
  • plan_image_path: An image to insert into the Checkout popup. Defaults to blank.
  • panel_label: The label of the button in the Checkout popup.
  • allow_remember_me: Whether to show the Remember me checkbox. Defaults to false.
  • email: Email address to pre-fill. Defaults to blank.
  • custom_fields: Data to pass to the charge_verifier (see Configuration Options)

Canceling Subscriptions

You can add a button to cancel a subscription like this:

<%= render 'payola/subscriptions/cancel', subscription: @subscription %>

Important Note: by default, Payola does no checking to verify that the current user actually has permission to cancel the given subscription. To add that, implement a method in your ApplicationController named payola_can_modify_subscription?, which takes the subscription in question and returns true or false. For Devise this should look something like:

def payola_can_modify_subscription?(subscription)
  subscription.owner == current_user
end

Upgrades / Downgrades

You can upgrade and downgrade subscriptions by POSTing to payola.change_subscription_plan_path(subscription) and passing plan_class and plan_id for the new plan as params. Payola provides a partial for you:

<%= render 'payola/subscriptions/change_plan',
    subscription: @subscription,
    new_plan: @new_plan %>

Important Note: by default, Payola does no checking to verify that the current user actually has permission to modify the given subscription. To add that, implement a method in your ApplicationController named payola_can_modify_subscription, which takes the subscription in question and returns true or false. For Devise this should look something like:

def payola_can_modify_subscription?(subscription)
  subscription.owner == current_user
end

Subscription Coupons

You can pass a coupon code to Payola by adding a data-stripe="coupon" input to your form. The coupon code will be passed directly to Stripe and attached to the subscription.

Subscription Quantity

Currently, a quantity of 1 is passed to Stripe upon creation of a Subscription. If you'd like to pass a different quantity (see this and this for reasons why you might want to do this), add a data-stripe="quantity" input to your form. The quantity will be passed directly to Stripe and attached to the subscription.

Also, if you'd like to update the quantity of the subscription later (e.g. customer adds users to their account, and you charge $/user/month), you can POST a form to payola.change_subscription_quantity_path(subscription.guid) with a quantity parameter, or you can simply call Payola::ChangeSubscriptionQuantity.call(subscription, quantity), where subscription is a Payola::Subscription and quantity is an integer. The latter will bypass Payola's payola_can_modify_subscription? method below, so check for permissions before calling the change directly.

Important Note: by default, Payola does no checking to verify that the current user actually has permission to modify the given subscription. To add that, implement a method in your ApplicationController named payola_can_modify_subscription, which takes the subscription in question and returns true or false. For Devise this should look something like:

def payola_can_modify_subscription?(subscription)
  subscription.owner == current_user
end
Clone this wiki locally