網站接入QQ登錄注意事項


本文主要跟大家分享下我的個人博客 陳新的個人博客 站點在接入QQ登錄的過程中所遇到的一些問題,在這里分享給大家,方便准備想接入QQ登錄功能的或者接入過程中正遇到一些問題的小伙伴快速解決問題,避免踩我已經踩過的坑。

一、跳轉到QQ登錄授權頁面的地址

跳轉到QQ登錄授權頁面的地址應該用:https://graph.qq.com/oauth2.0/authorize ,而不是用https://graph.qq.com/oauth2.0/show 這個前綴,后者這個是PC端的QQ授權頁面,如果你的網站跳轉到的是后面這個地址,將會導致手機端使用的QQ登錄授權頁面也是PC端的,這樣手機端就無法使用QQ一鍵登錄功能了,正確的應該使用前者這個地址,騰訊會自動判斷跳轉到PC端還是手機端的QQ登錄授權頁面。

手機端的QQ登錄界面應該類似於如下:

 

二、QQ授權頁面傳參

不要往QQ授權頁面的地址中傳入參數display=pc,這個參數告訴QQ說我當前正在PC端進行QQ一件登錄,因此也會造成和上述一樣的問題。

以上就是本人在對接QQ登錄過程中遇到的一些問題,下面附上本人的個人站中用到的QQ登錄的代碼,方便大家快速集成QQ登錄功能,本人的個人站使用asp.net core 3.1.

接口對接代碼

using BlogSys.Models;
using BlogSys.Models.QQLogin;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace BlogSys.Services
{
    /// <summary>
    /// QQ登錄功能。
    /// </summary>
    public class QQLoginService
    {
        const string callbackUrl = "這里填寫你提供給騰訊的你的網站的回調地址";
        const string clientId = "這里填寫網站應用ID";
        const string clientSecret = "這里填寫網站應用秘鑰";
        HttpClient client;
        ILogger<QQLoginService> logger;
        public QQLoginService(HttpClient client, ILogger<QQLoginService> logger)
        {
            this.client = client;
            this.logger = logger;
        }
        /// <summary>
        /// QQ 登錄
        /// </summary>
        /// <param name="code"></param>
        /// <param name="redirect_url"></param>
        /// <returns></returns>
        public async Task<QQUserInfo> Login(string code)
        {
            QQUserInfo userInfo = null;
            QQApiAccessToken accessToken = await this.GetAccessToken(code, callbackUrl);
            QQOpenIDInfo openIDInfo = await this.GetOpenID(accessToken.access_token);
            userInfo = await this.GetUserInfo(accessToken.access_token, clientId, openIDInfo.openid);
            userInfo.OpenID = openIDInfo.openid;
            return userInfo;
        }
        //根據不同頁面點擊QQ登錄時,生成QQ授權登錄頁面地址,方面登錄前在哪個頁面,登錄后就跳回哪個頁面。
        public string GetQQLoginUrl(string redirectUrl)
        {
            return $"https://graph.qq.com/oauth2.0/authorize?which=Login&response_type=code&redirect_uri={callbackUrl}&client_id={clientId}&state={redirectUrl}";
        }
        /// <summary>
        /// 獲取API訪問Token.
        /// </summary>
        /// <param name="code"></param>
        /// <param name="redirect_uri"></param>
        /// <param name="fmt"></param>
        /// <returns></returns>
        public async Task<QQApiAccessToken> GetAccessToken(string code, string redirect_uri, string fmt = "json")
        {
            string grant_type = "authorization_code";
            string apiUrl = $"/oauth2.0/token?grant_type={grant_type}&client_id={clientId}&client_secret={clientSecret}&code={code}&redirect_uri={redirect_uri}&fmt={fmt}";
            HttpResponseMessage responseMessage = await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, apiUrl));
            if (!responseMessage.IsSuccessStatusCode)
                return null;
            string resultStr = await responseMessage.Content.ReadAsStringAsync();
            if (string.IsNullOrWhiteSpace(resultStr))
            {
                return null;
            }
            return JsonSerializer.Deserialize<QQApiAccessToken>(resultStr);
        }
        /// <summary>
        /// 根據刷新Token獲取訪問Token.
        /// </summary>
        /// <param name="refresh_token"></param>
        /// <param name="fmt"></param>
        /// <returns></returns>
        public async Task<QQApiAccessToken> GetAccessTokenByRefreshToken(string refresh_token, string fmt = "json")
        {
            string grant_type = "refresh_token";
            string apiUrl = $"/oauth2.0/token?grant_type={grant_type}&client_id={clientId}&client_secret={clientSecret}&refresh_token={refresh_token}&fmt={fmt}";
            HttpResponseMessage responseMessage = await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, apiUrl));
            if (!responseMessage.IsSuccessStatusCode)
                return null;
            string resultStr = await responseMessage.Content.ReadAsStringAsync();
            if (string.IsNullOrWhiteSpace(resultStr))
            {
                return null;
            }
            return JsonSerializer.Deserialize<QQApiAccessToken>(resultStr);
        }
        /// <summary>
        /// 獲取QQ OpenId信息
        /// </summary>
        /// <param name="access_token">API訪問Token</param>
        /// <param name="fmt"></param>
        /// <returns></returns>
        public async Task<QQOpenIDInfo> GetOpenID(string access_token, string fmt = "json")
        {
            string apiUrl = $"oauth2.0/me?access_token={access_token}&fmt={fmt}";
            HttpResponseMessage responseMessage = await this.client.SendAsync(new HttpRequestMessage(HttpMethod.Get, apiUrl));
            if (!responseMessage.IsSuccessStatusCode)
                return null;
            string apiResult = await responseMessage.Content.ReadAsStringAsync();
            if (string.IsNullOrWhiteSpace(apiResult))
                return null;
            return JsonSerializer.Deserialize<QQOpenIDInfo>(apiResult);
        }
        /// <summary>
        /// 獲取用戶信息
        /// </summary>
        /// <param name="access_token"></param>
        /// <param name="oauth_consumer_key"></param>
        /// <param name="openid"></param>
        /// <returns></returns>
        public async Task<QQUserInfo> GetUserInfo(string access_token, string oauth_consumer_key, string openid)
        {
            string apiUrl = $"user/get_user_info?access_token={access_token}&oauth_consumer_key={oauth_consumer_key}&openid={openid}";
            HttpResponseMessage responseMessage = await this.client.SendAsync(new HttpRequestMessage(HttpMethod.Get, apiUrl));
            if (!responseMessage.IsSuccessStatusCode)
                return null;
            string apiResult = await responseMessage.Content.ReadAsStringAsync();
            if (string.IsNullOrWhiteSpace(apiResult))
                return null;
            return JsonSerializer.Deserialize<QQUserInfo>(apiResult);
        }
    }
}

 

