在原生微信小程序中获取用户的手机号并存储需要通过微信提供的wx.login
和wx.getUserProfile
接口来完成。这些接口允许小程序获取用户信息并在用户授权后获取其手机号。以下是一个详细的实现示例和相应的代码注释。
1. 配置小程序的权限
在实现获取手机号功能之前,需要确保小程序有获取用户信息和手机号的权限。在app.json
文件中添加如下代码:
{
"pages": [
"pages/index/index"
],
"permission": {
"scope.userInfo": {
"desc": "获取用户信息以便更好地提供服务"
},
"scope.userPhoneNumber": {
"desc": "获取用户手机号以便更好地提供服务"
}
}
}
2. 登录并获取临时登录凭证(code)
首先,需要调用wx.login
接口获取用户的临时登录凭证code
,然后使用这个code
去换取用户的session_key,这是后续解密用户手机号的关键。以下是在index.js
中的实现:
Page({
data: {
userInfo: null,
hasUserInfo: false,
canIUseGetUserProfile: false,
phoneNumber: ''
},
onLoad() {
// 判断是否可以使用getUserProfile
if (wx.getUserProfile) {
this.setData({
canIUseGetUserProfile: true
})
}
},
getUserProfile(e) {
wx.getUserProfile({
desc: '用于完善用户资料',
success: (res) => {
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
this.getPhoneNumber();
}
})
},
getPhoneNumber() {
wx.login({
success: res => {
const code = res.code;
// 发送code到后台换取 openId, sessionKey, unionId
if (code) {
wx.request({
url: 'https://yourserver.com/onLogin',
method: 'POST',
data: {
code: code
},
success: function (res) {
if (res.statusCode === 200) {
// 成功获取 session_key 等信息
wx.setStorageSync('sessionKey', res.data.sessionKey);
} else {
console.error('登录失败!', res.errMsg);
}
},
fail: function (err) {
console.error('请求失败!', err);
}
});
} else {
console.error('登录失败!', res.errMsg);
}
}
});
}
})
3. 获取手机号并存储
接下来,当用户点击按钮授权获取手机号时,需要调用wx.getUserProfile
接口获取用户的基本信息,然后通过微信提供的按钮组件<button open-type="getPhoneNumber">
来获取用户的手机号。以下是在index.wxml
和index.js
中的实现:
index.wxml
:
<view class="container">
<button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile">获取用户信息</button>
<button wx:if="{{hasUserInfo}}" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取手机号</button>
</view>
index.js
:
Page({
data: {
userInfo: null,
hasUserInfo: false,
canIUseGetUserProfile: false,
phoneNumber: ''
},
onLoad() {
if (wx.getUserProfile) {
this.setData({
canIUseGetUserProfile: true
})
}
},
getUserProfile(e) {
wx.getUserProfile({
desc: '用于完善用户资料',
success: (res) => {
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
},
getPhoneNumber(e) {
if (e.detail.errMsg === 'getPhoneNumber:ok') {
const encryptedData = e.detail.encryptedData;
const iv = e.detail.iv;
const sessionKey = wx.getStorageSync('sessionKey');
// 发送数据到后台解密
wx.request({
url: 'https://yourserver.com/decryptData',
method: 'POST',
data: {
encryptedData: encryptedData,
iv: iv,
sessionKey: sessionKey
},
success: res => {
if (res.statusCode === 200) {
// 成功获取手机号
this.setData({
phoneNumber: res.data.phoneNumber
});
} else {
console.error('解密失败!', res.errMsg);
}
},
fail: err => {
console.error('请求失败!', err);
}
});
} else {
console.error('用户拒绝授权获取手机号');
}
}
})
4. 后端服务接口
前端代码中的请求需要后台服务配合进行解密操作。以下是一个简单的Node.js后端服务示例,使用了axios
和crypto
模块:
const express = require('express');
const axios = require('axios');
const crypto = require('crypto');
const app = express();
app.use(express.json());
const appId = 'yourAppId';
const appSecret = 'yourAppSecret';
app.post('/onLogin', async (req, res) => {
const code = req.body.code;
try {
const response = await axios.get(`https://api.weixin.qq.com/sns/jscode2session`, {
params: {
appid: appId,
secret: appSecret,
js_code: code,
grant_type: 'authorization_code'
}
});
res.json(response.data);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.post('/decryptData', (req, res) => {
const { encryptedData, iv, sessionKey } = req.body;
try {
const decodedData = decryptData(appId, sessionKey, encryptedData, iv);
res.json(decodedData);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
function decryptData(appId, sessionKey, encryptedData, iv) {
const sessionKeyBuffer = Buffer.from(sessionKey, 'base64');
const encryptedDataBuffer = Buffer.from(encryptedData, 'base64');
const ivBuffer = Buffer.from(iv, 'base64');
const decipher = crypto.createDecipheriv('aes-128-cbc', sessionKeyBuffer, ivBuffer);
decipher.setAutoPadding(true);
let decoded = decipher.update(encryptedDataBuffer, 'binary', 'utf8');
decoded += decipher.final('utf8');
const decodedData = JSON.parse(decoded);
if (decodedData.watermark.appid !== appId) {
throw new Error('Invalid Buffer');
}
return decodedData;
}
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
5. 测试和调试
最后,确保你的前后端代码都已正确配置和部署,并在微信开发者工具中进行测试。通过点击按钮授权获取用户信息和手机号,并在控制台查看相应的日志输出。
这样,你就完成了在原生微信小程序中获取用户手机号并存储的功能。如果你有任何疑问或需要进一步的帮助,请随时向我提问。