فهرست منبع

add checkCertFilePath(),add client.PostRequest()

Jerry 5 سال پیش
والد
کامیت
4d843b9ae3
8فایلهای تغییر یافته به همراه159 افزوده شده و 76 حذف شده
  1. 4 1
      qq/client.go
  2. 1 1
      qq/client_test.go
  3. 44 16
      qq/param.go
  4. 9 0
      qq/service_api.go
  5. 51 37
      wechat/client.go
  6. 9 9
      wechat/client_test.go
  7. 32 12
      wechat/param.go
  8. 9 0
      wechat/service_api.go

+ 4 - 1
qq/client.go

@@ -131,7 +131,10 @@ func (q *Client) CloseOrder(bm gopay.BodyMap) (qqRsp *CloseOrderResponse, err er
 // 申请退款
 //    注意:如已使用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) {
+func (q *Client) Refund(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12FilePath interface{}) (qqRsp *RefundResponse, err error) {
+	if err = checkCertFilePath(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
+		return nil, err
+	}
 	err = bm.CheckEmptyError("nonce_str", "out_refund_no", "refund_fee", "op_user_id", "op_user_passwd")
 	if err != nil {
 		return nil, err

+ 1 - 1
qq/client_test.go

@@ -21,7 +21,7 @@ func TestMain(m *testing.M) {
 	//    apiKey:API秘钥值
 	client = NewClient(mchId, apiKey)
 
-	//err := client.AddCertFilePath("", "", "")
+	//err := client.AddCertFilePath(nil, nil, nil)
 	//if err != nil {
 	//	panic(err)
 	//}

+ 44 - 16
qq/param.go

@@ -22,16 +22,19 @@ import (
 //    keyFilePath:apiclient_key.pem 路径
 //    pkcs12FilePath:apiclient_cert.p12 路径
 //    返回err
-func (q *Client) AddCertFilePath(certFilePath, keyFilePath, pkcs12FilePath string) (err error) {
-	cert, err := ioutil.ReadFile(certFilePath)
+func (w *Client) AddCertFilePath(certFilePath, keyFilePath, pkcs12FilePath interface{}) (err error) {
+	if err = checkCertFilePath(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
+		return err
+	}
+	cert, err := ioutil.ReadFile(certFilePath.(string))
 	if err != nil {
 		return fmt.Errorf("ioutil.ReadFile:%w", err)
 	}
-	key, err := ioutil.ReadFile(keyFilePath)
+	key, err := ioutil.ReadFile(keyFilePath.(string))
 	if err != nil {
 		return fmt.Errorf("ioutil.ReadFile:%w", err)
 	}
-	pkcs, err := ioutil.ReadFile(pkcs12FilePath)
+	pkcs, err := ioutil.ReadFile(pkcs12FilePath.(string))
 	if err != nil {
 		return fmt.Errorf("ioutil.ReadFile:%w", err)
 	}
@@ -41,10 +44,29 @@ func (q *Client) AddCertFilePath(certFilePath, keyFilePath, pkcs12FilePath strin
 	}
 	pkcsPool := x509.NewCertPool()
 	pkcsPool.AppendCertsFromPEM(pkcs)
-	q.mu.Lock()
-	q.certificate = certificate
-	q.certPool = pkcsPool
-	q.mu.Unlock()
+	w.mu.Lock()
+	w.certificate = certificate
+	w.certPool = pkcsPool
+	w.mu.Unlock()
+	return nil
+}
+
+func checkCertFilePath(certFilePath, keyFilePath, pkcs12FilePath interface{}) error {
+	if certFilePath != nil && keyFilePath != nil && pkcs12FilePath != nil {
+		if v, ok := certFilePath.(string); !ok || v == gopay.NULL {
+			return errors.New("certFilePath not string type or is null string")
+		}
+		if v, ok := keyFilePath.(string); !ok || v == gopay.NULL {
+			return errors.New("keyFilePath not string type or is null string")
+		}
+		if v, ok := pkcs12FilePath.(string); !ok || v == gopay.NULL {
+			return errors.New("pkcs12FilePath not string type or is null string")
+		}
+		return nil
+	}
+	if !(certFilePath == nil && keyFilePath == nil && pkcs12FilePath == nil) {
+		return errors.New("cert paths must all nil or all not nil")
+	}
 	return nil
 }
 
@@ -69,9 +91,8 @@ func getReleaseSign(apiKey string, signType string, bm gopay.BodyMap) (sign stri
 	return strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
 }
 
-func (q *Client) addCertConfig(certFilePath, keyFilePath, pkcs12FilePath string) (tlsConfig *tls.Config, err error) {
-
-	if certFilePath == gopay.NULL && keyFilePath == gopay.NULL && pkcs12FilePath == gopay.NULL {
+func (q *Client) addCertConfig(certFilePath, keyFilePath, pkcs12FilePath interface{}) (tlsConfig *tls.Config, err error) {
+	if certFilePath == nil && keyFilePath == nil && pkcs12FilePath == nil {
 		q.mu.RLock()
 		defer q.mu.RUnlock()
 		if &q.certificate != nil && q.certPool != nil {
@@ -84,14 +105,22 @@ func (q *Client) addCertConfig(certFilePath, keyFilePath, pkcs12FilePath string)
 		}
 	}
 
-	if certFilePath != gopay.NULL && keyFilePath != gopay.NULL && pkcs12FilePath != gopay.NULL {
-		pkcs, err := ioutil.ReadFile(pkcs12FilePath)
+	if certFilePath != nil && keyFilePath != nil && pkcs12FilePath != nil {
+		cert, err := ioutil.ReadFile(certFilePath.(string))
+		if err != nil {
+			return nil, fmt.Errorf("ioutil.ReadFile:%w", err)
+		}
+		key, err := ioutil.ReadFile(keyFilePath.(string))
+		if err != nil {
+			return nil, fmt.Errorf("ioutil.ReadFile:%w", err)
+		}
+		pkcs, err := ioutil.ReadFile(pkcs12FilePath.(string))
 		if err != nil {
 			return nil, fmt.Errorf("ioutil.ReadFile:%w", err)
 		}
 		pkcsPool := x509.NewCertPool()
 		pkcsPool.AppendCertsFromPEM(pkcs)
-		certificate, err := tls.LoadX509KeyPair(certFilePath, keyFilePath)
+		certificate, err := tls.X509KeyPair(cert, key)
 		if err != nil {
 			return nil, fmt.Errorf("tls.LoadX509KeyPair:%w", err)
 		}
@@ -101,6 +130,5 @@ func (q *Client) addCertConfig(certFilePath, keyFilePath, pkcs12FilePath string)
 			InsecureSkipVerify: true}
 		return tlsConfig, nil
 	}
-
-	return nil, errors.New("certificate file path must be all input or all input null")
+	return nil, errors.New("cert paths must all nil or all not nil")
 }

+ 9 - 0
qq/service_api.go

@@ -1,6 +1,7 @@
 package qq
 
 import (
+	"crypto/tls"
 	"encoding/json"
 	"encoding/xml"
 	"errors"
@@ -14,6 +15,14 @@ import (
 	"github.com/iGoogle-ink/gopay"
 )
 
+// 向QQ发送Post请求,对于本库未提供的微信API,可自行实现,通过此方法发送请求
+//    bm:请求参数的BodyMap
+//    url:完整url地址,例如:https://qpay.qq.com/cgi-bin/pay/qpay_unified_order.cgi
+//    tlsConfig:tls配置,如无需证书请求,传nil
+func (q *Client) PostRequest(bm gopay.BodyMap, url string, tlsConfig *tls.Config) (bs []byte, err error) {
+	return q.doQQ(bm, url, tlsConfig)
+}
+
 // 解析QQ支付异步通知的结果到BodyMap
 //    req:*http.Request
 //    返回参数bm:Notify请求的参数

+ 51 - 37
wechat/client.go

@@ -45,10 +45,10 @@ func (w *Client) Micropay(bm gopay.BodyMap) (wxRsp *MicropayResponse, err error)
 	}
 	var bs []byte
 	if w.IsProd {
-		bs, err = w.doWeChatPostProd(bm, microPay, nil)
+		bs, err = w.doProdPost(bm, microPay, nil)
 	} else {
 		bm.Set("total_fee", 1)
-		bs, err = w.doWeChatPostSanBox(bm, sandboxMicroPay)
+		bs, err = w.doSanBoxPost(bm, sandboxMicroPay)
 	}
 	if err != nil {
 		return nil, err
@@ -68,7 +68,7 @@ func (w *Client) AuthCodeToOpenId(bm gopay.BodyMap) (wxRsp *AuthCodeToOpenIdResp
 		return nil, err
 	}
 
-	bs, err := w.doWeChatPostProd(bm, authCodeToOpenid, nil)
+	bs, err := w.doProdPost(bm, authCodeToOpenid, nil)
 	if err != nil {
 		return nil, err
 	}
@@ -88,10 +88,10 @@ func (w *Client) UnifiedOrder(bm gopay.BodyMap) (wxRsp *UnifiedOrderResponse, er
 	}
 	var bs []byte
 	if w.IsProd {
-		bs, err = w.doWeChatPostProd(bm, unifiedOrder, nil)
+		bs, err = w.doProdPost(bm, unifiedOrder, nil)
 	} else {
 		bm.Set("total_fee", 101)
-		bs, err = w.doWeChatPostSanBox(bm, sandboxUnifiedOrder)
+		bs, err = w.doSanBoxPost(bm, sandboxUnifiedOrder)
 	}
 	if err != nil {
 		return nil, err
@@ -115,9 +115,9 @@ func (w *Client) QueryOrder(bm gopay.BodyMap) (wxRsp *QueryOrderResponse, err er
 	}
 	var bs []byte
 	if w.IsProd {
-		bs, err = w.doWeChatPostProd(bm, orderQuery, nil)
+		bs, err = w.doProdPost(bm, orderQuery, nil)
 	} else {
-		bs, err = w.doWeChatPostSanBox(bm, sandboxOrderQuery)
+		bs, err = w.doSanBoxPost(bm, sandboxOrderQuery)
 	}
 	if err != nil {
 		return nil, err
@@ -138,9 +138,9 @@ func (w *Client) CloseOrder(bm gopay.BodyMap) (wxRsp *CloseOrderResponse, err er
 	}
 	var bs []byte
 	if w.IsProd {
-		bs, err = w.doWeChatPostProd(bm, closeOrder, nil)
+		bs, err = w.doProdPost(bm, closeOrder, nil)
 	} else {
-		bs, err = w.doWeChatPostSanBox(bm, sandboxCloseOrder)
+		bs, err = w.doSanBoxPost(bm, sandboxCloseOrder)
 	}
 	if err != nil {
 		return nil, err
@@ -155,7 +155,10 @@ func (w *Client) CloseOrder(bm gopay.BodyMap) (wxRsp *CloseOrderResponse, err er
 // 撤销订单
 //    注意:如已使用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) {
+func (w *Client) Reverse(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12FilePath interface{}) (wxRsp *ReverseResponse, err error) {
+	if err = checkCertFilePath(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
+		return nil, err
+	}
 	err = bm.CheckEmptyError("nonce_str", "out_trade_no")
 	if err != nil {
 		return nil, err
@@ -168,9 +171,9 @@ func (w *Client) Reverse(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12File
 		if tlsConfig, err = w.addCertConfig(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
 			return nil, err
 		}
-		bs, err = w.doWeChatPostProd(bm, reverse, tlsConfig)
+		bs, err = w.doProdPost(bm, reverse, tlsConfig)
 	} else {
-		bs, err = w.doWeChatPostSanBox(bm, sandboxReverse)
+		bs, err = w.doSanBoxPost(bm, sandboxReverse)
 	}
 	if err != nil {
 		return nil, err
@@ -185,7 +188,10 @@ func (w *Client) Reverse(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12File
 // 申请退款
 //    注意:如已使用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) {
+func (w *Client) Refund(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12FilePath interface{}) (wxRsp *RefundResponse, err error) {
+	if err = checkCertFilePath(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
+		return nil, err
+	}
 	err = bm.CheckEmptyError("nonce_str", "out_refund_no", "total_fee", "refund_fee")
 	if err != nil {
 		return nil, err
@@ -201,9 +207,9 @@ func (w *Client) Refund(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12FileP
 		if tlsConfig, err = w.addCertConfig(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
 			return nil, err
 		}
-		bs, err = w.doWeChatPostProd(bm, refund, tlsConfig)
+		bs, err = w.doProdPost(bm, refund, tlsConfig)
 	} else {
-		bs, err = w.doWeChatPostSanBox(bm, sandboxRefund)
+		bs, err = w.doSanBoxPost(bm, sandboxRefund)
 	}
 	if err != nil {
 		return nil, err
@@ -227,9 +233,9 @@ func (w *Client) QueryRefund(bm gopay.BodyMap) (wxRsp *QueryRefundResponse, err
 	}
 	var bs []byte
 	if w.IsProd {
-		bs, err = w.doWeChatPostProd(bm, refundQuery, nil)
+		bs, err = w.doProdPost(bm, refundQuery, nil)
 	} else {
-		bs, err = w.doWeChatPostSanBox(bm, sandboxRefundQuery)
+		bs, err = w.doSanBoxPost(bm, sandboxRefundQuery)
 	}
 	if err != nil {
 		return nil, err
@@ -254,9 +260,9 @@ func (w *Client) DownloadBill(bm gopay.BodyMap) (wxRsp string, err error) {
 	}
 	var bs []byte
 	if w.IsProd {
-		bs, err = w.doWeChatPostProd(bm, downloadBill, nil)
+		bs, err = w.doProdPost(bm, downloadBill, nil)
 	} else {
-		bs, err = w.doWeChatPostSanBox(bm, sandboxDownloadBill)
+		bs, err = w.doSanBoxPost(bm, sandboxDownloadBill)
 	}
 	if err != nil {
 		return gopay.NULL, err
@@ -268,7 +274,10 @@ func (w *Client) DownloadBill(bm gopay.BodyMap) (wxRsp string, err error) {
 //    注意:如已使用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) {
+func (w *Client) DownloadFundFlow(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12FilePath interface{}) (wxRsp string, err error) {
+	if err = checkCertFilePath(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
+		return gopay.NULL, err
+	}
 	err = bm.CheckEmptyError("nonce_str", "bill_date", "account_type")
 	if err != nil {
 		return gopay.NULL, err
@@ -282,7 +291,7 @@ func (w *Client) DownloadFundFlow(bm gopay.BodyMap, certFilePath, keyFilePath, p
 	if err != nil {
 		return gopay.NULL, err
 	}
-	bs, err := w.doWeChatPostProd(bm, downloadFundFlow, tlsConfig)
+	bs, err := w.doProdPost(bm, downloadFundFlow, tlsConfig)
 	if err != nil {
 		return gopay.NULL, err
 	}
@@ -304,9 +313,9 @@ func (w *Client) Report(bm gopay.BodyMap) (wxRsp *ReportResponse, err error) {
 	}
 	var bs []byte
 	if w.IsProd {
-		bs, err = w.doWeChatPostProd(bm, report, nil)
+		bs, err = w.doProdPost(bm, report, nil)
 	} else {
-		bs, err = w.doWeChatPostSanBox(bm, sandboxReport)
+		bs, err = w.doSanBoxPost(bm, sandboxReport)
 	}
 	if err != nil {
 		return nil, err
@@ -322,7 +331,10 @@ func (w *Client) Report(bm gopay.BodyMap) (wxRsp *ReportResponse, err error) {
 //    注意:如已使用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) {
+func (w *Client) BatchQueryComment(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12FilePath interface{}) (wxRsp string, err error) {
+	if err = checkCertFilePath(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
+		return gopay.NULL, err
+	}
 	err = bm.CheckEmptyError("nonce_str", "begin_time", "end_time", "offset")
 	if err != nil {
 		return gopay.NULL, err
@@ -332,7 +344,7 @@ func (w *Client) BatchQueryComment(bm gopay.BodyMap, certFilePath, keyFilePath,
 	if err != nil {
 		return gopay.NULL, err
 	}
-	bs, err := w.doWeChatPostProd(bm, batchQueryComment, tlsConfig)
+	bs, err := w.doProdPost(bm, batchQueryComment, tlsConfig)
 	if err != nil {
 		return gopay.NULL, err
 	}
@@ -340,12 +352,14 @@ func (w *Client) BatchQueryComment(bm gopay.BodyMap, certFilePath, keyFilePath,
 }
 
 // 企业向微信用户个人付款(正式)
-//    注意:如已使用client.AddCertFilePath()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",否则,3证书Path均不可空
+//    注意:如已使用client.AddCertFilePath()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传 nil,否则3证书Path均不可为nil(string类型)
 //    注意:此方法未支持沙箱环境,默认正式环境,转账请慎重
 //    文档地址: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) {
-	err = bm.CheckEmptyError("nonce_str", "partner_trade_no", "openid", "check_name", "amount", "desc", "spbill_create_ip")
-	if err != nil {
+func (w *Client) Transfer(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12FilePath interface{}) (wxRsp *TransfersResponse, err error) {
+	if err = checkCertFilePath(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
+		return nil, err
+	}
+	if err = bm.CheckEmptyError("nonce_str", "partner_trade_no", "openid", "check_name", "amount", "desc", "spbill_create_ip"); err != nil {
 		return nil, err
 	}
 	bm.Set("mch_appid", w.AppId)
@@ -383,7 +397,7 @@ func (w *Client) EntrustPublic(bm gopay.BodyMap) (wxRsp *EntrustPublicResponse,
 	if err != nil {
 		return nil, err
 	}
-	bs, err := w.doWeChatGetProd(bm, entrustPublic, SignType_MD5)
+	bs, err := w.doProdGet(bm, entrustPublic, SignType_MD5)
 	if err != nil {
 		return nil, err
 	}
@@ -401,7 +415,7 @@ func (w *Client) EntrustAppPre(bm gopay.BodyMap) (wxRsp *EntrustAppPreResponse,
 	if err != nil {
 		return nil, err
 	}
-	bs, err := w.doWeChatPostProd(bm, entrustApp, nil)
+	bs, err := w.doProdPost(bm, entrustApp, nil)
 	if err != nil {
 		return nil, err
 	}
@@ -419,7 +433,7 @@ func (w *Client) EntrustH5(bm gopay.BodyMap) (wxRsp *EntrustH5Response, err erro
 	if err != nil {
 		return nil, err
 	}
-	bs, err := w.doWeChatGetProd(bm, entrustH5, SignType_HMAC_SHA256)
+	bs, err := w.doProdGet(bm, entrustH5, SignType_HMAC_SHA256)
 	if err != nil {
 		return nil, err
 	}
@@ -440,7 +454,7 @@ func (w *Client) EntrustPaying(bm gopay.BodyMap) (wxRsp *EntrustPayingResponse,
 	if err != nil {
 		return nil, err
 	}
-	bs, err := w.doWeChatPostProd(bm, entrustPaying, nil)
+	bs, err := w.doProdPost(bm, entrustPaying, nil)
 	if err != nil {
 		return nil, err
 	}
@@ -451,8 +465,8 @@ func (w *Client) EntrustPaying(bm gopay.BodyMap) (wxRsp *EntrustPayingResponse,
 	return wxRsp, nil
 }
 
-// Post请求
-func (w *Client) doWeChatPostSanBox(bm gopay.BodyMap, path string) (bs []byte, err error) {
+// doSanBoxPost sanbox环境post请求
+func (w *Client) doSanBoxPost(bm gopay.BodyMap, path string) (bs []byte, err error) {
 	var url = baseUrlCh + path
 	w.mu.RLock()
 	defer w.mu.RUnlock()
@@ -485,7 +499,7 @@ func (w *Client) doWeChatPostSanBox(bm gopay.BodyMap, path string) (bs []byte, e
 }
 
 // Post请求、正式
-func (w *Client) doWeChatPostProd(bm gopay.BodyMap, path string, tlsConfig *tls.Config) (bs []byte, err error) {
+func (w *Client) doProdPost(bm gopay.BodyMap, path string, tlsConfig *tls.Config) (bs []byte, err error) {
 	var url = baseUrlCh + path
 	w.mu.RLock()
 	defer w.mu.RUnlock()
@@ -518,7 +532,7 @@ func (w *Client) doWeChatPostProd(bm gopay.BodyMap, path string, tlsConfig *tls.
 }
 
 // Get请求、正式
-func (w *Client) doWeChatGetProd(bm gopay.BodyMap, path, signType string) (bs []byte, err error) {
+func (w *Client) doProdGet(bm gopay.BodyMap, path, signType string) (bs []byte, err error) {
 	var url = baseUrlCh + path
 	w.mu.RLock()
 	defer w.mu.RUnlock()

+ 9 - 9
wechat/client_test.go

@@ -29,7 +29,7 @@ func TestMain(m *testing.M) {
 	// 设置国家,不设置默认就是 China
 	client.SetCountry(China)
 
-	//err := client.AddCertFilePath("", "", "")
+	//err := client.AddCertFilePath(nil, nil, nil)
 	//if err != nil {
 	//	panic(err)
 	//}
@@ -185,7 +185,7 @@ func TestClient_Refund(t *testing.T) {
 	//    certFilePath:cert证书路径
 	//    keyFilePath:Key证书路径
 	//    pkcs12FilePath:p12证书路径
-	wxRsp, err := client.Refund(bm, "", "", "")
+	wxRsp, err := client.Refund(bm, nil, nil, nil)
 	if err != nil {
 		fmt.Println("Error:", err)
 		return
@@ -219,8 +219,8 @@ func TestClient_Reverse(t *testing.T) {
 	bm.Set("out_trade_no", "6aDCor1nUcAihrV5JBlI09tLvXbUp02B")
 	bm.Set("sign_type", SignType_MD5)
 
-	// 请求撤销订单,成功后得到结果,沙箱环境下,证书路径参数可传
-	wxRsp, err := client.Reverse(bm, "", "", "")
+	// 请求撤销订单,成功后得到结果,沙箱环境下,证书路径参数可传nil
+	wxRsp, err := client.Reverse(bm, nil, nil, nil)
 	if err != nil {
 		fmt.Println("Error:", err)
 		return
@@ -245,7 +245,7 @@ func TestClient_Transfer(t *testing.T) {
 	//    certFilePath:cert证书路径
 	//    keyFilePath:Key证书路径
 	//    pkcs12FilePath:p12证书路径
-	wxRsp, err := client.Transfer(bm, "", "", "")
+	wxRsp, err := client.Transfer(bm, nil, nil, nil)
 	if err != nil {
 		fmt.Println("Error:", err)
 		return
@@ -278,8 +278,8 @@ func TestClient_DownloadFundFlow(t *testing.T) {
 	bm.Set("bill_date", "20190122")
 	bm.Set("account_type", "Basic")
 
-	// 请求下载资金账单,成功后得到结果,沙箱环境下,证书路径参数可传
-	wxRsp, err := client.DownloadFundFlow(bm, "", "", "")
+	// 请求下载资金账单,成功后得到结果,沙箱环境下,证书路径参数可传nil
+	wxRsp, err := client.DownloadFundFlow(bm, nil, nil, nil)
 	if err != nil {
 		fmt.Println("Error:", err)
 		return
@@ -296,8 +296,8 @@ func TestClient_BatchQueryComment(t *testing.T) {
 	bm.Set("end_time", "20190122174000")
 	bm.Set("offset", "0")
 
-	// 请求拉取订单评价数据,成功后得到结果,沙箱环境下,证书路径参数可传
-	wxRsp, err := client.BatchQueryComment(bm, "", "", "")
+	// 请求拉取订单评价数据,成功后得到结果,沙箱环境下,证书路径参数可传nil
+	wxRsp, err := client.BatchQueryComment(bm, nil, nil, nil)
 	if err != nil {
 		fmt.Println("Error:", err)
 		return

+ 32 - 12
wechat/param.go

@@ -45,16 +45,19 @@ func (w *Client) SetCountry(country Country) (client *Client) {
 //    keyFilePath:apiclient_key.pem 路径
 //    pkcs12FilePath:apiclient_cert.p12 路径
 //    返回err
-func (w *Client) AddCertFilePath(certFilePath, keyFilePath, pkcs12FilePath string) (err error) {
-	cert, err := ioutil.ReadFile(certFilePath)
+func (w *Client) AddCertFilePath(certFilePath, keyFilePath, pkcs12FilePath interface{}) (err error) {
+	if err = checkCertFilePath(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
+		return err
+	}
+	cert, err := ioutil.ReadFile(certFilePath.(string))
 	if err != nil {
 		return fmt.Errorf("ioutil.ReadFile:%w", err)
 	}
-	key, err := ioutil.ReadFile(keyFilePath)
+	key, err := ioutil.ReadFile(keyFilePath.(string))
 	if err != nil {
 		return fmt.Errorf("ioutil.ReadFile:%w", err)
 	}
-	pkcs, err := ioutil.ReadFile(pkcs12FilePath)
+	pkcs, err := ioutil.ReadFile(pkcs12FilePath.(string))
 	if err != nil {
 		return fmt.Errorf("ioutil.ReadFile:%w", err)
 	}
@@ -71,9 +74,8 @@ func (w *Client) AddCertFilePath(certFilePath, keyFilePath, pkcs12FilePath strin
 	return nil
 }
 
-func (w *Client) addCertConfig(certFilePath, keyFilePath, pkcs12FilePath string) (tlsConfig *tls.Config, err error) {
-
-	if certFilePath == gopay.NULL && keyFilePath == gopay.NULL && pkcs12FilePath == gopay.NULL {
+func (w *Client) addCertConfig(certFilePath, keyFilePath, pkcs12FilePath interface{}) (tlsConfig *tls.Config, err error) {
+	if certFilePath == nil && keyFilePath == nil && pkcs12FilePath == nil {
 		w.mu.RLock()
 		defer w.mu.RUnlock()
 		if &w.certificate != nil && w.certPool != nil {
@@ -86,16 +88,16 @@ func (w *Client) addCertConfig(certFilePath, keyFilePath, pkcs12FilePath string)
 		}
 	}
 
-	if certFilePath != gopay.NULL && keyFilePath != gopay.NULL && pkcs12FilePath != gopay.NULL {
-		cert, err := ioutil.ReadFile(certFilePath)
+	if certFilePath != nil && keyFilePath != nil && pkcs12FilePath != nil {
+		cert, err := ioutil.ReadFile(certFilePath.(string))
 		if err != nil {
 			return nil, fmt.Errorf("ioutil.ReadFile:%w", err)
 		}
-		key, err := ioutil.ReadFile(keyFilePath)
+		key, err := ioutil.ReadFile(keyFilePath.(string))
 		if err != nil {
 			return nil, fmt.Errorf("ioutil.ReadFile:%w", err)
 		}
-		pkcs, err := ioutil.ReadFile(pkcs12FilePath)
+		pkcs, err := ioutil.ReadFile(pkcs12FilePath.(string))
 		if err != nil {
 			return nil, fmt.Errorf("ioutil.ReadFile:%w", err)
 		}
@@ -111,8 +113,26 @@ func (w *Client) addCertConfig(certFilePath, keyFilePath, pkcs12FilePath string)
 			InsecureSkipVerify: true}
 		return tlsConfig, nil
 	}
+	return nil, errors.New("cert paths must all nil or all not nil")
+}
 
-	return nil, errors.New("certificate file path must be all input or all input null")
+func checkCertFilePath(certFilePath, keyFilePath, pkcs12FilePath interface{}) error {
+	if certFilePath != nil && keyFilePath != nil && pkcs12FilePath != nil {
+		if v, ok := certFilePath.(string); !ok || v == gopay.NULL {
+			return errors.New("certFilePath not string type or is null string")
+		}
+		if v, ok := keyFilePath.(string); !ok || v == gopay.NULL {
+			return errors.New("keyFilePath not string type or is null string")
+		}
+		if v, ok := pkcs12FilePath.(string); !ok || v == gopay.NULL {
+			return errors.New("pkcs12FilePath not string type or is null string")
+		}
+		return nil
+	}
+	if !(certFilePath == nil && keyFilePath == nil && pkcs12FilePath == nil) {
+		return errors.New("cert paths must all nil or all not nil")
+	}
+	return nil
 }
 
 // 获取微信支付正式环境Sign值

+ 9 - 0
wechat/service_api.go

@@ -6,6 +6,7 @@ import (
 	"crypto/hmac"
 	"crypto/md5"
 	"crypto/sha256"
+	"crypto/tls"
 	"encoding/base64"
 	"encoding/hex"
 	"encoding/json"
@@ -22,6 +23,14 @@ import (
 	"github.com/iGoogle-ink/gopay"
 )
 
+// 向微信发送Post请求,对于本库未提供的微信API,可自行实现,通过此方法发送请求
+//    bm:请求参数的BodyMap
+//    path:接口地址去掉baseURL的path,例如:url为https://api.mch.weixin.qq.com/pay/micropay,只需传 pay/micropay
+//    tlsConfig:tls配置,如无需证书请求,传nil
+func (w *Client) PostRequest(bm gopay.BodyMap, path string, tlsConfig *tls.Config) (bs []byte, err error) {
+	return w.doProdPost(bm, path, tlsConfig)
+}
+
 // 获取微信支付所需参数里的Sign值(通过支付参数计算Sign值)
 //    注意:BodyMap中如无 sign_type 参数,默认赋值 sign_type 为 MD5
 //    appId:应用ID