WeChatUtil.java 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. package com.ylx.massage.utils;
  2. /**
  3. * @author jianlong
  4. * @date 2024-06-04 10:13
  5. */
  6. import cn.hutool.http.HttpUtil;
  7. import com.alibaba.fastjson2.JSONObject;
  8. import com.ylx.common.config.WechatAccountConfig;
  9. import com.ylx.common.exception.ServiceException;
  10. import com.ylx.common.utils.StringUtils;
  11. import lombok.extern.slf4j.Slf4j;
  12. import org.springframework.stereotype.Component;
  13. import org.w3c.dom.Node;
  14. import org.w3c.dom.NodeList;
  15. import javax.annotation.Resource;
  16. import javax.xml.parsers.DocumentBuilder;
  17. import javax.xml.parsers.DocumentBuilderFactory;
  18. import javax.xml.transform.OutputKeys;
  19. import javax.xml.transform.Transformer;
  20. import javax.xml.transform.TransformerFactory;
  21. import javax.xml.transform.dom.DOMSource;
  22. import javax.xml.transform.stream.StreamResult;
  23. import java.io.ByteArrayInputStream;
  24. import java.io.InputStream;
  25. import java.io.StringWriter;
  26. import java.io.UnsupportedEncodingException;
  27. import java.net.URLEncoder;
  28. import java.util.HashMap;
  29. import java.util.Map;
  30. /**
  31. * 微信登录工具类
  32. */
  33. @Component
  34. @Slf4j
  35. public class WeChatUtil {
  36. private final static String ERROR_CODE = "errcode";
  37. @Resource
  38. private WechatAccountConfig wxPayProperties;
  39. /**
  40. * 获取微信授权code
  41. *
  42. * @param state state信息
  43. * @return 返回微信授权code的URL
  44. */
  45. public String getCode(String state) {
  46. try {
  47. StringBuffer url = new StringBuffer();
  48. url.append(wxPayProperties.getGetCodeUrl())
  49. .append("?appid=")
  50. .append(wxPayProperties.getMpAppId())
  51. .append("&redirect_uri=")
  52. .append(URLEncoder.encode(wxPayProperties.getRedirectUrl(), "UTF-8"))
  53. .append("&response_type=code&scope=snsapi_userinfo&state=")
  54. .append("STATE")
  55. .append("#wechat_redirect");
  56. return url.toString();
  57. } catch (UnsupportedEncodingException e) {
  58. throw new ServiceException("URL格式化异常");
  59. }
  60. }
  61. /**
  62. * 获取微信AccessToken
  63. *
  64. * @param code 用户code
  65. * @return 返回包含微信AccessToken的Map
  66. */
  67. public Map<?, ?> getAccessToken(String code) {
  68. StringBuffer url = new StringBuffer();
  69. url.append(wxPayProperties.getAccessTokenUrl())
  70. .append("?appid=").append(wxPayProperties.getMpAppId())
  71. .append("&secret=").append(wxPayProperties.getMpAppSecret())
  72. .append("&code=").append(code)
  73. .append("&grant_type=authorization_code");
  74. String rs = HttpUtil.get(url.toString());
  75. Map<?, ?> map = JSONObject.parseObject(rs, Map.class);
  76. if (null == map.get(ERROR_CODE)) {
  77. return map;
  78. } else {
  79. throw new ServiceException("获取access_token出错");
  80. }
  81. }
  82. /**
  83. * 获取微信AccessToken
  84. *
  85. *
  86. * @return 返回包含微信AccessToken的Map
  87. */
  88. public String getToken() {
  89. StringBuffer url = new StringBuffer();
  90. url.append("https://api.weixin.qq.com/cgi-bin/token")
  91. .append("?grant_type=").append("client_credential")
  92. .append("&appid=").append(wxPayProperties.getMpAppId())
  93. .append("&secret=").append(wxPayProperties.getMpAppSecret());
  94. String rs = HttpUtil.get(url.toString());
  95. Map<?, ?> map = JSONObject.parseObject(rs, Map.class);
  96. if (null == map.get(ERROR_CODE)) {
  97. return map.get("access_token").toString();
  98. } else {
  99. log.error("getToken-获取access_token出错:{}", map);
  100. throw new ServiceException("getToken-获取access_token出错");
  101. }
  102. }
  103. /**
  104. * 刷新AccessToken
  105. *
  106. * @param refreshToken 用户刷新token
  107. * @return 返回包含刷新后的微信AccessToken的Map
  108. */
  109. public Map<?, ?> refreshToken(String refreshToken) {
  110. StringBuffer url = new StringBuffer();
  111. url.append("https://api.weixin.qq.com/sns/oauth2/refresh_token")
  112. .append("?appid=").append(wxPayProperties.getMpAppId())
  113. .append("&grant_type=refresh_token&refresh_token=").append(refreshToken);
  114. String rs = HttpUtil.get(url.toString());
  115. Map<?, ?> map = JSONObject.parseObject(rs, Map.class);
  116. if (null == map.get(ERROR_CODE)) {
  117. return map;
  118. } else {
  119. log.error("刷新access_token出错:{}", map);
  120. throw new ServiceException("刷新access_token出错");
  121. }
  122. }
  123. /**
  124. * 获取用户信息
  125. *
  126. * @param accessToken 微信AccessToken
  127. * @param openid 用户的openid
  128. * @return 返回包含用户信息的JSON字符串
  129. */
  130. public String getUserInfo(String accessToken, String openid) {
  131. StringBuffer url = new StringBuffer();
  132. url.append("https://api.weixin.qq.com/sns/userinfo")
  133. .append("?access_token=").append(accessToken)
  134. .append("&openid=").append(openid)
  135. .append("&lang=zh_CN");
  136. return HttpUtil.get(url.toString());
  137. }
  138. /**
  139. * 生成公众号码ticket
  140. *
  141. * @param token access_token
  142. * @return 返回包含微信公众号码ticket的Map
  143. */
  144. public Map<?, ?> getTicket(String token, String openId){
  145. String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + token;
  146. String param = "{\"action_name\": \"QR_LIMIT_STR_SCENE\",\"action_info\": {\"scene\": {\"scene_str\": \"" + openId + "\"}}}";
  147. String rs = HttpUtil.post(url, param);
  148. Map<?, ?> map = JSONObject.parseObject(rs, Map.class);
  149. // String ticket = map.get("ticket").toString();
  150. //
  151. // String encode = null;
  152. // try {
  153. // encode = URLEncoder.encode(ticket, "UTF-8");
  154. // } catch (UnsupportedEncodingException e) {
  155. // throw new RuntimeException(e);
  156. // }
  157. //
  158. // String url1 = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket="+ encode;
  159. //
  160. // String s = HttpUtil.get(url1);
  161. //
  162. //
  163. //
  164. //
  165. // Map<?, ?> rsmap = JSONObject.parseObject(s, Map.class);
  166. // return rsmap;
  167. return map;
  168. }
  169. /**
  170. * 生成公众号码ticket
  171. *
  172. * @param token access_token
  173. * @return 返回包含微信公众号码ticket的Map
  174. */
  175. public Map<?, ?> menuUtil(String token) {
  176. String url = " https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" + token;
  177. String param = "{\"button\":[{\"type\":\"view\",\"name\":\"立即下单\",\"url\":\"http://www.soso.com/\"},{\"name\":\"更多\",\"sub_button\":[{\"type\":\"view\",\"name\":\"搜索\",\"url\":\"http://www.soso.com/\"},{\"type\":\"click\",\"name\":\"赞一下我们\",\"key\":\"V1001_GOOD\"}]}]}";
  178. String rs = HttpUtil.post(url, param);
  179. Map<?, ?> map = JSONObject.parseObject(rs, Map.class);
  180. return map;
  181. }
  182. /**
  183. * XML格式字符串转换为Map
  184. *
  185. * @param strXML XML字符串
  186. * @return XML数据转换后的Map
  187. * @throws Exception
  188. */
  189. public static Map<String, String> xmlToMap(String strXML) throws Exception {
  190. try {
  191. Map<String, String> data = new HashMap<>();
  192. DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
  193. DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
  194. InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
  195. org.w3c.dom.Document doc = documentBuilder.parse(stream);
  196. doc.getDocumentElement().normalize();
  197. NodeList nodeList = doc.getDocumentElement().getChildNodes();
  198. for (int idx = 0; idx < nodeList.getLength(); ++idx) {
  199. Node node = nodeList.item(idx);
  200. if (node.getNodeType() == Node.ELEMENT_NODE) {
  201. org.w3c.dom.Element element = (org.w3c.dom.Element) node;
  202. data.put(element.getNodeName(), element.getTextContent());
  203. }
  204. }
  205. try {
  206. stream.close();
  207. } catch (Exception ex) {
  208. // do nothing
  209. }
  210. return data;
  211. } catch (Exception ex) {
  212. log.error("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML);
  213. throw ex;
  214. }
  215. }
  216. /**
  217. * 将Map转换为XML格式的字符串
  218. *
  219. * @param data Map类型数据
  220. * @return XML格式的字符串
  221. * @throws Exception
  222. */
  223. public static String mapToXml(Map<String, String> data) throws Exception {
  224. DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
  225. DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();
  226. org.w3c.dom.Document document = documentBuilder.newDocument();
  227. org.w3c.dom.Element root = document.createElement("xml");
  228. document.appendChild(root);
  229. for (String key: data.keySet()) {
  230. String value = data.get(key);
  231. if (value == null) {
  232. value = "";
  233. }
  234. value = value.trim();
  235. org.w3c.dom.Element filed = document.createElement(key);
  236. filed.appendChild(document.createTextNode(value));
  237. root.appendChild(filed);
  238. }
  239. TransformerFactory tf = TransformerFactory.newInstance();
  240. Transformer transformer = tf.newTransformer();
  241. DOMSource source = new DOMSource(document);
  242. transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
  243. transformer.setOutputProperty(OutputKeys.INDENT, "yes");
  244. StringWriter writer = new StringWriter();
  245. StreamResult result = new StreamResult(writer);
  246. transformer.transform(source, result);
  247. String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
  248. try {
  249. writer.close();
  250. } catch (Exception ex) {
  251. }
  252. return output;
  253. }
  254. }