mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-01-13 00:48:49 +00:00
151 lines
5.8 KiB
Java
151 lines
5.8 KiB
Java
package com.imprimelibros.erp.redsys;
|
|
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
|
|
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
|
|
|
|
import java.lang.reflect.Field;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.Base64;
|
|
import java.util.Map;
|
|
|
|
import static org.junit.jupiter.api.Assertions.*;
|
|
|
|
import sis.redsys.api.Signature;
|
|
|
|
/**
|
|
* Tests de integración "locales" contra tu RedsysService
|
|
* usando el jar 'apiSha512V2.jar' (sis.redsys.api.*).
|
|
*
|
|
* Para que el test sea significativo:
|
|
* - Define la clave en entorno: REDSYS_SECRET_B64=tu_clave_base64
|
|
* - O en propiedad de sistema: -Dredsys.secret.b64=tu_clave_base64
|
|
*/
|
|
public class RedsysServiceTest {
|
|
|
|
private RedsysService service;
|
|
|
|
private static String readSecretFromEnvOrProp() {
|
|
String env = System.getenv("REDSYS_SECRET_B64");
|
|
if (env != null && !env.isBlank())
|
|
return env.trim();
|
|
String prop = System.getProperty("redsys.secret.b64");
|
|
if (prop != null && !prop.isBlank())
|
|
return prop.trim();
|
|
return "";
|
|
}
|
|
|
|
private static void setPrivate(Object target, String field, Object value) {
|
|
try {
|
|
Field f = target.getClass().getDeclaredField(field);
|
|
f.setAccessible(true);
|
|
f.set(target, value);
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
@BeforeEach
|
|
void setup() {
|
|
service = new RedsysService();
|
|
|
|
// ---- Config mínima para el test ----
|
|
setPrivate(service, "merchantCode", "124760810"); // FUC de ejemplo (sandbox)
|
|
setPrivate(service, "terminal", "1");
|
|
setPrivate(service, "currency", "978");
|
|
setPrivate(service, "txType", "0");
|
|
setPrivate(service, "urlOk", "http://localhost:8080/pagos/redsys/ok");
|
|
setPrivate(service, "urlKo", "http://localhost:8080/pagos/redsys/ko");
|
|
setPrivate(service, "urlNotify", "http://localhost:8080/pagos/redsys/notify");
|
|
setPrivate(service, "env", "test");
|
|
|
|
// Clave: del entorno o propiedad. Si queda vacía, los tests se auto-saltan.
|
|
setPrivate(service, "secretKeyBase64", readSecretFromEnvOrProp());
|
|
}
|
|
|
|
private boolean secretPresent() {
|
|
try {
|
|
Field f = service.getClass().getDeclaredField("secretKeyBase64");
|
|
f.setAccessible(true);
|
|
String key = (String) f.get(service);
|
|
return key != null && !key.isBlank();
|
|
} catch (Exception e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void buildRedirectForm_generates_signature_and_params() throws Exception {
|
|
if (!secretPresent()) {
|
|
System.out.println("SKIP: define REDSYS_SECRET_B64 o -Dredsys.secret.b64 para ejecutar este test.");
|
|
return;
|
|
}
|
|
|
|
// Pedido de ejemplo (usa uno único por intento)
|
|
String order = "T" + System.currentTimeMillis(); // p.ej. T1699999999999
|
|
long amountCents = 1234L;
|
|
|
|
var req = new RedsysService.PaymentRequest(order, amountCents, "Test compra");
|
|
var form = service.buildRedirectForm(req);
|
|
|
|
assertNotNull(form);
|
|
assertEquals("HMAC_SHA512_V1", form.signatureVersion());
|
|
assertNotNull(form.merchantParameters());
|
|
assertNotNull(form.signature());
|
|
assertTrue(form.action().contains("sis"), "Action debe ser endpoint de Redsys");
|
|
|
|
// Decodificamos los parámetros para comprobar que incluyen nuestro pedido e
|
|
// importe
|
|
String json = new String(Base64.getDecoder().decode(form.merchantParameters()), StandardCharsets.UTF_8);
|
|
assertTrue(json.contains("\"DS_MERCHANT_ORDER\":\"" + order + "\""));
|
|
assertTrue(json.contains("\"DS_MERCHANT_AMOUNT\":\"" + amountCents + "\""));
|
|
|
|
// Recomputamos firma con el mismo jar y comparamos
|
|
String recomputed = Signature.createMerchantSignature(
|
|
readSecretFromEnvOrProp(), order, form.merchantParameters());
|
|
assertEquals(form.signature(), recomputed, "La firma recomputada debe coincidir");
|
|
}
|
|
|
|
@Test
|
|
void validateAndParseNotification_roundtrip_ok() throws Exception {
|
|
if (!secretPresent()) {
|
|
System.out.println("SKIP: define REDSYS_SECRET_B64 o -Dredsys.secret.b64 para ejecutar este test.");
|
|
return;
|
|
}
|
|
|
|
// 1) Simula un pedido real
|
|
String order = "N" + System.currentTimeMillis();
|
|
long amountCents = 2500L; // 25,00 €
|
|
|
|
// 2) Construye el JSON de NOTIFICACIÓN (vuelta) con claves Ds_*
|
|
Map<String, Object> notifJson = Map.of(
|
|
"Ds_Order", order,
|
|
"Ds_Amount", String.valueOf(amountCents),
|
|
"Ds_Currency", "978",
|
|
"Ds_Response", "0" // autorizado
|
|
// añade lo que quieras: Ds_AuthorisationCode, etc.
|
|
);
|
|
|
|
// 3) Base64 de ese JSON (exactamente lo que recibirías en
|
|
// Ds_MerchantParameters)
|
|
String notifJsonStr = new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(notifJson);
|
|
String dsParams = java.util.Base64.getEncoder().encodeToString(
|
|
notifJsonStr.getBytes(java.nio.charset.StandardCharsets.UTF_8));
|
|
|
|
// 4) Firma de NOTIFICACIÓN (usa la misma API y clave que Redsys)
|
|
String dsSignature = sis.redsys.api.Signature.createMerchantSignature(
|
|
readSecretFromEnvOrProp(), order, dsParams);
|
|
|
|
// 5) Llama a tu servicio como lo haría el webhook
|
|
RedsysService.RedsysNotification notif = service.validateAndParseNotification(dsSignature, dsParams);
|
|
|
|
// 6) Asserts
|
|
assertEquals(order, notif.order);
|
|
assertEquals(amountCents, notif.amountCents);
|
|
assertEquals("978", notif.currency);
|
|
assertTrue(notif.authorized()); // porque Ds_Response="0"
|
|
}
|
|
|
|
}
|