Skip to content

Latest commit

 

History

History
67 lines (39 loc) · 6.12 KB

README.rdoc

File metadata and controls

67 lines (39 loc) · 6.12 KB

Freemium

The Freemium plugin attempts to encapsulate the Right Way to offer service subscriptions. It is built to handle multiple subscription plans (free, premium, premium plus, etc.), let you control your own invoices, and to interact with any merchant gateway that supports either automated recurring billing or credit card storage.

Freemium is a different beast from ActiveMerchant. Where the latter is optimized for one-off billing of credit cards (as in a retail environment), Freemium is optimized for storage and recurring billing of credit cards. This makes it a much cleaner and more complete solution for handling subscriptions. At the time of this writing, however, Freemium actually depends on ActiveMerchant because of its excellent CreditCard model, which I plan to steal.

This plugin was born out of my attempts to figure out the correct way to handle subscriptions. I decided that the safest/cleanest way was to simply keep track of how far out the subscription had been paid, and when that date came near, bill the subscription again to extend the paid_through date. The approach has turned out well, I think, though I strongly encourage anyone and everyone to review the processes in this plugin to make sure the assumptions it makes are appropriate.

Gateway Requirements

Rule #1: You never want to store credit card numbers yourself. This means that you need a gateway that either provides Automated Recurring Billing (ARB - a common offering) or credit card storage (e.g. TrustCommerce’s Citadel).

Freemium will work with any gateway that provides credit card storage (the preferred method!), but it will not work with every gateway that provides ARB. Just because your gateway provides ARB doesn’t mean that your application can fire-and-forget; you still needs to know about successful transactions (to send invoices) and failed transactions (to send warnings and/or expire a subscription). In order for your application to know about these events without your intervention, the ARB module either needs to send event notifications or it needs to provide an API to retrieve and review recent transactions.

Freemium will only work with ARB modules that provide an API to retrieve and review recent transactions. This is by far the safest route, since most gateways only send email notifications that must be manually processed by a human (ugh!) and the others can have unreliable event notification systems (e.g. PayPal, see talklikeaduck.denhaven2.com/articles/2007/09/02/how-to-cure-the-paypal-subscription-blues). And in any case, ARB modules that send event notifications hardly ever tell you about successful transactions, so you still have to keep track of the periodic cycles so you can send invoices, which makes the whole ARB thing barely useful.

So what we really need is a list of known good and known bad gateways. The list below is just the beginning, off the top of my head.

Good Gateways:

  • TrustCommerce with Citadel (can use Citadel and/or ARB)

  • Braintree Payment Solutions (SecureVault, or ARB)

Probably Good Gateways:

  • Authorize.net (CIM, or ARB if they also offer transaction review API)

Bad Gateways:

  • LoudCommerce’s LinkPoint (no storage, and no transaction review)

Expiration

I’ve tried to build Freemium with the understanding that sometimes a cron task might not run, and if that happens the customers should not get screwed. That means, for example, not expiring a customer account just because a billing process didn’t run. So the process for expiring a subscription is as follows: the first nightly billing process that runs after a subscription’s last paid day will set the final expiration date of that subscription. The final expiration date will be calculated as a certain number of days (the grace period) after the date of the billing process (grace begins when the program knows the account is pastdue). The first billing process that runs on or after the expiration date will then actually expire the subscription.

So there’s some possible slack in the timeline. Suppose a subscription is paid through the 14th and there’s a 2 day grace period. That means if a billing process runs on the 13th, then not until the 15th, the subscription will be set to expire on the 17th - the subscriber gets an extra day of grace because your billing process didn’t run.

Misc

  • If there’s no grace period then the same billing process will both set the expiration date and then actually expire the subscription, thanks to the order of events.

  • Expiring a subscription means downgrading it to a free plan (if any) or removing the plan altogether.

Install

1) Generate and run the migration:

> ./script/generate freemium_migration
> rake db:migrate

2) Populate the database with your subscription plan (create a migration to create SubscriptionPlan records)

> ./script/generate migration populate_subscription_plans

3) Create config/initializers/freemium.rb and configure at least the following:

gateway         pick one, then see rdoc for your gateway's options to see what needs to be configured (api key, etc.)
billing_control set to :full or :arb, depending on whether you're using your gateway's ARB module
grace period    in days, zero days grace is ok
mailer          for customized invoices, etc.

4) Create a SubscriptionsController (or similar) that does whatever it takes to get a unique billing key. This might mean storing the credit card (e.g. TrustCommerce Citadel) and/or setting up automated recurring billing, or getting the three keys from Amazon FPS. Most of these gateways don’t have concrete API classes in Freemium yet. If you write a gateway, let me know and I’ll include it.

5) Create association from your User model (or whatever) to the Subscription model.

6) Add a before_filter (or other logic) to properly enforce your premium plan. The filter should check that the User has an active Subscription to a SubscriptionPlan of the appropriate type.

7) Add ‘/PATH/TO/DEPLOYED/APP/script/runner -e production Subscription.run_billing’ to a daily cron task.

8) Tell me how any of this could be improved. I want this plugin to make freemium billing dead-simple.

Copyright © 2007 Lance Ivy, released under the MIT license