Skip to content

Commit

Permalink
lint fix
Browse files Browse the repository at this point in the history
  • Loading branch information
iGoogle-ink committed Nov 16, 2023
1 parent 7c387e4 commit 1b8858f
Show file tree
Hide file tree
Showing 23 changed files with 177 additions and 76 deletions.
11 changes: 8 additions & 3 deletions doc/mini.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -126,8 +126,13 @@ if err != nil {
* 开放数据解密:`sdk.DecryptOpenData()`
* <font color='#07C160' size='4'>客服消息</font>
* 获取客服消息内的临时素材:`sdk.CSMessageGetTempMedia()`
* 发送客服消息给用户:`sdk.CSMessageSend()`
* 发送客服消息:`sdk.CSMessageSend()`
* 下发客服当前输入状态给用户:`sdk.CSMessageSetTyping()`
* 把媒体文件上传到微信服务器(目前仅支持图片):`sdk.CSMessageUploadTempMedia()`
* 新增图片素材:`sdk.CSMessageUploadTempMedia()`
* <font color='#07C160' size='4'>统一服务消息</font>
* 发送统一服务消息:`sdk.UniformMessageSend()` 未完成

### 微信小程序 公共API

* `mini.GetAccessToken()` => 获取接口调用凭据
* `mini.GetStableAccessToken()` => 获取稳定版接口调用凭据
83 changes: 82 additions & 1 deletion mini/access_token.go
Original file line number Diff line number Diff line change
@@ -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) {

Check failure on line 15 in mini/access_token.go

View workflow job for this annotation

GitHub Actions / lint

func `(*SDK).getAccessToken` is unused (unused)
defer func() {
if err != nil {
Expand Down Expand Up @@ -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
Expand All @@ -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
}
12 changes: 6 additions & 6 deletions mini/customer_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion mini/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{}
Expand Down
23 changes: 18 additions & 5 deletions mini/mini.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand All @@ -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 {
Expand All @@ -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))
Expand All @@ -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
}
2 changes: 1 addition & 1 deletion mini/mini_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion mini/open_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down
14 changes: 7 additions & 7 deletions mini/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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))
Expand All @@ -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))
Expand All @@ -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 {
Expand All @@ -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))
Expand All @@ -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 {
Expand All @@ -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))
Expand Down
4 changes: 2 additions & 2 deletions open/open.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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))
Expand Down
12 changes: 6 additions & 6 deletions pkg/bmap/body_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
}
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 ""
}
Expand Down
Loading

0 comments on commit 1b8858f

Please sign in to comment.