liujie
2 天以前 3033ccf3878fae2c204df53be2a283f29f5853ed
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package com.ruoyi.system.utils.wx.tools;
 
 
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.system.utils.wx.body.resp.AccessTokenRespBody;
import com.ruoyi.system.utils.wx.body.resp.Code2SessionRespBody;
import com.ruoyi.system.utils.wx.body.resq.Code2SessionResqBody;
import com.ruoyi.system.utils.wx.model.WeixinProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
 
import java.text.MessageFormat;
import java.util.concurrent.TimeUnit;
 
/**
 * @author xiaochen
 * @ClassName WxAppletTools
 * @Description
 * @date 2024-8-04 13:55
 */
@Slf4j
public class WxAppletTools {
    private final static String ACCESSTOKEN_CACHE_KEY = "accessToken";
    /**
     * 请求参数
     * 属性    类型    默认值    必填    说明
     * appid    string        是    小程序 appId
     * secret    string        是    小程序 appSecret
     * js_code    string        是    登录时获取的 code
     * grant_type    string        是    授权类型,此处只需填写 authorization_cod
     * <p>
     * 返回值:
     * <p>
     * 属性    类型    说明
     * openid    string    用户唯一标识
     * session_key    string    会话密钥
     * unionid    string    用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回,详见 UnionID 机制说明。
     * errcode    number    错误码
     * errmsg    string    错误信息
     */
    private static final String JSCODE_2_SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";
    /**
     * 请求参数
     * 属性    类型    默认值    必填    说明
     * appid    string        是    公众号 appId
     * secret    string        是    公众号 appSecret
     * code    string        是    登录时获取的 code
     * grant_type    string        是    授权类型,此处只需填写 authorization_cod
     * <p>
     * 返回值:
     * <p>
     * 属性    类型    说明
     * openid    string    用户唯一标识
     * session_key    string    会话密钥
     * unionid    string    用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回,详见 UnionID 机制说明。
     * errcode    number    错误码
     * errmsg    string    错误信息
     */
    private static final String CODE_2_SESSION_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code";
    /**
     * 请求参数
     * 属性    类型    默认值    必填    说明
     * grant_type    string        是    填写 client_credential
     * appid    string        是    小程序唯一凭证,即 AppID,可在「微信公众平台 - 设置 - 开发设置」页中获得。(需要已经成为开发者,且帐号没有异常状态)
     * secret    string        是    小程序唯一凭证密钥,即 AppSecret,获取方式同 appid
     * 返回值
     * Object
     * 返回的 JSON 数据包
     * <p>
     * 属性    类型    说明
     * access_token    string    获取到的凭证
     * expires_in    number    凭证有效时间,单位:秒。目前是7200秒之内的值。
     * errcode    number    错误码
     * errmsg    string    错误信息
     */
    public static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
    private WeixinProperties wxConfig;
    private RestTemplate wxRestTemplate;
    private RedisService redisService;
 
    public WxAppletTools(RestTemplate wxRestTemplate, WeixinProperties wxConfig, RedisService redisService) {
        this.wxRestTemplate = wxRestTemplate;
        this.wxConfig = wxConfig;
        this.redisService = redisService;
    }
 
    /**
     * 自定义部分数据
     *
     * @param wxConfig
     * @return
     */
    public WxAppletTools build(WeixinProperties wxConfig) {
        this.wxConfig = wxConfig;
        return this;
    }
 
    /**
     * @param resqBody
     * @return
     */
    public Code2SessionRespBody getOpenIdByJscode2session(Code2SessionResqBody resqBody) {
        long start = System.currentTimeMillis();
        String requestUrl = MessageFormat.format(JSCODE_2_SESSION_URL, wxConfig.getAppId(), wxConfig.getSecretId(), resqBody.getJsCode());
        long end = System.currentTimeMillis();
        log.info("code换取sessionKey时间:{}", (end - start));
        String respBody = wxRestTemplate.getForEntity(requestUrl, String.class).getBody();
        end = System.currentTimeMillis();
        log.info("code换取sessionKey时间:{}", (end - start));
        log.info("Jscode2session:{}", respBody);
        Code2SessionRespBody code2SessionRespBody = WxJsonUtils.parseObject(respBody, Code2SessionRespBody.class);
        // 判断有误异常
        if (StringUtils.hasLength(code2SessionRespBody.getErrorMsg())) {
            // 抛出错误
            throw new WxException(code2SessionRespBody.getErrorCode() + ":" + code2SessionRespBody.getErrorMsg());
        }
        return code2SessionRespBody;
    }
 
    /**
     * 微信公众号获取openId
     * @param resqBody
     * @return
     */
    public Code2SessionRespBody getOpenIdByCode2session(Code2SessionResqBody resqBody) {
        long start = System.currentTimeMillis();
        String requestUrl = MessageFormat.format(CODE_2_SESSION_URL, wxConfig.getAppId(), wxConfig.getSecretId(), resqBody.getJsCode());
        long end = System.currentTimeMillis();
        log.info("code换取sessionKey时间:{}", (end - start));
        String respBody = wxRestTemplate.getForEntity(requestUrl, String.class).getBody();
        end = System.currentTimeMillis();
        log.info("code换取sessionKey时间:{}", (end - start));
        log.info("Jscode2session:{}", respBody);
        Code2SessionRespBody code2SessionRespBody = WxJsonUtils.parseObject(respBody, Code2SessionRespBody.class);
        // 判断有误异常
        if (StringUtils.hasLength(code2SessionRespBody.getErrorMsg())) {
            // 抛出错误
            throw new WxException(code2SessionRespBody.getErrorCode() + ":" + code2SessionRespBody.getErrorMsg());
        }
        return code2SessionRespBody;
    }
 
    /**
     * @return
     */
    public String getAccessToken() {
        String accessToken = redisService.getCacheObject(ACCESSTOKEN_CACHE_KEY);
        if (StringUtils.hasLength(accessToken)) {
            return accessToken;
        }
        String requestUrl = MessageFormat.format(ACCESS_TOKEN_URL, wxConfig.getAppId(), wxConfig.getSecretId());
        String respBody = wxRestTemplate.getForEntity(requestUrl, String.class).getBody();
        AccessTokenRespBody accessTokenRespBody = WxJsonUtils.parseObject(respBody, AccessTokenRespBody.class);
        // 判断有误异常
        if (StringUtils.hasLength(accessTokenRespBody.getErrorMsg())) {
            // 抛出错误
            throw new WxException(accessTokenRespBody.getErrorCode() + ":" + accessTokenRespBody.getErrorMsg());
        }
        redisService.setCacheObject(ACCESSTOKEN_CACHE_KEY, accessTokenRespBody.getAccessToken(), 7200L, TimeUnit.SECONDS);
        return accessTokenRespBody.getAccessToken();
    }
 
}