微信小程序开发交流qq群 173683895
如图:
小程序代码:
第一步,登录,获取用户的 session_key;
第二步,点击按钮调用 bindgetphonenumber 事件,通过该事件得到 encryptedData 和 iv
第三步,把session_key,encryptedData 和 iv 传递给后端解密得到用户的手机号信息
文章结尾有我的小程序util.js文件。
登录代码:(我是在app.js 里面统一封装的登录模块,如果有自己的登录模块,可以无视这段代码,把session_key放到第二段代码就可以)
//app.js
const util = require('./utils/util.js');
App({
onLaunch: function() {
var that = this;
// wx.login
that.login = (resolve) => {
wx.login({
success: (res) => {
if (res.code) {
that.loginRequest(res.code, resolve);
}
},
})
}
// session定时器
that.sessionIsExpire = (resolve) => {
const session = wx.getStorageSync('session_key');
const deadLine = wx.getStorageSync('deadline');
const nowDate = new Date().getTime();
if (session && deadLine) {
if (nowDate - deadLine >= 1000 * 60 * 60 * 24) {
that.login(resolve)
} else {
wx.checkSession({
success() {
// session_key 未过期,并且在本生命周期一直有效
resolve(session)
},
fail() {
// session_key 已经失效,需要重新执行登录流程
that.login(resolve)
}
})
}
} else {
that.login(resolve)
}
}
// 获取session
that.pro_getSession = new Promise((resolve) => {
that.sessionIsExpire(resolve)
})
// 请求login.do接口得到session
that.loginRequest = (code, resolve) => {
var url = '/login.php';
var data = {
code
}
util.request(url, 'post', data, '', (res) => {
console.log('登录了')
if (res.data.success == true) {
const session = res.session_key;
resolve(session)
wx.setStorageSync('openid', res.openid);
wx.setStorageSync('session_key', session);
wx.setStorageSync('deadline', new Date().getTime())
} else {
resolve(1)
}
}, (fail) => {
resolve(1)
})
}
},
globalData: {
userInfo: null
}
})
小程序代码片段2: 获取手机号页面的代码
// 获取手机号码
getPhoneNumber: function (e) {
console.log(e)
if (e.detail.errMsg == 'getPhoneNumber:fail') {
console.log(ErrMsg);
that.showToast_fail('未获取到手机号码');
return false;
} else if (e.detail.iv == undefined || !e.detail.iv) {
that.showToast_fail('授权失败');
return false;
} else {
// 解密手机号接口
var url = "/getTelNumber.php";
var params = {
session_key: wx.getStorageSync('session_key'),
encryptedData: e.detail.encryptedData,
iv: e.detail.iv
};
util.request(url, 'post', params, '', (res) => {
that.setData({
phone: res.data.phoneNumber,
})
wx.reLaunch({
url: '../index/index',
})
}, function () {
that.showToast_fail('获取手机号失败');
})
}
},
后端实现代码:
登录接口如图
login.php代码 (这个接口返回的是一个JSON对象)
getTelNumber.php代码如图
代码:
decryptData($encryptedData, $iv, $data );
if ($errCode == 0) {
print($data . "\n");
} else {
print($errCode . "\n");
}
?>
这里有引用到两个文件,放到相同的目录下就行
wxBizDataCrypt.php
sessionKey = $sessionKey;
$this->appid = $appid;
}
/**
* 检验数据的真实性,并且获取解密后的明文.
* @param $encryptedData string 加密的用户数据
* @param $iv string 与用户数据一同返回的初始向量
* @param $data string 解密后的原文
*
* @return int 成功0,失败返回对应的错误码
*/
public function decryptData( $encryptedData, $iv, &$data )
{
if (strlen($this->sessionKey) != 24) {
return ErrorCode::$IllegalAesKey;
}
$aesKey=base64_decode($this->sessionKey);
if (strlen($iv) != 24) {
return ErrorCode::$IllegalIv;
}
$aesIV=base64_decode($iv);
$aesCipher=base64_decode($encryptedData);
$result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
$dataObj=json_decode( $result );
if( $dataObj == NULL )
{
return ErrorCode::$IllegalBuffer;
}
if( $dataObj->watermark->appid != $this->appid )
{
return ErrorCode::$IllegalBuffer;
}
$data = $result;
return ErrorCode::$OK;
}
}
errorCode.php
* -41001: encodingAesKey 非法
* -41003: aes 解密失败
* -41004: 解密后得到的buffer非法
* -41005: base64加密失败
* -41016: base64解密失败
*
*/
class ErrorCode
{
public static $OK = 0;
public static $IllegalAesKey = -41001;
public static $IllegalIv = -41002;
public static $IllegalBuffer = -41003;
public static $DecodeBase64Error = -41004;
}
?>
小程序util.js文件
const formatTime = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()
return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}
// 网络请求
const request = function(url, method, data, msg, succ, fail, com) {
// 小程序顶部显示Loading
wx.showNavigationBarLoading();
if (msg != "") {
wx.showLoading({
title: msg
})
}
wx.request({
url: 'http://localhost/shige/minP'+url,
data: data,
header: {
'content-type': 'application/x-www-form-urlencoded'
},
method: method,
success: res => {
if (succ) succ(res);
},
fail: err => {
wx.showToast({
title: '网络错误,请稍后再试···',
icon:'none'
})
if (fail) fail(err);
},
complete: com => {
wx.hideNavigationBarLoading();
if (msg != "") {
wx.hideLoading();
}
console.log(url + ' 返回的data:', com.data);
}
})
}
const formatNumber = n => {
n = n.toString()
return n[1] ? n : '0' + n
}
module.exports = {
formatTime: formatTime,
request: request
}