| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- package com.ruoyi.app.omgpay;
- import ch.qos.logback.classic.Logger;
- import ch.qos.logback.classic.spi.ILoggingEvent;
- import ch.qos.logback.core.read.ListAppender;
- import com.ruoyi.app.omgpay.dto.OmgCreatePaymentRequest;
- import com.ruoyi.app.omgpay.dto.OmgCreatePaymentResponse;
- import com.ruoyi.app.omgpay.dto.OmgPaymentErrorResponse;
- import com.ruoyi.common.core.domain.AjaxResult;
- import com.ruoyi.common.utils.MessageUtils;
- import com.ruoyi.system.omgpay.service.OmgIpnAuditService;
- import org.junit.jupiter.api.AfterEach;
- import org.junit.jupiter.api.BeforeEach;
- import org.junit.jupiter.api.Test;
- import org.mockito.MockedStatic;
- import org.slf4j.LoggerFactory;
- import org.springframework.web.bind.annotation.PostMapping;
- import org.springframework.web.bind.annotation.RequestBody;
- import org.springframework.web.bind.annotation.RequestHeader;
- import org.springframework.web.bind.annotation.RequestMapping;
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
- import java.util.Map;
- import java.util.Set;
- import java.util.stream.Collectors;
- import static org.junit.jupiter.api.Assertions.*;
- import static org.mockito.Mockito.*;
- class OmgPaymentControllerTest {
- private MockedStatic<MessageUtils> messages;
- @BeforeEach
- void setUpMessages() {
- messages = mockStatic(MessageUtils.class);
- messages.when(() -> MessageUtils.message(anyString())).thenAnswer(invocation -> invocation.getArgument(0));
- }
- @AfterEach
- void closeMessages() {
- messages.close();
- }
- @Test
- void exposesOnlyExplicitCreateContract() throws Exception {
- RequestMapping mapping = OmgPaymentController.class.getAnnotation(RequestMapping.class);
- assertArrayEquals(new String[]{"/pay/omg"}, mapping.value());
- Method create = OmgPaymentController.class.getDeclaredMethod("create", String.class,
- String.class, OmgCreatePaymentRequest.class);
- assertArrayEquals(new String[]{"/create"}, create.getAnnotation(PostMapping.class).value());
- assertEquals("token", create.getParameters()[0].getAnnotation(RequestHeader.class).name());
- assertNotNull(create.getParameters()[1].getAnnotation(RequestHeader.class));
- assertNotNull(create.getParameters()[2].getAnnotation(RequestBody.class));
- assertEquals(Set.of("orderId", "paymentMethod"), java.util.Arrays.stream(OmgCreatePaymentRequest.class.getDeclaredFields())
- .map(Field::getName).collect(Collectors.toSet()));
- assertTrue(java.util.Arrays.stream(create.getParameterTypes()).noneMatch(Map.class::isAssignableFrom));
- }
- @Test
- void returnsSuccessShapeAndSafeDiagnosticLogs() {
- OmgPaymentTokenUserResolver resolver = mock(OmgPaymentTokenUserResolver.class);
- OmgPaymentCreateService service = mock(OmgPaymentCreateService.class);
- when(resolver.requireUserId("SECRET_TOKEN")).thenReturn(5L);
- OmgCreatePaymentResponse response = new OmgCreatePaymentResponse("stage", Map.of("CheckMacValue", "A".repeat(64)));
- when(service.create(5L, "DD-1\r\nforged=true", OmgPaymentMethod.CREDIT)).thenReturn(new OmgPaymentCreateOutcome(
- response, 9L, "DD-1", 5L, 77L, 100, "OMG12***4567"));
- OmgPaymentController controller = controller(resolver, service);
- OmgCreatePaymentRequest request = new OmgCreatePaymentRequest();
- request.setOrderId("DD-1\r\nforged=true");
- request.setPaymentMethod("CREDIT");
- ListAppender<ILoggingEvent> logs = captureLogs();
- AjaxResult result = controller.create("SECRET_TOKEN", null, request);
- assertSame(response, result.get("data"));
- verify(service).create(5L, "DD-1\r\nforged=true", OmgPaymentMethod.CREDIT);
- String messages = logs.list.stream().map(ILoggingEvent::getFormattedMessage).collect(Collectors.joining("\n"));
- assertTrue(messages.contains("attemptId=9"));
- assertFalse(messages.contains("SECRET_TOKEN"));
- assertFalse(messages.contains("\r"));
- assertFalse(messages.contains("forged=true"));
- assertFalse(messages.contains("A".repeat(64)));
- assertFalse(messages.contains("CheckMacValue"));
- }
- @Test
- void mapsBusinessAndUnexpectedErrorsToStableStatus() {
- OmgPaymentTokenUserResolver resolver = mock(OmgPaymentTokenUserResolver.class);
- OmgPaymentCreateService service = mock(OmgPaymentCreateService.class);
- when(resolver.requireUserId(anyString())).thenReturn(5L);
- OmgPaymentController controller = controller(resolver, service);
- AjaxResult business = controller.create("token", null, null);
- assertEquals("PAYMENT_METHOD_INVALID", ((OmgPaymentErrorResponse) business.get("data")).status());
- RuntimeException failure = new RuntimeException("unexpected");
- when(service.create(5L, "DD-2", OmgPaymentMethod.CREDIT)).thenThrow(failure);
- OmgCreatePaymentRequest request = new OmgCreatePaymentRequest();
- request.setOrderId("DD-2");
- request.setPaymentMethod("CREDIT");
- ListAppender<ILoggingEvent> logs = captureLogs();
- AjaxResult unexpected = controller.create("token", null, request);
- assertEquals("PAYMENT_CREATION_FAILED", ((OmgPaymentErrorResponse) unexpected.get("data")).status());
- assertTrue(logs.list.stream().anyMatch(event -> event.getThrowableProxy() != null
- && event.getThrowableProxy().getMessage().equals("unexpected")));
- }
- @Test
- void mapsEveryBusinessErrorToItsStableStatus() {
- for (OmgPaymentErrorCode code : OmgPaymentErrorCode.values()) {
- OmgPaymentTokenUserResolver resolver = mock(OmgPaymentTokenUserResolver.class);
- OmgPaymentCreateService service = mock(OmgPaymentCreateService.class);
- when(resolver.requireUserId("token")).thenReturn(5L);
- when(service.create(5L, "DD-1", OmgPaymentMethod.CREDIT)).thenThrow(new OmgPaymentBusinessException(code, 77L));
- OmgCreatePaymentRequest request = new OmgCreatePaymentRequest();
- request.setOrderId("DD-1");
- request.setPaymentMethod("CREDIT");
- AjaxResult result = controller(resolver, service).create("token", null, request);
- assertEquals(code.name(), ((OmgPaymentErrorResponse) result.get("data")).status());
- }
- }
- @Test
- void mapsResolverFailureWithoutLoggingToken() {
- OmgPaymentTokenUserResolver resolver = mock(OmgPaymentTokenUserResolver.class);
- when(resolver.requireUserId("NEVER_LOG_THIS")).thenThrow(
- new OmgPaymentBusinessException(OmgPaymentErrorCode.AUTH_REQUIRED));
- OmgPaymentController controller = controller(resolver, mock(OmgPaymentCreateService.class));
- ListAppender<ILoggingEvent> logs = captureLogs();
- AjaxResult result = controller.create("NEVER_LOG_THIS", null, null);
- assertEquals("AUTH_REQUIRED", ((OmgPaymentErrorResponse) result.get("data")).status());
- assertTrue(logs.list.stream().noneMatch(event -> event.getFormattedMessage().contains("NEVER_LOG_THIS")));
- }
- @Test
- void rejectsInvalidPaymentMethodsWithoutCallingCreateService() {
- OmgPaymentTokenUserResolver resolver = mock(OmgPaymentTokenUserResolver.class);
- OmgPaymentCreateService service = mock(OmgPaymentCreateService.class);
- when(resolver.requireUserId("token")).thenReturn(5L);
- OmgPaymentController controller = controller(resolver, service);
- for (String paymentMethod : new String[]{null, "ALL", "Credit", " CREDIT "}) {
- OmgCreatePaymentRequest request = new OmgCreatePaymentRequest();
- request.setOrderId("DD-1");
- request.setPaymentMethod(paymentMethod);
- AjaxResult result = controller.create("token", null, request);
- assertEquals("PAYMENT_METHOD_INVALID", ((OmgPaymentErrorResponse) result.get("data")).status());
- }
- verifyNoInteractions(service);
- }
- @Test
- void multiStoreChildNeedsNewAppCapabilityButOrdinaryOrderDoesNot() {
- OmgPaymentTokenUserResolver resolver = mock(OmgPaymentTokenUserResolver.class);
- OmgPaymentCreateService service = mock(OmgPaymentCreateService.class);
- OmgPaymentController controller = controller(resolver, service);
- OmgCreatePaymentRequest request = new OmgCreatePaymentRequest();
- request.setOrderId("MS-CHILD-001");
- request.setPaymentMethod("CREDIT");
- AjaxResult rejected = controller.create("token", null, request);
- assertEquals("UPGRADE_REQUIRED", rejected.get("errorCode"));
- verifyNoInteractions(service);
- }
- private static ListAppender<ILoggingEvent> captureLogs() {
- Logger logger = (Logger) LoggerFactory.getLogger(OmgPaymentController.class);
- ListAppender<ILoggingEvent> appender = new ListAppender<>();
- appender.start();
- logger.addAppender(appender);
- return appender;
- }
- private static OmgPaymentController controller(OmgPaymentTokenUserResolver resolver,
- OmgPaymentCreateService service) {
- return new OmgPaymentController(resolver, service, mock(OmgPaymentNotifyService.class),
- mock(OmgIpnAuditService.class), mock(OmgPaymentQueryService.class),
- mock(OmgPaymentRetryService.class),
- mock(OmgPaymentRefundService.class));
- }
- }
|