WeChatService.java 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. package com.caimei365.user.components;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.caimei365.user.model.JsonModel;
  5. import com.caimei365.user.utils.RequestUtil;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.apache.commons.codec.binary.Base64;
  8. import org.apache.commons.lang.StringUtils;
  9. import org.bouncycastle.jce.provider.BouncyCastleProvider;
  10. import org.springframework.beans.factory.annotation.Value;
  11. import org.springframework.http.HttpHeaders;
  12. import org.springframework.http.server.reactive.ServerHttpRequest;
  13. import org.springframework.stereotype.Component;
  14. import org.springframework.web.server.ServerWebExchange;
  15. import javax.crypto.Cipher;
  16. import javax.crypto.spec.IvParameterSpec;
  17. import javax.crypto.spec.SecretKeySpec;
  18. import java.security.AlgorithmParameters;
  19. import java.security.Security;
  20. import java.util.HashMap;
  21. import java.util.Map;
  22. /**
  23. * 微信 服务工具类
  24. *
  25. * @author : Charles
  26. * @date : 2021/3/9
  27. */
  28. @Slf4j
  29. @Component
  30. public class WeChatService {
  31. private String redirectUri;
  32. private String appId;
  33. private String appSecret;
  34. private String miniAppId;
  35. private String miniAppSecret;
  36. private String crmAppId;
  37. private String crmAppSecret;
  38. @Value("${wx.redirect-uri}")
  39. public void setRedirectUri(String redirectUri) {
  40. redirectUri = redirectUri;
  41. }
  42. @Value("${wx.app-id}")
  43. public void setAppId(String appId) {
  44. appId = appId;
  45. }
  46. @Value("${wx.app-secret}")
  47. public void setAppSecret(String appSecret) {
  48. appSecret = appSecret;
  49. }
  50. @Value("${wx.mini-app-id}")
  51. public void setMiniAppId(String miniAppId) {
  52. miniAppId = miniAppId;
  53. }
  54. @Value("${wx.mini-app-secret}")
  55. public void setMiniAppSecret(String miniAppSecret) {
  56. miniAppSecret = miniAppSecret;
  57. }
  58. @Value("${wx.crm-app-id}")
  59. public void setCrmAppId(String crmAppId) {
  60. crmAppId = crmAppId;
  61. }
  62. @Value("${wx.crm-app-secret}")
  63. public void setCrmAppSecret(String crmAppSecret) {
  64. crmAppSecret = crmAppSecret;
  65. }
  66. public String getRedirectUri() {
  67. return redirectUri;
  68. }
  69. public String getAppId() {
  70. return appId;
  71. }
  72. public String getAppSecret() {
  73. return appSecret;
  74. }
  75. public String getMiniAppId() {
  76. return miniAppId;
  77. }
  78. public String getMiniAppSecret() {
  79. return miniAppSecret;
  80. }
  81. public String getCrmAppId() {
  82. return crmAppId;
  83. }
  84. public String getCrmAppSecret() {
  85. return crmAppSecret;
  86. }
  87. static {
  88. // BouncyCastle是一个开源的加解密解决方案
  89. Security.addProvider(new BouncyCastleProvider());
  90. }
  91. /**
  92. * AES解密
  93. *
  94. * @param data 密文,被加密的数据
  95. * @param key 秘钥
  96. * @param iv 偏移量
  97. * @param encodingFormat 解密后的结果需要进行的编码
  98. * @return 解密结果
  99. */
  100. public static String decrypt(String data, String key, String iv, String encodingFormat) throws Exception {
  101. // 被加密的数据
  102. byte[] dataByte = Base64.decodeBase64(data);
  103. // 加密秘钥
  104. byte[] keyByte = Base64.decodeBase64(key);
  105. // 偏移量
  106. byte[] ivByte = Base64.decodeBase64(iv);
  107. try {
  108. Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
  109. SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
  110. AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
  111. parameters.init(new IvParameterSpec(ivByte));
  112. // 初始化
  113. cipher.init(Cipher.DECRYPT_MODE, spec, parameters);
  114. byte[] resultByte = cipher.doFinal(dataByte);
  115. if (null != resultByte && resultByte.length > 0) {
  116. return new String(resultByte, encodingFormat);
  117. }
  118. return null;
  119. } catch (Exception e) {
  120. e.printStackTrace();
  121. }
  122. return null;
  123. }
  124. /**
  125. * 小程序微信授权登录,获取openid
  126. *
  127. * @param code 微信凭证
  128. * @param serverWebExchange ServerWebExchange
  129. * @return HashMap
  130. */
  131. public JsonModel<Map<String, Object>> getInfoMapByApplets(String code, ServerWebExchange serverWebExchange) {
  132. log.info("Start get SessionKey");
  133. Map<String, Object> returnMap = new HashMap<>(4);
  134. // 获取当前微信小程序的环境
  135. ServerHttpRequest request = serverWebExchange.getRequest();
  136. HttpHeaders headers = request.getHeaders();
  137. String referer = headers.getFirst("Referer");
  138. log.info("referer-is----:" + referer);
  139. returnMap.put("referer", referer);
  140. String requestUrl = "https://api.weixin.qq.com/sns/jscode2session";
  141. Map<String, String> requestUrlParam = new HashMap<String, String>(4);
  142. // 小程序appId
  143. requestUrlParam.put("appId", miniAppId);
  144. log.info("appId: ---" + miniAppId);
  145. // 小程序appSecret
  146. requestUrlParam.put("appSecret", miniAppSecret);
  147. // 小程序端返回的code
  148. requestUrlParam.put("code", code);
  149. // 默认参数
  150. requestUrlParam.put("grantType", "authorization_code");
  151. // 发送post请求读取调用微信接口获取openid用户唯一标识
  152. String infos;
  153. try {
  154. infos = RequestUtil.sendPost(requestUrl, requestUrlParam);
  155. } catch (Exception e) {
  156. return JsonModel.error("服务器内部异常", returnMap);
  157. }
  158. // 解析相应内容(转换成json对象)
  159. JSONObject jsonObject = JSON.parseObject(infos);
  160. String openId = jsonObject.getString("openid");
  161. String unionId = jsonObject.getString("unionid");
  162. String sessionKey = jsonObject.getString("session_key");
  163. String errCode = jsonObject.getString("errcode");
  164. String errMsg = jsonObject.getString("errmsg");
  165. log.info("openId----->" + openId +", unionId------>" + unionId);
  166. returnMap.put("openId", openId);
  167. returnMap.put("unionId", unionId);
  168. returnMap.put("sessionKey", sessionKey);
  169. boolean errFlag = StringUtils.isNotEmpty(errCode) && ("-1".equals(errCode) || "40029".equals(errCode) || "45011".equals(errCode));
  170. if (errFlag) {
  171. return JsonModel.error(-1, errMsg, returnMap);
  172. }
  173. return JsonModel.success(returnMap);
  174. }
  175. /**
  176. * 微信公众号授权链接(www)
  177. * @param redirectUri 用于微信授权的中间页面
  178. * @param mode 授权方式:1静默授权,其他手动同意授权
  179. * @return newRedirectUri
  180. */
  181. public String getAuthorizationLink(String redirectUri, Integer mode) {
  182. String link = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
  183. // 应用唯一标识
  184. link = link.replace("APPID", crmAppId);
  185. // 中间页连接
  186. link = link.replace("REDIRECT_URI", redirectUri);
  187. if (mode == 1) {
  188. // 静默授权
  189. link = link.replace("snsapi_userinfo", "snsapi_base");
  190. }
  191. return link;
  192. }
  193. /**
  194. * 网页授权登录,通过code获取openid
  195. * @param code 微信code
  196. * @param source 来源
  197. * @return
  198. */
  199. public Map<String, Object> getInfoMapByWeb(String code, String source) throws Exception {
  200. String link = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
  201. if ("pc".equals(source)) {
  202. // 应用唯一标识
  203. link = link.replace("APPID", appId);
  204. // 应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
  205. link = link.replace("SECRET", appSecret);
  206. } else {
  207. //微信公众号
  208. link = link.replace("APPID", crmAppId);
  209. link = link.replace("SECRET", crmAppSecret);
  210. }
  211. // 获取的code参数
  212. link = link.replace("CODE", code);
  213. // 发送授权链接,得到微信用户信息
  214. String result = RequestUtil.sendGet(link);
  215. log.info(result);
  216. Map<String, Object> map = JSONObject.parseObject(result, Map.class);
  217. return map;
  218. }
  219. /**
  220. * 微信公众号获取access_token
  221. * @return access_token
  222. */
  223. public String getAccessToken() throws Exception {
  224. String link = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
  225. link = link.replace("APPID", crmAppId);
  226. link = link.replace("APPSECRET", crmAppSecret);
  227. String result = RequestUtil.sendGet(link);
  228. log.info("微信公众号获取access_token>>>" + result);
  229. Map<String, Object> map = JSONObject.parseObject(result, Map.class);
  230. return (String) map.get("access_token");
  231. }
  232. /**
  233. * 微信公众号获取用户信息
  234. * @return
  235. */
  236. public Map<String, Object> getUserInfo(String accessToken, String openid) throws Exception {
  237. String requestUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN";
  238. String userInfo = RequestUtil.sendGet(requestUrl);
  239. log.info("微信公众号授权用户数据>>>>>>>>>>>" + userInfo);
  240. Map<String, Object> map = JSONObject.parseObject(userInfo, Map.class);
  241. return map;
  242. }
  243. }