prometee/payum-stripe-checkout-session-bundle
A Symfony bundle that integrates Stripe Checkout Session with Payum, letting you accept card payments through Stripe's hosted checkout. It provides a ready-to-use payment gateway and simplifies wiring Stripe Checkout into Payum-based applications.
Install the bundle and register it:
composer require prometee/payum-stripe-checkout-session-bundle
// config/bundles.php
return [
// ...
Prometee\PayumStripeCheckoutSessionBundle\PayumStripeCheckoutSessionBundle::class => ['all' => true],
];
Set the Stripe credentials in .env:
STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
Configure a Payum gateway with the factory provided by the bundle. In Sylius this is usually done by creating a Payment Method in the admin UI and selecting the Stripe Checkout Session gateway factory; the equivalent fixture/config looks like:
# config/packages/_sylius.yaml or a fixtures file
sylius_payment:
gateways:
stripe_checkout_session:
factory: stripe_checkout_session
publishable_key: '%env(STRIPE_PUBLISHABLE_KEY)%'
secret_key: '%env(STRIPE_SECRET_KEY)%'
Look first at:
DependencyInjection/ and Resources/config/ files to see which Payum gateway factory, actions, and API services are registered;StripeCheckoutSessionGatewayFactory) and its createConfig() / create() methods;CaptureAction, NotifyAction, SyncAction, and StatusAction — these define the actual payment lifecycle;notify route.The first use case is a standard redirect checkout: capture a Sylius order payment, create a Stripe Checkout Session, redirect the customer to Stripe, then complete the order on return or via webhook.
use Payum\Core\Request\Capture;
use Payum\Core\Request\GetHumanStatus;
$gateway = $this->get('payum')->getGateway('stripe_checkout_session');
$gateway->execute($capture = new Capture($payment));
$status = new GetHumanStatus($payment);
$gateway->execute($status);
Sylius admin configuration. The day-to-day path is: create a Payment Method, choose the Stripe Checkout Session factory, enter publishable/secret keys, and assign it to a shipping/payment method. Keep one gateway per store/currency if you have multi-store pricing.
Capture → redirect → reconcile. CaptureAction builds the Stripe Checkout Session from the Payum Payment amount and currency, stores the session identifier in $payment->getDetails(), and returns a redirect. After the user returns, do not trust the query string alone: execute Sync and GetHumanStatus against the stored session before transitioning the Sylius order.
$gateway->execute(new Sync($payment));
$status = new GetHumanStatus($payment);
$gateway->execute($status);
if ($status->isCaptured()) {
// transition the Sylius order/payment state machine
}
Webhook/notify handling. Configure Stripe to send checkout.session.completed and, if you support delayed methods, checkout.session.async_payment_succeeded to the Payum notify URL for the payment. NotifyAction verifies the Stripe-Signature header, retrieves the Checkout Session, writes the payment intent/session details, and marks the payment captured. Webhook handling is what makes the flow reliable when the customer closes the browser after paying.
stripe listen --forward-to https://your-app.test/payment/notify
Customize the session. Extend or replace CaptureAction when you need metadata (order number, customer id), customer_email, line_items, allow_promotion_codes, or a custom success_url/cancel_url. Keep the amount/currency calculation in one place and pass it through the Payum request details so both capture and webhook paths agree.
Multiple actions and gateways. Register a custom gateway factory or override the action services if you need different behavior per channel (e.g. B2B vs B2C, different capture modes). Payum’s ActionInterface + ApiAwareInterface pattern means any custom action must receive the Stripe API service via setApi().
Testing. Use Stripe test keys and the Stripe CLI for webhook forwarding. For unit tests, mock the Stripe API client and assert that CaptureAction stores the session id and that StatusAction maps Stripe session statuses (open, complete, expired) to Payum statuses. Use Stripe test cards for end-to-end tests.
Order state machine integration. In Sylius, hook the payment transition (sylius_order_payment / complete) so the order becomes paid only after GetHumanStatus::STATUS_CAPTURED. Avoid completing orders directly in the controller; route all state changes through the state machine.
success_url without a completed payment, or close the tab after paying. Always reconcile with Sync/Status and rely on the webhook for finality.whsec_ secret. Reverse proxies, body parsers, or Symfony listeners that alter the request can break signature checks. Ensure the notify route is public, POST-only, and excluded from CSRF.checkout.session.completed events by checking the current payment status and using an idempotency key when creating sessions.{CHECKOUT_SESSION_ID} in success_url; otherwise you must rely on the stored payment token.complete + payment_status=paid to captured; expired/unpaid should stay pending or failed. Customize StatusAction if your business rules differ.composer why-not against your Symfony, Payum, Sylius, and stripe/stripe-php versions. Pin versions in production and run the test suite after upgrades.sk_ keys or full webhook payloads containing customer data. Keep test and live keys in separate environments and rotate webhook secrets when endpoints change.bin/console cache:clear) and verify the compiled Payum gateway config. Sylius can cache payment method gateway config in the database, so admin changes may need a cache warmup.localhost; use the Stripe CLI or a tunnel. If webhooks fail locally, payments may still succeed at Stripe while your order remains unpaid until manually reconciled.How can I help you explore Laravel packages today?