jerry 6 лет назад
Родитель
Сommit
c0a7c1b116
13 измененных файлов с 134 добавлено и 148 удалено
  1. 1 7
      README.md
  2. 1 1
      alipay/client.go
  3. 3 3
      alipay/param.go
  4. 10 10
      alipay/service_api.go
  5. 2 2
      http_client.go
  6. 1 1
      model.go
  7. 15 15
      qq/client.go
  8. 26 37
      qq/param.go
  9. 3 3
      qq/service_api.go
  10. 6 0
      release_note.txt
  11. 21 21
      wechat/client.go
  12. 34 37
      wechat/param.go
  13. 11 11
      wechat/service_api.go

+ 1 - 7
README.md

@@ -6,7 +6,7 @@
 QQ、微信、支付宝的Golang版本SDK
 
 ![Author](https://img.shields.io/badge/author-Jerry-blue.svg)
-[![Golang](https://img.shields.io/badge/golang-1.11+-brightgreen.svg)](https://golang.org)
+[![Golang](https://img.shields.io/badge/golang-1.13+-brightgreen.svg)](https://golang.org)
 [![Godoc](https://img.shields.io/badge/godoc-reference-informational.svg)](https://godoc.org/github.com/iGoogle-ink/gopay)
 ![GitHub release (latest by date)](https://img.shields.io/github/v/release/iGoogle-ink/gopay)
 ![Travis (.org)](https://img.shields.io/travis/iGoogle-ink/gopay)
@@ -175,12 +175,6 @@ client := wechat.NewClient("wxdaa2ab9ef87b5497", mchId, apiKey, false)
 //    gopay.Other:其他国家
 client.SetCountry(gopay.China)
 
-// 添加微信证书 Byte 数组
-//    certFile:apiclient_cert.pem byte数组
-//    keyFile:apiclient_key.pem byte数组
-//    pkcs12File:apiclient_cert.p12 byte数组
-client.AddCertFileByte()
-
 // 添加微信证书 Path 路径
 //    certFilePath:apiclient_cert.pem 路径
 //    keyFilePath:apiclient_key.pem 路径

+ 1 - 1
alipay/client.go

@@ -533,7 +533,7 @@ func (a *Client) doAliPay(bm gopay.BodyMap, method string) (bs []byte, err error
 	)
 	if bm != nil {
 		if bodyBs, err = json.Marshal(bm); err != nil {
-			return nil, fmt.Errorf("json.Marshal:%s", err.Error())
+			return nil, fmt.Errorf("json.Marshal:%w", err)
 		}
 		bodyStr = string(bodyBs)
 	}

+ 3 - 3
alipay/param.go

@@ -89,15 +89,15 @@ func (a *Client) SetAliPayRootCertSN(aliPayRootCertSN string) (client *Client) {
 func (a *Client) SetCertSnByPath(appCertPath, aliPayRootCertPath, aliPayPublicCertPath string) (err error) {
 	appCertSn, err := GetCertSN(appCertPath)
 	if err != nil {
-		return fmt.Errorf("get app_cert_sn return err, but alse return alipay client. err: %v", err)
+		return fmt.Errorf("get app_cert_sn return err, but alse return alipay client. err: %w", err)
 	}
 	rootCertSn, err := GetRootCertSN(aliPayRootCertPath)
 	if err != nil {
-		return fmt.Errorf("get alipay_root_cert_sn return err, but alse return alipay client. err: %v", err)
+		return fmt.Errorf("get alipay_root_cert_sn return err, but alse return alipay client. err: %w", err)
 	}
 	publicCertSn, err := GetCertSN(aliPayPublicCertPath)
 	if err != nil {
-		return fmt.Errorf("get alipay_cert_sn return err, but alse return alipay client. err: %v", err)
+		return fmt.Errorf("get alipay_cert_sn return err, but alse return alipay client. err: %w", err)
 	}
 	a.mu.Lock()
 	a.AppCertSN = appCertSn

+ 10 - 10
alipay/service_api.go

@@ -100,7 +100,7 @@ func ParseNotifyResult(req *http.Request) (notifyReq *NotifyRequest, err error)
 	if billList != gopay.NULL {
 		bills := make([]*fundBillListInfo, 0)
 		if err = json.Unmarshal([]byte(billList), &bills); err != nil {
-			return nil, fmt.Errorf(`"fund_bill_list" xml.Unmarshal:%s`, err.Error())
+			return nil, fmt.Errorf(`"fund_bill_list" xml.Unmarshal(%s):%w`, billList, err)
 		}
 		notifyReq.FundBillList = bills
 	} else {
@@ -111,7 +111,7 @@ func ParseNotifyResult(req *http.Request) (notifyReq *NotifyRequest, err error)
 	if detailList != gopay.NULL {
 		details := make([]*voucherDetailListInfo, 0)
 		if err = json.Unmarshal([]byte(detailList), &details); err != nil {
-			return nil, fmt.Errorf(`"voucher_detail_list" xml.Unmarshal:%s`, err.Error())
+			return nil, fmt.Errorf(`"voucher_detail_list" xml.Unmarshal(%s):%w`, detailList, err)
 		}
 		notifyReq.VoucherDetailList = details
 	} else {
@@ -182,10 +182,10 @@ func VerifySign(aliPayPublicKey string, bean interface{}) (ok bool, err error) {
 	} else {
 		bs, err := json.Marshal(bean)
 		if err != nil {
-			return false, fmt.Errorf("json.Marshal:%s", err.Error())
+			return false, fmt.Errorf("json.Marshal:%w", err)
 		}
 		if err = json.Unmarshal(bs, &bm); err != nil {
-			return false, fmt.Errorf("json.Unmarshal:%s", err.Error())
+			return false, fmt.Errorf("json.Unmarshal(%s):%w", string(bs), err)
 		}
 		bodySign = bm.Get("sign")
 		bodySignType = bm.Get("sign_type")
@@ -214,7 +214,7 @@ func verifySign(signData, sign, signType, aliPayPublicKey string) (err error) {
 		return errors.New("支付宝公钥Decode错误")
 	}
 	if pubKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil {
-		return fmt.Errorf("x509.ParsePKIXPublicKey:%s", err.Error())
+		return fmt.Errorf("x509.ParsePKIXPublicKey:%w", err)
 	}
 	if publicKey, ok = pubKey.(*rsa.PublicKey); !ok {
 		return errors.New("支付宝公钥转换错误")
@@ -379,7 +379,7 @@ func DecryptOpenDataToStruct(encryptedData, secretKey string, beanPtr interface{
 	ivKey := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 	secretData, _ := base64.StdEncoding.DecodeString(encryptedData)
 	if block, err = aes.NewCipher(aesKey); err != nil {
-		return fmt.Errorf("aes.NewCipher:%s", err.Error())
+		return fmt.Errorf("aes.NewCipher:%w", err)
 	}
 	if len(secretData)%len(aesKey) != 0 {
 		return errors.New("encryptedData is error")
@@ -391,7 +391,7 @@ func DecryptOpenDataToStruct(encryptedData, secretKey string, beanPtr interface{
 		originData = gopay.PKCS5UnPadding(originData)
 	}
 	if err = json.Unmarshal(originData, beanPtr); err != nil {
-		return fmt.Errorf("json.Unmarshal:%s", err.Error())
+		return fmt.Errorf("json.Unmarshal(%s):%w", string(originData), err)
 	}
 	return nil
 }
@@ -411,7 +411,7 @@ func DecryptOpenDataToBodyMap(encryptedData, secretKey string) (bm gopay.BodyMap
 	aesKey, _ = base64.StdEncoding.DecodeString(secretKey)
 	secretData, _ := base64.StdEncoding.DecodeString(encryptedData)
 	if block, err = aes.NewCipher(aesKey); err != nil {
-		return nil, fmt.Errorf("aes.NewCipher:%s", err.Error())
+		return nil, fmt.Errorf("aes.NewCipher:%w", err)
 	}
 	if len(secretData)%len(aesKey) != 0 {
 		return nil, errors.New("encryptedData is error")
@@ -424,7 +424,7 @@ func DecryptOpenDataToBodyMap(encryptedData, secretKey string) (bm gopay.BodyMap
 	}
 	bm = make(gopay.BodyMap)
 	if err = json.Unmarshal(originData, &bm); err != nil {
-		return nil, fmt.Errorf("json.Unmarshal:%s", err.Error())
+		return nil, fmt.Errorf("json.Unmarshal(%s):%w", string(originData), err)
 	}
 	return
 }
@@ -453,7 +453,7 @@ func SystemOauthToken(appId, privateKey, grantType, codeOrToken string) (rsp *Sy
 	}
 	rsp = new(SystemOauthTokenResponse)
 	if err = json.Unmarshal(bs, rsp); err != nil {
-		return nil, fmt.Errorf("json.Unmarshal:%s", err.Error())
+		return nil, fmt.Errorf("json.Unmarshal(%s):%w", string(bs), err)
 	}
 	if rsp.Response.AccessToken == "" {
 		return nil, errors.New("access_token is NULL")

+ 2 - 2
http_client.go

@@ -125,14 +125,14 @@ func (c *Client) EndStruct(v interface{}) (res *http.Response, errs []error) {
 	case TypeJSON:
 		err := json.Unmarshal(bs, &v)
 		if err != nil {
-			c.Errors = append(c.Errors, fmt.Errorf("json.Unmarshal:%s", err.Error()))
+			c.Errors = append(c.Errors, fmt.Errorf("json.Unmarshal(%s):%w", string(bs), err))
 			return nil, c.Errors
 		}
 		return res, nil
 	case TypeXML:
 		err := xml.Unmarshal(bs, &v)
 		if err != nil {
-			c.Errors = append(c.Errors, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error()))
+			c.Errors = append(c.Errors, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err))
 			return nil, c.Errors
 		}
 		return res, nil

+ 1 - 1
model.go

@@ -7,7 +7,7 @@ const (
 	SUCCESS    = "SUCCESS"
 	FAIL       = "FAIL"
 	OK         = "OK"
-	Version    = "2.0.1"
+	Version    = "2.0.2"
 )
 
 type ReturnMessage struct {

+ 15 - 15
qq/client.go

@@ -2,6 +2,7 @@ package qq
 
 import (
 	"crypto/tls"
+	"crypto/x509"
 	"encoding/xml"
 	"errors"
 	"fmt"
@@ -12,13 +13,12 @@ import (
 )
 
 type Client struct {
-	MchId      string
-	ApiKey     string
-	CertFile   []byte
-	KeyFile    []byte
-	Pkcs12File []byte
-	IsProd     bool
-	mu         sync.RWMutex
+	MchId       string
+	ApiKey      string
+	IsProd      bool
+	certificate tls.Certificate
+	certPool    *x509.CertPool
+	mu          sync.RWMutex
 }
 
 // 初始化QQ客户端(正式环境)
@@ -48,7 +48,7 @@ func (q *Client) MicroPay(bm gopay.BodyMap) (qqRsp *MicroPayResponse, err error)
 	}
 	qqRsp = new(MicroPayResponse)
 	if err = xml.Unmarshal(bs, qqRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
 	return qqRsp, nil
 }
@@ -66,7 +66,7 @@ func (q *Client) Reverse(bm gopay.BodyMap) (qqRsp *ReverseResponse, err error) {
 	}
 	qqRsp = new(ReverseResponse)
 	if err = xml.Unmarshal(bs, qqRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
 	return qqRsp, nil
 }
@@ -84,7 +84,7 @@ func (q *Client) UnifiedOrder(bm gopay.BodyMap) (qqRsp *UnifiedOrderResponse, er
 	}
 	qqRsp = new(UnifiedOrderResponse)
 	if err = xml.Unmarshal(bs, qqRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
 	return qqRsp, nil
 }
@@ -105,7 +105,7 @@ func (q *Client) OrderQuery(bm gopay.BodyMap) (qqRsp *OrderQueryResponse, err er
 	}
 	qqRsp = new(OrderQueryResponse)
 	if err = xml.Unmarshal(bs, qqRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
 	return qqRsp, nil
 }
@@ -123,13 +123,13 @@ func (q *Client) CloseOrder(bm gopay.BodyMap) (qqRsp *CloseOrderResponse, err er
 	}
 	qqRsp = new(CloseOrderResponse)
 	if err = xml.Unmarshal(bs, qqRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
 	return qqRsp, nil
 }
 
 // 申请退款
-//    注意:如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",否则,3证书Path均不可空
+//    注意:如已使用client.AddCertFilePath()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",否则,3证书Path均不可空
 //    文档地址:https://qpay.qq.com/buss/wiki/38/1207
 func (q *Client) Refund(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (qqRsp *RefundResponse, err error) {
 	err = bm.CheckEmptyError("nonce_str", "out_refund_no", "refund_fee", "op_user_id", "op_user_passwd")
@@ -149,7 +149,7 @@ func (q *Client) Refund(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12FileP
 	}
 	qqRsp = new(RefundResponse)
 	if err = xml.Unmarshal(bs, qqRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
 	return qqRsp, nil
 }
@@ -170,7 +170,7 @@ func (q *Client) RefundQuery(bm gopay.BodyMap) (qqRsp *RefundQueryResponse, err
 	}
 	qqRsp = new(RefundQueryResponse)
 	if err = xml.Unmarshal(bs, qqRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
 	return qqRsp, nil
 }

+ 26 - 37
qq/param.go

@@ -17,18 +17,6 @@ import (
 	"github.com/iGoogle-ink/gopay/v2"
 )
 
-// 添加QQ证书 Byte 数组
-//    certFile:apiclient_cert.pem byte数组
-//    keyFile:apiclient_key.pem byte数组
-//    pkcs12File:apiclient_cert.p12 byte数组
-func (q *Client) AddCertFileByte(certFile, keyFile, pkcs12File []byte) {
-	q.mu.Lock()
-	q.CertFile = certFile
-	q.KeyFile = keyFile
-	q.Pkcs12File = pkcs12File
-	q.mu.Unlock()
-}
-
 // 添加QQ证书 Path 路径
 //    certFilePath:apiclient_cert.pem 路径
 //    keyFilePath:apiclient_key.pem 路径
@@ -37,20 +25,25 @@ func (q *Client) AddCertFileByte(certFile, keyFile, pkcs12File []byte) {
 func (q *Client) AddCertFilePath(certFilePath, keyFilePath, pkcs12FilePath string) (err error) {
 	cert, err := ioutil.ReadFile(certFilePath)
 	if err != nil {
-		return err
+		return fmt.Errorf("ioutil.ReadFile:%w", err)
 	}
 	key, err := ioutil.ReadFile(keyFilePath)
 	if err != nil {
-		return err
+		return fmt.Errorf("ioutil.ReadFile:%w", err)
 	}
 	pkcs, err := ioutil.ReadFile(pkcs12FilePath)
 	if err != nil {
-		return err
+		return fmt.Errorf("ioutil.ReadFile:%w", err)
 	}
+	certificate, err := tls.X509KeyPair(cert, key)
+	if err != nil {
+		return fmt.Errorf("tls.LoadX509KeyPair:%w", err)
+	}
+	pkcsPool := x509.NewCertPool()
+	pkcsPool.AppendCertsFromPEM(pkcs)
 	q.mu.Lock()
-	q.CertFile = cert
-	q.KeyFile = key
-	q.Pkcs12File = pkcs
+	q.certificate = certificate
+	q.certPool = pkcsPool
 	q.mu.Unlock()
 	return nil
 }
@@ -77,34 +70,30 @@ func getReleaseSign(apiKey string, signType string, bm gopay.BodyMap) (sign stri
 }
 
 func (q *Client) addCertConfig(certFilePath, keyFilePath, pkcs12FilePath string) (tlsConfig *tls.Config, err error) {
-	var (
-		pkcs        []byte
-		certificate tls.Certificate
-		pkcsPool    = x509.NewCertPool()
-	)
 
 	if certFilePath == gopay.NULL && keyFilePath == gopay.NULL && pkcs12FilePath == gopay.NULL {
 		q.mu.RLock()
-		pkcsPool.AppendCertsFromPEM(q.Pkcs12File)
-		certificate, err = tls.X509KeyPair(q.CertFile, q.KeyFile)
-		q.mu.RUnlock()
-		if err != nil {
-			return nil, fmt.Errorf("tls.X509KeyPair:%s", err.Error())
+		defer q.mu.RUnlock()
+		if &q.certificate != nil && q.certPool != nil {
+			tlsConfig = &tls.Config{
+				Certificates:       []tls.Certificate{q.certificate},
+				RootCAs:            q.certPool,
+				InsecureSkipVerify: true,
+			}
+			return tlsConfig, nil
 		}
-		tlsConfig = &tls.Config{
-			Certificates:       []tls.Certificate{certificate},
-			RootCAs:            pkcsPool,
-			InsecureSkipVerify: true}
-		return tlsConfig, nil
 	}
 
 	if certFilePath != gopay.NULL && keyFilePath != gopay.NULL && pkcs12FilePath != gopay.NULL {
-		if pkcs, err = ioutil.ReadFile(pkcs12FilePath); err != nil {
-			return nil, fmt.Errorf("ioutil.ReadFile:%s", err.Error())
+		pkcs, err := ioutil.ReadFile(pkcs12FilePath)
+		if err != nil {
+			return nil, fmt.Errorf("ioutil.ReadFile:%w", err)
 		}
+		pkcsPool := x509.NewCertPool()
 		pkcsPool.AppendCertsFromPEM(pkcs)
-		if certificate, err = tls.LoadX509KeyPair(certFilePath, keyFilePath); err != nil {
-			return nil, fmt.Errorf("tls.LoadX509KeyPair:%s", err.Error())
+		certificate, err := tls.LoadX509KeyPair(certFilePath, keyFilePath)
+		if err != nil {
+			return nil, fmt.Errorf("tls.LoadX509KeyPair:%w", err)
 		}
 		tlsConfig = &tls.Config{
 			Certificates:       []tls.Certificate{certificate},

+ 3 - 3
qq/service_api.go

@@ -17,11 +17,11 @@ import (
 func ParseNotifyResultToBodyMap(req *http.Request) (bm gopay.BodyMap, err error) {
 	bs, err := ioutil.ReadAll(io.LimitReader(req.Body, int64(2<<20))) // default 2MB change the size you want;
 	if err != nil {
-		return nil, fmt.Errorf("ioutil.ReadAll:%s", err.Error())
+		return nil, fmt.Errorf("ioutil.ReadAll:%w", err)
 	}
 	bm = make(gopay.BodyMap)
 	if err = xml.Unmarshal(bs, &bm); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
 	return
 }
@@ -33,7 +33,7 @@ func ParseNotifyResultToBodyMap(req *http.Request) (bm gopay.BodyMap, err error)
 func ParseNotifyResult(req *http.Request) (notifyReq *NotifyRequest, err error) {
 	notifyReq = new(NotifyRequest)
 	if err = xml.NewDecoder(req.Body).Decode(notifyReq); err != nil {
-		return nil, fmt.Errorf("xml.NewDecoder:%s", err.Error())
+		return nil, fmt.Errorf("xml.NewDecoder.Decode:%w", err)
 	}
 	return
 }

+ 6 - 0
release_note.txt

@@ -1,3 +1,9 @@
+版本号:Release 2.0.2
+发布时间:2019/12/13 23:25
+修改记录:
+   (1) 微信:删除Client方法:client.AddCertFileByte()
+   (2) 版本限制 golang 1.13,fmt.Errorf() 使用 %w 格式化 error,1.13新特性
+
 版本号:Release 2.0.1
 发布时间:2019/12/13 17:20
 修改记录:

+ 21 - 21
wechat/client.go

@@ -2,6 +2,7 @@ package wechat
 
 import (
 	"crypto/tls"
+	"crypto/x509"
 	"encoding/xml"
 	"errors"
 	"fmt"
@@ -12,15 +13,14 @@ import (
 )
 
 type Client struct {
-	AppId      string
-	MchId      string
-	ApiKey     string
-	BaseURL    string
-	CertFile   []byte
-	KeyFile    []byte
-	Pkcs12File []byte
-	IsProd     bool
-	mu         sync.RWMutex
+	AppId       string
+	MchId       string
+	ApiKey      string
+	BaseURL     string
+	IsProd      bool
+	certificate tls.Certificate
+	certPool    *x509.CertPool
+	mu          sync.RWMutex
 }
 
 // 初始化微信客户端
@@ -54,7 +54,7 @@ func (w *Client) Micropay(bm gopay.BodyMap) (wxRsp *MicropayResponse, err error)
 	}
 	wxRsp = new(MicropayResponse)
 	if err = xml.Unmarshal(bs, wxRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
 	return
 }
@@ -78,7 +78,7 @@ func (w *Client) UnifiedOrder(bm gopay.BodyMap) (wxRsp *UnifiedOrderResponse, er
 	}
 	wxRsp = new(UnifiedOrderResponse)
 	if err = xml.Unmarshal(bs, wxRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
 	return
 }
@@ -104,7 +104,7 @@ func (w *Client) QueryOrder(bm gopay.BodyMap) (wxRsp *QueryOrderResponse, err er
 	}
 	wxRsp = new(QueryOrderResponse)
 	if err = xml.Unmarshal(bs, wxRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
 	return
 }
@@ -127,13 +127,13 @@ func (w *Client) CloseOrder(bm gopay.BodyMap) (wxRsp *CloseOrderResponse, err er
 	}
 	wxRsp = new(CloseOrderResponse)
 	if err = xml.Unmarshal(bs, wxRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
 	return
 }
 
 // 撤销订单
-//    注意:如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",否则,3证书Path均不可空
+//    注意:如已使用client.AddCertFilePath()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",否则,3证书Path均不可空
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_11&index=3
 func (w *Client) Reverse(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp *ReverseResponse, err error) {
 	err = bm.CheckEmptyError("nonce_str", "out_trade_no")
@@ -157,13 +157,13 @@ func (w *Client) Reverse(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12File
 	}
 	wxRsp = new(ReverseResponse)
 	if err = xml.Unmarshal(bs, wxRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
 	return
 }
 
 // 申请退款
-//    注意:如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",否则,3证书Path均不可空
+//    注意:如已使用client.AddCertFilePath()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",否则,3证书Path均不可空
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
 func (w *Client) Refund(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp *RefundResponse, err error) {
 	err = bm.CheckEmptyError("nonce_str", "out_refund_no", "total_fee", "refund_fee")
@@ -190,7 +190,7 @@ func (w *Client) Refund(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12FileP
 	}
 	wxRsp = new(RefundResponse)
 	if err = xml.Unmarshal(bs, wxRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
 	return
 }
@@ -216,7 +216,7 @@ func (w *Client) QueryRefund(bm gopay.BodyMap) (wxRsp *QueryRefundResponse, err
 	}
 	wxRsp = new(QueryRefundResponse)
 	if err = xml.Unmarshal(bs, wxRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
 	return
 }
@@ -246,7 +246,7 @@ func (w *Client) DownloadBill(bm gopay.BodyMap) (wxRsp string, err error) {
 }
 
 // 下载资金账单
-//    注意:如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",否则,3证书Path均不可空
+//    注意:如已使用client.AddCertFilePath()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",否则,3证书Path均不可空
 //    貌似不支持沙箱环境,因为沙箱环境默认需要用MD5签名,但是此接口仅支持HMAC-SHA256签名
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_18&index=7
 func (w *Client) DownloadFundFlow(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp string, err error) {
@@ -279,7 +279,7 @@ func (w *Client) DownloadFundFlow(bm gopay.BodyMap, certFilePath, keyFilePath, p
 }
 
 // 拉取订单评价数据
-//    注意:如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",否则,3证书Path均不可空
+//    注意:如已使用client.AddCertFilePath()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",否则,3证书Path均不可空
 //    貌似不支持沙箱环境,因为沙箱环境默认需要用MD5签名,但是此接口仅支持HMAC-SHA256签名
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_17&index=11
 func (w *Client) BatchQueryComment(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp string, err error) {
@@ -308,7 +308,7 @@ func (w *Client) BatchQueryComment(bm gopay.BodyMap, certFilePath, keyFilePath,
 }
 
 // 企业向微信用户个人付款
-//    注意:如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",否则,3证书Path均不可空
+//    注意:如已使用client.AddCertFilePath()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",否则,3证书Path均不可空
 //    注意:此方法未支持沙箱环境,默认正式环境,转账请慎重
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
 func (w *Client) Transfer(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp *TransfersResponse, err error) {

+ 34 - 37
wechat/param.go

@@ -40,18 +40,6 @@ func (w *Client) SetCountry(country Country) (client *Client) {
 	return w
 }
 
-// 添加微信证书 Byte 数组
-//    certFile:apiclient_cert.pem byte数组
-//    keyFile:apiclient_key.pem byte数组
-//    pkcs12File:apiclient_cert.p12 byte数组
-func (w *Client) AddCertFileByte(certFile, keyFile, pkcs12File []byte) {
-	w.mu.Lock()
-	w.CertFile = certFile
-	w.KeyFile = keyFile
-	w.Pkcs12File = pkcs12File
-	w.mu.Unlock()
-}
-
 // 添加微信证书 Path 路径
 //    certFilePath:apiclient_cert.pem 路径
 //    keyFilePath:apiclient_key.pem 路径
@@ -60,53 +48,62 @@ func (w *Client) AddCertFileByte(certFile, keyFile, pkcs12File []byte) {
 func (w *Client) AddCertFilePath(certFilePath, keyFilePath, pkcs12FilePath string) (err error) {
 	cert, err := ioutil.ReadFile(certFilePath)
 	if err != nil {
-		return err
+		return fmt.Errorf("ioutil.ReadFile:%w", err)
 	}
 	key, err := ioutil.ReadFile(keyFilePath)
 	if err != nil {
-		return err
+		return fmt.Errorf("ioutil.ReadFile:%w", err)
 	}
 	pkcs, err := ioutil.ReadFile(pkcs12FilePath)
 	if err != nil {
-		return err
+		return fmt.Errorf("ioutil.ReadFile:%w", err)
+	}
+	certificate, err := tls.X509KeyPair(cert, key)
+	if err != nil {
+		return fmt.Errorf("tls.LoadX509KeyPair:%w", err)
 	}
+	pkcsPool := x509.NewCertPool()
+	pkcsPool.AppendCertsFromPEM(pkcs)
 	w.mu.Lock()
-	w.CertFile = cert
-	w.KeyFile = key
-	w.Pkcs12File = pkcs
+	w.certificate = certificate
+	w.certPool = pkcsPool
 	w.mu.Unlock()
 	return nil
 }
 
 func (w *Client) addCertConfig(certFilePath, keyFilePath, pkcs12FilePath string) (tlsConfig *tls.Config, err error) {
-	var (
-		pkcs        []byte
-		certificate tls.Certificate
-		pkcsPool    = x509.NewCertPool()
-	)
 
 	if certFilePath == gopay.NULL && keyFilePath == gopay.NULL && pkcs12FilePath == gopay.NULL {
 		w.mu.RLock()
-		pkcsPool.AppendCertsFromPEM(w.Pkcs12File)
-		certificate, err = tls.X509KeyPair(w.CertFile, w.KeyFile)
-		w.mu.RUnlock()
-		if err != nil {
-			return nil, fmt.Errorf("tls.X509KeyPair:%s", err.Error())
+		defer w.mu.RUnlock()
+		if &w.certificate != nil && w.certPool != nil {
+			tlsConfig = &tls.Config{
+				Certificates:       []tls.Certificate{w.certificate},
+				RootCAs:            w.certPool,
+				InsecureSkipVerify: true,
+			}
+			return tlsConfig, nil
 		}
-		tlsConfig = &tls.Config{
-			Certificates:       []tls.Certificate{certificate},
-			RootCAs:            pkcsPool,
-			InsecureSkipVerify: true}
-		return tlsConfig, nil
 	}
 
 	if certFilePath != gopay.NULL && keyFilePath != gopay.NULL && pkcs12FilePath != gopay.NULL {
-		if pkcs, err = ioutil.ReadFile(pkcs12FilePath); err != nil {
-			return nil, fmt.Errorf("ioutil.ReadFile:%s", err.Error())
+		cert, err := ioutil.ReadFile(certFilePath)
+		if err != nil {
+			return nil, fmt.Errorf("ioutil.ReadFile:%w", err)
 		}
+		key, err := ioutil.ReadFile(keyFilePath)
+		if err != nil {
+			return nil, fmt.Errorf("ioutil.ReadFile:%w", err)
+		}
+		pkcs, err := ioutil.ReadFile(pkcs12FilePath)
+		if err != nil {
+			return nil, fmt.Errorf("ioutil.ReadFile:%w", err)
+		}
+		pkcsPool := x509.NewCertPool()
 		pkcsPool.AppendCertsFromPEM(pkcs)
-		if certificate, err = tls.LoadX509KeyPair(certFilePath, keyFilePath); err != nil {
-			return nil, fmt.Errorf("tls.LoadX509KeyPair:%s", err.Error())
+		certificate, err := tls.X509KeyPair(cert, key)
+		if err != nil {
+			return nil, fmt.Errorf("tls.LoadX509KeyPair:%w", err)
 		}
 		tlsConfig = &tls.Config{
 			Certificates:       []tls.Certificate{certificate},

+ 11 - 11
wechat/service_api.go

@@ -80,11 +80,11 @@ func GetSanBoxParamSign(appId, mchId, apiKey string, bm gopay.BodyMap) (sign str
 func ParseNotifyResultToBodyMap(req *http.Request) (bm gopay.BodyMap, err error) {
 	bs, err := ioutil.ReadAll(io.LimitReader(req.Body, int64(2<<20))) // default 2MB change the size you want;
 	if err != nil {
-		return nil, fmt.Errorf("ioutil.ReadAll:%s", err.Error())
+		return nil, fmt.Errorf("ioutil.ReadAll:%w", err)
 	}
 	bm = make(gopay.BodyMap)
 	if err = xml.Unmarshal(bs, &bm); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
 	return
 }
@@ -96,7 +96,7 @@ func ParseNotifyResultToBodyMap(req *http.Request) (bm gopay.BodyMap, err error)
 func ParseNotifyResult(req *http.Request) (notifyReq *NotifyRequest, err error) {
 	notifyReq = new(NotifyRequest)
 	if err = xml.NewDecoder(req.Body).Decode(notifyReq); err != nil {
-		return nil, fmt.Errorf("xml.NewDecoder:%s", err.Error())
+		return nil, fmt.Errorf("xml.NewDecoder.Decode:%w", err)
 	}
 	return
 }
@@ -108,7 +108,7 @@ func ParseNotifyResult(req *http.Request) (notifyReq *NotifyRequest, err error)
 func ParseRefundNotifyResult(req *http.Request) (notifyReq *RefundNotifyRequest, err error) {
 	notifyReq = new(RefundNotifyRequest)
 	if err = xml.NewDecoder(req.Body).Decode(notifyReq); err != nil {
-		return nil, fmt.Errorf("xml.NewDecoder:%s", err.Error())
+		return nil, fmt.Errorf("xml.NewDecoder.Decode:%w", err)
 	}
 	return
 }
@@ -154,7 +154,7 @@ func DecryptRefundNotifyReqInfo(reqInfo, apiKey string) (refundNotify *RefundNot
 	bs = gopay.PKCS7UnPadding(encryptionB)
 	refundNotify = new(RefundNotify)
 	if err = xml.Unmarshal(bs, refundNotify); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
 	return
 }
@@ -181,11 +181,11 @@ func VerifySign(apiKey, signType string, bean interface{}) (ok bool, err error)
 		goto Verify
 	}
 	if bs, err = json.Marshal(bean); err != nil {
-		return false, fmt.Errorf("json.Marshal:%s", err.Error())
+		return false, fmt.Errorf("json.Marshal(%s):%w", string(bs), err)
 	}
 	bm = make(gopay.BodyMap)
 	if err = json.Unmarshal(bs, &bm); err != nil {
-		return false, fmt.Errorf("json.Unmarshal:%s", err.Error())
+		return false, fmt.Errorf("json.Marshal(%s):%w", string(bs), err)
 	}
 Verify:
 	bodySign = bm.Get("sign")
@@ -344,7 +344,7 @@ func DecryptOpenDataToStruct(encryptedData, iv, sessionKey string, beanPtr inter
 		return errors.New("encryptedData is error")
 	}
 	if block, err = aes.NewCipher(aesKey); err != nil {
-		return fmt.Errorf("aes.NewCipher:%s", err.Error())
+		return fmt.Errorf("aes.NewCipher:%w", err)
 	}
 	blockMode = cipher.NewCBCDecrypter(block, ivKey)
 	plainText = make([]byte, len(cipherText))
@@ -353,7 +353,7 @@ func DecryptOpenDataToStruct(encryptedData, iv, sessionKey string, beanPtr inter
 		plainText = gopay.PKCS7UnPadding(plainText)
 	}
 	if err = json.Unmarshal(plainText, beanPtr); err != nil {
-		return fmt.Errorf("json.Unmarshal:%s", err.Error())
+		return fmt.Errorf("json.Marshal(%s):%w", string(plainText), err)
 	}
 	return
 }
@@ -376,7 +376,7 @@ func DecryptOpenDataToBodyMap(encryptedData, iv, sessionKey string) (bm gopay.Bo
 		return nil, errors.New("encryptedData is error")
 	}
 	if block, err = aes.NewCipher(aesKey); err != nil {
-		return nil, fmt.Errorf("aes.NewCipher:%s", err.Error())
+		return nil, fmt.Errorf("aes.NewCipher:%w", err)
 	} else {
 		blockMode = cipher.NewCBCDecrypter(block, ivKey)
 		plainText = make([]byte, len(cipherText))
@@ -386,7 +386,7 @@ func DecryptOpenDataToBodyMap(encryptedData, iv, sessionKey string) (bm gopay.Bo
 		}
 		bm = make(gopay.BodyMap)
 		if err = json.Unmarshal(plainText, &bm); err != nil {
-			return nil, fmt.Errorf("json.Unmarshal:%s", err.Error())
+			return nil, fmt.Errorf("json.Marshal(%s):%w", string(plainText), err)
 		}
 		return
 	}