From 944a70d1e71debd0af64019be620f1e06643ea94 Mon Sep 17 00:00:00 2001 From: 13009 Date: Fri, 26 Jul 2024 18:50:54 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=8F=91=E5=8F=B7=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/ApacheHttpclientRequestIdTest.java | 180 ++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 scfs-api-core/src/test/java/com/czcb/scfs/api/core/http/client/ApacheHttpclientRequestIdTest.java diff --git a/scfs-api-core/src/test/java/com/czcb/scfs/api/core/http/client/ApacheHttpclientRequestIdTest.java b/scfs-api-core/src/test/java/com/czcb/scfs/api/core/http/client/ApacheHttpclientRequestIdTest.java new file mode 100644 index 0000000..da96276 --- /dev/null +++ b/scfs-api-core/src/test/java/com/czcb/scfs/api/core/http/client/ApacheHttpclientRequestIdTest.java @@ -0,0 +1,180 @@ +package com.czcb.scfs.api.core.http.client; + +import com.czcb.scfs.api.core.*; +import com.czcb.scfs.api.core.cipher.*; +import com.czcb.scfs.api.core.http.*; +import com.czcb.scfs.api.core.util.DateTimes; +import com.czcb.scfs.api.core.util.Nonce; +import com.czcb.scfs.api.core.util.Strings; +import com.google.gson.Gson; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockserver.client.MockServerClient; +import org.mockserver.junit.jupiter.MockServerExtension; +import org.mockserver.junit.jupiter.MockServerSettings; + +import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.GZIPOutputStream; + +import static com.czcb.scfs.api.core.Constants.*; +import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +@ExtendWith(MockServerExtension.class) +@MockServerSettings(ports = {8888}) +class ApacheHttpclientRequestIdTest { + private MockServerClient client; + + @BeforeEach + public void beforeEachLifecyleMethod(MockServerClient client) { + this.client = client; + } + + /** + * 构建配置 + */ + private Profile profile() { + PrivateKey privateKey = KeyText.loadTestPrivateKeyRSA(); + X509Certificate certificate = KeyText.loadTestRSA(); + List list = new ArrayList<>(); + list.add(certificate); + CertificateProvider certificateProvider = new LocalCertificateProvider(list); + Privacy privacy = new TestPrivacy(privateKey, certificateProvider); + Signature signature = new DefaultSignature(certificateProvider, + new TestSigner(privateKey, "6CDDAA92CAD75998325027647847330C1756291"), + new TestVerifier(certificateProvider), + new DefaultSequencer()); + + return new TestProfile( + privacy, signature, new DefaultChannel.Builder() + .channelNo("0000") + .appNo("100000") + .build(), new DefaultHttpProfile.Builder() + .online(false) + .logLevel(LogLevel.BASIC) + .compressionEnabled(true) + .host("http://127.0.0.1:8888") + .build() + ); + } + + @Test + void doRemoteExecuteRequestId() { + TestResponse mockResponse = new TestResponse(); + mockResponse.setName("123456"); + ApiClient apiClient = mock(mockResponse.toJsonResponse().getBody()); + + TestRequest request = new TestRequest(); + RequestBody requestBody = new JsonRequestBody.Builder() + .body(new Gson().toJson(request)) + .build(); + + HttpRequest httpRequest = new HttpRequest.Builder().httpMethod(HttpMethod.POST) + .url("/mock/xxx") + .parameters(new QueryParameter()) + .headers(new HttpHeaders()) + .body(requestBody) + .id("00000000000") + .build(); + + HttpResponse response = apiClient.exchange(httpRequest, ApacheHttpclientTest.TestResponse.class); + + assertThatJson("{\"name\":\"123456\"}").isEqualTo(response.getServiceResponse().toJsonResponse().getBody()); + } + + private ApiClient mock(String body) { + ApiClient apiClient = ApiClientBuilder.custom() + .profile(profile()) + .build(); + + // 对称密钥 + byte[] secret = apiClient.getProfile().getPrivacy().getSecretCipher().getSecretKey(); + // 加密响应报文 + String responseBody = apiClient.getProfile().getPrivacy().getSecretCipher().encrypt(secret, body.getBytes(StandardCharsets.UTF_8)); + + // 加密对称密钥 + String secretKey = apiClient.getProfile().getPrivacy().getEncryptor().encrypt(Strings.toStr(secret)); + + org.mockserver.model.HttpResponse mock = response() + .withHeader(NONCE, Nonce.ofNonce()) + .withHeader(SECRET_KEY, secretKey) + .withHeader(REQUEST_ID, Nonce.ofNonce()) + .withHeader(BANK_CERTIFICATE_SERIAL, "6CDDAA92CAD75998325027647847330C1756291") + .withHeader(CHANNEL_CERTIFICATE_SERIAL, "6CDDAA92CAD75998325027647847330C1756291") + .withHeader(TIMESTAMP, DateTimes.ofTimestamp()); + + mock.withHeader("Content-Encoding", "gzip"); + mock.withBody(compress(responseBody)); + + String buildAuth = NONCE + "=" + mock.getHeader(NONCE).get(0) + "," + + TIMESTAMP + "=" + mock.getHeader(TIMESTAMP).get(0) + "," + + BANK_CERTIFICATE_SERIAL + "=" + mock.getHeader(BANK_CERTIFICATE_SERIAL).get(0) + "," + + CHANNEL_CERTIFICATE_SERIAL + "=" + mock.getHeader(CHANNEL_CERTIFICATE_SERIAL).get(0) + "," + + SECRET_KEY + "=" + secretKey; + + String message = buildAuth + "\n" + responseBody + "\n"; + mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getSignature()); + + client.when(request() + .withHeader("Authorization", "SCFS-SHA256withRSA X-SCFS-Channel-No=0000,X-SCFS-App-No=100000,X-SCFS-Signature=.*") + .withHeader("X-SCFS-Nonce", "00000000000") + .withHeader("X-SCFS-Secret-Key", ".*") + .withHeader("X-SCFS-Serial", "6CDDAA92CAD75998325027647847330C1756291") + .withHeader("X-SCFS-Channel-Serial", "6CDDAA92CAD75998325027647847330C1756291") + .withHeader("X-SCFS-Timestamp", ".*") + .withMethod(HttpMethod.POST.getUpperName()) + .withPath("/mock/xxx") + ).respond(mock); + + return apiClient; + } + + public static byte[] compress(String str) { + ByteArrayOutputStream out = null; + GZIPOutputStream gzip = null; + try { + if (str == null || str.isEmpty()) { + return null; + } + out = new ByteArrayOutputStream(); + gzip = new GZIPOutputStream(out); + gzip.write(str.getBytes(StandardCharsets.UTF_8)); + gzip.finish(); + return out.toByteArray(); + } catch (Exception e) { + return null; + } finally { + try { + if (out != null) { + out.close(); + } + if (gzip != null) { + gzip.close(); + } + } catch (Exception ignored) { + } + } + } + + public static class TestRequest implements ApiRequest { + } + + public static class TestResponse implements ApiResponse { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} \ No newline at end of file