Skip to content

Redsys

Redsys uses form redirection: the library generates the parameters signed with HMAC-SHA256 and serves a hosted page that auto-submits them via POST to the Redsys POS terminal. You just redirect the browser to the redirect_url in the response. The confirmation arrives via online notification to your merchant_url.

Configuration

ts
import { RedsysGateway } from '@kaizen/payments-gateway'

RedsysGateway.register({
  merchant_code: process.env.REDSYS_MERCHANT_CODE!,
  terminal: process.env.REDSYS_TERMINAL!,
  secret_key: process.env.REDSYS_SECRET_KEY!,
  environment: 'test',                       // 'test' | 'production'
  merchant_url: process.env.REDSYS_MERCHANT_URL!,
  merchant_name: 'My Store',                 // optional
})
FieldTypeRequiredDescription
merchant_codestringMerchant code (FUC)
terminalstringTerminal number
secret_keystringSecret key for the HMAC-SHA256 signature
environment'test' | 'production'Selects the POS endpoint
merchant_urlstringOnline notification URL (usually /webhooks/redsys)
merchant_namestringMerchant name shown at the gateway

POS endpoints

environmentURL
testhttps://sis-t.redsys.es:25443/sis/realizarPago
productionhttps://sis.redsys.es/sis/realizarPago

Environment variables

You provide the values from your own environment and pass them to RedsysGateway.register():

ini
REDSYS_MERCHANT_CODE=999008881
REDSYS_TERMINAL=001
REDSYS_SECRET_KEY=sq7HjrUOBfKmC576ILgskD5srU870gJ7
REDSYS_ENVIRONMENT=test          # 'test' | 'production'
REDSYS_MERCHANT_URL=https://your-domain.com/webhooks/redsys
REDSYS_MERCHANT_NAME=My Store    # optional
VariableFieldRequiredDescription
REDSYS_MERCHANT_CODEmerchant_codeMerchant code (FUC)
REDSYS_TERMINALterminalTerminal number
REDSYS_SECRET_KEYsecret_keySecret key for the HMAC-SHA256 signature
REDSYS_ENVIRONMENTenvironmenttest or production (picks the endpoint)
REDSYS_MERCHANT_URLmerchant_urlOnline notification URL (/webhooks/redsys)
REDSYS_MERCHANT_NAMEmerchant_nameMerchant name shown at the gateway

Create a charge

bash
curl -X POST http://localhost:3000/payments/charge \
  -H 'content-type: application/json' \
  -d '{
    "gateway": "redsys",
    "amount": 4900,
    "currency": "EUR",
    "reference": "order-001",
    "redirect": {
      "success_url": "http://localhost:3000/ok",
      "cancel_url": "http://localhost:3000/ko"
    }
  }'

Redsys requirements

  • redirect.success_url and redirect.cancel_url are mandatory (they map to DS_MERCHANT_URLOK / DS_MERCHANT_URLKO). Without them → 400.
  • Only EUR is supported (code 978). Any other currency → 400.
  • amount is in cents (4900 = €49.00).

How the user pays

The response has the same shape as every other gateway: a redirect_url you send the browser to.

json
{
  "payment_id": "b9c1…",
  "gateway": "redsys",
  "status": "pending",
  "redirect_url": "http://localhost:3000/payments/redsys/redirect/b9c1…"
}

Unlike Stripe or PayPal, that redirect_url does not point at the POS directly, but at a page the library itself mounts (GET /payments/redsys/redirect/:payment_id). When opened, that page auto-submits the signed form via POST to the Redsys POS:

html
<form action="https://sis-t.redsys.es:25443/sis/realizarPago" method="post">
  <input type="hidden" name="Ds_SignatureVersion" value="HMAC_SHA256_V1" />
  <input type="hidden" name="Ds_MerchantParameters" value="…" />
  <input type="hidden" name="Ds_Signature" value="…" />
</form>

You don't build that form: the library generates and serves it. The merchant parameters are serialized to JSON, Base64-encoded and signed with HMAC-SHA256 deriving the key per order number. From your side, the flow is identical to any other gateway: redirect the browser to redirect_url.

Notification and confirmation

Redsys calls your merchant_url (→ POST /webhooks/redsys). The library:

  1. Decodes Ds_MerchantParameters (url-safe Base64).
  2. Verifies the Ds_Signature against the order number. Invalid → 400.
  3. Reads Ds_Response:
    • 0–99 → payment captured → emits payment.captured.
    • anything else → failed → emits payment.failed.

The gateway_ref that matches the notification to the Payment is the order number (Ds_Order), generated by the library when creating the charge.