feat: init

This commit is contained in:
Rogee
2024-11-27 11:55:09 +08:00
parent e0eb7e5e2e
commit e4b9cc5f26
13 changed files with 462 additions and 2 deletions

33
pkg/wechat/errors.go Normal file
View File

@@ -0,0 +1,33 @@
package wechat
import "github.com/pkg/errors"
// -1 系统繁忙,此时请开发者稍候再试
// 0 请求成功
// 40001 AppSecret错误或者AppSecret不属于这个公众号请开发者确认AppSecret的正确性
// 40002 请确保grant_type字段值为client_credential
// 40164 调用接口的IP地址不在白名单中请在接口IP白名单中进行设置。
// 40243 AppSecret已被冻结请登录MP解冻后再次调用。
// 89503 此IP调用需要管理员确认,请联系管理员
// 89501 此IP正在等待管理员确认,请联系管理员
// 89506 24小时内该IP被管理员拒绝调用两次24小时内不可再使用该IP调用
// 89507 1小时内该IP被管理员拒绝调用一次1小时内不可再使用该IP调用
func translateError(errCode int) error {
errors := map[int]error{
0: nil,
-1: errors.New("系统繁忙,此时请开发者稍候再试"),
40001: errors.New("AppSecret错误或者AppSecret不属于这个公众号请开发者确认AppSecret的正确性"),
40002: errors.New("请确保grant_type字段值为client_credential"),
40164: errors.New("调用接口的IP地址不在白名单中请在接口IP白名单中进行设置"),
40243: errors.New("AppSecret已被冻结请登录MP解冻后再次调用"),
89503: errors.New("此IP调用需要管理员确认,请联系管理员"),
89501: errors.New("此IP正在等待管理员确认,请联系管理员"),
89506: errors.New("24小时内该IP被管理员拒绝调用两次24小时内不可再使用该IP调用"),
89507: errors.New("1小时内该IP被管理员拒绝调用一次1小时内不可再使用该IP调用"),
}
if err, ok := errors[errCode]; ok {
return err
}
return nil
}

39
pkg/wechat/options.go Normal file
View File

@@ -0,0 +1,39 @@
package wechat
import "github.com/imroc/req/v3"
type Options func(*Client)
func WithAppID(appID string) Options {
return func(we *Client) {
we.appID = appID
}
}
// WithAppSecret sets the app secret
func WithAppSecret(appSecret string) Options {
return func(we *Client) {
we.appSecret = appSecret
}
}
// WithToken sets the token
func WithToken(token string) Options {
return func(we *Client) {
we.token = token
}
}
// WithAESKey sets the AES key
func WithAESKey(aesKey string) Options {
return func(we *Client) {
we.aesKey = aesKey
}
}
// WithClient sets the http client
func WithClient(client *req.Client) Options {
return func(we *Client) {
we.client = client
}
}

16
pkg/wechat/response.go Normal file
View File

@@ -0,0 +1,16 @@
package wechat
type Response struct {
ErrCode int `json:"errcode"`
ErrMsg int `json:"errmsg"`
ErrDescribe int `json:"-"`
}
func (r *Response) Error() error {
return translateError(r.ErrCode)
}
type AccessTokenResponse struct {
AccessToken string `json:"access_token"`
ExpiresIn int `json:"expires_in"`
}

69
pkg/wechat/wechat.go Normal file
View File

@@ -0,0 +1,69 @@
package wechat
import (
"crypto/sha1"
"encoding/hex"
"sort"
"strings"
"github.com/imroc/req/v3"
"github.com/pkg/errors"
)
const BaseURL = "https://api.weixin.qq.com/"
var DefaultClient = req.
NewClient().
SetBaseURL(BaseURL).
SetCommonHeader("Content-Type", "application/json")
type Client struct {
client *req.Client
appID string
appSecret string
token string
aesKey string
}
func New(options ...Options) *Client {
we := &Client{
client: DefaultClient,
}
for _, opt := range options {
opt(we)
}
return we
}
func (we *Client) VerifyServer(signature, timestamp, nonce string) error {
params := []string{signature, timestamp, nonce, we.token}
sort.Strings(params)
str := strings.Join(params, "")
hash := sha1.Sum([]byte(str))
hashStr := hex.EncodeToString(hash[:])
if hashStr == signature {
return errors.New("Signature verification failed")
}
return nil
}
func (we *Client) GetAccessToken() (*AccessTokenResponse, error) {
params := map[string]string{
"grant_type": "client_credential",
"appid": we.appID,
"secret": we.appSecret,
}
var data AccessTokenResponse
_, err := we.client.R().SetSuccessResult(&data).SetQueryParams(params).Get("/cgi-bin/token")
if err != nil {
return nil, errors.Wrap(err, "call /cgi-bin/token failed")
}
return &data, nil
}

34
pkg/wechat/wechat_test.go Normal file
View File

@@ -0,0 +1,34 @@
package wechat
import (
"testing"
log "github.com/sirupsen/logrus"
. "github.com/smartystreets/goconvey/convey"
)
const (
WechatAppID = "wxf5bf0adeb99c2afd"
WechatAppSecret = "3cf8fad4aa414f2b861399f111b22bb5"
WechatToken = "W8Xhw5TivYBgY"
WechatAesKey = "F6AqCxAV4W1eCrY6llJ2zapphKK49CQN3RgtPDrjhnI"
)
func TestWechatClient_GetAccessToken(t *testing.T) {
Convey("Test GetAccessToken", t, func() {
log.SetLevel(log.DebugLevel)
wechatClient := New(
WithAppID(WechatAppID),
WithAppSecret(WechatAppSecret),
WithAESKey(WechatAesKey),
WithToken(WechatToken),
WithClient(DefaultClient.DevMode()),
)
token, err := wechatClient.GetAccessToken()
So(err, ShouldBeNil)
So(token.AccessToken, ShouldNotBeEmpty)
So(token.ExpiresIn, ShouldBeGreaterThan, 0)
})
}