WeChatUtil.java 9.9 KB

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