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

Laravel Cashier Paddle

Вступ

Laravel Cashier Paddle забезпечує виразний, вільний інтерфейс дляPaddleпослуги оплати підписки. Він обробляє майже весь код оплати підписки, який ви боїтеся. На додаток до основного управління передплатою, Cashierр може обробляти: купони, обмін підпискою, "кількість" підписки, пільгові періоди скасування тощо.

Під час співпраці з Cashier ми рекомендуємо вам також звертатися до Paddle'sпосібники користувачаіДокументація API.

Оновлення Cashier

Під час оновлення до нової версії Cashier важливо уважно переглянутипосібник з оновлення.

Встановлення

По-перше, вимагайте пакет Cashier для Paddle with Composer:

composer require laravel/cashier-paddle
Щоб гарантувати, що Cashierр правильно обробляє всі події Paddle, пам’ятайтеналаштувати обробку веб-хука Cashierра.

Міграції баз даних

Постачальник послуг Cashier реєструє власний каталог міграції бази даних, тому не забудьте перенести вашу базу даних після встановлення пакету. Міграція Cashierра створить новуcustomersтаблиця. Крім того, новийsubscriptionsбуде створена таблиця для зберігання всіх підписок вашого клієнта. Нарешті, новийreceiptsбуде створена таблиця для зберігання всієї інформації про квитанцію:

php artisan migrate

Якщо вам потрібно переписати міграції, що постачаються разом із пакетом Cashier, ви можете опублікувати їх за допомогоюvendor:publishКоманда ремісників:

php artisan vendor:publish --tag="cashier-migrations"

Якщо ви хочете запобігти повному запуску міграції Cashier, ви можете скористатисяignoreMigrationsнадані Cashierром. Як правило, цей метод слід викликати вregisterметод вашогоAppServiceProvider:

use Laravel\Paddle\Cashier;

Cashier::ignoreMigrations();

Конфігурація

Billable Модель

Перед використанням Cashier ви повинні додатиBillableвластивість до визначення вашої моделі користувача. Ця риса пропонує різні методи, що дозволяють виконувати загальні завдання щодо виставлення рахунків, такі як створення підписок, застосування купонів та оновлення інформації про спосіб оплати:

use Laravel\Paddle\Billable;

class User extends Authenticatable
{
    use Billable;
}

Якщо у вас є платні сутності, які не є користувачами, ви також можете додати ознаку до цих класів:

use Laravel\Paddle\Billable;

class Team extends Model
{
    use Billable;
}

Ключі API

Далі слід налаштувати ключі Paddle у вашому.envфайл. Ви можете отримати свої ключі API Paddle з панелі управління Paddle:

PADDLE_VENDOR_ID=your-paddle-vendor-id
PADDLE_VENDOR_AUTH_CODE=your-paddle-vendor-auth-code
PADDLE_PUBLIC_KEY="your-paddle-public-key"

Paddle JS

Paddle покладається на власну бібліотеку JavaScript, щоб ініціювати віджет перевірки Paddle. Ви можете завантажити бібліотеку JavaScript, розмістивши@paddleJSдирективу безпосередньо перед закриттям макета вашого додатка</head>тег:

<head>
    ...

    @paddleJS
</head>

Конфігурація валюти

Валютою Cashier за замовчуванням є долари США (USD). Ви можете змінити валюту за замовчуванням, встановившиCASHIER_CURRENCYзмінна середовища:

CASHIER_CURRENCY=EUR

Окрім налаштування валюти Cashier, Ви також можете вказати локаль, який використовуватиметься при форматуванні грошових значень для відображення на рахунках-фактурах. Внутрішньо Cashierр використовуєPHPNumberFormatterкласщоб встановити локаль валюти:

CASHIER_CURRENCY_LOCALE=nl_BE
Для того, щоб використовувати локалі, крімen, забезпечитиext-intlРозширення PHP встановлено та налаштовано на вашому сервері.

Основні поняття

Платні посилання

Paddle не має розширеного API CRUD для зміни стану. Тому більшість взаємодій з Paddle здійснюються черезйого віджет оформлення замовлення. Перш ніж ми зможемо відобразити віджет оплати, ми створимо "посилання на оплату" за допомогою Cashier:

$user = User::find(1);

$payLink = $user->newSubscription('default', $premium = 34567)
    ->returnTo(route('home'))
    ->create();

return view('billing', ['payLink' => $payLink]);

Cashierр включає в себеpaddle-buttonКомпонент Blade. Ми можемо передати URL-адресу посилання на оплату цьому компоненту як "підставку". Після натискання цієї кнопки відображатиметься віджет оформлення замовлення Paddle:

<x-paddle-button :url="$payLink" class="px-8 py-4">
    Subscribe
</x-paddle-button>

