@jsm406/medusa-plugin-redsys 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -78,14 +78,6 @@ class RedsysProviderService extends utils_1.AbstractPaymentProvider {
78
78
  }
79
79
  // ---------- Authorize ----------
80
80
  async authorizePayment(input) {
81
- const sessionData = input.data;
82
- if (sessionData?.status === "authorized" ||
83
- sessionData?.status === "pending") {
84
- return {
85
- status: utils_1.PaymentSessionStatus.AUTHORIZED,
86
- data: input.data,
87
- };
88
- }
89
81
  return {
90
82
  status: utils_1.PaymentSessionStatus.PENDING,
91
83
  data: input.data,
@@ -328,4 +320,4 @@ class RedsysProviderService extends utils_1.AbstractPaymentProvider {
328
320
  }
329
321
  RedsysProviderService.identifier = "redsys";
330
322
  exports.default = RedsysProviderService;
331
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9wcm92aWRlcnMvcmVkc3lzL3NlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxxREFLa0M7QUFDbEMsNkNBQTRFO0FBOEI1RSwrQ0FBb0Q7QUFDcEQsbURBQXFEO0FBQ3JELG1EQUFzRDtBQUN0RCwrQ0FBb0Q7QUFNcEQsTUFBTSxRQUFRLEdBQUc7SUFDZixRQUFRLEVBQUUsS0FBSztJQUNmLGVBQWUsRUFBRSxHQUFHO0NBQ1osQ0FBQTtBQUVWLE1BQU0scUJBQXNCLFNBQVEsK0JBQXNDO0lBT3hFLE1BQU0sQ0FBQyxlQUFlLENBQUMsT0FBZ0M7UUFDckQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLElBQUksT0FBTyxPQUFPLENBQUMsU0FBUyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ2hFLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLG1EQUFtRCxDQUNwRCxDQUFBO1FBQ0gsQ0FBQztRQUNELElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxJQUFJLE9BQU8sT0FBTyxDQUFDLFlBQVksS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUN0RSxNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUM5QixzREFBc0QsQ0FDdkQsQ0FBQTtRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsWUFBWSxTQUErQixFQUFFLE9BQXNCO1FBQ2pFLEtBQUssQ0FBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLENBQUE7UUFDekIsSUFBSSxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFBO1FBQy9CLElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFBO1FBRXZCLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBQSw2QkFBZSxFQUFDO1lBQy9CLFNBQVMsRUFBRSxPQUFPLENBQUMs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
323
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9wcm92aWRlcnMvcmVkc3lzL3NlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxxREFLa0M7QUFDbEMsNkNBQTRFO0FBOEI1RSwrQ0FBb0Q7QUFDcEQsbURBQXFEO0FBQ3JELG1EQUFzRDtBQUN0RCwrQ0FBb0Q7QUFNcEQsTUFBTSxRQUFRLEdBQUc7SUFDZixRQUFRLEVBQUUsS0FBSztJQUNmLGVBQWUsRUFBRSxHQUFHO0NBQ1osQ0FBQTtBQUVWLE1BQU0scUJBQXNCLFNBQVEsK0JBQXNDO0lBT3hFLE1BQU0sQ0FBQyxlQUFlLENBQUMsT0FBZ0M7UUFDckQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLElBQUksT0FBTyxPQUFPLENBQUMsU0FBUyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ2hFLE1BQU0sSUFBSSxtQkFBVyxDQUNuQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLG1EQUFtRCxDQUNwRCxDQUFBO1FBQ0gsQ0FBQztRQUNELElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxJQUFJLE9BQU8sT0FBTyxDQUFDLFlBQVksS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUN0RSxNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUM5QixzREFBc0QsQ0FDdkQsQ0FBQTtRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsWUFBWSxTQUErQixFQUFFLE9BQXNCO1FBQ2pFLEtBQUssQ0FBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLENBQUE7UUFDekIsSUFBSSxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFBO1FBQy9CLElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFBO1FBRXZCLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBQSw2QkFBZSxFQUFDO1lBQy9CLFNBQVMsRUFBRSxPQUFPLENBQUMs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
package/README.md CHANGED
@@ -1,497 +1,514 @@
1
- # medusa-payment-redsys
2
-
3
- Redsys / Sermepa TPV Virtual payment provider plugin for [MedusaJS v2](https://medusajs.com/).
4
-
5
- This plugin enables payment processing through Redsys' hosted payment page (TPV Virtual) via redirect flow. Customers are redirected to the Redsys secure payment page to complete their transaction.
6
-
7
- > **Production-proven**: This plugin is derived from a live production Medusa store processing real Redsys payments.
8
-
9
- ## Features
10
-
11
- - Redsys hosted payment page / TPV Virtual redirect flow
12
- - Sandbox and production environments
13
- - One-step payment (immediate capture) and two-step payment (pre-authorization + capture)
14
- - Full and partial refunds via Redsys API
15
- - Payment cancellation
16
- - Webhook handling with HMAC-SHA256 signature verification
17
- - Spanish error messages for Redsys response codes
18
- - Zero PCI scope — card data is handled by Redsys' secure page
19
-
20
- ## Prerequisites
21
-
22
- - MedusaJS v2.13.0 or later
23
- - Node.js v20 or later
24
- - A [Redsys merchant account](https://comercios.redsys.es/) (or sandbox test credentials)
25
- - `redsys-easy` v5.3.0+ (installed automatically as a dependency)
26
-
27
- ## Installation
28
-
29
- ```bash
30
- npm install medusa-payment-redsys
31
- # or
32
- yarn add medusa-payment-redsys
33
- # or
34
- pnpm add medusa-payment-redsys
35
- ```
36
-
37
- ## Configuration
38
-
39
- ### Environment Variables
40
-
41
- Add the following to your `.env` file:
42
-
43
- ```env
44
- REDSYS_SECRET_KEY=sq7Hj....
45
- REDSYS_MERCHANT_CODE=999008881
46
- REDSYS_TERMINAL=001
47
- REDSYS_ENVIRONMENT=sandbox
48
- REDSYS_NOTIFICATION_URL=https://your-api.com/hooks/payment/redsys_redsys
49
- REDSYS_SUCCESS_URL=https://your-store.com/checkout/redsys-callback
50
- REDSYS_ERROR_URL=https://your-store.com/checkout/redsys-callback?error=1
51
- ```
52
-
53
- For sandbox testing, use the following test credentials from Redsys:
54
-
55
- ```
56
- Merchant Code: 999008881
57
- Terminal: 001
58
- Secret Key: sq7Hj.......
59
- Environment: sandbox
60
- ```
61
-
62
- ### Medusa Configuration
63
-
64
- In your `medusa-config.ts`:
65
-
66
- ```ts
67
- import { defineConfig } from "@medusajs/framework/config"
68
-
69
- export default defineConfig({
70
- modules: [
71
- {
72
- resolve: "@medusajs/medusa/payment",
73
- options: {
74
- providers: [
75
- {
76
- resolve: "medusa-payment-redsys/providers/redsys",
77
- id: "redsys",
78
- options: {
79
- secretKey: process.env.REDSYS_SECRET_KEY,
80
- merchantCode: process.env.REDSYS_MERCHANT_CODE,
81
- terminal: process.env.REDSYS_TERMINAL || "001",
82
- environment:
83
- process.env.REDSYS_ENVIRONMENT || "sandbox",
84
- notificationUrl:
85
- process.env.REDSYS_NOTIFICATION_URL,
86
- successUrl: process.env.REDSYS_SUCCESS_URL,
87
- errorUrl: process.env.REDSYS_ERROR_URL,
88
- transactionType: "0", // "0" = immediate capture, "1" = pre-authorization
89
- },
90
- },
91
- ],
92
- },
93
- },
94
- ],
95
- })
96
- ```
97
-
98
- ### Enable in Region
99
-
100
- Enable the Redsys provider in your Medusa admin panel under **Settings > Regions** and select **Redsys** as a payment provider.
101
-
102
- The provider ID will be:
103
-
104
- ```
105
- pp_redsys_redsys
106
- ```
107
-
108
- ## Options
109
-
110
- | Option | Type | Required | Default | Description |
111
- |---|---|---|---|---|
112
- | `secretKey` | string | Yes | — | Redsys HMAC-SHA256 secret key |
113
- | `merchantCode` | string | Yes | — | Redsys merchant code (FUC) |
114
- | `terminal` | string | No | `"001"` | Terminal number |
115
- | `environment` | string | No | `"sandbox"` | `"sandbox"` or `"production"` |
116
- | `notificationUrl` | string | No | — | Webhook URL for Redsys to POST transaction results |
117
- | `successUrl` | string | No | — | URL to redirect after successful payment (URLOK) |
118
- | `errorUrl` | string | No | — | URL to redirect after failed payment (URLKO) |
119
- | `transactionType` | string | No | `"0"` | `"0"` = immediate capture, `"1"` = pre-authorization |
120
-
121
- ## Payment Flow
122
-
123
- 1. Customer selects **Redsys** as payment method
124
- 2. `initiatePayment()` creates a signed redirect form with Redsys merchant parameters
125
- 3. Customer clicks "Place Order" → storefront calls `cart.complete()` to create the order, stores a cookie mapping the Redsys internal order ID to the Medusa order ID, then auto-submits the redirect form to Redsys TPV
126
- 4. Customer completes payment on the Redsys hosted payment page
127
- 5. Redsys sends a **webhook notification** to `{backendUrl}/hooks/payment/redsys_redsys`
128
- 6. `getWebhookActionAndData()` validates the HMAC-SHA256 signature and updates the payment status
129
- 7. Redsys redirects the customer's browser to `successUrl` or `errorUrl` with the Redsys order ID as a query parameter
130
- 8. Storefront callback page reads the cookie to resolve the Medusa order ID and redirects to the order confirmation page
131
-
132
- ### Important: authorizePayment Behavior
133
-
134
- This plugin's `authorizePayment` returns `AUTHORIZED` for sessions with status `"pending"` **and** `"authorized"`. This is intentional for the redirect flow: the real authorization happens on Redsys TPV and is confirmed via webhook. Without this, `cart.complete()` would fail with a 400 error because Medusa requires the payment session to be authorized before completing the cart.
135
-
136
- ### ID Mapping (Redsys → Medusa)
137
-
138
- The plugin generates a 12-character alphanumeric `orderId` (e.g. `97727XYIWRRF`) used as Redsys' merchant order reference. When the order is completed via `cart.complete()`, Medusa generates its own order ID (e.g. `order_01KR3B4X...`). These are **different IDs**.
139
-
140
- The callback URL from Redsys only contains the Redsys order ID, not the Medusa order ID. To bridge this gap, the storefront stores a cookie `redsys_map_{redsysOrderId}={medusaOrderId}` before redirecting to the TPV. The callback page reads this cookie to resolve the real Medusa order and redirect to the confirmation page.
141
-
142
- ## Storefront Integration
143
-
144
- Redsys is a **redirect-based** payment method (no card input in your storefront — the customer enters card data on Redsys' secure TPV). You must adapt your Medusa Next.js storefront with the changes below.
145
-
146
- ### 1. `src/lib/constants.tsx` — Register the payment method
147
-
148
- Add Redsys to the payment info map and add a helper function:
149
-
150
- ```tsx
151
- // Inside paymentInfoMap, add:
152
- pp_redsys_redsys: {
153
- title: "Credit / Debit Card",
154
- icon: <CreditCard />,
155
- },
156
-
157
- // Add helper function:
158
- export const isRedsys = (providerId?: string) => {
159
- return providerId?.startsWith("pp_redsys_")
160
- }
161
- ```
162
-
163
- ### 2. `src/lib/data/cart.ts` — Add order completion without redirect
164
-
165
- Add a `completeCartWithoutRedirect` function. The standard `placeOrder` does a `redirect()` (server-side), but Redsys needs to redirect the browser to the TPV instead. This function completes the cart, creates the order, but returns the result so the client can handle the TPV redirect:
166
-
167
- ```ts
168
- export async function completeCartWithoutRedirect(cartId?: string) {
169
- const id = cartId || (await getCartId())
170
-
171
- if (!id) {
172
- throw new Error("No existing cart found when completing cart")
173
- }
174
-
175
- const headers = {
176
- ...(await getAuthHeaders()),
177
- }
178
-
179
- const cartRes = await sdk.store.cart
180
- .complete(id, {}, headers)
181
- .then(async (cartRes) => {
182
- const cartCacheTag = await getCacheTag("carts")
183
- revalidateTag(cartCacheTag)
184
- return cartRes
185
- })
186
- .catch(medusaError)
187
-
188
- if (cartRes?.type === "order") {
189
- const orderCacheTag = await getCacheTag("orders")
190
- revalidateTag(orderCacheTag)
191
- removeCartId()
192
- }
193
-
194
- return cartRes
195
- }
196
- ```
197
-
198
- ### 3. `src/modules/checkout/components/payment-button/index.tsx` — Redsys payment button
199
-
200
- Add a `RedsysPaymentButton` component that:
201
- 1. Reads the payment session data (formUrl, merchantParams, signature) from the cart
202
- 2. Calls `completeCartWithoutRedirect()` to create the order
203
- 3. Stores a cookie mapping the Redsys internal order ID Medusa order ID (see [ID Mapping](#id-mapping-redsys--medusa))
204
- 4. Dynamically builds and auto-submits a `<form>` to Redsys' TPV
205
-
206
- ```tsx
207
- // Add import:
208
- import { isManual, isRedsys, isStripeLike } from "@lib/constants"
209
- import { completeCartWithoutRedirect, placeOrder } from "@lib/data/cart"
210
-
211
- // Add case in PaymentButton's switch:
212
- case isRedsys(paymentSession?.provider_id):
213
- return (
214
- <RedsysPaymentButton
215
- notReady={notReady}
216
- cart={cart}
217
- data-testid={dataTestId}
218
- />
219
- )
220
-
221
- // Add the component:
222
- const RedsysPaymentButton = ({
223
- cart,
224
- notReady,
225
- "data-testid": dataTestId,
226
- }: {
227
- cart: HttpTypes.StoreCart
228
- notReady: boolean
229
- "data-testid"?: string
230
- }) => {
231
- const [submitting, setSubmitting] = useState(false)
232
- const [errorMessage, setErrorMessage] = useState<string | null>(null)
233
-
234
- const handlePayment = async () => {
235
- setSubmitting(true)
236
-
237
- const paymentSession = cart.payment_collection?.payment_sessions?.find(
238
- (s) => s.status === "pending" && isRedsys(s.provider_id)
239
- )
240
-
241
- const redsysData = paymentSession?.data as Record<string, string> | undefined
242
-
243
- if (!redsysData?.formUrl || !redsysData?.merchantParams || !redsysData?.signature) {
244
- setErrorMessage("No se pudieron obtener los datos de pago de Redsys")
245
- setSubmitting(false)
246
- return
247
- }
248
-
249
- const cartRes = await completeCartWithoutRedirect()
250
- .catch((err) => {
251
- setErrorMessage(err.message)
252
- setSubmitting(false)
253
- return null
254
- })
255
-
256
- if (!cartRes || cartRes.type !== "order") {
257
- setErrorMessage(cartRes ? "Error al crear el pedido" : "")
258
- setSubmitting(false)
259
- return
260
- }
261
-
262
- // Store mapping between Redsys internal orderId and Medusa orderId
263
- // The callback page uses this cookie to resolve the real order
264
- const medusaOrderId = cartRes.order.id
265
- const redsysOrderId = redsysData.orderId || ""
266
- document.cookie = `redsys_map_${redsysOrderId}=${medusaOrderId}; path=/; max-age=600; SameSite=Lax`
267
-
268
- const form = document.createElement("form")
269
- form.method = "POST"
270
- form.action = redsysData.formUrl
271
-
272
- const fields: Record<string, string> = {
273
- Ds_SignatureVersion: redsysData.signatureVersion,
274
- Ds_MerchantParameters: redsysData.merchantParams,
275
- Ds_Signature: redsysData.signature,
276
- }
277
-
278
- Object.entries(fields).forEach(([name, value]) => {
279
- const input = document.createElement("input")
280
- input.type = "hidden"
281
- input.name = name
282
- input.value = value
283
- form.appendChild(input)
284
- })
285
-
286
- document.body.appendChild(form)
287
- form.submit()
288
- }
289
-
290
- return (
291
- <>
292
- <Button
293
- disabled={notReady || submitting}
294
- isLoading={submitting}
295
- onClick={handlePayment}
296
- size="large"
297
- data-testid={dataTestId}
298
- >
299
- Place order
300
- </Button>
301
- <ErrorMessage
302
- error={errorMessage}
303
- data-testid="redsys-payment-error-message"
304
- />
305
- </>
306
- )
307
- }
308
- ```
309
-
310
- ### 4. `src/app/checkout/redsys-callback/page.tsx` — Callback page (new file)
311
-
312
- Create the page Redsys redirects to after payment. The `orderId` query param from Redsys contains the **internal Redsys order ID**, not the Medusa order ID. Use the cookie set in step 3 to resolve the real Medusa order and redirect to the confirmation page:
313
-
314
- ```tsx
315
- import { retrieveOrder } from "@lib/data/orders"
316
- import { cookies } from "next/headers"
317
- import { Metadata } from "next"
318
- import { redirect } from "next/navigation"
319
-
320
- export const metadata: Metadata = {
321
- title: "Resultado del pago",
322
- description: "Resultado de la operación con Redsys",
323
- }
324
-
325
- type Props = {
326
- searchParams: Promise<{ [key: string]: string | undefined }>
327
- }
328
-
329
- export default async function RedsysCallbackPage(props: Props) {
330
- const searchParams = await props.searchParams
331
-
332
- const isError = searchParams.error === "1"
333
- const redsysOrderId = searchParams.orderId
334
-
335
- if (isError) {
336
- return (
337
- <div className="flex flex-col items-center justify-center min-h-[50vh] gap-4 p-8">
338
- <h1 className="text-2xl font-bold text-red-600">Pago no completado</h1>
339
- <p className="text-gray-600">
340
- La operación no se ha completado correctamente.
341
- </p>
342
- <a href="/" className="mt-4 px-6 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
343
- Volver a la tienda
344
- </a>
345
- </div>
346
- )
347
- }
348
-
349
- if (redsysOrderId) {
350
- // Resolve the Medusa order ID from the cookie set by RedsysPaymentButton
351
- const cookieStore = await cookies()
352
- const medusaOrderId = cookieStore.get(`redsys_map_${redsysOrderId}`)?.value
353
- const orderId = medusaOrderId || redsysOrderId
354
-
355
- try {
356
- const order = await retrieveOrder(orderId)
357
- if (order) {
358
- const countryCode = order.shipping_address?.country_code?.toLowerCase() || "dk"
359
- return redirect(`/${countryCode}/order/${orderId}/confirmed`)
360
- }
361
- } catch {
362
- // Order not found, show success anyway
363
- }
364
- }
365
-
366
- return (
367
- <div className="flex flex-col items-center justify-center min-h-[50vh] gap-4 p-8">
368
- <h1 className="text-2xl font-bold text-green-600">Pago procesado</h1>
369
- <p className="text-gray-600">Tu pago ha sido procesado correctamente.</p>
370
- <a href="/" className="mt-4 px-6 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
371
- Volver a la tienda
372
- </a>
373
- </div>
374
- )
375
- }
376
- ```
377
-
378
- ### 5. `src/middleware.ts` — Bypass region redirect
379
-
380
- If your storefront uses middleware to enforce region/country code prefixes in URLs (as the default Medusa Next.js storefront does), add a bypass so `/checkout/redsys-callback` is not redirected. Add this early in the `middleware` function:
381
-
382
- ```ts
383
- // Redsys callback URL — bypass region redirect
384
- if (request.nextUrl.pathname.startsWith("/checkout/redsys-callback")) {
385
- return NextResponse.next()
386
- }
387
- ```
388
-
389
- ### 6. `medusa-config.ts` — CORS
390
-
391
- Ensure your storefront domain is allowed in CORS:
392
-
393
- ```ts
394
- projectConfig: {
395
- http: {
396
- storeCors: "http://localhost:8000,https://your-store.com",
397
- },
398
- }
399
- ```
400
-
401
- ### Session Data Reference
402
-
403
- The payment session `data` field returned by `initiatePayment`:
404
-
405
- ```ts
406
- {
407
- orderId: "1234ABCD5678",
408
- amount: "2550",
409
- currency: "978",
410
- status: "pending",
411
- transactionType: "0",
412
- merchantParams: "base64...", // Base64-encoded merchant parameters
413
- signature: "hmac...", // HMAC-SHA256 signature
414
- signatureVersion: "HMAC_SHA256_V1",
415
- formUrl: "https://sis-t.redsys.es:25443/sis/realizarPago"
416
- }
417
- ```
418
-
419
- These fields are used in step 3 to build the auto-submitting redirect form.
420
-
421
- ### Webhook
422
-
423
- Medusa automatically exposes a webhook endpoint for the Redsys provider at:
424
-
425
- ```
426
- /hooks/payment/redsys_redsys
427
- ```
428
-
429
- For local development with sandbox, you must expose your backend to the internet (e.g., via [ngrok](https://ngrok.com/)) so Redsys can reach the webhook. Set `notificationUrl` to the ngrok URL.
430
-
431
- **Important**: Redsys sends the notification to `notificationUrl` but the signature verification and payment status update happens through the Medusa webhook handler — make sure `notificationUrl` points to the same endpoint or forward notifications accordingly.
432
-
433
- ## Test Cards (Sandbox)
434
-
435
- | Card Number | Brand | Behavior |
436
- |---|---|---|
437
- | 4548810000000003 | VISA | 3DS v2 approved |
438
- | 5576441563045037 | Mastercard | 3DS v2 approved |
439
- | 4548814479727229 | VISA | 3DS frictionless |
440
- | 4548817212493017 | VISA | 3DS challenge |
441
- | Any + CVV 999 | Any | Payment declined |
442
-
443
- ## Transaction Types
444
-
445
- | Code | Type | Description |
446
- |---|---|---|
447
- | `"0"` | Payment | Authorization + immediate capture (default) |
448
- | `"1"` | Pre-authorization | Reserve funds only |
449
- | `"2"` | Confirmation | Capture pre-authorized funds |
450
- | `"3"` | Refund | Full or partial refund |
451
- | `"9"` | Cancellation | Cancel/void a transaction |
452
-
453
- ## Security
454
-
455
- - **Never log PAN, CVV, or the secret key**. The provider strips sensitive fields from log output.
456
- - **Always validate signatures server-side**. `getWebhookActionAndData()` uses `redsys-easy`'s `processRestNotification()` for HMAC-SHA256 verification.
457
- - **Use HTTPS** for all communication with Redsys.
458
- - **Do not trust client-side payment data**. The webhook with signature verification is the source of truth.
459
- - The redirect flow keeps you out of PCI scope — card data is handled by Redsys' secure page.
460
-
461
- ## Currency Support
462
-
463
- The plugin includes built-in numeric currency codes for all major currencies. If your currency is not listed, it defaults to EUR (`978`). See `src/types.ts` for the full list.
464
-
465
- ## Development
466
-
467
- ```bash
468
- # Install dependencies
469
- npm install
470
-
471
- # Build
472
- npm run build
473
-
474
- # Run tests
475
- npm test
476
-
477
- # Watch mode (for local plugin development)
478
- npm run dev
479
- ```
480
-
481
- ### Local Testing with a Medusa Project
482
-
483
- ```bash
484
- # From your plugin directory
485
- npm run dev
486
-
487
- # In your Medusa project directory:
488
- npx medusa plugin:add ../path-to/medusa-payment-redsys
489
- ```
490
-
491
- ## License
492
-
493
- MIT — see [LICENSE](./LICENSE) file for details.
494
-
495
- ## Support
496
-
497
- For issues and questions, please open an issue on [GitHub](https://github.com/juansoler/medusa-payment-redsys/issues).
1
+ # @jsm406/medusa-plugin-redsys
2
+
3
+ Redsys / Sermepa TPV Virtual payment provider plugin for [MedusaJS v2](https://medusajs.com/).
4
+
5
+ This plugin enables payment processing through Redsys' hosted payment page (TPV Virtual) via redirect flow. Customers are redirected to the Redsys secure payment page to complete their transaction.
6
+
7
+ > **Production-proven**: This plugin is derived from a live production Medusa store processing real Redsys payments.
8
+
9
+ ## Features
10
+
11
+ - Redsys hosted payment page / TPV Virtual redirect flow
12
+ - Sandbox and production environments
13
+ - One-step payment (immediate capture) and two-step payment (pre-authorization + capture)
14
+ - Full and partial refunds via Redsys API
15
+ - Payment cancellation
16
+ - Webhook handling with HMAC-SHA256 signature verification
17
+ - Spanish error messages for Redsys response codes
18
+ - Zero PCI scope — card data is handled by Redsys' secure page
19
+
20
+ ## Prerequisites
21
+
22
+ - MedusaJS v2.13.0 or later
23
+ - Node.js v20 or later
24
+ - A [Redsys merchant account](https://comercios.redsys.es/) (or sandbox test credentials)
25
+ - `redsys-easy` v5.3.0+ (installed automatically as a dependency)
26
+
27
+ ## Installation
28
+
29
+ ```bash
30
+ npm install @jsm406/medusa-plugin-redsys
31
+ # or
32
+ yarn add @jsm406/medusa-plugin-redsys
33
+ # or
34
+ pnpm add @jsm406/medusa-plugin-redsys
35
+ ```
36
+
37
+ ## Configuration
38
+
39
+ ### Environment Variables
40
+
41
+ Add the following to your `.env` file:
42
+
43
+ ```env
44
+ REDSYS_SECRET_KEY=sq7Hj....
45
+ REDSYS_MERCHANT_CODE=999008881
46
+ REDSYS_TERMINAL=001
47
+ REDSYS_ENVIRONMENT=sandbox
48
+ REDSYS_NOTIFICATION_URL=https://your-api.com/hooks/payment/redsys_redsys
49
+ REDSYS_SUCCESS_URL=https://your-store.com/checkout/redsys-callback
50
+ REDSYS_ERROR_URL=https://your-store.com/checkout/redsys-callback?error=1
51
+ ```
52
+
53
+ For sandbox testing, use the following test credentials from Redsys:
54
+
55
+ ```
56
+ Merchant Code: 999008881
57
+ Terminal: 001
58
+ Secret Key: sq7Hj.......
59
+ Environment: sandbox
60
+ ```
61
+
62
+ ### Medusa Configuration
63
+
64
+ In your `medusa-config.ts`:
65
+
66
+ ```ts
67
+ import { defineConfig } from "@medusajs/framework/config"
68
+
69
+ export default defineConfig({
70
+ modules: [
71
+ {
72
+ resolve: "@medusajs/medusa/payment",
73
+ options: {
74
+ providers: [
75
+ {
76
+ resolve: "@jsm406/medusa-plugin-redsys/providers/redsys",
77
+ id: "redsys",
78
+ options: {
79
+ secretKey: process.env.REDSYS_SECRET_KEY,
80
+ merchantCode: process.env.REDSYS_MERCHANT_CODE,
81
+ terminal: process.env.REDSYS_TERMINAL || "001",
82
+ environment:
83
+ process.env.REDSYS_ENVIRONMENT || "sandbox",
84
+ notificationUrl:
85
+ process.env.REDSYS_NOTIFICATION_URL,
86
+ successUrl: process.env.REDSYS_SUCCESS_URL,
87
+ errorUrl: process.env.REDSYS_ERROR_URL,
88
+ transactionType: "0", // "0" = immediate capture, "1" = pre-authorization
89
+ },
90
+ },
91
+ ],
92
+ },
93
+ },
94
+ ],
95
+ })
96
+ ```
97
+
98
+ ### Enable in Region
99
+
100
+ Enable the Redsys provider in your Medusa admin panel under **Settings > Regions** and select **Redsys** as a payment provider.
101
+
102
+ The provider ID will be:
103
+
104
+ ```
105
+ pp_redsys_redsys
106
+ ```
107
+
108
+ ## Options
109
+
110
+ | Option | Type | Required | Default | Description |
111
+ |---|---|---|---|---|
112
+ | `secretKey` | string | Yes | — | Redsys HMAC-SHA256 secret key |
113
+ | `merchantCode` | string | Yes | — | Redsys merchant code (FUC) |
114
+ | `terminal` | string | No | `"001"` | Terminal number |
115
+ | `environment` | string | No | `"sandbox"` | `"sandbox"` or `"production"` |
116
+ | `notificationUrl` | string | No | — | Webhook URL for Redsys to POST transaction results |
117
+ | `successUrl` | string | No | — | URL to redirect after successful payment (URLOK) |
118
+ | `errorUrl` | string | No | — | URL to redirect after failed payment (URLKO) |
119
+ | `transactionType` | string | No | `"0"` | `"0"` = immediate capture, `"1"` = pre-authorization |
120
+
121
+ ## Payment Flow
122
+
123
+ 1. Customer selects **Redsys** as payment method
124
+ 2. `initiatePayment()` creates a signed redirect form with Redsys merchant parameters
125
+ 3. Customer clicks "Place Order" → storefront calls `cart.complete()` to create the order, stores a cookie mapping the Redsys internal order ID to the Medusa order ID, then auto-submits the redirect form to Redsys TPV
126
+ 4. Customer completes payment on the Redsys hosted payment page
127
+ 5. Redsys sends a **webhook notification** to `{backendUrl}/hooks/payment/redsys_redsys`
128
+ 6. `getWebhookActionAndData()` validates the HMAC-SHA256 signature and updates the payment status
129
+ 7. Redsys redirects the customer's browser to `successUrl` or `errorUrl` with the Redsys order ID as a query parameter
130
+ 8. Storefront callback page reads the sessionStorage to resolve the Medusa order ID and redirects to the order confirmation page
131
+
132
+ ### Important: authorizePayment Behavior
133
+
134
+ This plugin's `authorizePayment` returns `AUTHORIZED` for sessions with status `"pending"` **and** `"authorized"`. This is intentional for the redirect flow: the real authorization happens on Redsys TPV and is confirmed via webhook. Without this, `cart.complete()` would fail with a 400 error because Medusa requires the payment session to be authorized before completing the cart.
135
+
136
+ ### ID Mapping (Redsys → Medusa)
137
+
138
+ The plugin generates a 12-character alphanumeric `orderId` (e.g. `97727XYIWRRF`) used as Redsys' merchant order reference. When the order is completed via `cart.complete()`, Medusa generates its own order ID (e.g. `order_01KR3B4X...`). These are **different IDs**.
139
+
140
+ The callback URL from Redsys only contains the Redsys order ID, not the Medusa order ID. To bridge this gap, the storefront stores the mapping `redsys_map_{redsysOrderId}` → `{ medusaOrderId, countryCode }` in `sessionStorage` before redirecting to the TPV. The callback page reads this value to redirect to the correct order confirmation page.
141
+
142
+ ## Storefront Integration
143
+
144
+ Redsys is a **redirect-based** payment method (no card input in your storefront — the customer enters card data on Redsys' secure TPV). You must adapt your Medusa Next.js storefront with the changes below.
145
+
146
+ ### 1. `src/lib/constants.tsx` — Register the payment method
147
+
148
+ Add Redsys to the payment info map and add a helper function:
149
+
150
+ ```tsx
151
+ // Inside paymentInfoMap, add:
152
+ pp_redsys_redsys: {
153
+ title: "Credit / Debit Card",
154
+ icon: <CreditCard />,
155
+ },
156
+
157
+ // Add helper function:
158
+ export const isRedsys = (providerId?: string) => {
159
+ return providerId?.startsWith("pp_redsys_")
160
+ }
161
+ ```
162
+
163
+ ### 2. `src/lib/data/cart.ts` — Add order completion without redirect
164
+
165
+ Add a `completeCartWithoutRedirect` function. The standard `placeOrder` does a `redirect()` (server-side), but Redsys needs to redirect the browser to the TPV instead. This function completes the cart, creates the order, but returns the result so the client can handle the TPV redirect:
166
+
167
+ ```ts
168
+ export async function completeCartWithoutRedirect(cartId?: string) {
169
+ const id = cartId || (await getCartId())
170
+
171
+ if (!id) {
172
+ throw new Error("No existing cart found when completing cart")
173
+ }
174
+
175
+ const headers = {
176
+ ...(await getAuthHeaders()),
177
+ }
178
+
179
+ const cartRes = await sdk.store.cart
180
+ .complete(id, {}, headers)
181
+ .then(async (cartRes) => {
182
+ const cartCacheTag = await getCacheTag("carts")
183
+ revalidateTag(cartCacheTag)
184
+ return cartRes
185
+ })
186
+ .catch(medusaError)
187
+
188
+ if (cartRes?.type === "order") {
189
+ const orderCacheTag = await getCacheTag("orders")
190
+ revalidateTag(orderCacheTag)
191
+ removeCartId()
192
+ }
193
+
194
+ return cartRes
195
+ }
196
+ ```
197
+
198
+ ### 3. `src/modules/checkout/components/payment-button/index.tsx` — Redsys payment button
199
+
200
+ Add a `RedsysPaymentButton` component that:
201
+ 1. Reads the payment session data (formUrl, merchantParams, signature) from the cart
202
+ 2. Calls `completeCartWithoutRedirect()` to create the order
203
+ 3. Stores the Redsys Medusa order ID mapping in `sessionStorage` (with country code), then builds and auto-submits a `<form>` to Redsys' TPV
204
+
205
+ ```tsx
206
+ // Add import:
207
+ import { isManual, isRedsys, isStripeLike } from "@lib/constants"
208
+ import { completeCartWithoutRedirect, placeOrder } from "@lib/data/cart"
209
+
210
+ // Add case in PaymentButton's switch:
211
+ case isRedsys(paymentSession?.provider_id):
212
+ return (
213
+ <RedsysPaymentButton
214
+ notReady={notReady}
215
+ cart={cart}
216
+ data-testid={dataTestId}
217
+ />
218
+ )
219
+
220
+ // Add the component:
221
+ const RedsysPaymentButton = ({
222
+ cart,
223
+ notReady,
224
+ "data-testid": dataTestId,
225
+ }: {
226
+ cart: HttpTypes.StoreCart
227
+ notReady: boolean
228
+ "data-testid"?: string
229
+ }) => {
230
+ const [submitting, setSubmitting] = useState(false)
231
+ const [errorMessage, setErrorMessage] = useState<string | null>(null)
232
+
233
+ const handlePayment = async () => {
234
+ setSubmitting(true)
235
+
236
+ const paymentSession = cart.payment_collection?.payment_sessions?.find(
237
+ (s) => s.status === "pending" && isRedsys(s.provider_id)
238
+ )
239
+
240
+ const redsysData = paymentSession?.data as Record<string, string> | undefined
241
+
242
+ if (!redsysData?.formUrl || !redsysData?.merchantParams || !redsysData?.signature) {
243
+ setErrorMessage("No se pudieron obtener los datos de pago de Redsys")
244
+ setSubmitting(false)
245
+ return
246
+ }
247
+
248
+ const cartRes = await completeCartWithoutRedirect()
249
+ .catch((err) => {
250
+ setErrorMessage(err.message)
251
+ setSubmitting(false)
252
+ return null
253
+ })
254
+
255
+ if (!cartRes || cartRes.type !== "order") {
256
+ setErrorMessage(cartRes ? "Error al crear el pedido" : "")
257
+ setSubmitting(false)
258
+ return
259
+ }
260
+
261
+ // Store Redsys ID → Medusa ID mapping + country code in sessionStorage.
262
+ // The callback page reads this to redirect to the order confirmation.
263
+ const medusaOrderId = cartRes.order.id
264
+ const redsysOrderId = redsysData.orderId || ""
265
+ const countryCode = cart.shipping_address?.country_code?.toLowerCase() || "dk"
266
+ sessionStorage.setItem(
267
+ `redsys_map_${redsysOrderId}`,
268
+ JSON.stringify({ medusaOrderId, countryCode })
269
+ )
270
+
271
+ const form = document.createElement("form")
272
+ form.method = "POST"
273
+ form.action = redsysData.formUrl
274
+
275
+ const fields: Record<string, string> = {
276
+ Ds_SignatureVersion: redsysData.signatureVersion,
277
+ Ds_MerchantParameters: redsysData.merchantParams,
278
+ Ds_Signature: redsysData.signature,
279
+ }
280
+
281
+ Object.entries(fields).forEach(([name, value]) => {
282
+ const input = document.createElement("input")
283
+ input.type = "hidden"
284
+ input.name = name
285
+ input.value = value
286
+ form.appendChild(input)
287
+ })
288
+
289
+ document.body.appendChild(form)
290
+ form.submit()
291
+ }
292
+
293
+ return (
294
+ <>
295
+ <Button
296
+ disabled={notReady || submitting}
297
+ isLoading={submitting}
298
+ onClick={handlePayment}
299
+ size="large"
300
+ data-testid={dataTestId}
301
+ >
302
+ Place order
303
+ </Button>
304
+ <ErrorMessage
305
+ error={errorMessage}
306
+ data-testid="redsys-payment-error-message"
307
+ />
308
+ </>
309
+ )
310
+ }
311
+ ```
312
+
313
+ ### 4. `src/app/checkout/redsys-callback/page.tsx` — Callback page (new file)
314
+
315
+ Create a **client component** page that Redsys redirects to after payment. It reads the `orderId` query param (Redsys internal ID), looks up the real Medusa order ID from `sessionStorage`, and redirects to the order confirmation page:
316
+
317
+ ```tsx
318
+ "use client"
319
+
320
+ import { useRouter, useSearchParams } from "next/navigation"
321
+ import { useEffect, useState } from "react"
322
+
323
+ export default function RedsysCallbackPage() {
324
+ const searchParams = useSearchParams()
325
+ const router = useRouter()
326
+ const [status, setStatus] = useState<"loading" | "error" | "success">("loading")
327
+
328
+ const isError = searchParams?.get("error") === "1"
329
+ const redsysOrderId = searchParams?.get("orderId")
330
+
331
+ useEffect(() => {
332
+ if (isError) {
333
+ setStatus("error")
334
+ return
335
+ }
336
+
337
+ if (!redsysOrderId) {
338
+ setStatus("success")
339
+ return
340
+ }
341
+
342
+ const stored = sessionStorage.getItem(`redsys_map_${redsysOrderId}`)
343
+
344
+ if (stored) {
345
+ let orderData: { medusaOrderId: string; countryCode: string }
346
+ try {
347
+ orderData = JSON.parse(stored)
348
+ } catch {
349
+ orderData = { medusaOrderId: stored, countryCode: "dk" }
350
+ }
351
+ sessionStorage.removeItem(`redsys_map_${redsysOrderId}`)
352
+ router.replace(
353
+ `/${orderData.countryCode}/order/${orderData.medusaOrderId}/confirmed`
354
+ )
355
+ return
356
+ }
357
+
358
+ setStatus("success")
359
+ }, [isError, redsysOrderId, router])
360
+
361
+ if (status === "loading") {
362
+ return (
363
+ <div className="flex flex-col items-center justify-center min-h-[50vh] gap-4 p-8">
364
+ <p className="text-gray-600">Procesando pago...</p>
365
+ </div>
366
+ )
367
+ }
368
+
369
+ if (status === "error") {
370
+ return (
371
+ <div className="flex flex-col items-center justify-center min-h-[50vh] gap-4 p-8">
372
+ <h1 className="text-2xl font-bold text-red-600">Pago no completado</h1>
373
+ <p className="text-gray-600">
374
+ La operación no se ha completado correctamente.
375
+ </p>
376
+ <a href="/" className="mt-4 px-6 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
377
+ Volver a la tienda
378
+ </a>
379
+ </div>
380
+ )
381
+ }
382
+
383
+ return (
384
+ <div className="flex flex-col items-center justify-center min-h-[50vh] gap-4 p-8">
385
+ <h1 className="text-2xl font-bold text-green-600">Pago procesado</h1>
386
+ <p className="text-gray-600">Tu pago ha sido procesado correctamente.</p>
387
+ <a href="/" className="mt-4 px-6 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
388
+ Volver a la tienda
389
+ </a>
390
+ </div>
391
+ )
392
+ }
393
+ ```
394
+
395
+ ### 5. `src/middleware.ts` — Bypass region redirect
396
+
397
+ If your storefront uses middleware to enforce region/country code prefixes in URLs (as the default Medusa Next.js storefront does), add a bypass so `/checkout/redsys-callback` is not redirected. Add this early in the `middleware` function:
398
+
399
+ ```ts
400
+ // Redsys callback URL — bypass region redirect
401
+ if (request.nextUrl.pathname.startsWith("/checkout/redsys-callback")) {
402
+ return NextResponse.next()
403
+ }
404
+ ```
405
+
406
+ ### 6. `medusa-config.ts` — CORS
407
+
408
+ Ensure your storefront domain is allowed in CORS:
409
+
410
+ ```ts
411
+ projectConfig: {
412
+ http: {
413
+ storeCors: "http://localhost:8000,https://your-store.com",
414
+ },
415
+ }
416
+ ```
417
+
418
+ ### Session Data Reference
419
+
420
+ The payment session `data` field returned by `initiatePayment`:
421
+
422
+ ```ts
423
+ {
424
+ orderId: "1234ABCD5678",
425
+ amount: "2550",
426
+ currency: "978",
427
+ status: "pending",
428
+ transactionType: "0",
429
+ merchantParams: "base64...", // Base64-encoded merchant parameters
430
+ signature: "hmac...", // HMAC-SHA256 signature
431
+ signatureVersion: "HMAC_SHA256_V1",
432
+ formUrl: "https://sis-t.redsys.es:25443/sis/realizarPago"
433
+ }
434
+ ```
435
+
436
+ These fields are used in step 3 to build the auto-submitting redirect form.
437
+
438
+ ### Webhook
439
+
440
+ Medusa automatically exposes a webhook endpoint for the Redsys provider at:
441
+
442
+ ```
443
+ /hooks/payment/redsys_redsys
444
+ ```
445
+
446
+ For local development with sandbox, you must expose your backend to the internet (e.g., via [ngrok](https://ngrok.com/)) so Redsys can reach the webhook. Set `notificationUrl` to the ngrok URL.
447
+
448
+ **Important**: Redsys sends the notification to `notificationUrl` but the signature verification and payment status update happens through the Medusa webhook handler — make sure `notificationUrl` points to the same endpoint or forward notifications accordingly.
449
+
450
+ ## Test Cards (Sandbox)
451
+
452
+ | Card Number | Brand | Behavior |
453
+ |---|---|---|
454
+ | 4548810000000003 | VISA | 3DS v2 approved |
455
+ | 5576441563045037 | Mastercard | 3DS v2 approved |
456
+ | 4548814479727229 | VISA | 3DS frictionless |
457
+ | 4548817212493017 | VISA | 3DS challenge |
458
+ | Any + CVV 999 | Any | Payment declined |
459
+
460
+ ## Transaction Types
461
+
462
+ | Code | Type | Description |
463
+ |---|---|---|
464
+ | `"0"` | Payment | Authorization + immediate capture (default) |
465
+ | `"1"` | Pre-authorization | Reserve funds only |
466
+ | `"2"` | Confirmation | Capture pre-authorized funds |
467
+ | `"3"` | Refund | Full or partial refund |
468
+ | `"9"` | Cancellation | Cancel/void a transaction |
469
+
470
+ ## Security
471
+
472
+ - **Never log PAN, CVV, or the secret key**. The provider strips sensitive fields from log output.
473
+ - **Always validate signatures server-side**. `getWebhookActionAndData()` uses `redsys-easy`'s `processRestNotification()` for HMAC-SHA256 verification.
474
+ - **Use HTTPS** for all communication with Redsys.
475
+ - **Do not trust client-side payment data**. The webhook with signature verification is the source of truth.
476
+ - The redirect flow keeps you out of PCI scope — card data is handled by Redsys' secure page.
477
+
478
+ ## Currency Support
479
+
480
+ The plugin includes built-in numeric currency codes for all major currencies. If your currency is not listed, it defaults to EUR (`978`). See `src/types.ts` for the full list.
481
+
482
+ ## Development
483
+
484
+ ```bash
485
+ # Install dependencies
486
+ npm install
487
+
488
+ # Build
489
+ npm run build
490
+
491
+ # Run tests
492
+ npm test
493
+
494
+ # Watch mode (for local plugin development)
495
+ npm run dev
496
+ ```
497
+
498
+ ### Local Testing with a Medusa Project
499
+
500
+ ```bash
501
+ # From your plugin directory
502
+ npm run dev
503
+
504
+ # In your Medusa project directory:
505
+ npx medusa plugin:add ../path-to/@jsm406/medusa-plugin-redsys
506
+ ```
507
+
508
+ ## License
509
+
510
+ MIT — see [LICENSE](./LICENSE) file for details.
511
+
512
+ ## Support
513
+
514
+ For issues and questions, please open an issue on [GitHub](https://github.com/juansoler/medusa-plugin-redsys/issues).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsm406/medusa-plugin-redsys",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Redsys / Sermepa TPV Virtual payment provider plugin for MedusaJS v2",
5
5
  "author": "Juan Soler Márquez",
6
6
  "license": "MIT",