diff --git a/doc/mini.md b/doc/mini.md index 1b2e1c8..dcfd919 100644 --- a/doc/mini.md +++ b/doc/mini.md @@ -21,7 +21,7 @@ import ( // 初始化微信小程序 SDK // Appid:Appid // Secret:appSecret -// autoManageToken:是否自动获取并自动维护刷新 AccessToken +// autoManageToken:是否自动获取并自动维护刷新 AccessToken,默认使用稳定版接口且force_refresh=false miniSDK, err := mini.New(Appid, Secret, true) if err != nil { xlog.Error(err) @@ -126,8 +126,13 @@ if err != nil { * 开放数据解密:`sdk.DecryptOpenData()` * 客服消息 * 获取客服消息内的临时素材:`sdk.CSMessageGetTempMedia()` - * 发送客服消息给用户:`sdk.CSMessageSend()` + * 发送客服消息:`sdk.CSMessageSend()` * 下发客服当前输入状态给用户:`sdk.CSMessageSetTyping()` - * 把媒体文件上传到微信服务器(目前仅支持图片):`sdk.CSMessageUploadTempMedia()` + * 新增图片素材:`sdk.CSMessageUploadTempMedia()` * 统一服务消息 * 发送统一服务消息:`sdk.UniformMessageSend()` 未完成 + +### 微信小程序 公共API + +* `mini.GetAccessToken()` => 获取接口调用凭据 +* `mini.GetStableAccessToken()` => 获取稳定版接口调用凭据 \ No newline at end of file diff --git a/mini/access_token.go b/mini/access_token.go index 6c135f2..52ddf30 100644 --- a/mini/access_token.go +++ b/mini/access_token.go @@ -1,15 +1,17 @@ package mini import ( + "context" "fmt" "runtime" + "strconv" "time" "github.com/go-pay/wechat-sdk/pkg/xlog" ) // 获取小程序全局唯一后台接口调用凭据(access_token) -// 微信小程序文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/access-token/auth.getAccessToken.html +// 微信小程序文档:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getAccessToken.html func (s *SDK) getAccessToken() (err error) { defer func() { if err != nil { @@ -57,6 +59,55 @@ func (s *SDK) goAutoRefreshAccessToken() { } } +// 获取稳定版接口调用凭据 +// 微信小程序文档:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getStableAccessToken.html +func (s *SDK) getStableAccessToken() (err error) { + defer func() { + if err != nil { + // reset default refresh internal + s.RefreshInternal = time.Second * 20 + if s.callback != nil { + go s.callback("", "", 0, err) + } + } + }() + + path := "/cgi-bin/stable_token?grant_type=client_credential&appid=" + s.Appid + "&secret=" + s.Secret + "&force_refresh=false" + at := &AccessToken{} + if err = s.DoRequestGet(s.ctx, path, at); err != nil { + return + } + if at.Errcode != Success { + err = fmt.Errorf("errcode(%d), errmsg(%s)", at.Errcode, at.Errmsg) + return + } + s.accessToken = at.AccessToken + s.RefreshInternal = time.Second * time.Duration(at.ExpiresIn) + if s.callback != nil { + go s.callback(s.Appid, at.AccessToken, at.ExpiresIn, nil) + } + return nil +} + +func (s *SDK) goAutoRefreshStableAccessToken() { + defer func() { + if r := recover(); r != nil { + buf := make([]byte, 64<<10) + buf = buf[:runtime.Stack(buf, false)] + xlog.Errorf("mini_goAutoRefreshAccessToken: panic recovered: %s\n%s", r, buf) + } + }() + for { + // every one hour, request new access token, default 10s + time.Sleep(s.RefreshInternal / 2) + err := s.getStableAccessToken() + if err != nil { + xlog.Errorf("get access token error, after 10s retry: %+v", err) + continue + } + } +} + // SetMiniAccessTokenCallback set mini access token callback listener func (s *SDK) SetMiniAccessTokenCallback(fn func(appid, accessToken string, expireIn int, err error)) { s.callback = fn @@ -71,3 +122,33 @@ func (s *SDK) GetMiniAccessToken() (at string) { func (s *SDK) SetMiniAccessToken(accessToken string) { s.accessToken = accessToken } + +// ===================================================================================================================== + +// 获取接口调用凭据 +// 微信小程序文档: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 + 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 +} + +// 获取稳定版接口调用凭据 +// 微信小程序文档: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) { + uri := HostDefault + "/cgi-bin/stable_token?grant_type=client_credential&appid=" + appid + "&secret=" + secret + "&force_refresh=" + strconv.FormatBool(forceRefresh) + 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 +} diff --git a/mini/customer_service.go b/mini/customer_service.go index fc6bee7..a130ef7 100644 --- a/mini/customer_service.go +++ b/mini/customer_service.go @@ -10,7 +10,7 @@ import ( // CSMessageGetTempMedia 获取客服消息内的临时素材 // mediaId:媒体文件 ID -// 文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/customer-message/customerServiceMessage.getTempMedia.html +// 文档:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/kf-mgnt/kf-message/getTempMedia.html func (s *SDK) CSMessageGetTempMedia(c context.Context, mediaId string) (media []byte, err error) { path := "/cgi-bin/media/get?access_token=" + s.accessToken + "&media_id=" + mediaId media, err = s.doRequestGetByte(c, path) @@ -20,12 +20,12 @@ func (s *SDK) CSMessageGetTempMedia(c context.Context, mediaId string) (media [] return } -// CSMessageSend 发送客服消息给用户 +// CSMessageSend 发送客服消息 // 注意:errcode = 0 为成功 // toUser:小程序用户的 OpenID // msgType:消息类型,枚举值:mini.MsgTypeText、mini.MsgTypeImage、mini.MsgTypeLink、mini.MsgTypeMiniPage // msgValue:对应 msgType 的value值,BodyMap key-value 格式传入 -// 文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/customer-message/customerServiceMessage.send.html +// 文档:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/kf-mgnt/kf-message/sendCustomMessage.html func (s *SDK) CSMessageSend(c context.Context, toUser string, msgType MsgType, msgValue bmap.BodyMap) (err error) { path := "/cgi-bin/message/custom/send?access_token=" + s.accessToken body := make(bmap.BodyMap) @@ -58,7 +58,7 @@ func (s *SDK) CSMessageSend(c context.Context, toUser string, msgType MsgType, m // 注意:errcode = 0 为成功 // toUser:小程序用户的 OpenID // typingStatus:枚举值:mini.TypingTyping、mini.TypingCancel -// 文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/customer-message/customerServiceMessage.setTyping.html +// 文档:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/kf-mgnt/kf-message/setTyping.html func (s *SDK) CSMessageSetTyping(c context.Context, toUser string, typingStatus TypingStatus) (err error) { path := "/cgi-bin/message/custom/typing?access_token=" + s.accessToken body := make(bmap.BodyMap) @@ -79,10 +79,10 @@ func (s *SDK) CSMessageSetTyping(c context.Context, toUser string, typingStatus return nil } -// CSMessageUploadTempMedia 把媒体文件上传到微信服务器 +// CSMessageUploadTempMedia 新增图片素材 // 注意:errcode = 0 为成功 // 注意:目前仅支持图片,用于发送客服消息或被动回复用户消息。 -// 文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/customer-message/customerServiceMessage.uploadTempMedia.html +// 文档:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/kf-mgnt/kf-message/uploadTempMedia.html func (s *SDK) CSMessageUploadTempMedia(c context.Context, img *util.File) (media *UploadTempMedia, err error) { path := "/cgi-bin/media/upload?access_token=" + s.accessToken body := make(bmap.BodyMap) diff --git a/mini/login.go b/mini/login.go index f98ee14..d133e48 100644 --- a/mini/login.go +++ b/mini/login.go @@ -8,7 +8,7 @@ import ( // Code2Session 登录凭证校验 // 注意:errcode = 0 为成功 // wxCode:小程序调用 wx.login 获取的code -// 文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html +// 文档:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/code2Session.html func (s *SDK) Code2Session(c context.Context, wxCode string) (session *Code2Session, err error) { path := "/sns/jscode2session?appid=" + s.Appid + "&secret=" + s.Secret + "&js_code=" + wxCode + "&grant_type=authorization_code" session = &Code2Session{} diff --git a/mini/mini.go b/mini/mini.go index 463c50e..957df31 100644 --- a/mini/mini.go +++ b/mini/mini.go @@ -27,7 +27,7 @@ type SDK struct { // New 初始化微信小程序 SDK // Appid:Appid // Secret:appSecret -// autoManageToken:是否自动获取并自动维护刷新 AccessToken +// autoManageToken:是否自动获取并自动维护刷新 AccessToken,默认使用稳定版接口且force_refresh=false func New(appid, secret string, autoManageToken bool) (m *SDK, err error) { m = &SDK{ ctx: context.Background(), @@ -37,15 +37,15 @@ func New(appid, secret string, autoManageToken bool) (m *SDK, err error) { Host: HostDefault, } if autoManageToken { - if err = m.getAccessToken(); err != nil { + if err = m.getStableAccessToken(); err != nil { return nil, err } - go m.goAutoRefreshAccessToken() + go m.goAutoRefreshStableAccessToken() } return } -func (s *SDK) DoRequestGet(c context.Context, path string, ptr interface{}) (err error) { +func (s *SDK) DoRequestGet(c context.Context, path string, ptr any) (err error) { uri := s.Host + path httpClient := xhttp.NewClient() if s.DebugSwitch == wechat.DebugOn { @@ -54,7 +54,7 @@ func (s *SDK) DoRequestGet(c context.Context, path string, ptr interface{}) (err httpClient.Header.Add(xhttp.HeaderRequestID, fmt.Sprintf("%s-%d", util.RandomString(21), time.Now().Unix())) res, bs, err := httpClient.Get(uri).EndBytes(c) if err != nil { - return fmt.Errorf("http.request(GET, %s):%w", uri, err) + return fmt.Errorf("http.request(GET, %s), status_code:%d, err:%w", uri, res.StatusCode, err) } if s.DebugSwitch == wechat.DebugOn { xlog.Debugf("Wechat_SDK_Response: [%d] -> %s", res.StatusCode, string(bs)) @@ -64,3 +64,16 @@ func (s *SDK) DoRequestGet(c context.Context, path string, ptr interface{}) (err } return } + +func doRequestGet(c context.Context, uri string, ptr any) (err error) { + httpClient := xhttp.NewClient() + httpClient.Header.Add(xhttp.HeaderRequestID, fmt.Sprintf("%s-%d", util.RandomString(21), time.Now().Unix())) + res, bs, err := httpClient.Get(uri).EndBytes(c) + if err != nil { + return fmt.Errorf("http.request(GET, %s), status_code:%d, err:%w", uri, res.StatusCode, err) + } + if err = json.Unmarshal(bs, ptr); err != nil { + return fmt.Errorf("json.Unmarshal(%s, %+v):%w", string(bs), ptr, err) + } + return +} diff --git a/mini/mini_test.go b/mini/mini_test.go index 4ed0bc5..3a09284 100644 --- a/mini/mini_test.go +++ b/mini/mini_test.go @@ -23,7 +23,7 @@ func TestMain(m *testing.M) { // 初始化微信小程序 SDK // Appid:Appid // Secret:appSecret - // autoManageToken:是否自动获取并自动维护刷新 AccessToken + // autoManageToken:是否自动获取并自动维护刷新 AccessToken,默认使用稳定版接口且force_refresh=false miniSDK, err = New(Appid, Secret, true) if err != nil { xlog.Error(err) diff --git a/mini/open_data.go b/mini/open_data.go index 328eecd..e26f8d3 100644 --- a/mini/open_data.go +++ b/mini/open_data.go @@ -33,7 +33,7 @@ func (s *SDK) VerifyDecryptOpenData(rowData, signature, sessionKey string) (ok b // sessionKey:会话密钥,通过 sdk.Code2Session() 方法获取到 // ptr:需要解析到的结构体指针,例:mini.UserPhone、mini.UserInfo // 文档:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html -func (s *SDK) DecryptOpenData(encryptedData, iv, sessionKey string, ptr interface{}) (err error) { +func (s *SDK) DecryptOpenData(encryptedData, iv, sessionKey string, ptr any) (err error) { if encryptedData == util.NULL || iv == util.NULL || sessionKey == util.NULL { return errors.New("input params can not null") } diff --git a/mini/request.go b/mini/request.go index 9f0f7f1..9198e5d 100644 --- a/mini/request.go +++ b/mini/request.go @@ -13,7 +13,7 @@ import ( "github.com/go-pay/wechat-sdk/pkg/xlog" ) -func (s *SDK) doRequestGet(c context.Context, path string, ptr interface{}) (err error) { +func (s *SDK) doRequestGet(c context.Context, path string, ptr any) (err error) { uri := s.Host + path httpClient := xhttp.NewClient() if s.DebugSwitch == wechat.DebugOn { @@ -22,7 +22,7 @@ func (s *SDK) doRequestGet(c context.Context, path string, ptr interface{}) (err httpClient.Header.Add(xhttp.HeaderRequestID, fmt.Sprintf("%s-%d", util.RandomString(21), time.Now().Unix())) res, bs, err := httpClient.Get(uri).EndBytes(c) if err != nil { - return fmt.Errorf("http.request(GET, %s):%w", uri, err) + return fmt.Errorf("http.request(GET, %s), status_code:%d, err:%w", uri, res.StatusCode, err) } if s.DebugSwitch == wechat.DebugOn { xlog.Debugf("Wechat_Mini_SDK_Response: [%d] -> %s", res.StatusCode, string(bs)) @@ -42,7 +42,7 @@ func (s *SDK) doRequestGetByte(c context.Context, path string) (bs []byte, err e httpClient.Header.Add(xhttp.HeaderRequestID, fmt.Sprintf("%s-%d", util.RandomString(21), time.Now().Unix())) res, bs, err := httpClient.Get(uri).EndBytes(c) if err != nil { - return nil, fmt.Errorf("http.request(GET, %s):%w", uri, err) + return nil, fmt.Errorf("http.request(GET, %s), status_code:%d, err:%w", uri, res.StatusCode, err) } if s.DebugSwitch == wechat.DebugOn { xlog.Debugf("Wechat_Mini_SDK_Response: [%d] -> %s", res.StatusCode, string(bs)) @@ -55,7 +55,7 @@ func (s *SDK) doRequestGetByte(c context.Context, path string) (bs []byte, err e return } -func (s *SDK) doRequestPost(c context.Context, path string, body bmap.BodyMap, ptr interface{}) (err error) { +func (s *SDK) doRequestPost(c context.Context, path string, body bmap.BodyMap, ptr any) (err error) { uri := s.Host + path httpClient := xhttp.NewClient() if s.DebugSwitch == wechat.DebugOn { @@ -65,7 +65,7 @@ func (s *SDK) doRequestPost(c context.Context, path string, body bmap.BodyMap, p httpClient.Header.Add(xhttp.HeaderRequestID, fmt.Sprintf("%s-%d", util.RandomString(21), time.Now().Unix())) res, bs, err := httpClient.Post(uri).SendBodyMap(body).EndBytes(c) if err != nil { - return fmt.Errorf("http.request(POST, %s):%w", uri, err) + return fmt.Errorf("http.request(POST, %s), status_code:%d, err:%w", uri, res.StatusCode, err) } if s.DebugSwitch == wechat.DebugOn { xlog.Debugf("Wechat_Mini_SDK_Response: [%d] -> %s", res.StatusCode, string(bs)) @@ -76,7 +76,7 @@ func (s *SDK) doRequestPost(c context.Context, path string, body bmap.BodyMap, p return } -func (s *SDK) doRequestPostFile(ctx context.Context, path string, body bmap.BodyMap, ptr interface{}) (err error) { +func (s *SDK) doRequestPostFile(ctx context.Context, path string, body bmap.BodyMap, ptr any) (err error) { uri := s.Host + path httpClient := xhttp.NewClient() if s.DebugSwitch == wechat.DebugOn { @@ -85,7 +85,7 @@ func (s *SDK) doRequestPostFile(ctx context.Context, path string, body bmap.Body httpClient.Header.Add(xhttp.HeaderRequestID, fmt.Sprintf("%s-%d", util.RandomString(21), time.Now().Unix())) res, bs, err := httpClient.Type(xhttp.TypeMultipartFormData).Post(uri).SendMultipartBodyMap(body).EndBytes(ctx) if err != nil { - return fmt.Errorf("http.request(POST, %s):%w", uri, err) + return fmt.Errorf("http.request(POST, %s), status_code:%d, err:%w", uri, res.StatusCode, err) } if s.DebugSwitch == wechat.DebugOn { xlog.Debugf("Wechat_Mini_SDK_Response: [%d] -> %s", res.StatusCode, string(bs)) diff --git a/open/open.go b/open/open.go index 302680f..ade52ae 100644 --- a/open/open.go +++ b/open/open.go @@ -48,7 +48,7 @@ func New(appid, secret string, autoManageToken bool) (o *SDK) { return } -func (s *SDK) DoRequestGet(c context.Context, path string, ptr interface{}) (err error) { +func (s *SDK) DoRequestGet(c context.Context, path string, ptr any) (err error) { uri := s.Host + path httpClient := xhttp.NewClient() if s.DebugSwitch == wechat.DebugOn { @@ -57,7 +57,7 @@ func (s *SDK) DoRequestGet(c context.Context, path string, ptr interface{}) (err httpClient.Header.Add(xhttp.HeaderRequestID, fmt.Sprintf("%s-%d", util.RandomString(21), time.Now().Unix())) res, bs, err := httpClient.Get(uri).EndBytes(c) if err != nil { - return fmt.Errorf("http.request(GET, %s):%w", uri, err) + return fmt.Errorf("http.request(GET, %s), status_code:%d, err:%w", uri, res.StatusCode, err) } if s.DebugSwitch == wechat.DebugOn { xlog.Debugf("Wechat_Open_SDK_Response: [%d] -> %s", res.StatusCode, string(bs)) diff --git a/pkg/bmap/body_map.go b/pkg/bmap/body_map.go index 340b5a5..1ed49f7 100644 --- a/pkg/bmap/body_map.go +++ b/pkg/bmap/body_map.go @@ -12,11 +12,11 @@ import ( "github.com/go-pay/wechat-sdk/pkg/util" ) -type BodyMap map[string]interface{} +type BodyMap map[string]any type xmlMapMarshal struct { XMLName xml.Name - Value interface{} `xml:",cdata"` + Value any `xml:",cdata"` } type xmlMapUnmarshal struct { @@ -25,7 +25,7 @@ type xmlMapUnmarshal struct { } // 设置参数 -func (bm BodyMap) Set(key string, value interface{}) BodyMap { +func (bm BodyMap) Set(key string, value any) BodyMap { bm[key] = value return bm } @@ -65,7 +65,7 @@ func (bm BodyMap) GetString(key string) string { } // 获取原始参数 -func (bm BodyMap) GetInterface(key string) interface{} { +func (bm BodyMap) GetInterface(key string) any { if bm == nil { return nil } @@ -94,7 +94,7 @@ func (bm BodyMap) JsonBody() (jb string) { } // Unmarshal to struct or slice point -func (bm BodyMap) Unmarshal(ptr interface{}) (err error) { +func (bm BodyMap) Unmarshal(ptr any) (err error) { bs, err := json.Marshal(bm) if err != nil { return err @@ -226,7 +226,7 @@ func (bm BodyMap) CheckEmptyError(keys ...string) error { return nil } -func convertToString(v interface{}) (str string) { +func convertToString(v any) (str string) { if v == nil { return "" } diff --git a/pkg/util/string.go b/pkg/util/string.go index b33dee3..3fb764d 100644 --- a/pkg/util/string.go +++ b/pkg/util/string.go @@ -2,7 +2,7 @@ package util import "encoding/json" -func ConvertToString(v interface{}) (str string) { +func ConvertToString(v any) (str string) { if v == nil { return NULL } diff --git a/pkg/xhttp/client.go b/pkg/xhttp/client.go index ad584f4..60d4113 100644 --- a/pkg/xhttp/client.go +++ b/pkg/xhttp/client.go @@ -32,7 +32,7 @@ type Client struct { FormString string ContentType string unmarshalType string - multipartBodyMap map[string]interface{} + multipartBodyMap map[string]any jsonByte []byte err error } @@ -113,7 +113,7 @@ func (c *Client) Patch(url string) (client *Client) { return c } -func (c *Client) SendStruct(v interface{}) (client *Client) { +func (c *Client) SendStruct(v any) (client *Client) { if v == nil { return c } @@ -126,7 +126,7 @@ func (c *Client) SendStruct(v interface{}) (client *Client) { case TypeJSON: c.jsonByte = bs case TypeXML, TypeUrlencoded, TypeForm, TypeFormData: - body := make(map[string]interface{}) + body := make(map[string]any) if err = json.Unmarshal(bs, &body); err != nil { c.err = fmt.Errorf("json.Unmarshal(%s, %+v):%w", string(bs), body, err) return c @@ -136,7 +136,7 @@ func (c *Client) SendStruct(v interface{}) (client *Client) { return c } -func (c *Client) SendBodyMap(bm map[string]interface{}) (client *Client) { +func (c *Client) SendBodyMap(bm map[string]any) (client *Client) { if bm == nil { return c } @@ -154,7 +154,7 @@ func (c *Client) SendBodyMap(bm map[string]interface{}) (client *Client) { return c } -func (c *Client) SendMultipartBodyMap(bm map[string]interface{}) (client *Client) { +func (c *Client) SendMultipartBodyMap(bm map[string]any) (client *Client) { if bm == nil { return c } @@ -185,7 +185,7 @@ func (c *Client) SendString(encodeStr string) (client *Client) { return c } -func (c *Client) EndStruct(ctx context.Context, v interface{}) (res *http.Response, err error) { +func (c *Client) EndStruct(ctx context.Context, v any) (res *http.Response, err error) { res, bs, err := c.EndBytes(ctx) if err != nil { return nil, err @@ -317,7 +317,7 @@ func (c *Client) EndBytes(ctx context.Context) (res *http.Response, bs []byte, e return res, bs, nil } -func FormatURLParam(body map[string]interface{}) (urlParam string) { +func FormatURLParam(body map[string]any) (urlParam string) { var ( buf strings.Builder keys []string @@ -344,7 +344,7 @@ func FormatURLParam(body map[string]interface{}) (urlParam string) { return buf.String()[:buf.Len()-1] } -func convertToString(v interface{}) (str string) { +func convertToString(v any) (str string) { if v == nil { return "" } diff --git a/pkg/xhttp/client_test.go b/pkg/xhttp/client_test.go index 32fc7d0..f12d8a9 100644 --- a/pkg/xhttp/client_test.go +++ b/pkg/xhttp/client_test.go @@ -12,9 +12,9 @@ import ( ) type HttpGet struct { - Code int `json:"code"` - Message string `json:"message"` - Data interface{} `json:"data,omitempty"` + Code int `json:"code"` + Message string `json:"message"` + Data any `json:"data,omitempty"` } var ctx = context.Background() diff --git a/pkg/xlog/color.go b/pkg/xlog/color.go index 8c1c9c1..facdf67 100644 --- a/pkg/xlog/color.go +++ b/pkg/xlog/color.go @@ -79,34 +79,34 @@ func Color(color ColorType) *ColorLogger { return cl } -func (l *ColorLogger) Info(args ...interface{}) { +func (l *ColorLogger) Info(args ...any) { l.i.LogOut(&l.Color, nil, args...) } -func (l *ColorLogger) Infof(format string, args ...interface{}) { +func (l *ColorLogger) Infof(format string, args ...any) { l.i.LogOut(&l.Color, &format, args...) } -func (l *ColorLogger) Debug(args ...interface{}) { +func (l *ColorLogger) Debug(args ...any) { l.d.LogOut(&l.Color, nil, args...) } -func (l *ColorLogger) Debugf(format string, args ...interface{}) { +func (l *ColorLogger) Debugf(format string, args ...any) { l.d.LogOut(&l.Color, &format, args...) } -func (l *ColorLogger) Warn(args ...interface{}) { +func (l *ColorLogger) Warn(args ...any) { l.w.LogOut(&l.Color, nil, args...) } -func (l *ColorLogger) Warnf(format string, args ...interface{}) { +func (l *ColorLogger) Warnf(format string, args ...any) { l.w.LogOut(&l.Color, &format, args...) } -func (l *ColorLogger) Error(args ...interface{}) { +func (l *ColorLogger) Error(args ...any) { l.e.LogOut(&l.Color, nil, args...) } -func (l *ColorLogger) Errorf(format string, args ...interface{}) { +func (l *ColorLogger) Errorf(format string, args ...any) { l.e.LogOut(&l.Color, &format, args...) } diff --git a/pkg/xlog/debug_logger.go b/pkg/xlog/debug_logger.go index 27c7c00..8f26fd3 100644 --- a/pkg/xlog/debug_logger.go +++ b/pkg/xlog/debug_logger.go @@ -12,7 +12,7 @@ type DebugLogger struct { once sync.Once } -func (d *DebugLogger) LogOut(col *ColorType, format *string, v ...interface{}) { +func (d *DebugLogger) LogOut(col *ColorType, format *string, v ...any) { d.once.Do(func() { d.init() }) diff --git a/pkg/xlog/error_logger.go b/pkg/xlog/error_logger.go index 32eba31..bd65a6a 100644 --- a/pkg/xlog/error_logger.go +++ b/pkg/xlog/error_logger.go @@ -12,7 +12,7 @@ type ErrorLogger struct { once sync.Once } -func (e *ErrorLogger) LogOut(col *ColorType, format *string, v ...interface{}) { +func (e *ErrorLogger) LogOut(col *ColorType, format *string, v ...any) { e.once.Do(func() { e.init() }) diff --git a/pkg/xlog/info_logger.go b/pkg/xlog/info_logger.go index f1552c2..bfe347c 100644 --- a/pkg/xlog/info_logger.go +++ b/pkg/xlog/info_logger.go @@ -12,7 +12,7 @@ type InfoLogger struct { once sync.Once } -func (i *InfoLogger) LogOut(col *ColorType, format *string, v ...interface{}) { +func (i *InfoLogger) LogOut(col *ColorType, format *string, v ...any) { i.once.Do(func() { i.init() }) diff --git a/pkg/xlog/log.go b/pkg/xlog/log.go index 2486744..223dc8f 100644 --- a/pkg/xlog/log.go +++ b/pkg/xlog/log.go @@ -19,38 +19,38 @@ var ( ) type XLogger interface { - LogOut(col *ColorType, format *string, args ...interface{}) + LogOut(col *ColorType, format *string, args ...any) } -func Info(args ...interface{}) { +func Info(args ...any) { infoLog.LogOut(nil, nil, args...) } -func Infof(format string, args ...interface{}) { +func Infof(format string, args ...any) { infoLog.LogOut(nil, &format, args...) } -func Debug(args ...interface{}) { +func Debug(args ...any) { debugLog.LogOut(nil, nil, args...) } -func Debugf(format string, args ...interface{}) { +func Debugf(format string, args ...any) { debugLog.LogOut(nil, &format, args...) } -func Warn(args ...interface{}) { +func Warn(args ...any) { warnLog.LogOut(nil, nil, args...) } -func Warnf(format string, args ...interface{}) { +func Warnf(format string, args ...any) { warnLog.LogOut(nil, &format, args...) } -func Error(args ...interface{}) { +func Error(args ...any) { errLog.LogOut(nil, nil, args...) } -func Errorf(format string, args ...interface{}) { +func Errorf(format string, args ...any) { errLog.LogOut(nil, &format, args...) } diff --git a/pkg/xlog/warn_logger.go b/pkg/xlog/warn_logger.go index 362b3e2..4b06565 100644 --- a/pkg/xlog/warn_logger.go +++ b/pkg/xlog/warn_logger.go @@ -12,7 +12,7 @@ type WarnLogger struct { once sync.Once } -func (w *WarnLogger) LogOut(col *ColorType, format *string, v ...interface{}) { +func (w *WarnLogger) LogOut(col *ColorType, format *string, v ...any) { w.once.Do(func() { w.init() }) diff --git a/pkg/xtime/xtime.go b/pkg/xtime/xtime.go index ff5b9f9..f23c5dc 100644 --- a/pkg/xtime/xtime.go +++ b/pkg/xtime/xtime.go @@ -11,7 +11,7 @@ import ( type Time int64 // Scan scan time. -func (t *Time) Scan(src interface{}) (err error) { +func (t *Time) Scan(src any) (err error) { switch sc := src.(type) { case time.Time: *t = Time(sc.Unix()) diff --git a/public/public.go b/public/public.go index 831daf4..95ca0ec 100644 --- a/public/public.go +++ b/public/public.go @@ -45,7 +45,7 @@ func New(appid, secret string, autoManageToken bool) (p *SDK, err error) { return } -func (s *SDK) DoRequestGet(c context.Context, path string, ptr interface{}) (err error) { +func (s *SDK) DoRequestGet(c context.Context, path string, ptr any) (err error) { uri := s.Host + path httpClient := xhttp.NewClient() if s.DebugSwitch == wechat.DebugOn { @@ -54,7 +54,7 @@ func (s *SDK) DoRequestGet(c context.Context, path string, ptr interface{}) (err httpClient.Header.Add(xhttp.HeaderRequestID, fmt.Sprintf("%s-%d", util.RandomString(21), time.Now().Unix())) res, bs, err := httpClient.Get(uri).EndBytes(c) if err != nil { - return fmt.Errorf("http.request(GET, %s):%w", uri, err) + return fmt.Errorf("http.request(GET, %s), status_code:%d, err:%w", uri, res.StatusCode, err) } if s.DebugSwitch == wechat.DebugOn { xlog.Debugf("Wechat_SDK_Response: [%d] -> %s", res.StatusCode, string(bs)) diff --git a/public/request.go b/public/request.go index e02a6ba..4907f3a 100644 --- a/public/request.go +++ b/public/request.go @@ -13,7 +13,7 @@ import ( "github.com/go-pay/wechat-sdk/pkg/xlog" ) -func (s *SDK) doRequestGet(c context.Context, path string, ptr interface{}) (err error) { +func (s *SDK) doRequestGet(c context.Context, path string, ptr any) (err error) { uri := s.Host + path httpClient := xhttp.NewClient() if s.DebugSwitch == wechat.DebugOn { @@ -22,7 +22,7 @@ func (s *SDK) doRequestGet(c context.Context, path string, ptr interface{}) (err httpClient.Header.Add(xhttp.HeaderRequestID, fmt.Sprintf("%s-%d", util.RandomString(21), time.Now().Unix())) res, bs, err := httpClient.Get(uri).EndBytes(c) if err != nil { - return fmt.Errorf("http.request(GET, %s):%w", uri, err) + return fmt.Errorf("http.request(GET, %s), status_code:%d, err:%w", uri, res.StatusCode, err) } if s.DebugSwitch == wechat.DebugOn { xlog.Debugf("Wechat_Public_SDK_Response: [%d] -> %s", res.StatusCode, string(bs)) @@ -42,7 +42,7 @@ func (s *SDK) doRequestGet(c context.Context, path string, ptr interface{}) (err // httpClient.Header.Add(xhttp.HeaderRequestID, fmt.Sprintf("%s-%d", util.RandomString(21), time.Now().Unix())) // res, bs, err := httpClient.Get(uri).EndBytes(c) // if err != nil { -// return nil, fmt.Errorf("http.request(GET, %s):%w", uri, err) +// return nil, fmt.Errorf("http.request(GET, %s), status_code:%d, err:%w", uri, res.StatusCode, err) // } // if s.DebugSwitch == wechat.DebugOn { // xlog.Debugf("Wechat_Public_SDK_Response: [%d] -> %s", res.StatusCode, string(bs)) @@ -55,7 +55,7 @@ func (s *SDK) doRequestGet(c context.Context, path string, ptr interface{}) (err // return //} -func (s *SDK) doRequestPost(c context.Context, path string, body bmap.BodyMap, ptr interface{}) (err error) { +func (s *SDK) doRequestPost(c context.Context, path string, body bmap.BodyMap, ptr any) (err error) { uri := s.Host + path httpClient := xhttp.NewClient() if s.DebugSwitch == wechat.DebugOn { @@ -65,7 +65,7 @@ func (s *SDK) doRequestPost(c context.Context, path string, body bmap.BodyMap, p httpClient.Header.Add(xhttp.HeaderRequestID, fmt.Sprintf("%s-%d", util.RandomString(21), time.Now().Unix())) res, bs, err := httpClient.Post(uri).SendBodyMap(body).EndBytes(c) if err != nil { - return fmt.Errorf("http.request(POST, %s):%w", uri, err) + return fmt.Errorf("http.request(POST, %s), status_code:%d, err:%w", uri, res.StatusCode, err) } if s.DebugSwitch == wechat.DebugOn { xlog.Debugf("Wechat_Public_SDK_Response: [%d] -> %s", res.StatusCode, string(bs)) @@ -76,7 +76,7 @@ func (s *SDK) doRequestPost(c context.Context, path string, body bmap.BodyMap, p return } -//func (s *SDK) doRequestPostFile(ctx context.Context, path string, body bmap.BodyMap, ptr interface{}) (err error) { +//func (s *SDK) doRequestPostFile(ctx context.Context, path string, body bmap.BodyMap, ptr any) (err error) { // uri := s.Host + path // httpClient := xhttp.NewClient() // if s.DebugSwitch == wechat.DebugOn { @@ -85,7 +85,7 @@ func (s *SDK) doRequestPost(c context.Context, path string, body bmap.BodyMap, p // httpClient.Header.Add(xhttp.HeaderRequestID, fmt.Sprintf("%s-%d", util.RandomString(21), time.Now().Unix())) // res, bs, err := httpClient.Type(xhttp.TypeMultipartFormData).Post(uri).SendMultipartBodyMap(body).EndBytes(ctx) // if err != nil { -// return fmt.Errorf("http.request(POST, %s):%w", uri, err) +// return fmt.Errorf("http.request(POST, %s), status_code:%d, err:%w", uri, res.StatusCode, err) // } // if s.DebugSwitch == wechat.DebugOn { // xlog.Debugf("Wechat_Public_SDK_Response: [%d] -> %s", res.StatusCode, string(bs)) diff --git a/release_note.txt b/release_note.txt index 45e5168..dc82cab 100644 --- a/release_note.txt +++ b/release_note.txt @@ -1,6 +1,8 @@ 版本号:Release 1.1.5 修改记录: (1) 微信公众号:新增 ticket获取,js-sdk使用校验签名接口 + (2) 微信小程序:自动维护token改为获取稳定版接口调用凭据,并且 forceRefresh=false + (3) 微信小程序:新增公共API 获取接口调用凭据、获取稳定版接口调用凭据 版本号:Release 1.1.4 修改记录: