微信小程序获取手机号 实战

    技术2025-09-16  6

    先吐槽,由于偷懒 某度一下 没发现完整的代码可以用,需要东拼西凑,没有拿来主义的感觉。

    获取手机号

    获取微信用户绑定的手机号,需先调用wx.login接口。

    因为需要用户主动触发才能发起获取手机号接口,所以该功能不由 API 来调用,需用 button 组件的点击来触发。

    注意:目前该接口针对非个人开发者,且完成了认证的小程序开放(不包含海外主体)。需谨慎使用,若用户举报较多或被发现在不必要场景下使用,微信有权永久回收该小程序的该接口权限。

    以上是官方说的,根据官方说的实现

    https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html

    流程:

    1.通过wx.login(Object object)获取登录凭证(code)。通过凭证进而换取用户登录态信息,包括用户的唯一标识(openid)及本次登录的会话密钥(session_key)

    wx.login({ success: res => { wx.request({ url: 'http://192.168.1.128:8088/app/wx/jscodeToSession', method: "POST", header: { 'content-type': 'application/x-www-form-urlencoded', 'Accept': 'application/json' }, dataType: 'json', data: { js_code: res.code, }, success(res) { that.globalData.session_key = res.data.data.session_key; that.globalData.openid = res.data.data.openid; }, fail(res) { console.log('拉取用户openid失败,将无法正常使用开放接口等服务', res) } }); // 发送 res.code 到后台换取 openId, sessionKey, unionId } }) @RequestMapping(value = "/jscodeToSession", produces = "application/json;charset=UTF-8", method = { RequestMethod.GET,RequestMethod.POST }) @ResponseBody public Map<String,Object> jscodeToSession(String js_code) {//js_code 登录(wx.login())时获取的 code Map<String,Object> reMap = new HashMap<String,Object>(); String v_appid = "小程序 appId"; String v_secret = "小程序 appSecret"; String readInterFaceFromUrlByUTF8 = ToolUtil.readInterFaceFromUrlByUTF8("https://api.weixin.qq.com/sns/jscode2session?appid="+v_appid+"&secret="+v_secret+"&js_code="+js_code+"&grant_type=authorization_code"); JSONObject root = JSONObject.parseObject(readInterFaceFromUrlByUTF8); JSONObject data = new JSONObject(); if(root.containsKey("errcode")){ reMap.put("success", false); data.put("errcode", root.getString("errcode")); data.put("errmsg", root.getString("errmsg")); reMap.put("data", data); }else{ reMap.put("success", true); data.put("session_key", root.getString("session_key")); data.put("openid", root.getString("openid")); reMap.put("data", data); } return reMap; } public static String readInterFaceFromUrlByUTF8(String UrlStr) { return readInterFaceFromUrl(UrlStr, "utf-8"); } public static String readInterFaceFromUrl(String UrlStr, String encode) { if (UrlStr.equalsIgnoreCase("") || UrlStr == null) return ""; String reVal = ""; URL url; HttpURLConnection httpConnection = null; try { url = new URL(UrlStr); URLConnection URLconnection = url.openConnection(); httpConnection = (HttpURLConnection) URLconnection; // httpConnection.setRequestMethod("POST"); int responseCode = httpConnection.getResponseCode(); System.out.println(responseCode); if (responseCode == HttpURLConnection.HTTP_OK) { InputStream urlStream = httpConnection.getInputStream(); BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(urlStream, encode)); String sCurrentLine = ""; String sTotalString = ""; while ((sCurrentLine = bufferedReader.readLine()) != null) { sTotalString += sCurrentLine; } reVal = sTotalString; } else { System.err.println("读取接口失败"); } } catch (Exception e) { // e.printStackTrace(); System.err.println("读取接口异常"); reVal = ""; } finally { httpConnection.disconnect(); } return reVal; }

    2.通过button组件来发起获取手机号接口,将事件回调获取到微信服务器返回的加密数据, 再结合 session_key 以及 app_id 进行解密获取手机号

    // button组建 放在 wxml里面 <button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button> //放到对应的js里面 getPhoneNumber(e) { if (e.detail.errMsg == "getPhoneNumber:ok") { wx.request({ url: 'http://192.168.1.128:8088/app/wx/getPhoneNumber', method: "POST", header: { 'content-type': 'application/x-www-form-urlencoded', 'Accept': 'application/json' }, dataType: 'json', data: { iv: e.detail.iv, encryptedData: e.detail.encryptedData, session_key: app.globalData.session_key }, success(res) { console.log(res); }, fail(res) { } }); } } @RequestMapping(value = "/getPhoneNumber", produces = "application/json;charset=UTF-8", method = { RequestMethod.GET,RequestMethod.POST }) @ResponseBody public Map<String,Object> getPhoneNumber(String session_key,String encryptedData,String iv) { Map<String,Object> reMap = new HashMap<String,Object>(); String v_result = analysisPhoneNumber(session_key,encryptedData,iv); JSONObject resultObject = JSONObject.parseObject(v_result); reMap.put("phoneNumber", resultObject.getString("phoneNumber")); reMap.put("purePhoneNumber", resultObject.getString("purePhoneNumber")); reMap.put("countryCode", resultObject.getString("countryCode"));//国家代码 return reMap; } /** * 解密手机号 * @author * @param session_key * @param encryptedData * @param iv * @return */ private static String analysisPhoneNumber(String session_key,String encryptedData,String iv ){ byte[] dataByte = Base64.decode(encryptedData); byte[] keyByte = Base64.decode(session_key); byte[] ivByte = Base64.decode(iv); try { int base = 16; if (keyByte.length % base != 0) { int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0); byte[] temp = new byte[groups * base]; Arrays.fill(temp, (byte) 0); System.arraycopy(keyByte, 0, temp, 0, keyByte.length); keyByte = temp; } Security.addProvider(new BouncyCastleProvider()); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); SecretKeySpec spec = new SecretKeySpec(keyByte, "AES"); AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES"); parameters.init(new IvParameterSpec(ivByte)); cipher.init(Cipher.DECRYPT_MODE, spec, parameters); byte[] resultByte = cipher.doFinal(dataByte); if (null != resultByte && resultByte.length > 0) { String result = new String(resultByte, "UTF-8"); return result; } } catch (Exception e) { e.printStackTrace(); } return null; }

    至此完事。

     

     

    Processed: 0.009, SQL: 9