accessToken.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. package context
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "time"
  6. "github.com/silenceper/wechat/v2/util"
  7. )
  8. const (
  9. componentAccessTokenURL = "https://api.weixin.qq.com/cgi-bin/component/api_component_token"
  10. getPreCodeURL = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=%s"
  11. queryAuthURL = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=%s"
  12. refreshTokenURL = "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=%s"
  13. getComponentInfoURL = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?component_access_token=%s"
  14. //TODO 获取授权方选项信息
  15. //getComponentConfigURL = "https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_option?component_access_token=%s"
  16. //TODO 获取已授权的账号信息
  17. //getuthorizerListURL = "POST https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_list?component_access_token=%s"
  18. )
  19. // ComponentAccessToken 第三方平台
  20. type ComponentAccessToken struct {
  21. AccessToken string `json:"component_access_token"`
  22. ExpiresIn int64 `json:"expires_in"`
  23. }
  24. // GetComponentAccessToken 获取 ComponentAccessToken
  25. func (ctx *Context) GetComponentAccessToken() (string, error) {
  26. accessTokenCacheKey := fmt.Sprintf("component_access_token_%s", ctx.AppID)
  27. val := ctx.Cache.Get(accessTokenCacheKey)
  28. if val == nil {
  29. return "", fmt.Errorf("cann't get component access token")
  30. }
  31. return val.(string), nil
  32. }
  33. // SetComponentAccessToken 通过component_verify_ticket 获取 ComponentAccessToken
  34. func (ctx *Context) SetComponentAccessToken(verifyTicket string) (*ComponentAccessToken, error) {
  35. body := map[string]string{
  36. "component_appid": ctx.AppID,
  37. "component_appsecret": ctx.AppSecret,
  38. "component_verify_ticket": verifyTicket,
  39. }
  40. respBody, err := util.PostJSON(componentAccessTokenURL, body)
  41. if err != nil {
  42. return nil, err
  43. }
  44. at := &ComponentAccessToken{}
  45. if err := json.Unmarshal(respBody, at); err != nil {
  46. return nil, err
  47. }
  48. accessTokenCacheKey := fmt.Sprintf("component_access_token_%s", ctx.AppID)
  49. expires := at.ExpiresIn - 1500
  50. if err := ctx.Cache.Set(accessTokenCacheKey, at.AccessToken, time.Duration(expires)*time.Second); err != nil {
  51. return nil, nil
  52. }
  53. return at, nil
  54. }
  55. // GetPreCode 获取预授权码
  56. func (ctx *Context) GetPreCode() (string, error) {
  57. cat, err := ctx.GetComponentAccessToken()
  58. if err != nil {
  59. return "", err
  60. }
  61. req := map[string]string{
  62. "component_appid": ctx.AppID,
  63. }
  64. uri := fmt.Sprintf(getPreCodeURL, cat)
  65. body, err := util.PostJSON(uri, req)
  66. if err != nil {
  67. return "", err
  68. }
  69. var ret struct {
  70. PreCode string `json:"pre_auth_code"`
  71. }
  72. if err := json.Unmarshal(body, &ret); err != nil {
  73. return "", err
  74. }
  75. return ret.PreCode, nil
  76. }
  77. // ID 微信返回接口中各种类型字段
  78. type ID struct {
  79. ID int `json:"id"`
  80. }
  81. // AuthBaseInfo 授权的基本信息
  82. type AuthBaseInfo struct {
  83. AuthrAccessToken
  84. FuncInfo []AuthFuncInfo `json:"func_info"`
  85. }
  86. // AuthFuncInfo 授权的接口内容
  87. type AuthFuncInfo struct {
  88. FuncscopeCategory ID `json:"funcscope_category"`
  89. }
  90. // AuthrAccessToken 授权方AccessToken
  91. type AuthrAccessToken struct {
  92. Appid string `json:"authorizer_appid"`
  93. AccessToken string `json:"authorizer_access_token"`
  94. ExpiresIn int64 `json:"expires_in"`
  95. RefreshToken string `json:"authorizer_refresh_token"`
  96. }
  97. // QueryAuthCode 使用授权码换取公众号或小程序的接口调用凭据和授权信息
  98. func (ctx *Context) QueryAuthCode(authCode string) (*AuthBaseInfo, error) {
  99. cat, err := ctx.GetComponentAccessToken()
  100. if err != nil {
  101. return nil, err
  102. }
  103. req := map[string]string{
  104. "component_appid": ctx.AppID,
  105. "authorization_code": authCode,
  106. }
  107. uri := fmt.Sprintf(queryAuthURL, cat)
  108. body, err := util.PostJSON(uri, req)
  109. if err != nil {
  110. return nil, err
  111. }
  112. var ret struct {
  113. util.CommonError
  114. Info *AuthBaseInfo `json:"authorization_info"`
  115. }
  116. if err := json.Unmarshal(body, &ret); err != nil {
  117. return nil, err
  118. }
  119. if ret.ErrCode != 0 {
  120. err = fmt.Errorf("QueryAuthCode error : errcode=%v , errmsg=%v", ret.ErrCode, ret.ErrMsg)
  121. return nil, err
  122. }
  123. return ret.Info, nil
  124. }
  125. // RefreshAuthrToken 获取(刷新)授权公众号或小程序的接口调用凭据(令牌)
  126. func (ctx *Context) RefreshAuthrToken(appid, refreshToken string) (*AuthrAccessToken, error) {
  127. cat, err := ctx.GetComponentAccessToken()
  128. if err != nil {
  129. return nil, err
  130. }
  131. req := map[string]string{
  132. "component_appid": ctx.AppID,
  133. "authorizer_appid": appid,
  134. "authorizer_refresh_token": refreshToken,
  135. }
  136. uri := fmt.Sprintf(refreshTokenURL, cat)
  137. body, err := util.PostJSON(uri, req)
  138. if err != nil {
  139. return nil, err
  140. }
  141. ret := &AuthrAccessToken{}
  142. if err := json.Unmarshal(body, ret); err != nil {
  143. return nil, err
  144. }
  145. authrTokenKey := "authorizer_access_token_" + appid
  146. if err := ctx.Cache.Set(authrTokenKey, ret.AccessToken, time.Minute*80); err != nil {
  147. return nil, err
  148. }
  149. return ret, nil
  150. }
  151. // GetAuthrAccessToken 获取授权方AccessToken
  152. func (ctx *Context) GetAuthrAccessToken(appid string) (string, error) {
  153. authrTokenKey := "authorizer_access_token_" + appid
  154. val := ctx.Cache.Get(authrTokenKey)
  155. if val == nil {
  156. return "", fmt.Errorf("cannot get authorizer %s access token", appid)
  157. }
  158. return val.(string), nil
  159. }
  160. // AuthorizerInfo 授权方详细信息
  161. type AuthorizerInfo struct {
  162. NickName string `json:"nick_name"`
  163. HeadImg string `json:"head_img"`
  164. ServiceTypeInfo ID `json:"service_type_info"`
  165. VerifyTypeInfo ID `json:"verify_type_info"`
  166. UserName string `json:"user_name"`
  167. PrincipalName string `json:"principal_name"`
  168. BusinessInfo struct {
  169. OpenStore string `json:"open_store"`
  170. OpenScan string `json:"open_scan"`
  171. OpenPay string `json:"open_pay"`
  172. OpenCard string `json:"open_card"`
  173. OpenShake string `json:"open_shake"`
  174. }
  175. Alias string `json:"alias"`
  176. QrcodeURL string `json:"qrcode_url"`
  177. }
  178. // GetAuthrInfo 获取授权方的帐号基本信息
  179. func (ctx *Context) GetAuthrInfo(appid string) (*AuthorizerInfo, *AuthBaseInfo, error) {
  180. cat, err := ctx.GetComponentAccessToken()
  181. if err != nil {
  182. return nil, nil, err
  183. }
  184. req := map[string]string{
  185. "component_appid": ctx.AppID,
  186. "authorizer_appid": appid,
  187. }
  188. uri := fmt.Sprintf(getComponentInfoURL, cat)
  189. body, err := util.PostJSON(uri, req)
  190. if err != nil {
  191. return nil, nil, err
  192. }
  193. var ret struct {
  194. AuthorizerInfo *AuthorizerInfo `json:"authorizer_info"`
  195. AuthorizationInfo *AuthBaseInfo `json:"authorization_info"`
  196. }
  197. if err := json.Unmarshal(body, &ret); err != nil {
  198. return nil, nil, err
  199. }
  200. return ret.AuthorizerInfo, ret.AuthorizationInfo, nil
  201. }