spryker-eco / stripe
Stripe module
Requires
- php: >=8.3
- spryker/acl-merchant-portal-extension: ^1.0.0
- spryker/application: ^3.46.0
- spryker/cart: ^7.16.0
- spryker/checkout-extension: ^1.5.0
- spryker/configuration-extension: ^1.0.0
- spryker/installer-extension: ^1.0.0
- spryker/kernel: ^3.84.0
- spryker/log: ^3.0.0
- spryker/merchant-app: ^1.5.0
- spryker/merchant-user: ^1.0.0
- spryker/payment-app: ^2.4.0
- spryker/payment-extension: ^1.1.0
- spryker/refund: ^5.0.0
- spryker/sales: ^11.78.0
- spryker/sales-payment-detail: ^1.5.0
- spryker/sales-payment-merchant-extension: ^1.1.0
- spryker/step-engine: ^3.7.0
- spryker/symfony: ^3.19.0
- spryker/util-encoding: ^2.0.0
- spryker/zed-request: ^3.26.0
- stripe/stripe-php: ^v13.0.0
Requires (Dev)
Suggests
- spryker-shop/checkout-page: When the project uses Yves and built-in module payment page.
- spryker-shop/checkout-widget: When the project uses Yves and built-in module payment page.
- spryker/merchant-sales-merchant-commission: Required for commission-aware merchant payouts.
- spryker/merchant-sales-order: Required when project have marketplace merchant orders and OMS uses StripeManualMarketplace01.xml.
- spryker/oms: When OMS plugins are used.
- spryker/router: When Yves router plugins are used.
This package is auto-updated.
Last update: 2026-04-20 12:10:39 UTC
README
Integration
Step 1: Install the package
composer require spryker-eco/stripe
Step 2: Remove old ACP MessageBroker plugins (if any)
File: src/Pyz/Zed/MessageBroker/MessageBrokerDependencyProvider.php
Remove these imports and their instantiations from getMessageHandlerPlugins():
// Remove these use statements: use Spryker\Zed\Payment\Communication\Plugin\MessageBroker\PaymentMethodMessageHandlerPlugin; use Spryker\Zed\Payment\Communication\Plugin\MessageBroker\PaymentOperationsMessageHandlerPlugin; use Spryker\Zed\PaymentApp\Communication\Plugin\MessageBroker\PaymentAppOperationsMessageHandlerPlugin; use Spryker\Zed\SalesPaymentDetail\Communication\Plugin\MessageBroker\SalesPaymentDetailMessageHandlerPlugin; use Spryker\Zed\MerchantApp\Communication\Plugin\MessageBroker\MerchantAppOnboardingMessageHandlerPlugin;
Step 3: Update OMS configuration
File: config/Shared/config_default.php
Add the Stripe OMS process location and activate the state machine:
$config[OmsConstants::PROCESS_LOCATION] = [ OmsConfig::DEFAULT_PROCESS_LOCATION, APPLICATION_ROOT_DIR . '/vendor/spryker-eco/stripe/config/Zed/oms', // Add this line ]; $config[OmsConstants::ACTIVE_PROCESSES] = [ // Replace ForeignPaymentStateMachine01 and ForeignPaymentB2CStateMachine01 with the Stripe process 'StripeManual01', // or StripeManualMarketplace01 for marketplace projects ]; $config[SalesConstants::PAYMENT_METHOD_STATEMACHINE_MAPPING] = [ \SprykerEco\Shared\Stripe\StripeConfig::PAYMENT_PROVIDER_NAME => 'StripeManual01', // or StripeManualMarketplace01 for marketplace projects ];
Step 4: Register Stripe OMS command and condition plugins
File: src/Pyz/Zed/Oms/OmsDependencyProvider.php
Add Stripe command plugins to extendCommandPlugins():
use SprykerEco\Zed\Stripe\Communication\Plugin\Oms\Command\StripeCancelCommandPlugin; use SprykerEco\Zed\Stripe\Communication\Plugin\Oms\Command\StripeCaptureCommandPlugin; use SprykerEco\Zed\Stripe\Communication\Plugin\Oms\Command\StripeRefundCommandPlugin; // In extendCommandPlugins(): $commandCollection->add(new StripeCaptureCommandPlugin(), 'Stripe/Capture'); $commandCollection->add(new StripeRefundCommandPlugin(), 'Stripe/Refund'); $commandCollection->add(new StripeCancelCommandPlugin(), 'Stripe/Cancel'); // ----- for Marketplace only $commandCollection->add(new MerchantPayoutCommandByOrderPlugin(), 'SalesPaymentMerchant/Payout'); $commandCollection->add(new MerchantPayoutReverseCommandByOrderPlugin(), 'SalesPaymentMerchant/ReversePayout');
Note:
StripeCaptureCommandPluginalways captures the full authorized amount regardless of which items are in the OMS batch. Stripe allows only one capture per PaymentIntent — any remaining uncaptured amount is automatically released after the first capture. Items canceled after capture are handled via refunds.
Also add payment conditions to extendConditionPlugins():
// In extendConditionPlugins(): $conditionCollection->add(new IsPaymentAppPaymentStatusAuthorizationFailedConditionPlugin(), 'Payment/IsAuthorizationFailed'); $conditionCollection->add(new IsPaymentAppPaymentStatusAuthorizedConditionPlugin(), 'Payment/IsAuthorized'); $conditionCollection->add(new IsPaymentAppPaymentStatusCanceledConditionPlugin(), 'Payment/IsCanceled'); $conditionCollection->add(new IsPaymentAppPaymentStatusCancellationFailedConditionPlugin(), 'Payment/IsCancellationFailed'); $conditionCollection->add(new IsPaymentAppPaymentStatusCapturedConditionPlugin(), 'Payment/IsCaptured'); $conditionCollection->add(new IsPaymentAppPaymentStatusCaptureFailedConditionPlugin(), 'Payment/IsCaptureFailed'); $conditionCollection->add(new IsPaymentAppPaymentStatusCaptureRequestedConditionPlugin(), 'Payment/IsCaptureRequested'); $conditionCollection->add(new IsPaymentAppPaymentStatusOverpaidConditionPlugin(), 'Payment/IsOverpaid'); $conditionCollection->add(new IsPaymentAppPaymentStatusUnderpaidConditionPlugin(), 'Payment/IsUnderpaid'); $conditionCollection->add(new IsPaymentAppPaymentStatusRefundedConditionPlugin(), 'Payment/IsRefunded'); $conditionCollection->add(new IsPaymentAppPaymentStatusRefundFailedConditionPlugin(), 'Payment/IsRefundFailed'); // ------- for Marketplace only $conditionCollection->add(new IsMerchantPaidOutConditionPlugin(), 'SalesPaymentMerchant/IsMerchantPaidOut'); $conditionCollection->add(new IsMerchantPayoutReversedConditionPlugin(), 'SalesPaymentMerchant/IsMerchantPayoutReversed');
Step 5: Register the Stripe payout transmission plugin (marketplace only)
File: src/Pyz/Zed/SalesPaymentMerchant/SalesPaymentMerchantDependencyProvider.php
Register StripePayoutTransmissionPlugin so the SalesPaymentMerchant module routes merchant payouts and payout reversals through direct Stripe Connect API calls:
use SprykerEco\Zed\Stripe\Communication\Plugin\SalesPaymentMerchant\StripePayoutTransmissionPlugin; // In getMerchantPayoutTransmissionPlugins(): return [ new StripePayoutTransmissionPlugin(), ];
The OMS subprocesses StripeMerchantPayout01.xml and StripeMerchantPayoutReverse01.xml use the generic SalesPaymentMerchant/Payout and SalesPaymentMerchant/ReversePayout commands.
StripePayoutTransmissionPlugin intercepts those commands and executes Stripe Connect transfers (forward payouts) or transfer reversals (payout reversals) directly via the Stripe API.
Step 6: Register Stripe checkout post-save plugin
File: src/Pyz/Zed/Checkout/CheckoutDependencyProvider.php
use SprykerEco\Zed\Stripe\Communication\Plugin\Checkout\StripeCheckoutPostSavePlugin; // In getCheckoutPostHooks(): new StripeCheckoutPostSavePlugin(),
Step 7: Register Stripe Yves checkout plugins
File: src/Pyz/Yves/CheckoutPage/CheckoutPageDependencyProvider.php
use SprykerEco\Shared\Stripe\StripeConfig as SharedStripeConfig; use SprykerEco\Yves\Stripe\Plugin\StepEngine\StripeStepHandlerPlugin; use SprykerEco\Yves\Stripe\Plugin\StepEngine\StripeSubFormPlugin; // In extendPaymentMethodHandler(): $paymentMethodHandler->add(new StripeStepHandlerPlugin(), SharedStripeConfig::PAYMENT_METHOD_NAME); // In extendSubFormPluginCollection(): $paymentSubFormPluginCollection->add(new StripeSubFormPlugin());
Step 8: Register payment method filter plugin (optional)
Only required if you need custom filtering logic, for example, to hide Stripe or other payment methods based on the Quote. Extend StripePaymentMethodFilterPlugin with your filtering logic.
File: src/Pyz/Zed/Payment/PaymentDependencyProvider.php
use SprykerEco\Zed\Stripe\Communication\Plugin\Payment\StripePaymentMethodFilterPlugin; // In getPaymentMethodFilterPlugins(): new StripePaymentMethodFilterPlugin(),
Step 9: Register Stripe routes
File: src/Pyz/Yves/Router/RouterDependencyProvider.php
use SprykerEco\Yves\Stripe\Plugin\Router\StripeRouteProviderPlugin; // In getRouteProvider(): new StripeRouteProviderPlugin(),
Step 10: Add Stripe payment form to the checkout payment template
File: src/Pyz/Yves/CheckoutPage/Theme/default/views/payment/payment.twig
Add the Stripe form entry to the customForms map:
{% define data = {
customForms: {
'Payone/credit_card': ['credit-card', 'payone'],
'Stripe/stripe': ['stripe'],
},
} %}
Step 11: Register the marketplace installer plugin (marketplace only)
File: src/Pyz/Zed/Installer/InstallerDependencyProvider.php
use SprykerEco\Zed\Stripe\Communication\Plugin\Installer\StripeMarketplaceInstallerPlugin; // In getInstallerPlugins(): new StripeMarketplaceInstallerPlugin(),
Step 12: Allow Stripe controllers in the Merchant Portal security config (marketplace only)
By default, Merchant Portal rejects all routes that do not match the portal pattern. The /stripe/* endpoint must be excluded from authentication.
File: src/Pyz/Zed/SecurityMerchantPortalGui/SecurityMerchantPortalGuiConfig.php
<?php namespace Pyz\Zed\SecurityMerchantPortalGui; use Spryker\Zed\SecurityMerchantPortalGui\SecurityMerchantPortalGuiConfig as SprykerSecurityMerchantPortalGuiConfig; class SecurityMerchantPortalGuiConfig extends SprykerSecurityMerchantPortalGuiConfig { protected const MERCHANT_PORTAL_ROUTE_PATTERN = '^/((.+)-merchant-portal-gui|multi-factor-auth-merchant-portal/(merchant-user|user-management)|_profiler|stripe)/'; protected const IGNORABLE_PATH_PATTERN = '^/(security-merchant-portal-gui|multi-factor-auth-merchant-portal|_profiler|stripe)'; }
Step 13: Configure Stripe credentials
Option A: Environment variable-based credentials
Set the values in your config file.
File: config/Shared/config_local.php
use SprykerEco\Shared\Stripe\StripeConstants; $config[StripeConstants::STRIPE_SECRET_KEY] = 'sk_live_***'; // from Stripe Dashboard → API keys $config[StripeConstants::STRIPE_PUBLISHABLE_KEY] = 'pk_live_***'; // from Stripe Dashboard → API keys $config[StripeConstants::STRIPE_WEBHOOK_SECRET] = 'whsec_***'; // from Stripe Dashboard → Webhooks → standard endpoint $config[StripeConstants::STRIPE_WEBHOOK_SECRET_CONNECT] = 'whsec_***'; // from Stripe Dashboard → Webhooks → Connect endpoint (marketplace only)
Option B: Back Office configuration
Requires the Spryker Configuration feature to be installed.
Once installed, activate it for this module by creating src/Pyz/Shared/Stripe/StripeConfig.php:
namespace Pyz\Shared\Stripe; use SprykerEco\Shared\Stripe\StripeConfig as SprykerEcoStripeConfig; class StripeConfig extends SprykerEcoStripeConfig { public function isConfigurationModuleUsed(): bool { return true; } }
Run the following command to sync the configuration settings to the database. This registers the Stripe configuration keys used by the Back Office:
vendor/bin/console configuration:sync
Configure Stripe credentials in the Back Office under Configuration > Integrations > Stripe. Enter the Secret Key, Publishable Key, and Webhook Secret. Webhook Secret (Connect) is optional and used only for marketplace.
To enable credential validation on save, register StripeCredentialsPreSavePlugin in src/Pyz/Zed/Configuration/ConfigurationDependencyProvider.php:
use \SprykerEco\Zed\Stripe\Communication\Plugin\Configuration\StripeCredentialsPreSavePlugin; protected function getConfigurationValuePreSavePlugins(): array { return [ new StripeCredentialsPreSavePlugin(), ]; }
Step 14: Import payment methods
The module provides pre-configured data import files for payment methods, store assignments, and translations.
Option 1: Import using the module's configuration file
Recommended during the development phase.
docker/sdk cli vendor/bin/console data:import --config=vendor/spryker-eco/stripe/data/import/stripe.yml
Option 2: Copy files and import individually
Recommended once the integration is tested and tuned.
Copy the file contents from vendor/spryker-eco/stripe/data/import/*.csv to the matching files in your project under data/import/common/common/. Then run:
docker/sdk cli vendor/bin/console data:import payment-method vendor/bin/console data:import payment-method-store vendor/bin/console data:import glossary
Customize payment methods
Before importing, you can customize the payment method data:
File: vendor/spryker-eco/stripe/data/import/payment_method.csv
- Update payment method names
- Enable/disable methods
- Add additional payment methods
File: vendor/spryker-eco/stripe/data/import/payment_method_store.csv
- Configure which stores each payment method is available in
File: vendor/spryker-eco/stripe/data/import/glossary.csv
- Customize translations for payment method names
- Add additional locales
Verify import
Check the Back Office:
- Go to Administration → Payment → Payment Methods
- Verify payment methods appear with correct names and provider
- Verify methods are assigned to the correct stores
- Go to Administration → Glossary and verify translations
- Enable the method for the store and validate the Storefront checkout payment step
Step 15: Run code generation and database migration
# Apply database schema changes (spy_stripe_payment, spy_stripe_merchant) vendor/bin/console propel:install # Generate new transfer objects vendor/bin/console transfer:generate # Run marketplace installer vendor/bin/console setup:init-db # Run marketplace ACL updater vendor/bin/console acl-entity:synchronize
Step 16: Register the Stripe webhook in the Stripe Dashboard
Both endpoints point to the same URL but are registered separately in the Stripe Dashboard — Stripe issues a different signing secret for each.
Standard endpoint
Go to Stripe Dashboard → Developers → Webhooks → Add endpoint and set:
https://your-domain.com/stripe/notification
Select these event types:
| Event | Triggered OMS status |
|---|---|
payment_intent.amount_capturable_updated |
Authorized |
payment_intent.succeeded |
Captured / Partially captured |
payment_intent.payment_failed |
Capture failed |
payment_intent.canceled |
Canceled |
charge.failed |
Capture failed (post-capture) |
charge.refunded |
Refunded / Partially refunded |
charge.refund.updated |
Refund failed |
Copy the Signing secret and set it as STRIPE_WEBHOOK_SECRET in your config.
Connect endpoint (marketplace only)
Go to Stripe Dashboard → Developers → Webhooks → Add endpoint and set the same URL:
https://your-domain.com/stripe/notification
Enable Listen to events on connected accounts and select these event types:
| Event | Purpose |
|---|---|
account.updated |
Updates merchant onboarding status in Merchant Portal |
account.application.authorized |
Merchant granted access to the platform (accepted silently) |
capability.updated |
Stripe capability change on a connected account (accepted silently) |
person.created |
Person added to a connected account (accepted silently) |
person.updated |
Person details updated on a connected account (accepted silently) |
account.external_account.created |
Bank account added to a connected account (accepted silently) |
"Accepted silently" means the handler returns HTTP 200 without writing any status — the events are acknowledged so Stripe does not retry them.
Copy the Signing secret and set it as STRIPE_WEBHOOK_SECRET_CONNECT in your config.
The handler tries the standard secret first. If verification fails, it automatically falls back to the Connect secret. This lets both standard and Connect events share a single URL.
Debugging: Each processed webhook event stores the raw Stripe object details (PaymentIntent, Charge, or Refund) as JSON in
spy_payment_app_payment_status_history.context. This makes it easy to trace exactly what Stripe reported at the time of each status change.
Step 17: Register your domain in the Stripe Dashboard
Google Pay and Apple Pay require your site domains to be registered in Stripe. Go to Settings > Payments > Payment method domains and add your domains.
Step 18: Verify the installation
- Place a test order and confirm the payment step renders Stripe Elements.
- Complete payment and confirm the order transitions to the authorized state.
- Capture the order from the Back Office and verify the
Stripe/CaptureOMS command triggers successfully (full authorized amount is captured). - Send a test webhook event from the Stripe Dashboard and confirm the order status updates.
- (Marketplace only) Log in to Merchant Portal with a merchant user and go to Payment Settings. The Stripe section should be visible.
- (Marketplace only) Complete merchant onboarding to Stripe (Stripe Connect must be enabled on the account).
- (Marketplace only) Trigger a payout and verify the Stripe Connect transfer appears in the Stripe Express Dashboard under the merchant's connected account (also visible under Transactions > Transfers in the main Stripe account).
Development
To check/fix code style and run static analysis, use:
composer cs-fix # can be used standalone cd project-root # only works together with Spryker project (uses autoloader from it) vendor/bin/phpstan analyze -c vendor/spryker-eco/stripe/phpstan.neon vendor/spryker-eco/stripe
Webhooks in local development environment
- Install Stripe CLI.
- Forward standard account events:
stripe listen --forward-to http://yves.eu.spryker.local/stripe/notification
- Copy the signing secret from the output and set it as
STRIPE_WEBHOOK_SECRETandSTRIPE_WEBHOOK_SECRET_CONNECT.
Configure the Stripe module:
// config/Shared/config_local.php // Get these from https://dashboard.stripe.com/apikeys and Dashboard > Webhooks $config[StripeConstants::STRIPE_SECRET_KEY] = 'sk_test_***'; $config[StripeConstants::STRIPE_PUBLISHABLE_KEY] = 'pk_test_***'; $config[StripeConstants::STRIPE_WEBHOOK_SECRET] = 'whsec_***'; // from: stripe listen --forward-to $config[StripeConstants::STRIPE_WEBHOOK_SECRET_CONNECT] = 'whsec_***'; // from: stripe listen --forward-connect-to (marketplace only)
Note: For testing Google Pay and Apple Pay you need to register your external domain in Stripe Payment method domains. You can use
ngrokfor this:
- Download and install ngrok from https://ngrok.com/.
- Run
ngrok http --host-header=yves.eu.spryker.local 80to expose your local environment to the internet (a dynamic domain will be assigned).To use a personal dev domain, register it at https://dashboard.ngrok.com/domains and then run:
ngrok http --domain=your-personal-domain.ngrok-free.dev --host-header=yves.eu.spryker.local 80
- Open https://your-personal-domain.ngrok-free.dev in the browser and go to the Stripe payment page.
Support
For issues or questions:
- Check Spryker Stripe documentation
- Review Stripe documentation
- Contact Spryker support
License
This module is licensed under the same license as Spryker Commerce OS.