從基礎庫 2.21.2 開始,對獲取手機號的介面進行了安全升級,以下是新版本介面使用指南。(舊版本介面目前可以繼續使用,但建議開發者使用新版本介面,以增強小程式安全性)
因為需要使用者主動觸發才能發起獲取手機號介面,所以該功能不由 API 來呼叫,需用 button 元件的點選來觸發。另外,新版本介面不再需要提前呼叫wx.login
進行登入。
注意:
需要將 button 元件 open-type
的值設定為 getPhoneNumber
,當用戶點選並同意之後,可以通過 bindgetphonenumber
事件回撥獲取到動態令牌code
,然後把code
傳到開發者後臺,並在開發者後臺呼叫微信後臺提供的 phonenumber.getPhoneNumber 介面,消費code
來換取使用者手機號。每個code
有效期為5分鐘,且只能消費一次。
注:getPhoneNumber
返回的 code
與 wx.login
返回的 code
作用是不一樣的,不能混用。
使用getphonenumber獲取回撥code
//小程式寫法 <button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">獲取手機號</button> //uni-app寫法 <button class="wx-login" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">獲取手機號</button>
呼叫伺服器的url,消費code
來換取使用者手機號
methods: { getPhoneNumber: function(e) { var that = this; var userPhone = uni.getStorageSync('userPhone'); if(userPhone != '') { getApp().globalData.userPhone = userPhone; uni.navigateTo({ url: 'personal' }); return; } if (e.detail.errMsg == "getPhoneNumber:ok") { //埠號是由後端伺服器生成 wx.request({ url: '後端服務URL', data: { code: e.detail.code }, method: "get", success: function(res) { uni.setStorageSync('userPhone', res.data); getApp().globalData.userPhone = res.data; uni.navigateTo({ url: 'personal' }); }, fail: function(res) { console.log(res.errMsg) } }) } } }
後端使用.net core設定api
"Wx": { "appid": "", "secret": "", "baseurl": "https://api.weixin.qq.com/", "getToken": "cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", "getuserphonenumber": "wxa/business/getuserphonenumber?access_token={0}" }
註冊HttpClient呼叫微信API
public void ConfigureServices(IServiceCollection services) { services.AddHttpClient("WxClient", config => { config.BaseAddress = new Uri(Configuration["Wx:baseurl"]); config.DefaultRequestHeaders.Add("Accept", "application/json"); }); }
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { GlobalContext.HttpClientFactory = app.ApplicationServices.GetService<IHttpClientFactory>(); }
獲取token方法與獲取手機號方法,通過HTTPClient呼叫獲取Token方法,用Token和Code呼叫getuserphonenumber獲取使用者手機號
using System; using System.Reflection; using System.Text; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.Hosting;using Microsoft.AspNetCore.Http; using System.Net.Http; using Newtonsoft.Json; namespace YiSha.Util { public class GlobalContext {public static IHttpClientFactory HttpClientFactory { get; set; } public static IConfiguration Configuration { get; set; }public static string Token { get; set; } public static DateTime TimeOutDate { get; set; } /// <summary> /// 獲取Token /// </summary> /// <returns>Item1 Token;Item2 是否成功</returns> public static Result GetToken() { //判斷Token是否存在 以及Token是否在有效期內 if (string.IsNullOrEmpty(Token) || TimeOutDate > DateTime.Now) { //構造請求連結 var requestBuild = Configuration["Wx:getToken"]; requestBuild = string.Format(requestBuild, Configuration["Wx:appid"], Configuration["Wx:secret"] ); using (var wxClient = HttpClientFactory.CreateClient("WxClient")) { var httpResponse = wxClient.GetAsync(requestBuild).Result; var dynamic = JsonConvert.DeserializeObject<dynamic>( httpResponse.Content.ReadAsStringAsync().Result ); if (dynamic.errmsg == null)//重新整理Token { Token = dynamic.access_token; var expires_in = Convert.ToDouble(dynamic.expires_in); TimeOutDate = DateTime.Now.AddSeconds(expires_in); return new Result(Token); } else { return new Result(errMsg:dynamic.errmsg); } } } else { return new Result(Token); } } public static Result GetUserPhoneNumber(string code) { var token = GetToken(); if(!token.isSuccess) { return token; } //構造請求連結 var requestBuild = Configuration["Wx:getuserphonenumber"]; requestBuild = string.Format(requestBuild, token.data); //建立HttpClient using (var wxClient = HttpClientFactory.CreateClient("WxClient")) { string content = $"{{\"code\":\"{code}\"}}"; byte[] data = Encoding.UTF8.GetBytes(content); var bytearray = new ByteArrayContent(data); var httpResponse = wxClient.PostAsync(requestBuild, bytearray).Result; var dynamic = JsonConvert.DeserializeObject<dynamic>( httpResponse.Content.ReadAsStringAsync().Result ); if (dynamic.errmsg == "ok") return new Result(dynamic.phone_info.phoneNumber.ToString()); else return new Result(errMsg: dynamic.errmsg.ToString()); } } /// <summary> /// 返回訊息 /// </summary> public class Result { public Result() { } /// <summary> /// 正確 /// </summary> /// <param name="data"></param> public Result(string data) { this.data = data; this.isSuccess = true; } /// <summary> /// 錯誤 /// </summary> /// <param name="errMsg"></param> /// <param name="isSuccess"></param> public Result(string errMsg,bool isSuccess = false) { this.errMsg = errMsg; this.isSuccess = isSuccess; } public string data { get; set; } public string errMsg { get; set; } public bool isSuccess { get; set; } } } }
[HttpGet] public string GetPhone(string code) { var phone = GlobalContext.GetUserPhoneNumber(code); if(!phone.isSuccess) { //錯誤處理 } return phone.data; }
檔案傳送門:
獲取手機號:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html