如何使用 python 调用QQ 登录 的 SDK 文档

qq目前没有为大家提供SDK 文档 来供大家直接使用 :  只提供了 参数获取的 的接口文档, 这里为大家提供一个封装好的 SDK

直接调用即可 .

详细参见 : https://gitee.com/y2030/qq_auxiliary_login_sdk.git

from urllib.parse import urlencode, parse_qs
from urllib.request import urlopen
import json
from django.conf import settings


from itsdangerous import TimedJSONWebSignatureSerializer as Serializer, BadData
from . import constants


import logging


# 日志记录器
from .exceptions import QQAPIException
logger = logging.getLogger('django')



class OAuthQQ(object):
    """QQ 认证辅助工具类"""


    def __init__(self, client_id=None, client_secret=None, redirect_uri=None, state=None):
        """构造方法, 用于接受说有的工具方法需要使用到的参数"""
        self.client_id = client_id or settings.QQ_CLIENT_ID
        self.client_secret = client_secret or settings.QQ_CLIENT_SECRET
        self.redirect_uri = redirect_uri or settings.QQ_REDIRECT_URI
        self.state = state or settings.QQ_STATE


    def get_qq_login_url(self):
        """
        获取qq登录的网址


        QQ登录参数:
        QQ_CLIENT_ID = '101474184'
        QQ_CLIENT_SECRET = 'c6ce949e04e12ecc909ae6a8b09b637c'
        QQ_REDIRECT_URI = 'http://www.meiduo.site:8080/oauth_callback.html'
        QQ_STATE = '/'


        :return: url
        """
        # 1, 准备url:  必须自己补充?
        login_url = 'https://graph.qq.com/oauth2.0/authorize?'
        # 2, 准备参数
        # 'https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=xx..
        params = {
            'response_type': 'code',  # 表示扫码后未来得到的code(获取access_token的凭据)
            'client_id': self.client_id,  # 创建应用时 的标识appid
            'redirect_uri': self.redirect_uri,  # 扫码成功后回调地址
            'state': self.state,  # next参数, client端的状态值。用于第三方应用防止CSRF攻击
            'scope': 'get_user_info',
        }
        login_url += urlencode(params)
        return login_url


    def get_access_token(self, code):
        """
        获取access_token


        :param code:qq提供的code


        :return:access_token
        """


        # 准备url  PC网站:https://graph.qq.com/oauth2.0/token
        get_token_url = 'https://graph.qq.com/oauth2.0/token?'


        # 准备参数
        params = {
            'grant_type': "authorization_code",
            'client_id': self.client_id,
            'client_secret': self.client_secret,
            'code': code,
            'redirect_uri': self.redirect_uri
        }


        try:
            get_token_url += urlencode(params)
            # 使用code向QQ服务器发送请求 读取到的数据为bytes类型
            response_data = urlopen(get_token_url).read()


            # 转码成字符串类型
            response_str = response_data.decode()


            # 将查询字符串格式数据转换为python的字典
            response_dict = parse_qs(response_str)


            # 从字典中取出access_token
            # access_token=FE04***************CCE2 & expires_in = 7776000 & refresh_token = 88E4****************BE14
            # response_dict.get('access_token')==[FE04 ************************ CCE2]
            access_token = response_dict.get('access_token')[0]
        except Exception as e:
            logger.error(e)


            # 抛出异常,在views中, 谁调用谁try
            raise QQAPIException('获取access_token失败')


        return access_token


    def get_openid(self, access_token):
        """
        获取用户的openid
        :param access_token: qq提供的access_token
        :return: open_id
        """
        # 准备url
        get_openid_url = 'https://graph.qq.com/oauth2.0/me?access_token=' + access_token


        # 使用access_token向QQ服务器发送请求, 读取到的是bytes类型, 将bytes类型的数据转码为字符串
        response_str = urlopen(get_openid_url).read().decode()
        try:
            # callback({"client_id": "YOUR_APPID", "openid": "YOUR_OPENID"});
            response_dict = json.loads(response_str[10:-4])
        except Exception:
            data = parse_qs(response_str)
            logger.error('code=%s msg=%s' % (data.get('code'), data.get('msg')))
            raise QQAPIException
            # 从字典中取出openid
        openid = response_dict.get('openid', None)
        return openid


    @staticmethod
    def generate_save_user_token(openid):
        """
        生成保存用户数据的token
        :param openid: 用户的openid
        :return: token
        """
        serializer = Serializer(settings.SECRET_KEY, expires_in=constants.SAVE_QQ_USER_TOKEN_EXPORES)
        data = {"openid": openid}
        token = serializer.dumps(data)
        return token.decode()


    @staticmethod
    def check_save_user_token(token):
        """
        检验保存用户数据的token
        :param token: token
        :return: openid or None
        """
        serializer = Serializer(settings.SECRET_KEY, expires_in=constants.SAVE_QQ_USER_TOKEN_EXPORES)
        try:
            data = serializer.loads(token)
        except BadData:
            return None
        else:

            return data.get('openid')

---------------------------------------------------------------------------------------------------------------------------------

在view.py中

from django.shortcuts import render
from rest_framework import status
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework.views import APIView
from .utils import OAuthQQ
from .exceptions import QQAPIException
from .models import OAuthQQUser
from rest_framework_jwt.views import api_settings
from . import serializers
from carts.utils import merge_cart_cookie_to_redis




# Create your views here.


# 第一大步
# 只负责拼接字符串, 不需要验证, 所以用APIView
# GET /oauth/qq/authorization/?next=xxx
# url(r'^qq.authorization/$', views.QQAuthURLView.as_view())
class QQAuthURLView(APIView):
    """
    获取QQ扫码登录界面的的url
    """


    def get(self, request):
        """
        提供用于qq登录的url
        """
        next = request.query_params.get('next')
        print(next)


        # 创建qq登录的工具类的对象
        oauth = OAuthQQ(state=next)
        # 生成QQ扫码登录的链接
        login_url = oauth.get_qq_login_url()
        return Response({'login_url': login_url})




# http://www.xxxx.com:8080/oauth_callback.html?code=468FE2461369C40E4EDA0813CCBDCEE9&state=%2F
# GET /oauth/qq/user/?code=xxx
# url(r'^qq/user/$', views.QQAuthUserView.as_view()),
class QQAuthUserView(GenericAPIView):
    """⽤户扫码登录的回调处理"""


    # 指定序列化器
    serializer_class = serializers.OAuthQQUserSerializer


    # 第二大步
    def get(self, request):
        # 提取code请求参数
        code = request.query_params.get('code')
        if not code:
            return Response({'message': '缺少code'}, status=status.HTTP_400_BAD_REQUEST)
        # 创建QQ登录的工具类对象
        oauth = OAuthQQ()
        try:
            # 使⽤code向QQ服务器请求access_token
            access_token = oauth.get_access_token(code)


            # 使⽤access_token向QQ服务器请求openid
            openid = oauth.get_openid(access_token)
        except QQAPIException:
            return Response({"message": "QQ服务器异常"}, status=status.HTTP_503_SERVICE_UNAVAILABLE)


        # 第三大步
        # 使⽤openid查询该QQ⽤户是否在美多商城中绑定过⽤户
        try:
            # oauth_user查出来的是一整条记录, OAuthQQUser的对象
            oauth_user = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 如果openid没绑定美多商城⽤户,创建⽤户并绑定到openid
            access_token_openid = OAuthQQ.generate_save_user_token(openid)


            return Response({"access_token": access_token_openid})
        else:
            # 如果openid已绑定美多商城⽤户,直接⽣成JWT token,并返回


            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER


            # 获取关联openid的user
            user = oauth_user.user
            payload = jwt_payload_handler(user)


            token = jwt_encode_handler(payload)


            response = Response({
                "user_id": user.id,
                "username": user.username,
                "token": token
            })

            # 向前端相应token, user_id, username
            return response


    # 本次创建用户模型类有两个, 所以不使用CreateAPIView
    def post(self, request):
        """用户扫码登录的回调处理"""


        # 获取序列化器 , 注册的数据都在post请求的请求体里面
        serializer = self.get_serializer(data=request.data)
        # 开启校验
        serializer.is_valid(raise_exception=True)
        # 保存校验的数据 : create 会返回user
        user = serializer.save()


        # 生成已经登录的token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER


        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)


        response = Response({
            'token': token,
            'user_id': user.id,
            'username': user.username
        })
        return response

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值