Jerry 6 лет назад
Родитель
Сommit
5877e2a78a
7 измененных файлов с 350 добавлено и 75 удалено
  1. 6 1
      README.md
  2. 15 0
      body_map.go
  3. 1 0
      http_client.go
  4. 9 0
      release_note.txt
  5. 185 52
      wechat/client.go
  6. 61 0
      wechat/client_test.go
  7. 73 22
      wechat/model.go

+ 6 - 1
README.md

@@ -42,6 +42,7 @@ func main() {
     * APP - app支付
     * MWEB - H5支付
 * 提交付款码支付:client.Micropay()
+* 授权码查询OpenId:client.AuthCodeToOpenId()
 * 查询订单:client.QueryOrder()
 * 关闭订单:client.CloseOrder()
 * 撤销订单:client.Reverse()
@@ -49,8 +50,12 @@ func main() {
 * 查询退款:client.QueryRefund()
 * 下载对账单:client.DownloadBill()
 * 下载资金账单:client.DownloadFundFlow()
+* 交易保障:client.Report()
 * 拉取订单评价数据:client.BatchQueryComment()
-* 企业向微信用户个人付款:client.Transfer()
+* 企业向微信用户个人付款(正式):client.Transfer()
+* 公众号纯签约(正式):client.EntrustPublic()
+* APP纯签约-预签约接口-获取预签约ID(正式):client.EntrustAppPre()
+* H5纯签约(正式):client.EntrustH5()
 
 ### 微信公共API
 

+ 15 - 0
body_map.go

@@ -150,6 +150,21 @@ func (bm BodyMap) EncodeAliPaySignParams() string {
 	return buf.String()[:buf.Len()-1]
 }
 
+func (bm BodyMap) EncodeGetParams() string {
+	var (
+		buf strings.Builder
+	)
+	for k, _ := range bm {
+		if v := bm.Get(k); v != NULL {
+			buf.WriteString(k)
+			buf.WriteByte('=')
+			buf.WriteString(v)
+			buf.WriteByte('&')
+		}
+	}
+	return buf.String()[:buf.Len()-1]
+}
+
 func (bm BodyMap) CheckEmptyError(keys ...string) error {
 	var emptyKeys []string
 	for _, k := range keys {

+ 1 - 0
http_client.go

@@ -141,6 +141,7 @@ func (c *Client) EndStruct(v interface{}) (res *http.Response, errs []error) {
 		return nil, c.Errors
 	}
 }
+
 func (c *Client) EndBytes() (res *http.Response, bs []byte, errs []error) {
 	if len(c.Errors) > 0 {
 		return nil, nil, c.Errors

+ 9 - 0
release_note.txt

@@ -1,3 +1,12 @@
+版本号:Release 2.0.3
+发布时间:2019/12/18 16:25
+修改记录:
+   (1) 微信:新增Client方法:client.AuthCodeToOpenId(),授权码查询OpenId
+   (2) 微信:新增Client方法:client.Report(),交易保障
+   (3) 微信:新增Client方法:client.EntrustPublic(),公众号纯签约(正式)
+   (4) 微信:新增Client方法:client.EntrustAppPre(),APP纯签约-预签约接口-获取预签约ID(正式)
+   (5) 微信:新增Client方法:client.EntrustH5(),H5纯签约(正式)
+
 版本号:Release 2.0.2
 发布时间:2019/12/13 23:25
 修改记录:

+ 185 - 52
wechat/client.go

@@ -45,18 +45,41 @@ func (w *Client) Micropay(bm gopay.BodyMap) (wxRsp *MicropayResponse, err error)
 	}
 	var bs []byte
 	if w.IsProd {
-		bs, err = w.doWeChat(bm, microPay, nil)
+		bs, err = w.doWeChatPost(bm, microPay, nil)
 	} else {
-		bs, err = w.doWeChat(bm, sandboxMicroPay, nil)
+		bs, err = w.doWeChatPost(bm, sandboxMicroPay, nil)
 	}
 	if err != nil {
-		return
+		return nil, err
 	}
 	wxRsp = new(MicropayResponse)
 	if err = xml.Unmarshal(bs, wxRsp); err != nil {
 		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
-	return
+	return wxRsp, nil
+}
+
+// 授权码查询openid
+//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_13&index=9
+func (w *Client) AuthCodeToOpenId(bm gopay.BodyMap) (wxRsp *AuthCodeToOpenIdResponse, err error) {
+	err = bm.CheckEmptyError("nonce_str", "auth_code")
+	if err != nil {
+		return nil, err
+	}
+	var bs []byte
+	if w.IsProd {
+		bs, err = w.doWeChatPost(bm, authCodeToOpenid, nil)
+	} else {
+		bs, err = w.doWeChatPost(bm, sandboxAuthCodeToOpenid, nil)
+	}
+	if err != nil {
+		return nil, err
+	}
+	wxRsp = new(AuthCodeToOpenIdResponse)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
+	}
+	return wxRsp, nil
 }
 
 // 统一下单
@@ -68,19 +91,19 @@ func (w *Client) UnifiedOrder(bm gopay.BodyMap) (wxRsp *UnifiedOrderResponse, er
 	}
 	var bs []byte
 	if w.IsProd {
-		bs, err = w.doWeChat(bm, unifiedOrder, nil)
+		bs, err = w.doWeChatPost(bm, unifiedOrder, nil)
 	} else {
 		bm.Set("total_fee", 101)
-		bs, err = w.doWeChat(bm, sandboxUnifiedOrder, nil)
+		bs, err = w.doWeChatPost(bm, sandboxUnifiedOrder, nil)
 	}
 	if err != nil {
-		return
+		return nil, err
 	}
 	wxRsp = new(UnifiedOrderResponse)
 	if err = xml.Unmarshal(bs, wxRsp); err != nil {
 		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
-	return
+	return wxRsp, nil
 }
 
 // 查询订单
@@ -95,18 +118,18 @@ func (w *Client) QueryOrder(bm gopay.BodyMap) (wxRsp *QueryOrderResponse, err er
 	}
 	var bs []byte
 	if w.IsProd {
-		bs, err = w.doWeChat(bm, orderQuery, nil)
+		bs, err = w.doWeChatPost(bm, orderQuery, nil)
 	} else {
-		bs, err = w.doWeChat(bm, sandboxOrderQuery, nil)
+		bs, err = w.doWeChatPost(bm, sandboxOrderQuery, nil)
 	}
 	if err != nil {
-		return
+		return nil, err
 	}
 	wxRsp = new(QueryOrderResponse)
 	if err = xml.Unmarshal(bs, wxRsp); err != nil {
 		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
-	return
+	return wxRsp, nil
 }
 
 // 关闭订单
@@ -118,18 +141,18 @@ func (w *Client) CloseOrder(bm gopay.BodyMap) (wxRsp *CloseOrderResponse, err er
 	}
 	var bs []byte
 	if w.IsProd {
-		bs, err = w.doWeChat(bm, closeOrder, nil)
+		bs, err = w.doWeChatPost(bm, closeOrder, nil)
 	} else {
-		bs, err = w.doWeChat(bm, sandboxCloseOrder, nil)
+		bs, err = w.doWeChatPost(bm, sandboxCloseOrder, nil)
 	}
 	if err != nil {
-		return
+		return nil, err
 	}
 	wxRsp = new(CloseOrderResponse)
 	if err = xml.Unmarshal(bs, wxRsp); err != nil {
 		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
-	return
+	return wxRsp, nil
 }
 
 // 撤销订单
@@ -148,18 +171,18 @@ 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.doWeChat(bm, reverse, tlsConfig)
+		bs, err = w.doWeChatPost(bm, reverse, tlsConfig)
 	} else {
-		bs, err = w.doWeChat(bm, sandboxReverse, nil)
+		bs, err = w.doWeChatPost(bm, sandboxReverse, nil)
 	}
 	if err != nil {
-		return
+		return nil, err
 	}
 	wxRsp = new(ReverseResponse)
 	if err = xml.Unmarshal(bs, wxRsp); err != nil {
 		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
-	return
+	return wxRsp, nil
 }
 
 // 申请退款
@@ -181,18 +204,18 @@ 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.doWeChat(bm, refund, tlsConfig)
+		bs, err = w.doWeChatPost(bm, refund, tlsConfig)
 	} else {
-		bs, err = w.doWeChat(bm, sandboxRefund, nil)
+		bs, err = w.doWeChatPost(bm, sandboxRefund, nil)
 	}
 	if err != nil {
-		return
+		return nil, err
 	}
 	wxRsp = new(RefundResponse)
 	if err = xml.Unmarshal(bs, wxRsp); err != nil {
 		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
-	return
+	return wxRsp, nil
 }
 
 // 查询退款
@@ -207,18 +230,18 @@ func (w *Client) QueryRefund(bm gopay.BodyMap) (wxRsp *QueryRefundResponse, err
 	}
 	var bs []byte
 	if w.IsProd {
-		bs, err = w.doWeChat(bm, refundQuery, nil)
+		bs, err = w.doWeChatPost(bm, refundQuery, nil)
 	} else {
-		bs, err = w.doWeChat(bm, sandboxRefundQuery, nil)
+		bs, err = w.doWeChatPost(bm, sandboxRefundQuery, nil)
 	}
 	if err != nil {
-		return
+		return nil, err
 	}
 	wxRsp = new(QueryRefundResponse)
 	if err = xml.Unmarshal(bs, wxRsp); err != nil {
 		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
 	}
-	return
+	return wxRsp, nil
 }
 
 // 下载对账单
