oauth.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package oauth
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/http"
  6. "net/url"
  7. "github.com/silenceper/wechat/context"
  8. "github.com/silenceper/wechat/util"
  9. )
  10. const (
  11. redirectOauthURL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect"
  12. accessTokenURL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code"
  13. refreshAccessTokenURL = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s"
  14. userInfoURL = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN"
  15. checkAccessTokenURL = "https://api.weixin.qq.com/sns/auth?access_token=%s&openid=%s"
  16. )
  17. //Oauth 保存用户授权信息
  18. type Oauth struct {
  19. *context.Context
  20. }
  21. //NewOauth 实例化授权信息
  22. func NewOauth(context *context.Context) *Oauth {
  23. auth := new(Oauth)
  24. auth.Context = context
  25. return auth
  26. }
  27. //GetRedirectURL 获取跳转的url地址
  28. func (oauth *Oauth) GetRedirectURL(redirectURI, scope, state string) (string, error) {
  29. //url encode
  30. urlStr := url.QueryEscape(redirectURI)
  31. return fmt.Sprintf(redirectOauthURL, oauth.AppID, urlStr, scope, state), nil
  32. }
  33. //Redirect 跳转到网页授权
  34. func (oauth *Oauth) Redirect(writer http.ResponseWriter, redirectURI, scope, state string) error {
  35. location, err := oauth.GetRedirectURL(redirectURI, scope, state)
  36. if err != nil {
  37. return err
  38. }
  39. //location 为完整地址,所以不需要request
  40. http.Redirect(writer, nil, location, 302)
  41. return nil
  42. }
  43. // ResAccessToken 获取用户授权access_token的返回结果
  44. type ResAccessToken struct {
  45. util.CommonError
  46. AccessToken string `json:"access_token"`
  47. ExpiresIn int64 `json:"expires_in"`
  48. RefreshToken string `json:"refresh_token"`
  49. OpenID string `json:"openid"`
  50. Scope string `json:"scope"`
  51. }
  52. // GetUserAccessToken 通过网页授权的code 换取access_token(区别于context中的access_token)
  53. func (oauth *Oauth) GetUserAccessToken(code string) (result ResAccessToken, err error) {
  54. urlStr := fmt.Sprintf(accessTokenURL, oauth.AppID, oauth.AppSecret, code)
  55. var response []byte
  56. response, err = util.HTTPGet(urlStr)
  57. if err != nil {
  58. return
  59. }
  60. err = json.Unmarshal(response, &result)
  61. if err != nil {
  62. return
  63. }
  64. if result.ErrCode != 0 {
  65. err = fmt.Errorf("GetUserAccessToken error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg)
  66. return
  67. }
  68. return
  69. }
  70. //RefreshAccessToken 刷新access_token
  71. func (oauth *Oauth) RefreshAccessToken(refreshToken string) (result ResAccessToken, err error) {
  72. urlStr := fmt.Sprintf(refreshAccessTokenURL, oauth.AppID, refreshToken)
  73. var response []byte
  74. response, err = util.HTTPGet(urlStr)
  75. if err != nil {
  76. return
  77. }
  78. err = json.Unmarshal(response, &result)
  79. if err != nil {
  80. return
  81. }
  82. if result.ErrCode != 0 {
  83. err = fmt.Errorf("GetUserAccessToken error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg)
  84. return
  85. }
  86. return
  87. }
  88. //CheckAccessToken 检验access_token是否有效
  89. func (oauth *Oauth) CheckAccessToken(accessToken, openID string) (b bool, err error) {
  90. urlStr := fmt.Sprintf(checkAccessTokenURL, accessToken, openID)
  91. var response []byte
  92. response, err = util.HTTPGet(urlStr)
  93. if err != nil {
  94. return
  95. }
  96. var result util.CommonError
  97. err = json.Unmarshal(response, &result)
  98. if err != nil {
  99. return
  100. }
  101. if result.ErrCode != 0 {
  102. b = false
  103. return
  104. }
  105. b = true
  106. return
  107. }
  108. //UserInfo 用户授权获取到用户信息
  109. type UserInfo struct {
  110. util.CommonError
  111. OpenID string `json:"openid"`
  112. Nickname string `json:"nickname"`
  113. Sex int32 `json:"sex"`
  114. Province string `json:"province"`
  115. City string `json:"city"`
  116. Country string `json:"country"`
  117. HeadImgURL string `json:"headimgurl"`
  118. Privilege []string `json:"privilege"`
  119. Unionid string `json:"unionid"`
  120. }
  121. //GetUserInfo 如果scope为 snsapi_userinfo 则可以通过此方法获取到用户基本信息
  122. func (oauth *Oauth) GetUserInfo(accessToken, openID string) (result UserInfo, err error) {
  123. urlStr := fmt.Sprintf(userInfoURL, accessToken, openID)
  124. var response []byte
  125. response, err = util.HTTPGet(urlStr)
  126. if err != nil {
  127. return
  128. }
  129. err = json.Unmarshal(response, &result)
  130. if err != nil {
  131. return
  132. }
  133. if result.ErrCode != 0 {
  134. err = fmt.Errorf("GetUserInfo error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg)
  135. return
  136. }
  137. return
  138. }