نسخه:

صندوقدار لاراول (پادل)

معرفی

این مستندات برای ادغام Cashier Paddle 2.x با Paddle Billing است. اگر هنوز از Paddle Classic استفاده می کنید، باید از Cashier Paddle 1.x استفاده کنید .

Laravel Cashier Paddle یک رابط رسا و روان برای خدمات صورتحساب اشتراک Paddle فراهم می کند. تقریباً تمام کدهای صورت‌حساب اشتراک دیگ بخار را که از آن می‌ترسید مدیریت می‌کند. علاوه بر مدیریت اشتراک اولیه، Cashier می‌تواند این موارد را نیز انجام دهد: تعویض اشتراک، "مقدار" اشتراک، توقف اشتراک، مهلت لغو، و موارد دیگر.

قبل از کاوش در Cashier Paddle، توصیه می کنیم راهنمای مفهومی Paddle و اسناد API را نیز مرور کنید .

ارتقاء صندوقدار

هنگام ارتقاء به نسخه جدید Cashier، مهم است که راهنمای ارتقا را به دقت مرور کنید .

نصب و راه اندازی

ابتدا بسته Cashier را برای Paddle با استفاده از مدیریت بسته Composer نصب کنید:

composer require laravel/cashier-paddle

در مرحله بعد، باید فایل های مهاجرت Cashier را با استفاده از vendor:publish دستور Artisan منتشر کنید:

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

سپس، باید مهاجرت های پایگاه داده برنامه خود را اجرا کنید. مهاجرت صندوقدار یک customers جدول جدید ایجاد می کند. علاوه بر این، جداول جدید subscriptions و subscription_items برای ذخیره تمام اشتراک های مشتری شما ایجاد می شود. در نهایت، یک جدول جدید transactions برای ذخیره تمام تراکنش‌های Paddle مرتبط با مشتریان شما ایجاد می‌شود:

php artisan migrate

برای اطمینان از اینکه Cashier به درستی همه رویدادهای Paddle را مدیریت می کند، به یاد داشته باشید که کنترل وب هوک Cashier را تنظیم کنید .

جعبه شنی دست و پا زدن

در طول توسعه محلی و مرحله‌ای، باید یک حساب Paddle Sandbox ثبت کنید . این حساب به شما یک محیط سندباکس می دهد تا برنامه های خود را بدون پرداخت واقعی آزمایش و توسعه دهید. می‌توانید از شماره‌های کارت تست Paddle برای شبیه‌سازی سناریوهای پرداخت مختلف استفاده کنید.

هنگام استفاده از محیط Paddle Sandbox، باید PADDLE_SANDBOX متغیر محیط را true در فایل برنامه خود تنظیم کنید .env :

PADDLE_SANDBOX=true

پس از اتمام توسعه برنامه خود، می توانید برای یک حساب فروشنده Paddle درخواست دهید . قبل از اینکه برنامه شما وارد مرحله تولید شود، Paddle باید دامنه برنامه شما را تأیید کند.

پیکربندی

مدل قابل پرداخت

قبل از استفاده از Cashier، باید این Billable ویژگی را به تعریف مدل کاربری خود اضافه کنید. این ویژگی روش‌های مختلفی را ارائه می‌کند تا به شما امکان می‌دهد کارهای رایج صورت‌حساب را انجام دهید، مانند ایجاد اشتراک و به‌روزرسانی اطلاعات روش پرداخت:

use Laravel\Paddle\Billable;
 
class User extends Authenticatable
{
use Billable;
}

اگر نهادهای قابل پرداختی دارید که کاربر نیستند، می‌توانید این ویژگی را نیز به آن کلاس‌ها اضافه کنید:

use Illuminate\Database\Eloquent\Model;
use Laravel\Paddle\Billable;
 
class Team extends Model
{
use Billable;
}

کلیدهای API

در مرحله بعد، باید کلیدهای Paddle خود را در .env فایل برنامه خود پیکربندی کنید. می توانید کلیدهای Paddle API خود را از کنترل پنل Paddle بازیابی کنید:

PADDLE_CLIENT_SIDE_TOKEN=your-paddle-client-side-token
PADDLE_API_KEY=your-paddle-api-key
PADDLE_RETAIN_KEY=your-paddle-retain-key
PADDLE_WEBHOOK_SECRET="your-paddle-webhook-secret"
PADDLE_SANDBOX=true

وقتی از محیط Sandbox Paddle استفاده می کنید، متغیر محیط PADDLE_SANDBOX باید روی آن تنظیم شود . اگر برنامه خود را برای تولید پیاده سازی می کنید و از محیط فروشنده زنده Paddle استفاده می کنید، باید روی این متغیر تنظیم شود . true PADDLE_SANDBOX false

اختیاری است و فقط در صورتی باید تنظیم شود که از Paddle با Retain PADDLE_RETAIN_KEY استفاده می کنید .

Paddle JS

Paddle برای راه‌اندازی ویجت پرداخت Paddle به کتابخانه جاوا اسکریپت خود متکی است. می‌توانید کتابخانه جاوا اسکریپت را با قرار دادن @paddleJS دستورالعمل Blade درست قبل از برچسب بسته شدن طرح‌بندی برنامه خود بارگیری کنید </head> :

<head>
...
 
@paddleJS
</head>

پیکربندی ارز

می‌توانید محلی را برای قالب‌بندی مقادیر پولی برای نمایش در صورت‌حساب‌ها تعیین کنید. در داخل، Cashier از کلاس کلاس PHP NumberFormatter برای تنظیم محلی ارز استفاده می کند:

CASHIER_CURRENCY_LOCALE=nl_BE

به منظور استفاده از زبان‌های محلی به غیر از en ، مطمئن شوید که ext-intl پسوند PHP روی سرور شما نصب و پیکربندی شده است.

نادیده گرفتن مدل های پیش فرض

شما آزاد هستید که مدل های مورد استفاده داخلی توسط صندوقدار را با تعریف مدل خود و گسترش مدل صندوقدار مربوطه گسترش دهید:

use Laravel\Paddle\Subscription as CashierSubscription;
 
class Subscription extends CashierSubscription
{
// ...
}

پس از تعریف مدل خود، ممکن است به Cashier دستور دهید که از مدل سفارشی شما از طریق Laravel\Paddle\Cashier کلاس استفاده کند. به طور معمول، شما باید مدل های سفارشی خود را در boot روش کلاس برنامه خود به Cashier اطلاع دهید App\Providers\AppServiceProvider :

use App\Models\Cashier\Subscription;
use App\Models\Cashier\Transaction;
 
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Cashier::useSubscriptionModel(Subscription::class);
Cashier::useTransactionModel(Transaction::class);
}

شروع سریع

فروش محصولات

قبل از استفاده از Paddle Checkout، باید محصولات با قیمت های ثابت را در داشبورد Paddle خود تعریف کنید. علاوه بر این، باید کنترل وب هوک Paddle را پیکربندی کنید .

ارائه صورتحساب محصول و اشتراک از طریق برنامه شما می تواند ترسناک باشد. با این حال، به لطف Cashier و Paddle's Checkout Overlay ، می توانید به راحتی یکپارچه سازی پرداخت مدرن و قوی ایجاد کنید.

برای دریافت هزینه از مشتریان برای محصولات غیر تکراری و تک شارژ، ما از Cashier استفاده می‌کنیم تا از مشتریان با Paddle's Checkout Overlay هزینه دریافت کنیم، جایی که آنها جزئیات پرداخت خود را ارائه کرده و خرید خود را تأیید می‌کنند. هنگامی که پرداخت از طریق Checkout Overlay انجام شد، مشتری به یک URL موفقیت آمیز انتخابی شما در برنامه شما هدایت می شود:

use Illuminate\Http\Request;
 
Route::get('/buy', function (Request $request) {
$checkout = $request->user()->checkout('pri_deluxe_album')
->returnTo(route('dashboard'));
 
return view('buy', ['checkout' => $checkout]);
})->name('checkout');

همانطور که در مثال بالا می بینید، ما از checkout روش ارائه شده توسط Cashier برای ایجاد یک شیء پرداخت استفاده می کنیم تا به مشتری Paddle Checkout Overlay را برای یک "شناسه قیمت" معین ارائه کنیم. هنگام استفاده از Paddle، "قیمت ها" به قیمت های تعریف شده برای محصولات خاص اشاره دارد .

در صورت لزوم، این checkout روش به طور خودکار یک مشتری در Paddle ایجاد می کند و رکورد مشتری Paddle را به کاربر مربوطه در پایگاه داده برنامه شما متصل می کند. پس از اتمام جلسه تسویه حساب، مشتری به یک صفحه موفقیت اختصاصی هدایت می شود که در آن می توانید یک پیام اطلاعاتی برای مشتری نمایش دهید.

