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

Payment Core Bundle Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require jms/payment-core-bundle
    

    Enable the bundle in config/bundles.php:

    return [
        // ...
        JMS\Payment\CoreBundle\JMSPaymentCoreBundle::class => ['all' => true],
    ];
    
  2. Database Configuration: Run migrations to create required tables:

    php bin/console doctrine:migrations:diff
    php bin/console doctrine:migrations:migrate
    
  3. 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
    
  4. 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);
    

Implementation Patterns

Core Workflows

  1. 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)
    }
    
  2. Webhook Handling:

    // In a controller or command
    $webhook = $webhookManager->createWebhook('paypal');
    $webhook->processRequest($request); // Handles incoming payment events
    
  3. Form Integration:

    // In a Symfony form
    $form = $this->createFormBuilder()
        ->add('payment_method', PaymentMethodType::class, [
            'payment_methods' => ['paypal', 'stripe'],
            'choice_options' => ['label' => false],
        ])
        ->getForm();
    
  4. Retry Logic:

    // Automatically retry failed payments
    $retryManager = $this->container->get('payment.retry_manager');
    $retryManager->retryFailedPayments();
    

Integration Tips

  • 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
    

Gotchas and Tips

Pitfalls

  1. Deprecated Services:

    • Avoid using payment.encryption_service (deprecated in favor of payment.encryption.mcrypt or payment.encryption.defuse).
    • Replace mcrypt with defuse_php_encryption for PHP 7.2+ compatibility.
  2. ExtendedDataInterface:

    • If implementing ExtendedDataInterface, ensure mayBePersisted() and set() with $persist parameter are defined (changed in v1.3.0).
  3. Symfony 4 Auto-Wiring:

    • Prefer injecting PluginController directly into controllers instead of using $container->get().
  4. Database Connection:

    • Ensure Doctrine is properly configured; the bundle may fail silently if the connection is unavailable.
  5. Webhook Validation:

    • Always validate webhook signatures to prevent fraud. Use WebhookManager with custom validators.

Debugging Tips

  • 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
    

Extension Points

  1. 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
    
  2. Custom Payment Forms: Extend PaymentFormType or create a new form type for custom payment methods.

  3. Custom Webhook Handlers: Implement WebhookHandlerInterface for handling specific payment provider events.

  4. Event Subscribers: Listen to events like PaymentCreatedEvent or TransactionFailedEvent for custom workflows.

Configuration Quirks

  • 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).

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.
labyrinthe/connect-php
encore2/laravel-admin2
cboxdk/laravel-console-kit
shapecode/doctrine-dbal-datetimeutc
gilads-otiannoh254/inertia-protocol
dakiquang/laravel-oauth-refresh-lock
woda/laravel-worktrees
dalefranks/ramasite
faghy/laracashbook
roundly-consulting/google-places-for-laravel
roundly-consulting/kubernetes-api-for-laravel
roundly-consulting/plausible-for-laravel
gvp/gvp-laravel-template
metasyncsite/laravel-metasync-client
roundly-consulting/onboarding-for-laravel
adachsoft/cli-process-tester
adachsoft/changelog-linter
adachsoft/collection
adachsoft/php-code-style
adachsoft/api-version-bundle