accessToken.go 6.3 KB

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