Каса Laravel
- Вступ
- Оновлення Cashier
- Встановлення
- Конфігурація
- Клієнти
- Методи оплати
- Підписки
- Trials підписки
- Обробка Stripe веб-хуків
- Одноразові Charges
- Invoices (Рахунки-фактури)
- Обробка невдалих платежів
- Сильна автентифікація клієнта (SCA)
- Stripe SDK
- Тестування
Вступ
Laravel Cashier надає виразний, вільний інтерфейс дляStripeпослуги оплати підписки. Він обробляє майже весь звітний код підписки, перед яким ви боїтеся писати. На додаток до основного управління передплатою, Cashierр може обробляти купони, обмінюватися передплатою, «кількістю» підписки, пільговими періодами скасування та навіть генерувати PDF-файли рахунків-фактур.
Оновлення Cashier
Під час оновлення до нової версії Cashier важливо уважно переглянутипосібник з оновлення.
Щоб запобігти порушенням змін, Cashier використовує фіксовану версію API Stripe. Cashier 12 використовує версію API Stripe2020-03-02
. Версія API Stripe буде оновлюватися в незначних версіях, щоб використовувати нові функції та вдосконалення Stripe.
Встановлення
По-перше, вимагайте пакет Cashier для Stripe with Composer:
composer require laravel/cashier
Щоб Cashierр правильно обробляв усі події Stripe, пам’ятайтеналаштувати обробку веб-хука Cashierра.
Міграції баз даних
Постачальник послуг Cashier реєструє власний каталог міграції бази даних, тому не забудьте перенести вашу базу даних після встановлення пакету. Міграція Cashier додасть кілька стовпців до вашогоusers
таблиці, а також створити новуsubscriptions
таблиця, щоб вмістити всі підписки вашого клієнта:
php artisan migrate
Якщо вам потрібно переписати міграції, які постачаються з пакетом Cashier, ви можете опублікувати їх за допомогоюvendor:publish
Команда ремісників:
php artisan vendor:publish --tag="cashier-migrations"
Якщо ви хочете повністю запобігти запуску міграції Cashier, ви можете скористатисяignoreMigrations
надані Cashierром. Як правило, цей метод слід викликати вregister
метод вашогоAppServiceProvider
:
use Laravel\Cashier\Cashier;
Cashier::ignoreMigrations();
Stripe рекомендує, щоб будь-який стовпець, що використовується для зберігання ідентифікаторів Stripe, був чутливим до регістру. Тому слід забезпечити сортування стовпців дляstripe_id
для стовпця встановлено, наприклад,utf8_bin
в MySQL. Більше інформації можна знайтиу документації Stripe.
Конфігурація
Модель, що підлягає оплаті
Перед використанням Cashier додайтеBillable
риса для визначення вашої моделі. Ця ознака пропонує різні методи, що дозволяють виконувати загальні завдання щодо виставлення рахунків, такі як створення підписок, застосування купонів та оновлення інформації про спосіб оплати:
use Laravel\Cashier\Billable;
class User extends Authenticatable
{
use Billable;
}
Cashierр припускає, що вашою платною моделлю будеApp\Models\User
class that ships with Laravel. If you wish to change this you can specify a different model in your .env
файл:
CASHIER_MODEL=App\Models\User
Якщо ви використовуєте модель, відмінну від поставленої LaravelApp\Models\User
модель, вам потрібно буде опублікувати та змінити файлміграціїнадається відповідно до назви таблиці вашої альтернативної моделі.
Ключі API
Далі слід налаштувати свої клавіші Stripe у вашому.env
файл. Ключі API Stripe можна отримати на панелі керування Stripe.
STRIPE_KEY=your-stripe-key
STRIPE_SECRET=your-stripe-secret
Конфігурація валюти
Валютою Cashier за замовчуванням є долари США (USD). Ви можете змінити валюту за замовчуванням, встановившиCASHIER_CURRENCY
змінна середовища:
CASHIER_CURRENCY=eur
Окрім налаштування валюти Cashier, Ви також можете вказати локаль, який використовуватиметься при форматуванні грошових значень для відображення на рахунках-фактурах. Внутрішньо Cashierр використовуєPHPNumberFormatter
класщоб встановити локаль валюти:
CASHIER_CURRENCY_LOCALE=nl_BE
Для того, щоб використовувати локалі, крімen
, забезпечитиext-intl
Розширення PHP встановлено та налаштовано на вашому сервері.
Logging
Каса дозволяє вказати канал журналу, який використовуватиметься при реєстрації всіх винятків, пов’язаних із Stripe. Ви можете вказати канал журналу за допомогоюCASHIER_LOGGER
змінна середовища:
CASHIER_LOGGER=stack
Клієнти
Отримання клієнтів
Ви можете отримати клієнта за його ідентифікатором Stripe, використовуючиCashier::findBillable
метод. Це поверне екземпляр моделі Billable:
use Laravel\Cashier\Cashier;
$user = Cashier::findBillable($stripeId);
Створення клієнтів
Іноді, можливо, ви захочете створити клієнта Stripe, не починаючи підписку. Ви можете досягти цього за допомогоюcreateAsStripeCustomer
метод:
$stripeCustomer = $user->createAsStripeCustomer();
Після створення клієнта в Stripe ви можете розпочати підписку пізніше. Ви також можете використовувати необов’язковий$options
масив для передачі будь-яких додаткових параметрів, які підтримуються Stripe API:
$stripeCustomer = $user->createAsStripeCustomer($options);
Ви можете використовуватиasStripeCustomer
метод, якщо ви хочете повернути об'єкт клієнта, якщо платний об'єкт вже є клієнтом у Stripe:
$stripeCustomer = $user->asStripeCustomer();
createOrGetStripeCustomer
метод може бути використаний, якщо ви хочете повернути об'єкт замовника, але не впевнені, чи платник є вже клієнтом у Stripe. Цей метод створить нового клієнта в Stripe, якщо такий ще не існує:
$stripeCustomer = $user->createOrGetStripeCustomer();
Оновлення клієнтів
Іноді, можливо, ви захочете оновити клієнта Stripe безпосередньо додатковою інформацією. Ви можете досягти цього за допомогоюupdateStripeCustomer
метод:
$stripeCustomer = $user->updateStripeCustomer($options);
Портал виставлення рахунків
Смугасті пропозиціїпростий спосіб створити платіжний порталтак що ваш клієнт може керувати підпискою, способами оплати та переглядати історію виставлення рахунків. Ви можете перенаправити своїх користувачів на платіжний портал за допомогоюredirectToBillingPortal
метод від контролера або маршруту:
use Illuminate\Http\Request;
public function billingPortal(Request $request)
{
return $request->user()->redirectToBillingPortal();
}
За замовчуванням, коли користувач закінчує керувати підпискою, він може повернутися доhome
маршрут вашої заявки. Ви можете надати користувацьку URL-адресу, до якої користувач повинен повернутися, передавши URL-адресу як аргумент дляredirectToBillingPortal
метод:
use Illuminate\Http\Request;
public function billingPortal(Request $request)
{
return $request->user()->redirectToBillingPortal(
route('billing')
);
}
Якщо ви хочете згенерувати лише URL-адресу платіжного порталу, ви можете скористатисяbillingPortalUrl
метод:
$url = $user->billingPortalUrl(route('billing'));
методи оплати
Зберігання способів оплати
Для того, щоб створити підписку або здійснити одноразові платежі за Stripe, вам потрібно буде зберегти спосіб оплати та отримати його ідентифікатор із Stripe. Підхід, який використовується для досягнення, відрізняється залежно від того, чи плануєте ви використовувати спосіб оплати для підписки або одноразової оплати, тому ми розглянемо обидва нижче.
Способи оплати підписки
При зберіганні кредитних карток у клієнта для подальшого використання необхідно використовувати API Stripe Setup Intents для надійного збору інформації про спосіб оплати клієнта. "Намір налаштування" означає, що Stripe має намір стягнути плату з способу оплати клієнта. CashierрськийBillable
риса включає в себеcreateSetupIntent
щоб легко створити новий намір налаштування. Вам слід зателефонувати за цим способом із маршруту або контролера, який надасть форму, яка збирає деталі способу оплати вашого клієнта:
return view('update-payment-method', [
'intent' => $user->createSetupIntent()
]);
Після того, як ви створили намір налаштування та передали його представленням, вам слід прикріпити його секрет до елемента, який збиратиме спосіб оплати. Наприклад, розгляньте цю форму "оновити спосіб оплати":
<input id="card-holder-name" type="text">
<!-- Stripe Elements Placeholder -->
<div id="card-element"></div>
<button id="card-button" data-secret="{{ $intent->client_secret }}">
Update Payment Method
</button>
Далі, бібліотека Stripe.js може бути використана для приєднання елемента смужки до форми та надійного збору платіжних даних клієнта:
<script src="https://js.stripe.com/v3/"></script>
<script>
const stripe = Stripe('stripe-public-key');
const elements = stripe.elements();
const cardElement = elements.create('card');
cardElement.mount('#card-element');
</script>
Далі картку можна перевірити та отримати захищений «ідентифікатор способу оплати» у Stripe за допомогоюStripeconfirmCardSetup
метод:
const cardHolderName = document.getElementById('card-holder-name');
const cardButton = document.getElementById('card-button');
const clientSecret = cardButton.dataset.secret;
cardButton.addEventListener('click', async (e) => {
const { setupIntent, error } = await stripe.confirmCardSetup(
clientSecret, {
payment_method: {
card: cardElement,
billing_details: { name: cardHolderName.value }
}
}
);
if (error) {
// Display "error.message" to the user...
} else {
// The card has been verified successfully...
}
});
Після перевірки картки Stripe ви можете передати отримануsetupIntent.payment_method
ідентифікатор вашої програми Laravel, де його можна прикріпити до замовника. Спосіб оплати може бути будь-якимдодано як новий спосіб оплатиабовикористовується для оновлення способу оплати за замовчуванням. Ви також можете негайно використовувати ідентифікатор способу оплати длястворити нову підписку.
Якщо вам потрібна додаткова інформація про наміри налаштування та збір даних про оплату клієнтів, будь ласкаперегляньте цей огляд, наданий Stripe.
Способи оплати одноразових платежів
Звичайно, під час одноразового стягнення платіжного способу клієнта нам потрібно буде використовувати ідентифікатор способу оплати лише один раз. Через обмеження Stripe ви не можете використовувати збережений спосіб оплати клієнта за замовчуванням для одноразових платежів. Ви повинні дозволити клієнту вводити дані свого способу оплати за допомогою бібліотеки Stripe.js. Наприклад, розглянемо таку форму:
<input id="card-holder-name" type="text">
<!-- Stripe Elements Placeholder -->
<div id="card-element"></div>
<button id="card-button">
Process Payment
</button>
Далі, бібліотека Stripe.js може бути використана для приєднання елемента смужки до форми та надійного збору платіжних даних клієнта:
<script src="https://js.stripe.com/v3/"></script>
<script>
const stripe = Stripe('stripe-public-key');
const elements = stripe.elements();
const cardElement = elements.create('card');
cardElement.mount('#card-element');
</script>
Далі картку можна перевірити та отримати захищений «ідентифікатор способу оплати» у Stripe за допомогоюStripecreatePaymentMethod
метод:
const cardHolderName = document.getElementById('card-holder-name');
const cardButton = document.getElementById('card-button');
cardButton.addEventListener('click', async (e) => {
const { paymentMethod, error } = await stripe.createPaymentMethod(
'card', cardElement, {
billing_details: { name: cardHolderName.value }
}
);
if (error) {
// Display "error.message" to the user...
} else {
// The card has been verified successfully...
}
});
Якщо картку успішно перевірено, ви можете передатиpaymentMethod.id
до вашої заявки Laravel та обробіть aодна Charge.
Отримання способів оплати
paymentMethods
метод на екземплярі моделі Billable повертає колекціюLaravel\Cashier\PaymentMethod
екземпляри:
$paymentMethods = $user->paymentMethods();
Щоб отримати спосіб оплати за замовчуванням,defaultPaymentMethod
може бути використаний метод:
$paymentMethod = $user->defaultPaymentMethod();
Ви також можете отримати певний спосіб оплати, який належить моделі Billable, використовуючиfindPaymentMethod
метод:
$paymentMethod = $user->findPaymentMethod($paymentMethodId);
Визначення, чи має користувач спосіб оплати
Щоб визначити, чи має модель, що підлягає оплаті, метод оплати за замовчуванням, прикріплений до її рахунку, за допомогоюhasDefaultPaymentMethod
метод:
if ($user->hasDefaultPaymentMethod()) {
//
}
Щоб визначити, чи має модель, яка підлягає оплаті, принаймні один спосіб оплати, прикріплений до її рахунку, за допомогоюhasPaymentMethod
метод:
if ($user->hasPaymentMethod()) {
//
}
Оновлення способу оплати за замовчуванням
updateDefaultPaymentMethod
метод може бути використаний для оновлення інформації про спосіб оплати за замовчуванням. Цей метод приймає ідентифікатор способу оплати Stripe та призначає новий спосіб оплати як спосіб оплати за замовчуванням за замовчуванням:
$user->updateDefaultPaymentMethod($paymentMethod);
Щоб синхронізувати інформацію про спосіб оплати за замовчуванням із інформацією про спосіб оплати за замовчуванням у Stripe, ви можете використовуватиupdateDefaultPaymentMethodFromStripe
метод:
$user->updateDefaultPaymentMethodFromStripe();
Спосіб оплати за замовчуванням для клієнта може використовуватися лише для виставлення рахунків та створення нових підписок. Через обмеження Stripe він не може використовуватися для одноразового заряджання.
Додавання способів оплати
Щоб додати новий спосіб оплати, ви можете зателефонувати за номеромaddPaymentMethod
для платного користувача, передаючи ідентифікатор способу оплати:
$user->addPaymentMethod($paymentMethod);
Щоб дізнатись, як отримати ідентифікатори способу оплати, перегляньтедокументація щодо зберігання способу оплати.
Видалення способів оплати
Щоб видалити спосіб оплати, ви можете зателефонувати за номеромdelete
метод наLaravel\Cashier\PaymentMethod
екземпляр, який ви хочете видалити:
$paymentMethod->delete();
deletePaymentMethods
метод видалить всю інформацію про спосіб оплати для моделі Billable:
$user->deletePaymentMethods();
Якщо у користувача активна підписка, вам слід заборонити йому видаляти спосіб оплати за замовчуванням.
Підписки
Підписки забезпечують можливість налаштування періодичних платежів для ваших клієнтів і підтримують кілька планів підписки, кількість підписки, пробні версії тощо.
Створення підписки
Щоб створити підписку, спочатку отримайте екземпляр вашої платної моделі, який зазвичай буде екземпляромApp\Models\User
. Отримавши екземпляр моделі, ви можете використовуватиnewSubscription
метод створення підписки на модель:
$user = User::find(1);
$user->newSubscription('default', 'price_premium')->create($paymentMethod);
Перший аргумент, переданий вnewSubscription
метод повинен бути назвою підписки. Якщо ваша програма пропонує лише одну підписку, ви можете зателефонувати за цим номеромdefault
абоprimary
. Другим аргументом є конкретний план, на який користувач підписується. Це значення повинно відповідати ідентифікатору ціни плану в смузі.
create
метод, який приймаєідентифікатор способу оплати у смузіабо СмугаPaymentMethod
об'єкт, розпочне підписку, а також оновить вашу базу даних за допомогою ідентифікатора клієнта та іншої відповідної платіжної інформації.
Передача ідентифікатора способу оплати безпосередньо доcreate()
метод підписки також автоматично додасть його до збережених користувачем способів оплати.
Кількості
Якщо ви хочете встановити певну кількість для плану під час створення підписки, ви можете використовуватиquantity
метод:
$user->newSubscription('default', 'price_monthly')
->quantity(5)
->create($paymentMethod);
Додаткові деталі
Якщо ви хочете вказати додаткові дані про клієнта або підписку, ви можете зробити це, передавши їх як другий та третій аргументи доcreate
метод:
$user->newSubscription('default', 'price_monthly')->create($paymentMethod, [
'email' => $email,
], [
'metadata' => ['note' => 'Some extra information.'],
]);
Щоб дізнатись більше про додаткові поля, які підтримує Stripe, ознайомтеся з документацією Stripe настворення клієнтівістворення підписки.
Купони
Якщо ви хочете застосувати купон під час створення підписки, ви можете використовуватиwithCoupon
метод:
$user->newSubscription('default', 'price_monthly')
->withCoupon('code')
->create($paymentMethod);
Додавання передплат
Якщо ви хочете додати підписку для клієнта, у якого вже встановлений метод оплати за замовчуванням, ви можете використовуватиadd
метод при використанніnewSubscription
метод:
$user = User::find(1);
$user->newSubscription('default', 'price_premium')->add();
Перевірка статусу підписки
Після того, як користувач підписався на вашу програму, ви можете легко перевірити стан її підписки, використовуючи різноманітні зручні методи. По-перше,subscribed
метод повертаєtrue
якщо у користувача активна підписка, навіть якщо підписка наразі перебуває у пробному періоді:
if ($user->subscribed('default')) {
//
}
subscribed
метод також робить чудового кандидата намаршрут проміжного програмного забезпечення, що дозволяє фільтрувати доступ до маршрутів та контролерів на основі статусу підписки користувача:
public function handle($request, Closure $next)
{
if ($request->user() && ! $request->user()->subscribed('default')) {
// This user is not a paying customer...
return redirect('billing');
}
return $next($request);
}
Якщо ви хочете визначити, чи перебуває користувач все ще в пробному періоді, ви можете використовуватиonTrial
метод. Цей метод може бути корисним для відображення попередження користувачеві про те, що він все ще перебуває у пробному періоді:
if ($user->subscription('default')->onTrial()) {
//
}
subscribedToPlan
метод може бути використаний для визначення того, чи підписаний користувач на певний план на основі заданого ідентифікатора ціни смуги. У цьому прикладі ми визначимо, чи користувачdefault
підписка активно підписується наmonthly
план:
if ($user->subscribedToPlan('price_monthly', 'default')) {
//
}
Передаючи масив доsubscribedToPlan
методом, ви можете визначити, чи користувачdefault
підписка активно підписується наmonthly
абоyearly
план:
if ($user->subscribedToPlan(['price_monthly', 'price_yearly'], 'default')) {
//
}
recurring
метод може бути використаний, щоб визначити, чи підписаний користувач на даний момент і чи не перебуває він у пробному періоді:
if ($user->subscription('default')->recurring()) {
//
}
Якщо у користувача є дві підписки з однаковим іменем, остання підписка завжди буде повернутаsubscription
метод. Наприклад, у користувача можуть бути названі два записи підпискиdefault
; однак одна з підписок може бути старою, термін дії якої минув, тоді як інша - поточна, активна підписка. Остання підписка завжди буде повернута, тоді як попередні підписки зберігаються в базі даних для історичного перегляду.
Статус скасованої підписки
Щоб визначити, чи був користувач колись активним Підписником, але скасував свою підписку, ви можете використовуватиcancelled
метод:
if ($user->subscription('default')->cancelled()) {
//
}
Ви також можете визначити, чи скасував користувач свою підписку, але все ще перебуває на "пільговому періоді", поки підписка повністю не закінчиться. Наприклад, якщо користувач скасовує підписку на 5 березня, термін дії якої спочатку планувався до 10 березня, користувач перебуває у "пільговому періоді" до 10 березня. Зверніть увагу, щоsubscribed
метод все ще повертаєтьсяtrue
протягом цього часу:
if ($user->subscription('default')->onGracePeriod()) {
//
}
To determine if the user has cancelled their subscription and is no longer within their "grace period", you may use the ended
метод:
if ($user->subscription('default')->ended()) {
//
}
Scopes підписки
Більшість станів підписки також доступні у вигляді обсягу запитів, так що ви можете легко здійснити запит у своїй базі даних щодо підписок, які перебувають у певному стані:
// Get all active subscriptions...
$subscriptions = Subscription::query()->active()->get();
// Get all of the cancelled subscriptions for a user...
$subscriptions = $user->subscriptions()->cancelled()->get();
Повний список доступних областей доступний нижче:
Subscription::query()->active();
Subscription::query()->cancelled();
Subscription::query()->ended();
Subscription::query()->incomplete();
Subscription::query()->notCancelled();
Subscription::query()->notOnGracePeriod();
Subscription::query()->notOnTrial();
Subscription::query()->onGracePeriod();
Subscription::query()->onTrial();
Subscription::query()->pastDue();
Subscription::query()->recurring();
Неповний та прострочений статус
Якщо підписка вимагає вторинної платіжної дії після створення, підписка буде позначена якincomplete
. Статуси підписки зберігаються вstripe_status
стовпець Cashiersubscriptions
таблиця бази даних.
Подібним чином, якщо під час обміну планами потрібна дія вторинного платежу, підписка буде позначена якpast_due
. Коли ваша підписка знаходиться в будь-якому з цих штатів, вона не буде активною, доки клієнт не підтвердить свою оплату. Перевірити, чи має підписка неповний платіж, можна за допомогоюhasIncompletePayment
метод на моделі Billable або екземплярі підписки:
if ($user->hasIncompletePayment('default')) {
//
}
if ($user->subscription('default')->hasIncompletePayment()) {
//
}
Якщо підписка має неповний платіж, вам слід направити користувача на сторінку підтвердження платежу Cashier, передавшиlatestPayment
ідентифікатор. Ви можете використовуватиlatestPayment
метод, доступний в екземплярі підписки для отримання цього ідентифікатора:
<a href="{{ route('cashier.payment', $subscription->latestPayment()->id) }}">
Please confirm your payment.
</a>
Якщо ви хочете, щоб підписка все ще вважалася активною, коли вона знаходиться вpast_due
штату, ви можете використовуватиkeepPastDueSubscriptionsActive
спосіб, наданий Cashierром. Як правило, цей метод слід викликати вregister
метод вашогоAppServiceProvider
:
use Laravel\Cashier\Cashier;
/**
* Register any application services.
*
* @return void
*/
public function register()
{
Cashier::keepPastDueSubscriptionsActive();
}
Коли підписка знаходиться вincomplete
заявіть, що його не можна змінити, поки не буде підтверджено платіж. Томуswap
іupdateQuantity
методи видадуть виняток, коли підписка знаходиться вincomplete
держава.
Зміна планів
Після того, як користувач підписався на вашу програму, він іноді може захотіти перейти на новий план підписки. Щоб замінити користувача на нову підписку, передайте ідентифікатор ціни плану наswap
метод:
$user = App\Models\User::find(1);
$user->subscription('default')->swap('provider-price-id');
Якщо користувач проходить пробний період, пробний період буде збережено. Крім того, якщо для підписки існує "кількість", ця кількість також буде збережена.
Якщо ви хочете поміняти місцями та скасувати будь-який пробний період, який зараз перебуває користувач, ви можете використовуватиskipTrial
метод:
$user->subscription('default')
->skipTrial()
->swap('provider-price-id');
Якщо ви хочете поміняти місцями та негайно виставити рахунок користувачеві, а не чекати наступного платіжного циклу, ви можете використовуватиswapAndInvoice
метод:
$user = App\Models\User::find(1);
$user->subscription('default')->swapAndInvoice('provider-price-id');
Пропорції
За замовчуванням Stripe пропорційно стягує плату при обміні між планами.noProrate
метод може бути використаний для оновлення підписки без пропорційних витрат:
$user->subscription('default')->noProrate()->swap('provider-price-id');
Щоб отримати додаткову інформацію про розподіл підписки, зверніться доСмугаста документація.
ВиконанняnoProrate
метод доswapAndInvoice
метод не вплине на розподіл. Рахунок завжди буде виставлений.
Кількість підписки
Іноді на підписки впливає "кількість". Наприклад, за вашу програму може стягуватися 10 доларів на місяцьна користувачана рахунку. Щоб легко збільшити або зменшити кількість підписки, використовуйтеincrementQuantity
іdecrementQuantity
методи:
$user = User::find(1);
$user->subscription('default')->incrementQuantity();
// Add five to the subscription's current quantity...
$user->subscription('default')->incrementQuantity(5);
$user->subscription('default')->decrementQuantity();
// Subtract five to the subscription's current quantity...
$user->subscription('default')->decrementQuantity(5);
Крім того, ви можете встановити конкретну кількість за допомогоюupdateQuantity
метод:
$user->subscription('default')->updateQuantity(10);
noProrate
метод може бути використаний для оновлення кількості підписки без збільшення пропорцій:
$user->subscription('default')->noProrate()->updateQuantity(10);
Щоб отримати додаткову інформацію про кількість підписки, зверніться доСмугаста документація.
Зверніть увагу, що при роботі з багатоплановими підписками для зазначених вище методів кількості потрібен додатковий параметр "план".
Підписки на кілька планів
Багатопланові підпискидозволяють призначати кілька тарифних планів для однієї підписки. Наприклад, уявіть, що ви створюєте додаток служби підтримки клієнтів, який має базову підписку 10 доларів на місяць, але пропонує додатковий план живого чату на додаткові 15 доларів на місяць:
$user = User::find(1);
$user->newSubscription('default', [
'price_monthly',
'chat-plan',
])->create($paymentMethod);
Тепер у клієнта буде два планиdefault
підписка. За обидва тарифи буде стягуватися плата відповідно до відповідних інтервалів виставлення рахунків. Ви також можете використовуватиquantity
спосіб вказати конкретну кількість для кожного плану:
$user = User::find(1);
$user->newSubscription('default', ['price_monthly', 'chat-plan'])
->quantity(5, 'chat-plan')
->create($paymentMethod);
Або ви можете динамічно додавати додатковий план та його кількість, використовуючиplan
метод:
$user = User::find(1);
$user->newSubscription('default', 'price_monthly')
->plan('chat-plan', 5)
->create($paymentMethod);
Крім того, ви можете додати новий план до існуючої підписки пізніше:
$user = User::find(1);
$user->subscription('default')->addPlan('chat-plan');
У наведеному вище прикладі буде додано новий план, і клієнту буде виставлено рахунок за нього під час наступного платіжного циклу. Якщо ви хочете негайно виставити рахунок клієнту, ви можете скористатися нимaddPlanAndInvoice
метод:
$user->subscription('default')->addPlanAndInvoice('chat-plan');
Якщо ви хочете додати план із конкретною кількістю, ви можете передати величину як другий параметрaddPlan
абоaddPlanAndInvoice
методи:
$user = User::find(1);
$user->subscription('default')->addPlan('chat-plan', 5);
Ви можете видалити плани з підписок за допомогоюremovePlan
метод:
$user->subscription('default')->removePlan('chat-plan');
Ви не можете видалити останній план підписки. Натомість вам слід просто скасувати підписку.
Обмін
Ви також можете змінити плани, приєднані до багатопланової підписки. Наприклад, уявіть, що ви наbasic-plan
підписка зchat-plan
і ви хочете перейти наpro-plan
план:
$user = User::find(1);
$user->subscription('default')->swap(['pro-plan', 'chat-plan']);
При виконанні наведеного вище коду основний елемент підписки зbasic-plan
видаляється, а той ізchat-plan
зберігається. Крім того, новий елемент підписки на новийpro-plan
створюється.
Ви також можете вказати параметри елементів підписки. Наприклад, вам може знадобитися вказати кількості плану підписки:
$user = User::find(1);
$user->subscription('default')->swap([
'pro-plan' => ['quantity' => 5],
'chat-plan'
]);
Якщо ви хочете поміняти один план на передплаті, ви можете зробити це за допомогоюswap
метод на самому елементі підписки. Цей підхід корисний, якщо ви, наприклад, хочете зберегти всі існуючі метадані в елементі підписки.
$user = User::find(1);
$user->subscription('default')
->findItemOrFail('basic-plan')
->swap('pro-plan');
Прорація
За замовчуванням Stripe буде пропорційно стягувати плату під час додавання або видалення планів з підписки. Якщо ви хочете внести коригування плану без пропорції, вам слід встановити ланцюжокnoProrate
методу на вашій операції плану:
$user->subscription('default')->noProrate()->removePlan('chat-plan');
Кількості
Якщо ви хочете оновити кількість за окремими тарифними планами, ви можете зробити це за допомогоюіснуючі кількісні методиі передаючи ім'я плану як додатковий аргумент методу:
$user = User::find(1);
$user->subscription('default')->incrementQuantity(5, 'chat-plan');
$user->subscription('default')->decrementQuantity(3, 'chat-plan');
$user->subscription('default')->updateQuantity(10, 'chat-plan');
Якщо у вас встановлено кілька тарифів на підписку,stripe_plan
іquantity
атрибути наSubscription
модель будеnull
. Щоб отримати доступ до індивідуальних планів, вам слід використовуватиitems
зв'язки, доступні наSubscription
модель.
Елементи підписки
Якщо у підписки є кілька планів, вона буде мати кілька елементів підписки, що зберігаються у вашій базі данихsubscription_items
таблиця. Ви можете отримати доступ до них черезitems
зв'язки за передплатою:
$user = User::find(1);
$subscriptionItem = $user->subscription('default')->items->first();
// Retrieve the Stripe plan and quantity for a specific item...
$stripePlan = $subscriptionItem->stripe_plan;
$quantity = $subscriptionItem->quantity;
Ви також можете отримати конкретний план за допомогоюfindItemOrFail
метод:
$user = User::find(1);
$subscriptionItem = $user->subscription('default')->findItemOrFail('chat-plan');
Податки на підписку
Щоб визначити ставки податку, які користувач сплачує за підписку, застосуйтеtaxRates
метод на вашій платіжній моделі та поверніть масив із ідентифікаторами податкових ставок. Ви можете визначити ці ставки податку впанель приладів Stripe:
public function taxRates()
{
return ['tax-rate-id'];
}
taxRates
Метод дозволяє застосовувати ставку податку на основі моделі, що може бути корисним для бази користувачів, яка охоплює кілька країн і податкові ставки. Якщо ви працюєте з багатоплановими підписками, ви можете визначити різні ставки податку для кожного плану, застосувавши aplanTaxRates
метод на вашій оплачуваній моделі:
public function planTaxRates()
{
return [
'plan-id' => ['tax-rate-id'],
];
}
taxRates
метод застосовується лише до плати за підписку. Якщо ви використовуєте Касу для одноразових платежів, вам потрібно буде вручну вказати ставку податку на той момент.
Синхронізація податкових ставок
При зміні жорстко закодованих ідентифікаторів податкових ставок, що повертаютьсяtaxRates
методом, податкові налаштування для будь-яких існуючих підписок для користувача залишаться незмінними. Якщо ви хочете оновити податкову вартість для існуючих підписок із повернутимиtaxTaxRates
значення, вам слід викликатиsyncTaxRates
метод на екземплярі підписки користувача:
$user->subscription('default')->syncTaxRates();
Це також синхронізує будь-які ставки податку на підписку, тому переконайтеся, що ви також правильно змінилиplanTaxRates
метод.
Звільнення від оподаткування
Cashierр також пропонує методи визначення, чи клієнт звільнений від сплати податку, зателефонувавши Stripe API.isNotTaxExempt
,isTaxExempt
, іreverseChargeApplies
методи, доступні на платній моделі:
$user = User::find(1);
$user->isTaxExempt();
$user->isNotTaxExempt();
$user->reverseChargeApplies();
Ці методи також доступні на будь-якихLaravel\Cashier\Invoice
об'єкт. Однак при виклику цих методів наInvoice
об'єкт, методи визначатимуть статус звільнення під час створення рахунка-фактури.
Дата Binding підписки
За замовчуванням прив’язкою платіжного циклу є дата створення підписки, або якщо використовується пробний період, дата закінчення пробної версії. Якщо ви хочете змінити дату Binding рахунків, ви можете використовуватиanchorBillingCycleOn
метод:
use App\Models\User;
use Carbon\Carbon;
$user = User::find(1);
$anchor = Carbon::parse('first day of next month');
$user->newSubscription('default', 'price_premium')
->anchorBillingCycleOn($anchor->startOfDay())
->create($paymentMethod);
Для отримання додаткової інформації щодо управління циклами виставлення рахунків підписки зверніться доДокументація циклу виставлення рахунків у смужку
Скасування підписки
Щоб скасувати підписку, зателефонуйте наcancel
метод підписки користувача:
$user->subscription('default')->cancel();
Коли підписку скасовано, Cashierр автоматично встановитьends_at
у вашій базі даних. Цей стовпець використовується, щоб знати, колиsubscribed
метод повинен почати повертатисяfalse
. Наприклад, якщо клієнт скасовує підписку 1 березня, але підписка закінчувалася до 5 березня,subscribed
метод продовжить повертатисяtrue
до 5 березня.
Ви можете визначити, скасував користувач підписку, але все ще перебуває на "пільговому періоді", використовуючиonGracePeriod
метод:
if ($user->subscription('default')->onGracePeriod()) {
//
}
Якщо ви бажаєте негайно скасувати підписку, зателефонуйте на номерcancelNow
метод підписки користувача:
$user->subscription('default')->cancelNow();
Відновлення підписки
Якщо користувач скасував свою підписку, і ви хочете відновити її, скористайтесьresume
метод. Користувачповиненвсе ще перебувати у своєму пільговому періоді, щоб відновити підписку:
$user->subscription('default')->resume();
Якщо користувач скасує підписку, а потім відновить підписку до закінчення терміну дії підписки, оплата за них не стягуватиметься негайно. Натомість їх підписка буде повторно активована, і вони будуть виставлені рахунки за початковим розрахунковим циклом.
Випробувальні підписки
Зі способом оплати вперед
Якщо ви хочете запропонувати пробні періоди своїм клієнтам, одночасно збираючи інформацію про спосіб оплати, вам слід скористатисяtrialDays
під час створення підписки:
$user = User::find(1);
$user->newSubscription('default', 'price_monthly')
->trialDays(10)
->create($paymentMethod);
Цей метод встановить дату закінчення пробного періоду в записі підписки в базі даних, а також вкаже Stripe не розпочинати виставлення рахунків клієнту до цієї дати. При використанніtrialDays
методом, Cashierр замінить будь-який пробний період за промовчанням, налаштований для плану в Stripe.
Якщо підписка клієнта не буде скасована до дати закінчення пробного періоду, з них буде стягнуто плату, як тільки закінчиться пробна версія, тому ви повинні обов’язково повідомити своїх користувачів про дату закінчення пробного періоду.
trialUntil
метод дозволяє надати aDateTime
екземпляр, щоб вказати, коли повинен закінчитися пробний період:
use Carbon\Carbon;
$user->newSubscription('default', 'price_monthly')
->trialUntil(Carbon::now()->addDays(10))
->create($paymentMethod);
Ви можете визначити, чи перебуває користувач протягом пробного періоду, використовуючи будь-який ізonTrial
метод екземпляра користувача, абоonTrial
метод екземпляра підписки. Два наведені нижче приклади однакові:
if ($user->onTrial('default')) {
//
}
if ($user->subscription('default')->onTrial()) {
//
}
Визначення пробних днів у смузі / касі
Ви можете визначити, скільки пробних днів отримує ваш план на інформаційній панелі Stripe, або завжди явно передавати їх за допомогою Cashier. Якщо ви вирішите визначити пробні дні свого плану в Stripe, ви повинні пам’ятати, що нові підписки, включаючи нові підписки для клієнта, який раніше підписувався, завжди отримуватимуть пробний період, якщо ви явно не зателефонуєтеtrialDays(0)
метод.
Без способу оплати
Якщо ви хочете запропонувати пробні періоди без попереднього збору інформації про спосіб оплати користувача, ви можете встановитиtrial_ends_at
у стовпці запису користувача до бажаної дати закінчення пробного періоду. Зазвичай це робиться під час реєстрації користувача:
$user = User::create([
// Populate other user properties...
'trial_ends_at' => now()->addDays(10),
]);
Обов’язково додайте aмутатор датидляtrial_ends_at
до визначення вашої моделі.
Cashierр називає цей тип судового розгляду «загальним випробуванням», оскільки він не додається до жодної існуючої підписки.onTrial
метод наUser
екземпляр повернетьсяtrue
якщо поточна дата не минула значенняtrial_ends_at
:
if ($user->onTrial()) {
// User is within their trial period...
}
Коли ви будете готові створити фактичну підписку для користувача, ви можете використовуватиnewSubscription
метод, як зазвичай:
$user = User::find(1);
$user->newSubscription('default', 'price_monthly')->create($paymentMethod);
Щоб отримати дату закінчення пробного періоду для користувача, ви можете використовуватиtrialEndsAt
метод. Цей метод повертає примірник дати Carbon, якщо користувач перебуває на пробній версії абоnull
якщо їх немає. Ви також можете передати необов’язковий параметр імені підписки, якщо хочете отримати дату закінчення пробного періоду для певної підписки, крім стандартної:
if ($user->onTrial()) {
$trialEndsAt = $user->trialEndsAt('main');
}
Ви також можете використовуватиonGenericTrial
метод, якщо ви хочете конкретно знати, що користувач перебуває у межах свого "загального" пробного періоду і ще не створив фактичну підписку:
if ($user->onGenericTrial()) {
// User is within their "generic" trial period...
}
Розширення випробувань
extendTrial
метод дозволяє продовжити пробний період підписки після її створення:
// End the trial 7 days from now...
$subscription->extendTrial(
now()->addDays(7)
);
// Add an additional 5 days to the trial...
$subscription->extendTrial(
$subscription->trial_ends_at->addDays(5)
);
Якщо пробна версія вже закінчилася, а клієнту вже виставляється рахунок за підписку, ви все одно можете запропонувати їм розширену пробну версію. Час, проведений протягом пробного періоду, буде вираховуватися із наступного рахунку клієнта.
Обробка Stripe веб-хуків
Ви можете використовуватисмужка CLIдля тестування веб-хуків під час локальної розробки.
Stripe може повідомляти вашу заявку про різноманітні події через веб-хуки. За замовчуванням маршрут, який вказує на контролер веб-хука Cashier, налаштовується через постачальника послуг Cashier. Цей контролер обробляє всі вхідні запити веб-хука.
За замовчуванням цей контролер автоматично обробляє скасування підписок, у яких занадто багато невдалих платежів (як це визначено в налаштуваннях Stripe), оновлення клієнтів, видалення клієнтів, оновлення підписки та зміни способу оплати; однак, як ми скоро дізнаємось, ви можете розширити цей контролер для обробки будь-якої події веб-хука, яка вам подобається.
Щоб ваша програма могла обробляти веб-хуки Stripe, налаштуйте URL-адресу веб-хука на панелі керування Stripe. За замовчуванням контролер веб-хука Cashierр прослуховує/stripe/webhook
Шлях URL. Повний список усіх веб-хуків, які слід налаштувати на панелі керування Stripe:
-
customer.subscription.updated
-
customer.subscription.deleted
-
customer.updated
-
customer.deleted
-
invoice.payment_action_required
Обов’язково захистіть вхідні запити за допомогою Cashierперевірка підписуMiddleware.
Захист веб-хуків та CSRF
Оскільки веб-хуки Stripe повинні обійти LaravelЗахист CSRF, не забудьте вказати URI як виняток у вашомуVerifyCsrfToken
Middleware або перелічіть маршрут за межамиweb
група проміжного програмного забезпечення:
protected $except = [
'stripe/*',
];
Визначення обробників подій Webhook
Каса автоматично обробляє скасування підписки за невдалі платежі, але якщо у вас є додаткові події веб-хука, які ви хотіли б обробити, розширте контролер Webhook. Назви ваших методів повинні відповідати очікуваній умові Cashierра, зокрема, до методів слід вводити префіксhandle
і назва "справи верблюда" веб-гачка, з яким ви хочете обробити. Наприклад, якщо ви хочете обробляти файлinvoice.payment_succeeded
webhook, вам слід додати ahandleInvoicePaymentSucceeded
метод до контролера:
<?php
namespace App\Http\Controllers;
use Laravel\Cashier\Http\Controllers\WebhookController as CashierController;
class WebhookController extends CashierController
{
/**
* Handle invoice payment succeeded.
*
* @param array $payload
* @return \Symfony\Component\HttpFoundation\Response
*/
public function handleInvoicePaymentSucceeded($payload)
{
// Handle The Event
}
}
Далі визначте маршрут до свого контролера Cashier в межах вашогоroutes/web.php
файл. Це перезапише відправлений маршрут за замовчуванням:
use App\Http\Controllers\WebhookController;
Route::post(
'stripe/webhook',
[WebhookController::class, 'handleWebhook']
);
Cashierр виділяєLaravel\Cashier\Events\WebhookReceived
подія, коли отримано веб-хук, таLaravel\Cashier\Events\WebhookHandled
подія, коли веб-хук обробляв Cashierр. Обидві події містять повне корисне навантаження веб-хука Stripe.
Невдалі підписки
Що робити, якщо термін дії кредитної картки клієнта закінчується? Не хвилюйтеся - контролер Webhook Cashier скасує підписку клієнта для вас. Невдалі платежі будуть автоматично зафіксовані та оброблені контролером. Контролер скасує підписку клієнта, коли Stripe виявить, що підписка не вдалася (зазвичай після трьох невдалих спроб оплати).
Перевірка підписів Webhook
Для захисту веб-хуків ви можете використовуватиПідписи веб-хука Стріпа. Для зручності Cashier автоматично включає Middleware, яке підтверджує, що вхідний запит веб-хука Stripe є дійсним.
Щоб увімкнути перевірку веб-хука, переконайтеся, щоSTRIPE_WEBHOOK_SECRET
змінна середовища встановлена у вашому.env
файл. Веб-хукsecret
може бути отримано з інформаційної панелі вашого облікового запису Stripe.
Одноразові Charges
Проста Charge
charge
метод приймає суму, яку ви хочете стягнути внайменший знаменник валюти, що використовується вашою заявкою.
Якщо ви хочете зробити одноразову комісію за спосіб оплати підписаного клієнта, ви можете використовуватиcharge
метод на екземплярі платної моделі. Вам потрібно буденадайте ідентифікатор способу оплатияк другий аргумент:
// Stripe Accepts Charges In Cents...
$stripeCharge = $user->charge(100, $paymentMethod);
charge
метод приймає масив як свій третій аргумент, дозволяючи передавати будь-які параметри, які ви хочете, для базового створення заряду Stripe. Зверніться до документації Stripe щодо варіантів, доступних вам під час створення нарахувань:
$user->charge(100, $paymentMethod, [
'custom_option' => $value,
]);
Ви також можете використовуватиcharge
метод без основного замовника або користувача:
use App\Models\User;
$stripeCharge = (new User)->charge(100, $paymentMethod);
charge
метод видасть виняток, якщо заряд не вдасться. Якщо звинувачення успішне, примірникLaravel\Cashier\Payment
буде повернуто з методу:
try {
$payment = $user->charge(100, $paymentMethod);
} catch (Exception $e) {
//
}
Стягніть рахунок-фактуру
Іноді вам може знадобитися зробити одноразову оплату, але також сформувати рахунок-фактуру, щоб ви могли запропонувати замовнику квитанцію у форматі PDF.invoiceFor
метод дозволяє зробити саме це. Наприклад, давайте виставляємо рахунки клієнту 5,00 доларів США за "одноразову плату":
// Stripe Accepts Charges In Cents...
$user->invoiceFor('One Time Fee', 500);
Рахунок-фактура буде негайно стягнуто з використання способу оплати користувача за замовчуванням.invoiceFor
метод також приймає масив як свій третій аргумент. Цей масив містить варіанти виставлення рахунка для позиції рахунка-фактури. Четвертий аргумент, прийнятий методом, також є масивом. Цей остаточний аргумент приймає варіанти виставлення рахунків для самого рахунку-фактури:
$user->invoiceFor('Stickers', 500, [
'quantity' => 50,
], [
'default_tax_rates' => ['tax-rate-id'],
]);
invoiceFor
метод створить рахунок-фактуру Stripe, який повторить спроби невдалих спроб виставлення рахунків. Якщо ви не хочете, щоб рахунки-фактури повторювали невдалі платежі, вам доведеться закрити їх за допомогою API Stripe після першого невдалого стягнення плати.
Повернення коштів
Якщо вам потрібно повернути плату за Stripe, ви можете використовуватиrefund
метод. Цей метод приймає ідентифікатор наміру платежу в якості першого аргументу:
$payment = $user->charge(100, $paymentMethod);
$user->refund($payment->id);
Рахунки-фактури
Отримання рахунків-фактур
Ви можете легко отримати масив рахунків-фактур, що оплачується, за допомогоюinvoices
метод:
$invoices = $user->invoices();
// Include pending invoices in the results...
$invoices = $user->invoicesIncludingPending();
Ви можете використовуватиfindInvoice
спосіб отримання конкретного рахунку-фактури:
$invoice = $user->findInvoice($invoiceId);
Відображення інформації про рахунок-фактуру
Перераховуючи рахунки для замовника, ви можете використовувати допоміжні методи рахунку-фактури для відображення відповідної інформації про рахунок. Наприклад, ви можете перерахувати кожен рахунок-фактуру в таблиці, що дозволить користувачеві легко завантажити будь-який з них:
<table>
@foreach ($invoices as $invoice)
<tr>
<td>{{ $invoice->date()->toFormattedDateString() }}</td>
<td>{{ $invoice->total() }}</td>
<td><a href="/user/invoice/{{ $invoice->id }}">Download</a></td>
</tr>
@endforeach
</table>
Створення PDF-фактур
Зсередини маршруту або контролера використовуйтеdownloadInvoice
метод створення PDF-фактури для завантаження. Цей метод автоматично генерує правильну відповідь HTTP для відправки завантаження у браузер:
use Illuminate\Http\Request;
Route::get('user/invoice/{invoice}', function (Request $request, $invoiceId) {
return $request->user()->downloadInvoice($invoiceId, [
'vendor' => 'Your Company',
'product' => 'Your Product',
]);
});
downloadInvoice
метод також допускає необов'язкове власне ім'я файлу як третій параметр. Це ім'я файлу буде автоматично суфіксом.pdf
для вас:
return $request->user()->downloadInvoice($invoiceId, [
'vendor' => 'Your Company',
'product' => 'Your Product',
], 'my-invoice');
Обробка невдалих платежів
Іноді платежі за підписку або одноразові платежі можуть не вдатися. Коли це станеться, Cashierр кине знакIncompletePayment
виняток, який повідомляє вас, що це сталося. Вловивши цей виняток, у вас є два варіанти, як діяти далі.
По-перше, ви можете перенаправити клієнта на спеціальну сторінку підтвердження платежу, яка додається до Cashier. Ця сторінка вже має пов’язаний маршрут, який зареєстрований через постачальника послуг Cashier. Отже, ви можете зловитиIncompletePayment
виключення та перенаправлення на сторінку підтвердження платежу:
use Laravel\Cashier\Exceptions\IncompletePayment;
try {
$subscription = $user->newSubscription('default', $planId)
->create($paymentMethod);
} catch (IncompletePayment $exception) {
return redirect()->route(
'cashier.payment',
[$exception->payment->id, 'redirect' => route('home')]
);
}
На сторінці підтвердження платежу клієнту буде запропоновано ще раз ввести дані своєї кредитної картки та виконати будь-які додаткові дії, які вимагає Stripe, наприклад, підтвердження "3D Secure". Після підтвердження оплати користувач буде перенаправлений на URL-адресу, надануredirect
параметр, зазначений вище. При перенаправленні,message
(рядок) таsuccess
(цілочисельні) змінні рядка запиту будуть додані до URL-адреси.
Крім того, ви можете дозволити Stripe обробляти для вас підтвердження платежу. У цьому випадку замість переадресації на сторінку підтвердження платежу ви можетеналаштування електронних листів автоматичного виставлення рахунківна панелі приладів Stripe. Однак якщоIncompletePayment
винятком виявлено, ви все одно повинні повідомити користувача, що він отримає електронне повідомлення з подальшими інструкціями щодо підтвердження платежу.
Винятки з оплати можуть бути використані для таких способів:charge
,invoiceFor
, іinvoice
наBillable
користувач. При обробці підписок файлcreate
метод наSubscriptionBuilder
, іincrementAndInvoice
іswapAndInvoice
методи наSubscription
модель може створювати винятки.
В даний час існує два типи винятків із платежів, які поширюютьсяIncompletePayment
. За потреби ви можете зловити їх окремо, щоб налаштувати взаємодію з користувачем:
-
PaymentActionRequired
: this indicates that Stripe requires extra verification in order to confirm and process a payment. -
PaymentFailure
: this indicates that a payment failed for various other reasons, such as being out of available funds.
Надійна аутентифікація клієнта
Якщо ваш бізнес базується в Європі, вам доведеться дотримуватися вимог жорсткої автентифікації клієнтів (SCA). Ці правила були введені у вересні 2019 року Європейським Союзом для запобігання шахрайству з платежами. На щастя, Stripe та Cashier підготовлені до створення додатків, сумісних із SCA.
Перш ніж розпочати, перегляньтеПосібник Stripe щодо PSD2 та SCAа також їхдокументація щодо нових API SCA.
Платежі, що вимагають додаткового підтвердження
Положення SCA часто вимагають додаткової перевірки для підтвердження та обробки платежу. Коли це станеться, Cashierр кинеPaymentActionRequired
виняток, який повідомляє вас про необхідність додаткової перевірки. Більше інформації про те, як обробляти ці винятки, можна знайтитут.
Незавершений та прострочений строк
Коли платіж потребує додаткового підтвердження, підписка залишатиметься вincomplete
абоpast_due
держави, як вказує йогоstripe_status
стовпець бази даних. Каса автоматично активує підписку клієнта через веб-хук, як тільки підтвердження оплати буде завершено.
Для отримання додаткової інформації проincomplete
іpast_due
штати, будь ласка, зверніться донаша додаткова документація.
Повідомлення про оплату поза сесією
Оскільки правила SCA вимагають від клієнтів час від часу перевіряти свої платіжні реквізити, навіть коли підписка активна, Cashierр може надіслати клієнту Notification про платіж, коли потрібно підтвердження оплати поза сесією. Наприклад, це може статися, коли підписка поновлюється. Повідомлення про оплату Cashier можна ввімкнути, встановившиCASHIER_PAYMENT_NOTIFICATION
середовища до класу сповіщень. За замовчуванням це Notification вимкнено. Звичайно, Cashier включає клас сповіщень, який ви можете використовувати для цієї мети, але за бажанням ви можете надати власний клас сповіщень:
CASHIER_PAYMENT_NOTIFICATION=Laravel\Cashier\Notifications\ConfirmPayment
Щоб переконатися, що надсилаються повідомлення про підтвердження оплати поза сесією, перевірте цеСмугасті веб-хуки налаштованідля вашої заявки таinvoice.payment_action_required
webhook увімкнено на вашій інформаційній панелі Stripe. Крім того, вашBillable
модель також повинна використовувати LaravelIlluminate\Notifications\Notifiable
риса.
Notification надсилатимуться навіть тоді, коли клієнти здійснюють платіж вручну, що вимагає додаткового підтвердження. На жаль, Stripe не може дізнатися, що оплата була здійснена вручну або "поза сесією". Але клієнт просто побачить повідомлення "Оплата виконана", якщо він відвідає сторінку платежів після того, як уже підтвердить свій платіж. Клієнту не дозволяється випадково двічі підтвердити один і той же платіж і випадково здійснити другу оплату.
Stripe SDK
Багато об'єктів Cashier є обгортками навколо об'єктів Stripe SDK. Якщо ви хочете взаємодіяти з об'єктами Stripe безпосередньо, ви можете зручно отримати їх за допомогоюasStripe
метод:
$stripeSubscription = $subscription->asStripeSubscription();
$stripeSubscription->application_fee_percent = 5;
$stripeSubscription->save();
Ви також можете використовуватиupdateStripeSubscription
метод оновлення підписки Stripe безпосередньо:
$subscription->updateStripeSubscription(['application_fee_percent' => 5]);
Тестування
Під час тестування програми, яка використовує Cashier, ви можете знущатися над фактичними HTTP-запитами до Stripe API; однак для цього потрібно частково повторно реалізувати власну поведінку Cashierра. Тому ми рекомендуємо дозволити вашим тестам вражати фактичний Stripe API. Хоча це відбувається повільніше, воно забезпечує більшу впевненість у тому, що ваш додаток працює належним чином, і будь-які повільні тести можуть бути розміщені у власній групі тестування PHPUnit.
Під час тестування пам’ятайте, що сам Cashierр вже має чудовий пакет тестів, тому вам слід зосередитись лише на тестуванні підписки та потоку платежів у вашому власному додатку, а не на кожній базовій поведінці Cashierра.
Для початку додайтетестуванняверсія вашої смужки секрет для вашогоphpunit.xml
файл:
<env name="STRIPE_SECRET" value="sk_test_<your-key>"/>
Тепер, коли ви взаємодієте з Cashier під час тестування, він надсилатиме фактичні запити API до вашого середовища тестування Stripe. Для зручності слід попередньо заповнити свій тестовий акаунт Stripe підписками / планами, які потім можна використовувати під час тестування.
Для тестування різноманітних сценаріїв виставлення рахунків, таких як відмови та помилки на кредитних картках, ви можете використовувати широкий спектртестування номерів карток та жетонівнадає Stripe.