@@ -234,15 +257,14 @@ func (w *Client) DownloadBill(bm gopay.BodyMap) (wxRsp string, err error) {
 	}
 	var bs []byte
 	if w.IsProd {
-		bs, err = w.doWeChat(bm, downloadBill, nil)
+		bs, err = w.doWeChatPost(bm, downloadBill, nil)
 	} else {
-		bs, err = w.doWeChat(bm, sandboxDownloadBill, nil)
+		bs, err = w.doWeChatPost(bm, sandboxDownloadBill, nil)
 	}
 	if err != nil {
-		return
+		return gopay.NULL, err
 	}
-	wxRsp = string(bs)
-	return
+	return string(bs), nil
 }
 
 // 下载资金账单
@@ -267,17 +289,45 @@ func (w *Client) DownloadFundFlow(bm gopay.BodyMap, certFilePath, keyFilePath, p
 		if tlsConfig, err = w.addCertConfig(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
 			return gopay.NULL, err
 		}
-		bs, err = w.doWeChat(bm, downloadFundFlow, tlsConfig)
+		bs, err = w.doWeChatPost(bm, downloadFundFlow, tlsConfig)
 	} else {
-		bs, err = w.doWeChat(bm, sandboxDownloadFundFlow, nil)
+		bs, err = w.doWeChatPost(bm, sandboxDownloadFundFlow, nil)
 	}
 	if err != nil {
-		return
+		return gopay.NULL, err
 	}
 	wxRsp = string(bs)
 	return
 }
 
