shikeyin
2024-01-11 65da8373531677b1c37a98f53eaa30c892f35e5a
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package com.ishop.mobile.util;
 
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.iplatform.base.PlatformRuntimeException;
import com.iplatform.base.WechatConstants;
import com.iplatform.core.util.AESUtils;
import com.walker.infrastructure.utils.JsonUtils;
import com.walker.infrastructure.utils.MD5;
import com.walker.infrastructure.utils.StringUtils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
 
import java.security.InvalidAlgorithmParameterException;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
 
public class WechatUtils {
 
    public static final String JS_SIGN = "jsapi_ticket={0}&noncestr={1}&timestamp={2}&url={3}";
 
    private static final String WATERMARK = "watermark";
    private static final String APPID = "appid";
 
    /**
     * 解密微信手机号。
     * @param miniAppId
     * @param encryptData
     * @param sessionKey
     * @param iv
     * @return
     * @date 2023-09-15
     */
    public static final String decryptPhoneNumber(String miniAppId, String encryptData, String sessionKey, String iv){
        String result = StringUtils.EMPTY_STRING;
        try {
            byte[] decryptByte = AESUtils.decrypt(Base64.decodeBase64(encryptData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv));
            if(decryptByte == null || decryptByte.length == 0){
                return result;
            }
 
            result = new String(WxPKCS7Encoder.decode(decryptByte));
//            JSONObject jsonObject = JSONObject.parseObject(result);
//            String decryptAppid = jsonObject.getJSONObject(WATERMARK).getString(APPID);
//            if(!appId.equals(decryptAppid)){
//                result = "";
//            }
            return result;
 
        } catch (InvalidAlgorithmParameterException e) {
            throw new RuntimeException("解密微信手机号错误:" + e.getMessage(), e);
        }
    }
 
    public static final String getWechatOauthAccessTokenUrl(String appId, String secret, String code){
        return MessageFormat.format(WechatConstants.WECHAT_OAUTH2_ACCESS_TOKEN_URL, appId, secret, code);
    }
 
    /**
     * 获取ticket时,生成签名信息。
     * @param nonceStr
     * @param ticket
     * @param timestamp
     * @param url
     * @return
     * @date 2023-07-16
     * @date 2023-07-25 timestamp必须用字符串形式,否则格式化会默认转为金额(逗号分隔)形式。
     */
    public static String getJsSdkSign(String nonceStr, String ticket, String timestamp, String url){
        String data = MessageFormat.format(JS_SIGN, ticket, nonceStr, timestamp, url);
        return DigestUtils.sha1Hex(data);
    }
 
    /**
     * 获取sign
     * @param voJson      微信公共下单对象
     * @param signKey 微信签名key
     * @return String
     */
    public static String getSign(String voJson, String signKey) throws Exception {
        // 对象转map
        Map<String, Object> map = JsonUtils.jsonStringToObject(voJson, Map.class);
        // map排序
        Set<String> keySet = map.keySet();
        String[] keyArray = keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            if (k.equals(MD5.NAME_SIGN_2)) {
                continue;
            }
            // 参数值为空,则不参与签名
            if (map.get(k) != null && StringUtils.isNotEmpty(map.get(k).toString())){
                sb.append(k).append("=").append(map.get(k)).append("&");
            }
        }
        sb.append("key=").append(signKey);
        String sign = DigestUtils.sha1Hex(sb.toString()).toUpperCase();
        System.out.println("sign ========== " + sign);
        return sign;
    }
 
    /**
     * 获取sign
     * @param map      待签名数据
     * @param signKey 微信签名key
     * @return String
     */
    public static String getSign(Map<String, String> map, String signKey) throws Exception{
        // map排序
        Set<String> keySet = map.keySet();
        String[] keyArray = keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            if (k.equals(MD5.NAME_SIGN_2)) {
                continue;
            }
            if (StringUtils.isNotEmpty(map.get(k)) && map.get(k).trim().length() > 0) // 参数值为空,则不参与签名
                sb.append(k).append("=").append(map.get(k).trim()).append("&");
        }
        sb.append("key=").append(signKey);
//        String sign = SecureUtil.md5(sb.toString()).toUpperCase();
        String sign = MD5.getMessageDigest(sb.toString().getBytes(StringUtils.DEFAULT_CHARSET_UTF8)).toUpperCase();
        System.out.println("sign ========== " + sign);
        return sign;
    }
 
    public static final ObjectNode acquireObjectNode(String entity){
        ObjectNode objectNode = null;
        try {
            objectNode = JsonUtils.jsonStringToObjectNode(entity);
        } catch (Exception e) {
            throw new PlatformRuntimeException("string转ObjectNode错误:" + e.getMessage(), e);
        }
        return objectNode;
    }
}