نسخه:

صندوقدار لاراول (استریپ)

معرفی

Laravel Cashier Stripe یک رابط رسا و روان برای خدمات صورتحساب اشتراک Stripe فراهم می کند. تقریباً تمام کدهای صورت‌حساب اشتراک دیگ بخار را که از نوشتن آن می‌ترسید مدیریت می‌کند. علاوه بر مدیریت اشتراک اولیه، Cashier می‌تواند کوپن‌ها، تعویض اشتراک، «مقدار» اشتراک، دوره‌های مهلت لغو، و حتی فایل‌های PDF فاکتور تولید کند.

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

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

برای جلوگیری از شکستن تغییرات، Cashier از یک نسخه API ثابت Stripe استفاده می کند. Cashier 15 از نسخه Stripe API استفاده می کند 2023-10-16 . نسخه Stripe API در نسخه‌های کوچک به‌روزرسانی می‌شود تا از ویژگی‌ها و بهبودهای جدید Stripe استفاده کند.

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

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

composer require laravel/cashier

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

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

سپس پایگاه داده خود را انتقال دهید:

php artisan migrate

مهاجرت صندوقدار چندین ستون به users جدول شما اضافه می کند. آنها همچنین یک subscriptions جدول جدید برای نگهداری تمام اشتراک های مشتری شما و یک subscription_items جدول برای اشتراک ها با چند قیمت ایجاد می کنند.

در صورت تمایل می توانید فایل پیکربندی Cashier را نیز با استفاده از vendor:publish دستور Artisan منتشر کنید:

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

در نهایت، برای اطمینان از اینکه Cashier به درستی همه رویدادهای Stripe را مدیریت می‌کند، به یاد داشته باشید که کنترل وب‌هوک Cashier را پیکربندی کنید .

Stripe توصیه می کند که هر ستونی که برای ذخیره شناسه های Stripe استفاده می شود باید به حروف بزرگ و کوچک حساس باشد. بنابراین، باید اطمینان حاصل کنید که هنگام استفاده از MySQL، ترکیب ستون برای stripe_id ستون تنظیم شده است utf8_bin . اطلاعات بیشتر در مورد این را می توان در مستندات Stripe یافت .

پیکربندی

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

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

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

صندوقدار فرض می کند مدل قابل پرداخت شما همان کلاسی است App\Models\User که با لاراول ارسال می شود. اگر می خواهید این را تغییر دهید، می توانید مدل دیگری را از طریق useCustomerModel روش مشخص کنید. این متد معمولاً باید در boot متد کلاس شما فراخوانی شود AppServiceProvider :

use App\Models\Cashier\User;
use Laravel\Cashier\Cashier;
 
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Cashier::useCustomerModel(User::class);
}

اگر از مدلی غیر از مدل ارائه شده لاراول استفاده می‌کنید App\Models\User ، باید مهاجرت‌های Cashier ارائه شده را منتشر کرده و تغییر دهید تا با نام جدول مدل جایگزین شما مطابقت داشته باشد.

کلیدهای API

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

STRIPE_KEY=your-stripe-key
STRIPE_SECRET=your-stripe-secret
STRIPE_WEBHOOK_SECRET=your-stripe-webhook-secret

باید اطمینان حاصل کنید که STRIPE_WEBHOOK_SECRET متغیر محیطی در فایل برنامه شما تعریف شده است .env ، زیرا این متغیر برای اطمینان از اینکه وب هوک های ورودی واقعاً از Stripe هستند استفاده می شود.

پیکربندی ارز

واحد پول نقد پیش فرض دلار آمریکا (USD) است. می‌توانید با تنظیم CASHIER_CURRENCY متغیر محیطی در فایل برنامه، واحد پول پیش‌فرض را تغییر دهید .env :

CASHIER_CURRENCY=eur

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

CASHIER_CURRENCY_LOCALE=nl_BE

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

پیکربندی مالیاتی

به لطف Stripe Tax ، امکان محاسبه خودکار مالیات برای همه فاکتورهای تولید شده توسط Stripe وجود دارد. می توانید محاسبه خودکار مالیات را با فراخوانی calculateTaxes روش موجود در boot متد کلاس برنامه خود فعال کنید App\Providers\AppServiceProvider :

use Laravel\Cashier\Cashier;
 
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Cashier::calculateTaxes();
}

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

برای اینکه این ویژگی به درستی کار کند، جزئیات صورت‌حساب مشتری، مانند نام، آدرس و شناسه مالیاتی مشتری، باید با Stripe همگام‌سازی شود. برای انجام این کار می‌توانید از روش‌های همگام‌سازی داده‌های مشتری و شناسه مالیاتی ارائه شده توسط Cashier استفاده کنید.

ورود به سیستم

Cashier به شما امکان می دهد کانال ورود به سیستم را برای استفاده در هنگام ثبت خطاهای کشنده Stripe مشخص کنید. می‌توانید کانال گزارش را با تعریف CASHIER_LOGGER متغیر محیطی در فایل برنامه خود مشخص کنید .env :

CASHIER_LOGGER=stack

استثناهایی که توسط فراخوانی های API به Stripe ایجاد می شوند از طریق کانال گزارش پیش فرض برنامه شما ثبت می شوند.

استفاده از مدل های سفارشی

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

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

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

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

شروع سریع

فروش محصولات

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

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

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

use Illuminate\Http\Request;
 
Route::get('/checkout', function (Request $request) {
$stripePriceId = 'price_deluxe_album';
 
$quantity = 1;
 
return $request->user()->checkout([$stripePriceId => $quantity], [
'success_url' => route('checkout-success'),
'cancel_url' => route('checkout-cancel'),
]);
})->name('checkout');
 
Route::view('checkout.success')->name('checkout-success');
Route::view('checkout.cancel')->name('checkout-cancel');

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

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

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

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

برای انجام این کار، ممکن است آرایه ای از متد ارائه metadata دهید 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',
]);
 
return $request->user()->checkout($order->price_ids, [
'success_url' => route('checkout-success').'?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => route('checkout-cancel'),
'metadata' => ['order_id' => $order->id],
]);
})->name('checkout');

همانطور که در مثال بالا می بینید، زمانی که کاربر فرآیند پرداخت را شروع می کند، ما همه شناسه های قیمت Stripe مربوط به سبد خرید/سفارش را به روش ارائه می دهیم checkout . البته، اپلیکیشن شما مسئول مرتبط کردن این موارد با «سبد خرید» یا سفارشی است که مشتری آنها را اضافه می‌کند. همچنین شناسه سفارش را از طریق metadata آرایه به جلسه Stripe Checkout ارائه می کنیم. در نهایت CHECKOUT_SESSION_ID متغیر قالب را به مسیر موفقیت Checkout اضافه کرده ایم . هنگامی که Stripe مشتریان را به برنامه شما هدایت می کند، این متغیر الگو به طور خودکار با شناسه جلسه Checkout پر می شود.

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

use App\Models\Order;
use Illuminate\Http\Request;
use Laravel\Cashier\Cashier;
 
Route::get('/checkout/success', function (Request $request) {
$sessionId = $request->get('session_id');
 
if ($sessionId === null) {
return;
}
 
$session = Cashier::stripe()->checkout->sessions->retrieve($sessionId);
 
if ($session->payment_status !== 'paid') {
return;
}
 
$orderId = $session['metadata']['order_id'] ?? null;
 
$order = Order::findOrFail($orderId);
 
$order->update(['status' => 'completed']);
 
return view('checkout-success', ['order' => $order]);
})->name('checkout-success');

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

فروش اشتراک

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

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

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

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

use Illuminate\Http\Request;
 
Route::get('/subscription-checkout', function (Request $request) {
return $request->user()
->newSubscription('default', 'price_basic_monthly')
->trialDays(5)
->allowPromotionCodes()
->checkout([
'success_url' => route('your-success-route'),
'cancel_url' => route('your-cancel-route'),
]);
});

همانطور که در مثال بالا می بینید، ما مشتری را به جلسه Stripe Checkout هدایت می کنیم که به آنها امکان می دهد در طرح اولیه ما مشترک شوند. پس از تسویه حساب یا لغو موفقیت آمیز، مشتری به آدرس اینترنتی که به روش ارائه کرده ایم هدایت می شود checkout . برای اینکه بدانیم اشتراک آنها واقعاً چه زمانی شروع شده است (از آنجایی که پردازش برخی از روش های پرداخت به چند ثانیه نیاز دارد)، همچنین باید مدیریت وب هوک 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('/billing');
}
 
return $next($request);
}
}

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

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

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

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

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

<a href="{{ route('billing') }}">
Billing
</a>

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

use Illuminate\Http\Request;
 
Route::get('/billing', function (Request $request) {
return $request->user()->redirectToBillingPortal(route('dashboard'));
})->middleware(['auth'])->name('billing');

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

مشتریان

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

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

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

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

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

$stripeCustomer = $user->createAsStripeCustomer();

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

$stripeCustomer = $user->createAsStripeCustomer($options);

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

$stripeCustomer = $user->asStripeCustomer();

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

$stripeCustomer = $user->createOrGetStripeCustomer();

به روز رسانی مشتریان

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

$stripeCustomer = $user->updateStripeCustomer($options);

موازنه

Stripe به شما این امکان را می دهد که "موجودی" مشتری را اعتبار یا بدهی کنید. بعداً این موجودی در فاکتورهای جدید بستانکار یا بدهکار خواهد شد. برای بررسی موجودی کل مشتری می توانید از روشی استفاده کنید balance که در مدل قابل پرداخت شما موجود است. این balance روش یک نمایش رشته فرمت شده از موجودی در واحد پول مشتری را برمی گرداند:

$balance = $user->balance();

برای اعتبار دادن به موجودی مشتری، ممکن است مقداری برای creditBalance روش ارائه دهید. در صورت تمایل می توانید توضیحاتی نیز ارائه دهید:

$user->creditBalance(500, 'Premium customer top-up.');

ارائه یک مقدار به debitBalance روش، موجودی مشتری را بدهکار می کند:

$user->debitBalance(300, 'Bad usage penalty.');

این applyBalance روش تراکنش های موجودی جدید مشتری را برای مشتری ایجاد می کند. می توانید این سوابق تراکنش را با استفاده از balanceTransactions روشی که ممکن است برای ارائه گزارشی از اعتبارات و بدهی ها برای بررسی مشتری مفید باشد، بازیابی کنید:

// Retrieve all transactions...
$transactions = $user->balanceTransactions();
 
foreach ($transactions as $transaction) {
// Transaction amount...
$amount = $transaction->amount(); // $2.31
 
// Retrieve the related invoice when available...
$invoice = $transaction->invoice();
}

شناسه های مالیاتی

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

$taxIds = $user->taxIds();

همچنین می‌توانید یک شناسه مالیاتی خاص را برای یک مشتری با شناسه آن بازیابی کنید:

$taxId = $user->findTaxId('txi_belgium');

می توانید با ارائه یک نوع و مقدار معتبر برای createTaxId روش، یک شناسه مالیاتی جدید ایجاد کنید:

$taxId = $user->createTaxId('eu_vat', 'BE0123456789');

این createTaxId روش بلافاصله شناسه مالیات بر ارزش افزوده را به حساب مشتری اضافه می کند. تایید شناسه های مالیات بر ارزش افزوده نیز توسط Stripe انجام می شود . با این حال، این یک فرآیند ناهمزمان است. می‌توانید با اشتراک در customer.tax_id.updated رویداد webhook و بررسی پارامتر VAT IDها verification از به‌روزرسانی‌های تأیید مطلع شوید . برای اطلاعات بیشتر در مورد مدیریت وب هوک، لطفاً به مستندات مربوط به تعریف کنترل کننده های وب هوک مراجعه کنید .

می توانید شناسه مالیاتی را با استفاده از deleteTaxId روش زیر حذف کنید:

$user->deleteTaxId('txi_belgium');

همگام سازی داده های مشتری با Stripe

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

برای خودکارسازی این کار، ممکن است شنونده رویدادی را در مدل قابل پرداخت خود تعریف کنید که به رویداد مدل واکنش نشان می‌دهد updated . سپس، در شنونده رویداد خود، می توانید syncStripeCustomerDetails متد را در مدل فراخوانی کنید:

use App\Models\User;
use function Illuminate\Events\queueable;
 
/**
* The "booted" method of the model.
*/
protected static function booted(): void
{
static::updated(queueable(function (User $customer) {
if ($customer->hasStripeId()) {
$customer->syncStripeCustomerDetails();
}
}));
}

اکنون، هر بار که مدل مشتری شما به‌روزرسانی می‌شود، اطلاعات آن با Stripe همگام‌سازی می‌شود. برای راحتی، Cashier به طور خودکار اطلاعات مشتری شما را با Stripe در ایجاد اولیه مشتری همگام می کند.

می‌توانید ستون‌هایی را که برای همگام‌سازی اطلاعات مشتری با Stripe استفاده می‌شوند، با نادیده گرفتن انواع روش‌های ارائه شده توسط Cashier سفارشی کنید. برای مثال، می‌توانید stripeName روش سفارشی‌سازی ویژگی‌ای را که باید به‌عنوان «نام» مشتری در نظر گرفته شود، در زمانی که Cashier اطلاعات مشتری را با Stripe همگام‌سازی می‌کند، لغو کنید:

/**
* Get the customer name that should be synced to Stripe.
*/
public function stripeName(): string|null
{
return $this->company_name;
}

به طور مشابه، می‌توانید روش‌های stripeEmail ، stripePhone و stripeAddress ، و را لغو کنید stripePreferredLocales . این روش‌ها هنگام به‌روزرسانی شی مشتری Stripe، اطلاعات را با پارامترهای مشتری مربوطه همگام‌سازی می‌کنند . اگر می‌خواهید کنترل کاملی بر فرآیند همگام‌سازی اطلاعات مشتری در دست بگیرید، ممکن است این syncStripeCustomerDetails روش را لغو کنید.

پورتال صورتحساب

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

use Illuminate\Http\Request;
 
Route::get('/billing-portal', function (Request $request) {
return $request->user()->redirectToBillingPortal();
});

به طور پیش فرض، زمانی که کاربر مدیریت اشتراک خود را به پایان رساند، می تواند home از طریق پیوندی در پورتال صورتحساب Stripe به مسیر برنامه شما بازگردد. شما می توانید یک URL سفارشی ارائه کنید که کاربر باید با ارسال URL به عنوان آرگومان به redirectToBillingPortal روش، به آن بازگردد:

use Illuminate\Http\Request;
 
Route::get('/billing-portal', function (Request $request) {
return $request->user()->redirectToBillingPortal(route('billing'));
});

اگر می خواهید URL را به درگاه صورتحساب بدون ایجاد پاسخ تغییر مسیر HTTP ایجاد کنید، می توانید billingPortalUrl روش زیر را فراخوانی کنید:

$url = $request->user()->billingPortalUrl(route('billing'));

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

ذخیره سازی روش های پرداخت

برای ایجاد اشتراک یا انجام هزینه‌های «یکباره» با Stripe، باید یک روش پرداخت را ذخیره کرده و شناسه آن را از Stripe بازیابی کنید. رویکرد مورد استفاده برای انجام این کار بسته به اینکه قصد دارید از روش پرداخت برای اشتراک یا هزینه تکی استفاده کنید متفاوت است، بنابراین در زیر هر دو را بررسی خواهیم کرد.

روش های پرداخت برای اشتراک

هنگام ذخیره اطلاعات کارت اعتباری مشتری برای استفاده در آینده توسط یک اشتراک، باید از Stripe "Setup Intents" API برای جمع آوری ایمن جزئیات روش پرداخت مشتری استفاده شود. یک "نیت راه اندازی" به Stripe نشان می دهد که قصد دارد از روش پرداخت مشتری هزینه کند. ویژگی Cashier Billable شامل createSetupIntent روش ایجاد آسان Setup Intent است. شما باید این روش را از مسیر یا کنترل‌کننده‌ای فراخوانی کنید که فرمی را که جزئیات روش پرداخت مشتری شما را جمع‌آوری می‌کند ارائه می‌کند:

return view('update-payment-method', [
'intent' => $user->createSetupIntent()
]);

پس از ایجاد Setup Intent و ارسال آن به view، باید راز آن را به عنصری متصل کنید که روش پرداخت را جمع آوری می کند. به عنوان مثال، این فرم "به روز رسانی روش پرداخت" را در نظر بگیرید:

<input id="card-holder-name" type="text">
 
<!-- Stripe Elements Placeholder -->
<div id="card-element"></div>
 
<button id="card-button" data-secret="{{ $intent->client_secret }}">
Update Payment Method
</button>

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

<script src="https://js.stripe.com/v3/"></script>
 
<script>
const stripe = Stripe('stripe-public-key');
 
const elements = stripe.elements();
const cardElement = elements.create('card');
 
cardElement.mount('#card-element');
</script>

در مرحله بعد، کارت را می توان تأیید کرد و یک "شناسه روش پرداخت" ایمن را می توان با استفاده از روش Stripe confirmCardSetup از Stripe بازیابی کرد :

const cardHolderName = document.getElementById('card-holder-name');
const cardButton = document.getElementById('card-button');
const clientSecret = cardButton.dataset.secret;
 
cardButton.addEventListener('click', async (e) => {
const { setupIntent, error } = await stripe.confirmCardSetup(
clientSecret, {
payment_method: {
card: cardElement,
billing_details: { name: cardHolderName.value }
}
}
);
 
if (error) {
// Display "error.message" to the user...
} else {
// The card has been verified successfully...
}
});

پس از تأیید کارت توسط Stripe، می توانید setupIntent.payment_method شناسه حاصل را به برنامه Laravel خود منتقل کنید، جایی که می توان آن را به مشتری متصل کرد. روش پرداخت را می توان به عنوان یک روش پرداخت جدید اضافه کرد یا برای به روز رسانی روش پرداخت پیش فرض استفاده کرد . همچنین می‌توانید بلافاصله از شناسه روش پرداخت برای ایجاد اشتراک جدید استفاده کنید .

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

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

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

<input id="card-holder-name" type="text">
 
<!-- Stripe Elements Placeholder -->
<div id="card-element"></div>
 
<button id="card-button">
Process Payment
</button>

پس از تعریف چنین فرمی، کتابخانه Stripe.js ممکن است برای پیوست کردن یک عنصر Stripe به فرم و جمع آوری ایمن جزئیات پرداخت مشتری استفاده شود:

<script src="https://js.stripe.com/v3/"></script>
 
<script>
const stripe = Stripe('stripe-public-key');
 
const elements = stripe.elements();
const cardElement = elements.create('card');
 
cardElement.mount('#card-element');
</script>

در مرحله بعد، کارت را می توان تأیید کرد و یک "شناسه روش پرداخت" ایمن را می توان با استفاده از روش Stripe createPaymentMethod از Stripe بازیابی کرد :

const cardHolderName = document.getElementById('card-holder-name');
const cardButton = document.getElementById('card-button');
 
cardButton.addEventListener('click', async (e) => {
const { paymentMethod, error } = await stripe.createPaymentMethod(
'card', cardElement, {
billing_details: { name: cardHolderName.value }
}
);
 
if (error) {
// Display "error.message" to the user...
} else {
// The card has been verified successfully...
}
});

اگر کارت با موفقیت تأیید شود، می‌توانید آن را paymentMethod.id به برنامه لاراول خود منتقل کنید و یک بار شارژ را پردازش کنید .

بازیابی روش های پرداخت

روش paymentMethods موجود در نمونه مدل قابل صورت‌حساب مجموعه‌ای از Laravel\Cashier\PaymentMethod نمونه‌ها را برمی‌گرداند:

$paymentMethods = $user->paymentMethods();

به طور پیش‌فرض، این روش روش‌های پرداخت را از هر نوع برمی‌گرداند. برای بازیابی روش های پرداخت از یک نوع خاص، می توانید type آرگومان را به روش ارسال کنید:

$paymentMethods = $user->paymentMethods('sepa_debit');

برای بازیابی روش پرداخت پیش‌فرض مشتری، defaultPaymentMethod ممکن است از روش زیر استفاده شود:

$paymentMethod = $user->defaultPaymentMethod();

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

$paymentMethod = $user->findPaymentMethod($paymentMethodId);

وجود روش پرداخت

برای تعیین اینکه آیا یک مدل قابل صورت‌حساب یک روش پرداخت پیش‌فرض به حساب خود دارد یا خیر، hasDefaultPaymentMethod روش را فراخوانی کنید:

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

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

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

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

if ($user->hasPaymentMethod('sepa_debit')) {
// ...
}

به روز رسانی روش پرداخت پیش فرض

این updateDefaultPaymentMethod روش ممکن است برای به‌روزرسانی اطلاعات روش پرداخت پیش‌فرض مشتری استفاده شود. این روش یک شناسه روش پرداخت Stripe را می‌پذیرد و روش پرداخت جدید را به عنوان روش پرداخت صورت‌حساب پیش‌فرض اختصاص می‌دهد:

$user->updateDefaultPaymentMethod($paymentMethod);

برای همگام‌سازی اطلاعات روش پرداخت پیش‌فرض خود با اطلاعات روش پرداخت پیش‌فرض مشتری در Stripe، می‌توانید از این updateDefaultPaymentMethodFromStripe روش استفاده کنید:

$user->updateDefaultPaymentMethodFromStripe();

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

اضافه کردن روش های پرداخت

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

$user->addPaymentMethod($paymentMethod);

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

حذف روش های پرداخت

برای حذف یک روش پرداخت، می‌توانید delete روشی را که Laravel\Cashier\PaymentMethod می‌خواهید حذف کنید تماس بگیرید:

$paymentMethod->delete();

این deletePaymentMethod روش یک روش پرداخت خاص را از مدل قابل صورت‌حساب حذف می‌کند:

$user->deletePaymentMethod('pm_visa');

این deletePaymentMethods روش همه اطلاعات روش پرداخت را برای مدل قابل صورت‌حساب حذف می‌کند:

$user->deletePaymentMethods();

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

$user->deletePaymentMethods('sepa_debit');

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

اشتراک ها

اشتراک ها راهی برای تنظیم پرداخت های مکرر برای مشتریان شما فراهم می کند. اشتراک‌های Stripe که توسط Cashier مدیریت می‌شوند، از قیمت‌های اشتراک چندگانه، مقادیر اشتراک، آزمایش‌ها و موارد دیگر پشتیبانی می‌کنند.

ایجاد اشتراک

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

use Illuminate\Http\Request;
 
Route::post('/user/subscribe', function (Request $request) {
$request->user()->newSubscription(
'default', 'price_monthly'
)->create($request->paymentMethodId);
 
// ...
});

اولین آرگومان ارسال شده به newSubscription روش باید نوع داخلی اشتراک باشد. اگر برنامه شما فقط یک اشتراک ارائه می دهد، می توانید با این default یا تماس بگیرید primary . این نوع اشتراک فقط برای استفاده داخلی برنامه است و قرار نیست به کاربران نشان داده شود. علاوه بر این، نباید دارای فاصله باشد و هرگز نباید پس از ایجاد اشتراک تغییر کند. آرگومان دوم، قیمت خاصی است که کاربر در آن مشترک است. این مقدار باید با شناسه قیمت در Stripe مطابقت داشته باشد.

این create روش که شناسه روش پرداخت Stripe یا PaymentMethod شی Stripe را می پذیرد، اشتراک را آغاز می کند و همچنین پایگاه داده شما را با شناسه مشتری Stripe مدل قابل پرداخت و سایر اطلاعات صورتحساب مرتبط به روز می کند.

ارسال شناسه روش پرداخت به طور مستقیم به create روش اشتراک نیز به طور خودکار آن را به روش های پرداخت ذخیره شده کاربر اضافه می کند.

جمع آوری پرداخت های مکرر از طریق ایمیل فاکتور

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

$user->newSubscription('default', 'price_monthly')->createAndSendInvoice();

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

$user->newSubscription('default', 'price_monthly')->createAndSendInvoice([], [
'days_until_due' => 30
]);

مقادیر

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

$user->newSubscription('default', 'price_monthly')
->quantity(5)
->create($paymentMethod);

توضیحات بیشتر

اگر می‌خواهید گزینه‌های مشتری یا اشتراک دیگری را که توسط Stripe پشتیبانی می‌شوند مشخص کنید ، می‌توانید این کار را با ارسال آن‌ها به عنوان آرگومان‌های دوم و سوم به create روش انجام دهید:

$user->newSubscription('default', 'price_monthly')->create($paymentMethod, [
'email' => $email,
], [
'metadata' => ['note' => 'Some extra information.'],
]);

کوپن

اگر می خواهید هنگام ایجاد اشتراک کوپن اعمال کنید، می توانید از withCoupon روش زیر استفاده کنید:

$user->newSubscription('default', 'price_monthly')
->withCoupon('code')
->create($paymentMethod);

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

$user->newSubscription('default', 'price_monthly')
->withPromotionCode('promo_code_id')
->create($paymentMethod);

شناسه کد تبلیغاتی داده شده باید شناسه Stripe API اختصاص داده شده به کد تبلیغاتی باشد و نه مشتری که با کد تبلیغاتی روبروست. اگر نیاز به یافتن شناسه کد تبلیغاتی بر اساس کد تبلیغاتی خاص مشتری دارید، می‌توانید از findPromotionCode روش زیر استفاده کنید:

// Find a promotion code ID by its customer facing code...
$promotionCode = $user->findPromotionCode('SUMMERSALE');
 
// Find an active promotion code ID by its customer facing code...
$promotionCode = $user->findActivePromotionCode('SUMMERSALE');

در مثال بالا، $promotionCode شیء برگشتی یک نمونه از Laravel\Cashier\PromotionCode . این کلاس یک Stripe\PromotionCode شی زیرین را تزئین می کند. می توانید کوپن مربوط به کد تبلیغاتی را با فراخوانی coupon روش بازیابی کنید:

$coupon = $user->findPromotionCode('SUMMERSALE')->coupon();

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

if ($coupon->isPercentage()) {
return $coupon->percentOff().'%'; // 21.5%
} else {
return $coupon->amountOff(); // $5.99
}

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

$discount = $billable->discount();
 
$discount = $subscription->discount();

نمونه های برگشتی Laravel\Cashier\Discount یک نمونه شی زیرین را تزئین می کنند Stripe\Discount . می توانید کوپن مربوط به این تخفیف را با استفاده از coupon روش زیر بازیابی کنید:

$coupon = $subscription->discount()->coupon();

اگر می‌خواهید یک کوپن یا کد تبلیغاتی جدید برای مشتری یا اشتراک اعمال کنید، می‌توانید این کار را از طریق applyCoupon یا applyPromotionCode روش‌های زیر انجام دهید:

$billable->applyCoupon('coupon_id');
$billable->applyPromotionCode('promotion_code_id');
 
$subscription->applyCoupon('coupon_id');
$subscription->applyPromotionCode('promotion_code_id');

به یاد داشته باشید، شما باید از Stripe API ID اختصاص داده شده به کد تبلیغاتی استفاده کنید نه مشتری که با کد تبلیغاتی روبروست. فقط یک کوپن یا کد تبلیغاتی را می توان در یک زمان معین برای مشتری یا اشتراک اعمال کرد.

برای اطلاعات بیشتر در مورد این موضوع، لطفاً به مستندات Stripe در مورد کوپن ها و کدهای تبلیغاتی مراجعه کنید .

اضافه کردن اشتراک ها

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

use App\Models\User;
 
$user = User::find(1);
 
$user->newSubscription('default', 'price_monthly')->add();

ایجاد اشتراک از داشبورد Stripe

همچنین می توانید از خود داشبورد Stripe اشتراک ایجاد کنید. هنگام انجام این کار، Cashier اشتراک‌های تازه اضافه شده را همگام‌سازی می‌کند و به آنها یک نوع اختصاص می‌دهد default . برای سفارشی کردن نوع اشتراکی که به اشتراک‌های ایجاد شده داشبورد اختصاص داده می‌شود، کنترل‌کننده‌های رویداد webhook را تعریف کنید .

علاوه بر این، می‌توانید فقط یک نوع اشتراک را از طریق داشبورد Stripe ایجاد کنید. اگر برنامه شما چندین اشتراک را ارائه می دهد که از انواع مختلف استفاده می کنند، ممکن است فقط یک نوع اشتراک از طریق داشبورد Stripe اضافه شود.

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

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

