/pay

A subscription engine for Ruby on Rails.

Primary LanguageRubyMIT LicenseMIT

Pay - Payments engine for Ruby on Rails

Build Status

Pay is a payments engine for Ruby on Rails 4.2 and higher.

Current Payment Providers

  • Stripe (API version 2018-08-23 or higher required)
  • Braintree

Want to add a new payment provider? Contributions are welcome and the instructions are here.

Installation

Add this line to your application's Gemfile:

gem 'pay'

And then execute:

$ bundle

Or install it yourself as:

$ gem install pay

Setup

Migrations

This engine will create a subscription model and the neccessary migrations for the model you want to make "billable." The most common use case for the billable model is a User.

To add the migrations to your application, run the following migration:

$ bin/rails pay:install:migrations

This will install two migrations:

  • db/migrate/create_subscriptions.rb
  • db/migrate/add_fields_to_users.rb

Non-User Model

If you need to use a model other than User, check out the wiki page.

Run the Migrations

Finally, run the migrations with $ rake db:migrate

Stripe

You'll need to add your private Stripe API key to your Rails secrets config/secrets.yml, credentials rails credentials:edit

development:
  stripe:
    private_key: xxxx
    public_key: yyyy
    signing_secret: zzzz

You can also use the STRIPE_PRIVATE_KEY and STRIPE_SIGNING_SECRET environment variables.

Usage

Include the Pay::Billable module in the model you want to know about subscriptions.

# app/models/user.rb
class User < ActiveRecord::Base
  include Pay::Billable
end

To see how to use Stripe Elements JS & Devise, click here.

Configuration

You can create an initializer config/initializers/pay.rb

Pay.setup do |config|
  config.billable_class = 'User'
  config.billable_table = 'users'

  config.chargeable_class = 'Pay::Charge'
  config.chargeable_table = 'charges'

  # For use in the receipt/refund/renewal mailers
  config.business_name = "Business Name"
  config.business_address = "1600 Pennsylvania Avenue NW"
  config.application_name = "My App"
  config.support_email = "helpme@example.com"

  config.send_emails = true
end

This allows you to create your own Charge class for instance, which could add receipt functionality:

class Charge < Pay::Charge
  def receipts
    # do some receipts stuff using the https://github.com/excid3/receipts gem
  end
end

Pay.setup do |config|
  config.chargeable_class = 'Charge'
end

Emails

Stripe

Emails can be enabled/disabled using the send_emails configuration option (enabled per default). When enabled, the following emails will be sent:

  • When a charge succeeded
  • When a charge was refunded
  • When a subscription is about to renew

User API

Trials

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

user = User.find_by(email: 'michael@bluthcompany.co')
user.on_trial?
#=> true or false

Generic Trials

Trials that don't require cards upfront simply

user = User.create(
  email: 'michael@bluthcompany.co',
  trial_ends_at: 30.days.from_now
)

user.on_generic_trial?
#=> true

Creating a Charge

user = User.find_by(email: 'michael@bluthcompany.co')
user.processor = 'stripe'
user.card_token = 'stripe-token'
user.charge(1500) # $15.00 USD

user = User.find_by(email: 'michael@bluthcompany.co')
user.processor = 'braintree'
user.card_token = 'nonce'
user.charge(1500) # $15.00 USD

The charge method takes the amount in cents as the primary argument.

You may pass optional arguments that will be directly passed on to either Stripe or Braintree. You can use these options to charge different currencies, etc.

Creating a Subscription

user = User.find_by(email: 'michael@bluthcompany.co')
user.processor = 'stripe'
user.card_token = 'stripe-token'
user.subscribe

A card_token must be provided as an attribute.

The subscribe method has three optional arguments with default values.

def subscribe(name: 'default', plan: 'default')
  ...
end
Name

Name is an internally used name for the subscription.

Plan

Plan is the plan ID from the payment processor.

Retrieving a Subscription from the Database

user = User.find_by(email: 'gob@bluthcompany.co')
user.subscription

Checking a User's Subscription Status

user = User.find_by(email: 'george.senior@bluthcompany.co')
user.subscribed?

The subscribed? method has two optional arguments with default values.

def subscribed?(name: 'default', plan: nil)
  ...
end
Name

Name is an internally used name for the subscription.

Plan

Plan is the plan ID from the payment processor.

Processor

Processor is the string value of the payment processor subscription. Pay currently only supports Stripe, but other implementations are welcome.

Retrieving a Payment Processor Account

user = User.find_by(email: 'george.michael@bluthcompany.co')
user.customer

Updating a Customer's Credit Card

user = User.find_by(email: 'tobias@bluthcompany.co')
user.update_card('stripe-token')

Retrieving a Customer's Subscription from the Processor

user = User.find_by(email: 'lucille@bluthcompany.co')
user.processor_subscription(subscription_id)

Subscription API

Checking a Subscription's Trial Status

user = User.find_by(email: 'lindsay@bluthcompany.co')
user.subscription.on_trial?

Checking a Subscription's Cancellation Status

user = User.find_by(email: 'buster@bluthcompany.co')
user.subscription.cancelled?

Checking a Subscription's Grace Period Status

user = User.find_by(email: 'her?@bluthcompany.co')
user.subscription.on_grace_period?

Checking to See If a Subscription Is Active

user = User.find_by(email: 'carl.weathers@bluthcompany.co')
user.subscription.active?

Cancel a Subscription (At End of Billing Cycle)

user = User.find_by(email: 'oscar@bluthcompany.co')
user.subscription.cancel

Cancel a Subscription Immediately

user = User.find_by(email: 'annyong@bluthcompany.co')
user.subscription.cancel_now!

Swap a Subscription to another Plan

user = User.find_by(email: 'steve.holt@bluthcompany.co')
user.subscription.swap("yearly")

Resume a Subscription on a Grace Period

user = User.find_by(email: 'steve.holt@bluthcompany.co')
user.subscription.resume

Retrieving the Subscription from the Processor

user = User.find_by(email: 'lucille2@bluthcompany.co')
user.subscription.processor_subscription

Contributors

Contributing

👋 Thanks for your interest in contributing. Feel free to fork this repo.

If you have an issue you'd like to submit, please do so using the issue tracker in GitHub. In order for us to help you in the best way possible, please be as detailed as you can.

If you'd like to open a PR please make sure the following things pass:

  • rake test
  • rubocop

These will need to be passing in order for a Pull Request to be accepted.

License

The gem is available as open source under the terms of the MIT License.