package com.dtb.portal.util; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; @Slf4j public class WxPhoneNumberUtils { /** * 获取微信手机号和openId */ public static JSONObject getPhoneNumberAndOpenId(String appId, String appSecret, String phoneCode, String loginCode) { try { // 1. 通过登录code获取session_key和openid String url = String.format( "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", appId, appSecret, loginCode); JSONObject sessionResult = httpGet(url); String sessionKey = sessionResult.getString("session_key"); String openId = sessionResult.getString("openid"); String unionId = sessionResult.getString("unionid"); if (StringUtils.isBlank(sessionKey)) { throw new RuntimeException("获取session_key失败"); } // 2. 通过手机号code获取手机号 url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber"; String accessToken = getAccessToken(appId, appSecret); url = url + "?access_token=" + accessToken; // 构建请求体 JSONObject requestBody = new JSONObject(); requestBody.put("code", phoneCode); // 发送POST请求 JSONObject phoneResult = httpPost(url, requestBody); log.info("获取手机号结果: {}", phoneResult); if (phoneResult.getInteger("errcode") != 0) { throw new RuntimeException("获取手机号失败: " + phoneResult.getString("errmsg")); } String phoneNumber = phoneResult.getJSONObject("phone_info").getString("phoneNumber"); // 3. 返回结果 JSONObject result = new JSONObject(); result.put("phoneNumber", phoneNumber); result.put("openId", openId); result.put("unionId", unionId); return result; } catch (Exception e) { log.error("获取微信手机号失败", e); throw new RuntimeException("获取微信手机号失败: " + e.getMessage()); } } /** * 获取APP微信登录的openId */ public static JSONObject getOpenIdByCode(String appId, String appSecret, String code) { try { // 通过code获取access_token和openid String url = String.format( "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", appId, appSecret, code); log.info("请求微信OAuth2接口URL: {}", url); JSONObject result = httpGet(url); log.info("微信OAuth2接口返回: {}", result); // 如果返回错误,尝试使用替代接口 if (result.containsKey("errcode") && result.getIntValue("errcode") != 0) { // 尝试使用替代接口 url = String.format( "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", appId, appSecret, code); log.info("尝试替代接口URL: {}", url); result = httpGet(url); log.info("替代接口返回: {}", result); } // 检查错误码 if (result.containsKey("errcode") && result.getIntValue("errcode") != 0) { throw new RuntimeException("微信接口返回错误: " + result.getString("errmsg")); } String accessToken = result.getString("access_token"); String openId = result.getString("openid"); String unionId = result.getString("unionid"); if (StringUtils.isBlank(openId)) { throw new RuntimeException("获取openid失败,微信接口返回: " + result.toJSONString()); } // 返回结果 JSONObject response = new JSONObject(); response.put("openid", openId); response.put("unionid", unionId); response.put("access_token", accessToken); return response; } catch (Exception e) { log.error("获取APP微信openId失败", e); throw new RuntimeException("获取APP微信openId失败: " + e.getMessage()); } } /** * 获取access_token */ private static String getAccessToken(String appId, String appSecret) { String url = String.format( "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appId, appSecret); JSONObject result = httpGet(url); return result.getString("access_token"); } /** * 发送GET请求 */ public static JSONObject httpGet(String url) { try { CloseableHttpClient client = HttpClients.createDefault(); HttpGet httpGet = new HttpGet(url); CloseableHttpResponse response = client.execute(httpGet); HttpEntity entity = response.getEntity(); String result = EntityUtils.toString(entity); JSONObject jsonResult = JSONObject.parseObject(result); log.debug("HTTP GET Response: {}", jsonResult); return jsonResult; } catch (Exception e) { log.error("HTTP GET请求失败: {}", e.getMessage()); throw new RuntimeException("HTTP请求失败: " + e.getMessage()); } } private static JSONObject httpPost(String url, JSONObject body) { try { CloseableHttpClient client = HttpClients.createDefault(); HttpPost httpPost = new HttpPost(url); // 设置请求头 httpPost.setHeader("Content-Type", "application/json"); // 设置请求体 StringEntity entity = new StringEntity(body.toString(), "UTF-8"); httpPost.setEntity(entity); // 发送请求 CloseableHttpResponse response = client.execute(httpPost); HttpEntity responseEntity = response.getEntity(); String result = EntityUtils.toString(responseEntity); JSONObject jsonResult = JSONObject.parseObject(result); log.debug("HTTP POST Response: {}", jsonResult); return jsonResult; } catch (Exception e) { log.error("HTTP POST请求失败: {}", e.getMessage()); throw new RuntimeException("HTTP请求失败: " + e.getMessage()); } } /** * 调试微信code */ public static JSONObject debugCode(String appId, String appSecret, String code) { JSONObject debug = new JSONObject(); try { // 获取session_key和openid String url = String.format( "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", appId, appSecret, code); JSONObject sessionResult = httpGet(url); debug.put("jscode2session", sessionResult); // 获取access_token String accessToken = getAccessToken(appId, appSecret); debug.put("access_token", accessToken); // 获取手机号 url = String.format( "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s", accessToken); JSONObject phoneResult = httpGet(url); debug.put("phone_result", phoneResult); return debug; } catch (Exception e) { debug.put("error", e.getMessage()); return debug; } } }