در buy نما، دکمه ای برای نمایش Checkout Overlay قرار می دهیم. جزء paddle-button Blade همراه با Cashier Paddle گنجانده شده است. با این حال، شما همچنین می توانید به صورت دستی یک پرداخت همپوشانی را ارائه دهید :

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

ارائه متا داده به Paddle Checkout

هنگام فروش محصولات، پیگیری سفارشات تکمیل‌شده و محصولات خریداری‌شده از طریق Cart و Order مدل‌هایی که توسط برنامه شخصی شما تعریف شده‌اند، معمول است. هنگام هدایت مشتریان به Paddle's Checkout Overlay برای تکمیل خرید، ممکن است لازم باشد یک شناسه سفارش موجود را ارائه دهید تا زمانی که مشتری به برنامه شما هدایت می شود، بتوانید خرید تکمیل شده را با سفارش مربوطه مرتبط کنید.

برای انجام این کار، ممکن است آرایه ای از داده های سفارشی را به checkout روش ارائه دهید. بیایید تصور کنیم Order زمانی که کاربر فرآیند پرداخت را شروع می‌کند، در برنامه ما یک معلق ایجاد می‌شود. به یاد داشته باشید، مدل‌های Cart و Order در این مثال گویا هستند و توسط Cashier ارائه نشده‌اند. شما آزاد هستید که این مفاهیم را بر اساس نیازهای برنامه خود پیاده سازی کنید:

use App\Models\Cart;
use App\Models\Order;
use Illuminate\Http\Request;
 
Route::get('/cart/{cart}/checkout', function (Request $request, Cart $cart) {
$order = Order::create([
'cart_id' => $cart->id,
'price_ids' => $cart->price_ids,
'status' => 'incomplete',
]);
 
$checkout = $request->user()->checkout($order->price_ids)
->customData(['order_id' => $order->id]);
 
return view('billing', ['checkout' => $checkout]);
})->name('checkout');

همانطور که در مثال بالا می بینید، زمانی که کاربر فرآیند پرداخت را شروع می کند، ما همه شناسه های قیمت Paddle مربوط به سبد خرید/سفارش را به روش ارائه می دهیم checkout . البته، اپلیکیشن شما مسئول مرتبط کردن این موارد با «سبد خرید» یا سفارشی است که مشتری آنها را اضافه می‌کند. ما همچنین شناسه سفارش را از طریق customData روش به Paddle Checkout Overlay ارائه می کنیم.

البته، احتمالاً می‌خواهید پس از اتمام فرآیند پرداخت، سفارش را به‌عنوان «کامل» علامت‌گذاری کنید. برای انجام این کار، می‌توانید به وب‌قلاب‌هایی که توسط Paddle ارسال شده و از طریق رویدادها توسط Cashier برای ذخیره اطلاعات سفارش در پایگاه داده خود ایجاد شده است، گوش دهید.

برای شروع، به TransactionCompleted رویداد ارسال شده توسط Cashier گوش دهید. به طور معمول، شما باید شنونده رویداد را در boot روش برنامه خود ثبت کنید AppServiceProvider :

use App\Listeners\CompleteOrder;
use Illuminate\Support\Facades\Event;
use Laravel\Paddle\Events\TransactionCompleted;
 
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Event::listen(TransactionCompleted::class, CompleteOrder::class);
}

در این مثال، CompleteOrder شنونده ممکن است به شکل زیر باشد:

namespace App\Listeners;
 
use App\Models\Order;
use Laravel\Cashier\Cashier;
use Laravel\Cashier\Events\TransactionCompleted;
 
class CompleteOrder
{
/**
* Handle the incoming Cashier webhook event.
*/
public function handle(TransactionCompleted $event): void
{
$orderId = $event->payload['data']['custom_data']['order_id'] ?? null;
 
$order = Order::findOrFail($orderId);
 
$order->update(['status' => 'completed']);
}
}

لطفاً برای اطلاعات بیشتر در مورد داده های موجود در transaction.completed رویداد به مستندات Paddle مراجعه کنید .

فروش اشتراک

قبل از استفاده از Paddle Checkout، باید محصولات با قیمت های ثابت را در داشبورد Paddle خود تعریف کنید. علاوه بر این، باید کنترل وب هوک Paddle را پیکربندی کنید .

ارائه صورتحساب محصول و اشتراک از طریق برنامه شما می تواند ترسناک باشد. با این حال، به لطف Cashier و Paddle's Checkout Overlay ، می توانید به راحتی یکپارچه سازی پرداخت مدرن و قوی ایجاد کنید.

برای یادگیری نحوه فروش اشتراک با استفاده از Cashier و Paddle's Checkout Overlay، اجازه دهید سناریوی ساده یک سرویس اشتراک با یک برنامه ماهانه ( price_basic_monthly ) و سالانه ( price_basic_yearly ) را در نظر بگیریم. این دو قیمت را می توان تحت یک محصول "پایه" ( pro_basic ) در داشبورد Paddle ما گروه بندی کرد. علاوه بر این، خدمات اشتراک ما ممکن است یک طرح متخصص به عنوان ارائه دهد pro_expert .

ابتدا، بیایید کشف کنیم که چگونه یک مشتری می تواند در خدمات ما مشترک شود. البته، می توانید تصور کنید که مشتری ممکن است روی دکمه "اشتراک" برای طرح پایه در صفحه قیمت برنامه ما کلیک کند. این دکمه یک Paddle Checkout Overlay را برای طرح انتخابی آنها فراخوانی می کند. برای شروع، اجازه دهید جلسه پرداخت را از طریق checkout روش زیر شروع کنیم:

use Illuminate\Http\Request;
 
Route::get('/subscribe', function (Request $request) {
$checkout = $request->user()->checkout('price_basic_monthly')
->returnTo(route('dashboard'));
 
return view('subscribe', ['checkout' => $checkout]);
})->name('subscribe');

در subscribe نما، دکمه ای برای نمایش Checkout Overlay قرار می دهیم. جزء paddle-button Blade همراه با Cashier Paddle گنجانده شده است. با این حال، شما همچنین می توانید به صورت دستی یک پرداخت همپوشانی را ارائه دهید :

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

اکنون با کلیک روی دکمه اشتراک، مشتری می‌تواند جزئیات پرداخت خود را وارد کرده و اشتراک خود را آغاز کند. برای اینکه بدانید واقعاً چه زمانی اشتراک آنها شروع شده است (از آنجایی که پردازش برخی از روش های پرداخت به چند ثانیه نیاز دارد)، باید مدیریت وب هوک Cashier را نیز پیکربندی کنید .

اکنون که مشتریان می توانند اشتراک را شروع کنند، باید بخش های خاصی از برنامه خود را محدود کنیم تا فقط کاربران مشترک بتوانند به آنها دسترسی داشته باشند. البته، ما همیشه می‌توانیم وضعیت اشتراک فعلی کاربر را از طریق subscribed روش ارائه شده توسط ویژگی Cashier تعیین کنیم Billable :

@if ($user->subscribed())
<p>You are subscribed.</p>
@endif

ما حتی می توانیم به راحتی تعیین کنیم که آیا کاربر مشترک محصول یا قیمت خاصی است یا خیر:

@if ($user->subscribedToProduct('pro_basic'))
<p>You are subscribed to our Basic product.</p>
@endif
 
@if ($user->subscribedToPrice('price_basic_monthly'))
<p>You are subscribed to our monthly Basic plan.</p>
@endif

ساخت میان افزار مشترک

برای راحتی، ممکن است بخواهید یک میان افزار ایجاد کنید که تعیین می کند آیا درخواست دریافتی از یک کاربر مشترک است یا خیر. هنگامی که این میان افزار تعریف شد، می توانید به راحتی آن را به مسیری اختصاص دهید تا از دسترسی کاربرانی که مشترک نیستند به مسیر جلوگیری کنید:

<?php
 
namespace App\Http\Middleware;
 
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
 
class Subscribed
{
/**
* Handle an incoming request.
*/
public function handle(Request $request, Closure $next): Response
{
if (! $request->user()?->subscribed()) {
// Redirect user to billing page and ask them to subscribe...
return redirect('/subscribe');
}
 
return $next($request);
}
}

هنگامی که میان افزار تعریف شد، می توانید آن را به یک مسیر اختصاص دهید:

use App\Http\Middleware\Subscribed;
 
Route::get('/dashboard', function () {
// ...
})->middleware([Subscribed::class]);

به مشتریان اجازه می دهد تا برنامه صورتحساب خود را مدیریت کنند

البته ممکن است مشتریان بخواهند طرح اشتراک خود را به محصول یا «سطح» دیگری تغییر دهند. در مثال بالا، می‌خواهیم به مشتری اجازه دهیم طرح خود را از اشتراک ماهانه به اشتراک سالانه تغییر دهد. برای این کار باید چیزی مانند دکمه ای را پیاده سازی کنید که به مسیر زیر منتهی می شود:

use Illuminate\Http\Request;
 
Route::put('/subscription/{price}/swap', function (Request $request, $price) {
$user->subscription()->swap($price); // With "$price" being "price_basic_yearly" for this example.
 
return redirect()->route('dashboard');
})->name('subscription.swap');

علاوه بر برنامه های مبادله، باید به مشتریان خود اجازه دهید اشتراک خود را لغو کنند. مانند برنامه های مبادله، دکمه ای را ارائه دهید که به مسیر زیر منتهی می شود:

use Illuminate\Http\Request;
 
Route::put('/subscription/cancel', function (Request $request, $price) {
$user->subscription()->cancel();
 
return redirect()->route('dashboard');
})->name('subscription.cancel');

و اکنون اشتراک شما در پایان دوره صورتحساب آن لغو خواهد شد.

تا زمانی که مدیریت وب هوک Cashier را پیکربندی کرده باشید، Cashier به طور خودکار جداول پایگاه داده مربوط به Cashier برنامه شما را با بازرسی وبکهک های دریافتی از Paddle همگام نگه می دارد. بنابراین، برای مثال، هنگامی که اشتراک مشتری را از طریق داشبورد Paddle لغو می‌کنید، Cashier وب هوک مربوطه را دریافت می‌کند و اشتراک را به‌عنوان «لغو شده» در پایگاه داده برنامه شما علامت‌گذاری می‌کند.

جلسات پرداخت

اکثر عملیات برای صورت‌حساب مشتریان با استفاده از «پرداخت‌ها» از طریق ویجت Paddle's Checkout Overlay یا با استفاده از پرداخت درون خطی انجام می‌شود .

قبل از پردازش پرداخت‌های پرداخت با استفاده از Paddle، باید پیوند پرداخت پیش‌فرض برنامه خود را در داشبورد تنظیمات پرداخت Paddle تعریف کنید.

پرداخت همپوشانی

قبل از نمایش ویجت Checkout Overlay، باید با استفاده از Cashier یک جلسه پرداخت ایجاد کنید. یک جلسه پرداخت، ویجت پرداخت را از عملیات صورت‌حساب که باید انجام شود مطلع می‌کند:

use Illuminate\Http\Request;
 
Route::get('/buy', function (Request $request) {
$checkout = $user->checkout('pri_34567')
->returnTo(route('dashboard'));
 
return view('billing', ['checkout' => $checkout]);
});

صندوقدار شامل یک paddle-button جزء تیغه است . شما می توانید جلسه پرداخت را به عنوان یک "سرپا" به این مؤلفه منتقل کنید. سپس، هنگامی که این دکمه کلیک می شود، ویجت پرداخت Paddle نمایش داده می شود:

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

به طور پیش‌فرض، ویجت را با استفاده از استایل پیش‌فرض Paddle نمایش می‌دهد. می‌توانید ویجت را با افزودن ویژگی‌های پشتیبانی شده از Paddle مانند data-theme='light' ویژگی به مؤلفه سفارشی کنید:

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

ویجت پرداخت Paddle ناهمزمان است. هنگامی که کاربر اشتراکی را در ویجت ایجاد کرد، Paddle برای برنامه شما یک webhook ارسال می کند تا بتوانید وضعیت اشتراک را در پایگاه داده برنامه خود به درستی به روز کنید. بنابراین، مهم است که به درستی وب هوک ها را برای تطبیق تغییرات وضعیت از Paddle تنظیم کنید .

پس از تغییر وضعیت اشتراک، تاخیر برای دریافت وب هوک مربوطه معمولاً حداقل است، اما باید با در نظر گرفتن این که اشتراک کاربر شما ممکن است بلافاصله پس از تکمیل پرداخت در دسترس نباشد، این را در برنامه خود در نظر بگیرید.

رندر کردن دستی یک پرداخت همپوشانی

همچنین می‌توانید بدون استفاده از اجزای Blade داخلی لاراول، یک پرداخت همپوشانی را به صورت دستی ارائه دهید. برای شروع، همانگونه که در مثال های قبلی نشان داده شد، جلسه پرداخت را ایجاد کنید :

use Illuminate\Http\Request;
 
Route::get('/buy', function (Request $request) {
$checkout = $user->checkout('pri_34567')
->returnTo(route('dashboard'));
 
return view('billing', ['checkout' => $checkout]);
});

در مرحله بعد، می توانید از Paddle.js برای مقداردهی اولیه پرداخت استفاده کنید. در این مثال، ما پیوندی ایجاد خواهیم کرد که به paddle_button کلاس اختصاص داده شده است. Paddle.js این کلاس را شناسایی می کند و هنگامی که روی پیوند کلیک می شود، پرداخت همپوشانی را نشان می دهد:

<?php
$items = $checkout->getItems();
$customer = $checkout->getCustomer();
$custom = $checkout->getCustomData();
?>
 
<a
href='#!'
class='paddle_button'
data-items='{!! json_encode($items) !!}'
@if ($customer) data-customer-id='{{ $customer->paddle_id }}' @endif
@if ($custom) data-custom-data='{{ json_encode($custom) }}' @endif
@if ($returnUrl = $checkout->getReturnUrl()) data-success-url='{{ $returnUrl }}' @endif
>
Buy Product
</a>

پرداخت درون خطی

اگر نمی‌خواهید از ویجت پرداخت به سبک «همپوشانی» Paddle استفاده کنید، Paddle همچنین گزینه‌ای برای نمایش ویجت درون خطی ارائه می‌کند. در حالی که این رویکرد به شما اجازه نمی دهد که هیچ یک از فیلدهای HTML پرداخت را تنظیم کنید، به شما امکان می دهد ویجت را در برنامه خود جاسازی کنید.

برای سهولت در شروع پرداخت درون خطی، Cashier شامل یک paddle-checkout جزء Blade است. برای شروع، باید یک جلسه پرداخت ایجاد کنید :

use Illuminate\Http\Request;
 
Route::get('/buy', function (Request $request) {
$checkout = $user->checkout('pri_34567')
->returnTo(route('dashboard'));
 
return view('billing', ['checkout' => $checkout]);
});

سپس، می توانید جلسه پرداخت را به ویژگی مؤلفه منتقل کنید checkout :

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

برای تنظیم ارتفاع مؤلفه پرداخت درون خطی، می توانید height ویژگی را به مؤلفه Blade منتقل کنید:

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

لطفاً برای جزئیات بیشتر در مورد گزینه‌های سفارشی‌سازی تسویه‌حساب داخلی، به راهنمای Paddle در مورد Inline Checkout و تنظیمات پرداخت موجود مراجعه کنید.

ارائه دستی پرداخت درون خطی

همچنین می توانید بدون استفاده از اجزای Blade داخلی لاراول، یک پرداخت درون خطی را به صورت دستی ارائه دهید. برای شروع، همانگونه که در مثال های قبلی نشان داده شد، جلسه پرداخت را ایجاد کنید :

use Illuminate\Http\Request;
 
Route::get('/buy', function (Request $request) {
$checkout = $user->checkout('pri_34567')
->returnTo(route('dashboard'));
 
return view('billing', ['checkout' => $checkout]);
});

در مرحله بعد، می توانید از Paddle.js برای مقداردهی اولیه پرداخت استفاده کنید. در این مثال، این را با استفاده از Alpine.js نشان خواهیم داد . با این حال، شما آزاد هستید که این مثال را برای پشته frontend خود تغییر دهید:

<?php
$options = $checkout->options();
 
$options['settings']['frameTarget'] = 'paddle-checkout';
$options['settings']['frameInitialHeight'] = 366;
?>
 
<div class="paddle-checkout" x-data="{}" x-init="
Paddle.Checkout.open(@json($options));
">
</div>

تسویه حساب مهمان

گاهی اوقات، ممکن است لازم باشد برای کاربرانی که نیازی به حساب کاربری در برنامه شما ندارند، یک جلسه پرداخت ایجاد کنید. برای انجام این کار، می توانید از guest روش زیر استفاده کنید:

use Illuminate\Http\Request;
use Laravel\Paddle\Checkout;
 
