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:
@@ -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
|
||||
|
||||
@@ -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
55
util/error_test.go
Normal 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
|
||||
}
|
||||
}
|
||||
73
util/http.go
73
util/http.go
@@ -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)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
//Signature sha1签名
|
||||
// Signature sha1签名
|
||||
func Signature(params ...string) string {
|
||||
sort.Strings(params)
|
||||
h := sha1.New()
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
//RandomStr 随机生成字符串
|
||||
// RandomStr 随机生成字符串
|
||||
func RandomStr(length int) string {
|
||||
str := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
bytes := []byte(str)
|
||||
|
||||
@@ -2,7 +2,7 @@ package util
|
||||
|
||||
import "time"
|
||||
|
||||
//GetCurrTS return current timestamps
|
||||
// GetCurrTS return current timestamps
|
||||
func GetCurrTS() int64 {
|
||||
return time.Now().Unix()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package util
|
||||
|
||||
//SliceChunk 用于将字符串切片分块
|
||||
// SliceChunk 用于将字符串切片分块
|
||||
func SliceChunk(src []string, chunkSize int) (chunks [][]string) {
|
||||
total := len(src)
|
||||
chunks = make([][]string, 0)
|
||||
|
||||
Reference in New Issue
Block a user