文章目录
前言
近期朋友聊起了小程序开发,遂想起之前19年在公司的一次小程序开发经历,由于专业是后端,所以当时也是踩了许多的坑,现在居然还能想起来一点,适值刚开始写博客,于是顺手回忆记录一下
背景
客户要求在原有微信公众号基础上,增加小程序端应用,希望使用小程序并能保留历史用户信息;
那么问题来了:
1.做过微信公众号开发的同学都知道,我们可以使用OpenId来辨识唯一用户身份(同一应用),但是这里涉及到多个应用,因此我采用了UnionID机制来统一公众号、小程序的用户账号;
2.原有公众号已经有现成的h5页面,我不需要重新开发一套页面,因此我采用了WebView,在小程序端嵌入原有h5页面
OpenId与UnionId
1.OpenId
openId是用户在当前公众号下的唯一标识(‘身份证’),就是说通过这个openId,就能区分在这个公众号下具体是哪个用户;
获取OpenId这里不再赘述,大致流程为:
1 第一步:用户同意授权,获取code
2 第二步:通过code换取网页授权access_token
3 第三步:刷新access_token(如果需要)
4 第四步:拉取用户信息(需scope为 snsapi_userinfo)
2.UnionId
UnionID机制的作用说明:如果开发者拥有多个移动应用、网站应用和公众帐号,可通过获取用户基本信息中的unionid来区分用户的唯一性,因为同一用户,对同一个微信开放平台下的不同应用(移动应用、网站应用和公众帐号),unionid是相同的;
3.使用UnionId实现用户账户统一
UnionID获取途径
绑定了开发者帐号的小程序,可以通过以下途径获取 UnionID。
1.开发者可以直接通过 wx.login + code2Session 获取到该用户 UnionID,无须用户授权。
2.小程序端调用云函数时,可在云函数中通过 Cloud.getWXContext 获取 UnionID。
3.用户在小程序(暂不支持小游戏)中支付完成后,开发者可以直接通过getPaidUnionId接口获取该用户的 UnionID,无需用户授权。注意:本接口仅在用户支付完成后的5分钟内有效,请开发者妥善处理。
以上这是官方文档提供的提供的说明
然而我们发现通过wx,login能获取到code,通过这个code在后台调用code2session这个接口的时候,就没有返回参数unionId
这里我直接描述一下我的获取方法:
第一步:
在微信开发平台上将原有公众号与小程序绑定
第二步:使用 wx.getUserInfo接口获取到用户的加密数据 encryptedData 和加密算法的初始向量iv,然后将 encryptdata、iv 以及 code传给后端,后端再去通过接收到的encryptedData、iv以、code 以及之前的 session_key 解密出用户的 openid、unionid 等
// 登录动作
doLogin: function () {
wx.login({
success: res => {
if (res.code) {
// 后台请求 获取openId, session_key
wx.request({
url: this.globalData.baseUrl + '/bpm/WeixinCore',
data: {
action: 'getToken',
js_code: res.code
},
success: res => {
console.log(res);
this.globalData.session_key = res.data.session_key; // session_key
// 把session_key在本地缓存
wx.setStorageSync('session_key', res.data.session_key);
console.log('-----------[app.js]session_key:' + res.data.session_key);
// 获取已授权的用户数据并解密出 unionid、openid
this.getApprovedUserInfo();
}
})
}
}
});
},
// 获取已授权的用户数据并解密出 unionid、openid
getApprovedUserInfo: function () {
// 已经授权,可以直接调用 getUserInfo 获取用户信息去后台解密,不会弹框
console.log('-----------[app.js]获取已授权的用户数据并解密');
wx.getUserInfo({
success: res => {
this.globalData.userInfo = res.userInfo; // 用户信息
this.globalData.nickName = res.userInfo.nickName; // 昵称
this.globalData.encryptedData = res.encryptedData; // 用户敏感信息
this.globalData.iv = res.iv; // 解密算法的向量
// 后台解密unionid
this.toGetUnionId();
}
})
},
// 后台解密得unionid
toGetUnionId: function () {
wx.request({
url: this.globalData.baseUrl + '/bpm/WeixinCore',
data: {
action: 'getUnionId',
encryptedData: this.globalData.encryptedData,
iv: this.globalData.iv,
session_key: wx.getStorageSync('session_key')
},
success: res => {
// 解密出unionid、openid
if (res.data.unionId) {
this.globalData.unionid = res.data.unionId;// unionid
console.log('[app.js]解密unionid:' + this.globalData.unionid);
this.globalData.openid = res.data.openId; // openid
console.log('[app.js]解密openid:' + this.globalData.openid);
this.globalData.avatarUrl = res.data.avatarUrl;// 用户头像链接
this.globalData.firstLogin = false;
// 跳转到首页
wx.redirectTo({
url: '/pages/account/account',
})
} else {
wx.showToast({
title: '登录已过期,重新登录',
icon: 'none',
})
this.doLogin();
}
},
})
},
不过最近看了文档似乎要将getUserInfo改为使用getUserProfile了,我记得这个接口改了好几次了,tx真的为所欲为
第三步:通过unionid,并结合webview,进入h5页面时,先通过原公众号接口获得公众号的openId,后台通过openId查询用户,能查询到的是则是历史用户,则将unionId更新上去,查不到则说明原先没有使用公众号(为新用户),则直接更新unionId
WebView使用遇到过的坑
一、在小程序端webview内嵌页面中无法调用h5当中原公众号的SDK
解决:
1.通过wx.miniProgram.getEnv()判断是否是小程序环境
//首先需要引入这个
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
<script>
function isMiniPrograms() {
var isMiniprogram = false;
// 判断是否是小程序打开
wx.miniProgram.getEnv(res => {
console.log(res.miniprogram)
if (res.miniprogram) {
//在小程序中
isMiniprogram = true;
}
});
return isMiniprogram;
}
</script>
2.若是小程序环境,则使用wx.miniProgram.navigateTo()从h5页面跳回小程序端
wx.miniProgram.navigateTo({
url: '/pages/xxx/xxx'//小程序页面
});
3.在小程序端调用对应的小程序SDK
二、使用WebView后,进入小程序应用首页,从首页进入详情页面时,额头的back返回导航按钮出不来
原因分析:估计是因为只在一个小程序页面(wxml)中嵌入一个webview,所以不管我们在webview嵌入的h5页面怎么跳转,在小程序端,始终认为只有一个小程序页面(wxml)
解决:使用两个小程序页面(wxml),一个webview放首页,另一个webview专门链接所有的明细页面
即大致流程为:
1.首页点击链接进入明显页面
2.h5跳转明细页面方法中判断运行环境是否为小程序环境
3.若是则:wx.miniProgram.navigateTo()并带上明细页面链接
4.小程序端进入第二个小程序页面,并将明细页面连接加载到webview