本文简单介绍uni-app 在app端做VX登录的操作,并赋实际例子
如何进行VX授权登录?
如何不在代码暴露 appsecret 还能进行登录
uni-app app的VX授权登录,使用h5+的方式实现,前端代码无需显示密钥,由后台完成登录,前端只关注检查服务商,获取相关信息交与后端处理,完成登录流程
开始
老规矩,先完成申请账号,新建app应用,开通登录权限,获取appid 等一条龙操作在看以下步骤
- zc账号指引
open.weixin.qq.com/
- 创建应用 (详细过程省略)
进入VX公众创建应用,通过后将appid 和 密钥 保存下来
- 配置 (以下为关键代码及操作)
如下图所示,只需填写appid,密钥等隐私信息无需填写在应用内
由于苹果iOS 13系统版本安全升级,VXSDK1.8.6版本要求支持Universal Links方式跳转,以便进行合法性校验,提升安全性。
ios平台通用链接配置指引 ask.dcloud.net.cn/article/364…
- 解析APPVX授权登录
获取授权服务商 以下操作用于检测服务商,并获取VX授权对象返回
// 获取服务
getServices() {
let weixinService = null; // 可用的登录授权服务
// #ifdef APP-PLUS
return new Promise((resolve, reject) => {
plus.oauth.getServices((services) => {
if (services && services.length) {
// 遍历授权服务数组
for (let i = 0, len = services.length; i < len; i++) {
if (services.id === 'weixin') {
weixinService = services; // VX授权对象
break;
}
}
if (!weixinService) {
this.showToast('没有VX登录授权服务')
reject()
}
resolve(weixinService)
} else {
this.showToast('暂无可用的登录授权服务')
reject()
}
},(error) => {
this.showToast('授权失败')
reject()
})
})
// #endif
},
获取code
// APP获取code
doLogin() {
// #ifdef APP-PLUS
if (this.isLogin) return
this.isLogin = true
// 返回VX授权对象
this.getServices().then(weixinService => {
weixinService.authorize((event) => { //此处获取code的关键
this.loginApi(event.code) // 调用后台登录
}, (error) => {
this.showToast('授权失败')
this.isLogin = false
},{
scope:'snsapi_userinfo',
state:'authorize',
appid: this.appId
});
}).catch(err => {
this.isLogin = false
})
// #endif
},
后台登录
loginApi(code) {
uni.showLoading({
title: "正在登录..."
})
uni.request({
url: '后台请求地址',
data: {
code: code,
appid: this.appId,
},
success: res => {
this.isLogin = false
uni.hideLoading();
// 根据不同后台返回失败状态
if (res && res.data.code !== 0) {
this.showToast('登录失败')
return;
}
// 登录成功执行
this.success(res.data.data)
},
fail: (err) => {
this.isLogin = false
console.log('登录失败 error', err)
}
})
}
完整示例 (功能可行,代码运行报错自行解决)
<template>
<view style="padding-top: 1px;">
<!-- #ifdef APP-PLUS -->
<view v-if="isCanUse">
<view>
<view class="header"><image :src="avatarUrl"></image></view>
<view class="content">
<view>申请获取以下权限</view>
<text>获得你的公开信息(昵称,头像、地区等)</text>
</view>
<button class="" @click="doLogin">APPVX授权登录</button>
</view>
</view>
<!-- #endif -->
</view>
</template>
<script>
const appId = '创建应用的appid'; // 此处也可以使用配置文件导入
export default {
data() {
return {
appId: appId,
avatarUrl: null,
isCanUse: true,
isLogin: false, // 登录状态 防止重复连续点击
};
},
methods: {
// 获取服务
getServices() {
let weixinService = null; // 可用的登录授权服务
// #ifdef APP-PLUS
return new Promise((resolve, reject) => {
plus.oauth.getServices((services) => {
if (services && services.length) {
// 遍历授权服务数组
for (let i = 0, len = services.length; i < len; i++) {
if (services.id === 'weixin') {
weixinService = services; // VX授权对象
break;
}
}
if (!weixinService) {
this.showToast('没有VX登录授权服务')
reject()
}
resolve(weixinService)
} else {
this.showToast('暂无可用的登录授权服务')
reject()
}
},(error) => {
this.showToast('授权失败')
reject()
})
})
// #endif
},
showToast(message) {
uni.showToast({
icon: 'none',
title: message || ''
})
},
// APP获取code
doLogin() {
// #ifdef APP-PLUS
if (this.isLogin) return
this.isLogin = true
this.getServices().then(weixinService => {
weixinService.authorize((event) => { //此处获取code的关键
this.loginApi(event.code) // 后台登录
}, (error) => {
this.showToast('授权失败')
this.isLogin = false
},{
scope:'snsapi_userinfo',
state:'authorize',
appid: this.appId
});
}).catch(err => {
this.isLogin = false
})
// #endif
},
success(data) {
//登录成功回调
uni.reLaunch({
//信息更新成功后跳转到首页
url: '/pages/index/index'
});
},
loginApi(code) {
uni.showLoading({
title: "正在登录..."
})
uni.request({
url: '后台请求地址',
data: {
code: code,
appid: this.appId,
},
success: res => {
this.isLogin = false
uni.hideLoading();
// 根据不同后台返回失败状态
if (res && res.data.code !== 0) {
this.showToast('登录失败')
return;
}
// 登录成功
this.success(res.data.data)
},
fail: (err) => {
this.isLogin = false
console.log('登录失败 error', err)
}
})
}
}
};
</script>
<style>
.header {
margin: 90rpx 0 90rpx 50rpx;
border-bottom: 1px solid #ccc;
text-align: center;
width: 650rpx;
height: 300rpx;
line-height: 450rpx;
}
.header image {
width: 200rpx;
height: 200rpx;
}
.content {
margin-left: 50rpx;
margin-bottom: 90rpx;
}
.content text {
display: block;
color: #9d9d9d;
margin-top: 40rpx;
}
.bottom {
border-radius: 80rpx;
margin: 70rpx 50rpx;
font-size: 35rpx;
}
</style>