За замовчуванням на ньому відображатиметься кнопка зі стандартним стилем Paddle. Ви можете видалити всі стилі Paddle, додавшиdata-theme="none"атрибут компонента:

<x-paddle-button :url="$payLink" class="px-8 py-4" data-theme="none">
    Subscribe
</x-paddle-button>

Віджет виплати Paddle є асинхронним. Після того, як користувач створить або оновить підписку у віджеті, Paddle надішле веб-хуки нашої програми, щоб ми могли належним чином оновити стан підписки у власній базі даних. Тому важливо, щоб ви були належним чиномналаштувати веб-хукищоб пристосуватись до змін штату від Paddle.

Після зміни стану підписки затримка отримання відповідного веб-хука, як правило, мінімальна, але вам слід врахувати це у своїй програмі, враховуючи, що підписка вашого користувача може бути недоступна відразу після завершення оформлення замовлення.

Для отримання додаткової інформації ви можете переглянутидокументація API Paddle щодо генерації посилань на оплату.

Вбудована оплата

Якщо ви не хочете використовувати віджет для оформлення замовлення в стилі "overlay", Paddle також має можливість відображати віджет вбудовано. Хоча такий підхід не дозволяє вам налаштувати жодне з полів HTML Cashier, він дозволяє вбудовувати віджет у вашу програму.

Щоб полегшити вам початок роботи з вбудованою Cashier, Cashier включає в себеpaddle-checkoutКомпонент Blade. Для початку вам слідсформувати посилання на оплатуі передайте посилання на оплату компонентуoverrideатрибут:

<x-paddle-checkout :override="$payLink" class="w-full" />

Щоб відрегулювати висоту вбудованого компонента оформлення замовлення, ви можете передатиheightатрибут компонента Blade:

<x-paddle-checkout :override="$payLink" class="w-full" height="500" />

Вбудована оплата без посилань на оплату

Крім того, ви можете налаштувати віджет за допомогою власних параметрів замість використання посилання на оплату:

$options = [
    'product' => $productId,
    'title' => 'Product Title',
];

<x-paddle-checkout :options="$options" class="w-full" />

Будь ласка, зверніться до Paddle'sпутівник по Inline Checkoutа також їхПосилання на параметридля отримання детальної інформації про доступні варіанти.

Якщо ви хочете також використовуватиpassthroughпараметр під час вказівки користувацьких параметрів, ви повинні надати масив ключ / значення, оскільки Cashier буде автоматично обробляти перетворення масиву в рядок JSON. Крім того,customer_idПараметр passthrough зарезервований для внутрішнього використання Cashierра.

Ідентифікація користувача

На відміну від Stripe, користувачі Paddle унікальні для всього Paddle, а не унікальні для кожного акаунта Paddle. Через це API Paddle наразі не надають способу оновлення даних користувача, таких як їх електронна адреса. При формуванні посилань на оплату Paddle визначає користувачів за допомогоюcustomer_emailпараметр. Створюючи підписку, Paddle спробує встановити відповідність наданого користувачем електронного листа існуючому користувачеві Paddle.

У світлі такої поведінки є кілька важливих речей, про які слід пам’ятати, користуючись Cashier та Paddle. По-перше, ви повинні пам’ятати, що навіть якщо підписки в Cashier пов’язані з одним користувачем програми,їх можна прив'язати до різних користувачів у внутрішніх системах Paddle. По-друге, кожна підписка має свою підключену інформацію про спосіб оплати, а також може мати різні адреси електронної пошти у внутрішніх системах Paddle (залежно від того, яка електронна пошта була призначена користувачеві під час створення підписки).

Тому, показуючи підписки, ви завжди повинні повідомляти користувачеві, яка електронна адреса чи інформація про спосіб оплати підключена до підписки на основі підписки. Отримати цю інформацію можна наступними методами наSubscriptionмодель:

$subscription = $user->subscription('default');

$customerEmailAddress = $subscription->paddleEmail();
$paymentMethod = $subscription->paymentMethod();
$cardBrand = $subscription->cardBrand();
$cardLastFour = $subscription->cardLastFour();
$cardExpirationDate = $subscription->cardExpirationDate();

Наразі неможливо змінити електронну адресу користувача за допомогою API Paddle. Коли користувач хоче оновити свою електронну адресу в Paddle, єдиний спосіб зробити це - зв’язатися зі службою підтримки Paddle. Спілкуючись із Paddle, вони повинні надатиpaddleEmailзначення підписки на допомогу Paddle в оновленні правильного користувача.

Ціни

Paddle дозволяє налаштовувати ціни на валюту, по суті, дозволяючи налаштовувати різні ціни для різних країн. Cashier Paddle дозволяє отримати всі ціни на певний товар за допомогоюproductPricesметод:

use Laravel\Paddle\Cashier;

// Retrieve prices for two products...
$prices = Cashier::productPrices([123, 456]);

