feat(payments): end-to-end Redsys hosted-redirect for Spain - #365
Conversation
Wire booking deposit and folio authorize to submitRedirectNextAction when PAYMENT_GATEWAY=redsys, and add a credentials form on the Redsys integrations row (FUC, terminal, secret, environment). Co-authored-by: telivity-otaip <telivity-otaip@users.noreply.github.com>
Shared client helper that auto-submits the PSP POST form returned as nextAction from authorize/book. Co-authored-by: telivity-otaip <telivity-otaip@users.noreply.github.com>
Implement HMAC signing, authorize redirect nextAction, REST capture/void/refund, per-property FUC credential resolution, signed MerchantURL webhook updates, and client-config exposure so Spain desk and booking flows can collect card money. Co-authored-by: telivity-otaip <telivity-otaip@users.noreply.github.com>
Pass redirect return URLs through booking-engine authorize, skip auto-confirm while checkout is pending, merge/mask Redsys secrets on Integrations upsert, and keep raw secrets available to the credentials resolver. Co-authored-by: telivity-otaip <telivity-otaip@users.noreply.github.com>
Persist booking confirmation across hosted checkout, surface Folio return toasts, and ship demo/docs/env examples for sandbox go-live. Co-authored-by: telivity-otaip <telivity-otaip@users.noreply.github.com>
Dashboard ESLint does not define react-hooks/exhaustive-deps, so the disable comment failed CI Lint & Type Check with a hard error. Co-authored-by: telivity-otaip <telivity-otaip@users.noreply.github.com>
PaymentService now injects ConfigService and RedsysCredentialsService; update Nest TestingModules and the legacy constructor seam so apps/api vitest can resolve the service again. Co-authored-by: telivity-otaip <telivity-otaip@users.noreply.github.com>
Constructor gained runtimeConfig for Redsys gateway resolution; unit and postgres pricing-lock helpers still used the old arity and shifted mocks. Co-authored-by: telivity-otaip <telivity-otaip@users.noreply.github.com>
CI reported 2258 passed tests across 272 files; published counts were still 2249/269. Co-authored-by: telivity-otaip <telivity-otaip@users.noreply.github.com>
agustinjch
left a comment
There was a problem hiding this comment.
I exercised the booking flow against the real Redsys sandbox and am requesting changes for three reproduced correctness failures:
- Booking return cannot recover the checkout. The generated OK/KO URLs return to origin-root routes, while the booking app uses an in-memory router and loses its state on the full-page round trip. A pathname-only correction is insufficient: the return must bootstrap from a durable, opaque booking/payment reference.
- A deposit is recorded before authorization.
recordDeposit()runs as soon as Redsys returns a hosted-checkout action, while the payment is still pending. Cancelling or abandoning checkout leaves an actionable deposit ledger entry for money that was never authorized. - Verified success does not complete auto-confirmation. Booking creation skips confirmation while redirect is pending, but the signed callback updates only the payment. With auto-confirm enabled, the payment becomes authorized while the reservation remains pending.
The browser return must be treated only as navigation. A signature-verified provider result must be the authority for payment state, deposit creation, and reservation confirmation, with an idempotent finalizer for duplicate/out-of-order callback and return delivery.
Non-blocking follow-up: Redsys inSite could provide a smoother embedded checkout, but it is a different REST/3DS integration and does not remove the need for the authoritative lifecycle fix above. I recommend evaluating it separately after this hosted-redirect path is made correct.
Browser return is navigation only. Skip deposit ledger writes on hosted redirect authorize, recover MemoryRouter state via haip_checkout token, and run an idempotent finalizer from the MerchantURL webhook for payment authorization, deposit creation, and booking-engine auto-confirm. Co-authored-by: telivity-otaip <telivity-otaip@users.noreply.github.com>
Co-authored-by: telivity-otaip <telivity-otaip@users.noreply.github.com>
|
The requested remediation is implemented and independently reviewed. The four reviewed commits have now been applied directly to this PR, ending at The superseded non-atomic finalizer was reverted before applying them, so the PR contains one finalization path. The current PR tree is byte-for-byte identical to the independently reviewed tree. The temporary helper PR #367 is therefore obsolete and has been closed. Commits to bring onto this PR head, in order:
Real EUR sandbox verification on the first three commits covered authorization and provider cancellation:
After the final security/lifecycle commit, the tracked-tree run passed 2,392 tests across 280 files, including the PostgreSQL callback and encrypted-credential suites. An independent final review found all blocking findings addressed and no new breakage. Build and typecheck pass; lint has zero errors (existing warnings remain). Deployment prerequisite: provision the documented credential-encryption key ring and run the idempotent Redsys credential backfill before enabling payment traffic. Migrations 0024–0026 must also be applied before the API/widget rollout. The embedded inSite checkout remains deliberately separate and non-blocking: #366 tracks merchant activation, multi-tenant domain registration/CSP, iframe choice, idOper lifecycle, embedded EMV 3-D Secure, accessibility, fallback, and reuse of the same authoritative finalizer. |
agustinjch
left a comment
There was a problem hiding this comment.
Re-reviewed after the four remediation commits were applied directly. The current head tree exactly matches the independently reviewed implementation. Real EUR sandbox authorization/cancellation and duplicate signed-callback replay passed; the tracked suite reports 2,392 passing tests, and all current GitHub checks are green. Ready to merge after the documented deployment prerequisite is scheduled: provision the credential-encryption key ring, run the idempotent Redsys credential backfill, and apply migrations 0024–0026 before payment traffic.
|
Gracias hermano. |
Summary
Completes the Redsys (Spanish TPV) hosted-redirect payment path end-to-end.
Status
Approved by Agus after re-review. Head
2bc2c61matches his independently reviewed tip (faaa96f). EUR sandbox auth/cancel + duplicate signed-callback replay verified; CI green (5/5).Remediation (on PR head)
Deploy before payment traffic
Schedule before merge/enablement:
Out of scope
Embedded inSite checkout — tracked in #366.
Test plan
2bc2c61