jms/payment-core-bundle
Symfony bundle providing a unified API for processing payments across multiple providers. Includes persistence for payments/transactions, retryable transaction management, encryption of sensitive data, and built-in support for many backends with easy extensibility.
Installation:
composer require jms/payment-core-bundle
Enable the bundle in config/bundles.php:
return [
// ...
JMS\Payment\CoreBundle\JMSPaymentCoreBundle::class => ['all' => true],
];
Database Configuration: Run migrations to create required tables:
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
First Use Case:
Create a payment plugin (e.g., for PayPal) by extending AbstractPlugin and register it in config/packages/jms_payment_core.yaml:
jms_payment_core:
plugins:
paypal:
class: App\Plugin\PayPalPlugin
Basic Payment Flow:
use JMS\Payment\CoreBundle\Model\PaymentInterface;
use JMS\Payment\CoreBundle\Plugin\PluginInterface;
// Create a payment
$payment = $paymentManager->createPayment('paypal', $amount);
// Execute payment
$result = $paymentPlugin->executePayment($payment);
Payment Creation & Execution:
// Create a payment with metadata
$payment = $paymentManager->createPayment('paypal', 100.00, [
'currency' => 'USD',
'order_id' => '12345',
]);
// Execute via plugin
$result = $paymentPlugin->executePayment($payment);
// Check result
if ($result->isSuccess()) {
// Success logic
} else {
// Handle failure (e.g., retry or notify user)
}
Webhook Handling:
// In a controller or command
$webhook = $webhookManager->createWebhook('paypal');
$webhook->processRequest($request); // Handles incoming payment events
Form Integration:
// In a Symfony form
$form = $this->createFormBuilder()
->add('payment_method', PaymentMethodType::class, [
'payment_methods' => ['paypal', 'stripe'],
'choice_options' => ['label' => false],
])
->getForm();
Retry Logic:
// Automatically retry failed payments
$retryManager = $this->container->get('payment.retry_manager');
$retryManager->retryFailedPayments();
Dependency Injection:
Use auto-wiring for services like PaymentManagerInterface, PluginController, and WebhookManagerInterface.
Event Listeners:
Subscribe to payment events (e.g., PaymentCreatedEvent, PaymentSucceededEvent) for custom logic:
// config/services.yaml
services:
App\EventListener\PaymentListener:
tags:
- { name: kernel.event_listener, event: payment.succeeded, method: onPaymentSucceeded }
Custom Plugins:
Extend AbstractPlugin and implement PluginInterface:
class CustomPlugin extends AbstractPlugin
{
public function executePayment(PaymentInterface $payment)
{
// Custom logic
return new Result($payment, true, 'Success');
}
}
Encryption:
Enable encryption in config/packages/jms_payment_core.yaml:
jms_payment_core:
encryption:
secret: '%env(PAYMENT_ENCRYPTION_SECRET)%'
provider: defuse_php_encryption
Generate a key with:
php bin/console jms:payment:generate-encryption-key
Deprecated Services:
payment.encryption_service (deprecated in favor of payment.encryption.mcrypt or payment.encryption.defuse).mcrypt with defuse_php_encryption for PHP 7.2+ compatibility.ExtendedDataInterface:
ExtendedDataInterface, ensure mayBePersisted() and set() with $persist parameter are defined (changed in v1.3.0).Symfony 4 Auto-Wiring:
PluginController directly into controllers instead of using $container->get().Database Connection:
Webhook Validation:
WebhookManager with custom validators.Enable Logging:
Configure monolog to log payment events:
monolog:
handlers:
payment:
type: stream
path: "%kernel.logs_dir%/payment.log"
level: debug
channels: ["payment"]
Check Payment Status:
Use the PaymentManager to fetch and inspect payments:
$payment = $paymentManager->findPaymentById($id);
$result = $payment->getResult();
Test Retry Logic: Manually trigger retries for failed payments:
php bin/console payment:retry-failed
Custom Encryption Providers:
Implement EncryptionServiceInterface for custom encryption:
class CustomEncryptionService implements EncryptionServiceInterface
{
public function encrypt($data) { /* ... */ }
public function decrypt($data) { /* ... */ }
}
Register in config/services.yaml:
jms_payment_core:
encryption:
provider: custom
Custom Payment Forms:
Extend PaymentFormType or create a new form type for custom payment methods.
Custom Webhook Handlers:
Implement WebhookHandlerInterface for handling specific payment provider events.
Event Subscribers:
Listen to events like PaymentCreatedEvent or TransactionFailedEvent for custom workflows.
Encryption Defaults:
Encryption is disabled by default. Explicitly configure encryption.secret and encryption.provider to enable it.
Plugin Configuration:
Plugins require unique names in jms_payment_core.plugins. Avoid duplicates.
Doctrine Migrations: Always run migrations after updating the bundle, as schema changes may not be backward-compatible.
Symfony 3 vs. 4:
Symfony 4 requires updated service aliases (e.g., PluginController instead of payment.plugin_controller).
How can I help you explore Laravel packages today?