Laravel Cashier Paddle
- Вступ
- Оновлення Cashier
- Встановлення
- Конфігурація
- Основні поняття
- Ціни
- Клієнти
- Підписки
- Випробувальні підписки
- Обробка Paddle веб-хуків
- Одноразові списання
- Receipts
- Обробка невдалих платежів
- Тестування
Вступ
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_created
webhook буде відправлений з 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_updated
webhook буде надіслано компанією 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 як виняток у вашомуVerifyCsrfToken
Middleware або перелічіть маршрут за межамиweb
група проміжного програмного забезпечення:
protected $except = [
'paddle/*',
];
Визначення обробників подій Webhook
Каса автоматично обробляє скасування підписки за невдалі платежі, але якщо у вас є додаткові події веб-хука, які ви хотіли б обробити, вам слід продовжитиWebhookController
. Назви ваших методів повинні відповідати очікуваним умовам Cashierра, зокрема, методи повинні мати префіксhandle
і назва "справи верблюда" веб-гачка, з яким ви хочете обробити. Наприклад, якщо ви хочете обробляти файлpayment_succeeded
webhook, вам слід додати 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_failed
webhook і ввімкнення опції "Не вдалося здійснити оплату підписки" в налаштуваннях 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% знижкою або безкоштовні товари під час тестування.