luodangjia
2024-10-08 4c96637a005891c709662ae84edd072ad9a4a57d
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
140
141
142
143
144
145
146
147
148
package com.ruoyi.account.ali.tools;
 
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipayEncrypt;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.request.AlipayUserInfoShareRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.alipay.api.response.AlipayUserInfoShareResponse;
import com.ruoyi.account.ali.Constant.AliConstant;
import com.ruoyi.account.ali.model.AliProperties;
import com.ruoyi.common.core.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
 
import java.util.Map;
 
/**
 * @author xiaochen
 * @ClassName WxAppletTools
 * @Description
 * @date 2024-8-04 13:55
 */
@Slf4j
public class AliAppletTools {
 
    //设置连接池中的最大可缓存的空闲连接数
    private static final Integer MaxIdleConnections = 5;
    //连接超时,单位:毫秒,默认3000
    private static final Integer ConnectTimeout = 3000;
    //读取超时,单位:毫秒,默认15000
    private static final Integer ReadTimeout = 15000;
    //空闲连接存活时间,单位:毫秒,默认10000L
    private static final Long KeepAliveDuration = 10000L;
    private AliProperties aliProperties;
 
    public AliAppletTools(AliProperties aliProperties) {
        this.aliProperties = aliProperties;
    }
 
    /**
     * 支付宝小程序授权登录接口
     * @param code
     * @return
     */
    public AlipaySystemOauthTokenResponse login(String code) {
        try {
            // 初始化SDK
            AlipayClient alipayClient = new DefaultAlipayClient(new AliAppletTools(aliProperties).getAlipayConfig(AliConstant.LOGIN_SERVER_URL));
            // 构造请求参数以调用接口
            AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
            // 设置授权码
            request.setCode(code);
            // 设置授权方式
            request.setGrantType(AliConstant.GRANT_TYPE);
            return alipayClient.execute(request);
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
    }
 
    /**
     * 支付宝小程序授权获取手机号
     * @return
     */
    public AlipayUserInfoShareResponse getUserInfo(String accessToken) {
        try {
            // 初始化SDK
            AlipayClient alipayClient = new DefaultAlipayClient(new AliAppletTools(aliProperties).getAlipayConfig(AliConstant.LOGIN_SERVER_URL));
            //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.user.userinfo.share
            AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest();
            //授权类接口执行API调用时需要带上accessToken
            return alipayClient.execute(request,accessToken);
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
    }
 
    /**
     * 获取用户手机号
     * @param response
     * @return
     */
    public String getPhoneNumber(String response){
        //1. 获取验签和解密所需要的参数
        Map<String, String> openapiResult = JSON.parseObject(response,new TypeReference<Map<String, String>>() {}, Feature.OrderedField);
        String signType = "RSA2";
        String charset = "UTF-8";
        String encryptType = "AES";
        String sign = openapiResult.get("sign");
        String content = openapiResult.get("response");
        //判断是否为加密内容
        boolean isDataEncrypted = !content.startsWith("{");
        boolean signCheckPass = false;
        //2. 验签
        String signContent = content;
        if (isDataEncrypted) {
            signContent = "\"" + signContent + "\"";
        } try {
            signCheckPass = AlipaySignature.rsaCheck(signContent, sign, aliProperties.getAlipayPublicKey(), charset, signType);
        } catch (AlipayApiException e) {
            // 验签异常, 日志
        } if (!signCheckPass) {
            //验签不通过(异常或者报文被篡改),终止流程(不需要做解密)
            throw new ServiceException("验签失败");
        }
        //3. 解密
        String plainData = null;
        if (isDataEncrypted) {
            try {
                plainData = AlipayEncrypt.decryptContent(content, encryptType, "84iAz9sTR7siFxTmAD6sfw==", charset);
            } catch (AlipayApiException e) {
                //解密异常, 记录日志
                throw new ServiceException("解密异常");
            }} else {
            plainData = content;
        }
        log.info("解密后的数据:{}", plainData);
        String phoneNumber = "";
        if (plainData.contains("mobile")) {
            phoneNumber = JSON.parseObject(plainData).getString("mobile");
        }
        return phoneNumber;
    }
 
    /**
     * 初始化支付宝配置
     * @return
     */
    public AlipayConfig getAlipayConfig(String serverUrl) {
        AlipayConfig alipayConfig = new AlipayConfig();
        alipayConfig.setServerUrl(serverUrl);
        alipayConfig.setAppId(aliProperties.getAppId());
        alipayConfig.setPrivateKey(aliProperties.getPrivateKey());
        alipayConfig.setAlipayPublicKey(aliProperties.getAlipayPublicKey());
        alipayConfig.setMaxIdleConnections(MaxIdleConnections);
        alipayConfig.setConnectTimeout(ConnectTimeout);
        alipayConfig.setReadTimeout(ReadTimeout);
        alipayConfig.setKeepAliveDuration(KeepAliveDuration);
        return alipayConfig;
    }
 
}