在 Uniapp 中实现兼容微信 H5、支付宝 H5、微信小程序和支付宝小程序的授权登录功能,需要根据不同平台采用不同的授权方式。下面我将提供一个完整的解决方案。

一、整体思路

  1. 判断运行平台:使用 uni.getSystemInfoSync().platform 或条件编译区分不同平台
  2. 各平台授权方式
    • 微信小程序:使用 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()
}
}
}

三、服务端配合要点

  1. 微信小程序
    • 使用 code 换取 session_key 和 openid
    • 解密 encryptedData 获取用户信息
  2. 支付宝小程序
    • 使用 authCode 换取 user_id 和访问令牌
    • 调用 alipay.user.info.share 获取用户信息
  3. 微信H5
    • 使用 code 换取 access_token 和 openid
    • 使用 access_token 获取用户信息
  4. 支付宝H5
    • 使用 authCode 换取用户信息

四、注意事项

  1. 小程序端
    • 微信小程序从2021年4月起,wx.getUserInfo 不再弹出授权窗口,需使用 wx.getUserProfile
    • 支付宝小程序需要配置 auth_user 权限
  2. H5端
    • 微信H5需要配置JS-SDK安全域名
    • 支付宝H5需要引入支付宝JS SDK
    • 都需要服务端支持OAuth2.0流程
  3. 用户体验
    • 在用户拒绝授权时给出明确提示
    • 提供明确的授权用途说明
    • 考虑未授权状态下的功能降级
  4. 隐私政策
    • 确保符合各平台的隐私政策要求
    • 在用户首次使用时展示隐私协议

五、扩展建议

  1. 可以封装一个统一的登录状态管理(Vuex/Pinia)
  2. 添加登录状态持久化(使用uni-app的storage)
  3. 实现自动登录/token刷新机制
  4. 添加登录超时处理

通过以上方案,你可以实现一个在Uniapp中兼容多平台的授权登录功能。根据实际项目需求,你可能需要调整部分细节,特别是与服务端的交互部分。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