Route::get('/buy', function (Request $request) {
$checkout = Checkout::guest('pri_34567')
->returnTo(route('home'));
 
return view('billing', ['checkout' => $checkout]);
});

سپس، می توانید جلسه پرداخت را به دکمه Paddle یا اجزای Blade پرداخت درون خطی ارائه دهید .

پیش نمایش قیمت

Paddle به شما امکان می‌دهد قیمت‌ها را برای هر ارز سفارشی کنید و اساساً به شما امکان می‌دهد قیمت‌های مختلف را برای کشورهای مختلف پیکربندی کنید. Cashier Paddle به شما امکان می دهد تمام این قیمت ها را با استفاده از previewPrices روش بازیابی کنید. این روش شناسه‌های قیمتی را می‌پذیرد که می‌خواهید قیمت‌ها را برای آنها بازیابی کنید:

use Laravel\Paddle\Cashier;
 
$prices = Cashier::previewPrices(['pri_123', 'pri_456']);

ارز بر اساس آدرس IP درخواست تعیین می شود. با این حال، می‌توانید به صورت اختیاری کشور خاصی را برای بازیابی قیمت‌ها ارائه دهید:

use Laravel\Paddle\Cashier;
 
$prices = Cashier::productPrices(['pri_123', 'pri_456'], ['address' => [
'country_code' => 'BE',
'postal_code' => '1234',
]]);

پس از بازیابی قیمت ها، می توانید آنها را هر طور که می خواهید نمایش دهید:

<ul>
@foreach ($prices as $price)
<li>{{ $price->product['name'] }} - {{ $price->total() }}</li>
@endforeach
</ul>

همچنین می توانید قیمت فرعی و مبلغ مالیات را جداگانه نمایش دهید:

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

برای اطلاعات بیشتر، اسناد API Paddle را در مورد پیش‌نمایش قیمت بررسی کنید .

پیش نمایش قیمت مشتری

اگر کاربری قبلاً مشتری است و می‌خواهید قیمت‌هایی را که برای آن مشتری اعمال می‌شود نمایش دهید، می‌توانید این کار را با بازیابی قیمت‌ها مستقیماً از نمونه مشتری انجام دهید:

use App\Models\User;
 
$prices = User::find(1)->previewPrices(['pri_123', 'pri_456']);

به صورت داخلی، صندوقدار از شناسه مشتری کاربر برای بازیابی قیمت ها به واحد پول خود استفاده می کند. بنابراین، برای مثال، کاربری که در ایالات متحده زندگی می کند قیمت ها را به دلار آمریکا می بیند در حالی که کاربر در بلژیک قیمت ها را به یورو می بیند. اگر ارز مشابهی پیدا نشد، واحد پول پیش‌فرض محصول استفاده می‌شود. می‌توانید تمام قیمت‌های یک محصول یا طرح اشتراک را در کنترل پنل Paddle سفارشی کنید.

تخفیف ها

همچنین می توانید انتخاب کنید که قیمت ها را پس از تخفیف نمایش دهید. هنگام فراخوانی previewPrices روش، شناسه تخفیف را از طریق discount_id گزینه ارائه می دهید:

use Laravel\Paddle\Cashier;
 
$prices = Cashier::previewPrices(['pri_123', 'pri_456'], [
'discount_id' => 'dsc_123'
]);

سپس قیمت های محاسبه شده را نمایش دهید:

<ul>
@foreach ($prices as $price)
<li>{{ $price->product['name'] }} - {{ $price->total() }}</li>
@endforeach
</ul>

مشتریان

پیش فرض های مشتری

صندوقدار به شما امکان می دهد هنگام ایجاد جلسات پرداخت، چند پیش فرض مفید برای مشتریان خود تعریف کنید. تنظیم این پیش‌فرض‌ها به شما این امکان را می‌دهد که آدرس ایمیل و نام مشتری را از قبل پر کنید تا بتوانند بلافاصله به بخش پرداخت ویجت پرداخت وارد شوند. می‌توانید این پیش‌فرض‌ها را با لغو روش‌های زیر در مدل قابل پرداخت خود تنظیم کنید:

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

این پیش‌فرض‌ها برای هر اقدامی در صندوقدار که یک جلسه پرداخت ایجاد می‌کند، استفاده می‌شود .

بازیابی مشتریان

با استفاده از این روش می‌توانید یک مشتری را با شناسه مشتری Paddle او بازیابی کنید Cashier::findBillable . این روش نمونه ای از مدل قابل پرداخت را برمی گرداند:

use Laravel\Cashier\Cashier;
 
$user = Cashier::findBillable($customerId);

ایجاد مشتریان

گاهی اوقات، ممکن است بخواهید بدون شروع اشتراک، یک مشتری Paddle ایجاد کنید. شما می توانید این کار را با استفاده از createAsCustomer روش زیر انجام دهید:

$customer = $user->createAsCustomer();

یک نمونه از Laravel\Paddle\Customer بازگشت داده می شود. هنگامی که مشتری در Paddle ایجاد شد، می توانید در تاریخ بعد اشتراک خود را شروع کنید. می‌توانید یک $options آرایه اختیاری برای ارسال هر پارامتر ایجاد مشتری اضافی که توسط Paddle API پشتیبانی می‌شود ارائه دهید :

$customer = $user->createAsCustomer($options);

اشتراک ها

ایجاد اشتراک

برای ایجاد اشتراک، ابتدا نمونه ای از مدل قابل پرداخت خود را از پایگاه داده خود بازیابی کنید، که معمولاً نمونه ای از App\Models\User . هنگامی که نمونه مدل را بازیابی کردید، می توانید از این subscribe روش برای ایجاد جلسه پرداخت مدل استفاده کنید:

use Illuminate\Http\Request;
 
Route::get('/user/subscribe', function (Request $request) {
$checkout = $request->user()->subscribe($premium = 12345, 'default')
->returnTo(route('home'));
 
return view('billing', ['checkout' => $checkout]);
});

اولین آرگومان ارائه شده به subscribe روش، قیمت خاصی است که کاربر در آن مشترک است. این مقدار باید با شناسه قیمت در Paddle مطابقت داشته باشد. این returnTo روش یک URL را می‌پذیرد که کاربر شما پس از تکمیل موفقیت‌آمیز پرداخت، به آن هدایت می‌شود. دومین آرگومان ارسال شده به subscribe روش باید «نوع» داخلی اشتراک باشد. اگر برنامه شما فقط یک اشتراک ارائه می دهد، می توانید با این default یا تماس بگیرید primary . این نوع اشتراک فقط برای استفاده داخلی برنامه است و قرار نیست برای کاربران نمایش داده شود. علاوه بر این، نباید دارای فاصله باشد و هرگز نباید پس از ایجاد اشتراک تغییر کند.

همچنین می‌توانید آرایه‌ای از متا داده‌های سفارشی در رابطه با اشتراک با استفاده از customData روش ارائه دهید:

$checkout = $request->user()->subscribe($premium = 12345, 'default')
->customData(['key' => 'value'])
->returnTo(route('home'));

هنگامی که یک جلسه پرداخت اشتراک ایجاد شد، جلسه پرداخت ممکن است به paddle-button مؤلفه Blade که با Cashier Paddle ارائه شده است ارائه شود:

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

پس از اینکه کاربر پرداخت خود را به پایان رساند، یک subscription_created وب هوک از Paddle ارسال می شود. صندوقدار این وب هوک را دریافت می کند و اشتراک را برای مشتری شما تنظیم می کند. برای اطمینان از اینکه همه وبکهک‌ها به درستی دریافت شده و توسط برنامه شما مدیریت می‌شوند، مطمئن شوید که مدیریت وب‌هوک را به‌درستی تنظیم کرده‌اید .

بررسی وضعیت اشتراک

هنگامی که کاربر در برنامه شما مشترک شد، می توانید وضعیت اشتراک او را با استفاده از روش های مختلف مناسب بررسی کنید. ابتدا، اگر کاربر اشتراک معتبری داشته باشد، subscribed روش برمی گردد ، حتی اگر اشتراک در حال حاضر در دوره آزمایشی خود باشد: true

if ($user->subscribed()) {
// ...
}

اگر برنامه شما چندین اشتراک ارائه می دهد، می توانید اشتراک را هنگام فراخوانی subscribed روش مشخص کنید:

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

این subscribed روش همچنین یک کاندیدای عالی برای میان‌افزار مسیر است که به شما امکان می‌دهد دسترسی به مسیرها و کنترل‌کننده‌ها را بر اساس وضعیت اشتراک کاربر فیلتر کنید:

<?php
 
namespace App\Http\Middleware;
 
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
 
class EnsureUserIsSubscribed
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
if ($request->user() && ! $request->user()->subscribed()) {
// This user is not a paying customer...
return redirect('billing');
}
 
return $next($request);
}
}

اگر می خواهید تعیین کنید که آیا کاربر هنوز در دوره آزمایشی خود است، می توانید از این onTrial روش استفاده کنید. این روش می تواند برای تعیین اینکه آیا باید هشداری را به کاربر نشان دهید که هنوز در دوره آزمایشی خود است مفید باشد:

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

این subscribedToPrice روش ممکن است برای تعیین اینکه آیا کاربر در یک طرح معین بر اساس شناسه قیمت Paddle معین مشترک شده است یا خیر، استفاده شود. در این مثال، تعیین می کنیم که آیا اشتراک کاربر default به طور فعال در قیمت ماهانه مشترک است یا خیر:

if ($user->subscribedToPrice($monthly = 'pri_123', 'default')) {
// ...
}

این recurring روش ممکن است برای تعیین اینکه آیا کاربر در حال حاضر در یک اشتراک فعال است و دیگر در دوره آزمایشی خود نیست یا در یک دوره مهلت استفاده می شود استفاده شود:

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

وضعیت اشتراک لغو شده

برای تعیین اینکه آیا کاربر زمانی مشترک فعال بوده است اما اشتراک خود را لغو کرده است، می توانید از canceled روش زیر استفاده کنید:

if ($user->subscription()->canceled()) {
// ...
}

همچنین می‌توانید تعیین کنید که آیا کاربر اشتراک خود را لغو کرده است یا خیر، اما تا زمانی که اشتراک به طور کامل منقضی شود، همچنان در «دوره مهلت» است. به عنوان مثال، اگر کاربر اشتراکی را در تاریخ 5 مارس لغو کند که در ابتدا قرار بود در 10 مارس منقضی شود، کاربر تا 10 مارس در "مهلت مهلت" خود است. علاوه بر این، روش همچنان در این مدت subscribed باز خواهد گشت : true

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

وضعیت سررسید گذشته

اگر پرداخت برای اشتراک ناموفق باشد، به عنوان علامت گذاری می شود past_due . هنگامی که اشتراک شما در این وضعیت باشد، تا زمانی که مشتری اطلاعات پرداخت خود را به روز نکند، فعال نخواهد بود. می توانید با استفاده از pastDue روش موجود در نمونه اشتراک تعیین کنید که آیا یک اشتراک سررسید شده است:

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

هنگامی که سررسید اشتراک به پایان می رسد، باید به کاربر دستور دهید که اطلاعات پرداخت خود را به روز کند .

اگر می‌خواهید اشتراک‌ها هنوز معتبر تلقی شوند past_due ، می‌توانید از keepPastDueSubscriptionsActive روش ارائه شده توسط Cashier استفاده کنید. به طور معمول، این روش باید در register متد شما فراخوانی شود AppServiceProvider :

use Laravel\Paddle\Cashier;
 
/**
* Register any application services.
*/
public function register(): void
{
Cashier::keepPastDueSubscriptionsActive();
}

هنگامی که اشتراکی در past_due وضعیتی است، تا زمانی که اطلاعات پرداخت به روز نشده باشد، نمی توان آن را تغییر داد. بنابراین، متدهای swap و updateQuantity زمانی که اشتراک در یک وضعیت باشد، استثنا ایجاد می‌کند past_due .

محدوده های اشتراک

اکثر حالت های اشتراک نیز به عنوان محدوده پرس و جو در دسترس هستند، به طوری که می توانید به راحتی پایگاه داده خود را برای اشتراک هایی که در یک وضعیت خاص هستند پرس و جو کنید:

// Get all valid subscriptions...
$subscriptions = Subscription::query()->valid()->get();
 
// Get all of the canceled subscriptions for a user...
$subscriptions = $user->subscriptions()->canceled()->get();

لیست کاملی از دامنه های موجود در زیر موجود است:

Subscription::query()->valid();
Subscription::query()->onTrial();
Subscription::query()->expiredTrial();
Subscription::query()->notOnTrial();
Subscription::query()->active();
Subscription::query()->recurring();
Subscription::query()->pastDue();
Subscription::query()->paused();
Subscription::query()->notPaused();
Subscription::query()->onPausedGracePeriod();
Subscription::query()->notOnPausedGracePeriod();
Subscription::query()->canceled();
Subscription::query()->notCanceled();
Subscription::query()->onGracePeriod();
Subscription::query()->notOnGracePeriod();

هزینه های تک اشتراک

هزینه های تک اشتراک به شما این امکان را می دهد که مشترکین را با یک بار هزینه در کنار اشتراک خود شارژ کنید. هنگام فراخوانی روش باید یک یا چند شناسه قیمت ارائه کنید charge :

// Charge a single price...
$response = $user->subscription()->charge('pri_123');
 
// Charge multiple prices at once...
$response = $user->subscription()->charge(['pri_123', 'pri_456']);

این charge روش در واقع تا فاصله زمانی صورتحساب بعدی اشتراک مشتری، هزینه ای را از مشتری دریافت نمی کند. اگر می خواهید بلافاصله صورتحساب مشتری را دریافت کنید، می توانید chargeAndInvoice به جای آن از روش زیر استفاده کنید:

$response = $user->subscription()->chargeAndInvoice('pri_123');

به روز رسانی اطلاعات پرداخت

Paddle همیشه یک روش پرداخت را برای هر اشتراک ذخیره می کند. اگر می‌خواهید روش پرداخت پیش‌فرض را برای اشتراک به‌روزرسانی کنید، باید مشتری خود را با استفاده از redirectToUpdatePaymentMethod روش موجود در مدل اشتراک، به صفحه به‌روزرسانی روش پرداخت میزبانی‌شده Paddle هدایت کنید :

use Illuminate\Http\Request;
 
Route::get('/update-payment-method', function (Request $request) {
$user = $request->user();
 
return $user->subscription()->redirectToUpdatePaymentMethod();
});

هنگامی که کاربر به‌روزرسانی اطلاعات خود را به پایان رساند، یک subscription_updated وب هوک توسط Paddle ارسال می‌شود و جزئیات اشتراک در پایگاه داده برنامه شما به‌روزرسانی می‌شود.

تغییر برنامه ها

پس از اینکه کاربر در برنامه شما مشترک شد، ممکن است گهگاه بخواهد به یک طرح اشتراک جدید تغییر کند. برای به روز رسانی طرح اشتراک برای یک کاربر، باید شناسه قیمت Paddle را به swap روش اشتراک ارسال کنید:

use App\Models\User;
 
$user = User::find(1);
 
$user->subscription()->swap($premium = 'pri_456');

اگر می‌خواهید به جای اینکه برای چرخه صورت‌حساب بعدی کاربر منتظر بمانید، برنامه‌ها را مبادله کنید و فوراً فاکتور بگیرید، می‌توانید از swapAndInvoice روش زیر استفاده کنید:

$user = User::find(1);
 
$user->subscription()->swapAndInvoice($premium = 'pri_456');

تناسب

به‌طور پیش‌فرض، Paddle هنگام جابجایی بین طرح‌ها، هزینه‌ها را نسبت می‌دهد. این noProrate روش ممکن است برای به‌روزرسانی اشتراک‌ها بدون نسبت هزینه‌ها استفاده شود:

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

اگر می‌خواهید فوراً نسبت به مشتریان غیرفعال شود، می‌توانید از این swapAndInvoice روش در ترکیب با موارد زیر استفاده کنید noProrate :

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

یا برای اینکه از مشتری خود برای تغییر اشتراک صورت حساب نگیرید، می توانید از doNotBill روش زیر استفاده کنید:

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

برای اطلاعات بیشتر در مورد خط‌مشی‌های تناسب Paddle، لطفاً به مستندات سهمیه Paddle مراجعه کنید .

مقدار اشتراک

گاهی اوقات اشتراک ها تحت تأثیر "کمیت" قرار می گیرند. به عنوان مثال، یک برنامه مدیریت پروژه ممکن است 10 دلار در ماه برای هر پروژه هزینه کند. برای افزایش یا کاهش آسان تعداد اشتراک خود، از روش ها incrementQuantity و decrementQuantity روش های زیر استفاده کنید:

$user = User::find(1);
 
$user->subscription()->incrementQuantity();
 
// Add five to the subscription's current quantity...
$user->subscription()->incrementQuantity(5);
 
$user->subscription()->decrementQuantity();
 
// Subtract five from the subscription's current quantity...
$user->subscription()->decrementQuantity(5);

از طرف دیگر، می‌توانید مقدار خاصی را با استفاده از updateQuantity روش زیر تنظیم کنید:

$user->subscription()->updateQuantity(10);

این noProrate روش ممکن است برای به روز رسانی مقدار اشتراک بدون نسبت هزینه ها استفاده شود:

$user->subscription()->noProrate()->updateQuantity(10);

مقادیر برای اشتراک با چندین محصول

اگر اشتراک شما اشتراکی با چندین محصول است ، باید شناسه قیمتی را که می‌خواهید مقدار آن را افزایش یا کاهش دهید، به عنوان آرگومان دوم برای روش‌های افزایش/کاهش ارسال کنید:

$user->subscription()->incrementQuantity(1, 'price_chat');

اشتراک با چندین محصول

اشتراک با چندین محصول به شما امکان می دهد چندین محصول صورتحساب را به یک اشتراک اختصاص دهید. به عنوان مثال، تصور کنید که در حال ساختن یک برنامه «خدمات راهنمایی» برای خدمات مشتری هستید که قیمت اشتراک پایه آن 10 دلار در ماه است اما یک محصول افزودنی چت زنده را با 15 دلار اضافی در ماه ارائه می دهد.

هنگام ایجاد جلسات پرداخت اشتراک، می توانید چندین محصول را برای یک اشتراک معین با ارسال آرایه ای از قیمت ها به عنوان اولین آرگومان متد مشخص کنید subscribe :

use Illuminate\Http\Request;
 
Route::post('/user/subscribe', function (Request $request) {
$checkout = $request->user()->subscribe([
'price_monthly',
'price_chat',
]);
 
return view('billing', ['checkout' => $checkout]);
});

در مثال بالا، مشتری دو قیمت به default اشتراک خود خواهد داشت. هر دو قیمت در فواصل صورتحساب مربوطه محاسبه می شوند. در صورت لزوم، می توانید یک آرایه انجمنی از جفت کلید / ارزش را برای نشان دادن مقدار خاصی برای هر قیمت ارسال کنید:

$user = User::find(1);
 
$checkout = $user->subscribe('default', ['price_monthly', 'price_chat' => 5]);

اگر می خواهید قیمت دیگری به اشتراک موجود اضافه کنید، باید از swap روش اشتراک استفاده کنید. هنگام فراخوانی swap روش، باید قیمت ها و مقادیر فعلی اشتراک را نیز درج کنید:

$user = User::find(1);
 
$user->subscription()->swap(['price_chat', 'price_original' => 2]);

مثال بالا قیمت جدید را اضافه می کند، اما مشتری تا چرخه صورتحساب بعدی خود برای آن صورتحساب دریافت نمی کند. اگر می خواهید بلافاصله صورتحساب مشتری را دریافت کنید، می توانید از swapAndInvoice روش زیر استفاده کنید:

$user->subscription()->swapAndInvoice(['price_chat', 'price_original' => 2]);

می‌توانید با استفاده از این swap روش قیمت‌ها را از اشتراک‌ها حذف کنید و قیمتی را که می‌خواهید حذف کنید حذف کنید:

$user->subscription()->swap(['price_original' => 2]);

نمی توانید آخرین قیمت اشتراک را حذف کنید. در عوض، شما باید به سادگی اشتراک را لغو کنید.

اشتراک های متعدد

Paddle به مشتریان شما اجازه می دهد تا چندین اشتراک را به طور همزمان داشته باشند. به عنوان مثال، شما ممکن است باشگاهی را اداره کنید که اشتراک شنا و وزنه برداری را ارائه می دهد و هر اشتراک ممکن است قیمت متفاوتی داشته باشد. البته، مشتریان باید بتوانند در یکی یا هر دو طرح مشترک شوند.

هنگامی که برنامه شما اشتراک ایجاد می کند، می توانید نوع اشتراک متد را subscribe به عنوان آرگومان دوم ارائه دهید. نوع ممکن است هر رشته ای باشد که نشان دهنده نوع اشتراکی است که کاربر شروع می کند:

use Illuminate\Http\Request;
 
Route::post('/swimming/subscribe', function (Request $request) {
$checkout = $request->user()->subscribe($swimmingMonthly = 'pri_123', 'swimming');
 
return view('billing', ['checkout' => $checkout]);
});

در این مثال، ما اشتراک ماهیانه شنا را برای مشتری آغاز کردیم. با این حال، آنها ممکن است بخواهند در زمان دیگری به اشتراک سالانه مبادله کنند. هنگام تنظیم اشتراک مشتری، می توانیم به سادگی قیمت swimming اشتراک را تعویض کنیم:

$user->subscription('swimming')->swap($swimmingYearly = 'pri_456');

البته، شما همچنین می توانید اشتراک را به طور کامل لغو کنید:

$user->subscription('swimming')->cancel();

توقف اشتراک ها

برای توقف موقت اشتراک، pause روش موجود در اشتراک کاربر را فراخوانی کنید:

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

هنگامی که یک اشتراک متوقف می شود، صندوقدار به طور خودکار paused_at ستون را در پایگاه داده شما تنظیم می کند. این ستون برای تعیین زمان paused شروع بازگشت متد استفاده می شود true . به عنوان مثال، اگر مشتری اشتراک خود را در اول مارس متوقف کند، اما قرار نبود اشتراک تا 5 مارس تکرار شود، این روش تا 5 مارس paused ادامه خواهد داشت . false این به این دلیل است که کاربر معمولاً مجاز است تا پایان چرخه صورت‌حساب خود از یک برنامه کاربردی استفاده کند.

به طور پیش‌فرض، مکث در بازه زمانی صورت‌حساب بعدی اتفاق می‌افتد تا مشتری بتواند از باقی‌مانده دوره‌ای که برای آن پرداخت کرده است استفاده کند. اگر می‌خواهید فوراً اشتراک را متوقف کنید، می‌توانید از pauseNow روش زیر استفاده کنید:

$user->subscription()->pauseNow();

با استفاده از pauseUntil روش، می‌توانید اشتراک را تا یک لحظه خاص متوقف کنید:

$user->subscription()->pauseUntil(now()->addMonth());

یا، می‌توانید از این pauseNowUntil روش برای توقف فوری اشتراک تا زمان معینی استفاده کنید:

$user->subscription()->pauseNowUntil(now()->addMonth());

onPausedGracePeriod با استفاده از این روش می‌توانید تعیین کنید که آیا کاربر اشتراک خود را موقتاً متوقف کرده است اما هنوز در "دوره مهلت" خود است :

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

برای از سرگیری اشتراک متوقف شده، می توانید از resume روش موجود در اشتراک استفاده کنید:

$user->subscription()->resume();

اشتراک در زمانی که موقتاً متوقف شده است قابل تغییر نیست. اگر می‌خواهید به طرح دیگری مبادله کنید یا مقادیر به‌روزرسانی کنید، ابتدا باید اشتراک را از سر بگیرید.

لغو اشتراک ها

برای لغو اشتراک، با cancel روش موجود در اشتراک کاربر تماس بگیرید:

$user->subscription()->cancel();

هنگامی که یک اشتراک لغو می شود، صندوقدار به طور خودکار ends_at ستون را در پایگاه داده شما تنظیم می کند. این ستون برای تعیین زمان subscribed شروع بازگشت متد استفاده می شود false . به عنوان مثال، اگر مشتری در تاریخ 1 مارس اشتراک خود را لغو کند، اما قرار نبود اشتراک تا 5 مارس پایان یابد، این روش تا 5 مارس subscribed ادامه خواهد داشت . true این کار به این دلیل انجام می شود که کاربر معمولاً مجاز است تا پایان چرخه صورتحساب خود از یک برنامه استفاده کند.

onGracePeriod با استفاده از این روش می‌توانید تعیین کنید که آیا کاربر اشتراک خود را لغو کرده است اما هنوز در «دوره مهلت» خود است :

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

اگر می‌خواهید فوراً اشتراک را لغو کنید، می‌توانید با cancelNow روش موجود در اشتراک تماس بگیرید:

$user->subscription()->cancelNow();

برای جلوگیری از لغو اشتراک در دوره مهلت، می توانید از stopCancelation روش زیر استفاده کنید:

$user->subscription()->stopCancelation();

اشتراک های Paddle پس از لغو قابل از سرگیری نمی باشد. اگر مشتری شما بخواهد اشتراک خود را از سر بگیرد، باید اشتراک جدیدی ایجاد کند.

آزمایشات اشتراک

با روش پرداخت از قبل

اگر می‌خواهید در حالی که اطلاعات روش پرداخت را از قبل جمع‌آوری می‌کنید، دوره‌های آزمایشی را به مشتریان خود ارائه دهید، باید از تعیین زمان آزمایشی در داشبورد Paddle با قیمتی که مشتری شما مشترک آن است استفاده کنید. سپس، جلسه پرداخت را به طور معمول شروع کنید:

use Illuminate\Http\Request;
 
Route::get('/user/subscribe', function (Request $request) {
$checkout = $request->user()->subscribe('pri_monthly')
->returnTo(route('home'));
 
return view('billing', ['checkout' => $checkout]);
});

هنگامی که برنامه شما subscription_created رویداد را دریافت کرد، صندوقدار تاریخ پایان دوره آزمایشی را در سابقه اشتراک در پایگاه داده برنامه شما تنظیم می‌کند و همچنین به Paddle دستور می‌دهد تا پس از این تاریخ، صورت‌حساب مشتری را شروع نکند.

اگر اشتراک مشتری قبل از تاریخ پایان دوره آزمایشی لغو نشود، به محض انقضای دوره آزمایشی هزینه از آنها کسر می شود، بنابراین باید حتماً کاربران خود را از تاریخ پایان دوره آزمایشی مطلع کنید.

onTrial شما می توانید با استفاده از روش نمونه کاربر یا onTrial روش نمونه اشتراک تعیین کنید که آیا کاربر در دوره آزمایشی خود است . دو مثال زیر معادل هستند:

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

برای تعیین اینکه آیا دوره آزمایشی موجود منقضی شده است، می توانید از hasExpiredTrial روش های زیر استفاده کنید:

if ($user->hasExpiredTrial()) {
// ...
}
 
if ($user->subscription()->hasExpiredTrial()) {
// ...
}

برای تعیین اینکه آیا کاربر برای یک نوع اشتراک خاص در حال آزمایش است یا خیر، می‌توانید نوع یا onTrial روش‌های hasExpiredTrial زیر را ارائه دهید:

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

بدون روش پرداخت از قبل

اگر می‌خواهید دوره‌های آزمایشی را بدون جمع‌آوری اطلاعات روش پرداخت کاربر از قبل ارائه دهید، می‌توانید ستون trial_ends_at روی سابقه مشتری پیوست شده به کاربر خود را به تاریخ پایان آزمایشی مورد نظر خود تنظیم کنید. این معمولاً در هنگام ثبت نام کاربر انجام می شود:

use App\Models\User;
 
$user = User::create([
// ...
]);
 
$user->createAsCustomer([
'trial_ends_at' => now()->addDays(10)
]);

صندوقدار به این نوع آزمایش به عنوان یک "آزمایش عمومی" اشاره می کند، زیرا به هیچ اشتراک موجود متصل نیست. اگر تاریخ فعلی از مقدار زیر گذشته نباشد، متد onTrial موجود در User نمونه برمی‌گردد . true trial_ends_at

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

هنگامی که آماده ایجاد یک اشتراک واقعی برای کاربر هستید، می توانید subscribe طبق معمول از روش زیر استفاده کنید:

use Illuminate\Http\Request;
 
Route::get('/user/subscribe', function (Request $request) {
$checkout = $user->subscribe('pri_monthly')
->returnTo(route('home'));
 
return view('billing', ['checkout' => $checkout]);
});

برای بازیابی تاریخ پایان آزمایشی کاربر، می توانید از این trialEndsAt روش استفاده کنید. این روش در صورتی که کاربر در حال آزمایش باشد یا null نباشد، یک نمونه تاریخ کربن را برمی گرداند. همچنین اگر می‌خواهید تاریخ پایان آزمایشی برای یک اشتراک خاص غیر از اشتراک پیش‌فرض را دریافت کنید، می‌توانید یک پارامتر نوع اشتراک اختیاری را ارسال کنید:

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

onGenericTrial اگر می خواهید به طور خاص بدانید که کاربر در دوره آزمایشی "عمومی" خود است و هنوز اشتراک واقعی ایجاد نکرده است، می توانید از این روش استفاده کنید :

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

یک دوره آزمایشی را تمدید یا فعال کنید

می‌توانید یک دوره آزمایشی موجود در اشتراک را با فراخوانی extendTrial روش و مشخص کردن زمان پایان دوره آزمایشی تمدید کنید:

$user->subsription()->extendTrial(now()->addDays(5));

یا، می‌توانید فوراً اشتراکی را با پایان دوره آزمایشی آن با فراخوانی activate روش موجود در اشتراک، فعال کنید:

$user->subscription()->activate();

رسیدگی به قلاب های وب پارویی

Paddle می تواند برنامه شما را از رویدادهای مختلف از طریق وب هوک ها مطلع کند. به طور پیش فرض، مسیری که به کنترلر وب هوک Cashier اشاره می کند توسط ارائه دهنده خدمات Cashier ثبت می شود. این کنترلر تمام درخواست های وب هوک دریافتی را رسیدگی می کند.

به‌طور پیش‌فرض، این کنترل‌کننده به‌طور خودکار لغو اشتراک‌هایی را که هزینه‌های ناموفق زیادی دارند، به‌روزرسانی‌های اشتراک و تغییرات روش پرداخت انجام می‌دهد. با این حال، همانطور که به زودی متوجه خواهیم شد، می‌توانید این کنترلر را برای مدیریت هر رویداد Paddle webhook که دوست دارید گسترش دهید.

برای اطمینان از اینکه برنامه شما می‌تواند به وبک‌هوک‌های Paddle رسیدگی کند، حتماً URL وب هوک را در پانل کنترل Paddle پیکربندی کنید . به طور پیش فرض، کنترلر وب هوک Cashier به /paddle/webhook مسیر URL پاسخ می دهد. لیست کامل تمام وبی هوک هایی که باید در کنترل پنل Paddle فعال کنید عبارتند از:

  • مشتری به روز شد
  • معامله انجام شد
  • تراکنش به روز شد
  • اشتراک ایجاد شد
  • اشتراک به روز شد
  • اشتراک متوقف شد
  • اشتراک لغو شد

Webhooks و CSRF Protection

از آنجایی که وب‌هوک‌های Paddle باید حفاظت CSRF لاراول را دور بزنند ، باید اطمینان حاصل کنید که لاراول تلاشی برای تأیید توکن CSRF برای وب‌هوک‌های Paddle دریافتی نمی‌کند. برای انجام این کار، باید paddle/* از حفاظت CSRF در فایل برنامه خود حذف کنید bootstrap/app.php :

->withMiddleware(function (Middleware $middleware) {
$middleware->validateCsrfTokens(except: [
'paddle/*',
]);
})

وب هوک ها و توسعه محلی

برای اینکه Paddle بتواند وب هوک های برنامه شما را در طول توسعه محلی ارسال کند، باید برنامه خود را از طریق یک سرویس اشتراک گذاری سایت مانند Ngrok یا Expose در معرض دید قرار دهید . اگر برنامه خود را به صورت محلی با استفاده از Laravel Sail توسعه می دهید، می توانید از دستور اشتراک گذاری سایت Sail استفاده کنید .

تعریف مدیریت رویداد Webhook

صندوق دار به طور خودکار لغو اشتراک را در صورت هزینه های ناموفق و سایر وب هوک های رایج Paddle کنترل می کند. با این حال، اگر رویدادهای webhook دیگری دارید که می‌خواهید مدیریت کنید، می‌توانید این کار را با گوش دادن به رویدادهای زیر که توسط Cashier ارسال می‌شود انجام دهید:

  • Laravel\Paddle\Events\WebhookReceived
  • Laravel\Paddle\Events\WebhookHandled

هر دو رویداد حاوی بار کامل وب هوک Paddle هستند. برای مثال، اگر می‌خواهید transaction_billed وب هوک را مدیریت کنید، می‌توانید شنونده‌ای را ثبت کنید که رویداد را مدیریت کند:

<?php
 
namespace App\Listeners;
 
use Laravel\Paddle\Events\WebhookReceived;
 
class PaddleEventListener
{
/**
* Handle received Paddle webhooks.
*/
public function handle(WebhookReceived $event): void
{
if ($event->payload['alert_name'] === 'transaction_billed') {
// Handle the incoming event...
}
}
}

صندوقدار همچنین رویدادهای اختصاص داده شده به نوع وب هوک دریافتی را منتشر می کند. علاوه بر بار کامل از Paddle، آنها همچنین حاوی مدل‌های مربوطه هستند که برای پردازش وب‌قلاب استفاده شده‌اند، مانند مدل قابل صورت‌حساب، اشتراک یا رسید:

  • Laravel\Paddle\Events\CustomerUpdated
  • Laravel\Paddle\Events\TransactionCompleted
  • Laravel\Paddle\Events\TransactionUpdated
  • Laravel\Paddle\Events\SubscriptionCreated
  • Laravel\Paddle\Events\SubscriptionUpdated
  • Laravel\Paddle\Events\SubscriptionPaused
  • Laravel\Paddle\Events\SubscriptionCanceled

