开发必备的条件
- 非个人开发者
- 小程序完成认证
功能实现必知
- 微信小程序获取手机号功能必须使用 button 组件的开放功能(open-type)实现
- 获取手机号之前必须调用 wx.login接口
参考文档:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html
实现步骤
- 先通过wx.login获取到 code
- 获取到 code,后台换取 session_key
换取 session_key的 url如下,其中 APPID 和 SECRET 及 JSCODE 需要换为自己的数据:
https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
换取 session_key具体实现代码如下:
const Koa = require('koa');
const app = new Koa();
const Router = require('koa-router');
const router = new Router();
const axios = require('axios');
var instance = axios.create();
//解析post
const koaBody = require('koa-body');
app.use(koaBody());
// 小程序相关配置
const config = {
AppID: '**********',
AppSecret: '**************'
}
router.post('/getWxCode', async (ctx,next) => {
let api_url = `https://api.weixin.qq.com/sns/jscode2session?appid=${config.AppID}&secret=${config.AppSecret}&js_code=${ctx.request.body.code}&grant_type=authorization_code`;
let result = await instance.get(api_url);
if (result.status == '200') {
console.log(result.data)
ctx.body = result.data
} else {
ctx.body = {
//错误处理
}
}
})
app.use(router.routes());
app.listen(3000);
console.log('3000端口监听中……')
实现过程中遇到的问题
由于服务器买的是服务商配置好的环境,对运行的 shell 脚本不熟悉,以至于不清楚如何打印日志进行调试。
后来了解到 shell 脚本中&符号放到命令最后是后台运行的意思,所以注释了 shell 脚本中的两行内容,单独执行 node 脚本,注释内容如下
# cd /data/home/***/***/bin
# node www &
以上便可以成功的拿到用户的 session_key和 openId。
数据揭秘获取手机号码
拿到了 session_key之后需要将session_key和绑定的获取手机号的方法中获取到的数据(bindgetPhoneNumber 中的 encryptedData,iv)传给 WXBizDataCrypt。
微信数据如何揭秘其实可以直接参考微信提供的示例,下载 Node 相关文件即可。
https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html
这里注意,在微信提供的 Node 示例的代码WXBizDataCrypt的 decryptData 方法中,原有的 new Buffer 方法被废弃,需做如下改动。
var sessionKey = Buffer.from(this.sessionKey, 'base64')
encryptedData = Buffer.from(encryptedData, 'base64')
iv = Buffer.from(iv, 'base64')
完整代码如下:
mpvue小程序端:
<i-button open-type="getPhoneNumber" @getphonenumber="getPhoneNumber" type="primary" long="true">立即报名</i-button>
methods: {
async getPhoneNumber (e) {
let encryptedData = e.target.encryptedData
let iv = e.target.iv
let forReqPhone = await getPhone(encryptedData)
forReqPhone.encryptedData = encryptedData
forReqPhone.iv = iv
let result = await decryptData(forReqPhone)
if (result.status === 200) {
let userPhone = result.data
} else {
// 错误处理
}
}
}
//getUrl 为 flyio 封装的方法
// 获取手机号
export async function getPhone (data = '') {
let api = '/getWxCode'
let codeData = await getLogin()
let loginData
console.log(codeData.code)
let result = await getUrl(api, 'post', {code: codeData.code})
if (result.status === 200) {
loginData = result.data
} else {
loginData = {}
}
let forReqPhone = {sessionKey: loginData.session_key}
return forReqPhone
}
// 解密 手机号
export async function decryptData (req_data = '') {
let api = '/getPhone'
let result = await getUrl(api, 'post', req_data)
return result
}
服务器端:
koa
router.post('/getWxCode', async (ctx,next) => {
let api_url = `https://api.weixin.qq.com/sns/jscode2session?appid=${config.AppID}&secret=${config.AppSecret}&js_code=${ctx.request.body.code}&grant_type=authorization_code`;
let result = await instance.get(api_url);
if (result.status == '200') {
console.log(result.data)
ctx.body = result.data
} else {
// 错误状态
ctx.body = {
}
}
})
router.post('/getPhone', async (ctx, next) => {
let data = ctx.request.body
let result = await getWXData(data)
ctx.body = result
})
/ 微信小程序解密数据
const WXBizDataCrypt = require (path.resolve(__dirname,'../utils/WXBizDataCrypt'))
async function getWXData (data) {
let {sessionKey, encryptedData, iv} = data
var pc = new WXBizDataCrypt(config.AppID, sessionKey)
var data = await pc.decryptData(encryptedData , iv)
return data.phoneNumber
}
省略文件:WXBizDataCrypt.js
【注意】:拷贝代码时请注意环境和路径!!!
网友评论