持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
1、背景
最近在做个需求,需要获取客户端的手机号,开始本以为小程序可以直接获取到,但是到后来前端告诉我需要后端调接口得到,人傻了,赶紧百度一下呗,但是找到的几乎都是以这种方式去获取的,但是我每一次调用成功的,返回的结果都是什么 code 无效之类的,没办法只好在官网上找了
String res = SendHttps.sendGet("https://api.weixin.qq.com/sns/jscode2session", "appid=" + appId + "&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code");
2、最新版本获取手机号步骤
小程序官网链接,点击进入:developers.weixin.qq.com/miniprogram…
2.1、获取access_token
在最新版本中,要想获取客户端的手机号需要2步,第一步获取 access_token
// 申请好小程序会有这二个值的
// appId:小程序的appId
// appSecret:小程序密钥
//调用微信接口获取access_token
String accessTokenResponse = SendHttpsUtil.sendGet(accessTokenUrl, "grant_type=client_credential&appid=" + appId + "&secret=" + appSecret);
//将返回结构进行格式化,获取真正的access_token的值
net.sf.json.JSONObject accessTokenResponseObject = net.sf.json.JSONObject.fromObject(accessTokenResponse);
String access_token = accessTokenResponseObject.getString("access_token");
2.2、通过code和access_token获取用户手机号
说实话,这个接口有点坑的,获取手机号是POST方法,但是access_token确实拼接在URL后面的,很多人一开始把 code 和 access_token二个参数都放到body中,就会调用失败
//拼接url,access_token就是2.1获取到的access_token的值
String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + access_token;
//获取手机号,这里要注意的是 code是放在body里面的,access_token是放在URL上的
String res = SendHttpsUtil.doPost(code,url);
net.sf.json.JSONObject resultObject = net.sf.json.JSONObject.fromObject(res);
net.sf.json.JSONObject phoneInfoObject = net.sf.json.JSONObject.fromObject(resultObject.get("phone_info"));
String phoneNumber = phoneInfoObject.getString("phoneNumber");
3、完整代码
3.1、http调用工具类
package com.util;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.apache.http.util.TextUtils;
import org.springframework.util.StreamUtils;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SendHttpsUtil {
/**
* 向指定URL发送GET方法的请求
*
* @param url 发送请求的URL
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return URL 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param) {
String result = "";
BufferedReader in = null;
try {
String urlNameString = url + "?" + param;
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立实际的连接
connection.connect();
// 获取所有响应头字段
Map<String, List<String>> map = connection.getHeaderFields();
// 遍历所有的响应头字段
for (String key : map.keySet()) {
System.out.println(key + "--->" + map.get(key));
}
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
connection.getInputStream(), "utf-8"));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
public static String doPost(String code,String url) {
JSONObject jsonObject = JSONUtil.createObj();
jsonObject.put("code", code);
String body = HttpRequest
.post(url)
.header("Content-Type", "application/json")
.body(jsonObject.toString())
.execute()
.body();
return body;
}
}
3.2、前端发送code参数到后端,后端返回客户端手机号
@Value("${appSecret}")
public String appId;
@Value("${appSecret}")
public String appSecret;
@Value("${accessTokenUrl}")
public String accessTokenUrl;
@Value("${getPhoneUrl}")
public String getPhoneUrl;
/**
* 获取客户端手机号
*/
@PostMapping(value = "/getPhoneNumber", produces = "application/json;charset=utf-8")
public R getPhoneNumber(@RequestBody SessionKeyDTO sessionKeyDTO) {
JSONObject result = new JSONObject();
String jsonPrettyStr = JSONUtil.toJsonPrettyStr(sessionKeyDTO);
JSONObject object = JSON.parseObject(jsonPrettyStr);
String code = object.getString("codeStr");
if (StringUtil.isBlank(code)) {
return R.fail("参数为空");
}
//获取access_token
String accessTokenResponse = SendHttpsUtil.sendGet(accessTokenUrl, "grant_type=client_credential&appid=" + appId + "&secret=" + appSecret);
net.sf.json.JSONObject accessTokenResponseObject = net.sf.json.JSONObject.fromObject(accessTokenResponse);
String access_token = accessTokenResponseObject.getString("access_token");
String url = getPhoneUrl + access_token;
String res = SendHttpsUtil.doPost(code,url);
net.sf.json.JSONObject resultObject = net.sf.json.JSONObject.fromObject(res);
net.sf.json.JSONObject phoneInfoObject = net.sf.json.JSONObject.fromObject(resultObject.get("phone_info"));
String phoneNumber = phoneInfoObject.getString("phoneNumber");
result.put("mobile", phoneNumber);
return R.ok(result);
}
3.3、后端接收code参数DTO类
@Data
public class SessionKeyDTO{
private String codeStr;
}
3.4、相关配置信息
appId: 你的appId
appSecret: 你的小程序密钥
accessTokenUrl: https://api.weixin.qq.com/cgi-bin/token
getPhoneUrl: https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=