Валюта визначатиметься на основі IP-адреси запиту; однак за бажанням ви можете вказати конкретну країну для отримання цін на:

use Laravel\Paddle\Cashier;

// Retrieve prices for two products...
$prices = Cashier::productPrices([123, 456], ['customer_country' => 'BE']);

Отримавши ціни, ви можете відображати їх як завгодно:

<ul>
    @foreach ($prices as $price)
        <li>{{ $price->product_title }} - {{ $price->price()->gross() }}</li>
    @endforeach
</ul>

Ви також можете відобразити ціну нетто (без податку) та окремо відобразити суму податку:

<ul>
    @foreach ($prices as $price)
        <li>{{ $price->product_title }} - {{ $price->price()->net() }} (+ {{ $price->price()->tax() }} tax)</li>
    @endforeach
</ul>

Якщо ви отримали ціни на тарифні плани, ви можете відобразити їх початкову та періодичну ціну окремо:

<ul>
    @foreach ($prices as $price)
        <li>{{ $price->product_title }} - Initial: {{ $price->initialPrice()->gross() }} - Recurring: {{ $price->recurringPrice()->gross() }}</li>
    @endforeach
</ul>

Для отримання додаткової інформації,перевірте документацію API Paddle щодо цін.

Клієнти

Якщо користувач вже є клієнтом, і ви хочете відобразити ціни, що стосуються цього клієнта, ви можете зробити це, отримавши ціни безпосередньо з екземпляра клієнта:

use App\Models\User;

// Retrieve prices for two products...
$prices = User::find(1)->productPrices([123, 456]);

Внутрішньо Cashierр використовуватиме користувальницькіpaddleCountryметодотримати ціни в їх валюті. Так, наприклад, користувач, який проживає в США, бачитиме ціни в доларах США, тоді як користувач у Бельгії бачитиме ціни в євро. Якщо не вдається знайти відповідну валюту, буде використана валюта за замовчуванням продукту. Ви можете налаштувати всі ціни на товар або план підписки на панелі керування Paddle.

Купони

Ви також можете вибрати відображення цін після зниження купона. При дзвінку вproductPricesметоду, купони можуть передаватися у Шаблоні рядка, розділеного комами:

use Laravel\Paddle\Cashier;

$prices = Cashier::productPrices([123, 456], ['coupons' => 'SUMMERSALE,20PERCENTOFF']);

Потім відобразіть розраховані ціни за допомогоюpriceметод:

<ul>
    @foreach ($prices as $price)
        <li>{{ $price->product_title }} - {{ $price->price()->gross() }}</li>
    @endforeach
</ul>

Ви можете відображати оригінальні перелічені ціни (без купонних знижок) за допомогоюlistPriceметод:

<ul>
    @foreach ($prices as $price)
        <li>{{ $price->product_title }} - {{ $price->listPrice()->gross() }}</li>
    @endforeach
</ul>
При використанні API цін, Paddle дозволяє застосовувати купони лише до продуктів одноразової покупки, а не до планів підписки.

Клієнти

Клієнт Defaults

Каса дозволяє встановити деякі корисні значення за замовчуванням для вашого клієнта при створенні посилань на оплату. Встановлення цих значень за замовчуванням дозволяє попередньо заповнити адресу електронної пошти, країну та поштовий індекс клієнта, щоб вони могли негайно перейти до платіжної частини віджета оформлення замовлення. Ви можете встановити ці значення за замовчуванням, замінивши наведені нижче способи для вашого платного користувача:

/**
 * Get the customer's email address to associate with Paddle.
 *
 * @return string|null
 */
public function paddleEmail()
{
    return $this->email;
}

/**
 * Get the customer's country to associate with Paddle.
 *
 * This needs to be a 2 letter code. See the link below for supported countries.
 *
 * @return string|null
 * @link https://developer.paddle.com/reference/platform-parameters/supported-countries
 */
public function paddleCountry()
{
    //
}

/**
 * Get the customer's postcode to associate with Paddle.
 *
 * See the link below for countries which require this.
 *
 * @return string|null
 * @link https://developer.paddle.com/reference/platform-parameters/supported-countries#countries-requiring-postcode
 */
public function paddlePostcode()
{
    //
}

Ці значення за замовчуванням будуть використовуватися для кожної дії в Касі, яка генерує aпосилання на оплату.

Підписки

Створення підписки

Щоб створити підписку, спочатку отримайте екземпляр вашої платної моделі, який зазвичай буде екземпляромApp\Models\User. Отримавши екземпляр моделі, ви можете використовуватиnewSubscriptionметод створення посилання на оплату підписки на модель:

$user = User::find(1);

$payLink = $user->newSubscription('default', $premium = 12345)
    ->returnTo(route('home'))
    ->create();

return view('billing', ['payLink' => $payLink]);

