WechatTemplate
/** * @description: 微信接口 **/ @Component @Slf4j @RefreshScope public class WeChatTemplate { @Value("${wx.appid:wxxxxxxcfaa}") private String appid; @Value("${wx.secret:2xxxx98fb5f1axxxx99c4xx0}") private String secret; @Value("${wx.message.templateId}") private String templateId; @Value("${wx.message.url}") private String url; @Autowired private RedisTemplate redisTemplate; public static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token"; public static final String USERS_URL = "https://api.weixin.qq.com/cgi-bin/user/get"; public static final String MESSAGE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="; public static final String USER_INFO_URL = "https://api.weixin.qq.com/cgi-bin/user/info"; public static final String OPRNID_URL = "https://api.weixin.qq.com/sns/oauth2/access_token"; public static final String ACCESS_TOKEN_CACHE = "wx:token"; public String getOpenId(String code) { Map<String, Object> params = new HashMap<>(8); params.put("appid", appid); params.put("secret", secret); params.put("code", code); params.put("grant_type", "authorization_code"); String access = HttpUtil.get(OPRNID_URL, params); log.debug("wx access_token {}", access); return (String) JSON.parseObject(access).get("openid"); } public String getAccessToken() { String token = (String) redisTemplate.opsForValue().get(ACCESS_TOKEN_CACHE); if (token != null) { return token; } String result = HttpUtil.get(ACCESS_TOKEN_URL, Map.of("grant_type", "client_credential", "appid", appid, "secret", secret)); token = (String) JSON.parseObject(result).get("access_token"); if (ObjectUtil.isNull(token)) { throw new FrameworkException(JSON.parseObject(result).get("errcode").toString()); } redisTemplate.opsForValue().set(ACCESS_TOKEN_CACHE, token, Long.valueOf(JSON.parseObject(result).get("expires_in").toString()) - 10, TimeUnit.SECONDS); return token; } public WxUsers getWxUsers(String nextOpenId) { String accessToken = getAccessToken(); Map<String, Object> param = Map.of("access_token", accessToken); if (StringUtils.isNotEmpty(nextOpenId)) { param.put("next_openid", nextOpenId); } String result = HttpUtil.get(USERS_URL, param); return JSON.parseObject(result, WxUsers.class); } public WxUserInfo getWxUserInfo(String openId) { String accessToken = getAccessToken(); Map<String, Object> param = Map.of("access_token", accessToken, "openid", openId, "lang", "zh_CN"); String result = HttpUtil.get(USER_INFO_URL, param); log.debug(result); return JSON.parseObject(result, WxUserInfo.class); } public void pushMessage(String openId, Map data) { String accessToken = getAccessToken(); Map<String, Object> param = new HashMap<>(); param.put("touser", openId); param.put("template_id", templateId); param.put("url", url + (String) data.get("id")); param.put("data", data); String result = HttpUtil.post(MESSAGE_URL + accessToken, JSON.toJSONString(param)); log.debug(result); } @Async public void pushMessageAllUsers(Map data) { log.info("发送开播提醒开始!"); WxUsers wxUsers = getWxUsers(null); List<String> openIds = wxUsers.getData().get("openid"); if (StringUtils.isEmpty(wxUsers.getErrcode())) { int total = wxUsers.getTotal(); String nextOpenId = wxUsers.getNextOpenid(); if (total > 10000) { while (total > 10000) { WxUsers users = getWxUsers(nextOpenId); openIds.addAll(wxUsers.getData().get("openid")); nextOpenId = users.getNextOpenid(); total = total - 10000; } } } if (CollectionUtils.isNotEmpty(openIds)) { openIds.parallelStream().forEach(openId -> { pushMessage(openId, data); }); } log.info("发送开播提醒结束!"); } public static final String TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket"; public Map jsSDKConfig(String webUrl) { String result = HttpUtil.get(TICKET_URL, Map.of("access_token", getAccessToken(), "type", "jsapi")); String ticket = (String) JSON.parseObject(result).get("ticket"); Map<String, String> ret = new HashMap<String, String>(); String nonceStr = createNonceStr(); String timestamp = createTimestamp(); String data; String signature = ""; // 注意这里参数名必须全部小写,且必须有序 data = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr + "×tamp=" + timestamp + "&url=" + webUrl; try { MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(data.getBytes("UTF-8")); signature = byteToHex(crypt.digest()); } catch (Exception e) { } ret.put("jsapi_ticket", ticket); ret.put("nonceStr", nonceStr); ret.put("timestamp", timestamp); ret.put("signature", signature); ret.put("appid", appid); return ret; } // 字节数组转换为十六进制字符串 private static String byteToHex(final byte[] hash) { Formatter formatter = new Formatter(); for (byte b : hash) { formatter.format("%02x", b); } String result = formatter.toString(); formatter.close(); return result; } // 生成随机字符串 private static String createNonceStr() { return UUID.randomUUID().toString(); } // 生成时间戳 private static String createTimestamp() { return Long.toString(System.currentTimeMillis() / 1000); } }