هنگامی که مشتری در برنامه شما مشترک شد، می توانید به راحتی وضعیت اشتراک او را با استفاده از روش های مختلف مناسب بررسی کنید. ابتدا، اگر مشتری اشتراک فعال داشته باشد، subscribed روش برمی گردد ، حتی اگر اشتراک در حال حاضر در دوره آزمایشی خود باشد. true متد 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('default')) {
// This user is not a paying customer...
return redirect('billing');
}
 
return $next($request);
}
}

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

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

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

if ($user->subscribedToProduct('prod_premium', 'default')) {
// ...
}

با ارسال یک آرایه به subscribedToProduct روش، می توانید تعیین کنید که آیا اشتراک کاربر default به طور فعال در محصول "پایه" یا "حق بیمه" برنامه مشترک است یا خیر:

if ($user->subscribedToProduct(['prod_basic', 'prod_premium'], 'default')) {
// ...
}

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

if ($user->subscribedToPrice('price_basic_monthly', 'default')) {
// ...
}

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

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

اگر کاربر دو اشتراک با یک نوع داشته باشد، آخرین اشتراک همیشه با subscription روش برگردانده می شود. به عنوان مثال، یک کاربر ممکن است دو رکورد اشتراک با نوع default ; با این حال، یکی از اشتراک ها ممکن است یک اشتراک قدیمی و منقضی شده باشد، در حالی که دیگری اشتراک فعلی و فعال باشد. آخرین اشتراک همیشه برگردانده می شود در حالی که اشتراک های قدیمی برای بررسی تاریخی در پایگاه داده نگهداری می شوند.

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

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

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

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

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

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

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

وضعیت ناقص و سررسید گذشته

اگر یک اشتراک پس از ایجاد به یک اقدام پرداخت ثانویه نیاز داشته باشد، اشتراک به عنوان علامت گذاری می شود incomplete . وضعیت اشتراک در stripe_status ستون جدول پایگاه داده صندوقدار ذخیره می شود subscriptions .

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

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

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

<a href="{{ route('cashier.payment', $subscription->latestPayment()->id) }}">
Please confirm your payment.
</a>

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

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

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

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

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

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

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

Subscription::query()->active();
Subscription::query()->canceled();
Subscription::query()->ended();
Subscription::query()->incomplete();
Subscription::query()->notCanceled();
Subscription::query()->notOnGracePeriod();
Subscription::query()->notOnTrial();
Subscription::query()->onGracePeriod();
Subscription::query()->onTrial();
Subscription::query()->pastDue();
Subscription::query()->recurring();

تغییر قیمت ها

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

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

اگر مشتری در حال آزمایش باشد، دوره آزمایشی حفظ خواهد شد. علاوه بر این، اگر یک "مقدار" برای اشتراک وجود داشته باشد، آن مقدار نیز حفظ خواهد شد.

اگر می‌خواهید قیمت‌ها را مبادله کنید و هر دوره آزمایشی را که مشتری در حال حاضر در آن است لغو کنید، می‌توانید از skipTrial روش زیر استفاده کنید:

$user->subscription('default')
->skipTrial()
->swap('price_yearly');

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

$user = User::find(1);
 
$user->subscription('default')->swapAndInvoice('price_yearly');

تناسب

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

$user->subscription('default')->noProrate()->swap('price_yearly');

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

اجرای noProrate متد قبل از swapAndInvoice متد تاثیری در proration نخواهد داشت. همیشه فاکتور صادر می شود.

مقدار اشتراک

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

use App\Models\User;
 
$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 from the subscription's current quantity...
$user->subscription('default')->decrementQuantity(5);

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

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

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

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

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

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

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

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

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

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

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

use Illuminate\Http\Request;
 
Route::post('/user/subscribe', function (Request $request) {
$request->user()->newSubscription('default', [
'price_monthly',
'price_chat',
])->create($request->paymentMethodId);
 
// ...
});

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

$user = User::find(1);
 
$user->newSubscription('default', ['price_monthly', 'price_chat'])
->quantity(5, 'price_chat')
->create($paymentMethod);

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

$user = User::find(1);
 
$user->subscription('default')->addPrice('price_chat');

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

$user->subscription('default')->addPriceAndInvoice('price_chat');

اگر می‌خواهید قیمتی را با یک مقدار مشخص اضافه کنید، می‌توانید مقدار را به عنوان آرگومان دوم متدهای addPrice یا ارسال کنید addPriceAndInvoice :

$user = User::find(1);
 
$user->subscription('default')->addPrice('price_chat', 5);

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

$user->subscription('default')->removePrice('price_chat');

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

معاوضه قیمت ها

همچنین می‌توانید قیمت‌های پیوست شده به اشتراکی را با چندین محصول تغییر دهید. به عنوان مثال، تصور کنید یک مشتری price_basic با یک price_chat محصول افزودنی اشتراک دارد و شما می خواهید مشتری را از قیمت price_basic به قیمت ارتقا دهید price_pro :

use App\Models\User;
 
$user = User::find(1);
 
$user->subscription('default')->swap(['price_pro', 'price_chat']);

هنگام اجرای مثال بالا، آیتم اشتراک زیرین با علامت price_basic حذف می شود و موردی که دارای the price_chat است حفظ می شود. علاوه بر این، یک آیتم اشتراک جدید برای آن price_pro ایجاد می شود.

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

$user = User::find(1);
 
$user->subscription('default')->swap([
'price_pro' => ['quantity' => 5],
'price_chat'
]);

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

$user = User::find(1);
 
$user->subscription('default')
->findItemOrFail('price_basic')
->swap('price_pro');

تناسب

به‌طور پیش‌فرض، Stripe هنگام افزودن یا حذف قیمت‌ها از اشتراکی با چندین محصول، هزینه‌ها را به نسبت هزینه‌ها محاسبه می‌کند. اگر می‌خواهید یک تعدیل قیمت را بدون تناسب انجام دهید، باید این noProrate روش را به عملیات قیمت خود زنجیره بزنید:

$user->subscription('default')->noProrate()->removePrice('price_chat');

مقادیر

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

$user = User::find(1);
 
$user->subscription('default')->incrementQuantity(5, 'price_chat');
 
$user->subscription('default')->decrementQuantity(3, 'price_chat');
 
$user->subscription('default')->updateQuantity(10, 'price_chat');

هنگامی که یک اشتراک چند قیمت داشته باشد، ویژگی ها stripe_price و quantity ویژگی های مدل Subscription خواهد بود null . برای دسترسی به ویژگی‌های قیمت جداگانه، باید از items رابطه موجود در Subscription مدل استفاده کنید.

اقلام اشتراک

هنگامی که یک اشتراک چندین قیمت دارد، چندین "اقلام" اشتراک در جدول پایگاه داده شما ذخیره می شود subscription_items . می توانید از طریق items رابطه موجود در اشتراک به این موارد دسترسی داشته باشید:

use App\Models\User;
 
$user = User::find(1);
 
$subscriptionItem = $user->subscription('default')->items->first();
 
// Retrieve the Stripe price and quantity for a specific item...
$stripePrice = $subscriptionItem->stripe_price;
$quantity = $subscriptionItem->quantity;

همچنین می توانید با استفاده از findItemOrFail روش زیر قیمت خاصی را بازیابی کنید:

$user = User::find(1);
 
$subscriptionItem = $user->subscription('default')->findItemOrFail('price_chat');

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

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

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

use Illuminate\Http\Request;
 
Route::post('/swimming/subscribe', function (Request $request) {
$request->user()->newSubscription('swimming')
->price('price_swimming_monthly')
->create($request->paymentMethodId);
 
// ...
});

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

$user->subscription('swimming')->swap('price_swimming_yearly');

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

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

صورتحساب اندازه گیری شده

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

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

use Illuminate\Http\Request;
 
Route::post('/user/subscribe', function (Request $request) {
$request->user()->newSubscription('default')
->meteredPrice('price_metered')
->create($request->paymentMethodId);
 
// ...
});

همچنین می‌توانید از طریق Stripe Checkout یک اشتراک اندازه‌گیری شده شروع کنید :

$checkout = Auth::user()
->newSubscription('default', [])
->meteredPrice('price_metered')
->checkout();
 
return view('your-checkout-view', [
'checkout' => $checkout,
]);

گزارش استفاده

همانطور که مشتری شما از برنامه شما استفاده می کند، استفاده از آنها را به Stripe گزارش می دهید تا به طور دقیق صورتحساب آنها دریافت شود. برای افزایش استفاده از اشتراک اندازه‌گیری شده، می‌توانید از reportUsage روش زیر استفاده کنید:

$user = User::find(1);
 
$user->subscription('default')->reportUsage();

به طور پیش فرض، یک "مقدار استفاده" 1 به دوره صورتحساب اضافه می شود. از طرف دیگر، می‌توانید مقدار خاصی از «استفاده» را برای افزودن به میزان استفاده مشتری برای دوره صورت‌حساب ارسال کنید:

$user = User::find(1);
 
$user->subscription('default')->reportUsage(15);

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

$user = User::find(1);
 
$user->subscription('default')->reportUsageFor('price_metered', 15);

گاهی اوقات، ممکن است لازم باشد استفاده ای را که قبلاً گزارش کرده اید به روز کنید. برای انجام این کار، می توانید یک مهر زمانی یا یک DateTimeInterface نمونه را به عنوان پارامتر دوم به reportUsage . هنگام انجام این کار، Stripe استفاده ای را که در آن زمان گزارش شده بود به روز می کند. می‌توانید به به‌روزرسانی سوابق استفاده قبلی ادامه دهید زیرا تاریخ و زمان معین هنوز در دوره صورت‌حساب فعلی است:

$user = User::find(1);
 
$user->subscription('default')->reportUsage(5, $timestamp);

بازیابی سوابق استفاده

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

$user = User::find(1);
 
$usageRecords = $user->subscription('default')->usageRecords();

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