Перший аргумент, переданий вnewSubscriptionметод повинен бути назвою підписки. Якщо ваша програма пропонує лише одну підписку, ви можете зателефонувати за цим номеромdefaultабоprimary. Другим аргументом є конкретний план, на який користувач підписується. Це значення має відповідати ідентифікатору плану в Paddle.returnToметод приймає URL-адресу, на яку ваш користувач буде перенаправлений після успішного завершення оформлення замовлення.

createметод створить посилання на оплату, яке можна використовувати для створення кнопки оплати. Кнопку оплати можна створити за допомогоюpaddle-buttonКомпонент Blade, який постачається з Cashier Paddle:

<x-paddle-button :url="$payLink" class="px-8 py-4">
    Subscribe
</x-paddle-button>

Після того, як користувач закінчив оплату, asubscription_createdwebhook буде відправлений з Paddle. Cashierр отримає цей веб-хук та налаштує підписку для вашого клієнта. Для того, щоб переконатися, що всі веб-хуки належним чином отримані та оброблені вашою програмою, переконайтеся, що у вас є належним чиномналаштування обробки веб-хука - -.

Додаткові деталі

Якщо ви хочете вказати додаткові дані про клієнта або підписку, ви можете зробити це, передавши їх як масив ключа / значення вcreateметод:

$payLink = $user->newSubscription('default', $monthly = 12345)
    ->returnTo(route('home'))
    ->create([
        'vat_number' => $vatNumber,
    ]);

Щоб дізнатись більше про додаткові поля, які підтримує Paddle, перегляньте документацію Paddle нагенерування посилань на оплату.

Купони

Якщо ви хочете застосувати купон під час створення підписки, ви можете використовуватиwithCouponметод:

$payLink = $user->newSubscription('default', $monthly = 12345)
    ->returnTo(route('home'))
    ->withCoupon('code')
    ->create();

Метадані

Ви також можете передавати масив метаданих за допомогоюwithMetadataметод:

$payLink = $user->newSubscription('default', $monthly = 12345)
    ->returnTo(route('home'))
    ->withMetadata(['key' => 'value'])
    ->create();
При наданні метаданих уникайте їх використанняsubscription_nameяк ключ метаданих. Цей ключ зарезервований для внутрішнього використання Cashierром.

Перевірка статусу підписки

Після того, як користувач підписався на вашу програму, ви можете перевірити стан її підписки за допомогою різноманітних зручних методів. По-перше,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підписка активно підписується на щомісячний план:

if ($user->subscribedToPlan($monthly = 12345, 'default')) {
    //
}

Передаючи масив доsubscribedToPlanметодом, ви можете визначити, чи користувачdefaultпідписка активно підписується на місячний або річний план:

if ($user->subscribedToPlan([$monthly = 12345, $yearly = 54321], 'default')) {
    //
}

recurringметод може бути використаний для визначення того, чи користувач підписаний на даний момент і чи більше він не перебуває у пробному періоді:

if ($user->subscription('default')->recurring()) {
    //
}

Статус скасованої підписки

Щоб визначити, чи був користувач колись активним абонентом, але скасував підписку, ви можете скористатисяcancelledметод:

if ($user->subscription('default')->cancelled()) {
    //
}

Ви також можете визначити, чи скасував користувач підписку, але все ще перебуває на "пільговому періоді", поки підписка повністю не закінчиться. Наприклад, якщо користувач скасовує підписку 5 березня, термін дії якої спочатку планувався до 10 березня, користувач перебуває у "пільговому періоді" до 10 березня. Зверніть увагу, щоsubscribedметод все ще повертаєтьсяtrueпротягом цього часу:

if ($user->subscription('default')->onGracePeriod()) {
    //
}

Щоб визначити, скасував користувач підписку і чи не перебуває він у межах "пільгового періоду", ви можете скористатися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()->onTrial();
Subscription::query()->notOnTrial();
Subscription::query()->pastDue();
Subscription::query()->recurring();
Subscription::query()->ended();
Subscription::query()->paused();
Subscription::query()->notPaused();
Subscription::query()->onPausedGracePeriod();
Subscription::query()->notOnPausedGracePeriod();
Subscription::query()->cancelled();
Subscription::query()->notCancelled();
Subscription::query()->onGracePeriod();
Subscription::query()->notOnGracePeriod();

Статус простроченого терміну

Якщо плата не вдається здійснити підписку, вона буде позначена якpast_due. Коли ваша підписка знаходиться в такому стані, вона не буде активною, поки клієнт не оновить свою платіжну інформацію. Ви можете визначити, чи прострочена підписка за допомогоюpastDueв екземплярі підписки:

if ($user->subscription('default')->pastDue()) {
    //
}

