微信退款官方文档:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_4&index=6
按照接口要求,获取 API 证书,下载解压好,会有三个文件:

  1. apiclient_cert.p12
  2. apiclient_cert.pem
  3. apiclient_key.pem

我们需要用到 2、3 文件,还有一点是需要 根证书文件,这个需要单独下载,地址是:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=23_4
上面有两个根证书,下载一个即可。

代码

  1. 封装 https 双向证书 客户端 POST 请求

    1. func httpsPost(url string, contentType string, body io.Reader) (resp *http.Response, err error) {
    2. var wechatPayCert = "conf/apiclient_cert.pem" // apiclient_cert.pem 文件地址
    3. var wechatPayKey = "conf/apiclient_key.pem" // apiclient_key.pem 文件地址
    4. var rootCaPath = "conf/rootca.pem" // 根证书 文件地址
    5. var tr *http.Transport
    6. // 加载证书
    7. certs, err := tls.LoadX509KeyPair(wechatPayCert, wechatPayKey)
    8. if err != nil {
    9. glog.Errorf("tls.LoadX509KeyPair err=%v", err)
    10. return
    11. }
    12. // 读取根证书内存
    13. rootCa, err := ioutil.ReadFile(rootCaPath)
    14. if err != nil {
    15. glog.Errorf("ioutil.ReadFile err=%v", err)
    16. return
    17. }
    18. pool := x509.NewCertPool()
    19. pool.AppendCertsFromPEM(rootCa)
    20. tr = &http.Transport{
    21. TLSClientConfig: &tls.Config{
    22. RootCAs: pool,
    23. Certificates: []tls.Certificate{certs},
    24. },
    25. }
    26. client := &http.Client{Transport: tr}
    27. resp, err = client.Post(url, contentType, body)
    28. return
    29. }
  2. 使用

    1. resp, err := httpsPost("https://api.mch.weixin.qq.com/secapi/pay/refund", "text/xml;charset=utf-8", strings.NewReader(reqStr))
    2. if err != nil {
    3. glog.Errorf("[ERROR]:Https post error: %v", err)
    4. return
    5. }