$user = User::find(1);
 
$usageRecords = $user->subscription('default')->usageRecordsFor('price_metered');

و متدها یک نمونه Collection حاوی یک آرایه انجمنی از سوابق استفاده را برمی‌گردانند usageRecords . usageRecordsFor برای نمایش کل مصرف مشتری، می‌توانید روی این آرایه تکرار کنید:

@foreach ($usageRecords as $usageRecord)
- Period Starting: {{ $usageRecord['period']['start'] }}
- Period Ending: {{ $usageRecord['period']['end'] }}
- Total Usage: {{ $usageRecord['total_usage'] }}
@endforeach

برای مرجع کامل همه داده‌های استفاده برگردانده شده و نحوه استفاده از صفحه‌بندی مبتنی بر مکان‌نما Stripe، لطفاً به اسناد رسمی Stripe API مراجعه کنید .

مالیات اشتراک

به‌جای محاسبه دستی نرخ‌های مالیات، می‌توانید به‌طور خودکار مالیات‌ها را با استفاده از Stripe Tax محاسبه کنید

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

/**
* The tax rates that should apply to the customer's subscriptions.
*
* @return array<int, string>
*/
public function taxRates(): array
{
return ['txr_id'];
}

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

اگر اشتراک‌هایی با چندین محصول ارائه می‌دهید، می‌توانید با اجرای روشی priceTaxRates در مدل قابل پرداخت خود، نرخ‌های مالیات متفاوتی را برای هر قیمت تعریف کنید:

/**
* The tax rates that should apply to the customer's subscriptions.
*
* @return array<string, array<int, string>>
*/
public function priceTaxRates(): array
{
return [
'price_monthly' => ['txr_id'],
];
}

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

همگام سازی نرخ های مالیاتی

هنگام تغییر شناسه‌های نرخ مالیاتی کدگذاری‌شده‌ای که با این taxRates روش بازگردانده می‌شوند، تنظیمات مالیاتی روی هر اشتراک موجود برای کاربر یکسان باقی می‌ماند. اگر می‌خواهید ارزش مالیات اشتراک‌های موجود را با taxRates مقادیر جدید به‌روزرسانی کنید، باید syncTaxRates روش موجود در نمونه اشتراک کاربر را فراخوانی کنید:

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

این همچنین نرخ مالیات موردی را برای یک اشتراک با چندین محصول همگام می‌کند. اگر برنامه شما اشتراک هایی با چندین محصول ارائه می دهد، باید مطمئن شوید که مدل قابل پرداخت شما priceTaxRates روشی را که در بالا توضیح داده شد اجرا می کند .

معافیت مالیاتی

صندوقدار همچنین روش های , و را برای تعیین معافیت مالیاتی مشتری ارائه isNotTaxExempt می isTaxExempt دهد reverseChargeApplies . این روش‌ها برای تعیین وضعیت معافیت مالیاتی مشتری، Stripe API را فراخوانی می‌کنند:

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

این روش ها بر روی هر شی نیز موجود است Laravel\Cashier\Invoice . با این حال، هنگامی که روی یک Invoice شیء فراخوانی می شود، متدها وضعیت معافیت را در زمان ایجاد فاکتور تعیین می کنند.

تاریخ لنگر اشتراک

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

use Illuminate\Http\Request;
 
Route::post('/user/subscribe', function (Request $request) {
$anchor = Carbon::parse('first day of next month');
 
$request->user()->newSubscription('default', 'price_monthly')
->anchorBillingCycleOn($anchor->startOfDay())
->create($request->paymentMethodId);
 
// ...
});

برای اطلاعات بیشتر در مورد مدیریت چرخه‌های صورت‌حساب اشتراک، به مستندات چرخه صورت‌حساب Stripe مراجعه کنید

لغو اشتراک ها

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

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

هنگامی که یک اشتراک لغو می شود، صندوقدار به طور خودکار ends_at ستون را در جدول پایگاه داده شما تنظیم می کند subscriptions . از این ستون برای دانستن زمان subscribed شروع بازگشت متد استفاده می شود false .

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

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

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

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

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

اگر می‌خواهید اشتراک را فوراً لغو کنید و هرگونه استفاده اندازه‌گیری‌شده بدون صورت‌حساب باقی‌مانده یا موارد جدید/درانتظار صورت‌حساب فاکتور را فاکتور کنید، با cancelNowAndInvoice روش روی اشتراک کاربر تماس بگیرید:

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

همچنین می توانید انتخاب کنید که اشتراک در یک لحظه خاص لغو شود:

$user->subscription('default')->cancelAt(
now()->addDays(10)
);

در نهایت، همیشه باید قبل از حذف مدل کاربر مرتبط، اشتراک کاربر را لغو کنید:

$user->subscription('default')->cancelNow();
 
$user->delete();

از سرگیری اشتراک ها

اگر مشتری اشتراک خود را لغو کرده است و شما می خواهید آن را از سر بگیرید، می توانید از resume روش موجود در اشتراک استفاده کنید. مشتری برای ازسرگیری اشتراک باید همچنان در "دوره مهلت" خود باشد:

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

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

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

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

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

use Illuminate\Http\Request;
 
Route::post('/user/subscribe', function (Request $request) {
$request->user()->newSubscription('default', 'price_monthly')
->trialDays(10)
->create($request->paymentMethodId);
 
// ...
});

این روش تاریخ پایان دوره آزمایشی را در سابقه اشتراک در پایگاه داده تنظیم می کند و به Stripe دستور می دهد که تا بعد از این تاریخ شروع به صدور صورت حساب مشتری نکند. هنگام استفاده از trialDays روش، Cashier هر دوره آزمایشی پیش‌فرضی را که برای قیمت در Stripe پیکربندی شده است، بازنویسی می‌کند.

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

این trialUntil روش به شما امکان می دهد نمونه ای را ارائه دهید DateTime که مشخص می کند دوره آزمایشی چه زمانی باید به پایان برسد:

use Carbon\Carbon;
 
$user->newSubscription('default', 'price_monthly')
->trialUntil(Carbon::now()->addDays(10))
->create($paymentMethod);

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

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

می‌توانید از این endTrial روش برای پایان فوری یک دوره آزمایشی اشتراک استفاده کنید:

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

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

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

تعریف روزهای آزمایشی در Stripe / Cashier

می‌توانید تعیین کنید که قیمت شما چند روز آزمایشی در داشبورد Stripe دریافت می‌کند یا همیشه آنها را با استفاده از Cashier به صراحت ارسال کنید. اگر انتخاب می‌کنید روزهای آزمایشی قیمت خود را در Stripe تعریف کنید، باید بدانید که اشتراک‌های جدید، از جمله اشتراک‌های جدید برای مشتری که در گذشته اشتراک داشته‌اند، همیشه یک دوره آزمایشی دریافت می‌کنند، مگر اینکه صریحاً با روش تماس بگیرید skipTrial() .

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

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

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

مطمئن شوید که یک تاریخ ارسال برای trial_ends_at ویژگی در تعریف کلاس مدل قابل پرداخت خود اضافه کنید.

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

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

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

$user = User::find(1);
 
$user->newSubscription('default', 'price_monthly')->create($paymentMethod);

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

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

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

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

تمدید آزمایشات

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

use App\Models\User;
 
$subscription = User::find(1)->subscription('default');
 
// End the trial 7 days from now...
$subscription->extendTrial(
now()->addDays(7)
);
 
// Add an additional 5 days to the trial...
$subscription->extendTrial(
$subscription->trial_ends_at->addDays(5)
);

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

می‌توانید از Stripe CLI برای کمک به آزمایش وبکهک‌ها در طول توسعه محلی استفاده کنید.

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

به‌طور پیش‌فرض، کنترل‌کننده وب‌هوک Cashier به‌طور خودکار لغو اشتراک‌هایی را که هزینه‌های ناموفق زیادی دارند (همانطور که تنظیمات Stripe شما تعریف کرده‌اند)، به‌روزرسانی‌های مشتری، حذف‌های مشتری، به‌روزرسانی‌های اشتراک و تغییرات روش پرداخت را کنترل می‌کند. با این حال، همانطور که به زودی متوجه خواهیم شد، می‌توانید این کنترلر را برای مدیریت هر رویداد Stripe webhook که دوست دارید گسترش دهید.

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

  • customer.subscription.created
  • customer.subscription.updated
  • customer.subscription.deleted
  • customer.updated
  • customer.deleted
  • payment_method.automatically_updated
  • invoice.payment_action_required
  • invoice.payment_succeeded

برای راحتی، Cashier شامل یک cashier:webhook فرمان Artisan است. این دستور یک webhook در Stripe ایجاد می کند که به تمام رویدادهای مورد نیاز Cashier گوش می دهد:

php artisan cashier:webhook

به طور پیش فرض، وب هوک ایجاد شده به URL تعریف شده توسط APP_URL متغیر محیطی و cashier.webhook مسیری که با Cashier ارائه شده است اشاره می کند. --url اگر می‌خواهید از URL دیگری استفاده کنید، می‌توانید هنگام فراخوانی دستور، این گزینه را ارائه دهید :

php artisan cashier:webhook --url "https://example.com/stripe/webhook"

وب هوکی که ایجاد می شود از نسخه Stripe API استفاده می کند که نسخه Cashier شما با آن سازگار است. اگر می خواهید از نسخه Stripe دیگری استفاده کنید، می توانید این --api-version گزینه را ارائه دهید:

php artisan cashier:webhook --api-version="2019-12-03"

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

php artisan cashier:webhook --disabled

Webhooks و CSRF Protection

از آنجایی که وب هوک های Stripe نیاز به دور زدن حفاظت CSRF لاراول دارند ، باید اطمینان حاصل کنید که لاراول برای اعتبار سنجی توکن CSRF برای وب هوک های Stripe ورودی اقدام نمی کند. برای انجام این کار، باید stripe/* از حفاظت CSRF در فایل برنامه خود حذف کنید bootstrap/app.php :

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

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

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

  • Laravel\Cashier\Events\WebhookReceived
  • Laravel\Cashier\Events\WebhookHandled

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

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

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

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

برای فعال کردن تأیید وب هوک، مطمئن شوید که STRIPE_WEBHOOK_SECRET متغیر محیط در فایل برنامه شما تنظیم شده است .env . وب هوک secret ممکن است از داشبورد حساب Stripe شما بازیابی شود.

شارژ تک

شارژ ساده

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

use Illuminate\Http\Request;
 
Route::post('/purchase', function (Request $request) {
$stripeCharge = $request->user()->charge(
100, $request->paymentMethodId
);
 
// ...
});

این charge روش یک آرایه را به عنوان آرگومان سوم خود می پذیرد و به شما این امکان را می دهد که هر گزینه ای را که می خواهید به ایجاد شارژ Stripe زیربنایی منتقل کنید. اطلاعات بیشتر در مورد گزینه‌هایی که هنگام ایجاد هزینه‌ها در دسترس شما هستند را می‌توانید در مستندات Stripe پیدا کنید :

$user->charge(100, $paymentMethod, [
'custom_option' => $value,
]);

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

use App\Models\User;
 
$stripeCharge = (new User)->charge(100, $paymentMethod);

این charge روش در صورت عدم موفقیت شارژ، یک استثنا ایجاد می کند. در صورت موفقیت آمیز بودن شارژ، نمونه ای Laravel\Cashier\Payment از متد برگردانده می شود:

try {
$payment = $user->charge(100, $paymentMethod);
} catch (Exception $e) {
// ...
}

این charge روش مبلغ پرداختی را در کمترین مخرج ارز مورد استفاده برنامه شما می پذیرد. به عنوان مثال، اگر مشتریان به دلار ایالات متحده پرداخت می کنند، مبالغ باید به پنی مشخص شود.

شارژ با فاکتور

گاهی اوقات ممکن است لازم باشد یک بار شارژ کنید و یک فاکتور PDF به مشتری خود ارائه دهید. این invoicePrice روش به شما امکان می دهد این کار را انجام دهید. به عنوان مثال، بیایید یک مشتری برای پنج پیراهن جدید فاکتور کنیم:

$user->invoicePrice('price_tshirt', 5);

فاکتور بلافاصله از روش پرداخت پیش فرض کاربر کسر می شود. متد invoicePrice همچنین یک آرایه را به عنوان آرگومان سوم خود می پذیرد. این آرایه شامل گزینه های صورتحساب برای مورد فاکتور است. آرگومان چهارم پذیرفته شده توسط متد نیز آرایه ای است که باید شامل گزینه های صورتحساب برای خود فاکتور باشد:

$user->invoicePrice('price_tshirt', 5, [
'discounts' => [
['coupon' => 'SUMMER21SALE']
],
], [
'default_tax_rates' => ['txr_id'],
]);

به طور مشابه invoicePrice ، می‌توانید از این tabPrice روش برای ایجاد شارژ یک‌باره برای چندین مورد (حداکثر 250 مورد در هر فاکتور) با افزودن آنها به "برگه" مشتری و سپس صورت‌حساب مشتری استفاده کنید. به عنوان مثال، ممکن است برای مشتری پنج پیراهن و دو لیوان فاکتور کنیم:

$user->tabPrice('price_tshirt', 5);
$user->tabPrice('price_mug', 2);
$user->invoice();

از طرف دیگر، می‌توانید از این invoiceFor روش برای ایجاد هزینه «یکباره» از روش پرداخت پیش‌فرض مشتری استفاده کنید:

$user->invoiceFor('One Time Fee', 500);

اگرچه این invoiceFor روش برای شما در دسترس است، اما توصیه می شود از روش های invoicePrice و tabPrice با قیمت های از پیش تعیین شده استفاده کنید. با انجام این کار، به تجزیه و تحلیل و داده های بهتری در داشبورد Stripe خود در رابطه با فروش خود بر اساس محصول دسترسی خواهید داشت.

روش های invoice , invoicePrice , و invoiceFor یک فاکتور Stripe ایجاد می کند که تلاش های صورتحساب ناموفق را دوباره امتحان می کند. اگر نمی‌خواهید فاکتورها هزینه‌های ناموفق را دوباره امتحان کنند، باید آنها را با استفاده از Stripe API پس از اولین شارژ ناموفق ببندید.

ایجاد اهداف پرداخت

می‌توانید با فراخوانی pay روش در نمونه‌ای از مدل قابل صورت‌حساب، یک هدف پرداخت Stripe جدید ایجاد کنید. فراخوانی این روش یک هدف پرداخت ایجاد می کند که در یک Laravel\Cashier\Payment نمونه پیچیده می شود:

use Illuminate\Http\Request;
 
Route::post('/pay', function (Request $request) {
$payment = $request->user()->pay(
$request->get('amount')
);
 
return $payment->client_secret;
});

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

هنگام استفاده از این pay روش، روش‌های پرداخت پیش‌فرض که در داشبورد Stripe شما فعال هستند در دسترس مشتری قرار می‌گیرند. از طرف دیگر، اگر فقط می‌خواهید استفاده از برخی روش‌های پرداخت خاص را مجاز کنید، می‌توانید از payWith روش زیر استفاده کنید:

use Illuminate\Http\Request;
 
Route::post('/pay', function (Request $request) {
$payment = $request->user()->payWith(
$request->get('amount'), ['card', 'bancontact']
);
 
return $payment->client_secret;
});

و روش‌ها مبلغ پرداختی pay را payWith در کمترین مخرج ارز مورد استفاده برنامه شما می‌پذیرند. به عنوان مثال، اگر مشتریان به دلار ایالات متحده پرداخت می کنند، مبالغ باید به پنی مشخص شود.

هزینه های بازپرداخت

اگر نیاز به بازپرداخت هزینه Stripe دارید، می‌توانید از این refund روش استفاده کنید. این روش شناسه هدف پرداخت Stripe را به عنوان اولین آرگومان خود می پذیرد:

$payment = $user->charge(100, $paymentMethodId);
 
$user->refund($payment->id);

فاکتورها

بازیابی فاکتورها

شما می توانید به راحتی آرایه ای از فاکتورهای یک مدل قابل پرداخت را با استفاده از این invoices روش بازیابی کنید. متد invoices مجموعه ای از Laravel\Cashier\Invoice نمونه ها را برمی گرداند:

$invoices = $user->invoices();

اگر می خواهید فاکتورهای معلق را در نتایج لحاظ کنید، می توانید از invoicesIncludingPending روش زیر استفاده کنید:

$invoices = $user->invoicesIncludingPending();

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

$invoice = $user->findInvoice($invoiceId);

نمایش اطلاعات فاکتور

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

<table>
@foreach ($invoices as $invoice)
<tr>
<td>{{ $invoice->date()->toFormattedDateString() }}</td>
<td>{{ $invoice->total() }}</td>
<td><a href="/user/invoice/{{ $invoice->id }}">Download</a></td>
</tr>
@endforeach
</table>

فاکتورهای آینده

برای بازیابی فاکتور آینده برای مشتری، می توانید از upcomingInvoice روش زیر استفاده کنید:

$invoice = $user->upcomingInvoice();

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

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

پیش نمایش فاکتورهای اشتراک

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

$invoice = $user->subscription('default')->previewInvoice('price_yearly');

می‌توانید مجموعه‌ای از قیمت‌ها را به previewInvoice روش ارسال کنید تا پیش‌نمایش صورت‌حساب‌ها را با چندین قیمت جدید مشاهده کنید:

$invoice = $user->subscription('default')->previewInvoice(['price_yearly', 'price_metered']);

تولید پی دی اف فاکتور

قبل از تولید فایل‌های PDF فاکتور، باید از Composer برای نصب کتابخانه Dompdf استفاده کنید، که رندر پیش‌فرض فاکتور برای Cashier است:

composer require dompdf/dompdf

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

use Illuminate\Http\Request;
 
Route::get('/user/invoice/{invoice}', function (Request $request, string $invoiceId) {
return $request->user()->downloadInvoice($invoiceId);
});

به طور پیش‌فرض، تمام داده‌های فاکتور از مشتری و داده‌های فاکتور ذخیره شده در Stripe مشتق می‌شوند. نام فایل بر اساس app.name مقدار پیکربندی شما است. با این حال، می‌توانید برخی از این داده‌ها را با ارائه یک آرایه به عنوان آرگومان دوم برای downloadInvoice متد شخصی‌سازی کنید. این آرایه به شما امکان می دهد اطلاعاتی مانند جزئیات شرکت و محصول خود را سفارشی کنید:

return $request->user()->downloadInvoice($invoiceId, [
'vendor' => 'Your Company',
'product' => 'Your Product',
'street' => 'Main Str. 1',
'location' => '2000 Antwerp, Belgium',
'phone' => '+32 499 00 00 00',
'email' => 'info@example.com',
'url' => 'https://example.com',
'vendorVat' => 'BE123456789',
]);

این downloadInvoice روش همچنین اجازه می دهد تا نام فایل سفارشی را از طریق آرگومان سوم خود انتخاب کنید. این نام فایل به طور خودکار با پسوند .pdf :

return $request->user()->downloadInvoice($invoiceId, [], 'my-invoice');

ارائه کننده فاکتور سفارشی

صندوقدار همچنین امکان استفاده از رندر فاکتور سفارشی را فراهم می کند. به‌طور پیش‌فرض، Cashier از DompdfInvoiceRenderer پیاده‌سازی استفاده می‌کند که از کتابخانه PHP dompdf برای تولید فاکتورهای Cashier استفاده می‌کند. با این حال، می توانید از هر رندری که می خواهید با پیاده سازی Laravel\Cashier\Contracts\InvoiceRenderer اینترفیس استفاده کنید. برای مثال، ممکن است بخواهید یک PDF فاکتور را با استفاده از یک تماس API به یک سرویس رندر PDF شخص ثالث ارائه دهید:

use Illuminate\Support\Facades\Http;
use Laravel\Cashier\Contracts\InvoiceRenderer;
use Laravel\Cashier\Invoice;
 
class ApiInvoiceRenderer implements InvoiceRenderer
{
/**
* Render the given invoice and return the raw PDF bytes.
*/
public function render(Invoice $invoice, array $data = [], array $options = []): string
{
$html = $invoice->view($data)->render();
 
return Http::get('https://example.com/html-to-pdf', ['html' => $html])->get()->body();
}
}

