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 Laravel Package

ekyna/payum-payzen

PayZen gateway for Payum (Systempay, Scellius, CLIC&PAY, OSB, SOGE_COMMERCE). Install via Composer and configure site_id, certificate, mode, hash, cache directory, and endpoint. Supports predefined endpoints or a custom endpoint URL.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require ekyna/payum-payzen
    
  2. Basic Configuration Define the gateway in your Laravel service provider (e.g., AppServiceProvider):

    use Ekyna\Component\Payum\Payzen\PayzenGatewayFactory;
    
    public function register()
    {
        $this->app->singleton('payzen.gateway', function ($app) {
            $factory = new PayzenGatewayFactory();
            return $factory->create([
                'site_id'     => env('PAYZEN_SITE_ID'),
                'certificate' => env('PAYZEN_CERTIFICATE'),
                'ctx_mode'    => \Ekyna\Component\Payum\Payzen\Api\Api::MODE_TEST, // Use MODE_PRODUCTION in live
                'hash_mode'   => \Ekyna\Component\Payum\Payzen\Api\Api::HASH_MODE_SHA256,
                'directory'   => storage_path('app/payzen-cache'),
                'endpoint'    => \Ekyna\Component\Payum\Payzen\Api\Api::ENDPOINT_SYSTEMPAY,
            ]);
        });
    }
    
  3. First Use Case: Capture a Payment

    use Payum\Core\Request\Capture;
    
    $gateway = app('payzen.gateway');
    $gateway->execute(new Capture([
        'amount' => 100.00,
        'currency' => 'EUR',
        'details' => [
            'siteId' => env('PAYZEN_SITE_ID'),
            'paymentId' => uniqid(),
            'amount' => 10000, // Amount in cents
            'currency' => '978', // ISO 4217 code for EUR
            'transactionType' => 'PAYMENT',
            'returnUrl' => route('payzen.return'),
            'notificationUrls' => [route('payzen.notification')],
        ],
    ]));
    

Key Files to Review

  • vendor/ekyna/payum-payzen/README.md (for API reference)
  • vendor/ekyna/payum-payzen/src/Api/Api.php (for endpoint and mode constants)
  • vendor/ekyna/payum-payzen/src/PayzenGatewayFactory.php (for factory configuration)

Implementation Patterns

Workflow: Payment Processing

  1. Initialize Payment Use Capture or Authorize requests to start a transaction.

    $gateway->execute(new Capture($details));
    
  2. Redirect to PayZen Use Payum\Core\Request\GetHttpRequest to fetch the redirect URL:

    $request = new GetHttpRequest();
    $gateway->execute($request);
    $redirectUrl = $request->getUri();
    return redirect($redirectUrl);
    
  3. Handle Return/Notification

    • Return URL: Verify the payment status via Payum\Core\Request\Status.
    • Notification URL: Use Payum\Core\Request\Notify to process asynchronous updates.
    $gateway->execute(new Notify($details));
    
  4. Refund a Payment

    $gateway->execute(new Refund($details));
    

Integration Tips

  • Laravel Request Handling Bind PayZen notifications to a route and validate the signature:

    Route::post('/payzen/notification', [PayzenController::class, 'handleNotification']);
    
    public function handleNotification(Request $request)
    {
        $gateway = app('payzen.gateway');
        $gateway->execute(new Notify($request->all()));
    }
    
  • Custom Actions Extend the gateway with custom actions (e.g., logging, validation):

    $gateway->addAction(new class implements \Payum\Core\GatewayAction\ActionInterface {
        public function __invoke($request)
        {
            // Custom logic (e.g., log payment details)
        }
    });
    
  • Testing Use MODE_TEST and the PayZen sandbox environment for development:

    'ctx_mode' => \Ekyna\Component\Payum\Payzen\Api\Api::MODE_TEST,
    

Gotchas and Tips

Pitfalls

  1. Signature Validation PayZen uses HMAC signatures. Ensure your notification handler validates the SIGNATURE field:

    $signature = $request->input('SIGNATURE');
    $expectedSignature = hash_hmac(
        'sha256',
        $request->except('SIGNATURE'),
        env('PAYZEN_CERTIFICATE')
    );
    if (!hash_equals($signature, $expectedSignature)) {
        abort(403, 'Invalid signature');
    }
    
  2. Amount Formatting PayZen expects amounts in cents (e.g., 100.00 EUR10000). Convert Laravel’s float values:

    $amountInCents = (int) ($amount * 100);
    
  3. Cache Directory Permissions Ensure the directory path is writable by the web server:

    mkdir -p storage/app/payzen-cache
    chmod -R 755 storage/app/payzen-cache
    
  4. Endpoint Mismatches Verify endpoint matches your PayZen contract (e.g., ENDPOINT_SYSTEMPAY vs. ENDPOINT_SCELLIUS). Test in sandbox first.

  5. Idempotency PayZen notifications may be retried. Use paymentId to deduplicate requests:

    $paymentId = $request->input('paymentId');
    if (Payment::where('payzen_id', $paymentId)->exists()) {
        return response()->json(['status' => 'OK']);
    }
    

Debugging

  • Enable Payum Logging Configure Monolog in config/logging.php to log Payum events:

    'channels' => [
        'payum' => [
            'driver' => 'single',
            'path' => storage_path('logs/payum.log'),
            'level' => 'debug',
        ],
    ],
    

    Then add a logger to the gateway:

    $gateway->addAction(new \Payum\Core\Bridge\Spl\ArrayObjectToArrayAction());
    $gateway->addAction(new \Payum\Core\Bridge\Spl\Log\LoggerAction());
    
  • PayZen API Responses Inspect raw responses in storage/app/payzen-cache for errors. Example error response:

    <PAYMENT>
        <ERROR>INVALID_SIGNATURE</ERROR>
    </PAYMENT>
    

Extension Points

  1. Custom Fields Extend the details array with PayZen-specific fields (e.g., customerEmail, orderId):

    'details' => [
        'customerEmail' => $user->email,
        'orderId' => $order->id,
        // ... other fields
    ],
    
  2. Webhook Validation Create a middleware to validate PayZen webhook signatures globally:

    namespace App\Http\Middleware;
    
    use Closure;
    use Illuminate\Http\Request;
    
    class ValidatePayzenSignature
    {
        public function handle(Request $request, Closure $next)
        {
            if ($request->is('payzen/*')) {
                $this->validateSignature($request);
            }
            return $next($request);
        }
    
        protected function validateSignature(Request $request)
        {
            // Signature validation logic
        }
    }
    
  3. Retry Logic Implement a retry mechanism for failed notifications using Laravel’s queue:

    $gateway->execute(new Notify($details));
    if ($request->isNew()) {
        NotifyPayment::dispatch($details)->delay(now()->addMinute());
    }
    
  4. Multi-Currency Support Dynamically set currency based on user locale:

    $currencyCode = app()->getLocale(); // e.g., 'fr_FR' → '978' (EUR)
    $details['currency'] = CurrencyCodes::get($currencyCode);
    
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor