diff --git a/cpxt-admin/src/main/java/com/cpxt/web/controller/biz/orderutil/cityDelivery.java b/cpxt-admin/src/main/java/com/cpxt/web/controller/biz/orderutil/cityDelivery.java new file mode 100644 index 0000000..5bc79b1 --- /dev/null +++ b/cpxt-admin/src/main/java/com/cpxt/web/controller/biz/orderutil/cityDelivery.java @@ -0,0 +1,196 @@ +package com.cpxt.web.controller.biz.orderutil; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import com.alibaba.fastjson.JSON; +import com.cpxt.common.annotation.Anonymous; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.security.Security; +import java.util.*; + +/** + * @Author Ly + * @Create 2024/12/4 18:57 + * @Desc + */ +@RestController +@RequestMapping("/test") +@Slf4j +public class cityDelivery { + private static final char[] specialChars = {'\n', '\r', '\t', '\f','\b',' '}; + + // test + String clientKey ="7480617400984563";//accessKey + String clientSecret = "91wCEvn82CeyMg3k"; + String sm4Key = "MJy05dcI4mPbGB61"; + String appType = "wxmp"; + String client_type = "other"; + String version = "1.0.0"; + + /*static{ + Security.addProvider(new BouncyCastleProvider()); + }*/ + + /** + * 同城急送平台工具,post接口 + */ + @Anonymous + public void cityDelivery_signBody2(){ + Long timeStamp = System.currentTimeMillis(); + String nonce = UUID.randomUUID().toString().replace("-",""); + System.out.println("nonce:"+nonce ); + System.out.println("timeStamp:"+timeStamp ); + //签名 + Map sortedMap = new TreeMap<>(); + //下单接口 + String body = "{\n" + + " \"customerCode\": \"GZHX\",\n" + + " \"payTypeFirst\": \"03\",\n" + + " \"convertFlag\": false,\n" + + " \"weight\": \"501\",\n" + + " \"expectedTime\": \"2024-11-11 12:12:00\",\n" + + " \"platformOrderNo\": \"\",\n" + + " \"channelOrderNo\": \"\",\n" + + " \"orderSource\": \"meituan\",\n" + + " \"orderSourcePlatform\": \"01\",\n" + + " \"costFee\": \"100\",\n" + + " \"packageDesc\": \"药品\",\n" + + " \"remark\": \"手机尾号1234\",\n" + + " \"expressNbr\": \"\",\n" + + " \"insuredFee\": \"1\",\n" + + " \"otherFee1\": \"2\",\n" + + " \"otherFee2\": \"3\",\n" + + " \"addressFirst\": {\n" + + " \"senderProviceCode\": \"440000\",\n" + + " \"senderProviceName\": \"广东省\",\n" + + " \"senderCityCode\": \"440100\",\n" + + " \"senderCityName\": \"广州市\",\n" + + " \"senderCountyCode\": \"440106\",\n" + + " \"senderCountyName\": \"天河区\",\n" + + " \"senderContactName\": \"中山三院\",\n" + + " \"senderContactPhone\": \"17523029470\",\n" + + " \"senderLongitude\": \"113.264000\",\n" + + " \"senderLatitude\": \"23.129101\",\n" + + " \"senderStreetCode\": \"001\",\n" + + " \"senderStreetName\": \"林和街道1\",\n" + + " \"senderAddr\": \"天河北路188号\",\n" + + " \"receiverProviceCode\": \"440000\",\n" + + " \"receiverProviceName\": \"广东省\",\n" + + " \"receiverCityCode\": \"440100\",\n" + + " \"receiverCityName\": \"广州市\",\n" + + " \"receiverCountyCode\": \"440106\",\n" + + " \"receiverCountyName\": \"天河区\",\n" + + " \"receiverContactName\": \"陈先生\",\n" + + " \"receiverContactPhone\": \"13711511111\",\n" + + " \"receiverAddr\": \"信源大厦20楼2007\",\n" + + " \"receiverLongitude\": \"113.265000\",\n" + + " \"receiverLatitude\": \"23.129101\",\n" + + " \"receiverStreetCode\": \"002\",\n" + + " \"receiverStreetName\": \"林和街道2\"\n" + + " },\n" + + " \"businessJson\": {\n" + + " \"a\": \"asd\",\n" + + " \"b\": \"asd\"\n" + + " }\n" + + "}"; + //查询物流轨迹 +// String body = "{\n" + +// " \"expressNbr\": \"1158114584567\",\n" + +// " \"channelOrderNo\": \"\"\n" + +// "}"; + //get请求,组装成 k v类型 +// sortedMap.put(paramName,request.getParameter(paramName)); + /** + * post请求,需要放data + */ + sortedMap.put("data", JSON.toJSONString(StrUtil.removeAll(body, specialChars))); + sortedMap.put("access_id",clientKey); + sortedMap.put("nonce", nonce); + sortedMap.put("timestamp",timeStamp); + //排序 + Map sortedParams = new TreeMap<>(sortedMap); + Set> entrySet = sortedParams.entrySet(); + // 遍历排序后的字典,将所有参数按"key=value"格式拼接在一起 + StringBuilder stringToSign = new StringBuilder(); + for (Map.Entry param : entrySet) { + stringToSign.append(param.getKey()).append("=").append(param.getValue()).append(","); + } + stringToSign.append("accessSecret").append("=").append(clientSecret); + String genSign = cityDelivery_SM4Util.encryptCBC(stringToSign.toString(),clientSecret,sm4Key); + System.out.println("sign:" + genSign); + } + + //获取token + @Anonymous + @PostMapping("/getToken") + public void getToken(){ + System.out.println("获取token"); + String url = "https://wyjcs.gdwyj.cn/szelec/city-delivery-api/api/mini/app/login/token"; + String nonce = UUID.randomUUID().toString().replace("-", ""); + Long timestamp = System.currentTimeMillis(); + //body + Map map = new HashMap(); + map.put("clientKey",clientKey); + map.put("clientSecret",clientSecret); + map.put("appType",appType); + map.put("clientType",client_type); + map.put("version",version); + + Map sortedParams1 = new TreeMap<>(map); + Set> entrySet1 = sortedParams1.entrySet(); + StringBuilder stringToSign = new StringBuilder(); + for (Map.Entry param : entrySet1) { + stringToSign.append(param.getKey()).append("=").append(param.getValue()).append(","); + } + + String encryptBase64 = cityDelivery_SM4Util.encryptCBC(stringToSign.toString(),clientSecret,sm4Key); + System.out.println("body:" + encryptBase64); + //签名 + Map sortedMap2 = new TreeMap<>(); + + //get请求,组装成 k v类型 +// sortedMap2.put(paramName,request.getParameter(paramName)); + /** + * post请求,需要放data + */ + Map bodyMap = new HashMap(); + bodyMap.put("body",encryptBase64); + String bodyJson = JSON.toJSONString(bodyMap); + sortedMap2.put("data", JSON.toJSONString(bodyJson)); + sortedMap2.put("access_id",clientKey); + sortedMap2.put("nonce", nonce); + sortedMap2.put("timestamp",timestamp); + //排序 + Map sortedParams2 = new TreeMap<>(sortedMap2); + Set> entrySet2 = sortedParams2.entrySet(); + // 遍历排序后的字典,将所有参数按"key=value"格式拼接在一起 + StringBuilder stringToSign2 = new StringBuilder(); + for (Map.Entry param : entrySet2) { + stringToSign2.append(param.getKey()).append("=").append(param.getValue()).append(","); + } + stringToSign2.append("accessSecret").append("=").append(clientSecret); +// String genSign = DigestUtils.md5Hex(stringToSign2.toString()); + String genSign = cityDelivery_SM4Util.encryptCBC(stringToSign2.toString(),clientSecret,sm4Key); + System.out.println("------------"); + System.out.println("sign:" + genSign); + + + HttpResponse response = HttpRequest.post(url) + .body(JSON.toJSONString(bodyMap)) + .header("Content-Type", "application/json") + .header("client_type", client_type) + .header("app_type", appType) + .header("access_id", clientKey) + .header("nonce", nonce) + .header("timestamp", timestamp.toString()) + .header("sign", genSign) + .execute(); + System.out.println(response); + } +} diff --git a/cpxt-admin/src/main/java/com/cpxt/web/controller/biz/orderutil/cityDelivery_SM4Util.java b/cpxt-admin/src/main/java/com/cpxt/web/controller/biz/orderutil/cityDelivery_SM4Util.java new file mode 100644 index 0000000..8ddc859 --- /dev/null +++ b/cpxt-admin/src/main/java/com/cpxt/web/controller/biz/orderutil/cityDelivery_SM4Util.java @@ -0,0 +1,131 @@ +package com.cpxt.web.controller.biz.orderutil; + +import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.Mode; +import cn.hutool.crypto.Padding; +import cn.hutool.crypto.symmetric.SM4; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Base64; + +/** + * TODO + * + * @Author Mitch + * @Date 2024-12-12 16:30 + */ +@Slf4j +@Component +public class cityDelivery_SM4Util { + + + + public static String encryptCBC(String str, String secretKey, String iv) { + return encryptCBC(str, secretKey, iv, true); + } + + public static String encryptCBC(String str, String secretKey, String iv, boolean checkBase64) { + String encryptBase64 = null; + if (StrUtil.isEmpty(str)) { + return ""; + } + if (checkBase64 && isBase64(str)) { + return str; + } + SM4 sm4 = new SM4(Mode.CBC, Padding.PKCS5Padding, + secretKey.getBytes(CharsetUtil.CHARSET_UTF_8), + iv.getBytes(CharsetUtil.CHARSET_UTF_8)); + encryptBase64 = sm4.encryptBase64(str); + return encryptBase64; + } + + public static String decryptCBC(String str, String secretKey, String iv) { + return decryptCBC(str, secretKey, iv, true); + } + + public static String decryptCBC(String str, String secretKey, String iv, boolean checkBase64) { + String decryptStr = null; + try { + if (checkBase64 && !isBase64(str)) { + return str; + } + SM4 sm4 = new SM4(Mode.CBC, Padding.PKCS5Padding, + secretKey.getBytes(CharsetUtil.CHARSET_UTF_8), + iv.getBytes(CharsetUtil.CHARSET_UTF_8)); + decryptStr = sm4.decryptStr(str); + } catch (Exception e) { + log.error("解密参数:{}", str, "国密解密算法工具类异常--->{}", ExceptionUtil.getMessage(e)); + e.printStackTrace(); + } + return decryptStr; + } + + public static boolean isBase64(String input) { + char specificChar = '='; + if (input == null || input.isEmpty()) { + return false; + } + if (input.length() == 20 && input.matches("[0-9]+")) { + return false; + } + if (input.length() % 4 != 0) { + return false; + } + if (input.length() < 16) { + return false; + } + if (input.length() == 16 && input.matches("[0-9]+")) { + return false; + } + try { + byte[] decodedBytes = Base64.getDecoder().decode(input); + // 判断是否以=号结尾的 + if (input.endsWith(String.valueOf(specificChar))) { + int numEquals = 0; + for (int i = input.length() - 1; i >= 0; i--) { + if (input.charAt(i) == '=') { + numEquals++; + } else { + break; + } + } + return numEquals >= 0 && numEquals <= 2; + } + for (char c : input.toCharArray()) { + if (!(isBase64Character(c))) { + return false; + } + } + + return true; + } catch (IllegalArgumentException e) { + return false; + } + } + + + private static boolean isBase64Character(char c) { + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') + || (c >= '0' && c <= '9') || c == '+' || c == '/'; + } + + private static String getKey(){ + return RandomUtil.randomString(16); + } + + public static void main(String[] args) { + // String content = "我是字符串"; + //16位字符串 + String key = "nCWGwBstWF3MOu8T"; + String iv = "ABtjL78T7vBjhqyb"; + // String s = encryptCBC(content, key, iv); + // System.out.println(s); + String m = "1lcPgvBeFGaXJKrDfpOiAw=="; + String string = decryptCBC(m, key, iv); + System.out.println(string); + } +} diff --git a/cpxt-common/pom.xml b/cpxt-common/pom.xml index 96d9401..91f5d96 100644 --- a/cpxt-common/pom.xml +++ b/cpxt-common/pom.xml @@ -137,6 +137,20 @@ 5.5.7 + + com.alibaba + fastjson + 1.2.83 + + + + + org.bouncycastle + bcprov-jdk15on + 1.70 + + + \ No newline at end of file