Laravel Cashier
مقدمة
يقدم Laravel Cashier واجهة قويّة لاشتراكات خدمات الفواتير Stripe و Braintree، وهي تعالج تقريبًا كل شيفرات boilerplate الخاصة باشتراك الفواتير التي تخشى من كتابتها، وبالإضافة إلى إدارة الاشتراكات الأساسية، يستطيع Cashier التعامل مع القسائم (coupons)، ومبادلة الاشتراكات وكميّات الاشتراكات وفترات السماح بالإلغاء وحتى إنشاء ملفات PDF للفواتير.
تنبيه: إذا كنت تضع رسوم لمرة واحدةً فقط ولا توفّر الاشتراكات، فيجب عليك أن لا تستخدم Cashier، وبدلًا من ذلك، يجب عليك استخدام حزمة برمجيات التطوير (SDK) الخاصة بـ Braintree و Stripe مباشرةً.
الضبط
Stripe
Composer
أولًا، أضف حزمة Cashier الخاصة بخدمة Stripe إلى اعتماديّاتك:
composer require "laravel/cashier":"~7.0"
تهجير قواعد البيانات
قبل استخدام Cashier، سنحتاج أيضًا إلى إعداد قاعدة البيانات، وذلك عن طريق إضافة عدة أعمدة إلى جدول users
وإنشاء جدول subscriptions
جديد لاحتواء جميع اشتراكات عملائنا:
Schema::table('users', function ($table) {
$table->string('stripe_id')->nullable();
$table->string('card_brand')->nullable();
$table->string('card_last_four')->nullable();
$table->timestamp('trial_ends_at')->nullable();
});
Schema::create('subscriptions', function ($table) {
$table->increments('id');
$table->unsignedInteger('user_id');
$table->string('name');
$table->string('stripe_id');
$table->string('stripe_plan');
$table->integer('quantity');
$table->timestamp('trial_ends_at')->nullable();
$table->timestamp('ends_at')->nullable();
$table->timestamps();
});
بمجرّد إنشاء التهجيرات، شغّل أمر migrate
Artisan.
نموذج Billable
بعد ذلك، أضف سمة Billable
إلى تعريف نموذجك، توفّر هذه السمة طرقًا مختلفة تسمح لك بتنفيذ مهام الفوترة الشائعة، كإنشاء الاشتراكات وتطبيق القسائم وتحديث بيانات بطاقة الائتمان:
use Laravel\Cashier\Billable;
class User extends Authenticatable
{
use Billable;
}
مفاتيح الواجهة البرمجيّة API
ختامًا، يجب عليك ضبط مفتاح Stripe في ملف الضبط services.php
، ويمكنك استرداد مفاتيح Stripe API من لوحة تحكم Stripe:
'stripe' => [
'model' => App\User::class,
'key' => env('STRIPE_KEY'),
'secret' => env('STRIPE_SECRET'),
],
Braintree
تحذيرات Braintree
تعمل تطبيقات Stripe و Braintree بنفس الطريقة في عدة عمليات، فكلاهما يوفران فوترة الاشتراك ببطاقات الائتمان لكن يدعم Paypal Braintree أيضًا، ومع ذلك، يفتقر Braintree إلى بعض المميزات المدعومة من Stripe، ويجب عليك مراعاة ما يلي عند اتخاذ قرار استخدام Stripe أو Braintree:
- يدعم Paypal Braintree على عكس Stripe.
- لا يدعم Braintree توابع الزيادة والنقصان على الاشتراكات، وهذه حدود Braintree وليست حدود Cashier.
- لا يدعم Braintree الخصومات القائمة على النسبة المئويّة، وهذه حدود Braintree وليست حدود Cashier.
Composer
أضف أولًا حزمة Cashier الخاصة بخدمة Braintree إلى اعتماديّاتك:
composer require "laravel/cashier-braintree":"~2.0"
مقدم الخدمة
بعد ذلك، سجّل مقدّم الخدمة Laravel\Cashier\CashierServiceProvider
في ملف الضبط config/app.php
:
Laravel\Cashier\CashierServiceProvider::class
قسيمة خطة الائتمان
قبل استخدام Cashier مع Braintree، ستحتاج إلى تعريف قسيمة plan-credit في لوحة تحكم Braintree، وسيُستخدم هذا الخصم لتجزئة الاشتراكات التي تتغيّر من الفوترة السنويّة إلى الشهريّة أو من الشهريّة إلى السنويّة.
يمكن أن يكون مقدار الخصم الذي تريد تكوينه في لوحة تحكم Braintree أي قيمة تريدها، حيث سيعيد Cashier تعريف المبلغ المحدد بالمبلغ المخصص الخاص بنا في كل مرة نطبّق فيها القسيمة، وهذه القسيمة مطلوبة لأن Braintree لا يدعم الاشتراكات التناسبية عبر ترددات الاشتراك.
تهجير قواعد البيانات
قبل استخدام Cashier، سنحتاج إلى إعداد قاعدة البيانات، وذلك عن طريق إضافة عدة أعمدة إلى جدول users
و إنشاء جدول subscriptions
جديد لاحتواء جميع اشتراكات عملائنا:
Schema::table('users', function ($table) {
$table->string('braintree_id')->nullable();
$table->string('paypal_email')->nullable();
$table->string('card_brand')->nullable();
$table->string('card_last_four')->nullable();
$table->timestamp('trial_ends_at')->nullable();
});
Schema::create('subscriptions', function ($table) {
$table->increments('id');
$table->unsignedInteger('user_id');
$table->string('name');
$table->string('braintree_id');
$table->string('braintree_plan');
$table->integer('quantity');
$table->timestamp('trial_ends_at')->nullable();
$table->timestamp('ends_at')->nullable();
$table->timestamps();
});
بمجرّد إنشاء التهجيرات، شغّل أمر migrate
Artisan.
نموذج Billable
بعد ذلك، أضف سمة Billable
إلى تعريف نموذجك:
use Laravel\Cashier\Billable;
class User extends Authenticatable
{
use Billable;
}
مفاتيح الواجهة البرمجيّة API
ختامًا، يجب عليك ضبط الخيارات التاليّة في ملف الضبط services.php
:
'braintree' => [
'model' => App\User::class,
'environment' => env('BRAINTREE_ENV'),
'merchant_id' => env('BRAINTREE_MERCHANT_ID'),
'public_key' => env('BRAINTREE_PUBLIC_KEY'),
'private_key' => env('BRAINTREE_PRIVATE_KEY'),
],
ثم يجب عليك إضافة استدعاءات حزمة برمجيات التطوير Braintree SDK التالية إلى تابع boot الخاص بموفّر الخدمة AppServiceProvider:
\Braintree_Configuration::environment(config('services.braintree.environment'));
\Braintree_Configuration::merchantId(config('services.braintree.merchant_id'));
\Braintree_Configuration::publicKey(config('services.braintree.public_key'));
\Braintree_Configuration::privateKey(config('services.braintree.private_key'));
ضبط العملة
العملة الافتراضية لـ Cashier هي الدولار الأمريكي (USD)، ويمكنك تغيير العملة الافتراضيّة باستدعاء تابع Cashier::useCurrency
من داخل تابع boot
من أحد موفرّي الخدمة.
يقبل تابع useCurrency
سلستين نصيتيّن كمعاملات: العملة ورمز العملة:
use Laravel\Cashier\Cashier;
Cashier::useCurrency('eur', '€');
الاشتراكات
إنشاء الاشتراكات
لإنشاء اشتراك، استردّ نسخة من نموذج billable
والتي ستكون عادةً نسخة من App\User
، وبمجرد استرداد نسخة النموذج، يمكنك استخدام تابع newSubscription
لإنشاء اشتراك النموذج:
$user = User::find(1);
$user->newSubscription('main', 'premium')->create($stripeToken);
يجب أن يكون المعامل الأول الممرّر إلى تابع newSubscription هو اسم الاشتراك، إذا كان تطبيقك يوفّر نوع واحد من الاشتراكات، يمكنك تسميته main أو primary، وأما المعامل الثاني فهو تحديد خطة Stripe أو Braintree التي يشترك فيها المستخدم، ويجب أن تتوافق هذه القيمة مع معرّف Stripe أو Braintree.
سيبدأ التابع create
، والذي يقبل بطاقة ائتمان أو رمز مصدر Stripe، الاشتراك بالإضافة إلى تحديث قاعدة بياناتك بمعرّف العميل ومعلومات الفوترة ذات الصلة.
بيانات المستخدم إضافيّة
إذا كنت ترغب في تحديد تفاصيل إضافيّة للعميل، فيمكنك القيام بذلك عن طريق تمريرها كمعامل ثاني إلى التابع create
:
$user->newSubscription('main', 'monthly')->create($stripeToken, [
'email' => $email,
]);
لمعرفة المزيد حول الحقول الإضافية المدعومة بواسطة Stripe أو Braintree، راجع توثيق Stripe حول إنشاء العميل أو توثيق Braintree المشابهة.
القسائم
إذا رغبت في تطبيق قسيمة عند إنشاء الاشتراك، فيمكنك استخدام تابع withCoupon
:
$user->newSubscription('main', 'monthly')
->withCoupon('code')
->create($stripeToken);
التحقق من حالة الاشتراك
بمجرد اشتراك المستخدم بتطبيقك، يمكنك التحقق بسهولة من حالة الاشتراك باستخدام مجموعة متنوعة من التوابع المناسبة، فالتابع subscribed
يرجع true
إذا كان للمستخدم اشتراك نشط، وحتى إذا كان الاشتراك حاليًا ضمن الفترة التجريبيّة:
if ($user->subscribed('main')) {
//
}
إن التابع subscribed
هو مرشح رائع لبرمجيّة وسيطة للمسار، فهو يسمح لك بترشيح الوصول إلى المسارات ووحدات التحكم بناءًا على حالة اشتراك المستخدم:
public function handle($request, Closure $next)
{
if ($request->user() && ! $request->user()->subscribed('main')) {
// This user is not a paying customer...
return redirect('billing');
}
return $next($request);
}
إذا أردت تحديد ما إذا كان المستخدم ما يزال ضمن الفترة التجريبيّة، فيمكنك استخدام التابع onTrial
، ويمكنك استخدام هذا التابع لعرض تحذير للمستخدم بأنه ما يزال في الفترة التجريبيّة الخاصة به:
if ($user->subscription('main')->onTrial()) {
//
}
يمكن استخدام التابع subscribedToPlan
لتحديد ما إذا كان المستخدم مشتركًا بخطة معينة بناءً على معرّف الخطة في Stripe / Braintree، وفي هذا المثال، سنحدد ما إذا كان الاشتراك main للمستخدم مفعّل للخطة الشهريّة:
if ($user->subscribedToPlan('monthly', 'main')) {
//
}
حالة الاشتراك الملغى
لتحديد ما إذا كان المستخدم مشتركًا نشيطًا سابقًا ولكنه ألغى اشتراكه، يمكنك استخدام تابع cancelled
:
if ($user->subscription('main')->cancelled()) {
//
}
يمكنك أيضًا تحديد ما إذا كان المستخدم قد ألغى اشتراكه ولكنه لا يزال في فترة "السماح" حتى انتهاء صلاحيّة اشتراكه بالكامل، فعلى سبيل المثال، إذا الغى المستخدم اشتراكه في الخامس من شهر آذار/مارس والذي من المقرر في الأصل أن تنتهي صلاحيته في 10 من آذار/مارس، فسيكون المستخدم في فترة "السماح" حتى 10 من آذار/مارس، ولاحظ أن التابع subscribed
سيرجع true
في هذه الحالة:
if ($user->subscription('main')->onGracePeriod()) {
//
}
تغيير الخطط
قد يرغب المستخدم بعد اشتراك في تطبيقك في تغييره إلى خطة اشتراك جديدة، ولاستبدال اشتراك جديد باشتراك المستخدم الحالي، مرّر معرّف الخطة إلى التابع swap
:
$user = App\User::find(1);
$user->subscription('main')->swap('provider-plan-id');
إذا كان المستخدم قيد الإصدار التجريبي، فسيُحتفظ بالفترة التجريبيّة أيضًا وإذا كان هنالك كميّة للاشتراك، فسيُحتفظ بتلك الكميّة quantity أيضًا.
إذا أردت مبادلة الخطط وإلغاء أي فترة تجريبيّة للمستخدم قيد التشغيل حاليًا، فيمكنك استخدام التابع skipTrial
:
$user->subscription('main')
->skipTrial()
->swap('provider-plan-id');
كميّة الاشتراك
تنبيه: كميّة الاشتراك مدعومة فقط من نسخة Stripe من Cashier، فلا يملك Braintree خاصيّة تتوافق مع "كميّة" Stripe.
تتأثر في بعض الأحيان الاشتراكات بالكميّة، فعلى سبيل المثال، إذا كان يتقاضى تطبيقك 10 دولارات شهريًا للمستخدم على الحساب، فلزيادة أو نقصان كميّة الاشتراك بسهولة، يمكنك استخدام التوابع incrementQuantity
وdecrementQuantity
:
$user = User::find(1);
$user->subscription('main')->incrementQuantity();
// Add five to the subscription's current quantity...
$user->subscription('main')->incrementQuantity(5);
$user->subscription('main')->decrementQuantity();
// Subtract five to the subscription's current quantity...
$user->subscription('main')->decrementQuantity(5);
يمكنك بدلًا من ذلك تعيين كميّة محددة باستخدام التابع updateQuantity
:
$user->subscription('main')->updateQuantity(10);
يمكنك استخدام التابع noProrate
لتحديث كميّة الاشتراك دون تقييم الرسوم:
$user->subscription('main')->noProrate()->updateQuantity(10);
للمزيد من المعلومات حول كميّات الاشتراك، راجع توثيق Stripe.
رسوم الاشتراك
لتحديد نسبة الرسوم للمستخدم على الاشتراك، طبّق التابع taxPercentage
على نموذج billable
الخاص بك، وأرجع قيمة رقميّة بين 0 و 100، مع عدم وجود أكثر من منزلتين عشريتين.
public function taxPercentage() {
return 20;
}
يمكّنك التابع taxPercentage
من تطبيق معدّل الرسوم على أساسيات نموذج بنموذج model-by-model، والذي قد يكون مفيدًا لقاعدة المستخدمين التي تغطي الكثير من البلدان ومعدلات الرسوم.
تنبيه: لا يطبّق التابع taxPercentage
على رسوم الاشتراك فقط، فإذا استخدمت Cashier لتحصيل رسوم دفعة واحدة، فستحتاج إلى تعديد معدل الرسوم يدويًا في ذلك الوقت.
إلغاء الاشتراكات
لإلغاء اشتراك، استدع التابع cancel
على اشتراك المستخدم:
$user->subscription('main')->cancel();
عند إلغاء الاشتراك، سيعيّن Cashier بشكل تلقائي عمود ends_at
في قاعدة بياناتك، وسيُستخدم هذا العمود لمعرفة متى يجب على التابع subscribed
إرجاع القيمة false
، فعلى سبيل المثال، إذا ألغى عميل اشتراكه في الأول من مارس،ولم يكن من المقرر أن ينتهي الاشتراك حتى الخامس من مارس، فسيبقى التابع subscribed
يرجع true
حتى تاريخ 5 مارس.
يمكنك تحديد ما إذا كان المستخدم قد ألغى اشتراكه ولكن لا يزال في فترة "السماح" عن طريق استخدام التابع onGracePeriod
:
if ($user->subscription('main')->onGracePeriod()) {
//
}
إذا رغبت في إنهاء الاشتراك فورًا، فاستدع التابع cancelNow
على اشتراك المستخدم:
$user->subscription('main')->cancelNow();
استئناف الاشتراكات
إذا ألغى مستخدم اشتراكه ويرغب في استئنافه استخدم التابع resume
، ويجب على المستخدم أن يظل في فترة السماح لاستئناف اشتراكه:
$user->subscription('main')->resume();
إذا ألغى مستخدم اشتراكه ثم استأنفه قبل انتهاء صلاحيّة الاشتراك بالكامل فلن يحاسب على الفور، وبدلًا من ذلك، سيعاد تنشيط اشتراكه وسيحاسب على دورة الفوترة الأصليّة.
تحديث بطاقات الائتمان
يمكن استخدام التابع updateCard
لتحديث معلومات بطاقة ائتمان العميل، ويقبل هذا التابع رمز Stripe وسيعيّن بطاقة الائتمان الجديدة المصدر الافتراضي للفوترة:
$user->updateCard($stripeToken);
الفترات التجريبيّة للاشتراكات
مع واجهة بطاقة الائتمان
إذا كنت ترغب في توفير فترات تجريبيّة لعملائك مع الاستمرار في جمع معلومات طريقة الدفع، يجب عليك استخدام التابع trialDays
عند إنشائك للاشتراك:
$user = User::find(1);
$user->newSubscription('main', 'monthly')
->trialDays(10)
->create($stripeToken);
سيحدد هذا التابع تاريخ انتهاء الفترة التجريبيّة في سجل الاشتراك داخل قاعدة البيانات، بالإضافة إلى إرشاد Stripe أو Braintree إلى عدم البدء في إعداد فواتير للعميل إلى ما بعد هذا التاريخ.
تنبيه: إذا لم يلغي العميل اشتراكه قبل انتهاء الفترة التجريبيّة فسُتفرض الرسوم فور انتهاء الفترة التجريبيّة، لذلك يجب عليك التأكد من إبلاغ المستخدمين بتاريخ انتهاء الفترة التجريبيّة.
يتيح لك التابع trialUntil
توفير نسخة DateTime
لتحديد موعد انتهاء الفترة التجريبيّة:
use Carbon\Carbon;
$user->newSubscription('main', 'monthly')
->trialUntil(Carbon::now()->addDays(10))
->create($stripeToken);
يمكنك معرفة ما إذا كان المستخدم في فترته التجريبيّة أو لا إما باستخدام التابع onTrial
على نسخة المستخدم أو باستخدام التابع onTrial
على نسخة الاشتراك، فالمثالان التاليان متطابقان:
if ($user->onTrial('main')) {
//
}
if ($user->subscription('main')->onTrial()) {
//
}
بدون واجهة بطاقة الائتمان
إذا كنت ترغب في تقديم فترات تجريبيّة دون جمع معلومات عن طريقة دفع المستخدم، يمكنك تعيين عمود trial_ends_at
في سجل المستخدم بناءً على تاريخ انتهاء الإصدار التجريبي المطلوب، ويتم ذلك عادةً أثناء تسجيل المستخدم:
$user = User::create([
// ملأ بقية خصائص المستخدم
'trial_ends_at' => now()->addDays(10),
]);
تنبيه: تأكد من إضافة تاريخ لـ trial_ends_at
لتعريف النموذج.
يشير Cashier إلى نوع الفترة التجريبيّة على أنها "تجربة عامة"، نظرًا لأنه غير مرتبط بأي اشتراك حالي، وسيُرجع التابع onTrial
في نسخة User
القيمة true
إذا لم يتجاوز التاريخ الحالي قيمة trial_ends_at
:
if ($user->onTrial()) {
// المستخدم في الفترة التجريبية
}
يمكنك أيضًا استخدام التابع onGenericTrial
إذا أردت معرفة على وجه التحديد أن المستخدم ضمن فترة النسخة التجريبيّة العامة ولم ينشئ اشتراكًا فعليًّا بعد:
if ($user->onGenericTrial()) {
// المستخدم في الفترة التجريبية العامة
}
بمجرّد استعدادك لإنشاء اشتراك فعلي للمستخدم، يمكنك استخدام التابع newSubscription
كالمعتاد:
$user = User::find(1);
$user->newSubscription('main', 'monthly')->create($stripeToken);
معالجة خطاطيف الويب في Stripe
يمكن لكل من Stripe وBraintree إعلام تطبيقك بمجموعة من الأحداث عبر خطاطيف الويب (webhooks)، ولمعالجة خطاطيف الويب في Stripe، يجب عليك تعريف المسار الذي يشير إلى وحدة تحكم خطّاف الويب الخاص بـ Cashier، وستُعالج وحدة التحكم هذه جميع طلبات خطّاف الويب الواردة وترسلها إلى تابع وحدة التحكم المناسب:
Route::post(
'stripe/webhook',
'\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook'
);
تنبيه: بمجرّد تسجيل الطريق الخاص بك، تأكد من تكوين عنوان خطاف ويب webhook URL في إعدادات لوحة تحكم Stripe.
بشكل افتراضي، ستتعامل وحدة التحكم تلقائيًا مع إلغاء الاشتراكات التي تحتوي على عدد كبير من محاولات الحصول على الرسوم الفاشلة (كما هو محدد بواسطة إعدادات Stripe)، ومع ذلك، كما سنكتشف قريبًا، يمكننا توسيع وحدة التحكم للتعامل مع أي حدث خطاف ويب ترغب به.
خطاطيف الويب وحماية CSRF
نظرًا لأن خطاطيف ويب Stripe تحتاج إلى تجاوز حماية CSRF الخاصة بإطار Laravel، تأكد من وضع عنوان URI كاستثناء في البرمجيّة الوسيطة VerifyCsrfToken
الخاصة بك أو ضع المسار خارج مجموعة البرمجيّة الوسيطة web:
protected $except = [
'stripe/*',
];
تعريف معالجات أحداث خطاطيف الويب
سيتعامل Cashier بشكل تلقائي بإلغاء الاشتراك عند فشل شحن المبلغ، لكن إذا كان لديك أحداث خطاطيف ويب Stripe ترغب في معالجتها، فوسّع وحدة التحكم خطّاف الويب ويجب أن تكون أسماء التوابع متطابقة مع اتفاقيّة Cashier المتوقعة، والتي تنصّ على أنه يجب أن تبدأ بالكلمة handle وتستخدم حالة سِنَام الجمل (camelCase) لاسم خطّاف الويب الذي ترغب في معالجته. فعلى سبيل المثال، إذا كنت ترغب في معالجة خطاف الويب الخاص بالخطاف invoice.payment_succeeded
فيجب عليك إضافة التابع handleInvoicePaymentSucceeded
إلى وحدة التحكم:
<?php
namespace App\Http\Controllers;
use Laravel\Cashier\Http\Controllers\WebhookController as CashierController;
class WebhookController extends CashierController
{
/**
* التعامل مع خطاطيف الويب.
*
* @param مصفوفة $payload
* @return Response
*/
public function handleInvoicePaymentSucceeded($payload)
{
// معالجة الحدث
}
}
بعد ذلك، حدد المسار إلى وحدة التحكم Cashier داخل ملف routes/web.php
:
Route::post(
'stripe/webhook',
'\App\Http\Controllers\WebhookController@handleWebhook'
);
اشتراكات فاشلة
ماذا لو انتهت صلاحيّة بطاقة ائتمان العميل؟ لا تقلق! يحتوي Cashier على وحدة تحكم خطاف ويب يمكنها إلغاء اشتراك العميل بسهولة.
وكما ذُكِر أعلاه، كل ما عليك القيام به هو توجيه المسار إلى وحدة التحكم:
Route::post(
'stripe/webhook',
'\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook'
);
وهذا كل شيء، ستُلتقط المدفوعات الفاشلة وتُعالج عن طريق وحدة التحكم، وستلغي وحدة التحكم اشتراك العميل عندما يعلن Stripe فشل الاشتراك (عادةً بعد ثلاث محاولات دفع فاشلة).
معالجة خطاطيف الويب في Braintree
يمكن لكل من Stripe وBraintree إعلام تطبيقك بمجموعة من الأحداث عبر خطاطيف الويب، ولمعالجة خطاطيف ويب Braintree، يجب عليك تعريف المسار الذي يشير إلى وحدة تحكم خطّاف الويب الخاص بـ Cashier، وستعالج وحدة التحكم هذه جميع طلبات خطّاف الويب الواردة وترسلها إلى تابع وحدة التحكم المناسب:
Route::post(
'braintree/webhook',
'\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook'
);
تنبيه: بمجرّد تسجيل المسار الخاص بك، تأكد من إنشاء عنوان خطاف ويب webhook URL في إعدادات لوحة تحكم Braintree.
بشكل افتراضي، ستتعامل وحدة التحكم هذه تلقائيًا مع إلغاء الاشتراكات التي تحتوي على عدد كبير من محاولات الحصول على الرسوم الفاشلة (كما هو محدد بواسطة إعدادات Braintree)، ومع ذلك، كما سنكتشف قريبًا، يمكننا توسيع وحدة التحكم للتعامل مع أي حدث خطّاف ويب ترغب به.
خطاطيف الويب وحماية CSRF
نظرًا لأن خطاطيف ويب Braintree تحتاج إلى تجاوز حماية CSRF الخاصة بإطار Laravel، فتأكد من وضع URI كاستثناء في وسيطة VerifyCsrfToken
الخاصة بك أو ضع مسار خارج مجموعة وسيطة web:
protected $except = [
'braintree/*',
];
تعريف معالجات أحداث خطاطيف الويب
سيتعامل Cashier بشكل تلقائي بإلغاء الاشتراك عند فشل شحن المبلغ، لكن إذا كان لديك أحداث Braintree خطّاف ويب ترغب في معالجتها، فوسّع وحدة التحكم خطّاف الويب ويجب أن تكون أسماء التوابع متطابقة مع اتفاقيّة Cashier المتوقعة، والتي تنصّ على أنه يجب أن تبدأ بالكلمة handle وتستخدم حالة سِنَام الجمل (camelCase) لاسم خطّاف الويب الذي ترغب في معالجته. فعلى سبيل المثال، إذا كنت ترغب في التعامل مع خطّاف الويب dispute_opened
فيجب عليك إضافة التابع handleDisputeOpened
إلى وحدة التحكم:
<?php
namespace App\Http\Controllers;
use Braintree\WebhookNotification;
use Laravel\Cashier\Http\Controllers\WebhookController as CashierController;
class WebhookController extends CashierController
{
/**
* التعامل مع خطّافي Braintree.
*
* @param WebhookNotification $webhook
* @return Response
*/
public function handleDisputeOpened(WebhookNotification $notification)
{
// Handle The Event
}
}
اشتراكات فاشلة
ماذا لو انتهت صلاحيّة بطاقة ائتمان العميل؟ لا تقلق! يحتوي Cashier على وحدة التحكم خطّاف الويب الذي يمكنه إلغاء اشتراك العميل بسهول.
وكما ذكر أعلاه، كل ما عليك القيام به هو توجيه المسار إلى وحدة التحكم:
Route::post(
'braintree/webhook',
'\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook'
);
وهذا كل شيء، ستُلتقط المدفوعات الفاشلة وتُعالج عن طريق وحدة التحكم، وستلغى وحدة التحكم اشتراك العميل عندما يعرّف Braintree بفشل الاشتراك (عادةً بعد ثلاث محاولات دفع فاشلة). لا تنس أنك بحاجة إلى إعداد عنوان خطّاف الويب webhook URI في إعدادات لوحة تحكم Braintree الخاصة بك.
رسوم واحدة
رسم بسيط
تنبيه: عند استخدام Stripe، سيقبل التابع charge
المقدار الذي ترغب في خصمه في أدنى مقام للعملة المستخدمة في طلب اشتراكك، ومع ذلك، عند استخدام Braintree، يجب عليك تمرير المبلغ الكامل بالدولار إلى التابع charge
:
إذا كنت ترغب في إجراء دفعة واحدة لبطاقة ائتمان أحد العملاء المشتركين، فيمكنك استخدام التابع charge
على نسخة نموذج Billable
.
// centsتقبل الدفعات بال Stripe
$user->charge(100);
//Dollarsتقبل الدفعات بال Braitree
$user->charge(1);
يقبل التابع charge
مصفوفة كمعامل ثاني مما يسمح لك بتمرير أي خيارات ترغب في تضمينها لرسوم إنشاء Stripe / Braintree، راجع توثيقات Stripe أو Braintree المتعلقة بالخيارات المتاحة لك عند إنشاء الرسوم:
$user->charge(100, [
'custom_option' => $value,
]);
سيرمي التابع charge
استثناء إذا فشلت عمليّة الشحن، وإذا نجحت، فستعاد إجابة Stripe أو Braintree كاملة من التابع:
try {
$response = $user->charge(100);
} catch (Exception $e) {
//
}
الشحن مع الفاتورة
قد تحتاج في بعض الأحيان إلى تحصيل رسوم لمرة واحدة ولكن ترغب أيضًا في إنشاء فاتورة لتحصيل الرسوم حتى تتمكن من تقديم إيصال بصيغة PDF إلى عميلك، يسمح لك التابع invoiceFor
بذلك. فعلى سبيل المثال، لنفرض على العميل رسوم 5.00$ لمرة واحدة:
// centsتقبل الدفعات بال Stripe
$user->invoiceFor('One Time Fee', 500);
// dollarsتقبل الدفعات بال Braitree
$user->invoiceFor('One Time Fee', 5);
ستفرض الفاتورة على الفور على بطاقة ائتمان المستخدم، يقبل التابع invoiceFor
مصفوفة كمعامل ثالث، مما يسمح لك بتمرير أي خيارات ترغب في تمريرها إلى Stripe أو Braintree عند إنشاء الرسم:
$user->invoiceFor('One Time Fee', 500, [
'custom-option' => $value,
]);
إذا كنت تستخدم Braintree كموفّر للفوترة، يجب عليك تضمين خيار description
عند استدعاء التابع invoiceFor
:
$user->invoiceFor('One Time Fee', 500, [
'description' => 'your invoice description here',
]);
سينشئ التابع invoiceFor
فاتورة Stripe والتي ستعيد محاولات الفوترة الفاشلة، وإذا كنت لا ترغب في إنشاء فاتورة لإعادة المحاولة مع العمليات الفاشلة، ستحتاج إلى إغلاقها باستخدام واجهة Stripe البرمجية بعد أول عمليّة تحصيل رسوم فاشلة.
الفواتير
يمكنك استرداد مصفوفة من فواتير نموذج billable
بسهولة باستخدام التابع invoices
:
$invoices = $user->invoices();
// تضمين الفواتير المعلّقة في النتائج
$invoices = $user->invoicesIncludingPending();
عند إدراج الفواتير الخاصة بالعميل، يجوز لك استخدام التوابع المساعدة لعرض معلومات الفاتورة ذات الصلة، فعلى سبيل المثال، قد ترغب في سرد كل فاتورة في جدول مما يسمح للمستخدم تنزيل أي منها بسهولة:
<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>
توليد فواتير PDF
من خلال المسار أو وحدة التحكم، استخدم التابع 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',
]);
});