payzum / sylius-payzum-plugin
Accept crypto and stablecoin payments (USDC, USDT and more) in Sylius through Payzum — non-custodial
Package info
github.com/payzum-dev/sylius-payzum-plugin
Type:sylius-plugin
pkg:composer/payzum/sylius-payzum-plugin
Requires
- php: ^8.2
- payzum/payzum-php: ^0.1.0
- sylius/core-bundle: ^2.0
Requires (Dev)
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.5
- symplify/easy-coding-standard: ^12.5
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-03 15:35:38 UTC
README
Accept crypto and stablecoin payments (USDC, USDT and more, multi-chain) in Sylius through Payzum — non-custodial: funds settle directly to your own wallet, Payzum never takes custody.
Built for Sylius 2.x on the PaymentRequest flow (not Payum), following the structure of the official StripePlugin.
How it works
- The customer picks Payzum at checkout and is redirected to a hosted checkout page, where they choose the asset and chain and send the payment. No wallet or card data touches your server.
- Crypto confirmation is asynchronous, so the payment is completed from
Payzum's signed server-to-server notification, never from the browser
return. When the buyer comes back, the pay page shows the real state — a
payment that is still confirming stays in
processing. - Every notification is verified with HMAC-SHA-512 over the raw request bytes (with a replay window) before a single field of it is read, and the invoice amount and currency are re-checked against the payment before it is completed. Redelivered notifications are a no-op, so an order is never fulfilled twice.
Installation
composer require payzum/sylius-payzum-plugin
Register the bundle in config/bundles.php:
return [ // ... Payzum\SyliusPayzumPlugin\PayzumSyliusPayzumPlugin::class => ['all' => true], ];
Then create a payment method in the admin panel (Configuration → Payment methods → Create), choose the Payzum (crypto & stablecoins) gateway and fill in:
| Setting | Meaning |
|---|---|
| API key | From your Payzum merchant dashboard |
| Webhook secret | Verifies incoming payment notifications; shown once, separately from the API key |
| Pay currency | Optional. Pin one asset, e.g. usdc; empty lets the buyer choose |
| Network | Optional. Pin one chain for that asset, e.g. polygon |
| Sandbox mode | Use the Payzum staging environment |
The notification endpoint is Sylius' own
sylius_payment_method_notify route (/payment-methods/{code}); the plugin
sends it to Payzum with every invoice, so there is nothing to configure in the
dashboard.
Architecture
The Payzum-specific code is kept out of the Sylius layer, so the API client, signature verification and status mapping can be read and tested on their own:
src/
Payzum/ API client factory, gateway config, webhook
verification, status mapping, amount conversion
Command/ Capture / Notify / Status / Cancel payment requests
CommandHandler/ One handler per command
CommandProvider/ Maps a payment request action to its command
Processor/ Raw-body notify payload processor; guarded
payment transitions
Provider/ Invoice parameters, notification → payment
resolution, return URL
OrderPay/Provider/ Redirect to the hosted checkout page
Form/Type/ Gateway configuration form
Two design points worth knowing:
- The payment request hash travels as the Payzum
order_id, so a verified notification is matched to its payment without trusting anything else in the payload — and each delivery is handled as a fresh payment request, which is what keeps the gateway's retries working after the order is paid. - Amounts are converted with exact string arithmetic (never through a float) and the currency's own number of decimals, so zero-decimal currencies (JPY) and three-decimal ones (KWD) are correct too.
Tests
composer install vendor/bin/phpunit
License
MIT. The payzum/payzum-php
SDK it builds on is MIT as well and has no runtime dependencies.