Selaa lähdekoodia

Add wechat miniprogram

tsurumure 5 kuukautta sitten
vanhempi
commit
a980dd9dab

+ 3 - 0
src/main/java/com/backendsys/modules/app/controller/AppAuthController.java

@@ -28,4 +28,7 @@ public class AppAuthController {
     public Result login(@Validated(AppAuth.Login.class) @RequestBody AppAuth appAuth) {
         return Result.success().put("data", appAuthService.login(appAuth));
     }
+
+
+
 }

+ 105 - 0
src/main/java/com/backendsys/modules/sdk/wechat/miniprogram/utils/AES_Dec.java

@@ -0,0 +1,105 @@
+package com.backendsys.modules.sdk.wechat.miniprogram.utils;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+/**
+ * API响应处理 - 解密
+ * https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/getting_started/api_signature.html
+ */
+public class AES_Dec {
+    public static Object getRealResp(JsonObject ctx,JsonObject resp){
+        byte[] decryptedBytes = null;
+        // 开发者本地信息
+        String local_appid = ctx.get("local_appid").getAsString();
+        String url_path = ctx.get("url_path").getAsString();
+        String local_sym_sn = ctx.get("local_sym_sn").getAsString();
+        String local_sym_key = ctx.get("local_sym_key").getAsString();
+        // API响应数据,解密只需要响应头时间戳与响应数据
+        long respTs = resp.get("resp_ts").getAsLong();
+        String respData = resp.get("resp_data").getAsString();
+
+        JsonParser parser = new JsonParser();
+        JsonElement resp_data = parser.parse(respData);
+        String iv = resp_data.getAsJsonObject().get("iv").getAsString();
+        String data = resp_data.getAsJsonObject().get("data").getAsString();
+        String authtag = resp_data.getAsJsonObject().get("authtag").getAsString();
+        // 构建AAD
+        String aad = url_path + "|" + local_appid + "|" + respTs + "|" + local_sym_sn;
+        // 拼接cipher和authtag
+        byte[] dataBytes = Base64.getDecoder().decode(data);
+        byte[] authtagBytes = Base64.getDecoder().decode(authtag);
+        byte[] new_dataBytes = new byte[dataBytes.length+authtagBytes.length];
+        System.arraycopy(dataBytes,0,new_dataBytes,0,dataBytes.length);
+        System.arraycopy(authtagBytes,0,new_dataBytes,dataBytes.length,authtagBytes.length);
+        byte[] aadBytes = aad.getBytes(StandardCharsets.UTF_8);
+        byte[] ivBytes = Base64.getDecoder().decode(iv);
+        Object realResp = null;
+        try
+        {
+            byte[] keyBytes = Base64.getDecoder().decode(local_sym_key);
+            SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
+            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+            GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128, ivBytes);
+            cipher.init(Cipher.DECRYPT_MODE, secretKey, gcmParameterSpec);
+            cipher.updateAAD(aadBytes);
+            try{
+                decryptedBytes = cipher.doFinal(new_dataBytes);
+            }catch (Exception e){
+                System.out.println("auth tag验证失败");
+                return null;
+            }
+
+            // 解密结果
+            String decryptedData = new String(decryptedBytes, StandardCharsets.UTF_8);
+            JsonElement element = parser.parse(decryptedData);
+            Gson gson = new Gson();
+            realResp = gson.fromJson(element,Object.class);
+            long localTs = System.currentTimeMillis() / 1000;
+            // 安全检查,根据业务实际需求判断
+            if (element.getAsJsonObject().get("_appid").getAsString() == local_appid // appid不匹配
+                    || element.getAsJsonObject().get("_timestamp").getAsLong() != respTs // timestamp与Wechatmp-TimeStamp不匹配
+                    || localTs - element.getAsJsonObject().get("_timestamp").getAsLong() > 300 // 响应数据的时候与当前时间超过5分钟
+            ) {
+                System.out.println("安全字段校验失败");
+                return null;
+            }
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+        return realResp;
+
+    }
+
+    private static JsonObject getCtx(){
+        JsonObject ctx = new JsonObject();
+        // 仅做演示,敏感信息请勿硬编码
+        ctx.addProperty("local_sym_key","otUpngOjU+nVQaWJIC3D/yMLV17RKaP6t4Ot9tbnzLY=");
+        ctx.addProperty("local_sym_sn","fa05fe1e5bcc79b81ad5ad4b58acf787");
+        ctx.addProperty("local_appid","wxba6223c06417af7b");
+        ctx.addProperty("url_path","https://api.weixin.qq.com/wxa/getuserriskrank");
+
+        return ctx;
+    }
+    private static JsonObject getResp(){
+        JsonObject resp = new JsonObject();
+        String respData = "{\"iv\":\"r2WDQt56rEAmMuoR\",\"data\":\"HExs66Ik3el+iM4IpeQ7SMEN934FRLFYOd3EmeaIrpP4EPTHckoco6O+PaoRZRa3lqaPRZT7r52f7LUok6gLxc6cdR8C4vpIIfh4xfLC4L7FNy9GbuMK1hcoi8b7gkWJcwZMkuCFNEDmqn3T49oWzAQOrY4LZnnnykv6oUJotdAsnKvmoJkLK7hRh7M2B1d2UnTnRuoIyarXc5Iojwoghx4BOvnV\",\"authtag\":\"z2BFD8QctKXTuBlhICGOjQ==\"}";
+        resp.addProperty("resp_ts",1635927956);
+        resp.addProperty("resp_data",respData);
+
+        return resp;
+    }
+    public static void main(String[] args)  {
+        JsonObject resp = getResp();
+        JsonObject ctx = getCtx();
+        Object res = getRealResp(ctx,resp);
+        System.out.println(res);
+    }
+}