+// 交易保障
+//    文档地址:(JSAPI)https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_8&index=9
+//    文档地址:(付款码)https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_14&index=8
+//    文档地址:(Native)https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_8&index=9
+//    文档地址:(APP)https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_8&index=10
+//    文档地址:(H5)https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_8&index=9
+//    文档地址:(微信小程序)https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_8&index=9
+func (w *Client) Report(bm gopay.BodyMap) (wxRsp *ReportResponse, err error) {
+	err = bm.CheckEmptyError("nonce_str", "interface_url", "execute_time", "return_code", "return_msg", "result_code", "user_ip")
+	if err != nil {
+		return nil, err
+	}
+	var bs []byte
+	if w.IsProd {
+		bs, err = w.doWeChatPost(bm, report, nil)
+	} else {
+		bs, err = w.doWeChatPost(bm, sandboxReport, nil)
+	}
+	if err != nil {
+		return nil, err
+	}
+	wxRsp = new(ReportResponse)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
+	}
+	return wxRsp, nil
+}
+
 // 拉取订单评价数据
 //    注意:如已使用client.AddCertFilePath()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",否则,3证书Path均不可空
 //    貌似不支持沙箱环境,因为沙箱环境默认需要用MD5签名,但是此接口仅支持HMAC-SHA256签名
