1、授权获取openId和手机号
<button class="sub_btn " v-if="!phone&&!openId" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">授权并获取手机号</button>
getPhoneNumber (e) {
console.log(e.detail,'获取手机号') // 动态令牌
// console.log(e.detail.code) // 动态令牌
// console.log(e.detail.errMsg) // 回调信息(成功失败都会返回)
// console.log(e.detail.errno) // 错误码(失败时返回)
this.phoneCode=e.detail.code
this.phoneEncryptedData=e.detail.encryptedData
this.phoneIv=e.detail.iv
//
this.login()
},
login(){
uni.login({
provider: 'weixin',
success: async (loginRes)=> {
// 打印临时凭证
console.log(loginRes.code,'code');
this.getSessionKey(loginRes.code)
// let res = await getOpenId({code:loginRes.code})
// console.log(JSON.parse(res).openId,'获取opneid')
// uni.setStorageSync('openId',JSON.parse(res).openId);
// // 获取用户信息
// uni.getUserInfo({
// provider: 'weixin',
// success: function (infoRes) {
// console.log('用户昵称为:' + infoRes.userInfo.nickName);
// console.log(infoRes);
// }
// });
}
});
},
async getSessionKey(code){
console.log('开始获取openId')
let res = await getOpenId({code})
console.log(JSON.parse(res),'获取opneid')
this.openId = JSON.parse(res).openId;
this.sessionKey = JSON.parse(res).session_key;
uni.setStorageSync('openId',JSON.parse(res).openId);
this.decrypt()
// uni.request({
// url: 'https://api.weixin.qq.com/sns/jscode2session',// 请求微信服务器
// method:'GET',
// data: {
// appid: this.appid, //你的小程序的APPID
// secret: this.secret, //你的小程序秘钥secret,
// js_code: code, //wx.login 登录成功后的code
// grant_type:'authorization_code' //此处为固定值
// },
// success: (res) => {
// console.log('获取信息',res);
// this.openId = res.data.openid;
// uni.setStorageSync('openId',res.data.openid)
// this.sessionKey = res.data.session_key;
// this.decrypt()
// }
// });
},
decrypt(){
console.log(this.sessionKey,this.phoneEncryptedData,this.phoneIv,'解密参数')
let pc = new WXBizDataCrypt(appId,this.sessionKey);
let data = pc.decryptData(this.phoneEncryptedData , this.phoneIv);
console.log(data,'解密结果') //data就是最终解密的用户信息
this.phone = data.phoneNumber // 手机号
uni.setStorageSync('phone',data.phoneNumber)
this.savePhone()
},
async savePhone(){
let res = await saveGndhSign({openId:this.openId,phone:this.phone})
console.log(res,'保存手机号')
uni.showModal({
title: '提示',
content: '是否允许订阅消息',
success: (res) =>{
if (res.confirm) {
uni.requestSubscribeMessage({
tmplIds,
success: res => {
console.log(res,'订阅消息成功')
//if(res.tmplId=='acc')
},
fail: res=>{
console.log(res,'取消订阅消息')
}
});
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
}
WXBizDataCrypt.js
var crypto = require('crypto')
function WXBizDataCrypt(appId, sessionKey) {
this.appId = appId
this.sessionKey = sessionKey
}
WXBizDataCrypt.prototype.decryptData = function (encryptedData, iv) {
// base64 decode
var sessionKey = new Buffer(this.sessionKey, 'base64')
encryptedData = new Buffer(encryptedData, 'base64')
iv = new Buffer(iv, 'base64')
try {
// 解密
var decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, iv)
// 设置自动 padding 为 true,删除填充补位
decipher.setAutoPadding(true)
var decoded = decipher.update(encryptedData, 'binary', 'utf8')
decoded += decipher.final('utf8')
decoded = JSON.parse(decoded)
} catch (err) {
throw new Error('Illegal Buffer')
}
if (decoded.watermark.appid !== this.appId) {
throw new Error('Illegal Buffer')
}
return decoded
}
module.exports = WXBizDataCrypt
2、小程序订阅消息
uni.showModal({
title: '提示',
content: '是否允许订阅消息',
success: (res) =>{
if (res.confirm) {
uni.requestSubscribeMessage({
tmplIds,//消息模版id
success: res => {
console.log(res,'订阅小程序消息成功')
//if(res.tmplId=='acc')
this.showOverlay=false
//跳转嵌套公众号页面
uni.navigateTo({
url:'/pages/official/official'
})
},
fail: res=>{
console.log(res,'取消订阅消息')
}
});
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
3、嵌套公众号H5页面
<template>
<view class="offical">
<!-- <web-view src="https://****/jidian/#/pages/authorize/authorize" @message="getMessage"></web-view> -->
<web-view :src="src" @message="getMessage"></web-view>
</view>
</template>
<script>
export default {
data() {
return {
//phone:
src:``
};
},
onLoad() {
let phone=uni.getStorageSync('phone')
this.src=`https://****/jidian/?phone=${phone}#/pages/authorize/authorize`
this.$forceUpdate()
},
methods: {
getMessage(e) {
console.log(e,'H5传给小程序的参数')
//获取不到--网页向应用 postMessage 时,会在特定时机(后退、组件销毁、分享)触发并收到消息。
//if(e.detail.data){
//uni.setStorageSync('wxopenId',e.detail.data[0].wxopenId);
//uni.navigateBack()
//}
}
},
}
</script>
<style lang="scss" scoped>
.offical{
width: 100%;
height: 100%;
}
</style>
4、公众号H5页面
<template>
<view class="authorize">
<view class="container">
<el-banner></el-banner>
<view class="main">
<view class="des">
微信授权是指用户在使用微信相关服务时,允许微信平台获取和使用其个人信息的行为。微信授权的主要目的是为了保障用户的合法权益,提高用户体验,同时确保平台的安全性和服务的个性化。
</view>
<view class="des">
该页面为了获取用户信息,从而根据用户身份码(openid)给用户推送订阅消息。
</view>
<view class="add_btn" @click="saveOpenId">订阅消息</view>
</view>
<el-footer></el-footer>
</view>
</view>
</template>
<script>
var jWeixin = require('jweixin-module');
export default {
data() {
return {
phone:'',
// openId:uni.getStorageSync('wxopenId')
};
},
onReady() {
console.log(jWeixin,'公众号wx对象')
console.log(uni.getStorageSync('openId'),'公众号openId')
console.log(uni.getStorageSync('mpopenId'),'小程序openId')
this.phone = this.GetUrlParame('phone')
console.log(this.phone,'小程序phone')
},
methods: {
getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
if (r != null) {
return unescape(r[2]);
}
return null;
},
// 截取code
GetUrlParame(parameName) {
/// 获取地址栏指定参数的值
/// <param name="parameName">参数名</param>
// 获取url中跟在问号后面的部分
var parames = window.location.search;
// 检测参数是否存在
if (parames.indexOf(parameName) > -1) {
var parameValue = "";
parameValue = parames.substring(
parames.indexOf(parameName),
parames.length
);
// 检测后面是否还有参数
if (parameValue.indexOf("&") > -1) {
// 去除后面多余的参数, 得到最终 parameName=parameValue 形式的值
parameValue = parameValue.substring(0, parameValue.indexOf("&"));
// 去掉参数名, 得到最终纯值字符串
parameValue = parameValue.replace(parameName + "=", "");
return parameValue;
}
return "";
}
},
//保存公众号opneId以便推送消息
saveOpenId() {
console.log(uni.getStorageSync('openId'),uni.getStorageSync('wxopenId'),'获取openId');
uni.request({
url:'https://*****/fmis-api/gndh/wx/about/savePublicGndhSign',
method:'POST',
header: {
'content-type': 'application/json' // 根据后端要求设置合适的Content-Type
},
data: {
openId:uni.getStorageSync('wxopenId'),
phone:this.phone?this.phone:uni.getStorageSync('wxphone')
},
dataType: "json",
success: (res) => {
console.log(res,uni.getStorageSync('openId'),'保存公众号openId');
console.log(res.data.code,'res.code')
// uni.showToast({
// title:JSON.stringify(res)
// })
//H5页面
//code=1成功
uni.showToast({
title:'授权成功',
icon:'success',
duration:3000,
success: () => {
if(jWeixin.miniProgram){
// webview代码块js,需要特别注意,得先返回再去postMessage
// jWeixin.miniProgram.navigateBack({
// delta: 1
// })
// jWeixin.miniProgram.postMessage({
// openId: uni.getStorageSync('openId')
// })
setTimeout(()=>{
jWeixin.miniProgram.redirectTo({
url:`/pages/index/index?wxopenId=${uni.getStorageSync('openId')}`
})
jWeixin.miniProgram.postMessage({ data: {wxopenId: uni.getStorageSync('openId')}})
},2000)
}
}
})
// if(res.data.code){
// }else{
// uni.showToast({
// title:'授权失败',
// icon:'error',
// duration:3000,
// success: () => {
// if(jWeixin.miniProgram){
// // webview代码块js,需要特别注意,得先返回再去postMessage
// jWeixin.miniProgram.navigateBack({
// delta: 1
// })
// }
// }
// })
// }
}
})
}
},
}
</script>
<style lang="scss" scoped>
.authorize{
width:100%;
height: 100%;
.add_btn{
width:620rpx;
height: 100rpx;
border-radius: 50rpx;
background-color: $uni-default-color;
color: #fff;
text-align: center;
line-height: 100rpx;
margin:0 auto;
}
.container{
width:100%;
height: 100%;
display: flex;
flex-direction: column;
.main{
width: 95%;
margin:20rpx auto;
flex:1;
background-color: rgba(255, 255, 255, 0.5);
padding: 29px 19px;
border-radius: 20rpx;
.des{
text-indent: 2em;
line-height: 50rpx;
margin-bottom: 20rpx;
}
}
}
}
</style>
5、跳转回程序获取公众号授权的opneId
onLoad(options) {
console.log(options,'公众号传参')
if(options.wxopenId){
uni.setStorageSync('wxopenId',options.wxopenId)
this.wxopenId=options.wxopenId
this.showOverlay=false
this.$forceUpdate()
}
},
6、后端根据opneId给公众号推送消息