|
|
@@ -0,0 +1,102 @@
|
|
|
+package com.ruoyi.app.omgpay;
|
|
|
+
|
|
|
+import com.ruoyi.app.omgpay.dto.OmgCreatePaymentResponse;
|
|
|
+import com.ruoyi.app.omgpay.dto.OmgQueryPaymentResponse;
|
|
|
+import org.junit.jupiter.api.BeforeEach;
|
|
|
+import org.junit.jupiter.api.Test;
|
|
|
+
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+import static com.ruoyi.app.omgpay.OmgPaymentErrorCode.ORDER_ALREADY_PAID;
|
|
|
+import static com.ruoyi.app.omgpay.OmgPaymentErrorCode.PAYMENT_RETRY_NOT_AVAILABLE;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertSame;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertThrows;
|
|
|
+import static org.mockito.Mockito.mock;
|
|
|
+import static org.mockito.Mockito.never;
|
|
|
+import static org.mockito.Mockito.verify;
|
|
|
+import static org.mockito.Mockito.verifyNoInteractions;
|
|
|
+import static org.mockito.Mockito.when;
|
|
|
+
|
|
|
+class OmgPaymentRetryServiceTest {
|
|
|
+ private OmgPaymentQueryService queryService;
|
|
|
+ private OmgPaymentCreateService createService;
|
|
|
+ private OmgPaymentRetryService service;
|
|
|
+
|
|
|
+ @BeforeEach
|
|
|
+ void setUp() {
|
|
|
+ queryService = mock(OmgPaymentQueryService.class);
|
|
|
+ createService = mock(OmgPaymentCreateService.class);
|
|
|
+ service = new OmgPaymentRetryService(queryService, createService);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void replacesVerifiedUnpaidAttemptWithoutSelectedPaymentType() {
|
|
|
+ OmgPaymentCreateOutcome expected = outcome();
|
|
|
+ when(queryService.query(5L, "DD-1")).thenReturn(query("UNPAID", "0", null));
|
|
|
+ when(createService.replaceActiveForRetry(5L, "DD-1", "OMGOLD"))
|
|
|
+ .thenReturn(expected);
|
|
|
+
|
|
|
+ OmgPaymentCreateOutcome actual = service.retry(5L, "DD-1");
|
|
|
+
|
|
|
+ assertSame(expected, actual);
|
|
|
+ verify(createService).replaceActiveForRetry(5L, "DD-1", "OMGOLD");
|
|
|
+ verify(createService, never()).create(5L, "DD-1");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void createsFreshAttemptAfterVerifiedGatewayFailureClosedOldAttempt() {
|
|
|
+ OmgPaymentCreateOutcome expected = outcome();
|
|
|
+ when(queryService.query(5L, "DD-1")).thenReturn(query("FAILED", "10200095", null));
|
|
|
+ when(createService.create(5L, "DD-1")).thenReturn(expected);
|
|
|
+
|
|
|
+ assertSame(expected, service.retry(5L, "DD-1"));
|
|
|
+
|
|
|
+ verify(createService).create(5L, "DD-1");
|
|
|
+ verify(createService, never()).replaceActiveForRetry(5L, "DD-1", "OMGOLD");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void rejectsPaidAttemptWithoutCreatingAnotherPayment() {
|
|
|
+ when(queryService.query(5L, "DD-1")).thenReturn(query("PAID", "1", "Credit_CreditCard"));
|
|
|
+
|
|
|
+ OmgPaymentBusinessException error = assertThrows(OmgPaymentBusinessException.class,
|
|
|
+ () -> service.retry(5L, "DD-1"));
|
|
|
+
|
|
|
+ assertEquals(ORDER_ALREADY_PAID, error.getCode());
|
|
|
+ verifyNoInteractions(createService);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void rejectsUnpaidAttemptThatAlreadyHasPaymentType() {
|
|
|
+ when(queryService.query(5L, "DD-1")).thenReturn(query("UNPAID", "0", "Credit_CreditCard"));
|
|
|
+
|
|
|
+ OmgPaymentBusinessException error = assertThrows(OmgPaymentBusinessException.class,
|
|
|
+ () -> service.retry(5L, "DD-1"));
|
|
|
+
|
|
|
+ assertEquals(PAYMENT_RETRY_NOT_AVAILABLE, error.getCode());
|
|
|
+ verifyNoInteractions(createService);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void rejectsUnknownGatewayStateWithoutMutatingAttempt() {
|
|
|
+ when(queryService.query(5L, "DD-1")).thenReturn(query("UNKNOWN", "7", null));
|
|
|
+
|
|
|
+ OmgPaymentBusinessException error = assertThrows(OmgPaymentBusinessException.class,
|
|
|
+ () -> service.retry(5L, "DD-1"));
|
|
|
+
|
|
|
+ assertEquals(PAYMENT_RETRY_NOT_AVAILABLE, error.getCode());
|
|
|
+ verifyNoInteractions(createService);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static OmgQueryPaymentResponse query(String status, String tradeStatus, String paymentType) {
|
|
|
+ return new OmgQueryPaymentResponse(status, tradeStatus, "OMGOLD", "GW1", 100,
|
|
|
+ null, "2026/08/14 11:17:01", paymentType, "0", "0");
|
|
|
+ }
|
|
|
+
|
|
|
+ private static OmgPaymentCreateOutcome outcome() {
|
|
|
+ return new OmgPaymentCreateOutcome(
|
|
|
+ new OmgCreatePaymentResponse("CREATED", "https://stage.example", Map.of()),
|
|
|
+ 9L, "DD-1", 5L, 77L, 100, "OMGNE***0001");
|
|
|
+ }
|
|
|
+}
|