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

Laravel Redsys Laravel Package

creagia/laravel-redsys

A Laravel package for integrating Spain's Redsys payment gateway. Easily generate signed payment requests, redirect customers to the virtual POS, and securely handle server notifications and callbacks with minimal configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Requirements for 4.0.0: PHP 8.2+ (adds PHP 8.5 compatibility) and Laravel 11, 12, or 13. Laravel 8–10 support was removed; remain on 3.0.3 if your app is older.
  • Install the package:
    composer require creagia/laravel-redsys
    
  • Publish the package assets and run the notification table migration:
    php artisan vendor:publish --provider="Creagia\Redsys\RedsysServiceProvider"
    php artisan migrate
    
  • Configure the gateway in .env:
    REDSYS_ENVIRONMENT=test
    REDSYS_MERCHANT_CODE=999008881
    REDSYS_TERMINAL=1
    REDSYS_SECRET_KEY=base64-encoded-terminal-secret
    
  • Look first at:
    • config/redsys.php for merchant code, terminal, secret key, environment, and route/notification settings.
    • The Redsys facade for form generation and response helpers.
    • The package notification route/controller and RedsysNotification model.
  • First use case: create a pending local order, generate the Redsys form, redirect the customer, then mark the order paid only from the validated server-to-server notification:
    use Creagia\Redsys\Facades\Redsys;
    
    $order = Order::create([...]); // status: pending
    
    $form = Redsys::generatePaymentForm(
        order: $order->reference,       // max 12 chars, unique
        amount: $order->total_cents,   // amount in cents
        urlOk: route('checkout.ok'),
        urlKo: route('checkout.ko'),
        notificationUrl: route('redsys.notification'),
    );
    
    return view('checkout.redirect', compact('form')); // render with {!! $form !!}
    

Implementation Patterns

  • Treat the notification as the source of truth. The urlOk/urlKo pages are user experience only; a customer can open the OK URL manually. Only fulfil an order after the package has validated the Redsys signature in the notification endpoint.
  • Standard order lifecycle:
    1. Create a local order with pending status and a unique merchant order reference.
    2. Generate and render the Redsys payment form.
    3. Customer pays on the Redsys/bank page.
    4. Redsys POSTs the notification to your app.
    5. The package validates the signature and persists the notification.
    6. Your listener reconciles the notification against the local order.
    7. The OK page reads the final local order status.
  • Listen to the notification event rather than putting business logic in the package controller:
    Event::listen(RedsysNotificationReceived::class, function ($event) {
        $notification = $event->redsysNotification;
    
        $order = Order::where('reference', $notification->order)->firstOrFail();
    
        if ($notification->isSuccessful()
            && $notification->amount === $order->total_cents) {
            $order->markAsPaid($notification->authorisation_code);
        }
    });
    
    Check the exact event class in your installed version; alternatively publish/override the notification controller and dispatch your own domain event.
  • Make reconciliation idempotent. Redsys can deliver the same notification more than once. Use a transaction and a unique constraint or “already processed” check on the merchant order plus response data before changing order state.
  • Verify amount and currency, not just the response code. Compare the notified amount with the expected order total to prevent tampering or stale attempts.
  • Use one merchant order per payment attempt. If a customer retries payment, create a new reference so each notification maps cleanly to one attempt and one local order/payment record.
  • Store raw notifications. The package’s notification record is useful for audit and support. Keep the raw Ds_MerchantParameters/response payload accessible when investigating bank-side disputes.
  • Test in the Redsys test environment with the documented test cards. Use the package’s signature generation/validation helpers to construct signed notification payloads in feature tests rather than mocking the signature check.
  • Separate payment initiation from domain fulfilment. A small PaymentService around the facade keeps controllers thin and lets you swap the package or add reconciliation commands later.
  • Refunds and other operations: the package primarily covers payment form generation and notification validation. If you need refunds, partial captures, or recurring payments, verify support in the installed version and otherwise implement those Redsys operations directly with the gateway API.
  • Operational reconciliation: add a scheduled command that finds stale pending orders and checks them against Redsys or your notification records. Do not rely solely on the browser returning to urlOk.

Gotchas and Tips

  • 4.0.0 is a compatibility major. The meaningful breaking change is dropping Laravel 8–10; there are no new payment features called out in the release. Upgrade only after confirming Laravel 11+ and PHP 8.2+, then run the full payment test suite.
  • Exclude the notification route from CSRF protection. Redsys posts form-encoded data server-to-server. In Laravel 11+ add the route to validateCsrfTokens(except: [...]); otherwise notifications fail with 419 and orders remain pending.
  • Amounts are in cents. Send integers (100 = 1.00 EUR). Confirm the currency in config/redsys.php; the default is usually EUR (978). A decimal amount will produce a wrong charge or signature mismatch.
  • Merchant order IDs must be short and stable. Redsys limits them to 12 characters and uses the exact order string when deriving the signature key. Leading zeros and formatting matter; do not trim or reformat the order after generating the form.
  • Secret keys are environment-specific. The test terminal secret is not the production secret. Use the exact base64 value supplied by the bank/terminal; do not URL-encode, trim, or wrap it.
  • Use absolute, public HTTPS URLs in production. Redsys cannot notify localhost or private hosts. Ensure notificationUrl is reachable and not behind auth, IP allow-listing, or maintenance mode.
  • Return a 2xx after persisting the notification. If your listener throws or returns an error, Redsys may retry. Persist first, then process; make retries harmless.
  • Do not mark orders paid from the OK redirect. Read the local order status populated by the notification instead.
  • Response codes are not binary. 0000–0099 are generally approved; 0900 is an authorization; codes such as 0101, 0102, 0190, and 0191 are denials. Store and display the raw code and authorization code.
  • Debug signature failures by comparing the exact Ds_Order and Ds_MerchantParameters. Log the order reference and response code, but never log the terminal secret or full derived key. A single character difference in the order string causes a valid-looking but rejected signature.
  • Clear config cache after changing Redsys environment variables. Use php artisan config:clear (and redeploy if config is cached during release).
  • Render the generated form unescaped. The facade returns an auto-submitting HTML form; Blade’s {{ }} will display markup instead of submitting it.
  • Extension points: publish and customise the config/route/controller, listen to notification events, replace or extend the notification model, and use the package’s request/parameter objects for language, currency, merchant data, and order expiry. Keep custom gateway operations isolated from the package’s notification path.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource