نسخه:

صندوقدار لاراول

معرفی

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

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

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

برای جلوگیری از شکستن تغییرات، Cashier از یک نسخه API ثابت Stripe استفاده می کند. Cashier 12 از نسخه Stripe API استفاده می کند 2020-03-02 . نسخه Stripe API در نسخه‌های کوچک به‌روزرسانی می‌شود تا از ویژگی‌ها و بهبودهای جدید Stripe استفاده کند.

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

ابتدا به بسته Cashier برای Stripe with Composer نیاز دارید:

composer require laravel/cashier

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

مهاجرت های پایگاه داده

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

php artisan migrate

اگر نیاز به بازنویسی انتقال‌هایی دارید که با بسته Cashier ارسال می‌شوند، می‌توانید آنها را با استفاده از vendor:publish دستور Artisan منتشر کنید:

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

اگر می خواهید از اجرای کامل مهاجرت صندوقدار جلوگیری کنید، می توانید از برنامه ignoreMigrations ارائه شده توسط صندوقدار استفاده کنید. register به طور معمول، این روش باید در متد شما فراخوانی شود AppServiceProvider :

use Laravel\Cashier\Cashier;
 
Cashier::ignoreMigrations();

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

پیکربندی

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

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

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

Cashier فرض می کند که مدل Billable شما کلاسی است App\User که با لاراول ارسال می شود. اگر می خواهید این را تغییر دهید، می توانید مدل دیگری را در .env فایل خود مشخص کنید:

CASHIER_MODEL=App\User

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

کلیدهای API

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

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

پیکربندی ارز

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

CASHIER_CURRENCY=eur

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

CASHIER_CURRENCY_LOCALE=nl_BE

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

ورود به سیستم

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

CASHIER_LOGGER=stack

مشتریان

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

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

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

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

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

$stripeCustomer = $user->createAsStripeCustomer();

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

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

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

$stripeCustomer = $user->asStripeCustomer();

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

$stripeCustomer = $user->createOrGetStripeCustomer();

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

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

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

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

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

use Illuminate\Http\Request;
 
public function billingPortal(Request $request)
{
return $request->user()->redirectToBillingPortal();
}

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

use Illuminate\Http\Request;
 
public function billingPortal(Request $request)
{
return $request->user()->redirectToBillingPortal(
route('billing')
);
}

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

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

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

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

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

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

هنگام ذخیره کارت های اعتباری برای مشتری برای استفاده در آینده، Stripe Setup Intents API باید برای جمع آوری ایمن جزئیات روش پرداخت مشتری استفاده شود. یک "نیت راه اندازی" به Stripe نشان می دهد که قصد دارد از روش پرداخت مشتری هزینه کند. Billable ویژگی Cashier شامل 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 موجود در نمونه مدل Billable مجموعه ای از Laravel\Cashier\PaymentMethod نمونه ها را برمی گرداند:

$paymentMethods = $user->paymentMethods();

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

$paymentMethod = $user->defaultPaymentMethod();

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

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

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

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

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

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

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

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

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

$user->updateDefaultPaymentMethod($paymentMethod);

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

$user->updateDefaultPaymentMethodFromStripe();

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

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

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

$user->addPaymentMethod($paymentMethod);

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

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

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

$paymentMethod->delete();

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

$user->deletePaymentMethods();

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

اشتراک ها

ایجاد اشتراک

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

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

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

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

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

مقادیر

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

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

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

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

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

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

کوپن

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

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

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

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

$user = User::find(1);
 
$user->newSubscription('default', 'price_premium')->add();

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

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

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

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

public function handle($request, Closure $next)
{
if ($request->user() && ! $request->user()->subscribed('default')) {
// This user is not a paying customer...
return redirect('billing');
}
 
return $next($request);
}

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

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

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

if ($user->subscribedToPlan('price_monthly', 'default')) {
//
}

با ارسال یک آرایه به متد، می توانید تعیین کنید که آیا اشتراک subscribedToPlan کاربر به طور فعال در طرح یا طرح مشترک است: default monthly yearly

if ($user->subscribedToPlan(['price_monthly', 'price_yearly'], 'default')) {
//
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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 ، می توانید از keepPastDueSubscriptionsActive روش ارائه شده توسط Cashier استفاده کنید. register به طور معمول، این روش باید در متد شما فراخوانی شود AppServiceProvider :

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

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

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

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

$user = App\User::find(1);
 
$user->subscription('default')->swap('provider-price-id');

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

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

$user->subscription('default')
->skipTrial()
->swap('provider-price-id');

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

$user = App\User::find(1);
 
$user->subscription('default')->swapAndInvoice('provider-price-id');

تناسب

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

$user->subscription('default')->noProrate()->swap('provider-price-id');

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

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

مقدار اشتراک

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

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

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

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

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

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

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

لطفاً توجه داشته باشید که هنگام کار با اشتراک های چندطرفه، یک پارامتر "طرح" اضافی برای روش های کمیت بالا مورد نیاز است.

اشتراک های چند پلان

اشتراک های Multiplan به شما امکان می دهد چندین طرح صورتحساب را به یک اشتراک اختصاص دهید. به عنوان مثال، تصور کنید که در حال ساختن یک برنامه کاربردی "helpdesk" برای خدمات مشتری هستید که اشتراک پایه آن 10 دلار در ماه است، اما یک برنامه افزودنی چت زنده را با 15 دلار اضافی در ماه ارائه می دهد:

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

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

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

یا، می توانید طرح اضافی و مقدار آن را به صورت پویا با استفاده از plan روش اضافه کنید:

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

از طرف دیگر، می‌توانید در فرصتی دیگر طرح جدیدی را به اشتراک موجود اضافه کنید:

$user = User::find(1);
 
$user->subscription('default')->addPlan('chat-plan');

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

$user->subscription('default')->addPlanAndInvoice('chat-plan');

اگر می‌خواهید طرحی با کمیت خاص اضافه کنید، می‌توانید مقدار را به عنوان پارامتر دوم addPlan یا addPlanAndInvoice متدها ارسال کنید:

$user = User::find(1);
 
$user->subscription('default')->addPlan('chat-plan', 5);

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

$user->subscription('default')->removePlan('chat-plan');

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

مبادله

همچنین می‌توانید طرح‌های پیوست شده به اشتراک چندطرفه را تغییر دهید. basic-plan به عنوان مثال، تصور کنید که در یک اشتراک با یک chat-plan افزونه هستید و می خواهید به pro-plan برنامه ارتقا دهید:

$user = User::find(1);
 
$user->subscription('default')->swap(['pro-plan', 'chat-plan']);

هنگام اجرای کد بالا، آیتم اشتراک زیرین با کد basic-plan حذف می شود و موردی که دارای آن است chat-plan حفظ می شود. علاوه بر این، یک آیتم اشتراک جدید برای جدید pro-plan ایجاد می شود.

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

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

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

$user = User::find(1);
 
$user->subscription('default')
->findItemOrFail('basic-plan')
->swap('pro-plan');

تناسب

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

$user->subscription('default')->noProrate()->removePlan('chat-plan');

مقادیر

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

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

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

موارد اشتراک

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

$user = User::find(1);
 
$subscriptionItem = $user->subscription('default')->items->first();
 
// Retrieve the Stripe plan and quantity for a specific item...
$stripePlan = $subscriptionItem->stripe_plan;
$quantity = $subscriptionItem->quantity;

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

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

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

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

public function taxRates()
{
return ['tax-rate-id'];
}

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

public function planTaxRates()
{
return [
'plan-id' => ['tax-rate-id'],
];
}

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

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

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

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

این همچنین نرخ مالیات آیتم های اشتراک را همگام می کند، بنابراین مطمئن شوید که planTaxRates روش را نیز به درستی تغییر داده اید.

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

Cashier همچنین روش هایی را برای تعیین معافیت مالیاتی مشتری با فراخوانی Stripe API ارائه می دهد. روش های isNotTaxExempt , isTaxExempt و reverseChargeApplies در مدل قابل صورتحساب موجود است:

$user = User::find(1);
 
$user->isTaxExempt();
$user->isNotTaxExempt();
$user->reverseChargeApplies();

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

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

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

use App\User;
use Carbon\Carbon;
 
$user = User::find(1);
 
$anchor = Carbon::parse('first day of next month');
 
$user->newSubscription('default', 'price_premium')
->anchorBillingCycleOn($anchor->startOfDay())
->create($paymentMethod);

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

لغو اشتراک ها

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

این روش به شما امکان می دهد نمونه ای برای تعیین زمان پایان دوره آزمایشی trialUntil ارائه دهید : 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()) {
//
}

تعریف روزهای آزمایشی در Stripe / صندوقدار

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

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

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

$user = User::create([
// Populate other user properties...
'trial_ends_at' => now()->addDays(10),
]);

حتماً یک تغییردهنده تاریخ برای trial_ends_at تعریف مدل خود اضافه کنید.

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

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

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

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

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

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

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

این extendTrial روش به شما امکان می دهد دوره آزمایشی یک اشتراک را پس از ایجاد آن تمدید کنید:

// End the trial 7 days from now...
$subscription->extendTrial(
now()->addDays(7)
);
 
// Add an additional 5 days to the trial...
$subscription->extendTrial(
$subscription->trial_ends_at->addDays(5)
);

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

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

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

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

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

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

  • customer.subscription.updated
  • customer.subscription.deleted
  • customer.updated
  • customer.deleted
  • invoice.payment_action_required

Webhooks & CSRF Protection

از آنجایی که وب هوک های Stripe باید حفاظت CSRF لاراول را دور بزنند ، حتماً URI را به عنوان یک استثنا در VerifyCsrfToken میان افزار خود فهرست کنید یا مسیر خارج از web گروه میان افزار را فهرست کنید:

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

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

Cashier به طور خودکار لغو اشتراک را در صورت هزینه های ناموفق رسیدگی می کند، اما اگر رویدادهای webhook دیگری دارید که می خواهید مدیریت کنید، کنترلر Webhook را گسترش دهید. نام روش‌های شما باید مطابق با قرارداد مورد انتظار Cashier باشد، به‌ویژه، باید پیشوند روش‌ها handle و نام «مورد شتر» وب‌قلابی باشد که می‌خواهید مدیریت کنید. به عنوان مثال، اگر می خواهید invoice.payment_succeeded وب هوک را مدیریت کنید، باید یک handleInvoicePaymentSucceeded روش به کنترلر اضافه کنید:

<?php
 
namespace App\Http\Controllers;
 
use Laravel\Cashier\Http\Controllers\WebhookController as CashierController;
 
class WebhookController extends CashierController
{
/**
* Handle invoice payment succeeded.
*
* @param array $payload
* @return \Symfony\Component\HttpFoundation\Response
*/
public function handleInvoicePaymentSucceeded($payload)
{
// Handle The Event
}
}

در مرحله بعد، مسیری را برای کنترل صندوقدار خود در routes/web.php فایل خود تعریف کنید. با این کار مسیر پیش‌فرض ارسال شده بازنویسی می‌شود:

Route::post(
'stripe/webhook',
'\App\Http\Controllers\WebhookController@handleWebhook'
);

Cashier یک Laravel\Cashier\Events\WebhookReceived رویداد را هنگامی که یک وب هوک دریافت می‌کند، و یک Laravel\Cashier\Events\WebhookHandled رویداد زمانی که یک وب هوک توسط Cashier مدیریت می‌شود، منتشر می‌کند. هر دو رویداد حاوی بار کامل وب هوک Stripe هستند.

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

اگر اعتبار کارت اعتباری مشتری منقضی شود چه می شود؟ نگران نباشید - کنترلر Cashier's Webhook اشتراک مشتری را برای شما لغو می کند. پرداخت‌های ناموفق به‌طور خودکار توسط کنترل‌کننده ضبط و رسیدگی می‌شود. هنگامی که Stripe تشخیص دهد که اشتراک ناموفق بوده است، کنترل کننده اشتراک مشتری را لغو می کند (معمولاً پس از سه بار تلاش برای پرداخت ناموفق).

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

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

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

شارژ تک

شارژ ساده

این charge روش مبلغی را می‌پذیرد که می‌خواهید با کمترین مخرج ارز استفاده شده توسط برنامه شما شارژ کنید .

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

// Stripe Accepts Charges In Cents...
$stripeCharge = $user->charge(100, $paymentMethod);

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

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

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

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

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

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

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

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

// Stripe Accepts Charges In Cents...
$user->invoiceFor('One Time Fee', 500);

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

$user->invoiceFor('Stickers', 500, [
'quantity' => 50,
], [
'default_tax_rates' => ['tax-rate-id'],
]);

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

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

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

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

فاکتورها

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

می توانید به راحتی آرایه ای از فاکتورهای یک مدل قابل پرداخت را با استفاده از invoices روش زیر بازیابی کنید:

$invoices = $user->invoices();
 
// Include pending invoices in the results...
$invoices = $user->invoicesIncludingPending();

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

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

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

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

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

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

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

use Illuminate\Http\Request;
 
Route::get('user/invoice/{invoice}', function (Request $request, $invoiceId) {
return $request->user()->downloadInvoice($invoiceId, [
'vendor' => 'Your Company',
'product' => 'Your Product',
]);
});

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

return $request->user()->downloadInvoice($invoiceId, [
'vendor' => 'Your Company',
'product' => 'Your Product',
], 'my-invoice');

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

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

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

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

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

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

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

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

  • PaymentActionRequired : این نشان می دهد که Stripe برای تأیید و پردازش پرداخت نیاز به تأیید بیشتری دارد.
  • PaymentFailure : این نشان می دهد که یک پرداخت به دلایل مختلف دیگر مانند کمبود وجوه موجود شکست خورده است.

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

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

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

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

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

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

برای اطلاعات بیشتر در مورد 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]);

آزمایش کردن

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

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

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

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

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

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