falta vista de pagos

This commit is contained in:
2025-11-04 14:40:18 +01:00
parent f528809c07
commit 7516e9e91e
24 changed files with 276 additions and 442 deletions

View File

@ -10,9 +10,7 @@ import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.UUID;
import org.springframework.transaction.annotation.Transactional;
@Controller
@RequestMapping("/pagos/redsys")
@ -100,7 +98,6 @@ public class RedsysController {
// integraciones ni lo usan)
@PostMapping(value = "/ok", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@ResponseBody
@jakarta.transaction.Transactional
public ResponseEntity<String> okPost(@RequestParam("Ds_Signature") String signature,
@RequestParam("Ds_MerchantParameters") String merchantParameters) {
try {
@ -121,14 +118,26 @@ public class RedsysController {
@PostMapping(value = "/ko", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@ResponseBody
public ResponseEntity<String> koPost(@RequestParam Map<String, String> form) {
// Podrías loguear 'form' si quieres ver qué manda Redsys
return ResponseEntity.ok("<h2>Pago cancelado o rechazado</h2><a href=\"/checkout\">Volver</a>");
public ResponseEntity<String> koPost(
@RequestParam("Ds_Signature") String signature,
@RequestParam("Ds_MerchantParameters") String merchantParameters) {
try {
// Procesamos la notificación IGUAL que en /ok y /notify
paymentService.handleRedsysNotification(signature, merchantParameters);
// Mensaje para el usuario (pago cancelado/rechazado)
String html = "<h2>Pago cancelado o rechazado</h2><a href=\"/checkout\">Volver</a>";
return ResponseEntity.ok(html);
} catch (Exception e) {
// Si algo falla al validar/procesar, lo mostramos (útil en entorno de pruebas)
String html = "<h2>Error procesando notificación KO</h2><pre>" + e.getMessage() + "</pre>";
return ResponseEntity.badRequest().body(html);
}
}
@PostMapping(value = "/notify", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@ResponseBody
@jakarta.transaction.Transactional
public String notifyRedsys(@RequestParam("Ds_Signature") String signature,
@RequestParam("Ds_MerchantParameters") String merchantParameters) {
try {

View File

@ -105,27 +105,31 @@ public class RedsysService {
// ---------- STEP 4: Validar notificación ----------
public RedsysNotification validateAndParseNotification(String dsSignature, String dsMerchantParametersB64)
throws Exception {
// 1) Decodificamos a mapa solo para leer campos
Map<String, Object> mp = decodeMerchantParametersToMap(dsMerchantParametersB64);
ApiMacSha256 api = new ApiMacSha256();
// 1) Decodificar Ds_MerchantParameters usando la librería oficial
String json = api.decodeMerchantParameters(dsMerchantParametersB64);
// 2) Convertir a Map para tu modelo
Map<String, Object> mp = MAPPER.readValue(json, new TypeReference<>() {
});
RedsysNotification notif = new RedsysNotification(mp);
if (notif.order == null || notif.order.isBlank()) {
System.out.println("### ATENCIÓN: Ds_Order no viene en MerchantParameters");
throw new IllegalArgumentException("Falta Ds_Order en Ds_MerchantParameters");
}
// 2) Calculamos la firma esperada usando el B64 tal cual
ApiMacSha256 api = new ApiMacSha256();
// Esta línea es opcional para createMerchantSignatureNotif, pero no molesta:
api.setParameter("Ds_MerchantParameters", dsMerchantParametersB64);
// 3) Calcular firma esperada: clave comercio + MerchantParameters en B64
String expected = api.createMerchantSignatureNotif(
secretKeyBase64,
dsMerchantParametersB64 // 👈 AQUÍ va el B64, NO el JSON
secretKeyBase64, // 👈 La misma que usas para crear la firma del pago
dsMerchantParametersB64 // 👈 SIEMPRE el B64 tal cual llega de Redsys, sin tocar
);
// 3) Comparamos en constante time, normalizando Base64 URL-safe
// 4) Comparar firma Redsys vs firma calculada
if (!safeEqualsB64(dsSignature, expected)) {
System.out.println("Firma Redsys no válida");
System.out.println("### Firma Redsys no válida");
System.out.println("Ds_Signature (Redsys) = " + dsSignature);
System.out.println("Expected (local) = " + expected);
throw new SecurityException("Firma Redsys no válida");