Uniapp 混合开发实现授权登录功能(兼容多平台)
·
在 Uniapp 中实现兼容微信 H5、支付宝 H5、微信小程序和支付宝小程序的授权登录功能,需要根据不同平台采用不同的授权方式。下面我将提供一个完整的解决方案。
一、整体思路
- 判断运行平台:使用
uni.getSystemInfoSync().platform或条件编译区分不同平台 - 各平台授权方式:
- 微信小程序:使用
wx.getUserProfile或wx.getUserInfo - 支付宝小程序:使用
my.getAuthCode - 微信 H5:使用 OAuth2.0 授权(需服务端配合)
- 支付宝 H5:使用支付宝 JS SDK 授权
- 微信小程序:使用
二、代码实现
1. 公共工具方法(utils/auth.js)
javascript
/** |
* 统一授权登录方法 |
* @param {Object} options 配置项 |
* @param {Function} success 成功回调 |
* @param {Function} fail 失败回调 |
*/ |
export function unifiedLogin(options = {}, success, fail) { |
const defaultOptions = { |
// 可传入的自定义参数 |
} |
const finalOptions = {...defaultOptions, ...options} |
// #ifdef MP-WEIXIN |
wechatMiniProgramLogin(finalOptions, success, fail) |
// #endif |
// #ifdef MP-ALIPAY |
alipayMiniProgramLogin(finalOptions, success, fail) |
// #endif |
// #ifdef H5 |
const ua = navigator.userAgent.toLowerCase() |
if (ua.match(/micromessenger/i)) { |
// 微信H5 |
wechatH5Login(finalOptions, success, fail) |
} else if (ua.match(/alipayclient/i)) { |
// 支付宝H5 |
alipayH5Login(finalOptions, success, fail) |
} else { |
fail && fail({errMsg: '不支持的H5环境'}) |
} |
// #endif |
} |
// 微信小程序授权 |
function wechatMiniProgramLogin(options, success, fail) { |
uni.getUserProfile({ |
desc: '用于完善会员资料', |
success: (res) => { |
const { userInfo, encryptedData, iv } = res |
// 获取code |
uni.login({ |
provider: 'weixin', |
success: (loginRes) => { |
const code = loginRes.code |
// 这里可以将code、userInfo等发送到服务端进行登录 |
success && success({ |
...userInfo, |
code, |
platform: 'wechat-mini' |
}) |
}, |
fail: (err) => { |
fail && fail(err) |
} |
}) |
}, |
fail: (err) => { |
// 用户拒绝授权 |
if (err.errMsg.includes('deny') || err.errMsg.includes('auth deny')) { |
uni.showModal({ |
title: '提示', |
content: '您拒绝了授权,部分功能将无法使用', |
showCancel: false |
}) |
} |
fail && fail(err) |
} |
}) |
} |
// 支付宝小程序授权 |
function alipayMiniProgramLogin(options, success, fail) { |
uni.getAuthCode({ |
scopes: ['auth_user'], |
success: (res) => { |
const authCode = res.authCode |
// 获取用户信息 |
uni.getUserInfo({ |
success: (userRes) => { |
success && success({ |
...userRes.userInfo, |
authCode, |
platform: 'alipay-mini' |
}) |
}, |
fail: (err) => { |
fail && fail(err) |
} |
}) |
}, |
fail: (err) => { |
fail && fail(err) |
} |
}) |
} |
// 微信H5授权 |
function wechatH5Login(options, success, fail) { |
// 微信H5需要服务端配合,这里假设服务端提供了授权URL |
const appid = '你的微信APPID' // 实际项目中应从配置中获取 |
const redirectUri = encodeURIComponent('你的回调地址') |
const state = '自定义状态参数' |
// 跳转到微信授权页面 |
const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirectUri}&response_type=code&scope=snsapi_userinfo&state=${state}#wechat_redirect` |
// 在H5中直接跳转 |
window.location.href = authUrl |
// 实际项目中,应该在回调页面处理授权结果 |
// 这里只是示例,实际回调处理需要服务端配合 |
} |
// 支付宝H5授权 |
function alipayH5Login(options, success, fail) { |
// 引入支付宝JS SDK |
if (window.AlipayJSBridge) { |
AlipayJSBridge.call('auth', { |
scopes: ['auth_user'], |
success: (res) => { |
const authCode = res.authCode |
// 这里应该将authCode发送到服务端换取用户信息 |
success && success({ |
authCode, |
platform: 'alipay-h5' |
}) |
}, |
fail: (err) => { |
fail && fail(err) |
} |
}) |
} else { |
// 如果JSBridge未准备好,监听事件 |
document.addEventListener('AlipayJSBridgeReady', () => { |
AlipayJSBridge.call('auth', { |
scopes: ['auth_user'], |
success: (res) => { |
const authCode = res.authCode |
success && success({ |
authCode, |
platform: 'alipay-h5' |
}) |
}, |
fail: (err) => { |
fail && fail(err) |
} |
}) |
}, false) |
} |
} |
2. 页面中使用
vue
<template> |
<view class="container"> |
<button @click="handleLogin">授权登录</button> |
</view> |
</template> |
<script> |
import { unifiedLogin } from '@/utils/auth.js' |
export default { |
methods: { |
handleLogin() { |
uni.showLoading({ title: '登录中...' }) |
unifiedLogin( |
{}, // 可传入自定义参数 |
(res) => { |
uni.hideLoading() |
console.log('授权成功', res) |
// 根据平台处理登录结果 |
if (res.platform === 'wechat-mini' || res.platform === 'alipay-mini') { |
// 小程序端处理 |
this.handleMiniLogin(res) |
} else if (res.platform === 'wechat-h5' || res.platform === 'alipay-h5') { |
// H5端处理(实际H5回调处理应在单独的回调页面) |
this.handleH5Login(res) |
} |
}, |
(err) => { |
uni.hideLoading() |
console.error('授权失败', err) |
uni.showToast({ |
title: '授权失败: ' + (err.errMsg || '未知错误'), |
icon: 'none' |
}) |
} |
) |
}, |
handleMiniLogin(res) { |
// 调用服务端接口,传递code和用户信息 |
this.$api.loginByMiniProgram({ |
code: res.code || res.authCode, |
userInfo: res, |
platform: res.platform |
}).then(loginRes => { |
// 登录成功处理 |
this.$store.dispatch('user/login', loginRes.data) |
uni.navigateBack() |
}).catch(err => { |
uni.showToast({ title: '登录失败', icon: 'none' }) |
}) |
}, |
handleH5Login(res) { |
// H5端通常在回调页面处理 |
// 这里可以展示一个提示,让用户知道授权已发起 |
uni.showToast({ |
title: '正在跳转授权页面...', |
icon: 'none' |
}) |
} |
} |
} |
</script> |
3. 微信H5回调页面处理
对于微信H5,你需要创建一个专门的回调页面来处理授权回调:
javascript
// pages/wechat-callback/index.vue |
export default { |
onLoad(options) { |
// 微信授权后会重定向到这里,并带上code和state参数 |
const { code, state } = options |
if (code) { |
// 调用服务端接口,用code换取用户信息 |
this.$api.loginByWechatH5({ code, state }).then(res => { |
// 登录成功处理 |
this.$store.dispatch('user/login', res.data) |
// 跳转到首页或其他页面 |
const redirect = uni.getStorageSync('wechat_redirect') || '/' |
uni.removeStorageSync('wechat_redirect') |
uni.redirectTo({ url: redirect }) |
}).catch(err => { |
uni.showToast({ title: '登录失败', icon: 'none' }) |
}) |
} else { |
uni.showToast({ title: '授权失败', icon: 'none' }) |
uni.navigateBack() |
} |
} |
} |
三、服务端配合要点
- 微信小程序:
- 使用
code换取session_key和openid - 解密
encryptedData获取用户信息
- 使用
- 支付宝小程序:
- 使用
authCode换取user_id和访问令牌 - 调用
alipay.user.info.share获取用户信息
- 使用
- 微信H5:
- 使用
code换取access_token和openid - 使用
access_token获取用户信息
- 使用
- 支付宝H5:
- 使用
authCode换取用户信息
- 使用
四、注意事项
- 小程序端:
- 微信小程序从2021年4月起,
wx.getUserInfo不再弹出授权窗口,需使用wx.getUserProfile - 支付宝小程序需要配置
auth_user权限
- 微信小程序从2021年4月起,
- H5端:
- 微信H5需要配置JS-SDK安全域名
- 支付宝H5需要引入支付宝JS SDK
- 都需要服务端支持OAuth2.0流程
- 用户体验:
- 在用户拒绝授权时给出明确提示
- 提供明确的授权用途说明
- 考虑未授权状态下的功能降级
- 隐私政策:
- 确保符合各平台的隐私政策要求
- 在用户首次使用时展示隐私协议
五、扩展建议
- 可以封装一个统一的登录状态管理(Vuex/Pinia)
- 添加登录状态持久化(使用uni-app的storage)
- 实现自动登录/token刷新机制
- 添加登录超时处理
通过以上方案,你可以实现一个在Uniapp中兼容多平台的授权登录功能。根据实际项目需求,你可能需要调整部分细节,特别是与服务端的交互部分。
更多推荐
所有评论(0)