qq.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. package dao
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "io/ioutil"
  7. "net/http"
  8. "net/url"
  9. "strconv"
  10. "strings"
  11. "time"
  12. "go-common/app/service/main/passport-sns/model"
  13. "go-common/library/ecode"
  14. "go-common/library/log"
  15. )
  16. const (
  17. _qqAuthorizeUrl = "https://graph.qq.com/oauth2.0/authorize"
  18. _qqAccessTokenUrl = "https://graph.qq.com/oauth2.0/token"
  19. _qqOpenIDUrl = "https://graph.qq.com/oauth2.0/me"
  20. _respCodeSuccess = 0
  21. )
  22. // QQAuthorize .
  23. func (d *Dao) QQAuthorize(c context.Context, appID, redirectURL, display string) (url string) {
  24. 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"
  25. displayParam := ""
  26. if display != "" {
  27. displayParam = "&display=" + display
  28. }
  29. return fmt.Sprintf(_qqAuthorizeUrl+"?response_type=code&state=authorize%s&client_id=%s&redirect_uri=%s&scope=%s", displayParam, appID, redirectURL, scope)
  30. }
  31. // QQOauth2Info .
  32. func (d *Dao) QQOauth2Info(c context.Context, code, redirectUrl string, app *model.SnsApps) (res *model.Oauth2Info, err error) {
  33. accessResp, err := d.qqAccessToken(c, code, app.AppID, app.AppSecret, redirectUrl)
  34. if err != nil {
  35. return nil, err
  36. }
  37. openIdResp, err := d.qqOpenID(c, accessResp.Token, app.Business)
  38. if err != nil {
  39. return nil, err
  40. }
  41. // TODO 保证能获取到UnionID的情况可以考虑去掉
  42. if openIdResp.UnionID == "" {
  43. openIdResp.UnionID = openIdResp.OpenID
  44. }
  45. res = &model.Oauth2Info{
  46. UnionID: openIdResp.UnionID,
  47. OpenID: openIdResp.OpenID,
  48. Token: accessResp.Token,
  49. Refresh: accessResp.Refresh,
  50. Expires: accessResp.Expires,
  51. }
  52. return
  53. }
  54. // qqAccessToken .
  55. func (d *Dao) qqAccessToken(c context.Context, code, appID, appSecret, redirectUrl string) (resp *model.QQAccessResp, err error) {
  56. var (
  57. res *http.Response
  58. bs []byte
  59. params = url.Values{}
  60. value = url.Values{}
  61. expires int64
  62. )
  63. params.Set("client_id", appID)
  64. params.Set("client_secret", appSecret)
  65. params.Set("grant_type", "authorization_code")
  66. params.Set("code", code)
  67. params.Set("redirect_uri", redirectUrl)
  68. if res, err = d.client.Get(_qqAccessTokenUrl + "?" + params.Encode()); err != nil {
  69. log.Error("d.qqAccessToken error(%+v) code(%s) appID(%s)", err, code, appID)
  70. return nil, err
  71. }
  72. defer res.Body.Close()
  73. if bs, err = ioutil.ReadAll(res.Body); err != nil {
  74. log.Error("ioutil.ReadAll() error(%+v) code(%s) appID(%s)", err, code, appID)
  75. return nil, err
  76. }
  77. respStr := string(bs)
  78. if strings.HasPrefix(respStr, "callback") {
  79. resp = new(model.QQAccessResp)
  80. start := strings.Index(respStr, "{")
  81. end := strings.Index(respStr, "}")
  82. respStr = respStr[start : end+1]
  83. if err = json.Unmarshal([]byte(respStr), resp); err != nil {
  84. return nil, err
  85. }
  86. log.Error("request qq token failed with code(%d) desc(%s)", resp.Code, resp.Description)
  87. return nil, ecode.PassportSnsRequestErr
  88. }
  89. value, err = url.ParseQuery(respStr)
  90. expires, err = strconv.ParseInt(value.Get("expires_in"), 10, 64)
  91. resp = &model.QQAccessResp{
  92. Token: value.Get("access_token"),
  93. Refresh: value.Get("refresh_token"),
  94. Expires: time.Now().Unix() + expires,
  95. }
  96. return resp, nil
  97. }
  98. // qqOpenID .
  99. func (d *Dao) qqOpenID(c context.Context, token string, business int) (resp *model.QQOpenIDResp, err error) {
  100. var (
  101. res *http.Response
  102. bs []byte
  103. params = url.Values{}
  104. )
  105. params.Set("access_token", token)
  106. params.Set("unionid", "1")
  107. // TODO 如果后续要支持没有unionid权限的appid,可以考虑在sns_apps表增加unionid权限标识的字段
  108. //if business == model.BusinessMall {
  109. // params.Set("unionid", "1")
  110. //}
  111. if res, err = d.client.Get(_qqOpenIDUrl + "?" + params.Encode()); err != nil {
  112. log.Error("d.qqOpenID error(%+v) token(%d) business(%d)", err, token, business)
  113. return nil, err
  114. }
  115. defer res.Body.Close()
  116. if bs, err = ioutil.ReadAll(res.Body); err != nil {
  117. log.Error("ioutil.ReadAll() error(%+v) token(%d) business(%d)", err, token, business)
  118. return nil, err
  119. }
  120. respStr := string(bs)
  121. if strings.HasPrefix(respStr, "callback") {
  122. start := strings.Index(respStr, "{")
  123. end := strings.Index(respStr, "}")
  124. respStr = respStr[start : end+1]
  125. }
  126. resp = new(model.QQOpenIDResp)
  127. if err = json.Unmarshal([]byte(respStr), resp); err != nil {
  128. return nil, err
  129. }
  130. if resp.Code == _respCodeSuccess {
  131. return resp, nil
  132. }
  133. log.Error("request qq openid failed with code(%d) desc(%s)", resp.Code, resp.Description)
  134. return nil, ecode.PassportSnsRequestErr
  135. }