2019-04-22 02:59:20 +00:00

149 lines
4.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package dao
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"go-common/app/service/main/passport-sns/model"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_qqAuthorizeUrl = "https://graph.qq.com/oauth2.0/authorize"
_qqAccessTokenUrl = "https://graph.qq.com/oauth2.0/token"
_qqOpenIDUrl = "https://graph.qq.com/oauth2.0/me"
_respCodeSuccess = 0
)
// QQAuthorize .
func (d *Dao) QQAuthorize(c context.Context, appID, redirectURL, display string) (url string) {
scope := "do_like,get_user_info,get_simple_userinfo,get_vip_info,get_vip_rich_info,add_one_blog,list_album,upload_pic,add_album,list_photo,get_info,add_t,del_t,add_pic_t,get_repost_list,get_other_info,get_fanslist,get_idollist,add_idol,del_idol,get_tenpay_addr"
displayParam := ""
if display != "" {
displayParam = "&display=" + display
}
return fmt.Sprintf(_qqAuthorizeUrl+"?response_type=code&state=authorize%s&client_id=%s&redirect_uri=%s&scope=%s", displayParam, appID, redirectURL, scope)
}
// QQOauth2Info .
func (d *Dao) QQOauth2Info(c context.Context, code, redirectUrl string, app *model.SnsApps) (res *model.Oauth2Info, err error) {
accessResp, err := d.qqAccessToken(c, code, app.AppID, app.AppSecret, redirectUrl)
if err != nil {
return nil, err
}
openIdResp, err := d.qqOpenID(c, accessResp.Token, app.Business)
if err != nil {
return nil, err
}
// TODO 保证能获取到UnionID的情况可以考虑去掉
if openIdResp.UnionID == "" {
openIdResp.UnionID = openIdResp.OpenID
}
res = &model.Oauth2Info{
UnionID: openIdResp.UnionID,
OpenID: openIdResp.OpenID,
Token: accessResp.Token,
Refresh: accessResp.Refresh,
Expires: accessResp.Expires,
}
return
}
// qqAccessToken .
func (d *Dao) qqAccessToken(c context.Context, code, appID, appSecret, redirectUrl string) (resp *model.QQAccessResp, err error) {
var (
res *http.Response
bs []byte
params = url.Values{}
value = url.Values{}
expires int64
)
params.Set("client_id", appID)
params.Set("client_secret", appSecret)
params.Set("grant_type", "authorization_code")
params.Set("code", code)
params.Set("redirect_uri", redirectUrl)
if res, err = d.client.Get(_qqAccessTokenUrl + "?" + params.Encode()); err != nil {
log.Error("d.qqAccessToken error(%+v) code(%s) appID(%s)", err, code, appID)
return nil, err
}
defer res.Body.Close()
if bs, err = ioutil.ReadAll(res.Body); err != nil {
log.Error("ioutil.ReadAll() error(%+v) code(%s) appID(%s)", err, code, appID)
return nil, err
}
respStr := string(bs)
if strings.HasPrefix(respStr, "callback") {
resp = new(model.QQAccessResp)
start := strings.Index(respStr, "{")
end := strings.Index(respStr, "}")
respStr = respStr[start : end+1]
if err = json.Unmarshal([]byte(respStr), resp); err != nil {
return nil, err
}
log.Error("request qq token failed with code(%d) desc(%s)", resp.Code, resp.Description)
return nil, ecode.PassportSnsRequestErr
}
value, err = url.ParseQuery(respStr)
expires, err = strconv.ParseInt(value.Get("expires_in"), 10, 64)
resp = &model.QQAccessResp{
Token: value.Get("access_token"),
Refresh: value.Get("refresh_token"),
Expires: time.Now().Unix() + expires,
}
return resp, nil
}
// qqOpenID .
func (d *Dao) qqOpenID(c context.Context, token string, business int) (resp *model.QQOpenIDResp, err error) {
var (
res *http.Response
bs []byte
params = url.Values{}
)
params.Set("access_token", token)
params.Set("unionid", "1")
// TODO 如果后续要支持没有unionid权限的appid可以考虑在sns_apps表增加unionid权限标识的字段
//if business == model.BusinessMall {
// params.Set("unionid", "1")
//}
if res, err = d.client.Get(_qqOpenIDUrl + "?" + params.Encode()); err != nil {
log.Error("d.qqOpenID error(%+v) token(%d) business(%d)", err, token, business)
return nil, err
}
defer res.Body.Close()
if bs, err = ioutil.ReadAll(res.Body); err != nil {
log.Error("ioutil.ReadAll() error(%+v) token(%d) business(%d)", err, token, business)
return nil, err
}
respStr := string(bs)
if strings.HasPrefix(respStr, "callback") {
start := strings.Index(respStr, "{")
end := strings.Index(respStr, "}")
respStr = respStr[start : end+1]
}
resp = new(model.QQOpenIDResp)
if err = json.Unmarshal([]byte(respStr), resp); err != nil {
return nil, err
}
if resp.Code == _respCodeSuccess {
return resp, nil
}
log.Error("request qq openid failed with code(%d) desc(%s)", resp.Code, resp.Description)
return nil, ecode.PassportSnsRequestErr
}