QQ登錄相關實體模型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BlogSys.Models.QQLogin
{
    public class QQUserInfo
    {
        /// <summary>
        /// 返回碼 0:成功 其他:失敗
        /// </summary>
        public int ret { get; set; }
        /// <summary>
        /// 如果ret<0,會有相應的錯誤信息提示,返回數據全部用UTF-8編碼。
        /// </summary>
        public string msg { get; set; }
        /// <summary>
        /// 用戶在QQ空間的昵稱。
        /// </summary>
        public string nickname { get; set; }
        /// <summary>
        /// 大小為30×30像素的QQ空間頭像URL。
        /// </summary>
        public string figureurl { get; set; }
        /// <summary>
        /// 大小為50×50像素的QQ空間頭像URL。
        /// </summary>
        public string figureurl_1 { get; set; }
        /// <summary>
        /// 大小為100×100像素的QQ空間頭像URL。
        /// </summary>
        public string figureurl_2 { get; set; }
        /// <summary>
        /// 大小為40×40像素的QQ頭像URL。
        /// </summary>
        public string figureurl_qq_1 { get; set; }
        /// <summary>
        /// 大小為100×100像素的QQ頭像URL。
        /// 需要注意,不是所有的用戶都擁有QQ的100x100的頭像,但40x40像素則是一定會有。
        /// </summary>
        public string figureurl_qq_2 { get; set; }
        /// <summary>
        /// 性別。 如果獲取不到則默認返回"男"
        /// </summary>
        public string gender { get; set; }
        public string is_yellow_vip { get; set; }
        public string vip { get; set; }
        public string yellow_vip_level { get; set; }
        public string level { get; set; }
        public string is_yellow_year_vip { get; set; }
        /// <summary>
        /// QQ用戶唯一標識。
        /// </summary>
        public string OpenID { get; set; }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BlogSys.Models.QQLogin
{
    public class QQApiAccessToken
    {
        /// <summary>
        /// 授權令牌,Access_Token。
        /// </summary>
        public string access_token { get; set; }
        /// <summary>
        /// 該access token的有效期,單位為秒。
        /// </summary>
        public string expires_in { get; set; }
        /// <summary>
        /// 在授權自動續期步驟中,獲取新的Access_Token時需要提供的參數。
        /// 注:refresh_token僅一次有效
        /// </summary>
        public string refresh_token { get; set; }
    }
}

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BlogSys.Models.QQLogin
{
    public class QQOpenIDInfo
    {
        public string client_id { get; set; }
        public string openid { get; set; }
    }
}

 以下代碼為asp.net core 中注入HttpClient 的部分。

public void ConfigureServices(IServiceCollection services)
{
	services.AddHttpClient<QQLoginService>(httpClient =>
	{
		httpClient.BaseAddress = new Uri("https://graph.qq.com");
	});
   
}

 

好了,以上就是我今天要和小伙伴們分享的內容,如果你在對接QQ登錄過程中遇到了一些困惑,那么請登錄我的  個人博客 並在我的這篇文章中留言,因為我的個人博客收到用戶留言,會立刻通知我這邊,以便我快速幫你們解答。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM