前端
wxml
<button name='phone' class='phone' value='{{userInfo.phone}}' wx:if="{{!userInfo.phone}}" bindgetphonenumber="getPhoneNumber" hover-class='none' open-type='getPhoneNumber'>点击获取
</button>
js
import { wxGetPhoneNumber } from "../../../api/miniapp/auth"
import { showErrorToast } from '../../../utils/util';
const app = getApp();Page({data: {userInfo: {},hasLogin: false},onShow: function () {let userInfo = wx.getStorageSync('userInfo');this.setData({userInfo: userInfo,hasLogin: true});},getPhoneNumber: function (e) {console.log('手机号获取',e);let that = this;if (e.detail.errMsg !== "getPhoneNumber:ok") {return;}if (!this.data.hasLogin) {wx.showToast({title: '绑定失败:请先登录',icon: 'none',duration: 2000});return;}wxGetPhoneNumber(e.detail.iv,e.detail.encryptedData).then((res) => {let userInfo = wx.getStorageSync('userInfo');userInfo.phone = res.data.phone;wx.setStorageSync('userInfo', userInfo);that.setData({userInfo: userInfo,hasLogin: true});wx.showToast({title: '绑定手机号成功',icon: 'success',duration: 2000});}).catch((error)=>{showErrorToast('绑定手机号失败');})}
})
export function wxGetPhoneNumber(iv,encryptedData) {return new Promise(function (resolve, reject) {wxlogin().then((res) => {app.wxRequest("/api/weixinopen/wxphonenumber", "GET", {code: res.code, //临时授权凭证iv: iv,encryptedData: encryptedData}).then(res => {if (res.code === 200) {resolve(res);} else {reject(res);}}).catch((error) => {reject(error);});}).catch((error) => {reject(error);})})
}
后端
- 创建OpenIdAndSessionKey.cs类
public class OpenIdAndSessionKey
{public string openid { get; set; }public string session_key { get; set; }public string errcode { get; set; }public string errmsg { get; set; }
}
- 请求https://api.weixin.qq.com/sns/jscode2session接口并传入参数
string text = "?appid=" + weixinOpenSettings.AppId + "&secret=" + weixinOpenSettings.AppSecret + "&js_code=" + code + "&grant_type=authorization_code";
string requestUri = "https://api.weixin.qq.com/sns/jscode2session" + text;
using HttpClient httpClient = new HttpClient();
byte[] wxresult = httpClient.GetByteArrayAsync(requestUri).Result;
var oiask = JsonConvert.DeserializeObject<OpenIdAndSessionKey>(Encoding.UTF8.GetString(wxresult));
- 创建WeixinAppPhoneNumber.cs
public class WeixinAppPhoneNumber{public class Watermark{public string appid { get; set; }public string timestamp { get; set; }}public string phoneNumber { get; set; }public string purePhoneNumber { get; set; }public string countryCode { get; set; }public Watermark watermark { get; set; }}
- 创建类Cryptography和方法AES_decrypt
public static string AES_decrypt(string encryptedData, string Session_key, string IV){try{byte[] array = Convert.FromBase64String(encryptedData);byte[] bytes = new RijndaelManaged{Key = Convert.FromBase64String(Session_key),IV = Convert.FromBase64String(IV),Mode = CipherMode.CBC,Padding = PaddingMode.PKCS7}.CreateDecryptor().TransformFinalBlock(array, 0, array.Length);return Encoding.Default.GetString(bytes);}catch (Exception){return "";}}
- 调用解密方法,WeixinAppPhoneNumber的phoneNumber拿到手机号。
WeixinAppPhoneNumber weixinAppPhoneNumber = JsonConvert.DeserializeObject<WeixinAppPhoneNumber>(Cryptography.AES_decrypt(encryptedData, oiask.session_key, iv));
效果
手机
微信开发者工具
可以看到返回信息中并没有手机号,可以将返回的iv和encryptedData作为参数调用用户的后台服务器,由后台去获取对应的手机号然后返回给前端小程序。
注意事项
- 如果你用的是正式appid,获取手机号时可能出现以下问题,提示“getPhoneNumber:fail no permission”,如下图所示
目前了解到的解决办法有两个
- 需要通过微信认证,通过该认证需要企业账号,且付费300元(Pass)。
注:如果需要去认证,打开微信小程序管理界面,在底部头像处悬浮鼠标,找到“账号设置”选项并点击,在界面右侧“基本设置”选项卡下找到“微信认证”选项,点击右边的“去认证”链接按要求认证即可。 - 使用微信测试号。
- 提示“getPhoneNumber:fail Error: 用户绑定的手机需要进行验证,请在客户端完成短信验证”。
在微信小程序开发平台上使用微信测试号获取手机号的时候会显示此错误信息,解决办法即在微信小程序开发工具上点击“预览”,然后用手机扫描二维码,在手机上获取手机号并填写验证码,以后再在微信小程序上操作便会有授权弹窗出现。