Коли термін підписки прострочений, ви повинні доручити користувачевіоновити свої платіжні дані. Ви можете налаштувати спосіб обробки прострочених підписок у вашомуНалаштування підписки на Paddle.

Якщо ви хочете, щоб підписки все ще вважалися активними, коли вони єpast_due, ви можете використовуватиkeepPastDueSubscriptionsActiveспосіб, наданий Cashierром. Як правило, цей метод слід викликати вregisterметод вашогоAppServiceProvider:

use Laravel\Paddle\Cashier;

/**
 * Register any application services.
 *
 * @return void
 */
public function register()
{
    Cashier::keepPastDueSubscriptionsActive();
}
Коли підписка знаходиться вpast_dueзаявіть, що його не можна змінити, поки не буде оновлено платіжну інформацію. ТомуswapіupdateQuantityметоди видадуть виняток, коли підписка знаходиться вpast_dueдержава.

Одноразова плата за підписку

Одноразова плата за підписку дозволяє платити Підписникам одноразовою оплатою поверх їхніх підписок:

$response = $user->subscription('default')->charge(12.99, 'Support Add-on');

На відміну відодноразові заряди, цей спосіб негайно стягуватиме з клієнта збережений спосіб оплати за підписку. Сума плати завжди вказана у валюті, для якої встановлено підписку.

Оновлення платіжної інформації

Paddle завжди зберігає спосіб оплати за підписку. Якщо ви хочете оновити спосіб оплати за замовчуванням для підписки, спочатку слід створити "URL-адресу оновлення" підписки, використовуючиupdateUrlметод на моделі підписки:

$user = App\Models\User::find(1);

$updateUrl = $user->subscription('default')->updateUrl();

Потім ви можете використовувати створену URL-адресу в поєднанні з наданою Cashierpaddle-buttonКомпонент Blade, що дозволяє користувачеві ініціювати віджет Paddle та оновлювати свою платіжну інформацію:

<x-paddle-button :url="$updateUrl" class="px-8 py-4">
    Update Card
</x-paddle-button>

Коли користувач закінчить оновлення своєї інформації, asubscription_updatedwebhook буде надіслано компанією Paddle, а деталі підписки будуть оновлені у базі даних вашої програми.

Зміна планів

Після того, як користувач підписався на вашу програму, він іноді може захотіти перейти на новий план підписки. Щоб замінити користувача на нову підписку, вам слід передати ідентифікатор плану Paddle на підпискуswapметод:

$user = App\Models\User::find(1);

$user->subscription('default')->swap($premium = 34567);

Якщо користувач пробується, пробний термін буде збережений. Крім того, якщо для підписки існує "кількість", ця кількість також буде збережена.

Якщо ви хочете поміняти місцями та скасувати будь-який пробний період, який зараз перебуває користувач, ви можете використовуватиskipTrialметод:

$user->subscription('default')
        ->skipTrial()
        ->swap($premium = 34567);

Якщо ви хочете поміняти місцями та негайно виставити рахунок користувачеві, а не чекати наступного платіжного циклу, ви можете використовуватиswapAndInvoiceметод:

$user = App\Models\User::find(1);

$user->subscription('default')->swapAndInvoice($premium = 34567);

Пропорції

За замовчуванням Paddle пропорційно стягує плату під час обміну між планами.noProrateметод може бути використаний для оновлення підписки без пропорційних витрат:

$user->subscription('default')->noProrate()->swap($premium = 34567);

Кількість підписки

Іноді на підписки впливає "кількість". Наприклад, за вашу програму може стягуватися 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);

Призупинення підписок

Щоб призупинити підписку, зателефонуйте на номерpauseметод підписки користувача:

$user->subscription('default')->pause();

Коли підписка призупинена, Cashierр автоматично встановлюєpaused_fromу вашій базі даних. Цей стовпець використовується, щоб знати, колиpausedметод повинен почати повертатисяtrue. Наприклад, якщо клієнт призупинить підписку 1 березня, але підписка не планувалась повторити до 5 березня,pausedметод продовжить повертатисяfalseдо 5 березня.

Ви можете визначити, чи користувач призупинив свою підписку, але все ще перебуває на "пільговому періоді", використовуючиonPausedGracePeriodметод:

if ($user->subscription('default')->onPausedGracePeriod()) {
    //
}

Щоб відновити призупинену підписку, ви можете зателефонувати доunpauseметод підписки користувача:

$user->subscription('default')->unpause();
Підписку не можна змінювати, поки вона призупинена. Якщо ви хочете перейти на інший план або оновити кількість, спочатку слід відновити підписку.

Скасування підписки

Щоб скасувати підписку, зателефонуйте на номер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();
Підписка на Paddle не може бути відновлена ​​після скасування. Якщо ваш клієнт бажає відновити підписку, йому доведеться підписатися на нову підписку.

Випробувальні підписки

Зі способом оплати вперед

Під час випробування та збору деталей способу оплати заздалегідь Paddle запобігає будь-яким змінам підписки, таким як обмін планами або оновлення кількості. Якщо ви хочете дозволити клієнту обмінятися планами під час пробного періоду, підписку потрібно скасувати та відновити.

Якщо ви хочете запропонувати пробні періоди своїм клієнтам, збираючи інформацію про спосіб оплати заздалегідь, вам слід використовуватиtrialDaysспосіб створення підписки на оплату посилань:

$user = User::find(1);

$payLink = $user->newSubscription('default', $monthly = 12345)
            ->returnTo(route('home'))
            ->trialDays(10)
            ->create();

return view('billing', ['payLink' => $payLink]);

Цей метод встановить дату закінчення пробного періоду в записі підписки в базі даних, а також вкаже Paddle не розпочинати виставлення рахунків клієнту до цієї дати.

Якщо підписка клієнта не буде скасована до дати закінчення пробного періоду, з них буде стягнуто плату, як тільки закінчиться пробна версія, тому ви повинні обов’язково повідомити своїх користувачів про дату закінчення пробного періоду.

Ви можете визначити, чи перебуває користувач протягом пробного періоду, використовуючи будь-який ізonTrialметод екземпляра користувача абоonTrialметод екземпляра підписки. Два наведені нижче приклади мають однакову поведінку:

if ($user->onTrial('default')) {
    //
}

if ($user->subscription('default')->onTrial()) {
    //
}

Визначення судових днів у Paddle / касі

You may choose to define how many trial days your plan's receive in the Paddle dashboard or always pass them explicitly using Cashier. If you choose to define your plan's trial days in Paddle you should be aware that new subscriptions, including new subscriptions for a customer that had a subscription in the past, will always receive a trial period unless you explicitly call the trialDays(0)метод.

Без способу оплати

Якщо ви хочете запропонувати пробні періоди без попереднього збору інформації про спосіб оплати користувача, ви можете встановитиtrial_ends_atстовпець у записі клієнта, прикріплений до вашого користувача до бажаної дати закінчення пробного періоду. Зазвичай це робиться під час реєстрації користувача:

$user = User::create([
    // Other user properties...
]);

$user->createAsCustomer([
    'trial_ends_at' => now()->addDays(10)
]);

Cashierр називає цей тип судового розгляду «загальним випробуванням», оскільки він не додається до жодної існуючої підписки.onTrialметод наUserекземпляр повернетьсяtrueякщо поточна дата не минула значенняtrial_ends_at:

if ($user->onTrial()) {
    // User is within their trial period...
}

Коли ви будете готові створити фактичну підписку для користувача, ви можете використовуватиnewSubscriptionметод, як зазвичай:

$user = User::find(1);

$payLink = $user->newSubscription('default', $monthly = 12345)
    ->returnTo(route('home'))
    ->create();

Щоб отримати дату завершення пробного періоду для користувача, ви можете використовуватиtrialEndsAtметод. Цей метод повертає екземпляр дати Carbon, якщо користувач пробний абоnullякщо їх немає. Ви також можете передати необов’язковий параметр імені підписки, якщо хочете отримати дату закінчення пробного періоду для певної підписки, крім стандартної:

if ($user->onTrial()) {
    $trialEndsAt = $user->trialEndsAt('main');
}

Ви також можете використовуватиonGenericTrialметод, якщо ви хочете конкретно знати, що користувач перебуває у межах "загального" пробного періоду і ще не створив фактичну підписку:

if ($user->onGenericTrial()) {
    // User is within their "generic" trial period...
}
Неможливо продовжити або змінити пробний період підписки на Paddle після її створення.

Обробка Paddle веб-хуків

Ви можете використовуватиВалеттshareкомандидля тестування веб-хуків під час локальної розробки.

Paddle може повідомляти вашу заявку про різноманітні події через веб-хуки. За замовчуванням маршрут, який вказує на контролер веб-хука Cashier, налаштовується через постачальника послуг Cashier. Цей контролер обробляє всі вхідні запити веб-хука.

За замовчуванням цей контролер буде автоматично обробляти скасування підписок, у яких занадто багато невдалих платежів (як визначено в налаштуваннях підписки на Paddle), оновлення підписки та зміни способу оплати; однак, як ми скоро дізнаємось, ви можете розширити цей контролер для обробки будь-якої події веб-хука, яка вам подобається.

Щоб ваша програма могла обробляти веб-хуки Paddle, обов’язковоналаштуйте URL-адресу веб-хука на панелі управління Paddle. За замовчуванням контролер веб-хука Cashierр прослуховує/paddle/webhookШлях URL. Повний список усіх веб-хуків, які слід налаштувати на панелі керування Paddle:

  • Підписка створена
  • Підписка оновлена
  • Підписку скасовано
  • Оплата виконана
  • Оплата підписки виконана