CASHIER_WEBHOOK همچنین می‌توانید با تعریف متغیر محیطی در فایل برنامه خود، مسیر پیش‌فرض و داخلی هوک را لغو کنید .env . این مقدار باید URL کامل مسیر وب هوک شما باشد و باید با URL تنظیم شده در پانل کنترل Paddle شما مطابقت داشته باشد:

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

تأیید امضاهای Webhook

برای ایمن سازی وب هوک های خود، می توانید از امضاهای وب هوک Paddle استفاده کنید . برای راحتی کار، Cashier به طور خودکار شامل یک میان افزار می شود که اعتبار درخواست دریافتی Paddle webhook را تأیید می کند.

برای فعال کردن تأیید وب هوک، مطمئن شوید که PADDLE_WEBHOOK_SECRET متغیر محیط در فایل برنامه شما تعریف شده است .env . راز webhook ممکن است از داشبورد حساب Paddle شما بازیابی شود.

شارژ تک

شارژ برای محصولات

اگر می‌خواهید خرید محصول را برای مشتری آغاز کنید، می‌توانید از روشی که checkout در نمونه‌ای از مدل قابل صدور صورت‌حساب است استفاده کنید تا یک جلسه پرداخت برای خرید ایجاد کنید. این checkout روش یک یا چند شناسه قیمت را می پذیرد. در صورت لزوم، ممکن است از یک آرایه انجمنی برای ارائه مقدار محصول خریداری شده استفاده شود:

use Illuminate\Http\Request;
 
Route::get('/buy', function (Request $request) {
$checkout = $request->user()->checkout(['pri_tshirt', 'pri_socks' => 5]);
 
return view('buy', ['checkout' => $checkout]);
});

پس از ایجاد جلسه پرداخت، می توانید از paddle-button مؤلفه Blade ارائه شده توسط Cashier استفاده کنید تا به کاربر اجازه دهید ویجت پرداخت Paddle را مشاهده کند و خرید را تکمیل کند:

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

جلسه تسویه حساب دارای customData روشی است که به شما امکان می دهد هر داده سفارشی را که می خواهید به ایجاد تراکنش اصلی منتقل کنید. لطفاً برای کسب اطلاعات بیشتر در مورد گزینه‌های موجود هنگام انتقال داده‌های سفارشی، به مستندات Paddle مراجعه کنید:

$checkout = $user->checkout('pri_tshirt')
->customData([
'custom_option' => $value,
]);

بازپرداخت تراکنش ها

تراکنش‌های بازپرداخت، مبلغ بازپرداخت شده را به روش پرداخت مشتری شما که در زمان خرید استفاده شده است، برمی‌گرداند. اگر نیاز به بازپرداخت خرید Paddle دارید، می‌توانید از این refund روش در Cashier\Paddle\Transaction مدل استفاده کنید. این روش یک دلیل را به عنوان اولین آرگومان می پذیرد، یک یا چند شناسه قیمت برای بازپرداخت با مقادیر اختیاری به عنوان یک آرایه انجمنی. می‌توانید تراکنش‌های یک مدل قابل پرداخت را با استفاده از این transactions روش بازیابی کنید.

به عنوان مثال، تصور کنید که می خواهیم یک تراکنش خاص را برای قیمت ها pri_123 و pri_456 . ما می خواهیم به طور کامل بازپرداخت کنیم pri_123 ، اما فقط دو دلار برای pri_456 :

use App\Models\User;
 
$user = User::find(1);
 
$transaction = $user->transactions()->first();
 
$response = $transaction->refund('Accidental charge', [
'pri_123', // Fully refund this price...
'pri_456' => 200, // Only partially refund this price...
]);

مثال بالا، اقلام خط خاصی را در یک تراکنش بازپرداخت می کند. اگر می خواهید کل تراکنش را بازپرداخت کنید، به سادگی یک دلیل ارائه دهید:

$response = $transaction->refund('Accidental charge');

برای اطلاعات بیشتر در مورد بازپرداخت، لطفاً به اسناد بازپرداخت Paddle مراجعه کنید .

بازپرداخت باید همیشه قبل از پردازش کامل توسط Paddle تأیید شود.

معاملات اعتباری

درست مانند بازپرداخت، می توانید معاملات را نیز اعتبار دهید. تراکنش‌های اعتباری، وجوه را به موجودی مشتری اضافه می‌کند تا برای خریدهای بعدی از آن استفاده شود. تراکنش‌های اعتباری فقط برای تراکنش‌های جمع‌آوری‌شده دستی و نه برای تراکنش‌هایی که به‌طور خودکار جمع‌آوری شده‌اند (مانند اشتراک‌ها) قابل انجام است، زیرا Paddle اعتبارات اشتراک را به‌طور خودکار مدیریت می‌کند:

$transaction = $user->transactions()->first();
 
// Credit a specific line item fully...
$response = $transaction->credit('Compensation', 'pri_123');

برای اطلاعات بیشتر، به مستندات Paddle در مورد اعتبار دهی مراجعه کنید .

اعتبار فقط برای تراکنش های جمع آوری شده به صورت دستی قابل اعمال است. تراکنش‌های جمع‌آوری‌شده به‌طور خودکار توسط خود Paddle اعتبار می‌شوند.

معاملات

می‌توانید به راحتی آرایه‌ای از تراکنش‌های یک مدل قابل پرداخت را از طریق transactions دارایی بازیابی کنید:

use App\Models\User;
 
$user = User::find(1);
 
$transactions = $user->transactions;

تراکنش ها نشان دهنده پرداخت برای محصولات و خریدهای شما هستند و همراه با فاکتورها هستند. فقط تراکنش های تکمیل شده در پایگاه داده برنامه شما ذخیره می شوند.

هنگام فهرست کردن تراکنش‌ها برای یک مشتری، می‌توانید از روش‌های نمونه تراکنش برای نمایش اطلاعات پرداخت مربوطه استفاده کنید. به عنوان مثال، ممکن است بخواهید هر تراکنش را در یک جدول فهرست کنید و به کاربر اجازه دهید به راحتی هر یک از فاکتورها را دانلود کند:

<table>
@foreach ($transactions as $transaction)
<tr>
<td>{{ $transaction->billed_at->toFormattedDateString() }}</td>
<td>{{ $transaction->total() }}</td>
<td>{{ $transaction->tax() }}</td>
<td><a href="{{ route('download-invoice', $transaction->id) }}" target="_blank">Download</a></td>
</tr>
@endforeach
</table>

مسیر download-invoice ممکن است به شکل زیر باشد:

use Illuminate\Http\Request;
use Laravel\Cashier\Transaction;
 
Route::get('/download-invoice/{transaction}', function (Request $request, Transaction $transaction) {
return $transaction->redirectToInvoicePdf();
})->name('download-invoice');

پرداخت های گذشته و آینده

می‌توانید از روش‌ها lastPayment و nextPayment روش‌ها برای بازیابی و نمایش پرداخت‌های گذشته یا آتی مشتری برای اشتراک‌های تکراری استفاده کنید:

use App\Models\User;
 
$user = User::find(1);
 
$subscription = $user->subscription();
 
$lastPayment = $subscription->lastPayment();
$nextPayment = $subscription->nextPayment();

هر دوی این روش ها نمونه ای از Laravel\Paddle\Payment ; با این حال، زمانی که تراکنش‌ها هنوز توسط وب‌هوک‌ها همگام‌سازی نشده باشند، lastPayment برمی‌گردند ، در حالی که پس از پایان چرخه صورت‌حساب (مانند زمانی که اشتراک لغو شده است) باز می‌گردد : null nextPayment null

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

آزمایش کردن

در حین آزمایش، باید به صورت دستی جریان صورتحساب خود را آزمایش کنید تا مطمئن شوید که یکپارچه سازی شما همانطور که انتظار می رود کار می کند.

برای آزمایش‌های خودکار، از جمله آزمایش‌هایی که در محیط CI انجام می‌شوند، می‌توانید از HTTP Client لاراول برای جعل تماس‌های HTTP که با Paddle انجام می‌شود استفاده کنید. اگرچه این پاسخ‌های واقعی Paddle را آزمایش نمی‌کند، اما راهی برای آزمایش برنامه شما بدون فراخوانی API Paddle ارائه می‌کند.