package com.ruoyi.app.omgpay; import com.ruoyi.app.omgpay.dto.OmgPaymentErrorResponse; import com.ruoyi.app.omgpay.dto.OmgRefundPaymentRequest; 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.Test; import org.mockito.MockedStatic; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; import java.lang.reflect.Method; import java.util.Map; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.*; class OmgPaymentRefundControllerTest { @Test void exposesAuthenticatedOrderIdOnlyRefundContract() throws Exception { Method method = OmgPaymentController.class.getDeclaredMethod( "refund", String.class, OmgRefundPaymentRequest.class); assertArrayEquals(new String[]{"/refund"}, method.getAnnotation(PostMapping.class).value()); assertEquals("token", method.getParameters()[0].getAnnotation(RequestHeader.class).name()); assertNotNull(method.getParameters()[1].getAnnotation(RequestBody.class)); assertEquals(1, OmgRefundPaymentRequest.class.getDeclaredFields().length); assertEquals("orderId", OmgRefundPaymentRequest.class.getDeclaredFields()[0].getName()); assertTrue(java.util.Arrays.stream(method.getParameterTypes()) .noneMatch(Map.class::isAssignableFrom)); } @Test void returnsStableLocalizedTestEnvironmentRejection() { try (MockedStatic messages = mockStatic(MessageUtils.class)) { messages.when(() -> MessageUtils.message(anyString())).thenAnswer(call -> call.getArgument(0)); OmgPaymentTokenUserResolver resolver = mock(OmgPaymentTokenUserResolver.class); OmgPaymentRefundService refundService = mock(OmgPaymentRefundService.class); when(resolver.requireUserId("token")).thenReturn(5L); when(refundService.refund(5L, "DD-1")).thenThrow(new OmgPaymentBusinessException( OmgPaymentErrorCode.PAYMENT_REFUND_UNAVAILABLE_IN_TEST_ENVIRONMENT)); OmgRefundPaymentRequest request = new OmgRefundPaymentRequest(); request.setOrderId("DD-1"); AjaxResult result = controller(resolver, refundService).refund("token", request); assertEquals("omg.pay.refund.unavailable.test.environment", result.get("msg")); assertEquals("PAYMENT_REFUND_UNAVAILABLE_IN_TEST_ENVIRONMENT", ((OmgPaymentErrorResponse) result.get("data")).status()); } } @Test void unexpectedFailureUsesStableRefundFailureWithoutLeakingToken() { try (MockedStatic messages = mockStatic(MessageUtils.class)) { messages.when(() -> MessageUtils.message(anyString())).thenAnswer(call -> call.getArgument(0)); OmgPaymentTokenUserResolver resolver = mock(OmgPaymentTokenUserResolver.class); OmgPaymentRefundService refundService = mock(OmgPaymentRefundService.class); when(resolver.requireUserId("NEVER_LOG")).thenReturn(5L); when(refundService.refund(5L, "DD-1")).thenThrow(new IllegalStateException("unexpected")); OmgRefundPaymentRequest request = new OmgRefundPaymentRequest(); request.setOrderId("DD-1"); AjaxResult result = controller(resolver, refundService).refund("NEVER_LOG", request); assertEquals("PAYMENT_REFUND_FAILED", ((OmgPaymentErrorResponse) result.get("data")).status()); } } private static OmgPaymentController controller(OmgPaymentTokenUserResolver resolver, OmgPaymentRefundService refundService) { return new OmgPaymentController(resolver, mock(OmgPaymentCreateService.class), mock(OmgPaymentNotifyService.class), mock(OmgIpnAuditService.class), mock(OmgPaymentQueryService.class), mock(OmgPaymentRetryService.class), refundService); } }