Обов’язково захистіть вхідні запити за допомогою Cashierперевірка підписуMiddleware.

Захист веб-хуків та CSRF

Оскільки веб-хуки Paddle повинні обходити LaravelЗахист CSRF, не забудьте вказати URI як виняток у вашомуVerifyCsrfTokenMiddleware або перелічіть маршрут за межамиwebгрупа проміжного програмного забезпечення:

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

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

Каса автоматично обробляє скасування підписки за невдалі платежі, але якщо у вас є додаткові події веб-хука, які ви хотіли б обробити, вам слід продовжитиWebhookController. Назви ваших методів повинні відповідати очікуваним умовам Cashierра, зокрема, методи повинні мати префіксhandleі назва "справи верблюда" веб-гачка, з яким ви хочете обробити. Наприклад, якщо ви хочете обробляти файлpayment_succeededwebhook, вам слід додати ahandlePaymentSucceededметод до контролера:

<?php

namespace App\Http\Controllers;

use Laravel\Paddle\Http\Controllers\WebhookController as CashierController;

class WebhookController extends CashierController
{
    /**
     * Handle payment succeeded.
     *
     * @param  array  $payload
     * @return void
     */
    public function handlePaymentSucceeded($payload)
    {
        // Handle The Event
    }
}

Далі визначте маршрут до свого контролера Cashier в межах вашогоroutes/web.phpфайл. Це перезапише маршрут, що входить до Cashier:

use App\Http\Controllers\WebhookController;

Route::post('paddle/webhook', WebhookController::class);

Cashierр виділяєLaravel\Paddle\Events\WebhookReceivedподія, коли отримано веб-хук іLaravel\Paddle\Events\WebhookHandledподія, коли оброблявся веб-хук. Обидві події містять повне навантаження веб-хука Paddle.

Cashierр також проводить події, присвячені типу отриманого веб-хука. На додаток до повного корисного навантаження від Paddle, вони також містять відповідні моделі, які використовувались для обробки веб-хука, такі як платна модель, підписка або квитанція:

  • PaymentSucceeded
  • SubscriptionPaymentSucceeded
  • SubscriptionCreated
  • SubscriptionUpdated
  • SubscriptionCancelled

Ви також можете замінити вбудований маршрут веб-хука за замовчуванням, встановившиCASHIER_WEBHOOKзмінну env у вашому.envфайл. Це значення має бути повною URL-адресою маршруту вашого веб-хука і має відповідати URL-адресі, встановленій на панелі керування Paddle:

CASHIER_WEBHOOK=https://example.com/my-paddle-webhook-url

Невдалі підписки

Що робити, якщо термін дії кредитної картки клієнта закінчується? Не хвилюйтеся - контролер Webhook Cashier скасує підписку клієнта для вас. Невдалі платежі будуть автоматично зафіксовані та оброблені контролером. Контролер скасовує підписку клієнта, коли Paddle виявляє, що підписка не вдалася (зазвичай після трьох невдалих спроб оплати).

Перевірка підписів Webhook

Для захисту веб-хуків ви можете використовуватиПідписи веб-гачка Paddle. Для зручності Cashier автоматично включає Middleware, яке підтверджує, що вхідний запит веб-хука Paddle є дійсним.

Щоб увімкнути перевірку веб-хука, переконайтеся, щоPADDLE_PUBLIC_KEYзмінна середовища встановлена ​​у вашому.envфайл. Відкритий ключ можна отримати з інформаційної панелі вашого акаунта Paddle.

Одноразові списання

Проста списання

Якщо ви хочете виставити клієнту одноразову оплату, ви можете використовуватиchargeметод на екземплярі платної моделі, щоб сформувати посилання на оплату за плату.chargeметод приймає суму комісії (float) як перший аргумент, а опис комісії як другий аргумент:

$payLink = $user->charge(12.99, 'Product Title');

return view('pay', ['payLink' => $payLink]);

Після генерації посилання на оплату ви можете використовувати надану касуpaddle-buttonКомпонент Blade, що дозволяє користувачеві ініціювати віджет Paddle і завершити зарядку:

<x-paddle-button :url="$payLink" class="px-8 py-4">
    Buy
</x-paddle-button>

chargeМетод приймає масив як свій третій аргумент, дозволяючи вам передавати будь-які параметри, які ви хочете, для базового створення посилання на оплату Paddle. Будь ласка, проконсультуйтесьдокументація на Paddleщоб дізнатись більше про варіанти, доступні вам під час створення нарахувань:

$payLink = $user->charge(12.99, 'Product Title', [
    'custom_option' => $value,
]);

Плата стягується у валюті, зазначеній уcashier.currencyваріант конфігурації. За замовчуванням для цього значення встановлено USD. Ви можете замінити валюту за замовчуванням, встановившиCASHIER_CURRENCYу вашому.envфайл:

CASHIER_CURRENCY=EUR

Ви також можетезамінити ціни на валютуза допомогою динамічної системи відповідності цін на Paddle. Для цього передайте масив цін замість фіксованої суми:

$payLink = $user->charge([
    'USD:19.99',
    'EUR:15.99',
], 'Product Title');

Charging Products

Якщо ви хочете зробити одноразову плату за певний продукт, налаштований в Paddle, ви можете використовуватиchargeProductметод на екземплярі платної моделі для формування посилання на оплату:

$payLink = $user->chargeProduct($productId);

return view('pay', ['payLink' => $payLink]);

Потім ви можете надати посилання на оплатуpaddle-buttonкомпонент, що дозволяє користувачеві ініціалізувати віджет Paddle:

<x-paddle-button :url="$payLink" class="px-8 py-4">
    Buy
</x-paddle-button>

chargeProductМетод приймає масив як другий аргумент, дозволяючи передавати будь-які параметри, які ви хочете, для базового створення посилання на оплату за допомогою Paddle. Будь ласка, проконсультуйтесьдокументація на Paddleщодо варіантів, доступних вам під час стягнення плати:

$payLink = $user->chargeProduct($productId, [
    'custom_option' => $value,
]);

Повернення коштів

Якщо вам потрібно повернути гроші за замовлення Paddle, ви можете скористатисяrefundметод. Цей метод приймає ідентифікатор замовлення Paddle як перший аргумент. Ви можете отримати квитанції для даної платної організації, використовуючиreceiptsметод:

$receipt = $user->receipts()->first();

$refundRequestId = $user->refund($receipt->order_id);

Ви також можете за бажанням вказати конкретну суму для відшкодування, а також причину відшкодування:

$receipt = $user->receipts()->first();

$refundRequestId = $user->refund(
    $receipt->order_id, 5.00, 'Unused product time'
);
Ви можете використовувати$refundRequestIdяк посилання на повернення коштів при зверненні до служби підтримки Paddle.

Квитанції

Ви можете легко отримати масив квитанцій оплачуваної моделі за допомогоюreceiptsметод:

$receipts = $user->receipts();

Перераховуючи квитанції для клієнта, ви можете використовувати допоміжні методи квитанції для відображення відповідної інформації про квитанцію. Наприклад, ви можете перерахувати кожну квитанцію в таблиці, що дозволить користувачеві легко завантажити будь-яку квитанцію:

<table>
    @foreach ($receipts as $receipt)
        <tr>
            <td>{{ $receipt->paid_at->toFormattedDateString() }}</td>
            <td>{{ $receipt->amount() }}</td>
            <td><a href="{{ $receipt->receipt_url }}" target="_blank">Download</a></td>
        </tr>
    @endforeach
</table>

Минулі та майбутні платежі

Ви можете використовуватиlastPaymentіnextPaymentметоди відображення минулих або майбутніх платежів клієнта за періодичні підписки:

$subscription = $user->subscription('default');

$lastPayment = $subscription->lastPayment();
$nextPayment = $subscription->nextPayment();

Обидва ці методи повернуть екземплярLaravel\Paddle\Payment; однак,nextPaymentповернетьсяnullколи платіжний цикл закінчився (наприклад, коли скасовано підписку):

Next payment: {{ $nextPayment->amount() }} due on {{ $nextPayment->date()->format('d/m/Y') }}

Обробка невдалих платежів

Платежі підписки зазнають невдачі з різних причин, таких як картки, термін дії яких закінчився, або картка, у якої недостатньо коштів. Коли це трапляється, ми рекомендуємо дозволити Paddle самостійно обробляти невдалі платежі. Зокрема, ви можетеналаштувати автоматичні електронні листи на рахунки Paddleна панелі приладів Paddle.

Крім того, ви можете виконати більш точну настройку, вловлюючиsubscription_payment_failedwebhook і ввімкнення опції "Не вдалося здійснити оплату підписки" в налаштуваннях Webhook на інформаційній панелі Paddle:

<?php

namespace App\Http\Controllers;

use Laravel\Paddle\Http\Controllers\WebhookController as CashierController;

class WebhookController extends CashierController
{
    /**
     * Handle subscription payment failed.
     *
     * @param  array  $payload
     * @return void
     */
    public function handleSubscriptionPaymentFailed($payload)
    {
        // Handle the failed subscription payment...
    }
}

Тестування

На даний момент у Paddle відсутній належний CRUD API, тому вам доведеться вручну протестувати свій платіжний потік. Paddle також не має середовища розробника, тому будь-які платежі, які ви робите, є реальними. Для того, щоб обійти цю проблему, ми рекомендуємо використовувати купони зі 100% знижкою або безкоштовні товари під час тестування.