IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    曲线救国 — 微信个人开发者使用微信账号登录实现

    obaby发表于 2024-02-02 02:46:33
    love 0
    之前在《应用商店上架记》一文中写过,关于三方登录中的微信账号登录不针对个人开发者开放的问题。就在这几天搜索了一下个人开发者微信登录的问题,有人提出了可以使用小程序的登录来实现微信登录。思考了一下,按照这个逻辑应该是可行的。因为小程序本身已经具备微信登录的相关能力,并且之前小程序也上架了。

    现在需要解决的问题就剩下这么几个:
    1.在微信小程序实现微信登录相关功能
    2.从 app 直接调用小程序登录页面,获取 openid或者登录凭证
    3.将小程序获取的 opendi 或者登录凭证调期 app,将相关的凭证回传 app 之后,app 使用相关的凭证进行登录。
    有了思路之后,后面就一步一步来实现吧:

    一、小程序登录

    1.获取小程序 appid,登录微信公众平台,官网链接:https://mp.weixin.qq.com/ 。点击开发管理页面查看小程序 appid  
    2.在 hbuilder 中修改 manifest.json 配置,微信小程序配置页面,填入微信小程序 appid  
    3.获取微信用户信息,可以使用uni.getUserProfile请求用户授权获取用户信息。接口文档地址:https://uniapp.dcloud.net.cn/api/plugins/login.html#getuserprofile 
    接口返回数据:
    参数 类型 说明
    userInfo OBJECT 用户信息对象
    rawData String 不包括敏感信息的原始数据字符串,用于计算签名。
    signature String 使用 sha1( rawData + sessionkey ) 得到字符串,用于校验用户信息。
    encryptedData String 包括敏感数据在内的完整用户信息的加密数据,详细见加密数据解密算法。
    iv String 加密算法的初始向量,详细见加密数据解密算法。
    cloudID String 敏感数据对应的云 ID,开通云开发的小程序才会返回,可通过云调用直接获取开放数据,详细见云调用直接获取开放数据
    errMsg String 描述信息
    不过调用该接口返回的数据,并没有太多的实际价值,多数数据都是空的。
    4.在能够获取基础数据之后,后续调用登录登录接口才能拿到凭证信息。
    使用uni.login方法,provider参数输入’weixin’,成功的返回值中如果errMsg=“login:ok” 代表成功,
    微信小程序端会返回一个code字符串
    5.拿到 code 之后通过服务端代码换取 openid  文档地址: https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/code2Session.html
     
    前端完整代码如下:
    vue部分:
    <!-- #ifdef APP-PLUS||MP -->
                <view class="fh-wechat-login-main">
                    <slot>
                        <view class="fh-wechat-login-button" @click="dowechatLogin">
                            <view class="fh-wechat-icon"></view>
                            使用微信账号登录
                        </view>
    
                    </slot>
                </view>
                <!--  #endif -->
     
    js 部分:
    dowechatLogin() {
                    // 展示加载框
                    uni.showLoading({
                        title: '加载中',
                    });
                    let url = this.$baseUrl +
                        'api/third-login/wechat-login/';
                    uni.getUserProfile({
                        desc: '登录后可同步数据',
                        success: async (obj) => {
                            console.log('obj', obj);
                            // 调用 action ,请求登录接口
                            // await this.login(obj);
                            uni.login({
                                provider: 'weixin',
                                success: (res) => {
                                    console.log('res-login', res);
                                    this.code = res.code;
                                    console.log('code', res.code);
                                    if (res.errMsg == 'login:ok') {
                                        uni.request({
                                            url: url,
                                            data: {
                                                code: this.code
                                            },
                                            method: "POST",
                                            header: {},
                                            success: (res) => {
                                                // console.log(res.data);
                                                
                                            },
                                            fail: (e) => {
                                                console.log('failed:', e);
                                                uni.showToast({
                                                    title: '登录失败,请稍候再试',
                                                    icon: 'none'
                                                });
                                                this.isLoginProcess = false;
                                            }
                                        });
                                        console.log('res', res);
                                    }
                                },
                            });
                        },
                        fail: err => {
                            console.log(err)
                            uni.showToast({
                                title: '授权已取消',
                                icon: 'error',
                                mask: true,
                            });
                        },
                        complete: () => {
                            // 隐藏loading
                            uni.hideLoading();
                        },
                    });
                },
    

    服务端部分:

    def wechat_login(self, request):
            try:
                # user = request.user
                # user = User.objects.get(pk=1)
                try:
                    code = request.data['code']
                    resp = requests.get(
                        'https://api.weixin.qq.com/sns/jscode2session?appid=appid&secret=secrct&js_code=' + code + '&grant_type=authorization_code ')
                    resp_json = json.loads(resp.text)
                    if 'errcode' in resp_json:
                        return ErrorResponse(_('code 已经被使用'))
                    # return DetailResponse(resp_json)
                    # print(resp_json)
                    user_info = resp_json
                    # print(user_info)
                    open_id = user_info['openid']
                    # auth_realname = user_info['auth_realname']
                    # 创建用户账号逻辑省略
                    msg = {'token': token.key,
                           'user': {}
                           }
                    return DetailResponse(msg)
    
                except Exception as e:
                    print("Exception=", e)
                    return ErrorResponse(_('数据错误'))
    
            except:
                return ErrorResponse(_('错误的数据格式'))
     
    至此,小程序登录部分就算完成了。后端拿到授权获取的 code 之后通过接口换出 openid,基于 openid 进行账号创建。并且将账号信息返回小程序,实现登录功能。
     

    二、app 打开小程序并且调起登录授权页面

    1. 配置 uniapp 的微信分享功能
    此处填写的 appid 跟上面的小程序的 appid 是一样的。
    配置完成之后,在调试的时候需要重新进行自定义基座打包,并且运行的时候选择自定义基座。否则会提示打包不包含 share 模块。
     
    2. app 打开小程序,相关代码:
    appToMp() {
                    let that = this
                    let url = '/pages/page/wechatLogin' //跳转小程序的路径
                    plus.share.getServices(function(res) {
                        var sweixin = null;
                        for (var i = 0; i < res.length; i++) {
                            var t = res[i];
                            if (t.id == 'weixin') {
                                sweixin = t;
                            }
                        }
                        if (sweixin) {
                            that.wxPay = true
                            sweixin.launchMiniProgram({
                                id: 'gh_8**********', //这里写你的小程序原始id(以gh开头)
                                type: 0, //微信小程序版本类型可取值: 0-正式版; 1-测试版; 2-体验版。 默认值为0。
                                path: url,
                                success(res) {
                                    // return true
                                    console.log('success=', res);
                                },
                                fail(res) {
                                    uni.showToast({
                                        title: '跳转小程序失败',
                                        icon: 'none',
                                        duration: 3000
                                    })
                                    console.log('跳转小程序失败', res)
                                    return false;
                                },
                            })
                        }
                    }, function(err) {
                        console.log(JSON.stringify(err));
                    })
                },
    需要注意的是launchMiniProgram方法中的 id 为小程序原始 id,gh 开头的 id,如下图,小程序账号信息页面查看:
    3. 登录微信开放平台,地址:https://open.weixin.qq.com/ 创建 app 并且提交审核。
    在 ios 应用部分配置Universal Links,如下图:
    4. 创建apple-app-site-association文件,并且上传到Universal Links根目录下,要求必须为 https。
    文件内容如下:
    {  
        "applinks": {  
            "apps": [],  
            "details": [  
                {  
                    "appID": "appTeamID.bundleid",  
                    "paths": ["/uni-universallinks/*"]  
                }  
            ]  
        }  
    }
    appID为 teamid+ bundleid 的组合。具体可以登录苹果开发者后台查看
     
    例如 teamid 为 abcdef,则 appID 为,abcdef.my.dayi.app
    5. 同时需要启用上图中的Associated Domains,在 uniapp 项目中配置Associated Domains。打包时需要下载最新的 mobileprovison 文件进行打包测试。
    6. 在微信开放平台绑定小程序,点击绑定小程序按钮输入小程序的账号密码进行绑定。
     
    上述流程如果配置出现问题可能会出现下面的错误提示
    此时就只能根据微信的文档进行排查了:https://docs.msdk.qq.com/v5/zh-CN/FAQS/402d19e50fff44c827a4f3b608bd5812/11796f3fcca548e16afca803e76e5265.html
     
    到这里第二步就算完成了,剩下的第三步就简单了。
     

    三、获取授权凭证跳会 app 进行自动登录 

    1. 小程序内创建授权登录页面,在这个页面需要能够获取 code 之后,并且回传到 app 内。跳转 app 需要使用独立的button 进行操作:
    vue 代码:
    <view v-if="isSuccess===0" class="fh-wechat-login-main" >
                    <slot>
                        <view  class="fh-wechat-login-button" @click="LoginForWechat">
                            <view class="fh-wechat-icon"></view>
                            使用微信账号登录
                        </view>
                    </slot>
                </view>
                <view v-if="isSuccess===1">
                    <button class="fh-wechat-login-main" open-type="launchApp" :app-parameter="params" @error="openError"
                        style="font-size: 14px;">授权成功,点击返回APP登录</button>
                </view>
     
    isSuccess用于控制获取到 code 之后显示返回 app 按钮。
    js 代码:
    uni.getUserProfile({
                        desc: '登录后可同步数据',
                        success: async (obj) => {
                            console.log('obj', obj);
                            // 调用 action ,请求登录接口
                            // await this.login(obj);
                            uni.login({
                                provider: 'weixin',
                                success: (res) => {
                                    console.log('res-login', res);
                                    this.code = res.code;
                                    console.log('code', res.code);
                                    if (res.errMsg == 'login:ok') {
                                        this.params = 'code=' + this.code;
                                        console.log('res', res);
                                        this.isSuccess = 1;
                                    }
                                },
                            });
                        },
                        fail: err => {
                            console.log(err)
                            uni.showToast({
                                title: '授权已取消',
                                icon: 'error',
                                mask: true,
                            });
                        },
                        complete: () => {
                            // 隐藏loading
                            uni.hideLoading();
                        },
                    });
    
    通过params进行参数传递
     
    2. app 获取小程序回传的code 凭证进行登录操作
    js 代码:
    onShow() {		
                // #ifdef APP-PLUS
                setTimeout(() => {
                    console.log('wechat login call back')
                    let code = plus.runtime.arguments
                    if (code && code.toString().indexOf('code=')>=0) {
                        plus.runtime.arguments = ''
                        // ...
                        console.log('code=', code);
    
                        code = code.replace('code=', '');
                        if (code.length > 4) {
                            //使用 code 进行登录操作
                            this.httpLoginwechatWithCode(code);
                        }
                    }
    
                }, 10)
                // #endif
            },
    至此,整个微信账号登录的流程就算完成了,实际效果:
     
    参考链接:
    https://codeantenna.com/a/j7qBaSRtQd
    https://blog.51cto.com/gblfy/5670283
    https://docs.msdk.qq.com/v5/zh-CN/FAQS/402d19e50fff44c827a4f3b608bd5812/11796f3fcca548e16afca803e76e5265.html

    The post 曲线救国 — 微信个人开发者使用微信账号登录实现 first appeared on obaby@mars.



沪ICP备19023445号-2号
友情链接