WeiXinRequestUtil.java
15 KB
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
package com.topdraw.weixin.util;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.topdraw.utils.RedisUtils;
import com.topdraw.utils.StringUtils;
import com.topdraw.weixin.beans.QrCode;
import com.topdraw.weixin.beans.WeiXinNotice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Component
@Slf4j
public class WeiXinRequestUtil {
@Autowired
private RedisUtils redisUtils;
/**
*
* */
private static String doGet(String url, Map<String, String> param) {
String result = null;
try {
String queryString = "";
if (null != param) {
for (Map.Entry<String, String> entry : param.entrySet()) {
queryString += entry.getKey() + "=" + URLEncoder.encode("" + entry.getValue(), "UTF-8") + "&";
}
if (queryString.length() > 0) {
queryString = queryString.substring(0, queryString.length() - 1);
}
}
log.info("weixin request: " + url + "?" + queryString);
HttpResponse response = HttpRequest.get(url + "?" + queryString).execute();
if (response.isOk()) {
result = response.body();
log.info("weixin response: " + result);
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
private String wx_token(String appid, String secret) {
Map<String, String> param = new HashMap<>();
param.put("grant_type", "client_credential");
param.put("appid", appid);
param.put("secret", secret);
return this.doGet(WeChatConstants.HTTPS_TOKEN, param);
}
@Retryable(value = Exception.class, maxAttempts = 2, backoff = @Backoff(delay = 0L, multiplier = 0.0))
public String wx_ticket_getticket(String appid, String secret) {
String token = getToken(appid, secret,null);
Map<String, String> param = new HashMap<>();
param.put("access_token", token);
param.put("type", "jsapi");
return doGet(WeChatConstants.HTTPS_TICKET_GETTICKET, param);
}
public String wx_sns_oauth2_access_token(String appid, String secret, String code) {
Map<String, String> param = new HashMap<>();
param.put("appid", appid);
param.put("secret", secret);
param.put("code", code);
param.put("grant_type", "authorization_code");
return doGet(WeChatConstants.HTTPS_SNS_OAUTH2_ACCESS_TOKEN, param);
}
public String wx_sns_userinfo(String oauth2_access_token, String openid) {
Map<String, String> param = new HashMap<>();
param.put("access_token", oauth2_access_token);
param.put("openid", openid);
param.put("lang", "zh_CN");
return doGet(WeChatConstants.HTTPS_SNS_USERINFO, param);
}
public String wx_get_userinfo(String oauth2_access_token, String openid) {
Map<String, String> param = new HashMap<>();
param.put("access_token", oauth2_access_token);
param.put("openid", openid);
param.put("lang", "zh_CN");
return doGet(WeChatConstants.GET_USER_INFO, param);
}
public String getToken(String appid, String secret,String code) {
String token = (String) redisUtils.get(WeChatConstants.TOKEN_KEY + appid);
if (StringUtils.isNotBlank(token)) {
return token;
}
token = this.getTokenNoRedis(appid, secret,code);
return token;
}
public String getToken(String appid, String secret) {
String token = (String) redisUtils.get(WeChatConstants.TOKEN_KEY + appid);
if (StringUtils.isNotBlank(token)) {
return token;
}
token = this.getTokenNoRedis(appid, secret,null);
return token;
}
public String getTokenNoRedis(String appid, String secret,String code) {
String token = null;
String response = this.wx_token(appid, secret);
// String response = this.wx_sns_oauth2_access_token(appid, secret,code);
try {
JSONObject joToken = JSON.parseObject(response);
if (null != joToken && null != joToken.getString("access_token")) {
token = joToken.getString("access_token");
Integer expiresIn = joToken.getInteger("expires_in");
redisUtils.set(WeChatConstants.TOKEN_KEY + appid, token, expiresIn, TimeUnit.SECONDS);
}
} catch (Exception e) {
e.printStackTrace();
}
return token;
}
public String getTokenNoRedis(String appid, String secret) {
String token = null;
// String response = this.wx_token(appid, secret);
String response = this.wx_sns_oauth2_access_token(appid, secret,null);
try {
JSONObject joToken = JSON.parseObject(response);
if (null != joToken && null != joToken.getString("access_token")) {
token = joToken.getString("access_token");
Integer expiresIn = joToken.getInteger("expires_in");
redisUtils.set(WeChatConstants.TOKEN_KEY + appid, token, expiresIn, TimeUnit.SECONDS);
}
} catch (Exception e) {
e.printStackTrace();
}
return token;
}
/**
* 发送订阅消息,access_token错误时,重新获取进行重试
*
* @param weixinInfo 微信参数
* @param request 订阅消息内容
*/
@Retryable(value = Exception.class, maxAttempts = 2, backoff = @Backoff(delay = 0L, multiplier = 0.0))
public void sendNotice(Map<String, String> weixinInfo, WeiXinNotice request) {
String accessToken = getToken(weixinInfo.get("appid"), weixinInfo.get("secret"));
String url = MessageFormat.format(WeChatConstants.SUBSCRIBE_SEND_URL, accessToken);
log.info("send notice request : " + JSONObject.toJSONString(request));
HttpResponse response = HttpRequest.post(url).body(JSONObject.toJSONString(request), "application/json;charset=utf-8").execute();
if (!response.isOk()) {
log.error("send notice error || {}", response);
throw new RuntimeException("send notice error");
}
JSONObject jsonObject = JSONObject.parseObject(response.body());
Integer errCode = jsonObject.getInteger(WeChatConstants.ERR_CODE);
if (errCode != null && errCode != 0) {
if (WeChatConstants.ACCESS_TOKEN_INVALID_CODE.equals(errCode.toString())) {
getTokenNoRedis(weixinInfo.get("appid"), weixinInfo.get("secret"));
}
// 返回errCode时,也输出返回的结果信息
log.error("send notice error || {}", response.body());
throw new RuntimeException("send notice error");
}
log.info("send notice response : " + response.body());
}
/**
* 微信小程序客服发送消息,access_token错误时,重新获取进行重试
*
* @param weixinInfo 微信参数
* @param body 消息内容
*/
@Retryable(value = Exception.class, maxAttempts = 2, backoff = @Backoff(delay = 0L, multiplier = 0.0))
public void sendMessage(Map<String, String> weixinInfo, String body) {
String accessToken = getToken(weixinInfo.get("appid"), weixinInfo.get("secret"));
String url = MessageFormat.format(WeChatConstants.CUSTOM_SEND_URL, accessToken);
HttpResponse response = HttpRequest.post(url).body(body, "application/json;charset=utf-8").execute();
if (!response.isOk()) {
log.error("send message error || {}", response);
throw new RuntimeException("send message error");
}
log.info("send message response || {}", response.body());
JSONObject jsonObject = JSONObject.parseObject(response.body());
Integer errCode = jsonObject.getInteger(WeChatConstants.ERR_CODE);
if (errCode != null && errCode != 0) {
if (WeChatConstants.ACCESS_TOKEN_INVALID_CODE.equals(errCode.toString())) {
getTokenNoRedis(weixinInfo.get("appid"), weixinInfo.get("secret"));
}
throw new RuntimeException("send message error");
}
}
/**
* 上传临时素材返回mediaId,access_token错误时,重新获取进行重试
*
* @param weixinInfo 微信参数
* @param imagePath 素材路径
*/
@Retryable(value = Exception.class, maxAttempts = 2, backoff = @Backoff(delay = 0L, multiplier = 0.0))
public String getMediaId(Map<String, String> weixinInfo, String imagePath) throws IOException {
String accessToken = getToken(weixinInfo.get("appid"), weixinInfo.get("secret"));
String mediaId = (String) redisUtils.get(WeChatConstants.WEIXIN_MEDIA_KEY + weixinInfo.get("appid"));
if (StringUtils.isNotBlank(mediaId)) {
return mediaId;
}
String url = MessageFormat.format(WeChatConstants.UPLOAD_URL, accessToken);
HttpResponse response = HttpRequest.post(url).form("file", new File(imagePath)).execute();
if (!response.isOk()) {
log.error("upload image error || {}", response);
throw new RuntimeException("upload image error");
}
log.info("upload image response || {}", response.body());
JSONObject jsonObject = JSONObject.parseObject(response.body());
Integer errCode = jsonObject.getInteger(WeChatConstants.ERR_CODE);
if (errCode != null && errCode != 0) {
if (WeChatConstants.ACCESS_TOKEN_INVALID_CODE.equals(errCode.toString())) {
getTokenNoRedis(weixinInfo.get("appid"), weixinInfo.get("secret"));
}
throw new RuntimeException("upload image error");
}
mediaId = jsonObject.getString("media_id");
redisUtils.set(WeChatConstants.WEIXIN_MEDIA_KEY + weixinInfo.get("appid"), mediaId, 60, TimeUnit.HOURS);
return mediaId;
}
/**
* 公众号获取带参数二维码,access_token错误时,重新获取进行重试
*
* @param weixinInfo 微信参数
* @param qrCode 二维码信息
*/
@Retryable(value = Exception.class, maxAttempts = 2, backoff = @Backoff(delay = 0L, multiplier = 0.0))
public JSONObject getQrCode(Map<String, String> weixinInfo, QrCode qrCode) throws IOException {
String accessToken = getToken(weixinInfo.get("appid"), weixinInfo.get("secret"));
String url = MessageFormat.format(WeChatConstants.QR_CODE_URL, accessToken);
HttpResponse response = HttpRequest.post(url).body(JSONObject.toJSONString(qrCode), "application/json;charset=utf-8").execute();
if (!response.isOk()) {
log.error("get qrCode error || {}", response);
throw new RuntimeException("get qrCode error");
}
log.info("get qrCode response || {}", response.body());
JSONObject jsonObject = JSONObject.parseObject(response.body());
Integer errCode = jsonObject.getInteger(WeChatConstants.ERR_CODE);
if (errCode != null && errCode != 0) {
if (WeChatConstants.ACCESS_TOKEN_INVALID_CODE.equals(errCode.toString())) {
getTokenNoRedis(weixinInfo.get("appid"), weixinInfo.get("secret"));
}
throw new RuntimeException("get qrCode error");
}
return jsonObject;
}
/**
* 公众号获取用户信息,access_token错误时,重新获取进行重试
*
* @param weixinInfo 微信参数
* @param openid 用户openid
*/
@Retryable(value = Exception.class, maxAttempts = 2, backoff = @Backoff(delay = 0L, multiplier = 0.0))
public JSONObject getUserInfo(Map<String, String> weixinInfo, String openid,String code) throws IOException {
String accessToken = this.getToken(weixinInfo.get("appid"), weixinInfo.get("secret"),code);
String url = MessageFormat.format(WeChatConstants.GET_USER_INFO, accessToken, openid);
// String url = MessageFormat.format(WeChatConstants.HTTPS_SNS_USERINFO, accessToken, openid);
// String url = MessageFormat.format(WeChatConstants.HTTPS_AUTHORIZE_WITH_SNSAPI_USERINFO, accessToken, openid);
HttpResponse response = HttpRequest.get(url).execute();
if (!response.isOk()) {
log.error("get userInfo error || {}", response);
throw new RuntimeException("get userInfo error");
}
log.info("get userInfo response || {}", response.body());
JSONObject jsonObject = JSONObject.parseObject(response.body());
Integer errCode = jsonObject.getInteger(WeChatConstants.ERR_CODE);
if (errCode != null && errCode != 0) {
if (WeChatConstants.ACCESS_TOKEN_INVALID_CODE.equals(errCode.toString())) {
this.getTokenNoRedis(weixinInfo.get("appid"), weixinInfo.get("secret"));
}
throw new RuntimeException("get userInfo error");
}
return jsonObject;
}
/**
* @param weixinInfo
* @param nextOpenId
* @return com.alibaba.fastjson.JSONObject
* @description 公众号批量获取关注者列表,不传nextOpenId默认从头开始拉取,引用重试机制
* @author Hongyan Wang
* @date 2021/9/2 9:42 上午
*/
@Retryable(value = Exception.class, maxAttempts = 2, backoff = @Backoff(delay = 0L, multiplier = 0.0))
public JSONObject getUserList(Map<String, String> weixinInfo, String nextOpenId) {
String accessToken = getToken(weixinInfo.get("appid"), weixinInfo.get("secret"));
// 不传next_openid,默认从头开始拉取
if (StrUtil.isBlank(nextOpenId))
nextOpenId = "";
String url = MessageFormat.format(WeChatConstants.GET_USER_LIST, accessToken, nextOpenId);
HttpResponse response = HttpRequest.get(url).execute();
if (!response.isOk()) {
log.error("get userList error || {}", response);
throw new RuntimeException("get userList error");
}
log.info("get userList response || {}", response.body());
//返回Json样例
// {
// "total":2,
// "count":2,
// "data":{
// "openid":["OPENID1","OPENID2"]},
// "next_openid":"NEXT_OPENID"
//}
JSONObject jsonObject = JSONObject.parseObject(response.body());
Integer errCode = jsonObject.getInteger(WeChatConstants.ERR_CODE);
if (errCode != null && errCode != 0) {
if (WeChatConstants.ACCESS_TOKEN_INVALID_CODE.equals(errCode.toString())) {
getTokenNoRedis(weixinInfo.get("appid"), weixinInfo.get("secret"));
}
throw new RuntimeException("get userList error");
}
return jsonObject;
}
}