如何为你的Web接入QQ登录

发布于 2023-07-06  1319 次阅读


一、注册成为开发者

前往QQ互联官网首页登录注册并进行实名制。等待腾讯审核,一般三天内审核完成。

二、注册应用

开发者审核完成后在QQ互联官网首页创建一个网站应用。(注意:审核完成后建议不要修改网站地址,网站地址变动将会导致重新审核,容易影响线上服务,回调地址变动不会影响)
按需填写,注意网站地址需要填写一个能够被正常访问且悬挂QQ登录的按钮页面
相关参数:

请求地址: PC网站:https://graph.qq.com/oauth2.0/authorize 请求方法: GET 请求参数: 请求参数请包含如下内容:

参数是否必须含义
response_type必须授权类型,此值固定为“code”。
client_id必须申请QQ登录成功后,分配给应用的appid。
redirect_uri必须成功授权后的回调地址,必须是注册appid时填写的主域名下的地址,建议设置为网站首页或网站的用户中心。注意需要将url进行URLEncode。
state必须client端的状态值。用于第三方应用防止CSRF攻击,成功授权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。
scope可选请求用户授权时向用户显示的可进行授权的列表。 可填写的值是API文档中列出的接口,如果要填写多个接口名称,请用逗号隔开。 例如:scope=get_user_info,list_album,upload_pic 不传则默认请求对接口get_user_info进行授权。 建议控制授权项的数量,只传入必要的接口名称,因为授权项越多,用户越可能拒绝进行任何授权。
display可选PC网站接入时使用。 用于展示的样式。不传则默认展示为PC下的样式。 如果传入“mobile”,则展示为mobile端下的样式。

以下是示例

<a href="https://graph.qq.com/oauth2.0/authorize?response_type=code&amp;client_id=替换为应用id&amp;redirect_uri=替换为自己的其中一个回调地址&amp;scope=get_user_info" class="qq-login-btn">使用QQ登录</a>

等待审核完成,一般一个工作日内完成。

三、程序接入QQ登录

获取Access_Token和openid

如果只需要实现登录功能,不需要显示用户详细信息,只需要获取到openid即可,openid是该用户在此APP中唯一识别码。

当用户点击按钮并QQ登录成功后会跳转到回调地址并传入参数?code=xxxxxx,我们需要通过传入的code获取用户Access_Token和openid

请求地址: PC网站:https://graph.qq.com/oauth2.0/token 请求方法: GET 请求参数: 请求参数请包含如下内容:

参数是否必须含义
grant_type必须授权类型,在本步骤中,此值为“authorization_code”。
client_id必须申请QQ登录成功后,分配给网站的appid。
client_secret必须申请QQ登录成功后,分配给网站的appkey。
code必须上一步返回的authorization code。 如果用户成功登录并授权,则会跳转到指定的回调地址,并在URL中带上Authorization Code。 例如,回调地址为www.qq.com/my.php,则跳转到: http://www.qq.com/my.php?code=520DD95263C1CFEA087** 注意此code会在10分钟内过期。
redirect_uri必须与上面一步中传入的redirect_uri保持一致。
fmt可选因历史原因,默认是x-www-form-urlencoded格式,如果填写json,则返回json格式

返回说明

如果成功返回,即可在返回包中获取到Access Token。 如(不指定fmt时):

access_token=FE04********CCE2&expires_in=7776000&refresh_token=88E4********BE14

参数说明描述
access_token授权令牌,Access_Token。
expires_in该access token的有效期,单位为秒。
refresh_token在授权自动续期步骤中,获取新的Access_Token时需要提供的参数。注:refresh_token仅一次有效


当获取到Access_Token,我们即可拉取所需信息,比如

分组名称API接口功能说明
访问用户资料get_user_info获取登录用户的昵称、头像、性别、openid(该用户在此应用中唯一识别码)
获取用户联调IDget_unionid不同的应用中openid不同,如果申请此接口可以获取联调ID,应用变动unionid不会发生变动,适用于多应用情形(需在审核完成后手动在当前应用控制台开启)
  1. 使用QQ登录授权页面引导用户进行登录授权,用户授权后会重定向到你预先指定的回调地址,并附带一个授权码(code)。
  2. 在你的应用服务端,通过发送POST请求获取access_token。请求URL为:https://graph.qq.com/oauth2.0/token
  3. 请求参数包括:
  • grant_type:授权类型,固定为authorization_code
  • client_id:你的QQ登录应用的app_id。
  • client_secret:你的QQ登录应用的app_key。
  • code:授权码(code)。
  • redirect_uri:回调地址,必须与授权时使用的回调地址一致。
  1. 发送POST请求获取access_token,并解析响应内容。
  • 如果请求成功,响应内容为一串以&分隔的参数键值对,其中包括access_tokenexpires_in等字段。
  • 如果请求失败,响应内容中会包含错误信息。
  1. 从响应内容中提取access_token字段,即为获取的QQ登录access_token。

请注意,获取access_token后,还可以使用access_token调用其他QQ登录API来获取用户信息等。具体的API调用方法,请参考QQ登录开发者文档。

理论说的再多不如上手,如果你看的云里雾里可以看看以下的示例:

以下是获取用户的openid和access_token的示例代码:

Python代码:

import requests

qq_app_id = "your_qq_app_id"       # QQ登录的app_id
qq_app_key = "your_qq_app_key"     # QQ登录的app_key
qq_redirect_uri = "your_redirect_uri"   # QQ登录的回调地址

def get_qq_access_token_and_openid(code):
    url = f"https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&client_id={qq_app_id}&client_secret={qq_app_key}&code={code}&redirect_uri={qq_redirect_uri}"
    response = requests.get(url)
    response_text = response.text

    # 解析access_token
    access_token = response_text.split("&")[0].split("=")[1]

    # 获取openid
    url = f"https://graph.qq.com/oauth2.0/me?access_token={access_token}&unionid=1"
    response = requests.get(url)
    response_text = response.text
    response_text = response_text.replace("callback(", "").replace(");", "")
    response_dict = json.loads(response_text)

    openid = response_dict.get("openid", "")

    return {"access_token": access_token, "openid": openid}

# 使用示例
code = "your_authorization_code"  # 这里是传入参数code的值
result = get_qq_access_token_and_openid(code)
print("access_token:", result["access_token"])
print("openid:", result["openid"])

Go代码:

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "net/url"
    "strings"
)

const (
    qqAppID       = "your_qq_app_id"       // QQ登录的app_id
    qqAppKey      = "your_qq_app_key"      // QQ登录的app_key
    qqRedirectURI = "your_redirect_uri"    // QQ登录的回调地址
)

func getQQAccessTokenAndOpenID(code string) (string, string, error) {
    accessTokenURL := "https://graph.qq.com/oauth2.0/token"

    params := url.Values{}
    params.Set("grant_type", "authorization_code")
    params.Set("client_id", qqAppID)
    params.Set("client_secret", qqAppKey)
    params.Set("code", code)
    params.Set("redirect_uri", qqRedirectURI)

    response, err := http.Post(accessTokenURL, "application/x-www-form-urlencoded", strings.NewReader(params.Encode()))
    if err != nil {
        return "", "", err
    }
    defer response.Body.Close()

    body, err := ioutil.ReadAll(response.Body)
    if err != nil {
        return "", "", err
    }

    responseText := string(body)
    accessToken := strings.Split(responseText, "&")[0][13:]

    openidURL := fmt.Sprintf("https://graph.qq.com/oauth2.0/me?access_token=%s&unionid=1", accessToken)
    response, err = http.Get(openidURL)
    if err != nil {
        return "", "", err
    }
    defer response.Body.Close()

    body, err = ioutil.ReadAll(response.Body)
    if err != nil {
        return "", "", err
    }

    responseText = string(body)
    responseText = strings.ReplaceAll(responseText, "callback(", "")
    responseText = strings.TrimSuffix(responseText, ");")
    responseDict := make(map[string]interface{})
    err = json.Unmarshal([]byte(responseText), &responseDict)
    if err != nil {
        return "", "", err
    }

    openid := responseDict["openid"].(string)

    return accessToken, openid, nil
}

// 使用示例
func main() {
    code := "your_authorization_code" // 这里是传入参数code的值
    accessToken, openid, err := getQQAccessTokenAndOpenID(code)
    if err != nil {
        fmt.Println("获取access_token和openid失败:", err)
        return
    }

    fmt.Println("access_token:", accessToken)
    fmt.Println("openid:", openid)
}

请根据实际情况选择适合自己的语言和库来实现相应功能。

获取用户信息

当获取到Access_Token之后后面的路就非常清晰了,只需要请求一次api就能拿到用户的相关信息了

请求https://graph.qq.com/user/get_user_info?access_token=获取到的ACCESS_TOKEN&oauth_consumer_key=你的APP_ID&openid=获取到的OPENID

当请求该地址后会返回如下json:

{
"ret":0,
"msg":"",
"nickname":"Peter",
"figureurl":"http://qzapp.qlogo.cn/qzapp/111111/942FEA70050EEAFBD4DCE2C1FC775E56/30",
"figureurl_1":"http://qzapp.qlogo.cn/qzapp/111111/942FEA70050EEAFBD4DCE2C1FC775E56/50",
"figureurl_2":"http://qzapp.qlogo.cn/qzapp/111111/942FEA70050EEAFBD4DCE2C1FC775E56/100",
"figureurl_qq_1":"http://q.qlogo.cn/qqapp/100312990/DE1931D5330620DBD07FB4A5422917B6/40",
"figureurl_qq_2":"http://q.qlogo.cn/qqapp/100312990/DE1931D5330620DBD07FB4A5422917B6/100",
"gender":"男"
}
参数说明描述
ret返回码
msg如果ret<0,会有相应的错误信息提示,返回数据全部用UTF-8编码
is_lost判断是否有数据丢失。如果应用不使用cache,不需要关心此参数。0或者不返回:没有数据丢失,可以缓存。1:有部分数据丢失或错误,不要缓存
nickname用户在QQ空间的昵称。
figureurl大小为30×30像素的QQ空间头像URL。
figureurl_1大小为50×50像素的QQ空间头像URL。
figureurl_2大小为100×100像素的QQ空间头像URL。
figureurl_qq_1大小为40×40像素的QQ头像URL。
figureurl_qq_2大小为100×100像素的QQ头像URL。需要注意,不是所有的用户都拥有QQ的100x100的头像,但40x40像素则是一定会有。
gender性别。 如果获取不到则默认返回"男"
gender_type性别类型。默认返回2
province
city
year
constellation星座
is_yellow_vip标识用户是否为黄钻用户
yellow_vip_level黄钻等级
is_yellow_year_vip是否为年费黄钻用户


至此,你就能完成接入QQ登录了,是不是很简单?快去实现你的想法吧!