• 微信登录


    1.首先页面点击微信图标

    2.后台方法调用微信,用户授权:

    前台向后台请求方法:

    @wechat.route('/open_weixin', methods=['GET'])
        def open_weixin():
            """第一步:用户同意授权,获取code
            redirect_uri :用户授权之后回调地址
            state:回调会带着此参数
            """
            return_url = request.args.get("return_url", "")
            url = _get_open_weixin_url("snsapi_userinfo", return_url)
            return redirect(url)
    
        def _get_open_weixin_url(scope, return_url=None, ordernum=None, ip=None):
            """获取微信授权页面url
            scope参数:
            snsapi_base 静默授权不需要用户操作,
            snsapi_userinfo 需要用户授权然后获取用户基本信息
            state :重定向后会带上state参数,如果你回调需要参数就放到这里,最多128字节
            redirect_uri:为微信回调地址
            appid: "qwb*********56d"  公众号的唯一标识
            """
            # 网页授权两种方式 回调不一样,1 静默授权只获取openid 2 用户授权获取用户信息,
            redirect_uri = ""
            state = ""
            if scope and scope == "snsapi_userinfo":
                redirect_uri = urllib.quote(
                    os.path.join("http://", DOMAIN_NAME, "wechat/wechat_user_info")
                )
                if return_url:
                    state = return_url
            else:
                redirect_uri = urllib.quote(
                    os.path.join("http://", DOMAIN_NAME, "wechat/snsapi_base_open_id"))
                state = "%s_%s" % (ordernum, ip)
            url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={appid}
        &redirect_uri={redirect_uri}&response_type=code&scope={scope}
        &state={state}#wechat_redirect".format(
                appid=appid, redirect_uri=redirect_uri,
                state=state, scope=scope)
            return url
    

    最后return redirect(url)重定向去请求威信接口。

    尤其注意:跳转回调redirect_uri,应当使用https链接来确保授权code的安全性。

    3.微信回调:

    snsapi_base 授权只获取用户openid回调:

    openid:用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID 这个是微信给微信每个用户分配的一个唯一标识,这里微信登录需要获取用户的基本信息,这里回调没啥用,如果别的操作需要获取用户的openid 可以这样获取

    @wechat.route('/snsapi_base_open_id', methods=['GET'])
        def snsapi_base_open_id():
            """静默授权回调方法
            获取openid回调地址"""
            print '==============>>>>>>>>>snsapi_base_open_id'
            print request.args.items().__str__()
            print
            code = request.args.get("code")
            state = request.args.get("state").split("_")
            ordernum = state[0]
            ip = state[1]
    
            # 通过code换取网页授权access_token
            view = _get_web_access_token(code)
            openid = view['openid']
            webutil.session_set_user_open_id(ordernum, openid)
            return redirect(url_for("order.pay", ordernum=ordernum, ip=ip))
            # return render_template("order/pay.html", view=view, ordernum=ordernum,
            # ip=ip)

     snsapi_userinfo 获取用户基本信息回调:

    @wechat.route('/wechat_user_info', methods=['GET', 'POST'])
        def wechat_user_info():
            '''
            用户授权回调方法
            微信获取用户基本信息
            1 第一步:用户同意授权,获取code
    
            2 第二步:通过code换取网页授权access_token
    
            3 第三步:刷新access_token(如果需要)
    
            4 第四步:拉取用户信息(需scope为 snsapi_userinfo)
    
            5 附:检验授权凭证(access_token)是否有效
            '''
            # 第一步:用户同意授权,获取code
    
            code = request.args.get("code")
            return_url = request.args.get("state")
            # 用户拒绝授权不会返回code参数
            if not code:
                return redirect(url_for('user.login'))
            # 通过code换取网页授权access_token
            view = _get_web_access_token(code)
            # 失败返回
            if not view or not view.get("openid"):
                return redirect(url_for('user.login'))
            access_token = view['access_token']
            openid = view['openid']
    
            # 判断此openid是否注册过
            user = User.query.filter_by(wx_open_id=openid).first()
            if user:
                return _wechat_login(user, return_url)
    
            # 检验授权凭证(access_token)是否有效
            val = _validation_access_token(access_token, openid)
            if val != "ok":
                # 刷新access_token
                new_view = _refresh_access_token(view['refresh_token'])
                access_token = new_view['access_token'] if new_view else ""
                openid = new_view['openid'] if new_view else ""
            user_view = _get_wechat_user_info(access_token, openid)
            # 失败返回
            if not user_view:
                return redirect(url_for('user.login'))
    
            # 为用户注册账号
            user = _wechat_register_user(user_view)
            return _wechat_login(user, return_url)
    

    下面是获取网页授权的access_token:

    def _get_web_access_token(code):
            """获取网页授权access_token 这个用来获取用户信息用
            access_token:网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
            expires_in:access_token接口调用凭证超时时间,单位(秒)
            refresh_token:用户刷新access_token
            openid:用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
            scope:用户授权的作用域,使用逗号(,)分隔
            """
            params = urllib.urlencode(
                {
                    'appid': appid, 'secret': secret, 'code': code,
                    'grant_type': 'authorization_code'
                }
            )
            f = urllib.urlopen(
                "https://api.weixin.qq.com/sns/oauth2/access_token?%s" % params)
            res = json.loads(f.read())
            view = {}
            if res and res.get("openid"):
                view = {"access_token": res.get("access_token"),
                        "expires_in": res.get("expires_in"),
                        "refresh_token": res.get("refresh_token"),
                        "openid": res.get("openid"),
                        "scope": res.get("scope")}
            return view
    

    这里获取用户基本信息:

    def _get_wechat_user_info(access_token, openid):
            '''微信获取用户基本信息
             access_token 网页授权的access_token
             openid:普通用户标识,对当前公众号唯一
             lang:国家地区语言版本,可不填 zh_CN 简体 zh_TW 繁体 en 英文
             返回参数:
            "openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", #用户的标识,对当前公众号唯一
            "nickname": "Band",#用户的昵称
            "sex": 1,#用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
            "city": "广州",
            "province": "广东",
            "country": "中国",
            "headimgurl":"" ,#用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
            "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL", #只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
            "privilege":用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)
            '''
            params = urllib.urlencode(
                {'access_token': access_token, 'openid': openid, 'lang': 'zh_CN'})
            f = urllib.urlopen("https://api.weixin.qq.com/sns/userinfo?%s" % params)
            res = json.loads(f.read())
            view = {}
            if res and res.get("openid"):
                view = {
                    "openid": res.get("openid"),
                    "nickname": res.get("nickname"),
                    "sex": res.get("sex"),
                    "city": res.get("city"),
                    "province": res.get("province"),
                    "country": res.get("country"),
                    "headimgurl": res.get("headimgurl")
                }
            return view
    

    然后给微信用户注册一个帐号,登录上就可以了; 其实就是用户授权微信获取用户信息,给用户注册帐号登录上;

  • 相关阅读:
    JobRunShell.cs not FOUND
    Manjaro Linux 更新后无法启动问题
    VMware Workstation 16 启动虚拟机失败(vmmon 版本问题)
    sql生成表模型字段
    【短道速滑六】古老的视频去噪算法(FLT_GradualNoise)解析并优化,可实现1920*1080 YUV数据400fps的处理能力。
    Mvc Redis 相关资料
    Android Handler内存泄露
    ANDROID中HANDLER使用浅析
    Android并发编程之白话文详解Future,FutureTask和Callable
    企业微信考勤接口返回的秒数与统计天数关系
  • 原文地址:https://www.cnblogs.com/2014-02-17/p/6936362.html
Copyright © 2020-2023  润新知