|
| 1 | +# Laravel Cashier |
| 2 | + |
| 3 | +- [Introduction](#introduction) |
| 4 | +- [Configuration](#configuration) |
| 5 | +- [Subscribing To A Plan](#subscribing-to-a-plan) |
| 6 | +- [No Card Up Front](#no-card-up-front) |
| 7 | +- [Swapping Subscriptions](#swapping-subscriptions) |
| 8 | +- [Subscription Quantity](#subscription-quantity) |
| 9 | +- [Cancelling A Subscription](#cancelling-a-subscription) |
| 10 | +- [Resuming A Subscription](#resuming-a-subscription) |
| 11 | +- [Checking Subscription Status](#checking-subscription-status) |
| 12 | +- [Handling Failed Payments](#handling-failed-payments) |
| 13 | +- [Invoices](#invoices) |
| 14 | + |
| 15 | +<a name="introduction"></a> |
| 16 | +## Introduction |
| 17 | + |
| 18 | +Laravel Cashier provides an expressive, fluent interface to [Stripe's](https://stripe.com) subscription billing services. It handles almost all of the boilerplate subscription billing code you are dreading writing. In addition to basic subscription management, Cashier can handle coupons, swapping subscription, subscription "quantites", cancellation grace periods, and even generate invoice PDFs. |
| 19 | + |
| 20 | +<a name="configuration"></a> |
| 21 | +## Configuration |
| 22 | + |
| 23 | +#### Composer |
| 24 | + |
| 25 | +First, add the Cashier package to your `composer.json` file: |
| 26 | + |
| 27 | + "laravel/cashier": "~2.0" |
| 28 | + |
| 29 | +#### Service Provider |
| 30 | + |
| 31 | +Next, register the `Laravel\Cashier\CashierServiceProvider` in your `app` configuration file. |
| 32 | + |
| 33 | +#### Migration |
| 34 | + |
| 35 | +Before using Cashier, we'll need to add several columns to your database. Don't worry, you can use the `cashier:table` Artisan command to create a migration to add the necessary column. Once the migration has been created, simply run the `migrate` command. |
| 36 | + |
| 37 | +#### Model Setup |
| 38 | + |
| 39 | +Next, add the BillableTrait and appropriate date mutators to your model definition: |
| 40 | + |
| 41 | + use Laravel\Cashier\BillableTrait; |
| 42 | + use Laravel\Cashier\BillableInterface; |
| 43 | + |
| 44 | + class User extends Eloquent implements BillableInterface { |
| 45 | + |
| 46 | + use BillableTrait; |
| 47 | + |
| 48 | + protected $dates = ['trial_ends_at', 'subscription_ends_at']; |
| 49 | + |
| 50 | + } |
| 51 | + |
| 52 | +#### Stripe Key |
| 53 | + |
| 54 | +Finally, set your Stripe key in one of your bootstrap files: |
| 55 | + |
| 56 | + User::setStripeKey('stripe-key'); |
| 57 | + |
| 58 | +<a name="subscribing-to-a-plan"></a> |
| 59 | +## Subscribing To A Plan |
| 60 | + |
| 61 | +Once you have a model instance, you can easily subscribe that user to a given Stripe plan: |
| 62 | + |
| 63 | + $user = User::find(1); |
| 64 | + |
| 65 | + $user->subscription('monthly')->create($creditCardToken); |
| 66 | + |
| 67 | +If you would like to apply a coupon when creating the subscription, you may use the `withCoupon` method: |
| 68 | + |
| 69 | + $user->subscription('monthly') |
| 70 | + ->withCoupon('code') |
| 71 | + ->create($creditCardToken); |
| 72 | + |
| 73 | +The `subscription` method will automatically create the Stripe subscription, as well as update your database with Stripe customer ID and other relevant billing information. |
| 74 | + |
| 75 | +If your plan has a trial period, make sure to set the trial end date on your model after subscribing: |
| 76 | + |
| 77 | + $user->trial_ends_at = Carbon::now()->addDays(14); |
| 78 | + |
| 79 | + $user->save(); |
| 80 | + |
| 81 | +<a name="no-card-up-front"></a> |
| 82 | +## No Card Up Front |
| 83 | + |
| 84 | +If your application offers a free-trial with no credit-card up front, set the `cardUpFront` property on your model to `false`: |
| 85 | + |
| 86 | + protected $cardUpFront = false; |
| 87 | + |
| 88 | +On account creation, be sure to set the trial end date on the model: |
| 89 | + |
| 90 | + $user->trial_ends_at = Carbon::now()->addDays(14); |
| 91 | + |
| 92 | + $user->save(); |
| 93 | + |
| 94 | +<a name="swapping-subscriptions"></a> |
| 95 | +## Swapping Subscriptions |
| 96 | + |
| 97 | +To swap a user to a new subscription, use the `swap` method: |
| 98 | + |
| 99 | + $user->subscription('premium')->swap(); |
| 100 | + |
| 101 | +If the user is on trial, the trial will be maintained as normal. Also, if a "quantity" exists for the subscription, that quantity will also be maintained. |
| 102 | + |
| 103 | +<a name="subscription-quantity"></a> |
| 104 | +## Subscription Quantity |
| 105 | + |
| 106 | +Sometimes subscriptions are affected by "quantity". For example, your application might charge $10 per month per user on an account. To easily increment or decrement your subscription quantity, use the `increment` and `decrement` methods: |
| 107 | + |
| 108 | + $user = User::find(1); |
| 109 | + |
| 110 | + $user->subscription()->increment(); |
| 111 | + |
| 112 | + // Add five to the subscription's current quantity... |
| 113 | + $user->subscription()->increment(5) |
| 114 | + |
| 115 | + $user->subscription->decrement(); |
| 116 | + |
| 117 | + // Subtract five to the subscription's current quantity... |
| 118 | + $user->subscription()->decrement(5) |
| 119 | + |
| 120 | +<a name="cancelling-a-subscription"></a> |
| 121 | +## Cancelling A Subscription |
| 122 | + |
| 123 | +Cancelling a subscription is a walk in the park: |
| 124 | + |
| 125 | + $user->subscription()->cancel(); |
| 126 | + |
| 127 | +When a subscription is cancelled, Cashier will automatically set the `subscription_ends_at` column on your database. This column is used to know when the `subscribed` method should begin returning `false`. For example, if a customer cancels a subscription on March 1st, but the subscription was not scheduled to end until March 5th, the `subscribed` method will continue to return `true` until March 5th. |
| 128 | + |
| 129 | +<a name="resuming-a-subscription"></a> |
| 130 | +## Resuming A Subscription |
| 131 | + |
| 132 | +If a user has cancelled their subscription and you wish to resume it, use the `resume` method: |
| 133 | + |
| 134 | + $user->subscription('monthly')->resume($creditCardToken); |
| 135 | + |
| 136 | +If the user cancels a subscription and then resumes that subscription before the subscription has fully expired, they will not be billed immediately. Their subscription will simply be re-activated, and they will be billed on the original billing cycle. |
| 137 | + |
| 138 | +<a name="checking-subscription-status"></a> |
| 139 | +## Checking Subscription Status |
| 140 | + |
| 141 | +To verify that a user is subscribed to your application, use the `subscribed` command: |
| 142 | + |
| 143 | + if ($user->subscribed()) |
| 144 | + { |
| 145 | + // |
| 146 | + } |
| 147 | + |
| 148 | +The `subscribed` method makes a great candidate for a route filter: |
| 149 | + |
| 150 | + Route::filter('subscribed', function() |
| 151 | + { |
| 152 | + if (Auth::user() && ! Auth::user()->subscribed()) |
| 153 | + { |
| 154 | + return Redirect::to('billing'); |
| 155 | + } |
| 156 | + }); |
| 157 | + |
| 158 | +You may also determine if the user is still within their trial period (if applicable) using the `onTrial` method: |
| 159 | + |
| 160 | + if ($user->onTrial()) |
| 161 | + { |
| 162 | + // |
| 163 | + } |
| 164 | + |
| 165 | +To determine if the user was once an active subscriber, but has cancelled their subscription, you may use the `cancelled` method: |
| 166 | + |
| 167 | + if ($user->cancelled()) |
| 168 | + { |
| 169 | + // |
| 170 | + } |
| 171 | + |
| 172 | +You may also determine if a user has cancelled their subscription, but are still on their "grace period" until the subscription fully expires. For example, if a user cancels a subscription on March 5th that was scheduled to end on March 10th, the user is on their "grace period" until March 10th. Note that the `subscribed` method still returns `true` during this time. |
| 173 | + |
| 174 | + if ($user->onGracePeriod()) |
| 175 | + { |
| 176 | + // |
| 177 | + } |
| 178 | + |
| 179 | +The `everSubscribed` method may be used to determine if the user has ever subscribed to a plan in your application: |
| 180 | + |
| 181 | + if ($user->everSubscribed()) |
| 182 | + { |
| 183 | + // |
| 184 | + } |
| 185 | + |
| 186 | +<a name="handling-failed-payments"></a> |
| 187 | +## Handling Failed Payments |
| 188 | + |
| 189 | +What if a customer's credit card expires? No worries - Cashier includes a Webhook controller that can easily cancel the customer's subscription for you. Just point a route to the controller: |
| 190 | + |
| 191 | + Route::post('stripe/webhook', 'Laravel\Cashier\WebhookController@handleWebhook'); |
| 192 | + |
| 193 | +That's it! Failed payments will be captured and handled by the controller. The controller will cancel the customer's subscription after three failed payment attempts. The `stripe/webhook` URI in this example is just for example. You will need to configure the URI in your Stripe settings. |
| 194 | + |
| 195 | +If you have additional Stripe webhook events you would like to handle, simply extend the Webhook controller: |
| 196 | + |
| 197 | + class WebhookController extends Laravel\Cashier\WebhookController { |
| 198 | + |
| 199 | + public function handleWebhook() |
| 200 | + { |
| 201 | + // Handle other events... |
| 202 | + |
| 203 | + // Fallback to failed payment check... |
| 204 | + return parent::handleWebhook(); |
| 205 | + } |
| 206 | + |
| 207 | + } |
| 208 | + |
| 209 | +> **Note:** In addition to updating the subscription information in your database, the Webhook controller will also cancel the subscription via the Stripe API. |
| 210 | +
|
| 211 | +<a name="invoices"></a> |
| 212 | +## Invoices |
| 213 | + |
| 214 | +You can easily retrieve an array of a user's invoices using the `invoices` method: |
| 215 | + |
| 216 | + $invoices = $user->invoices(); |
| 217 | + |
| 218 | +When listing the invoices for the customer, you may use these helper methods to display the relevant invoice information: |
| 219 | + |
| 220 | + {{ $invoice->id }} |
| 221 | + |
| 222 | + {{ $invoice->dateString() }} |
| 223 | + |
| 224 | + {{ $invoice->dollars() }} |
| 225 | + |
| 226 | +Use the `downloadInvoice` method to generate a PDF download of the invoice. Yes, it's really this easy: |
| 227 | + |
| 228 | + return $user->downloadInvoice($invoice->id, [ |
| 229 | + 'vendor' => 'Your Company', |
| 230 | + 'product' => 'Your Product', |
| 231 | + ]); |
0 commit comments