Weave Code
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

Payum Payzen Bundle Laravel Package

ekyna/payum-payzen-bundle

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Install the Bundle**
   ```bash
   composer require ekyna/payum-payzen-bundle

Ensure Ekyna\PayumPayzenBundle\EkynaPayumPayzenBundle is registered in config/bundles.php.

  1. Configure Payum Add the PayZen gateway to your config/packages/payum.yaml:

    payum:
        gateways:
            payzen:
                factory: 'payum.core.gateway_factory'
                class:    'Ekyna\PayumPayzen\PayzenGateway'
                config:
                    api_key:      '%env(PAYZEN_API_KEY)%'
                    secret_key:   '%env(PAYZEN_SECRET_KEY)%'
                    sandbox:      '%env(bool:PAYZEN_SANDBOX)%'
                    currency:     'EUR'
                    payment_method: 'CB'  # or 'IDEAL', 'SEPA', etc.
    
  2. First Use Case: Payment Initiation Inject the Payum service and trigger a payment:

    use Payum\Core\Payum;
    use Payum\Core\Request\Capture;
    
    public function __construct(private Payum $payum) {}
    
    public function processPayment(float $amount, string $orderId): void
    {
        $storage = $this->payum->getStorage('Ekyna\PayumPayzenBundle\Model\PayzenPayment');
        $payment = $storage->create();
    
        $payment->setNumber($orderId);
        $payment->setTotalAmount($amount);
        $payment->setCurrencyCode('EUR');
    
        $captureRequest = new Capture();
        $captureRequest->setToken($payment->getToken());
        $captureRequest->setModel($payment);
    
        $this->payum->getGateway('payzen')->execute($captureRequest);
    
        // Redirect to PayZen's payment page (URL stored in $payment->getAfterUrl())
    }
    

Implementation Patterns

Workflow: Payment Lifecycle

  1. Initiate Payment Use Capture request to redirect users to PayZen’s payment page. Store the token and afterUrl for later use.

    $this->payum->getGateway('payzen')->execute($captureRequest);
    return new RedirectResponse($payment->getAfterUrl());
    
  2. Handle Callback PayZen posts a callback to your afterUrl. Use Notify request to validate the payment:

    public function handlePayzenCallback(Request $request)
    {
        $notifyRequest = new Notify();
        $notifyRequest->setModel($this->payum->getStorage()->find($request->get('PAYMENT_ID')));
    
        $this->payum->getGateway('payzen')->execute($notifyRequest);
    
        if ($notifyRequest->isSuccessful()) {
            // Payment successful: update order status, send confirmation, etc.
        }
    }
    
  3. Refunds & Cancellations Use Refund or Cancel requests for post-payment actions:

    $refundRequest = new Refund();
    $refundRequest->setModel($payment);
    $refundRequest->setAmount(10.00);
    $this->payum->getGateway('payzen')->execute($refundRequest);
    

Integration Tips

  • Symfony Forms Integration Use Payum\Core\Bridge\Symfony\Forms\Type\PaymentType to bind payments to forms:

    # config/packages/payum.yaml
    payum:
        gateways:
            payzen:
                # ... config ...
                payment_methods:
                    - 'CB'
                    - 'IDEAL'
    
    $builder->add('payment', PaymentType::class, [
        'action' => $this->generateUrl('payum_payzen_notify'),
        'gateway_name' => 'payzen',
    ]);
    
  • Storage Customization Extend Ekyna\PayumPayzenBundle\Model\PayzenPayment to add custom fields (e.g., customerEmail):

    class CustomPayzenPayment extends PayzenPayment
    {
        protected $customerEmail;
    
        public function getCustomerEmail(): ?string { return $this->customerEmail; }
        public function setCustomerEmail(string $email): self { $this->customerEmail = $email; return $this; }
    }
    

    Update config/packages/payum.yaml to use your class:

    payum:
        storage:
            Ekyna\PayumPayzenBundle\Model\PayzenPayment: doctrine://default
    
  • Webhook Validation Validate PayZen callbacks using the secret_key:

    use Ekyna\PayumPayzen\PayzenGateway;
    
    public function handleCallback(Request $request)
     {
         $gateway = $this->payum->getGateway('payzen');
         if (!$gateway->validateCallback($request->getContent(), $request->get('PAYMENT_ID'))) {
             throw new \RuntimeException('Invalid callback signature');
         }
     }
    

Gotchas and Tips

Pitfalls

  1. Sandbox vs. Production

    • Always test in sandbox mode (sandbox: true) before going live.
    • PayZen’s sandbox uses test cards (e.g., 4929010000000007 for CB). Verify PayZen’s test docs.
  2. Callback Handling

    • PayZen sends callbacks to your afterUrl. Ensure this endpoint:
      • Is publicly accessible (no auth).
      • Validates the PAYMENT_ID and signature (use validateCallback()).
      • Does not rely on session data (callbacks are stateless).
    • Example of a broken implementation:
      // ❌ Avoid: Assuming $request->get('PAYMENT_ID') is trusted without validation.
      $payment = $this->payum->getStorage()->find($request->get('PAYMENT_ID'));
      
  3. Currency & Amount Precision

    • PayZen expects amounts in minor units (e.g., 10.00 EUR1000 cents).
    • Use number_format($amount * 100, 0, '', '') to avoid floating-point errors.
  4. Payment Method Restrictions

    • Some payment methods (e.g., SEPA) require additional validation (IBAN, BIC). Validate these before initiating the payment.

Debugging

  1. Enable Payum Logging Add to config/packages/monolog.yaml:

    handlers:
        payum:
            type: stream
            path: "%kernel.logs_dir%/payum.log"
            level: debug
            channels: ["payum"]
    

    Then configure Payum to use the channel:

    # config/packages/payum.yaml
    payum:
        logging: true
    
  2. Gateway Configuration Errors

    • If payments fail silently, check:
      • api_key and secret_key are correct (no trailing whitespace).
      • The payment_method is supported by PayZen (e.g., CB, IDEAL).
      • The currency matches PayZen’s supported currencies.
  3. Doctrine Storage Issues

    • Ensure your PayzenPayment entity is properly mapped:
      /** @ORM\Entity(repositoryClass="Ekyna\PayumPayzenBundle\Repository\PayzenPaymentRepository") */
      class PayzenPayment extends AbstractPayzenPayment {}
      
    • Run php bin/console doctrine:schema:validate to catch mapping errors.

Extension Points

  1. Custom Payment Actions Extend the gateway to add custom logic (e.g., pre-authorization):

    use Ekyna\PayumPayzen\PayzenGateway as BaseGateway;
    
    class CustomPayzenGateway extends BaseGateway
    {
        public function preAuthorize(array $details)
        {
            $details['action'] = 'PREAUTHORIZATION';
            return parent::execute($details);
        }
    }
    

    Register it in config/packages/payum.yaml:

    payum:
        gateways:
            custom_payzen:
                factory: 'payum.core.gateway_factory'
                class: 'App\Payum\CustomPayzenGateway'
                config: { ... }
    
  2. Override Callback Validation Extend Ekyna\PayumPayzen\PayzenGateway to add custom validation rules:

    public function validateCallback(string $content, string $paymentId): bool
    {
        if (!$this->validateSignature($content)) {
            return false;
        }
        // Add custom logic (e.g., check IP, user agent)
        return true;
    }
    
  3. Webhook Retry Logic Implement a retry mechanism for failed callbacks using Symfony Messenger:

    use Payum\Core\Request\Notify;
    
    public function handleCallback(Request $request)
    {
        try {
            $this->
    
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.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware