Введение
Laravel Cashier (кассир) обеспечивает выразительный и гибкий интерфейс для сервисов биллинговых подписок Stripe. Он сам создаст практически весь шаблонный код биллинговых подписок, который вы боитесь писать. В дополнение к основному управлению подписками Cashier может работать с купонами, заменой подписок, «величинами» подписок, отменой льготного периода, и даже генерировать PDF-файлы счетов.
Настройка
Composer
Сначала добавьте пакет Cashier в свой файл composer.json:
"laravel/cashier": "~2.0"
Поставщик услуг
Затем зарегистрируйте Laravel\Cashier\CashierServiceProvider в вашем файле настроек app.
Миграция
Перед тем как начать использовать Cashier, надо добавить несколько столбцов в БД. Не волнуйтесь, вы можете использовать Artisan-команду shcashier:table
для создания миграции, которая добавит необходимые столбцы. Например, чтобы добавить столбец в таблицу пользователей, используйте shphp artisan cashier:table users
. После создания миграции просто выполните команду shmigrate
.
Установка модели
Далее добавьте BillableTrait и соответствующий мутатор даты в определение вашей модели:
use Laravel\Cashier\BillableTrait;
use Laravel\Cashier\BillableInterface;
class User extends Eloquent implements BillableInterface {
use BillableTrait;
protected $dates = ['trial_ends_at', 'subscription_ends_at'];
}
Stripe-ключ
Наконец, внесите ваш Stripe-ключ в один из своих загрузочных файлов:
User::setStripeKey('stripe-key');
Подписка на план
Когда у вас есть экземпляр модели, вы легко можете подписать пользователя на данный Stripe-план:
$user = User::find(1);
$user->subscription('monthly')->create($creditCardToken);
Если надо применить купон при создании подписки, используйте метод PHPwithCoupon
:
$user->subscription('monthly')
->withCoupon('code')
->create($creditCardToken);
Метод PHPsubscription
автоматически создаст Stripe-подписку, а также внесёт в базу данных ID Stripe-клиента и другую необходимую биллинговую информацию. Если для вашего плана в Stripe настроен пробный период, то дата окончания этого периода будет также автоматически задана для пользователя.
Если пробный период вашего плана не настроен в Stripe, вам надо вручную задать дату окончания после применения подписки:
$user->trial_ends_at = Carbon::now()->addDays(14);
$user->save();
Указание дополнительной информации о пользователе
Если вы хотите указать дополнительную информацию о клиенте, вы можете передать её в качестве второго аргумента в метод PHPcreate
:
$user->subscription('monthly')->create($creditCardToken, [
'email' => $email, 'description' => 'Our First Customer'
]);
Прочитайте документацию по созданию клиентов, чтобы узнать больше о дополнительных полях, поддерживаемых в Stripe.
Без предоплаты
Если в вашем приложении будет бесплатный пробный период, не требующий предварительного предъявления кредитной карты, установите свойство PHPcardUpFront
вашей модели в PHPfalse
:
protected $cardUpFront = false;
При создании аккаунта не забудьте установить дату окончания триальной версии в модели:
$user->trial_ends_at = Carbon::now()->addDays(14);
$user->save();
Подключение к подпискам
Чтобы переключить пользователя на новую подписку, используйте метод PHPswap
:
$user->subscription('premium')->swap();
Если у пользователя была триальная подписка, он будет переключен на обычную. Кроме того, если у подписки есть «количество», то оно тоже применится.
Количество подписок
Иногда подписки зависят от «количества». Например, ваше приложение стоит 10$ в месяц с одного пользователя учётной записи. Чтобы легко увеличить или уменьшить количество вашей подписки, используйте методы PHPincrement
и PHPdecrement
:
$user = User::find(1);
$user->subscription()->increment();
// Добавить 5 к текущему количеству подписок...
$user->subscription()->increment(5);
$user->subscription->decrement();
// Вычесть 5 от текущего количества подписок...
$user->subscription()->decrement(5);
Отмена подписки
Отменить подписку проще пареной репы:
$user->subscription()->cancel();
При отмене подписки Cashier автоматически задаст столбец subscription_ends_at в вашей базе данных. Этот столбец используется, чтобы знать, когда метод PHPsubscribed
должен начать возвращать false. Например, если клиент отменит подписку 1 марта, но срок подписки по плану до 5 марта, то метод PHPsubscribed
будет продолжать возвращать true до 5 марта.
Возобновление подписки
Если подписка была отменена пользователем, и вам надо её возобновить, используйте метод PHPresume
:
$user->subscription('monthly')->resume($creditCardToken);
Если пользователь отменит подписку и затем возобновит её до того, как она полностью истекла, тогда не произойдет моментального расчёта оплаты. Его подписка будет просто повторно активирована, и расчёт оплаты будет происходить по изначальному циклу.
Проверка статуса подписки
Чтобы проверить, что пользователь подписан на ваше приложение, используйте метод PHPsubscribed
:
if ($user->subscribed())
{
//
}
Метод PHPsubscribed
создает отличный вариант для фильтра маршрута:
Route::filter('subscribed', function()
{
if (Auth::user() && ! Auth::user()->subscribed())
{
return Redirect::to('billing');
}
});
Вы также можете определить, идёт ли до сих пор триальный период у пользователя (для подходящего пользователя) с помощью метода PHPonTrial
:
if ($user->onTrial())
{
//
}
Чтобы определить, был ли пользователь ранее активным подписчиком, но позже отменил подписку, используйте метод PHPcancelled
:
if ($user->cancelled())
{
//
}
Вы можете также определить, отменил ли пользователь подписку, но находится все ещё на «льготном периоде», пока подписка полностью не истекла. Например, если пользователь отменяет подписку 5 марта, которая по плану закончится 10 марта, пользователь будет на «льготном периоде» до 10 марта. Обратите внимание на то, что метод PHPsubscribed
всё ещё возвращает true в это время.
if ($user->onGracePeriod())
{
//
}
Метод PHPeverSubscribed
используется для определения, подписывался ли пользователь когда-либо на ваше приложение:
if ($user->everSubscribed())
{
//
}
Метод PHPonPlan
используется для определения, подписан ли пользователь на данный план на основе его ID:
if ($user->onPlan('monthly'))
{
//
}
Обработка неудавшихся платежей
Что если кредитная карта клиента искекла? Никаких проблем — Cashier включает в себя контроллер Webhook, который может легко отменить подписку клиента. Просто укажите путь к контроллеру:
Route::post('stripe/webhook', 'Laravel\Cashier\WebhookController@handleWebhook');
Вот и всё! Неудавшиеся платежи будут перехвачены и обработаны контроллером. Контроллер отменит подписку клиента после трёх неудавшихся платежных попыток. URI Stripe/webhook в этом примере взят просто для примера. Вам надо настроить URI в параметрах вашего Stripe.
Обработка других webhook’ов Stripe
Если у вас есть дополнительные webhook-события для Stripe, которые вы хотели бы обработать, просто наследуйте контроллер Webhook. Ваши имена методов должны соответствовать принятому в Cashier соглашению, в частности, методы должны быть снабжены префиксом handle и именем того webhook-события Stripe, которое вы хотите обработать. Например, если вы хотите обработать webhook PHPinvoice.payment_succeeded
, вы должны добавить метод PHPhandleInvoicePaymentSucceeded
в контроллер.
class WebhookController extends Laravel\Cashier\WebhookController {
public function handleInvoicePaymentSucceeded($payload)
{
// Обработка события
}
}
Кроме обновления информации о подписке в вашей базе данных, контроллер Webhook также отменит подписку через Stripe API.
Счета
Вы можете легко получить массив счетов пользователя, используя метод PHPinvoices
:
$invoices = $user->invoices();
При просмотре счетов клиента вы можете использовать эти вспомогательные методы, чтобы вывести на экран соответствующую информацию о счёте:
{{ $invoice->id }}
{{ $invoice->dateString() }}
{{ $invoice->dollars() }}
Используйте метод PHPdownloadInvoice
, чтобы cгенерировать PDF-файл счёта. Да, это действительно так просто:
return $user->downloadInvoice($invoice->id, [
'vendor' => 'Your Company',
'product' => 'Your Product',
]);