1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.talentcard.server.business.payment.huifu;
 
import static org.assertj.core.api.Assertions.assertThat;
 
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.MessageDigest;
import java.util.Base64;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.junit.jupiter.api.Test;
 
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
class HuifuSignatureServiceTests {
 
    @Autowired
    private HuifuPaymentProperties runtimeProperties;
 
    @Test
    void printsResolvedHuifuConfiguration() throws Exception {
        System.out.println("Huifu enabled=" + runtimeProperties.isEnabled());
        System.out.println("Huifu environment=" + runtimeProperties.getEnvironment());
        System.out.println("Huifu systemId=" + runtimeProperties.getSystemId());
        System.out.println("Huifu productId=" + runtimeProperties.getProductId());
        System.out.println("Huifu merchantId=" + runtimeProperties.getMerchantId());
        System.out.println("Huifu miniProgramAppId=" + runtimeProperties.getMiniProgramAppId());
        System.out.println("Huifu notifyUrl=" + runtimeProperties.getNotifyUrl());
        System.out.println("Huifu privateKey=" + keySummary(runtimeProperties.getPrivateKey()));
        System.out.println("Huifu platformPublicKey=" + keySummary(runtimeProperties.getPlatformPublicKey()));
    }
 
    @Test
    void acceptsASignedCallbackPayloadAndRejectsTampering() throws Exception {
        KeyPair keys = KeyPairGenerator.getInstance("RSA").generateKeyPair();
        HuifuPaymentProperties properties = new HuifuPaymentProperties();
        properties.setPlatformPublicKey(Base64.getEncoder().encodeToString(keys.getPublic().getEncoded()));
        HuifuSignatureService service = new HuifuSignatureService(properties);
        String payload = "{\"req_seq_id\":\"P202607300001\",\"trans_stat\":\"S\"}";
 
        Signature signer = Signature.getInstance("SHA256WithRSA");
        signer.initSign(keys.getPrivate());
        signer.update(payload.getBytes(StandardCharsets.UTF_8));
        String signature = Base64.getEncoder().encodeToString(signer.sign());
 
        assertThat(service.verifyCallbackPayload(payload, signature)).isTrue();
        assertThat(service.verifyCallbackPayload(payload + " ", signature)).isFalse();
    }
 
    private String keySummary(String value) throws Exception {
        if (value == null || value.isBlank()) return "missing";
        byte[] digest = MessageDigest.getInstance("SHA-256").digest(value.trim().getBytes(StandardCharsets.UTF_8));
        StringBuilder fingerprint = new StringBuilder();
        for (byte item : digest) fingerprint.append(String.format("%02x", item));
        return "configured(length=" + value.trim().length() + ", sha256=" + fingerprint.substring(0, 16) + ")";
    }
}