@@ -296,18 +346,17 @@ func (w *Client) BatchQueryComment(bm gopay.BodyMap, certFilePath, keyFilePath,
 		if tlsConfig, err = w.addCertConfig(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
 			return gopay.NULL, err
 		}
-		bs, err = w.doWeChat(bm, batchQueryComment, tlsConfig)
+		bs, err = w.doWeChatPost(bm, batchQueryComment, tlsConfig)
 	} else {
-		bs, err = w.doWeChat(bm, sandboxBatchQueryComment, nil)
+		bs, err = w.doWeChatPost(bm, sandboxBatchQueryComment, nil)
 	}
 	if err != nil {
-		return
+		return gopay.NULL, err
 	}
-	wxRsp = string(bs)
-	return
+	return string(bs), nil
 }
 
-// 企业向微信用户个人付款
+// 企业向微信用户个人付款(正式)
 //    注意:如已使用client.AddCertFilePath()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",否则,3证书Path均不可空
 //    注意:此方法未支持沙箱环境,默认正式环境,转账请慎重
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
@@ -344,20 +393,77 @@ func (w *Client) Transfer(bm gopay.BodyMap, certFilePath, keyFilePath, pkcs12Fil
 	return wxRsp, nil
 }
 
-// 公众号纯签约(未完成
+// 公众号纯签约(正式
 //    文档地址:https://pay.weixin.qq.com/wiki/doc/api/pap.php?chapter=18_1&index=1
-func (w *Client) EntrustPublic(bm gopay.BodyMap) (bs []byte, err error) {
-	bs, err = w.doWeChat(bm, entrustPublic, nil)
+func (w *Client) EntrustPublic(bm gopay.BodyMap) (wxRsp *EntrustPublicResponse, err error) {
+	err = bm.CheckEmptyError("plan_id", "contract_code", "request_serial", "contract_display_account", "notify_url", "version", "timestamp")
+	if err != nil {
+		return nil, err
+	}
+	bs, err := w.doWeChatGet(bm, entrustPublic, SignType_MD5)
+	if err != nil {
+		return nil, err
+	}
+	wxRsp = new(EntrustPublicResponse)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
+	}
+	return wxRsp, nil
+}
+
+// APP纯签约-预签约接口-获取预签约ID(正式)
+//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/pap.php?chapter=18_5&index=2
+func (w *Client) EntrustAppPre(bm gopay.BodyMap) (wxRsp *EntrustAppPreResponse, err error) {
+	err = bm.CheckEmptyError("plan_id", "contract_code", "request_serial", "contract_display_account", "notify_url", "version", "timestamp")
+	if err != nil {
+		return nil, err
+	}
+	var url = baseUrlCh + entrustApp
+	bm.Set("appid", w.AppId)
+	bm.Set("mch_id", w.MchId)
+	bm.Set("sign", getReleaseSign(w.ApiKey, bm.Get("sign_type"), bm))
+	httpClient := gopay.NewHttpClient().Type(gopay.TypeXML)
+	if w.BaseURL != gopay.NULL {
+		w.mu.RLock()
+		url = w.BaseURL + entrustApp
+		w.mu.RUnlock()
+	}
+	wxRsp = new(EntrustAppPreResponse)
+	res, errs := httpClient.Post(url).SendString(generateXml(bm)).EndStruct(wxRsp)
+	if len(errs) > 0 {
+		return nil, errs[0]
+	}
+	if res.StatusCode != 200 {
+		return nil, fmt.Errorf("HTTP Request Error, StatusCode = %d", res.StatusCode)
+	}
+	return wxRsp, nil
+}
 
