| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- package com.ruoyi.app.omgpay;
- import org.junit.jupiter.api.BeforeEach;
- import org.junit.jupiter.api.Test;
- import org.springframework.context.annotation.AnnotationConfigApplicationContext;
- import java.net.URLEncoder;
- import java.nio.charset.StandardCharsets;
- import java.time.Clock;
- import java.time.Instant;
- import java.time.ZoneOffset;
- import java.util.LinkedHashMap;
- import java.util.Map;
- import java.util.Set;
- import static org.junit.jupiter.api.Assertions.assertEquals;
- import static org.junit.jupiter.api.Assertions.assertNotNull;
- import static org.junit.jupiter.api.Assertions.assertThrows;
- import static org.mockito.ArgumentMatchers.anyMap;
- import static org.mockito.Mockito.mock;
- import static org.mockito.Mockito.verify;
- import static org.mockito.Mockito.when;
- class OmgStoreCredentialVerifierTest {
- private static final String HASH_KEY = "5294y06JbISpM5x9";
- private static final String HASH_IV = "v77hoKGq4kWxNNIS";
- private OmgPaymentQueryGateway gateway;
- private OmgCheckMacSigner signer;
- private OmgStoreCredentialVerifier verifier;
- @BeforeEach
- void setUp() {
- gateway = mock(OmgPaymentQueryGateway.class);
- signer = new OmgCheckMacSigner();
- verifier = new OmgStoreCredentialVerifier(gateway, new OmgQueryResponseParser(), signer,
- Clock.fixed(Instant.ofEpochSecond(1_786_598_400L), ZoneOffset.UTC));
- }
- @Test
- void signsAStageProbeAndVerifiesEveryReturnedField() {
- when(gateway.query(anyMap())).thenAnswer(invocation -> signedResponse(invocation.getArgument(0)));
- Map<String, String> response = verifier.verify("1000031", HASH_KEY, HASH_IV);
- assertEquals("0", response.get("TradeStatus"));
- @SuppressWarnings("unchecked")
- var request = org.mockito.ArgumentCaptor.forClass(Map.class);
- verify(gateway).query(request.capture());
- assertEquals(Set.of("MerchantID", "MerchantTradeNo", "TimeStamp", "CheckMacValue"),
- request.getValue().keySet());
- assertEquals("1000031", request.getValue().get("MerchantID"));
- assertEquals("OMGVERIFY1786598400", request.getValue().get("MerchantTradeNo"));
- assertEquals("1786598400", request.getValue().get("TimeStamp"));
- LinkedHashMap<String, String> signingFields = new LinkedHashMap<>(request.getValue());
- String actual = signingFields.remove("CheckMacValue");
- assertEquals(signer.sign(signingFields, HASH_KEY, HASH_IV), actual);
- }
- @Test
- void rejectsAnyTamperedExtraResponseField() {
- when(gateway.query(anyMap())).thenAnswer(invocation ->
- signedResponse(invocation.getArgument(0)).replace("FutureEmptyField=", "FutureEmptyField=tampered"));
- assertThrows(IllegalArgumentException.class,
- () -> verifier.verify("1000031", HASH_KEY, HASH_IV));
- }
- @Test
- void springContextCreatesCredentialVerifierWithDependencies() {
- try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
- context.registerBean(OmgPaymentQueryGateway.class, () -> gateway);
- context.registerBean(OmgQueryResponseParser.class);
- context.registerBean(OmgCheckMacSigner.class);
- context.register(OmgStoreCredentialVerifier.class);
- context.refresh();
- assertNotNull(context.getBean(OmgStoreCredentialVerifier.class));
- }
- }
- private String signedResponse(Map<String, String> request) {
- LinkedHashMap<String, String> fields = new LinkedHashMap<>();
- fields.put("MerchantID", request.get("MerchantID"));
- fields.put("MerchantTradeNo", request.get("MerchantTradeNo"));
- fields.put("TradeStatus", "0");
- fields.put("RtnMsg", "Not found");
- fields.put("FutureEmptyField", "");
- fields.put("CheckMacValue", signer.sign(fields, HASH_KEY, HASH_IV));
- return fields.entrySet().stream()
- .map(entry -> encode(entry.getKey()) + "=" + encode(entry.getValue()))
- .collect(java.util.stream.Collectors.joining("&"));
- }
- private static String encode(String value) {
- return URLEncoder.encode(value, StandardCharsets.UTF_8);
- }
- }
|