هنگامی که قرارداد ارائه کننده فاکتور را اجرا کردید، باید cashier.invoices.renderer مقدار پیکربندی را در فایل پیکربندی برنامه خود به روز کنید config/cashier.php . این مقدار پیکربندی باید روی نام کلاس اجرای رندر سفارشی شما تنظیم شود.

وارسی

Cashier Stripe همچنین از Stripe Checkout پشتیبانی می کند . Stripe Checkout با ارائه یک صفحه پرداخت از پیش ساخته شده و میزبانی شده، درد اجرای صفحات سفارشی برای پذیرش پرداخت را کاهش می دهد.

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

بررسی های محصول

می‌توانید برای یک محصول موجود که در داشبورد Stripe شما ایجاد شده است، با استفاده از checkout روش روی یک مدل صورت‌حساب، تسویه حساب کنید. این checkout روش یک جلسه جدید Stripe Checkout را آغاز می کند. به‌طور پیش‌فرض، باید شناسه Stripe Price را ارسال کنید:

use Illuminate\Http\Request;
 
Route::get('/product-checkout', function (Request $request) {
return $request->user()->checkout('price_tshirt');
});

در صورت نیاز، می توانید مقدار محصول را نیز مشخص کنید:

use Illuminate\Http\Request;
 
Route::get('/product-checkout', function (Request $request) {
return $request->user()->checkout(['price_tshirt' => 15]);
});

هنگامی که یک مشتری از این مسیر بازدید می کند، به صفحه پرداخت Stripe هدایت می شود. به‌طور پیش‌فرض، زمانی که کاربر خریدی را با موفقیت انجام می‌دهد یا لغو می‌کند، به مکان مسیر شما هدایت می‌شود home ، اما می‌توانید URL‌های پاسخ به تماس سفارشی را با استفاده از گزینه‌های success_url و مشخص کنید cancel_url :

use Illuminate\Http\Request;
 
Route::get('/product-checkout', function (Request $request) {
return $request->user()->checkout(['price_tshirt' => 1], [
'success_url' => route('your-success-route'),
'cancel_url' => route('your-cancel-route'),
]);
});

هنگام تعریف success_url گزینه پرداخت خود، ممکن است به Stripe دستور دهید تا هنگام فراخوانی URL شما، شناسه جلسه پرداخت را به عنوان پارامتر رشته پرس و جو اضافه کند. برای انجام این کار، رشته لفظی را {CHECKOUT_SESSION_ID} به رشته پرس و جو خود اضافه کنید success_url . Stripe این مکان‌نما را با شناسه جلسه پرداخت واقعی جایگزین می‌کند:

use Illuminate\Http\Request;
use Stripe\Checkout\Session;
use Stripe\Customer;
 
Route::get('/product-checkout', function (Request $request) {
return $request->user()->checkout(['price_tshirt' => 1], [
'success_url' => route('checkout-success').'?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => route('checkout-cancel'),
]);
});
 
Route::get('/checkout-success', function (Request $request) {
$checkoutSession = $request->user()->stripe()->checkout->sessions->retrieve($request->get('session_id'));
 
return view('checkout.success', ['checkoutSession' => $checkoutSession]);
})->name('checkout-success');

کدهای تبلیغاتی

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

use Illuminate\Http\Request;
 
Route::get('/product-checkout', function (Request $request) {
return $request->user()
->allowPromotionCodes()
->checkout('price_tshirt');
});

تسویه حساب تک شارژ

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

use Illuminate\Http\Request;
 
Route::get('/charge-checkout', function (Request $request) {
return $request->user()->checkoutCharge(1200, 'T-Shirt', 5);
});

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

پرداخت های اشتراک

استفاده از Stripe Checkout برای اشتراک‌ها از شما می‌خواهد که customer.subscription.created webhook را در داشبورد Stripe خود فعال کنید. این وب هوک رکورد اشتراک را در پایگاه داده شما ایجاد می کند و همه موارد اشتراک مربوطه را ذخیره می کند.

همچنین می‌توانید از Stripe Checkout برای شروع اشتراک‌ها استفاده کنید. پس از تعریف اشتراک خود با روش های سازنده اشتراک صندوقدار، می توانید checkout روش را فراخوانی کنید. هنگامی که مشتری از این مسیر بازدید می کند، به صفحه پرداخت Stripe هدایت می شود:

use Illuminate\Http\Request;
 
Route::get('/subscription-checkout', function (Request $request) {
return $request->user()
->newSubscription('default', 'price_monthly')
->checkout();
});

درست مانند تسویه‌حساب‌های محصول، می‌توانید URL موفقیت و لغو را سفارشی کنید:

use Illuminate\Http\Request;
 
Route::get('/subscription-checkout', function (Request $request) {
return $request->user()
->newSubscription('default', 'price_monthly')
->checkout([
'success_url' => route('your-success-route'),
'cancel_url' => route('your-cancel-route'),
]);
});

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

use Illuminate\Http\Request;
 
Route::get('/subscription-checkout', function (Request $request) {
return $request->user()
->newSubscription('default', 'price_monthly')
->allowPromotionCodes()
->checkout();
});

متأسفانه Stripe Checkout از همه گزینه‌های صورت‌حساب اشتراک هنگام شروع اشتراک پشتیبانی نمی‌کند. استفاده از anchorBillingCycleOn روش در سازنده اشتراک، تنظیم رفتار تناسب یا تنظیم رفتار پرداخت هیچ تاثیری در جلسات Stripe Checkout نخواهد داشت. لطفاً برای بررسی پارامترهای موجود، به مستندات Stripe Checkout Session API مراجعه کنید.

Stripe Checkout و دوره های آزمایشی

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

$checkout = Auth::user()->newSubscription('default', 'price_monthly')
->trialDays(3)
->checkout();

با این حال، دوره آزمایشی باید حداقل 48 ساعت باشد، که حداقل مدت زمان آزمایشی پشتیبانی شده توسط Stripe Checkout است.

اشتراک ها و وب هوک ها

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

جمع آوری شناسه های مالیاتی

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

$checkout = $user->collectTaxIds()->checkout('price_tshirt');

هنگامی که این روش فراخوانی می شود، یک چک باکس جدید در دسترس مشتری قرار می گیرد که به او امکان می دهد مشخص کند که آیا به عنوان یک شرکت خرید می کند یا خیر. در این صورت، آنها این فرصت را خواهند داشت که شماره شناسه مالیاتی خود را ارائه کنند.

اگر قبلاً جمع آوری مالیات خودکار را در ارائه دهنده خدمات برنامه خود پیکربندی کرده اید ، این ویژگی به طور خودکار فعال می شود و نیازی به فراخوانی روش نیست collectTaxIds .

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

با استفاده از این Checkout::guest روش، می‌توانید جلسات پرداخت را برای مهمانان برنامه خود که «حساب» ندارند، راه‌اندازی کنید:

use Illuminate\Http\Request;
use Laravel\Cashier\Checkout;
 
Route::get('/product-checkout', function (Request $request) {
return Checkout::guest()->create('price_tshirt', [
'success_url' => route('your-success-route'),
'cancel_url' => route('your-cancel-route'),
]);
});

به طور مشابه هنگام ایجاد جلسات تسویه حساب برای کاربران فعلی، می توانید از روش های اضافی موجود در Laravel\Cashier\CheckoutBuilder نمونه برای سفارشی کردن جلسه پرداخت مهمان استفاده کنید:

use Illuminate\Http\Request;
use Laravel\Cashier\Checkout;
 
Route::get('/product-checkout', function (Request $request) {
return Checkout::guest()
->withPromotionCode('promo-code')
->create('price_tshirt', [
'success_url' => route('your-success-route'),
'cancel_url' => route('your-cancel-route'),
]);
});

پس از اتمام تسویه حساب مهمان، Stripe می‌تواند checkout.session.completed رویداد webhook را ارسال کند، بنابراین مطمئن شوید که وب‌هوک Stripe خود را طوری پیکربندی کرده‌اید که واقعاً این رویداد را به برنامه شما ارسال کند. هنگامی که وب هوک در داشبورد Stripe فعال شد، می توانید وب هوک را با Cashier مدیریت کنید . شی موجود در محموله وب هوک، checkout شیئی خواهد بود که می توانید برای انجام سفارش مشتری خود، آن را بررسی کنید.

رسیدگی به پرداخت های ناموفق