-	return nil, nil
+// H5纯签约(正式)
+//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/pap.php?chapter=18_16&index=4
+func (w *Client) EntrustH5(bm gopay.BodyMap) (wxRsp *EntrustH5Response, err error) {
+	err = bm.CheckEmptyError("plan_id", "contract_code", "request_serial", "contract_display_account", "notify_url", "version", "timestamp", "clientip")
+	if err != nil {
+		return nil, err
+	}
+	bs, err := w.doWeChatGet(bm, entrustH5, SignType_HMAC_SHA256)
+	if err != nil {
+		return nil, err
+	}
+	wxRsp = new(EntrustH5Response)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%w", string(bs), err)
+	}
+	return wxRsp, nil
 }
 
-// 向微信发送请求
-func (w *Client) doWeChat(bm gopay.BodyMap, path string, tlsConfig *tls.Config) (bs []byte, err error) {
+// Post请求
+func (w *Client) doWeChatPost(bm gopay.BodyMap, path string, tlsConfig *tls.Config) (bs []byte, err error) {
 	var url = baseUrlCh + path
+	w.mu.RLock()
+	defer w.mu.RUnlock()
 	bm.Set("appid", w.AppId)
 	bm.Set("mch_id", w.MchId)
-
 	if bm.Get("sign") == gopay.NULL {
 		var sign string
 		if !w.IsProd {
@@ -376,21 +482,48 @@ func (w *Client) doWeChat(bm gopay.BodyMap, path string, tlsConfig *tls.Config)
 	if w.IsProd && tlsConfig != nil {
 		httpClient.SetTLSConfig(tlsConfig)
 	}
+	if w.BaseURL != gopay.NULL {
+		url = w.BaseURL + path
+	}
+	res, bs, errs := httpClient.Type(gopay.TypeXML).Post(url).SendString(generateXml(bm)).EndBytes()
+	if len(errs) > 0 {
+		return nil, errs[0]
+	}
+	if res.StatusCode != 200 {
+		return nil, fmt.Errorf("HTTP Request Error, StatusCode = %d", res.StatusCode)
+	}
+	if strings.Contains(string(bs), "HTML") || strings.Contains(string(bs), "html") {
+		return nil, errors.New(string(bs))
+	}
+	return bs, nil
+}
+
+// Get请求
+func (w *Client) doWeChatGet(bm gopay.BodyMap, path, signType string) (bs []byte, err error) {
+	var url = baseUrlCh + path
+	w.mu.RLock()
+	defer w.mu.RUnlock()
+	bm.Set("appid", w.AppId)
+	bm.Set("mch_id", w.MchId)
+	bm.Remove("sign")
+	sign := getReleaseSign(w.ApiKey, signType, bm)
+	bm.Set("sign", sign)
 
 	if w.BaseURL != gopay.NULL {
 		w.mu.RLock()
 		url = w.BaseURL + path
 		w.mu.RUnlock()
 	}
-
-	res, bs, errs := httpClient.Type(gopay.TypeXML).Post(url).SendString(generateXml(bm)).EndBytes()
+	param := bm.EncodeGetParams()
+	url = url + "?" + param
+	res, bs, errs := gopay.NewHttpClient().Get(url).EndBytes()
 	if len(errs) > 0 {
 		return nil, errs[0]
 	}
 	if res.StatusCode != 200 {
 		return nil, fmt.Errorf("HTTP Request Error, StatusCode = %d", res.StatusCode)
 	}
-	if strings.Contains(string(bs), "HTML") {
+	if strings.Contains(string(bs), "HTML") || strings.Contains(string(bs), "html") {
 		return nil, errors.New(string(bs))
 	}
 	return bs, nil

+ 61 - 0
wechat/client_test.go

@@ -292,6 +292,67 @@ func TestClient_BatchQueryComment(t *testing.T) {
 	fmt.Println("wxRsp:", wxRsp)
 }
 
+func TestClient_EntrustPublic(t *testing.T) {
+	// 初始化参数结构体
+	bm := make(gopay.BodyMap)
+	bm.Set("plan_id", "12535")
+	bm.Set("contract_code", "100000")
+	bm.Set("request_serial", "1000")
+	bm.Set("contract_display_account", "微信代扣")
+	bm.Set("notify_url", "https://www.igoogle.ink")
+	bm.Set("version", "1.0")
+	bm.Set("timestamp", time.Now().Unix())
+
+	// 公众号纯签约
+	wxRsp, err := client.EntrustPublic(bm)
+	if err != nil {
+		fmt.Println("Error:", err)
+		return
+	}
+	fmt.Println("wxRsp:", wxRsp)
+}
+
+func TestClient_EntrustAppPre(t *testing.T) {
+	// 初始化参数结构体
+	bm := make(gopay.BodyMap)
+	bm.Set("plan_id", "12535")
+	bm.Set("contract_code", "100000")
+	bm.Set("request_serial", "1000")
+	bm.Set("contract_display_account", "微信代扣")
+	bm.Set("notify_url", "https://www.igoogle.ink")
+	bm.Set("version", "1.0")
+	bm.Set("timestamp", time.Now().Unix())
+
+	// APP纯签约
+	wxRsp, err := client.EntrustAppPre(bm)
+	if err != nil {
+		fmt.Println("Error:", err)
+		return
+	}
+	fmt.Println("wxRsp:", wxRsp)
+}
+
+func TestClient_EntrustH5(t *testing.T) {
+	// 初始化参数结构体
+	bm := make(gopay.BodyMap)
+	bm.Set("plan_id", "12535")
+	bm.Set("contract_code", "100000")
+	bm.Set("request_serial", "1000")
+	bm.Set("contract_display_account", "微信代扣")
+	bm.Set("notify_url", "https://www.igoogle.ink")
+	bm.Set("version", "1.0")
+	bm.Set("timestamp", time.Now().Unix())
+	bm.Set("clientip", "127.0.0.1")
+
+	// H5纯签约
+	wxRsp, err := client.EntrustH5(bm)
+	if err != nil {
+		fmt.Println("Error:", err)
+		return
+	}
+	fmt.Println("wxRsp:", wxRsp)
+}
+
 // =======================
 
 func TestDecryptOpenDataToStruct(t *testing.T) {

+ 73 - 22
wechat/model.go

@@ -8,30 +8,33 @@ const (
 	Other         Country = 4 // 其他国家
 
 	// URL
-	baseUrlCh  = "https://api.mch.weixin.qq.com/"   //中国国内
-	baseUrlCh2 = "https://api2.mch.weixin.qq.com/"  //中国国内
-	baseUrlHk  = "https://apihk.mch.weixin.qq.com/" //东南亚
-	baseUrlUs  = "https://apius.mch.weixin.qq.com/" //其他
+	baseUrlCh  = "https://api.mch.weixin.qq.com/"   // 中国国内
+	baseUrlCh2 = "https://api2.mch.weixin.qq.com/"  // 中国国内
+	baseUrlHk  = "https://apihk.mch.weixin.qq.com/" // 东南亚
+	baseUrlUs  = "https://apius.mch.weixin.qq.com/" // 其他
 
 	// 正式
-	microPay          = "pay/micropay"                          //提交付款码支付
-	unifiedOrder      = "pay/unifiedorder"                      //统一下单
-	orderQuery        = "pay/orderquery"                        //查询订单
-	closeOrder        = "pay/closeorder"                        //关闭订单
-	refund            = "secapi/pay/refund"                     //申请退款
-	reverse           = "secapi/pay/reverse"                    //撤销订单
-	refundQuery       = "pay/refundquery"                       //查询退款
-	downloadBill      = "pay/downloadbill"                      //下载对账单
-	downloadFundFlow  = "pay/downloadfundflow"                  //下载资金账单
-	batchQueryComment = "billcommentsp/batchquerycomment"       //拉取订单评价数据
-	transfers         = "mmpaymkttransfers/promotion/transfers" //企业向微信用户个人付款
-	entrustPublic     = "papay/entrustweb"                      //公众号纯签约
-	entrustApp        = "papay/preentrustweb"                   //APP纯签约
-	entrustH5         = "papay/h5entrustweb"                    //H5纯签约
-	entrustQuery      = "papay/querycontract"                   //查询签约关系
-	entrustDelete     = "papay/deletecontract"                  //申请解约
-	entrustApplyPay   = "pay/pappayapply"                       //申请扣款
-	entrustQueryOrder = "pay/paporderquery"                     //查询扣款订单
+	microPay          = "pay/micropay"                          // 提交付款码支付
+	unifiedOrder      = "pay/unifiedorder"                      // 统一下单
+	orderQuery        = "pay/orderquery"                        // 查询订单
+	closeOrder        = "pay/closeorder"                        // 关闭订单
+	refund            = "secapi/pay/refund"                     // 申请退款
+	reverse           = "secapi/pay/reverse"                    // 撤销订单
+	refundQuery       = "pay/refundquery"                       // 查询退款
+	downloadBill      = "pay/downloadbill"                      // 下载对账单
+	downloadFundFlow  = "pay/downloadfundflow"                  // 下载资金账单
+	report            = "payitil/report"                        // 交易保障
+	batchQueryComment = "billcommentsp/batchquerycomment"       // 拉取订单评价数据
+	transfers         = "mmpaymkttransfers/promotion/transfers" // 企业向微信用户个人付款
+	authCodeToOpenid  = "tools/authcodetoopenid"                // 授权码查询openid
+	entrustPublic     = "papay/entrustweb"                      // 公众号纯签约
+	entrustApp        = "papay/preentrustweb"                   // APP纯签约
+	entrustH5         = "papay/h5entrustweb"                    // H5纯签约
+	entrustPaying     = "pay/contractorder"                     // 支付中签约
+	entrustQuery      = "papay/querycontract"                   // 查询签约关系
+	entrustApplyPay   = "pay/pappayapply"                       // 申请扣款
+	entrustDelete     = "papay/deletecontract"                  // 申请解约
+	entrustQueryOrder = "pay/paporderquery"                     // 查询扣款订单
 
 	// SanBox
 	sandboxGetSignKey        = "https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey"
@@ -44,7 +47,10 @@ const (
 	sandboxRefundQuery       = "sandboxnew/pay/refundquery"
 	sandboxDownloadBill      = "sandboxnew/pay/downloadbill"
 	sandboxDownloadFundFlow  = "sandboxnew/pay/downloadfundflow"
+	sandboxReport            = "sandboxnew/payitil/report"
 	sandboxBatchQueryComment = "sandboxnew/billcommentsp/batchquerycomment"
+	sandboxAuthCodeToOpenid  = "sandboxnew/tools/authcodetoopenid"
+	sandboxEntrustH5         = "sandboxnew/papay/h5entrustweb"
 
 	// 支付类型
 	TradeType_Mini   = "JSAPI"  // 小程序支付
@@ -288,6 +294,18 @@ type MicropayResponse struct {
 	PromotionDetail    string `xml:"promotion_detail,omitempty" json:"promotion_detail,omitempty"`
 }
 
+type AuthCodeToOpenIdResponse struct {
+	ReturnCode string `xml:"return_code,omitempty" json:"return_code,omitempty"`
+	ReturnMsg  string `xml:"return_msg,omitempty" json:"return_msg,omitempty"`
+	Appid      string `xml:"appid,omitempty" json:"appid,omitempty"`
+	MchId      string `xml:"mch_id,omitempty" json:"mch_id,omitempty"`
+	NonceStr   string `xml:"nonce_str,omitempty" json:"nonce_str,omitempty"`
+	Sign       string `xml:"sign,omitempty" json:"sign,omitempty"`
+	ResultCode string `xml:"result_code,omitempty" json:"result_code,omitempty"`
+	ErrCode    string `xml:"err_code,omitempty" json:"err_code,omitempty"`
+	Openid     string `xml:"openid,omitempty" json:"openid,omitempty"`
+}
+
 type TransfersResponse struct {
 	ReturnCode     string `xml:"return_code,omitempty" json:"return_code,omitempty"`
 	ReturnMsg      string `xml:"return_msg,omitempty" json:"return_msg,omitempty"`
@@ -303,6 +321,39 @@ type TransfersResponse struct {
 	PaymentTime    string `xml:"payment_time,omitempty" json:"payment_time,omitempty"`
 }
 
+type ReportResponse struct {
+	ReturnCode string `xml:"return_code,omitempty" json:"return_code,omitempty"`
+	ReturnMsg  string `xml:"return_msg,omitempty" json:"return_msg,omitempty"`
+	ResultCode string `xml:"result_code,omitempty" json:"result_code,omitempty"`
+}
+
+type EntrustPublicResponse struct {
+	ReturnCode string `xml:"return_code,omitempty" json:"return_code,omitempty"`
+	ReturnMsg  string `xml:"return_msg,omitempty" json:"return_msg,omitempty"`
+	ResultCode string `xml:"result_code,omitempty" json:"result_code,omitempty"`
+	ResultMsg  string `xml:"result_msg,omitempty" json:"result_msg,omitempty"`
+}
+
+type EntrustAppPreResponse struct {
+	ReturnCode      string `xml:"return_code,omitempty" json:"return_code,omitempty"`
+	ReturnMsg       string `xml:"return_msg,omitempty" json:"return_msg,omitempty"`
+	ResultCode      string `xml:"result_code,omitempty" json:"result_code,omitempty"`
+	ErrCode         string `xml:"err_code,omitempty" json:"err_code,omitempty"`
+	Appid           string `xml:"appid,omitempty" json:"appid,omitempty"`
+	MchId           string `xml:"mch_id,omitempty" json:"mch_id,omitempty"`
+	Sign            string `xml:"sign,omitempty" json:"sign,omitempty"`
+	NonceStr        string `xml:"nonce_str,omitempty" json:"nonce_str,omitempty"`
+	PreEntrustwebId string `xml:"pre_entrustweb_id,omitempty" json:"pre_entrustweb_id,omitempty"`
+}
+
+type EntrustH5Response struct {
+	ReturnCode  string `xml:"return_code,omitempty" json:"return_code,omitempty"`
+	ReturnMsg   string `xml:"return_msg,omitempty" json:"return_msg,omitempty"`
+	ResultCode  string `xml:"result_code,omitempty" json:"result_code,omitempty"`
+	ResultMsg   string `xml:"result_msg,omitempty" json:"result_msg,omitempty"`
+	RedirectUrl string `xml:"redirect_url,omitempty" json:"redirect_url,omitempty"`
+}
+
 type getSignKeyResponse struct {
 	ReturnCode     string `xml:"return_code,omitempty" json:"return_code,omitempty"`
 	ReturnMsg      string `xml:"return_msg,omitempty" json:"return_msg,omitempty"`