• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

uni-app小程序微信一键登录实现过程记录

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

话不多是,直接上代码(我里面按钮用到了vant的组件):

<template>
    <view
        style="height: 100vh;display: flex;flex-direction: column;align-items: center;justify-content: center;box-sizing: border-box;">
        <van-button type="primary" block open-type="getUserInfo" @getuserinfo="appLoginWx">
            微信一键登录
        </van-button>
        <van-button v-show="showPhone" type="primary" block open-type="getPhoneNumber" @getphonenumber="getPhone">
            授权电话
        </van-button>
    </view>
</template>

<script>
    const WXBizDataCrypt = require(\'@/utils/WXBizDataCrypt\')
    export default {
        data() {
            return {
                appId:\'******************\', // 小程序的appId(注意需要企业的appId,并且你是开发人员,不然后续无法获取到手机号码)
                showPhone: false,
                userInfo: {},
                sessionKey: null,
                unionid: null,
                openId: null,
                phone: null
            }
        },
        methods: {
            // 授权获取微信用户信息
            appLoginWx(res) {
                console.log(res)
                // 获取用户信息成功
                if (res.detail.errMsg === \'getUserProfile:ok\' || res.detail.errMsg === \'getUserInfo:ok\') {this.userInfo = res.detail.userInfo;
                    let _this = this;
                    uni.showLoading({
                        title: \'获取用户信息...\',
                        mask: true
                    });
                    // 获取jsCode
                    uni.login({
                        provider: \'weixin\',
                        success(resLogin) {
                            console.log(resLogin);
                            if (resLogin.errMsg === "login:ok") {
                                // 获取jsCode成功,通过jsCode调用微信api获取用户openId
                                _this.wechatLogin(resLogin.code);
                                return
                            }
                            uni.hideLoading();
                            uni.showToast({
                                title: \'获取用户信息失败,请重试\',
                                icon: \'none\',
                                duration: 2000
                            });
                        },
                        fail() {
                            uni.hideLoading();
                            uni.showToast({
                                title: \'获取用户信息失败,请重试\',
                                icon: \'none\',
                                duration: 2000
                            });
                        }
                    });
                }
            },
            wechatLogin(wxCode) {
                // 这里一般让后端去调用微信api获取openId等信息,前端调用的话像会多下面这个请求
                // 因为若果是后端去调用的话,后端拿到微信api返回的openId后可直接去数据库查询判断该用户是否已注册,
                // 如果已经注册了就直接返回注册的用户信息,
                // 如果未注册,则后端需要返回openId、sessionKeyde等信息,
                // 然后前端页面弹出授权获取手机号码的按钮,用户点击后拿到手机号后进行解密后再把信息提交给后台进行注册
                const params = {
                    appid: this.appId, // 小程序的appId(注意需要企业的appId,并且你目前是开发人员,不然后续无法获取到手机号码)
                    secret: \'***************\', // 企业小程序的secret
                    js_code: wxCode, // 注意jsCode动态获取的,使用一次后将失效
                    grant_type: \'authorization_code\' // 这个参数固定写死
                }
                // 调用微信api获取openid等信息
                this.$get(\'https://api.weixin.qq.com/sns/jscode2session\', params).then(res => {
                    console.log(res)
                    if (res.errcode) {
                        console.log(\'获取openId失败\')
                        uni.hideLoading();
                        uni.showToast({
                            title: \'获取用户信息失败\',
                            icon: \'none\',
                            duration: 2000
                        });
                        return
                    }
                    this.openId = res.openid
                    this.sessionKey = res.session_key
                    this.unionid = res.unionid

                    // 调用后端接口判断用户是否已注册过
                    this.$post(\'/login\', {
                        openId: this.openId
                    }).then(res => {
                        uni.hideLoading();
                        // 若返回的参数中有token说明已经注册过
                        if (res.status === 200 && res.data.token) {
                            uni.showToast({
                                title: \'登录成功!\',
                                duration: 1000
                            });
                            // 缓存用户信息
                            uni.setStorageSync("token", res.data.token);
                            uni.setStorageSync("userInfo", res.data);
                            // 登录成功返回上一页
                            setTimeout(() => {
                                uni.navigateBack({
                                    delta: 1
                                })
                            }, 1000)
                            return
                        }
                        // 走到这里说明没有注册过,需要弹出授权获取用户手机号的弹框按钮让用户授权
                        if (res.status == 200) {
                            this.showPhone = true
                            return
                        }
                        uni.showToast({
                            title: res.message,
                            icon: \'none\',
                            duration: 2000
                        });
                    }).catch(() => {
                        uni.hideLoading();
                        uni.showToast({
                            title: \'登录失败,请稍后重试\',
                            icon: \'none\',
                            duration: 2000
                        });
                    })

                }).catch(err => {
                    console.log(err)
                    uni.hideLoading();
                    uni.showToast({
                        title: \'获取用户信息失败\',
                        icon: \'none\',
                        duration: 2000
                    });
                })

                // 下面注释的就是后端去调用微信api获取用户openId的提供给前端的接口
                // this.$post(\'/login\', {
                //     jsCode: wxCode
                // }).then(res => {
                //     console.log(res);
                //     uni.hideLoading();
                //     // 若直接返回token说明已经注册
                //     if (res.status === 200 && res.data.token) {
                //         uni.showToast({
                //             title: \'登录成功!\',
                //             duration: 1000
                //         });
                //         uni.setStorageSync("token", res.data.token);
                //         this.saveUserInfo(res.data);
                //         setTimeout(() => {
                //             // this.goTabBar(\'/pages/index\')
                //             uni.navigateBack({
                //                  delta: 1
                //             })
                //         }, 1000)
                //         return
                //     }
                //     if (res.status == 200) {
                //         this.openId = res.data.openid
                //         this.sessionKey = res.data.session_key
                //         this.unionid = res.data.unionid
                //         this.id = res.data.id
                //         this.showPhone = true
                //         return
                //     }
                //     uni.showToast({
                //         title: res.message,
                //         icon: \'none\',
                //         duration: 2000
                //     });
                // }).catch(() => {
                //     uni.hideLoading();
                //     uni.showToast({
                //         title: \'登录失败,请稍后重试\',
                //         icon: \'none\',
                //         duration: 2000
                //     });
                // })
            },
            // 授权电话号回调 (这里千万注意:小程序必须要完成 微信认证才能获取到加密的手机号码)
            getPhone(res) {
                console.log(res)
                if (res.detail.errMsg === \'getPhoneNumber:ok\') {
                    const encryptedData = res.detail.encryptedData
                    console.log(123, sessionKey, encryptedData, iv)
                    const pc = new WXBizDataCrypt(this.appId, this.sessionKey)  
                    const data = pc.decryptData(encryptedData, res.detail.iv) // 这里使用解密手机号的方法
                    console.log(\'解密后 data: \', data.phoneNumber)
                    this.phone = data.phoneNumber
                    this.showPhone = false
                    this.loginHandle()
                } else {
                    this.showPhone = false
                    uni.showToast({
                        title: \'获取手机号失败,请重试\',
                        icon: \'none\',
                        duration: 2000
                    });
                }
            },
            // 用户注册
            loginHandle() {
                const data = {
                    "account": this.phone,
                    "icon": this.userInfo.avatarUrl,
                    "id": this.id,
                    "nickname": this.userInfo.nickName,
                    "openId": this.openId,
                    "phone": this.phone,
                    "unionid": this.unionid
                }
                console.log(data)
                uni.showLoading({
                    title: \'登录中...\',
                    mask: true
                });
                this.$post(\'/login/login\', data).then(res => {
                    console.log(res);
                    uni.hideLoading();
                    if (res.status == 200) {
                        uni.showToast({
                            title: \'登录成功!\',
                            duration: 1000
                        });
                        uni.setStorageSync("token", res.data.token);
                        uni.setStorageSync("userInfo", res.data);
                        setTimeout(() => {
                            uni.navigateBack({
                                delta: 1
                            })
                        }, 1000)
                    } else {
                        uni.showToast({
                            title: res.message,
                            icon: \'none\',
                            duration: 2000
                        });
                    }
                });
            },
        }
    }
</script>

<style>
</style>

 

以下是上面解密手机号方法的封装,我是放在utils目录下的:

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

 

 

注意事项:想要获取到手机号并成功解密的话,appId 必须是企业的,且需要完成微信认真,然后你是当前项目的开发人员。

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap