Версія фреймворка: 8.x

Каса Laravel

Вступ

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 як виняток у вашомуVerifyCsrfTokenMiddleware або перелічіть маршрут за межамиwebгрупа проміжного програмного забезпечення:

protected $except = [
    'stripe/*',
];

Визначення обробників подій Webhook

Каса автоматично обробляє скасування підписки за невдалі платежі, але якщо у вас є додаткові події веб-хука, які ви хотіли б обробити, розширте контролер Webhook. Назви ваших методів повинні відповідати очікуваній умові Cashierра, зокрема, до методів слід вводити префіксhandleі назва "справи верблюда" веб-гачка, з яким ви хочете обробити. Наприклад, якщо ви хочете обробляти файлinvoice.payment_succeededwebhook, вам слід додати 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_requiredwebhook увімкнено на вашій інформаційній панелі 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.