+ 116 - 0
src/main/java/com/backendsys/modules/sdk/wechat/miniprogram/utils/AES_Enc.java

@@ -0,0 +1,116 @@
+package com.backendsys.modules.sdk.wechat.miniprogram.utils;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.Base64;
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+
+/**
+ * API请求处理 - 加密
+ * https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/getting_started/api_signature.html
+ */
+public class AES_Enc {
+    private static JsonObject getReqForSign(JsonObject ctx, JsonObject req) {
+        Gson gson = new Gson();
+        // 开发者本地信息
+        String local_appid = ctx.get("local_appid").getAsString();
+        String url_path = ctx.get("url_path").getAsString();
+        String local_sym_sn = ctx.get("local_sym_sn").getAsString();
+        String local_sym_key = ctx.get("local_sym_key").getAsString();
+        //加密签名使用的统一时间戳
+        long localTs = System.currentTimeMillis() / 1000;
+        String nonce = generateNonce();
+
+        req.addProperty("_n",nonce);
+        req.addProperty("_appid",local_appid);
+        req.addProperty("_timestamp",localTs);
+        String plaintext = gson.toJson(req);
+
+        String aad = url_path + "|" + local_appid + "|" + localTs + "|" + local_sym_sn;
+        byte[] realKey = Base64.getDecoder().decode(local_sym_key);
+        byte[] realIv = generateRandomBytes(12);
+        byte[] realAad = aad.getBytes(StandardCharsets.UTF_8);
+        byte[] realPlaintext = plaintext.getBytes(StandardCharsets.UTF_8);
+
+        try {
+            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+            SecretKeySpec keySpec = new SecretKeySpec(realKey, "AES");
+            GCMParameterSpec parameterSpec = new GCMParameterSpec(128, realIv);
+            cipher.init(Cipher.ENCRYPT_MODE, keySpec, parameterSpec);
+            cipher.updateAAD(realAad);
+
+            byte[] ciphertext = cipher.doFinal(realPlaintext);
+            byte[] encryptedData = Arrays.copyOfRange(ciphertext, 0, ciphertext.length - 16);
+            byte[] authTag = Arrays.copyOfRange(ciphertext, ciphertext.length - 16, ciphertext.length);
+
+            String iv = base64Encode(realIv);
+            String data = base64Encode(encryptedData);
+            String authtag = base64Encode(authTag);
+
+
+            JsonObject reqData = new JsonObject();
+            reqData.addProperty("iv",iv);
+            reqData.addProperty("data",data);
+            reqData.addProperty("authtag",authtag);
+
+
+            JsonObject reqforsign = new JsonObject();
+            reqforsign.addProperty("req_ts",localTs);
+            reqforsign.addProperty("req_data",reqData.toString());
+
+            return reqforsign;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+    private static String generateNonce() {
+        byte[] nonce = generateRandomBytes(16);
+        return base64Encode(nonce).replace("=", "");
+    }
+
+    private static byte[] generateRandomBytes(int length) {
+        byte[] bytes = new byte[length];
+        new SecureRandom().nextBytes(bytes);
+        return bytes;
+    }
+
+    private static String base64Encode(byte[] data) {
+        return Base64.getEncoder().encodeToString(data);
+    }
+    private static JsonObject getCtx(){
+        JsonObject ctx = new JsonObject();
+        // 仅做演示,敏感信息请勿硬编码
+        ctx.addProperty("local_sym_key","otUpngOjU+nVQaWJIC3D/yMLV17RKaP6t4Ot9tbnzLY=");
+        ctx.addProperty("local_sym_sn","fa05fe1e5bcc79b81ad5ad4b58acf787");
+        ctx.addProperty("local_appid","wxba6223c06417af7b");
+        ctx.addProperty("url_path","https://api.weixin.qq.com/wxa/getuserriskrank");
+
+        return ctx;
+    }
+    private static JsonObject getRawReq(){
+        JsonObject req = new JsonObject();
+        req.addProperty("appid","wxba6223c06417af7b");
+        req.addProperty("openid","oEWzBfmdLqhFS2mTXCo2E4Y9gJAM");
+        req.addProperty("scene",0);
+        req.addProperty("client_ip","127.0.0.1");
+
+        return req;
+    }
+    public static void main(String[] args) {
+        JsonObject req = getRawReq();
+        JsonObject ctx = getCtx();
+        JsonObject reqforsign = getReqForSign(ctx,req);
+        if(reqforsign != null){
+            System.out.println(reqforsign.get("req_ts").getAsLong());
+            System.out.println(reqforsign.get("req_data").getAsString());
+        }
+    }
+}

+ 109 - 0
src/main/java/com/backendsys/modules/sdk/wechat/miniprogram/utils/RSA_Sign.java

@@ -0,0 +1,109 @@
+package com.backendsys.modules.sdk.wechat.miniprogram.utils;
+
+import com.google.gson.JsonObject;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyFactory;
+import java.security.Signature;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.spec.MGF1ParameterSpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.PSSParameterSpec;
+import java.util.Base64;
+
+/**
+ * API请求处理 - 签名
+ * https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/getting_started/api_signature.html
+ */
+public class RSA_Sign {
+    public static String getSignature(JsonObject ctx, JsonObject req){
+        String signatureBase64 = null;
+        // 开发者本地信息
+        String local_appid = ctx.get("local_appid").getAsString();
+        String url_path = ctx.get("url_path").getAsString();
+        String local_sym_sn = ctx.get("local_sym_sn").getAsString();
+        String local_private_key = ctx.get("local_private_key").getAsString();
+        // 待请求API数据
+        long reqTs = req.get("req_ts").getAsLong();
+        String reqData = req.get("req_data").getAsString();
+
+        String payload = url_path + "\n" + local_appid + "\n" + reqTs + "\n" + reqData;
+        byte[] dataBuffer = payload.getBytes(StandardCharsets.UTF_8);
+        try{
+            local_private_key = local_private_key.replace("-----BEGIN PRIVATE KEY-----", "");
+            local_private_key = local_private_key.replace("-----END PRIVATE KEY-----", "");
+            local_private_key = local_private_key.replaceAll("\\s+","");
+            byte[] decoded = Base64.getDecoder().decode(local_private_key);
+            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoded);
+            RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(keySpec);
+            Signature signature = Signature.getInstance("RSASSA-PSS");
+            // salt长度,需与SHA256结果长度(32)一致
+            PSSParameterSpec pssParameterSpec = new PSSParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1);
+            signature.setParameter(pssParameterSpec);
+            signature.initSign(priKey);
+            signature.update(dataBuffer);
+            byte[] sigBuffer = signature.sign();
+            signatureBase64 = Base64.getEncoder().encodeToString(sigBuffer);
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return signatureBase64;
+        /*
+        最终请求头字段
+        {
+            "Wechatmp-Appid": local_appid,
+            "Wechatmp-TimeStamp": req_ts,
+            "Wechatmp-Signature": sig,
+        }
+        */
+    }
+    private static JsonObject getReq(){
+        JsonObject req = new JsonObject();
+        req.addProperty("req_ts",1635927954);
+        req.addProperty("req_data","{\"iv\":\"fmW/zNxXlytUZBgj\",\"data\":\"0IDVdrPtSPF/Oe2CTXCV2vVNPbVJdJlP2WaTMQnoYLh5iCrrSNfQFh25EnStDMf0hLlVNBCZQtf9NaV0m4aRA4AAYIO7oR/Ge+4yY4EmZp5EVPB42xjScgMx5X3D4VdLCfynXIUKUtZHZvk1zmLVE3RauzJgiM1BB1CPmwcENo3MTJ0z8Vfkf5tMv54kOXobDLlV5rfqKdAX7gM/rP82DgZdt9vvZX44ipdbHIjJvw83ZXAFtvftdVw2Qd8=\",\"authtag\":\"5qeM/2vZv+6KtScN94IpMg==\"}");
+        return req;
+    }
+    private static JsonObject getCtx(){
+        JsonObject ctx = new JsonObject();
+        // 仅做演示,敏感信息请勿硬编码
+        String localPrivateKey = "-----BEGIN PRIVATE KEY-----\n" +
+                "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDcWhA6Y6Xn8IXm\n" +
+                "EXu1rgTMLLYtpTcS7aT0MHBDvcnzYjndLH0sCAzUMfcixiiFFHH8ERJ9t0MjamjC\n" +
+                "+vpBgpUgL7hhq/CDuDOFlHFZaZPUeu4QAMJkCCRQK770iX/0U+6K09KgikF3Ts2p\n" +
+                "2SRF7zY0E5+spN2GB7/nN3jnt+XsnzVDlVMjE7y++rsVLDuTom2/546NHpJk5Ztt\n" +
+                "Q7t/2vhS5SRea90a/bWqKq1o7UQzDi1QIQvNjvczs2kIfdGiuWiaZhfc/qrRWuQM\n" +
+                "esITT9AyGYewX7joT4hFwnfC0SPen+Y7VWgKkSFrALVTvbxlRPBY0SKLyE8SFw0B\n" +
+                "lMppAxpNAgMBAAECggEBAJe/mn9rkpzJgpzvm1+B6SHnBMsohWYOrNPR6+5q7IIl\n" +
+                "Oi477jP9k0Aq7MRQ7STA8MKjyzUymRTxuhXVG7UzxZk14+e3rlo355ttoCXwVHM2\n" +
+                "+W2h6D1VchSYG9hyPOE5UAThXaNbszwD1BTNSnKzC4QPo54Up84e1iTYifYiKkCq\n" +
+                "F9vJzqCfu5lJZNCyg7qEYFFDsSPH6+DCtvFkpVntRds8cPSU4Q+toDc8f9BR5Qqk\n" +
+                "3ArY1dCgHFZxHbzf8fEVICONJKwZIEqwKfAM3nk/YVDQc2LlivBQ1P3X3Q0hdJ7K\n" +
+                "BpHLVv4P7IF+b7ITv+pfActkIeyM77a0xJLcoaOWVMECgYEA/0U95g0pm67mO31G\n" +
+                "lnBcJz0TsjPtuYzvPCzp26fp1AfTFVVYVWaIYi7Tt6rIHwc1qBex4XOhctXkRDH7\n" +
+                "cNoHRsAf5kSkcYkmkBZIu6yKCywVQW5O9MXD6sLmHE5+J0xrr73dJTmlZ4lvTMkX\n" +
+                "w9ENondSbCXCli5sXXuxPg8Pqn0CgYEA3PtGWFFIW+CAmOEQyl6Tc4hhauuVE07Y\n" +
+                "xVw/uL98Y1MeGvDs4dw0ZGh/nhBnZjRtovvW8c2iRsraadP5xBdj+BcyZwT95XjH\n" +
+                "JEZiIgv2cF2uQt6tzjcRg+/568O+DKOLr7LienlwqoetLwX5jMBOTzYm30eB0jYy\n" +
+                "99slORJuaBECgYAc08v2s9vUCf9UDoSvLocpozsbL8QT5TeLGyNZu++rEysiSJ4O\n" +
+                "HuMd+13LawzofB7yGaLr6+v6lO8PSHm1t9mEguPXVD8h1zQ0p1+VWhnIwzSvS+68\n" +
+                "s6y5UUM9RRv4AihTE2Tq9ESamampCTiW03/vrfvv3J/J5/oy4GoWsQq63QKBgH0V\n" +
+                "+y646/Wd8g0XsTJsMJkAROyJ57ujMQ8eda91LMroXK0xXVVIGZwQjtSBQpZW7QyJ\n" +
+                "85SyKr5ZyyKGa+Y0u1DOiKhJ6hI/uLHu6VOOY/QdAyw08js9bru5VkW/ak+rL8HH\n" +
+                "x20+Wqkc3co1XpnurSUnaP+QcYr1RQqJ0NsqdLaRAoGAdnRxjPCH1ieZ9fH2aKYX\n" +
+                "ntpBDxoVz3Jp4Pn/cbb5r8Vlwe1jNR0dDs89LfluUPXv82eG6ceG6pqRuBqsf8sg\n" +
+                "UwchMJW4ZBPjFLfiQVWMVWGJPdwd9bIFsnoZtC7PMXHP9QoMMp/f843jWTxQ/bQZ\n" +
+                "2+a//5zqpCMo9rIwTzV6W6w=\n" +
+                "-----END PRIVATE KEY-----";
+        ctx.addProperty("local_private_key",localPrivateKey);
+        ctx.addProperty("local_sym_sn","97845f6ed842ea860df6fdf65941ff56");
+        ctx.addProperty("local_appid","wxba6223c06417af7b");
+        ctx.addProperty("url_path","https://api.weixin.qq.com/wxa/getuserriskrank");
+        return ctx;
+    }
+    public static void main(String[] args) {
+        JsonObject req = getReq();
+        JsonObject ctx = getCtx();
+        String res = getSignature(ctx,req);
+        System.out.println(res);
+
+    }
+}

+ 121 - 0
src/main/java/com/backendsys/modules/sdk/wechat/miniprogram/utils/RSA_Verify.java

@@ -0,0 +1,121 @@
+package com.backendsys.modules.sdk.wechat.miniprogram.utils;
+
+import com.google.gson.JsonObject;
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.security.Signature;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.spec.MGF1ParameterSpec;
+import java.security.spec.PSSParameterSpec;
+import java.util.Base64;
+
+/**
+ * API响应处理 - 验签
+ * https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/getting_started/api_signature.html
+ */
+public class RSA_Verify {
+    public static boolean checkSignature(JsonObject ctx,JsonObject resp){
+        String signature = null;
+        boolean result = false;
+        // 开发者本地信息
+        String local_appid = ctx.get("local_appid").getAsString();
+        String url_path = ctx.get("url_path").getAsString();
+        String local_sym_sn = ctx.get("local_sym_sn").getAsString();
+        String local_certificate = ctx.get("local_certificate").getAsString();
+
+        long respTs = resp.get("resp_ts").getAsLong();
+        String respAppid = resp.get("resp_appid").getAsString();
+        String respSn = resp.get("resp_sn").getAsString();
+        String respSig = resp.get("resp_sig").getAsString();
+        String respDeprecatedSn = resp.get("resp_deprecated_sn").getAsString();
+        String respDeprecatedSig = resp.get("resp_deprecated_sig").getAsString();
+        String respData = resp.get("resp_data").getAsString();
+
+        long localTs = System.currentTimeMillis() / 1000;
+        // 安全检查,根据业务实际需求判断
+        if (respAppid != local_appid || // 回包appid不正确
+                localTs - respTs > 300){  // 回包时间超过5分钟
+            System.out.println("安全字段校验失败");
+            return result;
+        }
+        if(local_sym_sn ==  respSn){
+            signature = respSig;
+        }else if(local_sym_sn == respDeprecatedSn){
+            System.out.println("平台证书即将过期,请及时更换"); // 本地证书编号与即将过期编号一致,需及时更换
+            signature = respDeprecatedSig;
+        }else{
+            System.out.println("sn不匹配");
+            return result;
+        }
+        String payload = url_path + "\n" + local_appid + "\n" + respTs + "\n" + respData;
+        byte[] dataBuffer = payload.getBytes(StandardCharsets.UTF_8);
+        try{
+            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
+            ByteArrayInputStream inputStream = new ByteArrayInputStream(local_certificate.getBytes());
+            X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(inputStream);
+            Signature verifier = Signature.getInstance("RSASSA-PSS");
+            PSSParameterSpec pssParameterSpec = new PSSParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1);
+            verifier.setParameter(pssParameterSpec);
+            verifier.initVerify(certificate);
+            verifier.update(dataBuffer);
+            byte[] sig_buffer = Base64.getDecoder().decode(signature);
+            result = verifier.verify(sig_buffer);
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return result;
+    }
+    private static JsonObject getCtx(){
+        JsonObject ctx = new JsonObject();
+        // 仅做演示,敏感信息请勿硬编码
+        String localCertificate = "-----BEGIN CERTIFICATE-----\n" +
+                "MIID0jCCArqgAwIBAgIUeE+Yy7vM/o+eHHsfM+1bGJJEZTQwDQYJKoZIhvcNAQEL\n" +
+                "BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT\n" +
+                "FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg\n" +
+                "Q0EwHhcNMjIwOTA1MDgzOTIyWhcNMjcwOTA0MDgzOTIyWjBkMRswGQYDVQQDDBJ3\n" +
+                "eGQ5MzBlYTVkNWEyNThmNGYxFTATBgNVBAoMDFRlbmNlbnQgSW5jLjEOMAwGA1UE\n" +
+                "CwwFV3hnTXAxCzAJBgNVBAYMAkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJ\n" +
+                "KoZIhvcNAQEBBQADggEPADCCAQoCggEBAM5D9qlkCmk1kr3FpF0e9pc3kGsvz5RA\n" +
+                "0/YRny9xPKIyV2UVMDZvRQ+mDHsiQQFE6etg457KFYSxTDKtItbdl6hJQVGeAvg0\n" +
+                "mqPYE9SkHRGTfL/AnXRbKBG2GC2OcaPSAprsLOersjay2me+9pF8VHybV8aox78A\n" +
+                "NsU75G/OO3V1iEE0s5Pmglqk8DEiw9gB/dGJzsNfXwzvyJyiUP9ZujYexyjsS+/Z\n" +
+                "GdSOUkqL/th+16yHj8alcdyga6YGfWEDyWkt/i/B28cwx4nzwk8xgrurifPaLuMk\n" +
+                "0+9wJQLCfAn/f7zyHrC8PcD1XvvRt9VBNMBASXs3710ODyyVf2lkMgkCAwEAAaOB\n" +
+                "gTB/MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgTwMGUGA1UdHwReMFwwWqBYoFaGVGh0\n" +
+                "dHA6Ly9ldmNhLml0cnVzLmNvbS5jbi9wdWJsaWMvaXRydXNjcmw/Q0E9MUJENDIy\n" +
+                "MEU1MERCQzA0QjA2QUQzOTc1NDk4NDZDMDFDM0U4RUJEMjANBgkqhkiG9w0BAQsF\n" +
+                "AAOCAQEAL2MK9tYu+ljLVBlSbfEeaKyF07TN+G31Ya5NBzeS1ZCx4joUEIyACWmG\n" +
+                "fUkKNKiKV+EMzxeEhKRso1Qif3E7Ipl+PQBoQw6OSR/jFHciYurnGR9CLkL03Zo1\n" +
+                "qw1Xetv9OipsvlpA0SOWc207e/XpGdm8C7FMXM6bzvVp8I/STTjC1vqjIZu9WavI\n" +
+                "RgGM4jyAPz2XogUq0BNijef8BXbbav9fAsXjHSwn5BQv4iLms3fiLm/eoyQ6dZ2R\n" +
+                "oTudrlcyr1bG4vwETLmHF+3yfVp9dpvJ+lyfiviwDwyfa8t2WlJm27DuF4vWoxir\n" +
+                "mjgj9tDutIFqxLIovLyg3uiAYtSQ/Q==\n" +
+                "-----END CERTIFICATE-----";
+        ctx.addProperty("local_certificate",localCertificate);
+        ctx.addProperty("local_sym_sn","79ba700ea147819f640941bceb38b1d1");
+        ctx.addProperty("local_appid","wxba6223c06417af7b");
+        ctx.addProperty("url_path","https://api.weixin.qq.com/wxa/getuserriskrank");
+        return ctx;
+    }
+    private static JsonObject getResp(){
+        JsonObject resp = new JsonObject();
+        resp.addProperty("resp_appid","wxba6223c06417af7b");
+        resp.addProperty("resp_ts",1635927956);
+        resp.addProperty("resp_sn","79ba700ea147819f640941bceb38b1d1");
+        resp.addProperty("resp_sig","Ht0VfQkkEweJ4hU266C14Aj64H9AXfkwNi5zxUZETCvR2svU1ZYdosDhFX/voLj1TyszqKsVxAlENGt7PPZZ8RQX7jnA4SKhiPUhW4LTbyTenisHJ+ohSfDjYnXavjQsBHspFS+BlPHuSSJ2xyQzw1+HuC6nid09ZL4FnGSYo4OI5MJrSb9xLzIVZMIDuUQchGKi/KaB1KzxECLEZcfjqbAgmxC7qOmuBLyO1WkHYDM95NJrHJWba5xv4wrwPru9yYTJSNRnlM+zrW5w9pOubC4Jtj3szTAEuOz9AcqUmgaAvMLNAIa8hfODLRe3n/cu4SgYlN/ZkNRU4QXVNbPGMg==");
+        resp.addProperty("resp_deprecated_sn","2171af9cdf1d7404423852e7e183d852");
+        resp.addProperty("resp_deprecated_sig","ZP1OODikAOePc+YJUMLxunF6xV05kextO/T1fy5lWv/CwV6OCsPBRM2xRRCi+B4lYXbbfYDdjzCz5BIAWEwIdjMlg/IHcJVHhRNAlKt5A3zvzfaJa5IJQel7xuUEXk/B6KVyEb41PbzrptjUGqWyTFMrjxQ4ThJfCuYocnUng7OuDU95enMqK2hZpO8o7kFW638BAwKDSiFNEwEJDWYkLz0kEw7ma3keezm4YHYKfJmjChK39tmZld7Rw/yrV1U9RiL/DO5ayP9VmrQkT/vYrPKyqI4/xKrIaTq44jFYTPIJKdU2OnLt6kjqwp2hvCzMuJdjRcrvzhWJ2A8xZ5hI2w==");
+        resp.addProperty("resp_data","{\"iv\":\"r2WDQt56rEAmMuoR\",\"data\":\"HExs66Ik3el+iM4IpeQ7SMEN934FRLFYOd3EmeaIrpP4EPTHckoco6O+PaoRZRa3lqaPRZT7r52f7LUok6gLxc6cdR8C4vpIIfh4xfLC4L7FNy9GbuMK1hcoi8b7gkWJcwZMkuCFNEDmqn3T49oWzAQOrY4LZnnnykv6oUJotdAsnKvmoJkLK7hRh7M2B1d2UnTnRuoIyarXc5Iojwoghx4BOvnV\",\"authtag\":\"z2BFD8QctKXTuBlhICGOjQ==\"}");
+
+
+        return resp;
+    }
+    public static void main(String[] args) {
+        JsonObject resp = getResp();
+        JsonObject ctx = getCtx();
+        boolean res =  checkSignature(ctx,resp);
+        System.out.println(res);
+
+    }
+}