Subscriptions for Rails

This gem helps with building services which have paid subscriptions. It includes the models to store subscription status, and provides integration with PayPal for paid subscriptions.

Assumptions

SubscriptionFu makes the following assumptions on how subscriptions are used:

  • There is a subscription subject, i.e. a user or some other object which needs a subscription in order to access your site. In the examples below we'll use "group".

  • You have a subscription initiator, which is usually the user object. In the examples below we'll use "user"

Installation

Add to your Gemfile:

gem 'subscription_fu', :git => "git://github.com/mobalean/subscription_fu.git"

Run "bundle install".

Then install the required files:

rails g subscription_fu:install

Updating

See UPDATING.md

Configuration

  1. Edit config/initializers/subscription_fu.rb (generated by the install generator)

  2. Add "needs_subscription" to the subscription subject:

    class Group < ActiveRecord::Base
      needs_subscription
      ...
    end
    
  3. Create subscriptions and transactions controllers and views, for example see examples

General subscription flow

  1. The user starts the subscription process by selecting a plan (if multiple ones are available, otherwise you can skip this and just have a subscribe button). We assume you'll do that selection in SubscriptionsController#new.

    link_to image_tag("https://www.paypal.com/ja_JP/JP/i/btn/btn_xpressCheckout.gif", :alt => "PayPal で決済を行う"), subscription_path, :method => :post
    
  2. The subscribe form posts to SubscriptionsController#create, which creates an inactive subscription and associated transaction, and finally redirects the user to a checkout URL:

    @subscription = current_group.build_next_subscription("basic")
    @subscription.save!
    @transaction = @subscription.initiate_activation(current_user)
    redirect_to @transaction.start_checkout(url_for(:action => :confirm, :controller => "transactions"), url_for(:action => :abort, :controller => "transactions"))
    
  3. If the transaction gets approved, the user will get back to TransactionsController#confirm. Otherwise she might not return or return to TransactionsController#abort.

  4. The TransactionsController#confirm is supposed to show the user a final confirmation screen before executing the transaction. To load a pending transaction, use a before filter like this:

    before_filter :require_valid_transaction
    def require_valid_transaction
      @token = params[:token]
      @transaction = current_group.pending_transaction(@token)
      unless @transaction
        logger.info("Invalid transaction for token: #{@token}")
        flash[:error] = "Invalid transaction, please try again."
        redirect_to root_path
      end
    end
    

    The form would look like this: (HAML with simple_form)

    = simple_form_for @transaction, :url => transaction_path do |f|
      = hidden_field_tag :token, @token
      .submit= f.button :submit, '申込む'
    
  5. The confirmation form posts to TransactionsController#update, which completes the transaction:

    if @transaction.complete
      flash[:notice] = "Sucessfully updated your subscription."
    else
      flash[:error] = "Transaction was not successfull, please try again."
    end
    redirect_to root_path
    

That's it.

Using the subscriptions

Once setup, your subscription subject (the group in our example) will get a couple new methods. To check whether or not it has a subscription, use:

group.active_subscription?

For getting the group's plan, you can simply use:

group.subscription_plan

Which will give you an instance of the subscription plan as defined in the initializer.

For more details, see SubscriptionFu::Models