WxPhoneNumberUtils.java 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. package com.dtb.portal.util;
  2. import com.alibaba.fastjson.JSONObject;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.apache.commons.lang3.StringUtils;
  5. import org.apache.http.HttpEntity;
  6. import org.apache.http.client.methods.CloseableHttpResponse;
  7. import org.apache.http.client.methods.HttpGet;
  8. import org.apache.http.client.methods.HttpPost;
  9. import org.apache.http.entity.StringEntity;
  10. import org.apache.http.impl.client.CloseableHttpClient;
  11. import org.apache.http.impl.client.HttpClients;
  12. import org.apache.http.util.EntityUtils;
  13. @Slf4j
  14. public class WxPhoneNumberUtils {
  15. /**
  16. * 获取微信手机号和openId
  17. */
  18. public static JSONObject getPhoneNumberAndOpenId(String appId, String appSecret, String phoneCode, String loginCode) {
  19. try {
  20. // 1. 通过登录code获取session_key和openid
  21. String url = String.format(
  22. "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
  23. appId, appSecret, loginCode);
  24. JSONObject sessionResult = httpGet(url);
  25. String sessionKey = sessionResult.getString("session_key");
  26. String openId = sessionResult.getString("openid");
  27. String unionId = sessionResult.getString("unionid");
  28. if (StringUtils.isBlank(sessionKey)) {
  29. throw new RuntimeException("获取session_key失败");
  30. }
  31. // 2. 通过手机号code获取手机号
  32. url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber";
  33. String accessToken = getAccessToken(appId, appSecret);
  34. url = url + "?access_token=" + accessToken;
  35. // 构建请求体
  36. JSONObject requestBody = new JSONObject();
  37. requestBody.put("code", phoneCode);
  38. // 发送POST请求
  39. JSONObject phoneResult = httpPost(url, requestBody);
  40. log.info("获取手机号结果: {}", phoneResult);
  41. if (phoneResult.getInteger("errcode") != 0) {
  42. throw new RuntimeException("获取手机号失败: " + phoneResult.getString("errmsg"));
  43. }
  44. String phoneNumber = phoneResult.getJSONObject("phone_info").getString("phoneNumber");
  45. // 3. 返回结果
  46. JSONObject result = new JSONObject();
  47. result.put("phoneNumber", phoneNumber);
  48. result.put("openId", openId);
  49. result.put("unionId", unionId);
  50. return result;
  51. } catch (Exception e) {
  52. log.error("获取微信手机号失败", e);
  53. throw new RuntimeException("获取微信手机号失败: " + e.getMessage());
  54. }
  55. }
  56. /**
  57. * 获取APP微信登录的openId
  58. */
  59. public static JSONObject getOpenIdByCode(String appId, String appSecret, String code) {
  60. try {
  61. // 通过code获取access_token和openid
  62. String url = String.format(
  63. "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code",
  64. appId, appSecret, code);
  65. log.info("请求微信OAuth2接口URL: {}", url);
  66. JSONObject result = httpGet(url);
  67. log.info("微信OAuth2接口返回: {}", result);
  68. // 如果返回错误,尝试使用替代接口
  69. if (result.containsKey("errcode") && result.getIntValue("errcode") != 0) {
  70. // 尝试使用替代接口
  71. url = String.format(
  72. "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
  73. appId, appSecret, code);
  74. log.info("尝试替代接口URL: {}", url);
  75. result = httpGet(url);
  76. log.info("替代接口返回: {}", result);
  77. }
  78. // 检查错误码
  79. if (result.containsKey("errcode") && result.getIntValue("errcode") != 0) {
  80. throw new RuntimeException("微信接口返回错误: " + result.getString("errmsg"));
  81. }
  82. String accessToken = result.getString("access_token");
  83. String openId = result.getString("openid");
  84. String unionId = result.getString("unionid");
  85. if (StringUtils.isBlank(openId)) {
  86. throw new RuntimeException("获取openid失败,微信接口返回: " + result.toJSONString());
  87. }
  88. // 返回结果
  89. JSONObject response = new JSONObject();
  90. response.put("openid", openId);
  91. response.put("unionid", unionId);
  92. response.put("access_token", accessToken);
  93. return response;
  94. } catch (Exception e) {
  95. log.error("获取APP微信openId失败", e);
  96. throw new RuntimeException("获取APP微信openId失败: " + e.getMessage());
  97. }
  98. }
  99. /**
  100. * 获取access_token
  101. */
  102. private static String getAccessToken(String appId, String appSecret) {
  103. String url = String.format(
  104. "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
  105. appId, appSecret);
  106. JSONObject result = httpGet(url);
  107. return result.getString("access_token");
  108. }
  109. /**
  110. * 发送GET请求
  111. */
  112. public static JSONObject httpGet(String url) {
  113. try {
  114. CloseableHttpClient client = HttpClients.createDefault();
  115. HttpGet httpGet = new HttpGet(url);
  116. CloseableHttpResponse response = client.execute(httpGet);
  117. HttpEntity entity = response.getEntity();
  118. String result = EntityUtils.toString(entity);
  119. JSONObject jsonResult = JSONObject.parseObject(result);
  120. log.debug("HTTP GET Response: {}", jsonResult);
  121. return jsonResult;
  122. } catch (Exception e) {
  123. log.error("HTTP GET请求失败: {}", e.getMessage());
  124. throw new RuntimeException("HTTP请求失败: " + e.getMessage());
  125. }
  126. }
  127. private static JSONObject httpPost(String url, JSONObject body) {
  128. try {
  129. CloseableHttpClient client = HttpClients.createDefault();
  130. HttpPost httpPost = new HttpPost(url);
  131. // 设置请求头
  132. httpPost.setHeader("Content-Type", "application/json");
  133. // 设置请求体
  134. StringEntity entity = new StringEntity(body.toString(), "UTF-8");
  135. httpPost.setEntity(entity);
  136. // 发送请求
  137. CloseableHttpResponse response = client.execute(httpPost);
  138. HttpEntity responseEntity = response.getEntity();
  139. String result = EntityUtils.toString(responseEntity);
  140. JSONObject jsonResult = JSONObject.parseObject(result);
  141. log.debug("HTTP POST Response: {}", jsonResult);
  142. return jsonResult;
  143. } catch (Exception e) {
  144. log.error("HTTP POST请求失败: {}", e.getMessage());
  145. throw new RuntimeException("HTTP请求失败: " + e.getMessage());
  146. }
  147. }
  148. /**
  149. * 调试微信code
  150. */
  151. public static JSONObject debugCode(String appId, String appSecret, String code) {
  152. JSONObject debug = new JSONObject();
  153. try {
  154. // 获取session_key和openid
  155. String url = String.format(
  156. "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
  157. appId, appSecret, code);
  158. JSONObject sessionResult = httpGet(url);
  159. debug.put("jscode2session", sessionResult);
  160. // 获取access_token
  161. String accessToken = getAccessToken(appId, appSecret);
  162. debug.put("access_token", accessToken);
  163. // 获取手机号
  164. url = String.format(
  165. "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s",
  166. accessToken);
  167. JSONObject phoneResult = httpGet(url);
  168. debug.put("phone_result", phoneResult);
  169. return debug;
  170. } catch (Exception e) {
  171. debug.put("error", e.getMessage());
  172. return debug;
  173. }
  174. }
  175. }