گاهی اوقات، پرداخت برای اشتراک یا هزینه های تکی ممکن است با شکست مواجه شود. وقتی این اتفاق می‌افتد، Cashier استثنایی می‌اندازد Laravel\Cashier\Exceptions\IncompletePayment که به شما اطلاع می‌دهد که این اتفاق افتاده است. پس از گرفتن این استثنا، شما دو گزینه در مورد نحوه ادامه دارید.

ابتدا، می توانید مشتری خود را به صفحه تأیید پرداخت اختصاصی که همراه صندوقدار است هدایت کنید. این صفحه قبلاً دارای یک مسیر با نام مرتبط است که از طریق ارائه‌دهنده خدمات Cashier ثبت شده است. بنابراین، می توانید IncompletePayment استثنا را بگیرید و کاربر را به صفحه تأیید پرداخت هدایت کنید:

use Laravel\Cashier\Exceptions\IncompletePayment;
 
try {
$subscription = $user->newSubscription('default', 'price_monthly')
->create($paymentMethod);
} catch (IncompletePayment $exception) {
return redirect()->route(
'cashier.payment',
[$exception->payment->id, 'redirect' => route('home')]
);
}

در صفحه تأیید پرداخت، از مشتری خواسته می‌شود که اطلاعات کارت اعتباری خود را دوباره وارد کند و هرگونه اقدام اضافی مورد نیاز Stripe، مانند تأیید «3D Secure» را انجام دهد. پس از تایید پرداخت، کاربر به URL ارائه شده توسط redirect پارامتر مشخص شده در بالا هدایت می شود. پس از تغییر مسیر، متغیرهای رشته پرس و جو message (رشته) و success (عدد صحیح) به URL اضافه می شوند. صفحه پرداخت در حال حاضر از انواع روش پرداخت زیر پشتیبانی می کند:

  • کارت های اعتباری
  • Alipay
  • Bancontact
  • بدهی مستقیم BECS
  • EPS
  • جیروپای
  • ایده آل
  • SEPA Direct Debit

از طرف دیگر، می‌توانید به Stripe اجازه دهید تا تأیید پرداخت را برای شما انجام دهد. در این حالت، به جای هدایت مجدد به صفحه تأیید پرداخت، می‌توانید ایمیل‌های صورت‌حساب خودکار Stripe را در داشبورد Stripe خود تنظیم کنید. با این حال، اگر IncompletePayment استثنایی مشخص شود، همچنان باید به کاربر اطلاع دهید که یک ایمیل با دستورالعمل‌های تأیید پرداخت بیشتر دریافت خواهد کرد.

استثناهای پرداخت ممکن است برای روش‌های زیر اعمال شود: charge , invoiceFor و invoice در مدل‌هایی که از این Billable ویژگی استفاده می‌کنند. هنگام تعامل با اشتراک‌ها، create روش روی SubscriptionBuilder , و روش‌های incrementAndInvoice و swapAndInvoice در مدل‌های Subscription و SubscriptionItem ممکن است استثنائات پرداخت ناقصی ایجاد کند.

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

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

شما می توانید وضعیت خاص یک پرداخت ناقص را با بررسی payment دارایی در مورد استثنا بدست آورید:

use Laravel\Cashier\Exceptions\IncompletePayment;
 
try {
$user->charge(1000, 'pm_card_threeDSecure2Required');
} catch (IncompletePayment $exception) {
// Get the payment intent status...
$exception->payment->status;
 
// Check specific conditions...
if ($exception->payment->requiresPaymentMethod()) {
// ...
} elseif ($exception->payment->requiresConfirmation()) {
// ...
}
}

تایید پرداخت ها

برخی از روش‌های پرداخت برای تأیید پرداخت‌ها به داده‌های اضافی نیاز دارند. به عنوان مثال، روش‌های پرداخت SEPA به داده‌های «اجباری» اضافی در طول فرآیند پرداخت نیاز دارند. شما می توانید این داده ها را با استفاده از روش زیر در اختیار صندوقدار قرار دهید withPaymentConfirmationOptions :

$subscription->withPaymentConfirmationOptions([
'mandate_data' => '...',
])->swap('price_xxx');

برای بررسی همه گزینه‌های پذیرفته‌شده هنگام تأیید پرداخت‌ها، می‌توانید به اسناد Stripe API مراجعه کنید.

احراز هویت قوی مشتری

اگر کسب و کار شما یا یکی از مشتریان شما در اروپا مستقر است، باید از مقررات قوی تایید هویت مشتری (SCA) اتحادیه اروپا پیروی کنید. این مقررات در سپتامبر 2019 توسط اتحادیه اروپا برای جلوگیری از تقلب در پرداخت وضع شد. خوشبختانه، Stripe و Cashier برای ساخت برنامه های سازگار با SCA آماده شده اند.

پرداخت هایی که نیاز به تایید اضافی دارند

مقررات SCA معمولاً برای تأیید و پردازش پرداخت نیاز به تأیید اضافی دارند. وقتی این اتفاق می‌افتد، Cashier استثنایی ایجاد می‌کند Laravel\Cashier\Exceptions\IncompletePayment که به شما اطلاع می‌دهد که تأیید اضافی لازم است. اطلاعات بیشتر در مورد نحوه رسیدگی به این استثنائات را می توان در اسناد رسیدگی به پرداخت های ناموفق یافت .

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

وضعیت ناقص و سررسید گذشته

هنگامی که پرداخت نیاز به تأیید اضافی دارد، اشتراک در وضعیت incomplete یا past_due وضعیتی باقی می‌ماند که در ستون پایگاه داده آن نشان داده شده است stripe_status . صندوقدار به محض تکمیل تایید پرداخت و درخواست شما توسط Stripe از طریق webhook از تکمیل آن به طور خودکار اشتراک مشتری را فعال می کند.

برای اطلاعات بیشتر در مورد incomplete و past_due وضعیت ها، لطفاً به اسناد اضافی ما در مورد این ایالت ها مراجعه کنید .

اطلاعیه های پرداخت خارج از جلسه

از آنجایی که مقررات SCA مشتریان را ملزم می کند که گهگاه جزئیات پرداخت خود را حتی در زمانی که اشتراک آنها فعال است تأیید کنند، صندوقدار می تواند در صورت نیاز به تأیید پرداخت خارج از جلسه، اعلانی را برای مشتری ارسال کند. به عنوان مثال، این ممکن است زمانی رخ دهد که یک اشتراک در حال تمدید است. اعلان پرداخت صندوقدار را می توان با تنظیم CASHIER_PAYMENT_NOTIFICATION متغیر محیطی روی یک کلاس اطلاع رسانی فعال کرد. به طور پیش فرض، این اعلان غیرفعال است. البته، Cashier شامل یک کلاس اعلان است که می توانید برای این منظور از آن استفاده کنید، اما در صورت تمایل می توانید کلاس اعلان خود را ارائه دهید:

CASHIER_PAYMENT_NOTIFICATION=Laravel\Cashier\Notifications\ConfirmPayment

برای اطمینان از اینکه اعلان‌های تأیید پرداخت خارج از جلسه تحویل داده می‌شوند، بررسی کنید که وبک‌هوک‌های Stripe برای برنامه شما پیکربندی شده‌اند invoice.payment_action_required و وب‌هوک در داشبورد Stripe شما فعال است. علاوه بر این، Billable مدل شما باید از ویژگی لاراول نیز استفاده کند Illuminate\Notifications\Notifiable .

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

Stripe SDK

بسیاری از اشیاء Cashier در اطراف اشیاء Stripe SDK قرار دارند. اگر می‌خواهید مستقیماً با اشیاء Stripe تعامل داشته باشید، می‌توانید به راحتی آنها را با استفاده از asStripe روش زیر بازیابی کنید:

$stripeSubscription = $subscription->asStripeSubscription();
 
$stripeSubscription->application_fee_percent = 5;
 
$stripeSubscription->save();

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

$subscription->updateStripeSubscription(['application_fee_percent' => 5]);

اگر می خواهید مستقیماً از کلاینت استفاده کنید، می توانید stripe متد را در کلاس فراخوانی کنید . به عنوان مثال، می توانید از این روش برای دسترسی به نمونه و بازیابی لیست قیمت ها از حساب Stripe خود استفاده کنید: Cashier Stripe\StripeClient StripeClient

use Laravel\Cashier\Cashier;
 
$prices = Cashier::stripe()->prices->all();

آزمایش کردن

هنگام آزمایش برنامه‌ای که از Cashier استفاده می‌کند، ممکن است درخواست‌های HTTP واقعی به Stripe API را تقلید کنید. با این حال، این مستلزم آن است که تا حدی رفتار خود Cashier را مجدداً اجرا کنید. بنابراین، توصیه می‌کنیم به تست‌های شما اجازه دهید به Stripe API واقعی برسند. اگرچه این سرعت کندتر است، اما اطمینان بیشتری به شما می دهد که برنامه شما همانطور که انتظار می رود کار می کند و هر آزمایش کند ممکن است در گروه آزمایش Pest / PHPUnit خود قرار گیرد.

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

برای شروع، نسخه آزمایشی راز Stripe خود را به phpunit.xml فایل خود اضافه کنید:

<env name="STRIPE_SECRET" value="sk_test_<your-key>"/>

اکنون، هر زمان که هنگام آزمایش با Cashier تعامل داشته باشید، درخواست‌های API واقعی را به محیط تست Stripe شما ارسال می‌کند. برای راحتی، باید حساب آزمایشی Stripe خود را با اشتراک ها / قیمت هایی که ممکن است در طول آزمایش استفاده کنید، از قبل پر کنید.

به منظور آزمایش انواع سناریوهای صورت‌حساب، مانند رد کردن و خرابی کارت اعتباری، می‌توانید از طیف وسیعی از شماره‌ها و نشانه‌های کارت تست ارائه شده توسط Stripe استفاده کنید.