From d0eea86cd373dc1cb6f7c35af9c6756d2a9373d0 Mon Sep 17 00:00:00 2001 From: zijiren233 Date: Sun, 3 Dec 2023 22:04:43 +0800 Subject: [PATCH] Fix: qq oauth2 get token and refresh token and get user info --- internal/db/db.go | 2 +- internal/provider/providers/qq.go | 79 +++++++++++++++++++++++++++---- 2 files changed, 70 insertions(+), 11 deletions(-) diff --git a/internal/db/db.go b/internal/db/db.go index 6980b01..96a979d 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -288,7 +288,7 @@ func WhereRoomUserStatus(status model.RoomUserStatus) func(db *gorm.DB) *gorm.DB func HandleNotFound(err error, errMsg ...string) error { if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { - return fmt.Errorf("not found: %s", strings.Join(errMsg, " ")) + return fmt.Errorf("%s not found", strings.Join(errMsg, " ")) } return err } diff --git a/internal/provider/providers/qq.go b/internal/provider/providers/qq.go index 59d51ae..040b44c 100644 --- a/internal/provider/providers/qq.go +++ b/internal/provider/providers/qq.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net/http" + "net/url" json "github.com/json-iterator/go" "github.com/synctv-org/synctv/internal/provider" @@ -20,7 +21,7 @@ func newQQProvider() provider.ProviderInterface { Scopes: []string{"get_user_info"}, Endpoint: oauth2.Endpoint{ AuthURL: "https://graph.qq.com/oauth2.0/authorize", - TokenURL: "https://graph.qq.com/oauth2.0/token?grant_type=authorization_code", + TokenURL: "https://graph.qq.com/oauth2.0/token", }, }, } @@ -41,40 +42,98 @@ func (p *QQProvider) NewAuthURL(state string) string { } func (p *QQProvider) GetToken(ctx context.Context, code string) (*oauth2.Token, error) { - return p.config.Exchange(ctx, code) + params := url.Values{} + params.Set("grant_type", "authorization_code") + params.Set("code", code) + params.Set("redirect_uri", p.config.RedirectURL) + params.Set("client_id", p.config.ClientID) + params.Set("client_secret", p.config.ClientSecret) + params.Set("fmt", "json") + req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s?%s", p.config.Endpoint.TokenURL, params.Encode()), nil) + if err != nil { + return nil, err + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + tk := &oauth2.Token{} + return tk, json.NewDecoder(resp.Body).Decode(tk) } func (p *QQProvider) RefreshToken(ctx context.Context, tk string) (*oauth2.Token, error) { - return p.config.TokenSource(ctx, &oauth2.Token{RefreshToken: tk}).Token() + params := url.Values{} + params.Set("grant_type", "refresh_token") + params.Set("refresh_token", tk) + params.Set("client_id", p.config.ClientID) + params.Set("client_secret", p.config.ClientSecret) + params.Set("fmt", "json") + req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s?%s", p.config.Endpoint.TokenURL, params.Encode()), nil) + if err != nil { + return nil, err + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + newTk := &oauth2.Token{} + return newTk, json.NewDecoder(resp.Body).Decode(newTk) } func (p *QQProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*provider.UserInfo, error) { - client := p.config.Client(ctx, tk) req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("https://graph.qq.com/oauth2.0/me?access_token=%s&fmt=json", tk.AccessToken), nil) if err != nil { return nil, err } - resp, err := client.Do(req) + resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer resp.Body.Close() - ui := qqProviderUserInfo{} - err = json.NewDecoder(resp.Body).Decode(&ui) + ume := qqProviderMe{} + err = json.NewDecoder(resp.Body).Decode(&ume) + if err != nil { + return nil, err + } + req, err = http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("https://graph.qq.com/user/get_user_info?access_token=%s&oauth_consumer_key=%s&openid=%s&fmt=json", tk.AccessToken, p.config.ClientID, ume.Openid), nil) + if err != nil { + return nil, err + } + resp2, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + defer resp2.Body.Close() + ui := qqUserInfo{} + err = json.NewDecoder(resp2.Body).Decode(&ui) if err != nil { return nil, err } return &provider.UserInfo{ - Username: ui.Openid, - ProviderUserID: ui.Openid, + Username: ui.Nickname, + ProviderUserID: ume.Openid, }, nil } -type qqProviderUserInfo struct { +type qqProviderMe struct { ClientID string `json:"client_id"` Openid string `json:"openid"` } +type qqUserInfo struct { + Ret int `json:"ret"` + Msg string `json:"msg"` + Nickname string `json:"nickname"` + Figureurl string `json:"figureurl"` + Figureurl1 string `json:"figureurl_1"` + Figureurl2 string `json:"figureurl_2"` + FigureurlQq1 string `json:"figureurl_qq_1"` + FigureurlQq2 string `json:"figureurl_qq_2"` + Gender string `json:"gender"` +} + func init() { RegisterProvider(newQQProvider()) }