diff --git a/mini/access_token.go b/mini/access_token.go index 8e3edc8..7211b24 100644 --- a/mini/access_token.go +++ b/mini/access_token.go @@ -63,7 +63,7 @@ func (s *SDK) goAutoRefreshStableAccessToken() { time.Sleep(s.RefreshInternal / 2) err := s.getStableAccessToken() if err != nil { - s.logger.Errorf("get access token error, after 10s retry: %+v", err) + s.logger.Errorf("get stable access token error, after 10s retry: %+v", err) continue } } @@ -86,7 +86,7 @@ func (s *SDK) SetMiniAccessToken(accessToken string) { // ===================================================================================================================== -// 获取接口调用凭据 +// 获取 Access Token // 微信小程序文档:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getAccessToken.html func GetAccessToken(c context.Context, appid, secret string) (at *AccessToken, err error) { uri := HostDefault + "/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret @@ -100,7 +100,7 @@ func GetAccessToken(c context.Context, appid, secret string) (at *AccessToken, e return at, nil } -// 获取稳定版接口调用凭据 +// 获取 Stable Access Token // 微信小程序文档:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getStableAccessToken.html func GetStableAccessToken(c context.Context, appid, secret string, forceRefresh bool) (at *AccessToken, err error) { url := HostDefault + "/cgi-bin/stable_token" diff --git a/public/access_token.go b/public/access_token.go index 0711a92..d3e8561 100644 --- a/public/access_token.go +++ b/public/access_token.go @@ -1,14 +1,17 @@ package public import ( + "context" "fmt" "runtime" "time" + + "github.com/go-pay/bm" ) -// 获取公众号全局唯一后台接口调用凭据(access_token) -// 公众号文档:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html -func (s *SDK) getAccessToken() (err error) { +// 获取公众号全局唯一后台稳定版接口调用凭据(access_token) +// 公众号文档:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/getStableAccessToken.html +func (s *SDK) getStableAccessToken() (err error) { defer func() { if err != nil { // reset default refresh internal @@ -19,9 +22,14 @@ func (s *SDK) getAccessToken() (err error) { } }() - path := "/cgi-bin/token?grant_type=client_credential&appid=" + s.Appid + "&secret=" + s.Secret + path := "/cgi-bin/stable_token" + body := make(bm.BodyMap) + body.Set("grant_type", "client_credential"). + Set("appid", s.Appid). + Set("secret", s.Secret). + Set("force_refresh", false) at := &AccessToken{} - if _, err = s.DoRequestGet(s.ctx, path, at); err != nil { + if _, err = s.doRequestPost(s.ctx, path, body, at); err != nil { return } if at.Errcode != Success { @@ -36,26 +44,26 @@ func (s *SDK) getAccessToken() (err error) { return nil } -func (s *SDK) goAutoRefreshAccessTokenJob() { +func (s *SDK) goAutoRefreshStableAccessToken() { defer func() { if r := recover(); r != nil { buf := make([]byte, 64<<10) buf = buf[:runtime.Stack(buf, false)] - s.logger.Errorf("public_goAutoRefreshAccessTokenJob: panic recovered: %s\n%s", r, buf) + s.logger.Errorf("public_goAutoRefreshStableAccessTokenJob: panic recovered: %s\n%s", r, buf) time.Sleep(time.Second * 3) - if err := s.getAccessToken(); err != nil { + if err := s.getStableAccessToken(); err != nil { // 失败就不再自动刷新了 return } - s.goAutoRefreshAccessTokenJob() + s.goAutoRefreshStableAccessToken() } }() for { // every one hour, request new access token, default 10s time.Sleep(s.RefreshInternal / 2) - err := s.getAccessToken() + err := s.getStableAccessToken() if err != nil { - s.logger.Errorf("get access token error, after 10s retry: %+v", err) + s.logger.Errorf("get stable access token error, after 10s retry: %+v", err) continue } } @@ -75,3 +83,36 @@ func (s *SDK) GetPublicAccessToken() (at string) { func (s *SDK) SetPublicAccessToken(accessToken string) { s.accessToken = accessToken } + +// 获取 Access Token +// 微信公众号文档:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html +func GetAccessToken(c context.Context, appid, secret string) (at *AccessToken, err error) { + uri := HostDefault + "/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret + at = &AccessToken{} + if err = doRequestGet(c, uri, at); err != nil { + return nil, err + } + if at.Errcode != Success { + return nil, fmt.Errorf("errcode(%d), errmsg(%s)", at.Errcode, at.Errmsg) + } + return at, nil +} + +// 获取 Stable Access Token +// 微信公众号文档:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/getStableAccessToken.html +func GetStableAccessToken(c context.Context, appid, secret string, forceRefresh bool) (at *AccessToken, err error) { + url := HostDefault + "/cgi-bin/stable_token" + body := make(bm.BodyMap) + body.Set("grant_type", "client_credential"). + Set("appid", appid). + Set("secret", secret). + Set("force_refresh", forceRefresh) + at = &AccessToken{} + if err = doRequestPost(c, url, body, at); err != nil { + return nil, err + } + if at.Errcode != Success { + return nil, fmt.Errorf("errcode(%d), errmsg(%s)", at.Errcode, at.Errmsg) + } + return at, nil +} diff --git a/public/public.go b/public/public.go index d7f7720..d5d8422 100644 --- a/public/public.go +++ b/public/public.go @@ -3,6 +3,7 @@ package public import ( "context" "fmt" + "github.com/go-pay/bm" "net/http" "time" @@ -44,10 +45,10 @@ func New(appid, secret string, autoManageToken bool) (p *SDK, err error) { logger: logger, } if autoManageToken { - if err = p.getAccessToken(); err != nil { + if err = p.getStableAccessToken(); err != nil { return nil, err } - go p.goAutoRefreshAccessTokenJob() + go p.goAutoRefreshStableAccessToken() } return } @@ -84,3 +85,29 @@ func (s *SDK) DoRequestGet(c context.Context, path string, ptr any) (res *http.R } return res, nil } + +func doRequestGet(c context.Context, uri string, ptr any) (err error) { + req := xhttp.NewClient().Req() + req.Header.Add(wechat.HeaderRequestID, fmt.Sprintf("%s-%d", util.RandomString(21), time.Now().Unix())) + _, bs, err := req.Get(uri).EndBytes(c) + if err != nil { + return fmt.Errorf("http.request(GET, %s), err:%w", uri, err) + } + if err = js.UnmarshalBytes(bs, ptr); err != nil { + return fmt.Errorf("js.UnmarshalBytes(%s, %+v):%w", string(bs), ptr, err) + } + return +} + +func doRequestPost(c context.Context, url string, body bm.BodyMap, ptr any) (err error) { + req := xhttp.NewClient().Req() + req.Header.Add(wechat.HeaderRequestID, fmt.Sprintf("%s-%d", util.RandomString(21), time.Now().Unix())) + _, bs, err := req.Post(url).SendBodyMap(body).EndBytes(c) + if err != nil { + return fmt.Errorf("http.request(POST, %s), err:%w", url, err) + } + if err = js.UnmarshalBytes(bs, ptr); err != nil { + return fmt.Errorf("js.UnmarshalBytes(%s, %+v):%w", string(bs), ptr, err) + } + return +}