1
0
mirror of https://github.com/silenceper/wechat.git synced 2026-02-07 14:12:27 +08:00

Merge branch 'release-2.0' of github.com:hb1707/wechat into release-2.0

# Conflicts:
#	work/externalcontact/client.go
#	work/oauth/oauth.go
#	work/work.go
This commit is contained in:
wind
2023-01-09 17:15:41 +08:00
163 changed files with 6586 additions and 1205 deletions

View File

@@ -40,7 +40,7 @@ func EncryptMsg(random, rawXMLMsg []byte, appID, aesKey string) (encrtptMsg []by
}
// AESEncryptMsg ciphertext = AES_Encrypt[random(16B) + msg_len(4B) + rawXMLMsg + appId]
//参考github.com/chanxuehong/wechat.v2
// 参考github.com/chanxuehong/wechat.v2
func AESEncryptMsg(random, rawXMLMsg []byte, appID string, aesKey []byte) (ciphertext []byte) {
const (
BlockSize = 32 // PKCS#7
@@ -123,7 +123,7 @@ func aesKeyDecode(encodedAESKey string) (key []byte, err error) {
}
// AESDecryptMsg ciphertext = AES_Encrypt[random(16B) + msg_len(4B) + rawXMLMsg + appId]
//参考github.com/chanxuehong/wechat.v2
// 参考github.com/chanxuehong/wechat.v2
func AESDecryptMsg(ciphertext []byte, aesKey []byte) (random, rawXMLMsg, appID []byte, err error) {
const (
BlockSize = 32 // PKCS#7

View File

@@ -8,10 +8,24 @@ import (
// CommonError 微信返回的通用错误json
type CommonError struct {
apiName string
ErrCode int64 `json:"errcode"`
ErrMsg string `json:"errmsg"`
}
func (c *CommonError) Error() string {
return fmt.Sprintf("%s Error , errcode=%d , errmsg=%s", c.apiName, c.ErrCode, c.ErrMsg)
}
// NewCommonError 新建CommonError错误对于无errcode和errmsg的返回也可以返回该通用错误
func NewCommonError(apiName string, code int64, msg string) *CommonError {
return &CommonError{
apiName: apiName,
ErrCode: code,
ErrMsg: msg,
}
}
// DecodeWithCommonError 将返回值按照CommonError解析
func DecodeWithCommonError(response []byte, apiName string) (err error) {
var commError CommonError
@@ -19,8 +33,9 @@ func DecodeWithCommonError(response []byte, apiName string) (err error) {
if err != nil {
return
}
commError.apiName = apiName
if commError.ErrCode != 0 {
return fmt.Errorf("%s Error , errcode=%d , errmsg=%s", apiName, commError.ErrCode, commError.ErrMsg)
return &commError
}
return nil
}
@@ -45,7 +60,11 @@ func DecodeWithError(response []byte, obj interface{}, apiName string) error {
return fmt.Errorf("errcode or errmsg is invalid")
}
if errCode.Int() != 0 {
return fmt.Errorf("%s Error , errcode=%d , errmsg=%s", apiName, errCode.Int(), errMsg.String())
return &CommonError{
apiName: apiName,
ErrCode: errCode.Int(),
ErrMsg: errMsg.String(),
}
}
return nil
}

55
util/error_test.go Normal file
View File

@@ -0,0 +1,55 @@
package util
import "testing"
var okErrData string = `{"errcode": 0}`
var errData string = `{"errcode": 43101, "errmsg": "user refuse to accept the msg"}`
var expectError string = "Send Error , errcode=43101 , errmsg=user refuse to accept the msg"
func TestDecodeWithCommonErrorNoError(t *testing.T) {
err := DecodeWithCommonError([]byte(okErrData), "Send")
if err != nil {
t.Error("DecodeWithCommonError should not return error")
return
}
}
func TestDecodeWithCommonError(t *testing.T) {
err := DecodeWithCommonError([]byte(errData), "Send")
if err == nil {
t.Error("DecodeWithCommonError should return error")
return
}
cErr, ok := err.(*CommonError)
if !ok {
t.Errorf("DecodeWithCommonError should return *CommonError but %T", err)
return
}
if !(cErr.ErrCode == 43101 && cErr.ErrMsg == "user refuse to accept the msg" && cErr.Error() == expectError) {
t.Error("DecodeWithCommonError return bad *CommonError")
return
}
}
func TestDecodeWithError(t *testing.T) {
type DE struct {
CommonError
}
var obj DE
err := DecodeWithError([]byte(errData), &obj, "Send")
if err == nil {
t.Error("DecodeWithError should return error")
return
}
cErr, ok := err.(*CommonError)
if !ok {
t.Errorf("DecodeWithError should return *CommonError but %T", err)
return
}
if !(cErr.ErrCode == 43101 && cErr.ErrMsg == "user refuse to accept the msg" && cErr.Error() == expectError) {
t.Error("DecodeWithError return bad *CommonError")
return
}
}

View File

@@ -2,13 +2,13 @@ package util
import (
"bytes"
"context"
"crypto/tls"
"encoding/json"
"encoding/pem"
"encoding/xml"
"fmt"
"io"
"io/ioutil"
"log"
"mime/multipart"
"net/http"
@@ -17,9 +17,18 @@ import (
"golang.org/x/crypto/pkcs12"
)
//HTTPGet get 请求
// HTTPGet get 请求
func HTTPGet(uri string) ([]byte, error) {
response, err := http.Get(uri)
return HTTPGetContext(context.Background(), uri)
}
// HTTPGetContext get 请求
func HTTPGetContext(ctx context.Context, uri string) ([]byte, error) {
request, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, err
}
response, err := http.DefaultClient.Do(request)
if err != nil {
return nil, err
}
@@ -28,25 +37,39 @@ func HTTPGet(uri string) ([]byte, error) {
if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("http get error : uri=%v , statusCode=%v", uri, response.StatusCode)
}
return ioutil.ReadAll(response.Body)
return io.ReadAll(response.Body)
}
//HTTPPost post 请求
// HTTPPost post 请求
func HTTPPost(uri string, data string) ([]byte, error) {
body := bytes.NewBuffer([]byte(data))
response, err := http.Post(uri, "", body)
return HTTPPostContext(context.Background(), uri, []byte(data), nil)
}
// HTTPPostContext post 请求
func HTTPPostContext(ctx context.Context, uri string, data []byte, header map[string]string) ([]byte, error) {
body := bytes.NewBuffer(data)
request, err := http.NewRequestWithContext(ctx, http.MethodPost, uri, body)
if err != nil {
return nil, err
}
for key, value := range header {
request.Header.Set(key, value)
}
response, err := http.DefaultClient.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("http get error : uri=%v , statusCode=%v", uri, response.StatusCode)
return nil, fmt.Errorf("http post error : uri=%v , statusCode=%v", uri, response.StatusCode)
}
return ioutil.ReadAll(response.Body)
return io.ReadAll(response.Body)
}
//PostJSON post json 数据请求
// PostJSON post json 数据请求
func PostJSON(uri string, obj interface{}) ([]byte, error) {
jsonBuf := new(bytes.Buffer)
enc := json.NewEncoder(jsonBuf)
@@ -64,7 +87,7 @@ func PostJSON(uri string, obj interface{}) ([]byte, error) {
if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("http get error : uri=%v , statusCode=%v", uri, response.StatusCode)
}
return ioutil.ReadAll(response.Body)
return io.ReadAll(response.Body)
}
// PostJSONWithRespContentType post json数据请求且返回数据类型
@@ -86,24 +109,24 @@ func PostJSONWithRespContentType(uri string, obj interface{}) ([]byte, string, e
if response.StatusCode != http.StatusOK {
return nil, "", fmt.Errorf("http get error : uri=%v , statusCode=%v", uri, response.StatusCode)
}
responseData, err := ioutil.ReadAll(response.Body)
responseData, err := io.ReadAll(response.Body)
contentType := response.Header.Get("Content-Type")
return responseData, contentType, err
}
//PostFile 上传文件
func PostFile(fieldname, filename, uri string) ([]byte, error) {
// PostFile 上传文件
func PostFile(fieldName, filename, uri string) ([]byte, error) {
fields := []MultipartFormField{
{
IsFile: true,
Fieldname: fieldname,
Fieldname: fieldName,
Filename: filename,
},
}
return PostMultipartForm(fields, uri)
}
//MultipartFormField 保存文件或其他字段信息
// MultipartFormField 保存文件或其他字段信息
type MultipartFormField struct {
IsFile bool
Fieldname string
@@ -111,7 +134,7 @@ type MultipartFormField struct {
Filename string
}
//PostMultipartForm 上传文件或其他多个字段
// PostMultipartForm 上传文件或其他多个字段
func PostMultipartForm(fields []MultipartFormField, uri string) (respBody []byte, err error) {
bodyBuf := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(bodyBuf)
@@ -159,11 +182,11 @@ func PostMultipartForm(fields []MultipartFormField, uri string) (respBody []byte
if resp.StatusCode != http.StatusOK {
return nil, err
}
respBody, err = ioutil.ReadAll(resp.Body)
respBody, err = io.ReadAll(resp.Body)
return
}
//PostXML perform a HTTP/POST request with XML body
// PostXML perform a HTTP/POST request with XML body
func PostXML(uri string, obj interface{}) ([]byte, error) {
xmlData, err := xml.Marshal(obj)
if err != nil {
@@ -180,13 +203,13 @@ func PostXML(uri string, obj interface{}) ([]byte, error) {
if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("http code error : uri=%v , statusCode=%v", uri, response.StatusCode)
}
return ioutil.ReadAll(response.Body)
return io.ReadAll(response.Body)
}
//httpWithTLS CA证书
// httpWithTLS CA证书
func httpWithTLS(rootCa, key string) (*http.Client, error) {
var client *http.Client
certData, err := ioutil.ReadFile(rootCa)
certData, err := os.ReadFile(rootCa)
if err != nil {
return nil, fmt.Errorf("unable to find cert path=%s, error=%v", rootCa, err)
}
@@ -202,7 +225,7 @@ func httpWithTLS(rootCa, key string) (*http.Client, error) {
return client, nil
}
//pkcs12ToPem 将Pkcs12转成Pem
// pkcs12ToPem 将Pkcs12转成Pem
func pkcs12ToPem(p12 []byte, password string) tls.Certificate {
blocks, err := pkcs12.ToPEM(p12, password)
defer func() {
@@ -224,7 +247,7 @@ func pkcs12ToPem(p12 []byte, password string) tls.Certificate {
return cert
}
//PostXMLWithTLS perform a HTTP/POST request with XML body and TLS
// PostXMLWithTLS perform a HTTP/POST request with XML body and TLS
func PostXMLWithTLS(uri string, obj interface{}, ca, key string) ([]byte, error) {
xmlData, err := xml.Marshal(obj)
if err != nil {
@@ -245,5 +268,5 @@ func PostXMLWithTLS(uri string, obj interface{}, ca, key string) ([]byte, error)
if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("http code error : uri=%v , statusCode=%v", uri, response.StatusCode)
}
return ioutil.ReadAll(response.Body)
return io.ReadAll(response.Body)
}

View File

@@ -8,7 +8,7 @@ import (
"sort"
)
//Signature sha1签名
// Signature sha1签名
func Signature(params ...string) string {
sort.Strings(params)
h := sha1.New()

View File

@@ -3,7 +3,7 @@ package util
import "testing"
func TestSignature(t *testing.T) {
//abc sig
// abc sig
abc := "a9993e364706816aba3e25717850c26c9cd0d89d"
if abc != Signature("a", "b", "c") {
t.Error("test Signature Error")

View File

@@ -5,7 +5,7 @@ import (
"time"
)
//RandomStr 随机生成字符串
// RandomStr 随机生成字符串
func RandomStr(length int) string {
str := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
bytes := []byte(str)

View File

@@ -2,7 +2,7 @@ package util
import "time"
//GetCurrTS return current timestamps
// GetCurrTS return current timestamps
func GetCurrTS() int64 {
return time.Now().Unix()
}

View File

@@ -1,6 +1,6 @@
package util
//SliceChunk 用于将字符串切片分块
// SliceChunk 用于将字符串切片分块
func SliceChunk(src []string, chunkSize int) (chunks [][]string) {
total := len(src)
chunks = make([][]string, 0)