Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Stripe Bundle Laravel Package

fpt/stripe-bundle

A Symfony bundle for integrating Stripe payments into PHP applications, with configuration for API keys, services for charges and webhooks, and helpers for checkout, subscriptions, and payment flows. Simplifies adding Stripe support to Symfony projects.

View on GitHub
Deep Wiki
Context7

Getting Started

First, calibrate expectations: this is not a Laravel package. fpt/stripe-bundle is a Symfony bundle (FabienPapet, MIT, ~14 stars, last release Oct 2024). There is no ServiceProvider, no config/stripe.php auto-merge, no facade, no publishable assets. A Laravel developer cannot composer require it and expect it to boot. Treat it as either (a) a reference implementation to read, or (b) something you swap for a thin Laravel wrapper around the same underlying SDK.

The bundle itself is a thin DI/config layer over stripe/stripe-php. That is the important fact: the hard part (Stripe's API) is identical in Laravel and Symfony. Only the wiring differs.

Day-one path for a Laravel developer:

  1. composer require stripe/stripe-php in your Laravel app — the bundle adds convenience, not capability.
  2. Read the bundle's src/ to crib three things: the config shape (keys, webhook secret, API version pin), how it registers a StripeClient-style service, and how it verifies webhook signatures.
  3. In Laravel, bind a singleton in AppServiceProvider:
$this->app->singleton(\Stripe\StripeClient::class, fn () => new \Stripe\StripeClient([
    'api_key'        => config('services.stripe.secret'),
    'stripe_version' => '2024-06-20',
]));
  1. Add STRIPE_KEY, STRIPE_SECRET, STRIPE_WEBHOOK_SECRET to .env and config/services.php.

First use case: a Checkout Session or PaymentIntent created from a controller, and a webhook endpoint that verifies the signature. Those two flows cover ~80% of what teams actually ship, and both map cleanly from the bundle's Symfony controllers/subscribers to Laravel controllers/listeners.

Implementation Patterns

Webhooks are the load-bearing wall. The bundle's main value is demonstrating signature verification and event dispatch as framework-native constructs. In Laravel the translation is:

Route::post('/stripe/webhook', StripeWebhookController::class)
    ->withoutMiddleware([VerifyCsrfToken::class]);

// controller
$event = \Stripe\Webhook::constructEvent(
    $request->getContent(),                 // raw body, not $request->all()
    $request->header('Stripe-Signature'),
    config('services.stripe.webhook_secret')
);

Then switch on $event->type — or, better, map to Laravel events (PaymentSucceeded, SubscriptionDeleted) and register listeners, mirroring the bundle's Symfony event subscribers. This keeps Stripe's wire format out of your domain code.

Service-layer pattern. The bundle injects Stripe services into application services via Symfony DI. The Laravel analogue is constructor injection of the singleton plus an idempotency key on every mutating call:

$stripe->paymentIntents->create($params, [
    'idempotency_key' => "order-{$order->id}-attempt-{$order->attempts}",
]);

Configuration parity. Symfony bundles use config/packages/stripe.yaml; Laravel uses config/services.php + .env. Whatever keys the bundle supports (public_key, secret_key, webhook_secret, endpoints, API version), reproduce them as env-driven config so test/live switching is a deploy concern, not a code concern.

Entity/model mapping, if you use its Doctrine side. If the bundle ships entities for customers/subscriptions, don't port them literally. In Laravel you want a stripe_customers table keyed by user_id + stripe_id, and a subscriptions table that mirrors only the fields you query on. Stripe remains the source of truth; your DB is a projection rebuilt from webhooks.

Test both sides. Use Stripe\StripeClient against test-mode keys, and stripe listen --forward-to localhost:8000/stripe/webhook locally. Mirror the bundle's own test approach (it almost certainly mocks the client or uses Stripe's test fixtures) so you can assert your listeners without hitting the network.

Integration tip: put the Stripe client behind a small port interface (PaymentGateway) implemented with the SDK. When the bundle's abstractions change — or when you eventually swap to Laravel Cashier — only the adapter changes.

Gotchas and Tips

  • Package identity mismatch. Do not add fpt/stripe-bundle to a Laravel composer.json hoping autodiscovery does something. Symfony bundles require config/bundles.php registration and a kernel. php artisan will not help you. If you truly need it, run it in a Symfony sidecar service and talk over HTTP — but for most teams, that's overkill versus stripe/stripe-php.
  • Raw body for webhooks. Laravel's $request->all() or any middleware that re-encodes the payload will break signature verification. Read getContent() and keep JSON-parsing middleware off that route.
  • CSRF and webhook routes. Exclude the webhook URI from VerifyCsrfToken, or the POST dies with a 419 before your code runs.
  • API version pinning. The bundle likely accepts a pinned api_version. Pin the same version in your SDK config — Stripe changes object shapes between versions, and un-pinned clients drift.
  • Idempotency is not optional. Retries and duplicate webhook deliveries are normal. Store processed event->id values (a webhook_events table with a unique index) and short-circuit on repeats.
  • Maintenance and ecosystem. 14 stars, zero dependents, one release in 2024. It's a small bundle with no community buffer — pin exact versions, read changelogs on bumps, and don't expect answers to issues quickly. That alone argues against making it load-bearing in production.
  • Debugging. Log the raw Stripe-Signature header and event id/type at the top of your handler. When verification fails, the exception message is generic; comparing the timestamp (Stripe-Signature t= value) against server clock drift catches most of them.
  • Extension points. Because it's thin, the useful extension is not subclassing the bundle but wrapping your own service around the SDK. That gives you the same ergonomics without inheriting a low-traffic dependency — the pragmatic conclusion for a Laravel team evaluating this package.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core