Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Laravel Cashier (Stripe) - Subscription billing and payment processing
.claude/skills/microck-laravel-cashier-stripe/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-09 | ✗→✓ | ▲ Improved | 56% | 0% |
| case-19 | ✗→✓ | ▲ Improved | 140% | 0% |
| case-21 | ✓→✓ | = Same ✓ | 60% | 0% |
| case-01 | ✓→✓ | = Same ✓ | 495% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 422% | 0% |
Comprehensive assistance with Laravel Cashier (Stripe) development for subscription billing, payment processing, and Stripe integration in Laravel applications.
This skill should be triggered when:
bash# Install Cashier composer require laravel/cashier # Publish migrations and migrate php artisan vendor:publish --tag="cashier-migrations" php artisan migrate # Publish config (optional) php artisan vendor:publish --tag="cashier-config"
phpuse Laravel\Cashier\Billable; class User extends Authenticatable { use Billable; }
php// Basic subscription with trial and checkout $user->newSubscription('default', 'price_monthly') ->trialDays(5) ->allowPromotionCodes() ->checkout([ 'success_url' => route('checkout.success'), 'cancel_url' => route('checkout.cancel'), ]);
php// Check if user has active subscription if ($user->subscribed('default')) { // User is subscribed to "default" plan } // Check specific product subscription if ($user->subscribedToProduct('prod_premium', 'default')) { // User is subscribed to premium product } // Check trial status if ($user->subscription('default')->onTrial()) { // User is still in trial period }
php// Store payment method (in view with Stripe.js) $intent = $user->createSetupIntent(); // Retrieve payment methods $paymentMethods = $user->paymentMethods(); $defaultMethod = $user->defaultPaymentMethod(); // Add and update payment methods $user->addPaymentMethod($paymentMethodId); $user->updateDefaultPaymentMethod($paymentMethodId);
php// Swap to different price/plan $user->subscription('default')->swap('price_yearly'); // Swap and skip trial $user->subscription('default')->skipTrial()->swap('price_yearly');
php// One-time charge $user->charge(1000, $paymentMethodId, [ 'description' => 'One-time charge', ]); // Create invoice for service $user->invoiceFor('Premium Support', 5000, [ 'description' => '3 months of premium support', ]); // Refund a charge $user->refund($chargeId);
php// Cancel immediately $user->subscription('default')->cancel(); // Cancel at end of billing period $user->subscription('default')->cancelAtEndOfBillingPeriod(); // Resume canceled subscription if ($user->subscription('default')->onGracePeriod()) { $user->subscription('default')->resume(); }
php// Get all invoices $invoices = $user->invoices(); // Get upcoming invoice $upcomingInvoice = $user->upcomingInvoice('default'); // Download invoice PDF return $user->invoices()->first()->download();
php// Redirect to Stripe billing portal Route::get('/billing', function (Request $request) { return $request->user() ->redirectToBillingPortal(route('dashboard')); })->middleware(['auth']);
php// Create/get Stripe customer $stripeCustomer = $user->createOrGetStripeCustomer(); // Update customer details $user->updateStripeCustomer([ 'name' => 'Updated Name', 'email' => 'updated@example.com', ]); // Manage tax IDs $taxId = $user->createTaxId('eu_vat', 'BE0123456789'); $user->deleteTaxId('txi_belgium');
The Billable trait adds subscription and payment functionality to your Eloquent models (typically User). It provides methods for creating subscriptions, processing charges, managing payment methods, and accessing invoices.
Cashier manages recurring billing through subscriptions. Each subscription has:
Stripe payment methods represent stored payment credentials (cards, bank accounts). Cashier provides helpers to:
Stripe sends webhook events for subscription changes, payment failures, invoice updates, etc. Cashier automatically handles common webhooks, but you can extend functionality by listening to specific events.
Stripe Checkout provides a pre-built payment page. Cashier simplifies creating checkout sessions for subscriptions and one-time products, handling the complete payment flow with minimal code.
Cashier provides access to Stripe invoices for both subscriptions and one-time charges. You can retrieve, preview, and download invoices as PDFs.
This skill includes comprehensive documentation in references/:
Use view to read the reference file when you need detailed information about specific features.
Start by:
Billable trait to your User modelnewSubscription()Basic workflow:
php// 1. Configure model use Laravel\Cashier\Billable; class User extends Authenticatable { use Billable; } // 2. Create subscription $user->newSubscription('default', 'price_monthly')->create(); // 3. Check status if ($user->subscribed('default')) { // Grant access }
Focus on:
Explore:
references/other.md for complete implementation detailsRequired environment variables in .env:
envSTRIPE_KEY=pk_test_your_stripe_publishable_key STRIPE_SECRET=sk_test_your_stripe_secret_key STRIPE_WEBHOOK_SECRET=whsec_your_webhook_signing_secret CASHIER_CURRENCY=usd
Important: Use test mode keys (pk_test_, sk_test_) during development and switch to live keys (pk_live_, sk_live_) for production.
php// 1. Create checkout session public function subscribe(Request $request) { return $request->user() ->newSubscription('default', 'price_monthly') ->trialDays(14) ->allowPromotionCodes() ->checkout([ 'success_url' => route('checkout.success') . '?session_id={CHECKOUT_SESSION_ID}', 'cancel_url' => route('checkout.cancel'), ]); } // 2. Handle success public function success(Request $request) { $sessionId = $request->get('session_id'); if ($request->user()->subscribed('default')) { return redirect()->route('dashboard') ->with('success', 'Subscription activated!'); } }
php// Upgrade to annual plan with prorated credit public function upgrade(Request $request) { $subscription = $request->user()->subscription('default'); if ($subscription->active()) { $subscription->swap('price_yearly'); return back()->with('success', 'Upgraded to annual plan!'); } }
php// Controller: Generate setup intent public function paymentMethods(Request $request) { return view('billing.payment-methods', [ 'intent' => $request->user()->createSetupIntent(), 'paymentMethods' => $request->user()->paymentMethods(), ]); } // View: Stripe.js integration (Blade) <form id="payment-form" method="POST" action="{{ route('payment-method.add') }}"> @csrf <div id="card-element"></div> <button type="submit">Add Payment Method</button> </form> // Controller: Store payment method public function addPaymentMethod(Request $request) { $request->user()->addPaymentMethod($request->payment_method); return back()->with('success', 'Payment method added!'); }
Use Stripe test card numbers for development:
4242 4242 4242 42424000 0000 0000 00024000 0025 0000 3155Always use test mode API keys during development and testing.
This skill is based on Laravel Cashier for Laravel 12.x. For the latest information, refer to the official documentation at https://laravel.com/docs/billing.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-21 | pass→pass | 18,375 | 13,931 | -24% | 1 | 1 | 0% | 3,310 | 5,309 | +60% | 0 | 0 | — |
case-01 | pass→pass | 3,100 | 2,725 | -12% | 1 | 1 | 0% | 534 | 3,177 | +495% | 0 | 0 | — |
case-02 | pass→pass | 3,326 | 2,479 | -25% | 1 | 1 | 0% | 589 | 3,074 | +422% | 0 | 0 | — |
case-03 | pass→pass | 8,666 | 5,726 | -34% | 1 | 1 | 0% | 1,604 | 3,717 | +132% | 0 | 0 | — |
case-04 | pass→pass | 6,977 | 4,475 | -36% | 1 | 1 | 0% | 1,094 | 3,429 | +213% | 0 | 0 | — |
case-05 | pass→pass | 2,833 | 4,354 | +54% | 1 | 1 | 0% | 435 | 3,434 | +689% | 0 | 0 | — |
case-06 | pass→pass | 11,261 | 4,744 | -58% | 1 | 1 | 0% | 1,865 | 3,501 | +88% | 0 | 0 | — |
case-07 | pass→pass | 5,884 | 4,598 | -22% | 1 | 1 | 0% | 1,039 | 3,435 | +231% | 0 | 0 | — |
case-08 | fail→fail | 11,698 | 15,296 | +31% | 1 | 1 | 0% | 1,430 | 4,709 | +229% | 0 | 0 | — |
case-09 | fail→pass | 12,687 | 4,157 | -67% | 1 | 1 | 0% | 2,120 | 3,305 | +56% | 0 | 0 | — |
case-10 | pass→pass | 5,776 | 5,742 | -1% | 1 | 1 | 0% | 919 | 3,618 | +294% | 0 | 0 | — |
case-11 | pass→pass | 3,734 | 3,797 | +2% | 1 | 1 | 0% | 630 | 3,351 | +432% | 0 | 0 | — |
case-12 | pass→pass | 5,643 | 3,942 | -30% | 1 | 1 | 0% | 922 | 3,313 | +259% | 0 | 0 | — |
case-13 | pass→pass | 4,282 | 4,179 | -2% | 1 | 1 | 0% | 721 | 3,330 | +362% | 0 | 0 | — |
case-14 | pass→pass | 4,929 | 4,514 | -8% | 1 | 1 | 0% | 778 | 3,490 | +349% | 0 | 0 | — |
case-15 | pass→pass | 9,153 | 5,645 | -38% | 1 | 1 | 0% | 1,583 | 3,710 | +134% | 0 | 0 | — |
case-16 | pass→pass | 6,760 | 3,286 | -51% | 1 | 1 | 0% | 1,245 | 3,296 | +165% | 0 | 0 | — |
case-17 | pass→pass | 3,047 | 2,085 | -32% | 1 | 1 | 0% | 438 | 2,931 | +569% | 0 | 0 | — |
case-18 | pass→pass | 4,712 | 3,861 | -18% | 1 | 1 | 0% | 727 | 3,227 | +344% | 0 | 0 | — |
case-19 | fail→pass | 11,343 | 24,979 | +120% | 1 | 1 | 0% | 1,596 | 3,834 | +140% | 0 | 0 | — |
case-20 | pass→pass | 13,062 | 13,716 | +5% | 1 | 1 | 0% | 2,584 | 5,343 | +107% | 0 | 0 | — |
case-22 | pass→pass | 4,676 | 4,474 | -4% | 1 | 1 | 0% | 831 | 3,508 | +322% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +9 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.