gusmanwidodo/laravel-billing-stripe

Stripe payment provider for gusmanwidodo/laravel-billing. Implements the PaymentProvider contract: Checkout Session charge, Stripe-Signature webhook verification, event mapping, and refund.

Maintainers

Package info

github.com/gusmanwidodo/laravel-billing-stripe

pkg:composer/gusmanwidodo/laravel-billing-stripe

Transparency log

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-08-26 13:27 UTC

This package is auto-updated.

Last update: 2026-08-26 13:30:55 UTC


README

Stripe payment provider for gusmanwidodo/laravel-billing. Implements the billing PaymentProvider contract using Stripe Checkout, so you can charge invoices via a hosted Checkout page and settle them from verified webhooks.

Tests License: MIT

Features

  • Checkout charge — creates a Checkout Session and returns its hosted URL.
  • Webhook verification — validates the Stripe-Signature header (t=<ts>,v1=<HMAC-SHA256(ts + "." + payload, whsec)>) with a timestamp tolerance to reject replays.
  • Event mappingcheckout.session.completed(paid) / payment_intent.succeeded → succeeded, expired → canceled, payment_failed → failed, charge.refunded → refunded.
  • Refund — creates a refund for the session's payment intent.
  • Auto-registers itself into laravel-billing's provider registry.

Requirements

  • PHP ^8.3
  • gusmanwidodo/laravel-billing ^0.4
  • Laravel 12
  • A Stripe account (secret key + webhook signing secret)

Installation

composer require gusmanwidodo/laravel-billing-stripe
php artisan vendor:publish --tag=billing-stripe-config
STRIPE_SECRET_KEY=sk_live_or_test
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_SUCCESS_URL=https://your-app.test/billing/success
STRIPE_CANCEL_URL=https://your-app.test/billing/cancel
STRIPE_AS_DEFAULT=false

Usage

use Gusmanwidodo\Billing\Facades\Billing;

// 1. Charge an invoice via Stripe Checkout -> pending intent with the hosted URL.
$intent = Billing::charge($invoice, provider: 'stripe');
return redirect($intent->meta['redirect_url']);   // Stripe Checkout page

// 2. Stripe webhook route — pass the RAW body + headers; the signature is verified.
Route::post('/webhooks/stripe', function (Illuminate\Http\Request $request) {
    try {
        Billing::handleWebhook('stripe', $request->getContent(), $request->headers->all());
    } catch (\RuntimeException $e) {
        abort(403); // signature verification failed
    }
    return response('', 200);
});

// 3. Refund a succeeded intent.
Billing::refund($intent);

On a verified checkout.session.completed (payment_status paid) event, a real Payment is recorded and the invoice becomes paid. Settlement is idempotent, keyed by the Checkout Session id (the intent's external_id).

Amounts

Stripe's unit_amount is the smallest currency unit (cents) — the same as laravel-billing's integer minor units — so amounts pass through directly, no conversion needed.

Security

Signature verification is mandatory and includes replay protection: Billing::handleWebhook('stripe', ...) throws if the HMAC-SHA256 signature does not match or the timestamp is outside signature_tolerance (default 300s), so a forged, tampered, or replayed notification never records a payment.

Testing

composer test   # 12 tests, all HTTP mocked via Http::fake (no real API key needed)

License

MIT © Gusman Widodo. See LICENSE.