Explorar o código

Merge pull request #17 from iGoogle-ink/gopay/add-qq-pay

版本号:Release 2.0.0
发布时间:2019/12/12 18:22
修改记录:
   (1) 按支付渠道模块分包大调整
   (2) 一大推细小改动,不一一描述了
   (3) 支付宝:修改公共API方法:alipay.GetCertSN(),不再支持支付宝根证书的SN获取
   (4) 支付宝:新增公共API方法:alipay.GetRootCertSN(),获取root证书序列号SN
   (5) 支付宝:新增Client方法:alipay.SetLocation(),设置时区,不设置或出错均为默认服务器时间
Jerry %!s(int64=6) %!d(string=hai) anos
pai
achega
0a71210d7b
Modificáronse 63 ficheiros con 2970 adicións e 1439 borrados
  1. 217 165
      README.md
  2. 0 0
      alipay/cert/alipayCertPublicKey_RSA2.crt
  3. 0 0
      alipay/cert/alipayRootCert.crt
  4. 0 0
      alipay/cert/appCertPublicKey.crt
  5. 75 0
      alipay/cert/java_sdk.txt
  6. 152 137
      alipay/client.go
  7. 487 0
      alipay/client_test.go
  8. 55 42
      alipay/model.go
  9. 37 19
      alipay/param.go
  10. 47 45
      alipay/service_api.go
  11. 0 144
      alipay_client_test.go
  12. 41 18
      body_map.go
  13. 0 75
      constant.go
  14. 6 4
      examples/alipay/alipay_FundTransToaccountTransfer.go
  15. 5 3
      examples/alipay/alipay_OpenAuthTokenApp.go
  16. 26 17
      examples/alipay/alipay_ServiceApi.go
  17. 6 4
      examples/alipay/alipay_SystemOauthToken.go
  18. 5 3
      examples/alipay/alipay_TradeAppPay.go
  19. 5 3
      examples/alipay/alipay_TradeCancel.go
  20. 5 3
      examples/alipay/alipay_TradeClose.go
  21. 5 3
      examples/alipay/alipay_TradeCreate.go
  22. 5 3
      examples/alipay/alipay_TradeFastPayRefundQuery.go
  23. 7 5
      examples/alipay/alipay_TradeOrderSettle.go
  24. 5 3
      examples/alipay/alipay_TradePagePay.go
  25. 6 4
      examples/alipay/alipay_TradePay.go
  26. 5 3
      examples/alipay/alipay_TradePrecreate.go
  27. 5 3
      examples/alipay/alipay_TradeQuery.go
  28. 5 3
      examples/alipay/alipay_TradeRefund.go
  29. 4 3
      examples/alipay/alipay_TradeWapPay.go
  30. 5 4
      examples/alipay/alipay_UserCertifyOpenCertify.go
  31. 5 4
      examples/alipay/alipay_UserCertifyOpenInit.go
  32. 5 4
      examples/alipay/alipay_UserCertifyOpenQuery.go
  33. 7 7
      examples/alipay/alipay_UserInfoShare.go
  34. 3 1
      examples/alipay/alipay_ZhimaCreditScoreGet.go
  35. 5 5
      examples/wechat/wx_BatchQueryComment.go
  36. 5 4
      examples/wechat/wx_CloseOrder.go
  37. 4 3
      examples/wechat/wx_DownloadBill.go
  38. 5 4
      examples/wechat/wx_DownloadFundFlow.go
  39. 7 6
      examples/wechat/wx_Micropay.go
  40. 5 4
      examples/wechat/wx_QueryOrder.go
  41. 4 3
      examples/wechat/wx_QueryRefund.go
  42. 4 3
      examples/wechat/wx_Refund.go
  43. 4 3
      examples/wechat/wx_Reverse.go
  44. 21 20
      examples/wechat/wx_ServiceApi.go
  45. 3 2
      examples/wechat/wx_Transfer.go
  46. 7 5
      examples/wechat/wx_UnifiedOrder.go
  47. 20 0
      gopay_test.go
  48. 2 2
      http_client.go
  49. 0 12
      message.go
  50. 16 0
      model.go
  51. 243 0
      qq/client.go
  52. 42 0
      qq/client_test.go
  53. 207 0
      qq/model.go
  54. 117 0
      qq/param.go
  55. 39 0
      qq/service_api.go
  56. 10 1
      release_note.txt
  57. 397 0
      wechat/client.go
  58. 375 0
      wechat/client_test.go
  59. 109 50
      wechat/model.go
  60. 31 30
      wechat/param.go
  61. 47 45
      wechat/service_api.go
  62. 0 334
      wechat_client.go
  63. 0 171
      wechat_client_test.go

+ 217 - 165
README.md

@@ -3,7 +3,7 @@
 
 # GoPay
 
-微信和支付宝的Golang版本SDK
+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)
@@ -12,9 +12,17 @@
 ![Travis (.org)](https://img.shields.io/travis/iGoogle-ink/gopay)
 ![License](https://img.shields.io/github/license/iGoogle-ink/gopay)
 
-### 微信Client
+### 微信 Client
 
-* client := gopay.NewWeChatClient() => 初始化微信支付客户端
+* wechat.NewClient() => 初始化微信支付客户端
+
+```go
+import (
+	"github.com/iGoogle-ink/gopay/wechat"
+)
+
+client := wechat.NewClient()
+```
 
 ### 微信支付API
 
@@ -36,67 +44,77 @@
 
 ### 微信公共API
 
-* gopay.GetWeChatParamSign() => 获取微信支付所需参数里的Sign值(通过支付参数计算Sign值)
-* gopay.GetWeChatSanBoxParamSign() => 获取微信支付沙箱环境所需参数里的Sign值(通过支付参数计算Sign值)
-* gopay.GetMiniPaySign() => 获取微信小程序支付所需要的paySign
-* gopay.GetH5PaySign() => 获取微信内H5支付所需要的paySign
-* gopay.GetAppPaySign() => 获取APP支付所需要的paySign
-* gopay.ParseWeChatNotifyResultToBodyMap() => 解析微信支付异步通知的参数到BodyMap
-* gopay.ParseWeChatNotifyResult() => 解析微信支付异步通知的参数
-* gopay.ParseWeChatRefundNotifyResult() => 解析微信退款异步通知的参数
-* gopay.VerifyWeChatSign() => 微信同步返回参数验签或异步通知参数验签
-* gopay.Code2Session() => 登录凭证校验:获取微信用户OpenId、UnionId、SessionKey
-* gopay.GetWeChatAppletAccessToken() => 获取微信小程序全局唯一后台接口调用凭据
-* gopay.GetWeChatAppletPaidUnionId() => 微信小程序用户支付完成后,获取该用户的 UnionId,无需用户授权
-* gopay.GetWeChatUserInfo() => 微信公众号:获取用户基本信息(UnionID机制)
-* gopay.DecryptWeChatOpenDataToStruct() => 加密数据,解密到指定结构体
-* gopay.DecryptWeChatOpenDataToBodyMap() => 加密数据,解密到 BodyMap
-* gopay.GetOpenIdByAuthCode() => 授权码查询openid
-* gopay.GetAppWeChatLoginAccessToken() => App应用微信第三方登录,code换取access_token
-* gopay.RefreshAppWeChatLoginAccessToken() => 刷新App应用微信第三方登录后,获取的 access_token
-* gopay.DecryptRefundNotifyReqInfo() => 解密微信退款异步通知的加密数据
+* wechat.GetParamSign() => 获取微信支付所需参数里的Sign值(通过支付参数计算Sign值)
+* wechat.GetSanBoxParamSign() => 获取微信支付沙箱环境所需参数里的Sign值(通过支付参数计算Sign值)
+* wechat.GetMiniPaySign() => 获取微信小程序支付所需要的paySign
+* wechat.GetH5PaySign() => 获取微信内H5支付所需要的paySign
+* wechat.GetAppPaySign() => 获取APP支付所需要的paySign
+* wechat.ParseNotifyResultToBodyMap() => 解析微信支付异步通知的参数到BodyMap
+* wechat.ParseNotifyResult() => 解析微信支付异步通知的参数
+* wechat.ParseRefundNotifyResult() => 解析微信退款异步通知的参数
+* wechat.VerifySign() => 微信同步返回参数验签或异步通知参数验签
+* wechat.Code2Session() => 登录凭证校验:获取微信用户OpenId、UnionId、SessionKey
+* wechat.GetAppletAccessToken() => 获取微信小程序全局唯一后台接口调用凭据
+* wechat.GetAppletPaidUnionId() => 微信小程序用户支付完成后,获取该用户的 UnionId,无需用户授权
+* wechat.GetUserInfo() => 微信公众号:获取用户基本信息(UnionID机制)
+* wechat.DecryptOpenDataToStruct() => 加密数据,解密到指定结构体
+* wechat.DecryptOpenDataToBodyMap() => 加密数据,解密到 BodyMap
+* wechat.GetOpenIdByAuthCode() => 授权码查询openid
+* wechat.GetAppLoginAccessToken() => App应用微信第三方登录,code换取access_token
+* wechat.RefreshAppLoginAccessToken() => 刷新App应用微信第三方登录后,获取的 access_token
+* wechat.DecryptRefundNotifyReqInfo() => 解密微信退款异步通知的加密数据
 
 ---
 
-### 支付宝Client
+### 支付宝 Client
+
+* client := alipay.NewClient() => 初始化支付宝支付客户端
 
-* client := gopay.NewAliPayClient() => 初始化支付宝支付客户端
+```go
+import (
+	"github.com/iGoogle-ink/gopay/alipay"
+)
+
+client := alipay.NewClient()
+```
 
 ### 支付宝支付API
 
-* 手机网站支付接口2.0(手机网站支付):client.AliPayTradeWapPay()
-* 统一收单下单并支付页面接口(电脑网站支付):client.AliPayTradePagePay()
-* APP支付接口2.0(APP支付):client.AliPayTradeAppPay()
-* 统一收单交易支付接口(商家扫用户付款码):client.AliPayTradePay()
-* 统一收单交易创建接口(小程序支付):client.AliPayTradeCreate()
-* 统一收单线下交易查询:client.AliPayTradeQuery()
-* 统一收单交易关闭接口:client.AliPayTradeClose()
-* 统一收单交易撤销接口:client.AliPayTradeCancel()
-* 统一收单交易退款接口:client.AliPayTradeRefund()
-* 统一收单退款页面接口:client.AliPayTradePageRefund()
-* 统一收单交易退款查询:client.AliPayTradeFastPayRefundQuery()
-* 统一收单交易结算接口:client.AliPayTradeOrderSettle()
-* 统一收单线下交易预创建(用户扫商品收款码):client.AliPayTradePrecreate()
-* 单笔转账到支付宝账户接口(商户给支付宝用户转账):client.AlipayFundTransToaccountTransfer()
-* 换取授权访问令牌(获取access_token,user_id等信息):client.AliPaySystemOauthToken()
-* 支付宝会员授权信息查询接口(App支付宝登录):client.AlipayUserInfoShare()
-* 换取应用授权令牌(获取app_auth_token,auth_app_id,user_id等信息):client.AliPayOpenAuthTokenApp()
+* 手机网站支付接口2.0(手机网站支付):client.TradeWapPay()
+* 统一收单下单并支付页面接口(电脑网站支付):client.TradePagePay()
+* APP支付接口2.0(APP支付):client.TradeAppPay()
+* 统一收单交易支付接口(商家扫用户付款码):client.TradePay()
+* 统一收单交易创建接口(小程序支付):client.TradeCreate()
+* 统一收单线下交易查询:client.TradeQuery()
+* 统一收单交易关闭接口:client.TradeClose()
+* 统一收单交易撤销接口:client.TradeCancel()
+* 统一收单交易退款接口:client.TradeRefund()
+* 统一收单退款页面接口:client.TradePageRefund()
+* 统一收单交易退款查询:client.TradeFastPayRefundQuery()
+* 统一收单交易结算接口:client.TradeOrderSettle()
+* 统一收单线下交易预创建(用户扫商品收款码):client.TradePrecreate()
+* 单笔转账到支付宝账户接口(商户给支付宝用户转账):client.FundTransToaccountTransfer()
+* 换取授权访问令牌(获取access_token,user_id等信息):client.SystemOauthToken()
+* 支付宝会员授权信息查询接口(App支付宝登录):client.UserInfoShare()
+* 换取应用授权令牌(获取app_auth_token,auth_app_id,user_id等信息):client.OpenAuthTokenApp()
 * 获取芝麻信用分:client.ZhimaCreditScoreGet()
-* 身份认证初始化服务:client.AliPayUserCertifyOpenInit()
-* 身份认证开始认证(获取认证链接):client.AliPayUserCertifyOpenCertify()
-* 身份认证记录查询:client.AliPayUserCertifyOpenQuery()
+* 身份认证初始化服务:client.UserCertifyOpenInit()
+* 身份认证开始认证(获取认证链接):client.UserCertifyOpenCertify()
+* 身份认证记录查询:client.UserCertifyOpenQuery()
 
 ### 支付宝公共API
 
-* gopay.GetCertSN() => 获取证书SN号(app_cert_sn、alipay_cert_sn、alipay_root_cert_sn>
-* gopay.AliPaySystemOauthToken() => 换取授权访问令牌(得到access_token,user_id等信息)
-* gopay.FormatPrivateKey() => 格式化应用私钥
-* gopay.FormatAliPayPublicKey() => 格式化支付宝公钥
-* gopay.ParseAliPayNotifyResult() => 解析支付宝支付异步通知的参数到Struct
-* gopay.ParseAliPayNotifyResultToBodyMap() => 解析支付宝支付异步通知的参数到BodyMap
-* gopay.VerifyAliPaySign() => 支付宝异步通知参数验签
-* gopay.VerifyAliPaySyncSign() => 支付宝同步返回参数验签
-* gopay.DecryptAliPayOpenDataToStruct() => 支付宝小程序敏感加密数据解析到结构体
+* alipay.GetCertSN() => 获取证书SN号(app_cert_sn、alipay_cert_sn)
+* alipay.GetRootCertSN() => 获取证书SN号(alipay_root_cert_sn)
+* alipay.SystemOauthToken() => 换取授权访问令牌(得到access_token,user_id等信息)
+* alipay.FormatPrivateKey() => 格式化应用私钥
+* alipay.FormatPublicKey() => 格式化支付宝公钥
+* alipay.ParseNotifyResult() => 解析支付宝支付异步通知的参数到Struct
+* alipay.ParseNotifyResultToBodyMap() => 解析支付宝支付异步通知的参数到BodyMap
+* alipay.VerifySign() => 支付宝异步通知参数验签
+* alipay.VerifySyncSign() => 支付宝同步返回参数验签
+* alipay.DecryptOpenDataToStruct() => 解密支付宝开放数据到 结构体
+* alipay.DecryptOpenDataToBodyMap() => 解密支付宝开放数据到 BodyMap
 
 # 一、安装
 
@@ -106,11 +124,11 @@ $ go get -u github.com/iGoogle-ink/gopay
 
 * #### 查看 GoPay 版本
     * [版本更新记录](https://github.com/iGoogle-ink/gopay/blob/master/release_note.txt)
+    * 2.0+ 版本未经严格测试,如若有问题,请提交PR修复或切回 v1.4.8
 ```go
-package main
-
 import (
     "fmt"
+
     "github.com/iGoogle-ink/gopay"
 )
 
@@ -122,7 +140,8 @@ func main() {
 # 二、文档说明
 
 * [GoDoc](https://godoc.org/github.com/iGoogle-ink/gopay)
-* 所有方法,如有问题,请仔细查看 examples
+* QQ支付 使用方法请参考微信的
+* 所有方法,如有问题,请仔细查看 wechat_client_test.go、alipay_client_test.go 或 examples
 * 有问题请加QQ群(加群验证答案:gopay)。在此,非常感谢那些加群后,提出意见和反馈问题的同志们!
 
 QQ群:
@@ -132,18 +151,22 @@ QQ群:
 
 ---
 
-## 1、初始化GoPay客户端并做配置(HTTP请求均设置tls.Config{InsecureSkipVerify: true})
+## 1、初始化GoPay客户端并做配置(HTTP请求均默认设置tls.Config{InsecureSkipVerify: true})
 
 * #### 微信客户端,如无需更改Appid、Mchid和ApiKey等参数,可在init()方法中初始化,全局适用
 
 微信官方文档:[官方文档](https://pay.weixin.qq.com/wiki/doc/api/index.html)
 ```go
+import (
+	"github.com/iGoogle-ink/gopay/wechat"
+)
+
 // 初始化微信客户端
 //    appId:应用ID
 //    mchId:商户ID
 //    apiKey:API秘钥值
 //    isProd:是否是正式环境
-client := gopay.NewWeChatClient("wxdaa2ab9ef87b5497", mchId, apiKey, false)
+client := wechat.NewClient("wxdaa2ab9ef87b5497", mchId, apiKey, false)
 
 // 设置国家:不设置默认 中国国内
 //    gopay.China:中国国内
@@ -176,23 +199,28 @@ client.AddCertFilePath()
 沙箱环境使用说明:[文档地址](https://docs.open.alipay.com/200/105311)
 
 ```go
-//初始化支付宝客户端
+import (
+	"github.com/iGoogle-ink/gopay/alipay"
+)
+
+// 初始化支付宝客户端
 //    appId:应用ID
 //    privateKey:应用秘钥
 //    isProd:是否是正式环境
-client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+client := alipay.NewClient("2016091200494382", privateKey, false)
 
-//设置支付宝请求 公共参数
+// 设置支付宝请求 公共参数
 //    注意:具体设置哪些参数,根据不同的方法而不同,此处列举出所以设置参数
-client.SetAliPayRootCertSN().               //设置支付宝根证书SN,通过 gopay.GetRootCertSN() 获取
-    SetAppCertSN().                         //设置应用公钥证书SN,通过 gopay.GetCertSN() 获取
+client.SetLocation().                       // 设置时区,不设置或出错均为默认服务器时间
+    SetAliPayRootCertSN().                  // 设置支付宝根证书SN,通过 alipay.GetRootCertSN() 获取
+    SetAppCertSN().                         // 设置应用公钥证书SN,通过 alipay.GetCertSN() 获取
     SetAliPayPublicCertSN().                // 设置支付宝公钥证书SN,通过 alipay.GetCertSN() 获取
-    SetCharset("utf-8").                    //设置字符编码,不设置默认 utf-8
-    SetSignType("RSA2").                    //设置签名类型,不设置默认 RSA2
-    SetReturnUrl("https://www.gopay.ink").  //设置返回URL
-    SetNotifyUrl("https://www.gopay.ink").  //设置异步通知URL
-    SetAppAuthToken().                      //设置第三方应用授权
-    SetAuthToken()                          //设置个人信息授权
+    SetCharset("utf-8").                    // 设置字符编码,不设置默认 utf-8
+    SetSignType("RSA2").                    // 设置签名类型,不设置默认 RSA2
+    SetReturnUrl("https://www.gopay.ink").  // 设置返回URL
+    SetNotifyUrl("https://www.gopay.ink").  // 设置异步通知URL
+    SetAppAuthToken().                      // 设置第三方应用授权
+    SetAuthToken()                          // 设置个人信息授权
 
 err := client.SetCertSnByPath("appCertPublicKey.crt", "alipayRootCert.crt", "alipayCertPublicKey_RSA2.crt")
 ```
@@ -203,7 +231,11 @@ err := client.SetCertSnByPath("appCertPublicKey.crt", "alipayRootCert.crt", "ali
 
 具体参数请根据不同接口查看:[微信支付接口文档](https://pay.weixin.qq.com/wiki/doc/api/index.html)
 ```go
-//初始化 BodyMap
+import (
+	"github.com/iGoogle-ink/gopay/wechat"
+)
+
+// 初始化 BodyMap
 bm := make(gopay.BodyMap)
 bm.Set("nonce_str", gopay.GetRandomString(32))
 bm.Set("body", "小程序测试支付")
@@ -216,7 +248,7 @@ bm.Set("device_info", "WEB")
 bm.Set("sign_type", gopay.SignType_MD5)
 bm.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")
 
-//嵌套json格式数据(例如:H5支付的 scene_info 参数)
+// 嵌套json格式数据(例如:H5支付的 scene_info 参数)
 h5Info := make(map[string]string)
 h5Info["type"] = "Wap"
 h5Info["wap_url"] = "http://www.gopay.ink"
@@ -227,10 +259,10 @@ sceneInfo["h5_info"] = h5Info
 
 bm.Set("scene_info", sceneInfo)
 
-//参数 sign ,可单独生成赋值到BodyMap中;也可不传sign参数,client内部会自动获取
-//如需单独赋值 sign 参数,需通过下面方法,最后获取sign值并在最后赋值此参数
-sign := gopay.GetWeChatParamSign("wxdaa2ab9ef87b5497", mchId, apiKey, body)
-//sign, _ := gopay.GetWeChatSanBoxParamSign("wxdaa2ab9ef87b5497", mchId, apiKey, body)
+// 参数 sign ,可单独生成赋值到BodyMap中;也可不传sign参数,client内部会自动获取
+// 如需单独赋值 sign 参数,需通过下面方法,最后获取sign值并在最后赋值此参数
+sign := wechat.GetParamSign("wxdaa2ab9ef87b5497", mchId, apiKey, body)
+// sign, _ := wechat.GetSanBoxParamSign("wxdaa2ab9ef87b5497", mchId, apiKey, body)
 bm.Set("sign", sign)
 ```
 
@@ -238,8 +270,7 @@ bm.Set("sign", sign)
 
 具体参数请根据不同接口查看:[支付宝支付API接口文档](https://docs.open.alipay.com/api_1/alipay.trade.wap.pay)
 ```go
-//此时李
-//初始化 BodyMap
+// 初始化 BodyMap
 bm := make(gopay.BodyMap)
 bm.Set("subject", "手机网站测试支付")
 bm.Set("out_trade_no", "GZ201901301040355703")
@@ -267,38 +298,38 @@ wxRsp, err := client.Transfer(bm, "apiclient_cert.pem", "apiclient_key.pem", "ap
 
 * #### 支付宝 client
 ```go
-//手机网站支付是通过服务端获取支付URL后,然后返回给客户端,请求URL地址即可打开支付页面
-payUrl, err := client.AliPayTradeWapPay(bm)
-
-//电脑网站支付是通过服务端获取支付URL后,然后返回给客户端,请求URL地址即可打开支付页面
-payUrl, err := client.AliPayTradePagePay(bm)
-
-//APP支付是通过服务端获取支付参数后,然后通过Android/iOS客户端的SDK调用支付功能
-payParam, err := client.AliPayTradeAppPay(bm)
-
-//商家使用扫码枪等条码识别设备扫描用户支付宝钱包上的条码/二维码,完成收款
-aliRsp, err := client.AliPayTradePay(bm)
-
-//支付宝小程序支付时 buyer_id 为必传参数,需要提前获取,获取方法如下两种
-//    1、gopay.AliPaySystemOauthToken()     返回取值:rsp.AliPaySystemOauthTokenResponse.UserId
-//    2、client.AliPaySystemOauthToken()    返回取值:aliRsp.AliPaySystemOauthTokenResponse.UserId
-aliRsp, err := client.AliPayTradeCreate(bm)
-
-aliRsp, err := client.AliPayTradeQuery(bm)
-aliRsp, err := client.AliPayTradeClose(bm)
-aliRsp, err := client.AliPayTradeCancel(bm)
-aliRsp, err := client.AliPayTradeRefund(bm)
-aliRsp, err := client.AliPayTradePageRefund(bm)
-aliRsp, err := client.AliPayTradeFastPayRefundQuery(bm)
-aliRsp, err := client.AliPayTradeOrderSettle(bm)
-aliRsp, err := client.AliPayTradePrecreate(bm)
-aliRsp, err := client.AlipayFundTransToaccountTransfer(bm)
-aliRsp, err := client.AliPaySystemOauthToken(bm)
-aliRsp, err := client.AliPayOpenAuthTokenApp(bm)
+// 手机网站支付是通过服务端获取支付URL后,然后返回给客户端,请求URL地址即可打开支付页面
+payUrl, err := client.TradeWapPay(bm)
+
+// 电脑网站支付是通过服务端获取支付URL后,然后返回给客户端,请求URL地址即可打开支付页面
+payUrl, err := client.TradePagePay(bm)
+
+// APP支付是通过服务端获取支付参数后,然后通过Android/iOS客户端的SDK调用支付功能
+payParam, err := client.TradeAppPay(bm)
+
+// 商家使用扫码枪等条码识别设备扫描用户支付宝钱包上的条码/二维码,完成收款
+aliRsp, err := client.TradePay(bm)
+
+// 支付宝小程序支付时 buyer_id 为必传参数,需要提前获取,获取方法如下两种
+//    1、gopay.SystemOauthToken()     返回取值:rsp.SystemOauthTokenResponse.UserId
+//    2、client.SystemOauthToken()    返回取值:aliRsp.SystemOauthTokenResponse.UserId
+aliRsp, err := client.TradeCreate(bm)
+
+aliRsp, err := client.TradeQuery(bm)
+aliRsp, err := client.TradeClose(bm)
+aliRsp, err := client.TradeCancel(bm)
+aliRsp, err := client.TradeRefund(bm)
+aliRsp, err := client.TradePageRefund(bm)
+aliRsp, err := client.TradeFastPayRefundQuery(bm)
+aliRsp, err := client.TradeOrderSettle(bm)
+aliRsp, err := client.TradePrecreate(bm)
+aliRsp, err := client.FundTransToaccountTransfer(bm)
+aliRsp, err := client.SystemOauthToken(bm)
+aliRsp, err := client.OpenAuthTokenApp(bm)
 aliRsp, err := client.ZhimaCreditScoreGet(bm)
-aliRsp, err := client.AliPayUserCertifyOpenInit(bm)
-aliRsp, err := client.AliPayUserCertifyOpenCertify(bm)
-aliRsp, err := client.AliPayUserCertifyOpenQuery(bm)
+aliRsp, err := client.UserCertifyOpenInit(bm)
+aliRsp, err := client.UserCertifyOpenCertify(bm)
+aliRsp, err := client.UserCertifyOpenQuery(bm)
 ```
 
 ## 4、微信统一下单后,获取微信小程序支付、APP支付、微信内H5支付所需要的 paySign
@@ -310,42 +341,46 @@ APP支付官方文档:[APP端调起支付的参数列表文档](https://pay.we
 
 微信内H5支付官方文档:[微信内H5支付文档](https://pay.weixin.qq.com/wiki/doc/api/external/jsapi.php?chapter=7_7&index=6)
 ```go
-//====微信小程序 paySign====
+import (
+	"github.com/iGoogle-ink/gopay/wechat"
+)
+
+// ====微信小程序 paySign====
 timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
-prepayId := "prepay_id=" + wxRsp.PrepayId   //此处的 wxRsp.PrepayId ,统一下单成功后得到
-//获取微信小程序支付的 paySign
-//    appId:APPID
+prepayId := "prepay_id=" + wxRsp.PrepayId   // 此处的 wxRsp.PrepayId ,统一下单成功后得到
+// 获取微信小程序支付的 paySign
+//    appId:AppID
 //    nonceStr:随机字符串
 //    prepayId:统一下单成功后得到的值
 //    signType:签名方式,务必与统一下单时用的签名方式一致
 //    timeStamp:时间
 //    apiKey:API秘钥值
-paySign := gopay.GetMiniPaySign(AppID, wxRsp.NonceStr, prepayId, gopay.SignType_MD5, timeStamp, apiKey)
+paySign := wechat.GetMiniPaySign(AppID, wxRsp.NonceStr, prepayId, wechat.SignType_MD5, timeStamp, apiKey)
 
-//====APP支付 paySign====
+// ====APP支付 paySign====
 timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
-//获取APP支付的 paySign
-//注意:package 参数因为是固定值,无需开发者再传入
-//    appId:APPID
+// 获取APP支付的 paySign
+// 注意:package 参数因为是固定值,无需开发者再传入
+//    appId:AppID
 //    partnerid:partnerid
 //    nonceStr:随机字符串
 //    prepayId:统一下单成功后得到的值
 //    signType:签名方式,务必与统一下单时用的签名方式一致
 //    timeStamp:时间
 //    apiKey:API秘钥值
-paySign := gopay.GetAppPaySign(appid, partnerid, wxRsp.NonceStr, wxRsp.PrepayId, gopay.SignType_MD5, timeStamp, apiKey)
+paySign := wechat.GetAppPaySign(appid, partnerid, wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, apiKey)
 
-//====微信内H5支付 paySign====
+// ====微信内H5支付 paySign====
 timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
-packages := "prepay_id=" + wxRsp.PrepayId   //此处的 wxRsp.PrepayId ,统一下单成功后得到
-//获取微信内H5支付 paySign
-//    appId:APPID
+packages := "prepay_id=" + wxRsp.PrepayId   // 此处的 wxRsp.PrepayId ,统一下单成功后得到
+// 获取微信内H5支付 paySign
+//    appId:AppID
 //    nonceStr:随机字符串
 //    packages:统一下单成功后拼接得到的值
 //    signType:签名方式,务必与统一下单时用的签名方式一致
 //    timeStamp:时间
 //    apiKey:API秘钥值
-paySign := gopay.GetMiniPaySign(AppID, wxRsp.NonceStr, packages, gopay.SignType_MD5, timeStamp, apiKey)
+paySign := wechat.GetH5PaySign(AppID, wxRsp.NonceStr, packages, wechat.SignType_MD5, timeStamp, apiKey)
 ```
 
 ## 5、同步返回参数验签Sign、异步通知参数解析和验签Sign、异步通知返回
@@ -358,7 +393,12 @@ paySign := gopay.GetMiniPaySign(AppID, wxRsp.NonceStr, packages, gopay.SignType_
 
 * #### 微信
 ```go
-//====同步返回参数验签Sign====
+import (
+	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/wechat"
+)
+
+// ====同步返回参数验签Sign====
 wxRsp, err := client.UnifiedOrder(bm)
 // 微信同步返回参数验签或异步通知参数验签
 //    apiKey:API秘钥值
@@ -366,33 +406,33 @@ wxRsp, err := client.UnifiedOrder(bm)
 //    bean:微信同步返回的结构体 wxRsp 或 异步通知解析的结构体 notifyReq
 //    返回参数 ok:是否验签通过
 //    返回参数 err:错误信息
-ok, err := gopay.VerifyWeChatSign(apiKey, gopay.SignType_MD5, wxRsp)
+ok, err := wechat.VerifySign(apiKey, wechat.SignType_MD5, wxRsp)
 
-//====支付异步通知参数解析和验签Sign====
+// ====支付异步通知参数解析和验签Sign====
 // 解析支付异步通知的参数
 //    req:*http.Request
 //    返回参数 notifyReq:通知的参数
 //    返回参数 err:错误信息
-notifyReq, err := gopay.ParseWeChatNotifyResult(c.Request())    //c.Request()是 echo 框架的获取 *http.Request 的写法
-//验签操作
-ok, err := gopay.VerifyWeChatSign(apiKey, gopay.SignType_MD5, notifyReq)
+notifyReq, err := wechat.ParseNotifyResult(c.Request())    // c.Request()是 echo 框架的获取 *http.Request 的写法
+// 验签操作
+ok, err := wechat.VerifySign(apiKey, wechat.SignType_MD5, notifyReq)
 
-//====退款异步通知参数解析,退款通知无sign,不用验签====
+// ====退款异步通知参数解析,退款通知无sign,不用验签====
 // 
 // 解析退款异步通知的参数,解析出来的 req_info 是加密数据,需解密
 //    req:*http.Request
 //    返回参数 notifyReq:通知的参数
 //    返回参数 err:错误信息
-notifyReq, err := gopay.ParseWeChatRefundNotifyResult(c.Request())
+notifyReq, err := wechat.ParseRefundNotifyResult(c.Request())
 
-//==解密退款异步通知的加密参数 req_info ==
-refundNotify, err := gopay.DecryptRefundNotifyReqInfo(notifyReq.ReqInfo, apiKey)
+// ==解密退款异步通知的加密参数 req_info ==
+refundNotify, err := wechat.DecryptRefundNotifyReqInfo(notifyReq.ReqInfo, apiKey)
 
-//==异步通知,返回给微信平台的信息==
-rsp := new(gopay.WeChatNotifyResponse) //回复微信的数据
+// ==异步通知,返回给微信平台的信息==
+rsp := new(wechat.NotifyResponse) // 回复微信的数据
 rsp.ReturnCode = gopay.SUCCESS
 rsp.ReturnMsg = gopay.OK
-return c.String(http.StatusOK, rsp.ToXmlString())   //此写法是 echo 框架返回客户端数据的写法
+return c.String(http.StatusOK, rsp.ToXmlString())   // 此写法是 echo 框架返回客户端数据的写法
 ```
 
 * #### 支付宝
@@ -401,30 +441,34 @@ return c.String(http.StatusOK, rsp.ToXmlString())   //此写法是 echo 框架
 
 支付宝支付后的同步/异步通知验签文档:[支付结果通知](https://docs.open.alipay.com/200/106120)
 ```go
-//====同步返回参数验签Sign====
-aliRsp, err := client.AliPayTradePay(bm)
-//支付宝同步返回验签
+import (
+	"github.com/iGoogle-ink/gopay/alipay"
+)
+
+// ====同步返回参数验签Sign====
+aliRsp, err := client.TradePay(bm)
+// 支付宝同步返回验签
 //    注意:APP支付,手机网站支付,电脑网站支付 暂不支持同步返回验签
 //    aliPayPublicKey:支付宝公钥
 //    signData:待验签参数,aliRsp.SignData
 //    sign:待验签sign,aliRsp.Sign
 //    返回参数ok:是否验签通过
 //    返回参数err:错误信息
-ok, err := gopay.VerifyAliPaySyncSign(aliPayPublicKey, aliRsp.SignData, aliRsp.Sign)
+ok, err := alipay.VerifySyncSign(aliPayPublicKey, aliRsp.SignData, aliRsp.Sign)
 
-//====异步通知参数解析和验签Sign====
-//解析异步通知的参数
+// ====异步通知参数解析和验签Sign====
+// 解析异步通知的参数
 //    req:*http.Request
 //    返回参数 notifyReq:通知的参数
 //    返回参数 err:错误信息
-notifyReq, err = gopay.ParseAliPayNotifyResult(c.Request())     //c.Request()是 echo 框架的获取
-//验签操作
-ok, err = gopay.VerifyAliPaySign(aliPayPublicKey, notifyReq)
+notifyReq, err = alipay.ParseNotifyResult(c.Request())     // c.Request()是 echo 框架的获取
+// 验签操作
+ok, err = alipay.VerifySign(aliPayPublicKey, notifyReq)
 
-//==异步通知,返回支付宝平台的信息==
+// ==异步通知,返回支付宝平台的信息==
 //    文档:https://docs.open.alipay.com/203/105286
 //    程序执行完后必须打印输出“success”(不包含引号)。如果商户反馈给支付宝的字符不是success这7个字符,支付宝服务器会不断重发通知,直到超过24小时22分钟。一般情况下,25小时以内完成8次通知(通知的间隔频率一般是:4m,10m,10m,1h,2h,6h,15h)
-return c.String(http.StatusOK, "success")   //此写法是 echo 框架返回客户端数据的写法
+return c.String(http.StatusOK, "success")   // 此写法是 echo 框架返回客户端数据的写法
 ```
 
 ## 6、微信、支付宝 公共API(仅部分说明)
@@ -437,45 +481,49 @@ button按钮获取手机号码:[button组件文档](https://developers.weixin.
 
 微信解密算法文档:[解密算法文档](https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html)
 ```go
-//获取微信小程序用户的OpenId、SessionKey、UnionId
+import (
+	"github.com/iGoogle-ink/gopay/wechat"
+)
+
+// 获取微信小程序用户的OpenId、SessionKey、UnionId
 //    appId:微信小程序的APPID
 //    appSecret:微信小程序的AppSecret
 //    wxCode:小程序调用wx.login 获取的code
-sessionRsp, err := gopay.Code2Session(appId, appSecret, wxCode)
+sessionRsp, err := wechat.Code2Session(appId, appSecret, wxCode)
 
-//====解密微信加密数据到指定结构体====
+// ====解密微信加密数据到指定结构体====
 
 //小程序获取手机号
 data := "Kf3TdPbzEmhWMuPKtlKxIWDkijhn402w1bxoHL4kLdcKr6jT1jNcIhvDJfjXmJcgDWLjmBiIGJ5acUuSvxLws3WgAkERmtTuiCG10CKLsJiR+AXVk7B2TUQzsq88YVilDz/YAN3647REE7glGmeBPfvUmdbfDzhL9BzvEiuRhABuCYyTMz4iaM8hFjbLB1caaeoOlykYAFMWC5pZi9P8uw=="
 iv := "Cds8j3VYoGvnTp1BrjXdJg=="
 session := "lyY4HPQbaOYzZdG+JcYK9w=="
-phone := new(gopay.WeChatUserPhone)
-//解密开放数据
+phone := new(wechat.UserPhone)
+// 解密开放数据
 //    encryptedData:包括敏感数据在内的完整用户信息的加密数据,小程序获取到
 //    iv:加密算法的初始向量,小程序获取到
 //    sessionKey:会话密钥,通过 gopay.Code2Session() 方法获取到
 //    beanPtr:需要解析到的结构体指针,操作完后,声明的结构体会被赋值
-err := gopay.DecryptWeChatOpenDataToStruct(data, iv, session, phone)
+err := wechat.DecryptOpenDataToStruct(data, iv, session, phone)
 fmt.Println(*phone)
-//获取微信小程序用户信息
+// 获取微信小程序用户信息
 sessionKey := "tiihtNczf5v6AKRyjwEUhQ=="
 encryptedData := "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZMQmRzooG2xrDcvSnxIMXFufNstNGTyaGS9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+3hVbJSRgv+4lGOETKUQz6OYStslQ142dNCuabNPGBzlooOmB231qMM85d2/fV6ChevvXvQP8Hkue1poOFtnEtpyxVLW1zAo6/1Xx1COxFvrc2d7UL/lmHInNlxuacJXwu0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn/Hz7saL8xz+W//FRAUid1OksQaQx4CMs8LOddcQhULW4ucetDf96JcR3g0gfRK4PC7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns/8wR2SiRS7MNACwTyrGvt9ts8p12PKFdlqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYVoKlaRv85IfVunYzO0IKXsyl7JCUjCpoG20f0a04COwfneQAGGwd5oa+T8yO5hzuyDb/XcxxmK01EpqOyuxINew=="
 iv2 := "r7BXXKkLb8qrSNn05n0qiA=="
 
-//微信小程序 用户信息
-userInfo := new(gopay.WeChatAppletUserInfo)
-err = gopay.DecryptWeChatOpenDataToStruct(encryptedData, iv2, sessionKey, userInfo)
+// 微信小程序 用户信息
+userInfo := new(wechat.AppletUserInfo)
+err = wechat.DecryptOpenDataToStruct(encryptedData, iv2, sessionKey, userInfo)
 fmt.Println(*userInfo)
 
 data := "Kf3TdPbzEmhWMuPKtlKxIWDkijhn402w1bxoHL4kLdcKr6jT1jNcIhvDJfjXmJcgDWLjmBiIGJ5acUuSvxLws3WgAkERmtTuiCG10CKLsJiR+AXVk7B2TUQzsq88YVilDz/YAN3647REE7glGmeBPfvUmdbfDzhL9BzvEiuRhABuCYyTMz4iaM8hFjbLB1caaeoOlykYAFMWC5pZi9P8uw=="
 iv := "Cds8j3VYoGvnTp1BrjXdJg=="
 session := "lyY4HPQbaOYzZdG+JcYK9w=="
     
-//解密开放数据到 BodyMap
+// 解密开放数据到 BodyMap
 //    encryptedData:包括敏感数据在内的完整用户信息的加密数据
 //    iv:加密算法的初始向量
 //    sessionKey:会话密钥
-bm, err := gopay.DecryptWeChatOpenDataToBodyMap(data, iv, session)
+bm, err := wechat.DecryptOpenDataToBodyMap(data, iv, session)
 if err != nil {
      fmt.Println("err:", err)
      return
@@ -491,21 +539,25 @@ fmt.Println("WeChatUserPhone:", bm)
 
 支付宝加解密文档:[AES配置文档](https://docs.alipay.com/mini/introduce/aes),[AES加解密文档](https://docs.open.alipay.com/common/104567)
 ```go
-//换取授权访问令牌(默认使用utf-8,RSA2)
+import (
+	"github.com/iGoogle-ink/gopay/alipay"
+)
+
+// 换取授权访问令牌(默认使用utf-8,RSA2)
 //    appId:应用ID
 //    privateKey:应用私钥
 //    grantType:值为 authorization_code 时,代表用code换取;值为 refresh_token 时,代表用refresh_token换取,传空默认code换取
 //    codeOrToken:支付宝授权码或refresh_token
-rsp, err := gopay.AlipaySystemOauthToken(appId, privateKey, grantType, codeOrToken)
+rsp, err := alipay.SystemOauthToken(appId, privateKey, grantType, codeOrToken)
 
-//解密支付宝开放数据带到指定结构体
+// 解密支付宝开放数据带到指定结构体
 //    以小程序获取手机号为例
-phone := new(gopay.AliPayUserPhone)
-//解密支付宝开放数据
+phone := new(alipay.UserPhone)
+// 解密支付宝开放数据
 //    encryptedData:包括敏感数据在内的完整用户信息的加密数据
 //    secretKey:AES密钥,支付宝管理平台配置
 //    beanPtr:需要解析到的结构体指针
-err := gopay.DecryptAliPayOpenDataToStruct(encryptedData, secretKey, phone)
+err := alipay.DecryptOpenDataToStruct(encryptedData, secretKey, phone)
 fmt.Println(*phone)
 ```
 

+ 0 - 0
alipay_cert/alipayCertPublicKey_RSA2.crt → alipay/cert/alipayCertPublicKey_RSA2.crt


+ 0 - 0
alipay_cert/alipayRootCert.crt → alipay/cert/alipayRootCert.crt


+ 0 - 0
alipay_cert/appCertPublicKey.crt → alipay/cert/appCertPublicKey.crt


+ 75 - 0
alipay/cert/java_sdk.txt

@@ -0,0 +1,75 @@
+
+// Java SDK 获取Root证书SN  AntCertificationUtil.getRootCertSN();
+/**
+ * 从公钥证书中提取公钥序列号
+ *
+ * @param certPath 公钥证书存放路径,例如:/home/admin/cert.crt
+ * @return 公钥证书序列号
+ * @throws AlipayApiException
+ */
+public static String getCertSN(String certPath) throws AlipayApiException {
+    InputStream inputStream = null;
+    try {
+        inputStream = new FileInputStream(certPath);
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
+        MessageDigest md = MessageDigest.getInstance("MD5");
+        md.update((cert.getIssuerX500Principal().getName() + cert.getSerialNumber()).getBytes());
+        String certSN = new BigInteger(1, md.digest()).toString(16);
+        //BigInteger会把0省略掉,需补全至32位
+        certSN = fillMD5(certSN);
+        return certSN;
+
+    } catch (NoSuchAlgorithmException e) {
+        throw new AlipayApiException(e);
+    } catch (IOException e) {
+        throw new AlipayApiException(e);
+    } catch (CertificateException e) {
+        throw new AlipayApiException(e);
+    } finally {
+        try {
+            if (inputStream != null) {
+                inputStream.close();
+            }
+        } catch (IOException e) {
+            throw new AlipayApiException(e);
+        }
+    }
+}
+
+// Java SDK 获取证书SN  AlipaySignature.getCertSN();
+/**
+ * 获取根证书序列号
+ *
+ * @param rootCertContent
+ * @return
+ */
+public static String getRootCertSN(String rootCertContent) {
+    String rootCertSN = null;
+    try {
+        X509Certificate[] x509Certificates = readPemCertChain(rootCertContent);
+        MessageDigest md = MessageDigest.getInstance("MD5");
+        for (X509Certificate c : x509Certificates) {
+            if (c.getSigAlgOID().startsWith("1.2.840.113549.1.1")) {
+                md.update((c.getIssuerX500Principal().getName() + c.getSerialNumber()).getBytes());
+                String certSN = new BigInteger(1, md.digest()).toString(16);
+                //BigInteger会把0省略掉,需补全至32位
+                certSN = fillMD5(certSN);
+                if (StringUtils.isEmpty(rootCertSN)) {
+                    rootCertSN = certSN;
+                } else {
+                    rootCertSN = rootCertSN + "_" + certSN;
+                }
+            }
+
+        }
+    } catch (Exception e) {
+        AlipayLogger.logBizError(("提取根证书失败"));
+    }
+    return rootCertSN;
+
+}
+
+private static String fillMD5(String md5) {
+    return md5.length() == 32 ? md5 : fillMD5("0" + md5);
+}

+ 152 - 137
alipay_client.go → alipay/client.go

@@ -1,4 +1,4 @@
-package gopay
+package alipay
 
 import (
 	"encoding/json"
@@ -7,11 +7,14 @@ import (
 	"strings"
 	"sync"
 	"time"
+
+	"github.com/iGoogle-ink/gopay"
 )
 
-type AliPayClient struct {
+type Client struct {
 	AppId              string
 	PrivateKey         string
+	LocationName       string
 	AppCertSN          string
 	AliPayPublicCertSN string
 	AliPayRootCertSN   string
@@ -22,6 +25,7 @@ type AliPayClient struct {
 	AppAuthToken       string
 	AuthToken          string
 	IsProd             bool
+	location           *time.Location
 	mu                 sync.RWMutex
 }
 
@@ -30,8 +34,8 @@ type AliPayClient struct {
 //    appId:应用ID
 //    PrivateKey:应用私钥
 //    IsProd:是否是正式环境
-func NewAliPayClient(appId, privateKey string, isProd bool) (client *AliPayClient) {
-	return &AliPayClient{
+func NewClient(appId, privateKey string, isProd bool) (client *Client) {
+	return &Client{
 		AppId:      appId,
 		PrivateKey: privateKey,
 		IsProd:     isProd,
@@ -40,21 +44,21 @@ func NewAliPayClient(appId, privateKey string, isProd bool) (client *AliPayClien
 
 // alipay.trade.fastpay.refund.query(统一收单交易退款查询)
 //    文档地址:https://docs.open.alipay.com/api_1/alipay.trade.fastpay.refund.query
-func (a *AliPayClient) AliPayTradeFastPayRefundQuery(body BodyMap) (aliRsp *AliPayTradeFastpayRefundQueryResponse, err error) {
+func (a *Client) TradeFastPayRefundQuery(bm gopay.BodyMap) (aliRsp *TradeFastpayRefundQueryResponse, err error) {
 	var (
 		bs []byte
 	)
-	if body.Get("out_trade_no") == null && body.Get("trade_no") == null {
+	if bm.Get("out_trade_no") == gopay.NULL && bm.Get("trade_no") == gopay.NULL {
 		return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
 	}
-	if bs, err = a.doAliPay(body, "alipay.trade.fastpay.refund.query"); err != nil {
+	if bs, err = a.doAliPay(bm, "alipay.trade.fastpay.refund.query"); err != nil {
 		return
 	}
-	aliRsp = new(AliPayTradeFastpayRefundQueryResponse)
+	aliRsp = new(TradeFastpayRefundQueryResponse)
 	if err = json.Unmarshal(bs, aliRsp); err != nil {
 		return nil, err
 	}
-	if aliRsp.Response.Code != "10000" {
+	if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
 		info := aliRsp.Response
 		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
 	}
@@ -64,21 +68,21 @@ func (a *AliPayClient) AliPayTradeFastPayRefundQuery(body BodyMap) (aliRsp *AliP
 
 // alipay.trade.order.settle(统一收单交易结算接口)
 //    文档地址:https://docs.open.alipay.com/api_1/alipay.trade.order.settle
-func (a *AliPayClient) AliPayTradeOrderSettle(body BodyMap) (aliRsp *AliPayTradeOrderSettleResponse, err error) {
+func (a *Client) TradeOrderSettle(bm gopay.BodyMap) (aliRsp *TradeOrderSettleResponse, err error) {
 	var (
 		bs []byte
 	)
-	if body.Get("out_request_no") == null || body.Get("trade_no") == null {
+	if bm.Get("out_request_no") == gopay.NULL || bm.Get("trade_no") == gopay.NULL {
 		return nil, errors.New("out_request_no or trade_no are not allowed to be null")
 	}
-	if bs, err = a.doAliPay(body, "alipay.trade.order.settle"); err != nil {
+	if bs, err = a.doAliPay(bm, "alipay.trade.order.settle"); err != nil {
 		return
 	}
-	aliRsp = new(AliPayTradeOrderSettleResponse)
+	aliRsp = new(TradeOrderSettleResponse)
 	if err = json.Unmarshal(bs, aliRsp); err != nil {
 		return nil, err
 	}
-	if aliRsp.Response.Code != "10000" {
+	if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
 		info := aliRsp.Response
 		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
 	}
@@ -88,21 +92,21 @@ func (a *AliPayClient) AliPayTradeOrderSettle(body BodyMap) (aliRsp *AliPayTrade
 
 // alipay.trade.create(统一收单交易创建接口)
 //    文档地址:https://docs.open.alipay.com/api_1/alipay.trade.create
-func (a *AliPayClient) AliPayTradeCreate(body BodyMap) (aliRsp *AliPayTradeCreateResponse, err error) {
+func (a *Client) TradeCreate(bm gopay.BodyMap) (aliRsp *TradeCreateResponse, err error) {
 	var (
 		bs []byte
 	)
-	if body.Get("out_trade_no") == null && body.Get("buyer_id") == null {
+	if bm.Get("out_trade_no") == gopay.NULL && bm.Get("buyer_id") == gopay.NULL {
 		return nil, errors.New("out_trade_no and buyer_id are not allowed to be null at the same time")
 	}
-	if bs, err = a.doAliPay(body, "alipay.trade.create"); err != nil {
+	if bs, err = a.doAliPay(bm, "alipay.trade.create"); err != nil {
 		return
 	}
-	aliRsp = new(AliPayTradeCreateResponse)
+	aliRsp = new(TradeCreateResponse)
 	if err = json.Unmarshal(bs, aliRsp); err != nil {
 		return nil, err
 	}
-	if aliRsp.Response.Code != "10000" {
+	if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
 		info := aliRsp.Response
 		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
 	}
@@ -112,21 +116,21 @@ func (a *AliPayClient) AliPayTradeCreate(body BodyMap) (aliRsp *AliPayTradeCreat
 
 // alipay.trade.close(统一收单交易关闭接口)
 //    文档地址:https://docs.open.alipay.com/api_1/alipay.trade.close
-func (a *AliPayClient) AliPayTradeClose(body BodyMap) (aliRsp *AliPayTradeCloseResponse, err error) {
+func (a *Client) TradeClose(bm gopay.BodyMap) (aliRsp *TradeCloseResponse, err error) {
 	var (
 		bs []byte
 	)
-	if body.Get("out_trade_no") == null && body.Get("trade_no") == null {
+	if bm.Get("out_trade_no") == gopay.NULL && bm.Get("trade_no") == gopay.NULL {
 		return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
 	}
-	if bs, err = a.doAliPay(body, "alipay.trade.close"); err != nil {
+	if bs, err = a.doAliPay(bm, "alipay.trade.close"); err != nil {
 		return
 	}
-	aliRsp = new(AliPayTradeCloseResponse)
+	aliRsp = new(TradeCloseResponse)
 	if err = json.Unmarshal(bs, aliRsp); err != nil {
 		return nil, err
 	}
-	if aliRsp.Response.Code != "10000" {
+	if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
 		info := aliRsp.Response
 		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
 	}
@@ -136,21 +140,21 @@ func (a *AliPayClient) AliPayTradeClose(body BodyMap) (aliRsp *AliPayTradeCloseR
 
 // alipay.trade.cancel(统一收单交易撤销接口)
 //    文档地址:https://docs.open.alipay.com/api_1/alipay.trade.cancel
-func (a *AliPayClient) AliPayTradeCancel(body BodyMap) (aliRsp *AliPayTradeCancelResponse, err error) {
+func (a *Client) TradeCancel(bm gopay.BodyMap) (aliRsp *TradeCancelResponse, err error) {
 	var (
 		bs []byte
 	)
-	if body.Get("out_trade_no") == null && body.Get("trade_no") == null {
+	if bm.Get("out_trade_no") == gopay.NULL && bm.Get("trade_no") == gopay.NULL {
 		return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
 	}
-	if bs, err = a.doAliPay(body, "alipay.trade.cancel"); err != nil {
+	if bs, err = a.doAliPay(bm, "alipay.trade.cancel"); err != nil {
 		return
 	}
-	aliRsp = new(AliPayTradeCancelResponse)
+	aliRsp = new(TradeCancelResponse)
 	if err = json.Unmarshal(bs, aliRsp); err != nil {
 		return nil, err
 	}
-	if aliRsp.Response.Code != "10000" {
+	if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
 		info := aliRsp.Response
 		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
 	}
@@ -160,21 +164,21 @@ func (a *AliPayClient) AliPayTradeCancel(body BodyMap) (aliRsp *AliPayTradeCance
 
 // alipay.trade.refund(统一收单交易退款接口)
 //    文档地址:https://docs.open.alipay.com/api_1/alipay.trade.refund
-func (a *AliPayClient) AliPayTradeRefund(body BodyMap) (aliRsp *AliPayTradeRefundResponse, err error) {
+func (a *Client) TradeRefund(bm gopay.BodyMap) (aliRsp *TradeRefundResponse, err error) {
 	var (
 		bs []byte
 	)
-	if body.Get("out_trade_no") == null && body.Get("trade_no") == null {
+	if bm.Get("out_trade_no") == gopay.NULL && bm.Get("trade_no") == gopay.NULL {
 		return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
 	}
-	if bs, err = a.doAliPay(body, "alipay.trade.refund"); err != nil {
+	if bs, err = a.doAliPay(bm, "alipay.trade.refund"); err != nil {
 		return nil, err
 	}
-	aliRsp = new(AliPayTradeRefundResponse)
+	aliRsp = new(TradeRefundResponse)
 	if err = json.Unmarshal(bs, aliRsp); err != nil {
 		return nil, err
 	}
-	if aliRsp.Response.Code != "10000" {
+	if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
 		info := aliRsp.Response
 		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
 	}
@@ -182,23 +186,23 @@ func (a *AliPayClient) AliPayTradeRefund(body BodyMap) (aliRsp *AliPayTradeRefun
 	return
 }
 
-// alipay.trade.refund(统一收单退款页面接口)
+// alipay.trade.page.refund(统一收单退款页面接口)
 //    文档地址:https://docs.open.alipay.com/api_1/alipay.trade.page.refund
-func (a *AliPayClient) AliPayTradePageRefund(body BodyMap) (aliRsp *AliPayTradePageRefundResponse, err error) {
+func (a *Client) TradePageRefund(bm gopay.BodyMap) (aliRsp *TradePageRefundResponse, err error) {
 	var (
 		bs []byte
 	)
-	if body.Get("out_trade_no") == null && body.Get("trade_no") == null {
+	if bm.Get("out_trade_no") == gopay.NULL && bm.Get("trade_no") == gopay.NULL {
 		return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
 	}
-	if bs, err = a.doAliPay(body, "alipay.trade.page.refund"); err != nil {
+	if bs, err = a.doAliPay(bm, "alipay.trade.page.refund"); err != nil {
 		return
 	}
-	aliRsp = new(AliPayTradePageRefundResponse)
+	aliRsp = new(TradePageRefundResponse)
 	if err = json.Unmarshal(bs, aliRsp); err != nil {
 		return nil, err
 	}
-	if aliRsp.Response.Code != "10000" {
+	if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
 		info := aliRsp.Response
 		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
 	}
@@ -208,41 +212,45 @@ func (a *AliPayClient) AliPayTradePageRefund(body BodyMap) (aliRsp *AliPayTradeP
 
 // alipay.trade.precreate(统一收单线下交易预创建)
 //    文档地址:https://docs.open.alipay.com/api_1/alipay.trade.precreate
-func (a *AliPayClient) AliPayTradePrecreate(body BodyMap) (aliRsp *AliPayTradePrecreateResponse, err error) {
+func (a *Client) TradePrecreate(bm gopay.BodyMap) (aliRsp *TradePrecreateResponse, err error) {
 	var bs []byte
-	if body.Get("out_trade_no") == null {
+	if bm.Get("out_trade_no") == gopay.NULL {
 		return nil, errors.New("out_trade_no is not allowed to be null")
 	}
-	if bs, err = a.doAliPay(body, "alipay.trade.precreate"); err != nil {
+	if bs, err = a.doAliPay(bm, "alipay.trade.precreate"); err != nil {
 		return
 	}
-	aliRsp = new(AliPayTradePrecreateResponse)
+	aliRsp = new(TradePrecreateResponse)
 	if err = json.Unmarshal(bs, aliRsp); err != nil {
 		return nil, err
 	}
-	if aliRsp.Response.Code != "10000" {
+	if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
 		info := aliRsp.Response
 		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
 	}
+	if aliRsp.NullResponse != nil {
+		info := aliRsp.NullResponse
+		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
+	}
 	aliRsp.SignData = getSignData(bs)
 	return
 }
 
 // alipay.trade.pay(统一收单交易支付接口)
 //    文档地址:https://docs.open.alipay.com/api_1/alipay.trade.pay
-func (a *AliPayClient) AliPayTradePay(body BodyMap) (aliRsp *AliPayTradePayResponse, err error) {
+func (a *Client) TradePay(bm gopay.BodyMap) (aliRsp *TradePayResponse, err error) {
 	var bs []byte
-	if body.Get("out_trade_no") == null {
+	if bm.Get("out_trade_no") == gopay.NULL {
 		return nil, errors.New("out_trade_no is not allowed to be null")
 	}
-	if bs, err = a.doAliPay(body, "alipay.trade.pay"); err != nil {
+	if bs, err = a.doAliPay(bm, "alipay.trade.pay"); err != nil {
 		return
 	}
-	aliRsp = new(AliPayTradePayResponse)
+	aliRsp = new(TradePayResponse)
 	if err = json.Unmarshal(bs, aliRsp); err != nil {
 		return nil, err
 	}
-	if aliRsp.Response.Code != "10000" {
+	if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
 		info := aliRsp.Response
 		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
 	}
@@ -252,21 +260,21 @@ func (a *AliPayClient) AliPayTradePay(body BodyMap) (aliRsp *AliPayTradePayRespo
 
 // alipay.trade.query(统一收单线下交易查询)
 //    文档地址:https://docs.open.alipay.com/api_1/alipay.trade.query
-func (a *AliPayClient) AliPayTradeQuery(body BodyMap) (aliRsp *AliPayTradeQueryResponse, err error) {
+func (a *Client) TradeQuery(bm gopay.BodyMap) (aliRsp *TradeQueryResponse, err error) {
 	var (
 		bs []byte
 	)
-	if body.Get("out_trade_no") == null && body.Get("trade_no") == null {
+	if bm.Get("out_trade_no") == gopay.NULL && bm.Get("trade_no") == gopay.NULL {
 		return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
 	}
-	if bs, err = a.doAliPay(body, "alipay.trade.query"); err != nil {
+	if bs, err = a.doAliPay(bm, "alipay.trade.query"); err != nil {
 		return
 	}
-	aliRsp = new(AliPayTradeQueryResponse)
+	aliRsp = new(TradeQueryResponse)
 	if err = json.Unmarshal(bs, aliRsp); err != nil {
 		return nil, err
 	}
-	if aliRsp.Response.Code != "10000" {
+	if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
 		info := aliRsp.Response
 		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
 	}
@@ -276,13 +284,13 @@ func (a *AliPayClient) AliPayTradeQuery(body BodyMap) (aliRsp *AliPayTradeQueryR
 
 // alipay.trade.app.pay(app支付接口2.0)
 //    文档地址:https://docs.open.alipay.com/api_1/alipay.trade.app.pay
-func (a *AliPayClient) AliPayTradeAppPay(body BodyMap) (payParam string, err error) {
+func (a *Client) TradeAppPay(bm gopay.BodyMap) (payParam string, err error) {
 	var bs []byte
-	if body.Get("out_trade_no") == null {
-		return null, errors.New("out_trade_no is not allowed to be null")
+	if bm.Get("out_trade_no") == gopay.NULL {
+		return gopay.NULL, errors.New("out_trade_no is not allowed to be null")
 	}
-	if bs, err = a.doAliPay(body, "alipay.trade.app.pay"); err != nil {
-		return null, err
+	if bs, err = a.doAliPay(bm, "alipay.trade.app.pay"); err != nil {
+		return gopay.NULL, err
 	}
 	payParam = string(bs)
 	return
@@ -290,14 +298,14 @@ func (a *AliPayClient) AliPayTradeAppPay(body BodyMap) (payParam string, err err
 
 // alipay.trade.wap.pay(手机网站支付接口2.0)
 //    文档地址:https://docs.open.alipay.com/api_1/alipay.trade.wap.pay
-func (a *AliPayClient) AliPayTradeWapPay(body BodyMap) (payUrl string, err error) {
+func (a *Client) TradeWapPay(bm gopay.BodyMap) (payUrl string, err error) {
 	var bs []byte
-	if body.Get("out_trade_no") == null {
-		return null, errors.New("out_trade_no is not allowed to be null")
+	if bm.Get("out_trade_no") == gopay.NULL {
+		return gopay.NULL, errors.New("out_trade_no is not allowed to be null")
 	}
-	body.Set("product_code", "QUICK_WAP_WAY")
-	if bs, err = a.doAliPay(body, "alipay.trade.wap.pay"); err != nil {
-		return null, err
+	bm.Set("product_code", "QUICK_WAP_WAY")
+	if bs, err = a.doAliPay(bm, "alipay.trade.wap.pay"); err != nil {
+		return gopay.NULL, err
 	}
 	payUrl = string(bs)
 	return
@@ -305,14 +313,14 @@ func (a *AliPayClient) AliPayTradeWapPay(body BodyMap) (payUrl string, err error
 
 // alipay.trade.page.pay(统一收单下单并支付页面接口)
 //    文档地址:https://docs.open.alipay.com/api_1/alipay.trade.page.pay
-func (a *AliPayClient) AliPayTradePagePay(body BodyMap) (payUrl string, err error) {
+func (a *Client) TradePagePay(bm gopay.BodyMap) (payUrl string, err error) {
 	var bs []byte
-	if body.Get("out_trade_no") == null {
-		return null, errors.New("out_trade_no is not allowed to be null")
+	if bm.Get("out_trade_no") == gopay.NULL {
+		return gopay.NULL, errors.New("out_trade_no is not allowed to be null")
 	}
-	body.Set("product_code", "FAST_INSTANT_TRADE_PAY")
-	if bs, err = a.doAliPay(body, "alipay.trade.page.pay"); err != nil {
-		return null, err
+	bm.Set("product_code", "FAST_INSTANT_TRADE_PAY")
+	if bs, err = a.doAliPay(bm, "alipay.trade.page.pay"); err != nil {
+		return gopay.NULL, err
 	}
 	payUrl = string(bs)
 	return
@@ -320,19 +328,19 @@ func (a *AliPayClient) AliPayTradePagePay(body BodyMap) (payUrl string, err erro
 
 // alipay.fund.trans.toaccount.transfer(单笔转账到支付宝账户接口)
 //    文档地址:https://docs.open.alipay.com/api_28/alipay.fund.trans.toaccount.transfer
-func (a *AliPayClient) AliPayFundTransToaccountTransfer(body BodyMap) (aliRsp *AliPayFundTransToaccountTransferResponse, err error) {
+func (a *Client) FundTransToaccountTransfer(bm gopay.BodyMap) (aliRsp *FundTransToaccountTransferResponse, err error) {
 	var bs []byte
-	if body.Get("out_biz_no") == null {
+	if bm.Get("out_biz_no") == gopay.NULL {
 		return nil, errors.New("out_biz_no is not allowed to be null")
 	}
-	if bs, err = a.doAliPay(body, "alipay.fund.trans.toaccount.transfer"); err != nil {
+	if bs, err = a.doAliPay(bm, "alipay.fund.trans.toaccount.transfer"); err != nil {
 		return
 	}
-	aliRsp = new(AliPayFundTransToaccountTransferResponse)
+	aliRsp = new(FundTransToaccountTransferResponse)
 	if err = json.Unmarshal(bs, aliRsp); err != nil {
 		return nil, err
 	}
-	if aliRsp.Response.Code != "10000" {
+	if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
 		info := aliRsp.Response
 		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
 	}
@@ -342,28 +350,28 @@ func (a *AliPayClient) AliPayFundTransToaccountTransfer(body BodyMap) (aliRsp *A
 
 // alipay.trade.orderinfo.sync(支付宝订单信息同步接口)
 //    文档地址:https://docs.open.alipay.com/api_1/alipay.trade.orderinfo.sync
-func (a *AliPayClient) AliPayTradeOrderinfoSync(body BodyMap) {
+func (a *Client) TradeOrderinfoSync(body gopay.BodyMap) {
 
 }
 
 // alipay.system.oauth.token(换取授权访问令牌)
 //    文档地址:https://docs.open.alipay.com/api_9/alipay.system.oauth.token
-func (a *AliPayClient) AliPaySystemOauthToken(body BodyMap) (aliRsp *AliPaySystemOauthTokenResponse, err error) {
+func (a *Client) SystemOauthToken(bm gopay.BodyMap) (aliRsp *SystemOauthTokenResponse, err error) {
 	var bs []byte
-	if body.Get("grant_type") == null {
+	if bm.Get("grant_type") == gopay.NULL {
 		return nil, errors.New("grant_type is not allowed to be null")
 	}
-	if body.Get("code") == null && body.Get("refresh_token") == null {
+	if bm.Get("code") == gopay.NULL && bm.Get("refresh_token") == gopay.NULL {
 		return nil, errors.New("code and refresh_token are not allowed to be null at the same time")
 	}
-	if bs, err = aliPaySystemOauthToken(a.AppId, a.PrivateKey, body, "alipay.system.oauth.token", a.IsProd); err != nil {
+	if bs, err = systemOauthToken(a.AppId, a.PrivateKey, bm, "alipay.system.oauth.token", a.IsProd); err != nil {
 		return
 	}
-	aliRsp = new(AliPaySystemOauthTokenResponse)
+	aliRsp = new(SystemOauthTokenResponse)
 	if err = json.Unmarshal(bs, aliRsp); err != nil {
 		return nil, err
 	}
-	if aliRsp.Response.AccessToken == null {
+	if aliRsp.ErrorResponse != nil {
 		info := aliRsp.ErrorResponse
 		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
 	}
@@ -374,16 +382,16 @@ func (a *AliPayClient) AliPaySystemOauthToken(body BodyMap) (aliRsp *AliPaySyste
 // alipay.user.info.share(支付宝会员授权信息查询接口)
 //    body:此接口无需body参数
 //    文档地址:https://docs.open.alipay.com/api_2/alipay.user.info.share
-func (a *AliPayClient) AliPayUserInfoShare() (aliRsp *AliPayUserInfoShareResponse, err error) {
+func (a *Client) UserInfoShare() (aliRsp *UserInfoShareResponse, err error) {
 	var bs []byte
 	if bs, err = a.doAliPay(nil, "alipay.user.info.share"); err != nil {
 		return nil, err
 	}
-	aliRsp = new(AliPayUserInfoShareResponse)
+	aliRsp = new(UserInfoShareResponse)
 	if err = json.Unmarshal(bs, aliRsp); err != nil {
 		return nil, err
 	}
-	if aliRsp.Response.Code != "10000" {
+	if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
 		info := aliRsp.Response
 		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
 	}
@@ -393,22 +401,22 @@ func (a *AliPayClient) AliPayUserInfoShare() (aliRsp *AliPayUserInfoShareRespons
 
 // alipay.open.auth.token.app(换取应用授权令牌)
 //    文档地址:https://docs.open.alipay.com/api_9/alipay.open.auth.token.app
-func (a *AliPayClient) AliPayOpenAuthTokenApp(body BodyMap) (aliRsp *AliPayOpenAuthTokenAppResponse, err error) {
+func (a *Client) OpenAuthTokenApp(bm gopay.BodyMap) (aliRsp *OpenAuthTokenAppResponse, err error) {
 	var bs []byte
-	if body.Get("grant_type") == null {
+	if bm.Get("grant_type") == gopay.NULL {
 		return nil, errors.New("grant_type is not allowed to be null")
 	}
-	if body.Get("code") == null && body.Get("refresh_token") == null {
+	if bm.Get("code") == gopay.NULL && bm.Get("refresh_token") == gopay.NULL {
 		return nil, errors.New("code and refresh_token are not allowed to be null at the same time")
 	}
-	if bs, err = a.doAliPay(body, "alipay.open.auth.token.app"); err != nil {
+	if bs, err = a.doAliPay(bm, "alipay.open.auth.token.app"); err != nil {
 		return
 	}
-	aliRsp = new(AliPayOpenAuthTokenAppResponse)
+	aliRsp = new(OpenAuthTokenAppResponse)
 	if err = json.Unmarshal(bs, aliRsp); err != nil {
 		return nil, err
 	}
-	if aliRsp.Response.Code != "10000" {
+	if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
 		info := aliRsp.Response
 		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
 	}
@@ -418,24 +426,24 @@ func (a *AliPayClient) AliPayOpenAuthTokenApp(body BodyMap) (aliRsp *AliPayOpenA
 
 // zhima.credit.score.get(芝麻分)
 //    文档地址:https://docs.open.alipay.com/api_8/zhima.credit.score.get
-func (a *AliPayClient) ZhimaCreditScoreGet(body BodyMap) (aliRsp *ZhimaCreditScoreGetResponse, err error) {
+func (a *Client) ZhimaCreditScoreGet(bm gopay.BodyMap) (aliRsp *ZhimaCreditScoreGetResponse, err error) {
 	var (
 		bs []byte
 	)
-	if body.Get("product_code") == null {
-		body.Set("product_code", "w1010100100000000001")
+	if bm.Get("product_code") == gopay.NULL {
+		bm.Set("product_code", "w1010100100000000001")
 	}
-	if body.Get("transaction_id") == null {
+	if bm.Get("transaction_id") == gopay.NULL {
 		return nil, errors.New("transaction_id is not allowed to be null")
 	}
-	if bs, err = a.doAliPay(body, "zhima.credit.score.get"); err != nil {
+	if bs, err = a.doAliPay(bm, "zhima.credit.score.get"); err != nil {
 		return
 	}
 	aliRsp = new(ZhimaCreditScoreGetResponse)
 	if err = json.Unmarshal(bs, aliRsp); err != nil {
 		return nil, err
 	}
-	if aliRsp.Response.Code != "10000" {
+	if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
 		info := aliRsp.Response
 		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
 	}
@@ -445,30 +453,30 @@ func (a *AliPayClient) ZhimaCreditScoreGet(body BodyMap) (aliRsp *ZhimaCreditSco
 
 // alipay.user.certify.open.initialize(身份认证初始化服务)
 //    文档地址:https://docs.open.alipay.com/api_2/alipay.user.certify.open.initialize
-func (a *AliPayClient) AliPayUserCertifyOpenInit(body BodyMap) (aliRsp *AliPayUserCertifyOpenInitResponse, err error) {
+func (a *Client) UserCertifyOpenInit(bm gopay.BodyMap) (aliRsp *UserCertifyOpenInitResponse, err error) {
 	var (
 		bs []byte
 	)
-	if body.Get("biz_code") == null {
+	if bm.Get("biz_code") == gopay.NULL {
 		return nil, errors.New("biz_code is not allowed to be null")
 	}
-	if body.Get("outer_order_no") == null {
+	if bm.Get("outer_order_no") == gopay.NULL {
 		return nil, errors.New("outer_order_no is not allowed to be null")
 	}
-	if body.Get("identity_param") == null {
+	if bm.Get("identity_param") == gopay.NULL {
 		return nil, errors.New("identity_param is not allowed to be null")
 	}
-	if body.Get("merchant_config") == null {
+	if bm.Get("merchant_config") == gopay.NULL {
 		return nil, errors.New("merchant_config is not allowed to be null")
 	}
-	if bs, err = a.doAliPay(body, "alipay.user.certify.open.initialize"); err != nil {
+	if bs, err = a.doAliPay(bm, "alipay.user.certify.open.initialize"); err != nil {
 		return
 	}
-	aliRsp = new(AliPayUserCertifyOpenInitResponse)
+	aliRsp = new(UserCertifyOpenInitResponse)
 	if err = json.Unmarshal(bs, aliRsp); err != nil {
 		return nil, err
 	}
-	if aliRsp.Response.Code != "10000" {
+	if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
 		info := aliRsp.Response
 		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
 	}
@@ -479,15 +487,15 @@ func (a *AliPayClient) AliPayUserCertifyOpenInit(body BodyMap) (aliRsp *AliPayUs
 // alipay.user.certify.open.certify(身份认证开始认证)
 //    API文档地址:https://docs.open.alipay.com/api_2/alipay.user.certify.open.certify
 //    产品文档地址:https://docs.open.alipay.com/20181012100420932508/quickstart
-func (a *AliPayClient) AliPayUserCertifyOpenCertify(body BodyMap) (certifyUrl string, err error) {
+func (a *Client) UserCertifyOpenCertify(bm gopay.BodyMap) (certifyUrl string, err error) {
 	var (
 		bs []byte
 	)
-	if body.Get("certify_id") == null {
-		return null, errors.New("certify_id is not allowed to be null")
+	if bm.Get("certify_id") == gopay.NULL {
+		return gopay.NULL, errors.New("certify_id is not allowed to be null")
 	}
-	if bs, err = a.doAliPay(body, "alipay.user.certify.open.certify"); err != nil {
-		return null, err
+	if bs, err = a.doAliPay(bm, "alipay.user.certify.open.certify"); err != nil {
+		return gopay.NULL, err
 	}
 	certifyUrl = string(bs)
 	return
@@ -495,21 +503,21 @@ func (a *AliPayClient) AliPayUserCertifyOpenCertify(body BodyMap) (certifyUrl st
 
 // alipay.user.certify.open.query(身份认证记录查询)
 //    文档地址:https://docs.open.alipay.com/api_2/alipay.user.certify.open.query
-func (a *AliPayClient) AliPayUserCertifyOpenQuery(body BodyMap) (aliRsp *AliPayUserCertifyOpenQueryResponse, err error) {
+func (a *Client) UserCertifyOpenQuery(bm gopay.BodyMap) (aliRsp *UserCertifyOpenQueryResponse, err error) {
 	var (
 		bs []byte
 	)
-	if body.Get("certify_id") == null {
+	if bm.Get("certify_id") == gopay.NULL {
 		return nil, errors.New("certify_id is not allowed to be null")
 	}
-	if bs, err = a.doAliPay(body, "alipay.user.certify.open.query"); err != nil {
+	if bs, err = a.doAliPay(bm, "alipay.user.certify.open.query"); err != nil {
 		return
 	}
-	aliRsp = new(AliPayUserCertifyOpenQueryResponse)
+	aliRsp = new(UserCertifyOpenQueryResponse)
 	if err = json.Unmarshal(bs, aliRsp); err != nil {
 		return nil, err
 	}
-	if aliRsp.Response.Code != "10000" {
+	if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
 		info := aliRsp.Response
 		return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
 	}
@@ -518,75 +526,82 @@ func (a *AliPayClient) AliPayUserCertifyOpenQuery(body BodyMap) (aliRsp *AliPayU
 }
 
 // 向支付宝发送请求
-func (a *AliPayClient) doAliPay(body BodyMap, method string) (bs []byte, err error) {
+func (a *Client) doAliPay(bm gopay.BodyMap, method string) (bs []byte, err error) {
 	var (
-		bodyStr, sign, url string
-		bodyBs             []byte
+		bodyStr, url string
+		bodyBs       []byte
 	)
-	if body != nil {
-		if bodyBs, err = json.Marshal(body); err != nil {
+	if bm != nil {
+		if bodyBs, err = json.Marshal(bm); err != nil {
 			return nil, fmt.Errorf("json.Marshal:%s", err.Error())
 		}
 		bodyStr = string(bodyBs)
 	}
-	pubBody := make(BodyMap)
+	pubBody := make(gopay.BodyMap)
 	pubBody.Set("app_id", a.AppId)
 	pubBody.Set("method", method)
 	pubBody.Set("format", "JSON")
-	if a.AppCertSN != null {
+	if a.AppCertSN != gopay.NULL {
 		a.mu.RLock()
 		pubBody.Set("app_cert_sn", a.AppCertSN)
 		a.mu.RUnlock()
 	}
-	if a.AliPayRootCertSN != null {
+	if a.AliPayRootCertSN != gopay.NULL {
 		a.mu.RLock()
 		pubBody.Set("alipay_root_cert_sn", a.AliPayRootCertSN)
 		a.mu.RUnlock()
 	}
-	if a.ReturnUrl != null {
+	if a.ReturnUrl != gopay.NULL {
 		a.mu.RLock()
 		pubBody.Set("return_url", a.ReturnUrl)
 		a.mu.RUnlock()
 	}
-	if a.Charset == null {
+	if a.Charset == gopay.NULL {
 		pubBody.Set("charset", "utf-8")
 	} else {
 		a.mu.RLock()
 		pubBody.Set("charset", a.Charset)
 		a.mu.RUnlock()
 	}
-	if a.SignType == null {
+	if a.SignType == gopay.NULL {
 		pubBody.Set("sign_type", "RSA2")
 	} else {
 		a.mu.RLock()
 		pubBody.Set("sign_type", a.SignType)
 		a.mu.RUnlock()
 	}
-	pubBody.Set("timestamp", time.Now().Format(TimeLayout))
+	if a.LocationName != gopay.NULL && a.location != nil {
+		a.mu.RLock()
+		pubBody.Set("timestamp", time.Now().In(a.location).Format(gopay.TimeLayout))
+		a.mu.RUnlock()
+	} else {
+		pubBody.Set("timestamp", time.Now().Format(gopay.TimeLayout))
+	}
 	pubBody.Set("version", "1.0")
-	if a.NotifyUrl != null {
+	if a.NotifyUrl != gopay.NULL {
 		a.mu.RLock()
 		pubBody.Set("notify_url", a.NotifyUrl)
 		a.mu.RUnlock()
 	}
-	if a.AppAuthToken != null {
+	if a.AppAuthToken != gopay.NULL {
 		a.mu.RLock()
 		pubBody.Set("app_auth_token", a.AppAuthToken)
 		a.mu.RUnlock()
 	}
-	if a.AuthToken != null {
+	if a.AuthToken != gopay.NULL {
 		a.mu.RLock()
 		pubBody.Set("auth_token", a.AuthToken)
 		a.mu.RUnlock()
 	}
-	if bodyStr != null {
+	if bodyStr != gopay.NULL {
 		pubBody.Set("biz_content", bodyStr)
 	}
-	if sign, err = getRsaSign(pubBody, pubBody.Get("sign_type"), FormatPrivateKey(a.PrivateKey)); err != nil {
+	sign, err := getRsaSign(pubBody, pubBody.Get("sign_type"), FormatPrivateKey(a.PrivateKey))
+	if err != nil {
 		return
 	}
 	pubBody.Set("sign", sign)
-	param := FormatAliPayURLParam(pubBody)
+	param := FormatURLParam(pubBody)
 
 	switch method {
 	case "alipay.trade.app.pay":
@@ -597,13 +612,13 @@ func (a *AliPayClient) doAliPay(body BodyMap, method string) (bs []byte, err err
 		}
 		return []byte(zfbBaseUrl + "?" + param), nil
 	default:
-		httpClient := NewHttpClient()
+		httpClient := gopay.NewHttpClient()
 		if !a.IsProd {
 			url = zfbSandboxBaseUrlUtf8
 		} else {
 			url = zfbBaseUrlUtf8
 		}
-		res, bs, errs := httpClient.Type(TypeForm).Post(url).SendString(param).EndBytes()
+		res, bs, errs := httpClient.Type(gopay.TypeForm).Post(url).SendString(param).EndBytes()
 		if len(errs) > 0 {
 			return nil, errs[0]
 		}

+ 487 - 0
alipay/client_test.go

@@ -0,0 +1,487 @@
+package alipay
+
+import (
+	"fmt"
+	"os"
+	"testing"
+
+	"github.com/iGoogle-ink/gopay"
+)
+
+var (
+	client          *Client
+	appid           = "2016091200494382"
+	aliPayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
+	privateKey      = "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
+)
+
+func TestMain(m *testing.M) {
+
+	// 初始化支付宝客户端
+	//    appId:应用ID
+	//    privateKey:应用秘钥
+	//    isProd:是否是正式环境
+	client = NewClient(appid, privateKey, false)
+	// 配置公共参数
+	client.SetCharset("utf-8").
+		SetSignType("RSA2").
+		//SetReturnUrl("https://www.gopay.ink").
+		SetNotifyUrl("https://www.gopay.ink")
+
+	//err := client.SetCertSnByPath("cert/appCertPublicKey.crt", "cert/alipayRootCert.crt", "cert/alipayCertPublicKey_RSA2.crt")
+	//if err != nil {
+	//	fmt.Println("SetCertSnByPath:", err)
+	//	return
+	//}
+
+	os.Exit(m.Run())
+}
+
+func TestClient_TradePrecreate(t *testing.T) {
+	// 请求参数
+	bm := make(gopay.BodyMap)
+	bm.Set("subject", "预创建创建订单")
+	bm.Set("out_trade_no", gopay.GetRandomString(32))
+	bm.Set("total_amount", "100")
+
+	// 创建订单
+	aliRsp, err := client.TradePrecreate(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("aliRsp:", *aliRsp)
+	fmt.Println("aliRsp.QrCode:", aliRsp.Response.QrCode)
+	fmt.Println("aliRsp.OutTradeNo:", aliRsp.Response.OutTradeNo)
+}
+
+func TestClient_TradeCreate(t *testing.T) {
+	// 请求参数
+	bm := make(gopay.BodyMap)
+	bm.Set("subject", "创建订单")
+	bm.Set("buyer_id", "2088802095984694")
+	bm.Set("out_trade_no", "GZ201901301040355709")
+	bm.Set("total_amount", "0.01")
+
+	// 创建订单
+	aliRsp, err := client.TradeCreate(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("aliRsp:", *aliRsp)
+	fmt.Println("aliRsp.TradeNo:", aliRsp.Response.TradeNo)
+}
+
+func TestClient_TradeAppPay(t *testing.T) {
+	// 请求参数
+	bm := make(gopay.BodyMap)
+	bm.Set("subject", "测试APP支付")
+	bm.Set("out_trade_no", "GZ201901301040355706100469")
+	bm.Set("total_amount", "1.00")
+
+	// 手机APP支付参数请求
+	payParam, err := client.TradeAppPay(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("payParam:", payParam)
+}
+
+func TestClient_TradeCancel(t *testing.T) {
+	// 请求参数
+	bm := make(gopay.BodyMap)
+	bm.Set("out_trade_no", "GZ201909081743431443")
+
+	// 撤销支付订单
+	aliRsp, err := client.TradeCancel(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("aliRsp:", *aliRsp)
+}
+
+func TestClient_TradeClose(t *testing.T) {
+	// 请求参数
+	bm := make(gopay.BodyMap)
+	bm.Set("out_trade_no", "GZ201909081743431443")
+
+	// 条码支付
+	aliRsp, err := client.TradeClose(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("aliRsp:", *aliRsp)
+}
+
+func TestClient_TradePay(t *testing.T) {
+	// 请求参数
+	bm := make(gopay.BodyMap)
+	bm.Set("subject", "条码支付")
+	bm.Set("scene", "bar_code")
+	bm.Set("auth_code", "286248566432274952")
+	bm.Set("out_trade_no", "GZ201909081743431443")
+	bm.Set("total_amount", "0.01")
+	bm.Set("timeout_express", "2m")
+
+	// 条码支付
+	aliRsp, err := client.TradePay(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("aliRsp:", *aliRsp)
+
+	// 同步返回验签
+	ok, err := VerifySyncSign(aliPayPublicKey, aliRsp.SignData, aliRsp.Sign)
+	if err != nil {
+		fmt.Println("err:::", err)
+	}
+	fmt.Println("同步返回验签:", ok)
+}
+
+func TestClient_TradeQuery(t *testing.T) {
+	// 请求参数
+	bm := make(gopay.BodyMap)
+	bm.Set("out_trade_no", "GZ201909081743431443")
+
+	// 查询订单
+	aliRsp, err := client.TradeQuery(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("aliRsp:", *aliRsp)
+}
+
+func TestClient_TradeWapPay(t *testing.T) {
+	// 请求参数
+	bm := make(gopay.BodyMap)
+	bm.Set("subject", "手机网站测试支付")
+	bm.Set("out_trade_no", "GZ201909081743431443")
+	bm.Set("quit_url", "https://www.gopay.ink")
+	bm.Set("total_amount", "100.00")
+	bm.Set("product_code", "QUICK_WAP_WAY")
+
+	// 手机网站支付请求
+	payUrl, err := client.TradeWapPay(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("payUrl:", payUrl)
+}
+
+func TestClient_TradePagePay(t *testing.T) {
+	// 请求参数
+	bm := make(gopay.BodyMap)
+	bm.Set("subject", "网站测试支付")
+	bm.Set("out_trade_no", "GZ201909081743431443")
+	bm.Set("total_amount", "88.88")
+	bm.Set("product_code", "FAST_INSTANT_TRADE_PAY")
+
+	// 电脑网站支付请求
+	payUrl, err := client.TradePagePay(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("payUrl:", payUrl)
+}
+
+func TestClient_TradeRefund(t *testing.T) {
+	// 请求参数
+	body := make(gopay.BodyMap)
+	body.Set("out_trade_no", "GZ201909081743431443")
+	body.Set("refund_amount", "5")
+	body.Set("refund_reason", "测试退款")
+
+	// 发起退款请求
+	aliRsp, err := client.TradeRefund(body)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("aliRsp:", *aliRsp)
+}
+
+func TestClient_TradePageRefund(t *testing.T) {
+	// 请求参数
+	bm := make(gopay.BodyMap)
+	bm.Set("out_trade_no", "GZ201909081743431443")
+	bm.Set("refund_amount", "5")
+	bm.Set("out_request_no", gopay.GetRandomString(32))
+
+	// 发起退款请求
+	aliRsp, err := client.TradePageRefund(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("aliRsp:", *aliRsp)
+}
+
+func TestClient_SystemOauthToken(t *testing.T) {
+	// 请求参数
+	bm := make(gopay.BodyMap)
+	bm.Set("grant_type", "authorization_code")
+	bm.Set("code", "3a06216ac8f84b8c93507bb9774bWX11")
+
+	// 发起请求
+	aliRsp, err := client.SystemOauthToken(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("aliRsp:", *aliRsp)
+	fmt.Println("aliRsp:", aliRsp.Response.AccessToken)
+	fmt.Println("aliRsp:", aliRsp.SignData)
+}
+
+func TestClient_TradeOrderSettle(t *testing.T) {
+	//请求参数
+	bm := make(gopay.BodyMap)
+	bm.Set("out_request_no", "201907301518083384")
+	bm.Set("trade_no", "2019072522001484690549776067")
+
+	var listParams []OpenApiRoyaltyDetailInfoPojo
+	listParams = append(listParams, OpenApiRoyaltyDetailInfoPojo{"transfer", "2088802095984694", "userId", "userId", "2088102363632794", "0.01", "分账给2088102363632794"})
+
+	bm.Set("royalty_parameters", listParams)
+	//fmt.Println("listParams:", bm.Get("royalty_parameters"))
+
+	// 发起交易结算接口
+	aliRsp, err := client.TradeOrderSettle(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("aliRsp:", *aliRsp)
+}
+
+func TestClient_OpenAuthTokenApp(t *testing.T) {
+	// 请求参数
+	bm := make(gopay.BodyMap)
+	bm.Set("grant_type", "authorization_code")
+	bm.Set("code", "866185490c4e40efa9f71efea6766X02")
+
+	// 发起请求
+	aliRsp, err := client.OpenAuthTokenApp(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("aliRsp:", *aliRsp)
+}
+
+func TestClient_TradeFastPayRefundQuery(t *testing.T) {
+	// 请求参数
+	bm := make(gopay.BodyMap)
+	bm.Set("out_trade_no", "GZ201909081743431443")
+	bm.Set("out_request_no", "GZ201909081743431443")
+
+	// 发起退款查询请求
+	aliRsp, err := client.TradeFastPayRefundQuery(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("aliRsp:", *aliRsp)
+}
+
+func TestClient_FundTransToaccountTransfer(t *testing.T) {
+	// 请求参数
+	bm := make(gopay.BodyMap)
+	bm.Set("out_biz_no", gopay.GetRandomString(32))
+	bm.Set("payee_type", "ALIPAY_LOGONID")
+	bm.Set("payee_account", "otmdfd2378@sandbox.com")
+	bm.Set("amount", "1000")
+	bm.Set("payer_show_name", "发钱人名字")
+	bm.Set("payee_real_name", "沙箱环境")
+	bm.Set("remark", "转账测试")
+
+	// 转账
+	aliRsp, err := client.FundTransToaccountTransfer(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("aliRsp:", *aliRsp)
+}
+
+func TestClient_UserCertifyOpenInit(t *testing.T) {
+	//请求参数
+	bm := make(gopay.BodyMap)
+	bm.Set("outer_order_no", "ZGYD201809132323000001234")
+	// 认证场景码:FACE:多因子人脸认证,CERT_PHOTO:多因子证照认证,CERT_PHOTO_FACE :多因子证照和人脸认证,SMART_FACE:多因子快捷认证
+	bm.Set("biz_code", "FACE")
+	// 需要验证的身份信息参数,格式为json
+	identity := make(map[string]string)
+	identity["identity_type"] = "CERT_INFO"
+	identity["cert_type"] = "IDENTITY_CARD"
+	identity["cert_name"] = "张三"
+	identity["cert_no"] = "310123199012301234"
+	bm.Set("identity_param", identity)
+	// 商户个性化配置,格式为json
+	merchant := make(map[string]string)
+	merchant["return_url"] = "https://www.gopay.ink"
+	bm.Set("merchant_config", merchant)
+
+	// 发起请求
+	aliRsp, err := client.UserCertifyOpenInit(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("aliRsp:", *aliRsp)
+}
+
+func TestClient_UserCertifyOpenCertify(t *testing.T) {
+	// 请求参数
+	bm := make(gopay.BodyMap)
+	// 本次申请操作的唯一标识,由开放认证初始化接口调用后生成,后续的操作都需要用到
+	bm.Set("certify_id", "53827f9d085b3ce43938c6e5915b4729")
+
+	// 发起请求
+	certifyUrl, err := client.UserCertifyOpenCertify(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("certifyUrl:", certifyUrl)
+}
+
+func TestClient_UserCertifyOpenQuery(t *testing.T) {
+	// 请求参数
+	bm := make(gopay.BodyMap)
+	// 本次申请操作的唯一标识,由开放认证初始化接口调用后生成,后续的操作都需要用到
+	bm.Set("certify_id", "OC201809253000000393900404029253")
+
+	// 发起请求
+	aliRsp, err := client.UserCertifyOpenQuery(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("aliRsp:", *aliRsp)
+	fmt.Println("aliRsp.Response.Passed:", aliRsp.Response.Passed)
+
+}
+
+func TestClient_UserInfoShare(t *testing.T) {
+	// 发起请求
+	aliRsp, err := client.UserInfoShare()
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("aliRsp:", *aliRsp)
+
+	// 同步返回验签
+	ok, err := VerifySyncSign(aliPayPublicKey, aliRsp.SignData, aliRsp.Sign)
+	if err != nil {
+		fmt.Println("VerifySign-err:", err)
+		return
+	}
+	fmt.Println("ok:", ok)
+}
+
+func TestClient_ZhimaCreditScoreGet(t *testing.T) {
+	// 请求参数
+	body := make(gopay.BodyMap)
+	body.Set("transaction_id", gopay.GetRandomString(48))
+	body.Set("product_code", "w1010100100000000001")
+
+	// 芝麻分
+	aliRsp, err := client.ZhimaCreditScoreGet(body)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("aliRsp:", *aliRsp)
+}
+
+// =================================================
+
+func TestSyncVerifySign(t *testing.T) {
+	signData := `{"code":"10000","msg":"Success","buyer_logon_id":"854***@qq.com","buyer_pay_amount":"0.01","buyer_user_id":"2088102363632794","fund_bill_list":[{"amount":"0.01","fund_channel":"PCREDIT"}],"gmt_payment":"2019-08-29 20:14:05","invoice_amount":"0.01","out_trade_no":"GZ201901301040361012","point_amount":"0.00","receipt_amount":"0.01","total_amount":"0.01","trade_no":"2019082922001432790585537960"}`
+	sign := "bk3SzX0CZRI811IJioS2XKQHcgMixUT8mYyGQj+vcOAQas7GIYi6LpykqqSc3m7+yvqoG0TdX/c2JjYnpw/J53JxtC2IC4vsLuIPIgghVo5qafsfSxEJ22w20RZDatI2dYqFVcj8Jp+4aesQ8zMMNw7cX9NLyk7kw3DecYeyQp+zrZMueZPqLh88Z+54G+e6QuSU++0ouqQVd4PkpPqy6YI+8MdMUX4Ve0jOQxMmYH8BC6n5ZsTH/uEaLEtzYVZdSw/xdSQ7K1SH73aEH8XbRYx6rL7RkKksrdvhezX+ThDjQ+fTWjvNFrGcg3fmqXRy2elvoalu+BQmqlkWWjEJYA=="
+	aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp8gueNlkbiDidz6FBQEBpqoRgH8h7JtsPtYW0nzAqy1MME4mFnDSMfSKlreUomS3a55gmBopL1eF4/Km/dEnaL5tCY9+24SKn1D4iyls+lvz/ZjvUjVwxoUYBh8kkcxMZSDeDz8//o+9qZTrICVP2a4sBB8T0XmU4gxfw8FsmtoomBH1nLk3AO7wgRN2a3+SRSAmxrhIGDmF1lljSlhY32eJpJ2TZQKaWNW+7yDBU/0Wt3kQVY84vr14yYagnSCiIfqyVFqePayRtmVJDr5qvSXr51tdqs2zKZCu+26X7JAF4BSsaq4gmY5DmDTm4TohCnBduI1+bPGD+igVmtl05wIDAQAB"
+	pKey := FormatPublicKey(aliPayPublicKey)
+	err := verifySign(signData, sign, "RSA2", pKey)
+	if err != nil {
+		fmt.Println("err:", err)
+	}
+}
+
+func TestVerifySign(t *testing.T) {
+	// 测试,假数据,无法验签通过
+	bm := make(gopay.BodyMap)
+	bm.Set("sign", "kPbQIjX+xQc8F0/A6/AocELIjhhZnGbcBN6G4MM/HmfWL4ZiHM6fWl5NQhzXJusaklZ1LFuMo+lHQUELAYeugH8LYFvxnNajOvZhuxNFbN2LhF0l/KL8ANtj8oyPM4NN7Qft2kWJTDJUpQOzCzNnV9hDxh5AaT9FPqRS6ZKxnzM=")
+	bm.Set("sign_type", "RSA2")
+	bm.Set("total_amount", "2.00")
+	bm.Set("buyer_id", "2088102116773037")
+	bm.Set("body", "大乐透2.1")
+	bm.Set("trade_no", "2016071921001003030200089909")
+	bm.Set("refund_fee", "0.00")
+	bm.Set("notify_time", "2016-07-19 14:10:49")
+	bm.Set("subject", "大乐透2.1")
+	bm.Set("charset", "utf-8")
+	bm.Set("notify_type", "trade_status_sync")
+	bm.Set("out_trade_no", "0719141034-6418")
+	bm.Set("gmt_close", "2016-07-19 14:10:46")
+	bm.Set("gmt_payment", "2016-07-19 14:10:47")
+	bm.Set("trade_status", "TRADE_SUCCESS")
+	bm.Set("version", "1.0")
+	bm.Set("gmt_create", "2016-07-19 14:10:44")
+	bm.Set("app_id", "2015102700040153")
+	bm.Set("seller_id", "2088102119685838")
+	bm.Set("notify_id", "4a91b7a78a503640467525113fb7d8bg8e")
+
+	ok, err := VerifySign("aliPayPublicKey", bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("OK:", ok)
+}
+
+func TestGetCertSN(t *testing.T) {
+	sn, err := GetCertSN("cert/alipayCertPublicKey_RSA2.crt")
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	// 04afd423ea5bd6f5c5482854ed73278c
+	fmt.Println("alipayCertPublicKey_RSA2:", sn)
+
+	sn, err = GetCertSN("cert/appCertPublicKey.crt")
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	// 4498aaa8ab0c8986c15c41b36186db7d
+	fmt.Println("appCertPublicKey:", sn)
+
+	sn, err = GetRootCertSN("cert/alipayRootCert.crt")
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	// 687b59193f3f462dd5336e5abf83c5d8_02941eef3187dddf3d3b83462e1dfcf6
+	fmt.Println("alipay_root_cert_sn:", sn)
+}
+
+func TestDecryptOpenDataToBodyMap(t *testing.T) {
+	data := "MkvuiIZsGOC8S038cu/JIpoRKnF+ZFjoIRGf5d/K4+ctYjCtb/eEkwgrdB5TeH/93bxff1Ylb+SE+UGStlpvcg=="
+	key := "TDftre9FpItr46e9BVNJcw=="
+	bm, err := DecryptOpenDataToBodyMap(data, key)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("bm:", bm)
+}

+ 55 - 42
alipay_rsp.go → alipay/model.go

@@ -1,6 +1,16 @@
-package gopay
+package alipay
 
-type AliPayNotifyRequest struct {
+const (
+	// URL
+	zfbBaseUrl            = "https://openapi.alipay.com/gateway.do"
+	zfbSandboxBaseUrl     = "https://openapi.alipaydev.com/gateway.do"
+	zfbBaseUrlUtf8        = "https://openapi.alipay.com/gateway.do?charset=utf-8"
+	zfbSandboxBaseUrlUtf8 = "https://openapi.alipaydev.com/gateway.do?charset=utf-8"
+
+	locationShanghai = "Asia/Shanghai"
+)
+
+type NotifyRequest struct {
 	NotifyTime        string                   `json:"notify_time,omitempty"`
 	NotifyType        string                   `json:"notify_type,omitempty"`
 	NotifyId          string                   `json:"notify_id,omitempty"`
@@ -58,7 +68,7 @@ type voucherDetailListInfo struct {
 	PurchaseAntContribute      string `json:"purchase_ant_contribute,omitempty"`
 }
 
-type AliPayUserPhone struct {
+type UserPhone struct {
 	Code    string `json:"code,omitempty"`
 	Msg     string `json:"msg,omitempty"`
 	SubCode string `json:"subCode,omitempty"`
@@ -66,8 +76,15 @@ type AliPayUserPhone struct {
 	Mobile  string `json:"mobile,omitempty"`
 }
 
+type ErrorResponse struct {
+	Code    string `json:"code,omitempty"`
+	Msg     string `json:"msg,omitempty"`
+	SubCode string `json:"sub_code,omitempty"`
+	SubMsg  string `json:"sub_msg,omitempty"`
+}
+
 //===================================================
-type AliPayTradePayResponse struct {
+type TradePayResponse struct {
 	Response *payResponse `json:"alipay_trade_pay_response,omitempty"`
 	SignData string       `json:"-"`
 	Sign     string       `json:"sign"`
@@ -130,7 +147,7 @@ type payResponse struct {
 }
 
 //===================================================
-type AliPayTradeQueryResponse struct {
+type TradeQueryResponse struct {
 	Response *queryResponse `json:"alipay_trade_query_response,omitempty"`
 	SignData string         `json:"-"`
 	Sign     string         `json:"sign"`
@@ -193,7 +210,7 @@ type queryResponse struct {
 }
 
 //===================================================
-type AliPayTradeCreateResponse struct {
+type TradeCreateResponse struct {
 	Response *createResponse `json:"alipay_trade_create_response,omitempty"`
 	SignData string          `json:"-"`
 	Sign     string          `json:"sign"`
@@ -209,7 +226,7 @@ type createResponse struct {
 }
 
 //===================================================
-type AliPayTradeCloseResponse struct {
+type TradeCloseResponse struct {
 	Response *closeResponse `json:"alipay_trade_close_response,omitempty"`
 	SignData string         `json:"-"`
 	Sign     string         `json:"sign"`
@@ -225,9 +242,9 @@ type closeResponse struct {
 }
 
 //===================================================
-type AliPayTradeCancelResponse struct {
+type TradeCancelResponse struct {
 	Response     *cancelResponse `json:"alipay_trade_cancel_response,omitempty"`
-	AliPayCertSn string          `json:"alipay_cert_sn,omitempty"`
+	AlipayCertSn string          `json:"alipay_cert_sn,omitempty"`
 	SignData     string          `json:"-"`
 	Sign         string          `json:"sign"`
 }
@@ -246,17 +263,12 @@ type cancelResponse struct {
 }
 
 //===================================================
-type AliPaySystemOauthTokenResponse struct {
+type SystemOauthTokenResponse struct {
 	Response      *oauthTokenInfo `json:"alipay_system_oauth_token_response,omitempty"`
-	ErrorResponse *struct {
-		Code    string `json:"code,omitempty"`
-		Msg     string `json:"msg,omitempty"`
-		SubCode string `json:"sub_code,omitempty"`
-		SubMsg  string `json:"sub_msg,omitempty"`
-	} `json:"error_response,omitempty"`
-	AliPayCertSn string `json:"alipay_cert_sn,omitempty"`
-	SignData     string `json:"-"`
-	Sign         string `json:"sign"`
+	ErrorResponse *ErrorResponse  `json:"error_response,omitempty"`
+	AlipayCertSn  string          `json:"alipay_cert_sn,omitempty"`
+	SignData      string          `json:"-"`
+	Sign          string          `json:"sign"`
 }
 type oauthTokenInfo struct {
 	AccessToken  string `json:"access_token,omitempty"`
@@ -268,9 +280,9 @@ type oauthTokenInfo struct {
 }
 
 //===================================================
-type AliPayUserInfoShareResponse struct {
+type UserInfoShareResponse struct {
 	Response     *userInfoShare `json:"alipay_user_info_share_response,omitempty"`
-	AliPayCertSn string         `json:"alipay_cert_sn,omitempty"`
+	AlipayCertSn string         `json:"alipay_cert_sn,omitempty"`
 	SignData     string         `json:"-"`
 	Sign         string         `json:"sign"`
 }
@@ -293,9 +305,9 @@ type userInfoShare struct {
 }
 
 //===================================================
-type AliPayTradeRefundResponse struct {
+type TradeRefundResponse struct {
 	Response     *refundResponse `json:"alipay_trade_refund_response,omitempty"`
-	AliPayCertSn string          `json:"alipay_cert_sn,omitempty"`
+	AlipayCertSn string          `json:"alipay_cert_sn,omitempty"`
 	SignData     string          `json:"-"`
 	Sign         string          `json:"sign"`
 }
@@ -334,9 +346,9 @@ type tradeFundBill struct {
 }
 
 //===================================================
-type AliPayTradeFastpayRefundQueryResponse struct {
+type TradeFastpayRefundQueryResponse struct {
 	Response     *refundQueryResponse `json:"alipay_trade_fastpay_refund_query_response,omitempty"`
-	AliPayCertSn string               `json:"alipay_cert_sn,omitempty"`
+	AlipayCertSn string               `json:"alipay_cert_sn,omitempty"`
 	SignData     string               `json:"-"`
 	Sign         string               `json:"sign"`
 }
@@ -371,9 +383,9 @@ type refundQueryResponse struct {
 }
 
 //===================================================
-type AliPayTradeOrderSettleResponse struct {
+type TradeOrderSettleResponse struct {
 	Response     *orderSettleResponse `json:"alipay_trade_order_settle_response,omitempty"`
-	AliPayCertSn string               `json:"alipay_cert_sn,omitempty"`
+	AlipayCertSn string               `json:"alipay_cert_sn,omitempty"`
 	SignData     string               `json:"-"`
 	Sign         string               `json:"sign"`
 }
@@ -386,9 +398,10 @@ type orderSettleResponse struct {
 }
 
 //===================================================
-type AliPayTradePrecreateResponse struct {
+type TradePrecreateResponse struct {
 	Response     *precreateResponse `json:"alipay_trade_precreate_response,omitempty"`
-	AliPayCertSn string             `json:"alipay_cert_sn,omitempty"`
+	NullResponse *ErrorResponse     `json:"null_response,omitempty"`
+	AlipayCertSn string             `json:"alipay_cert_sn,omitempty"`
 	SignData     string             `json:"-"`
 	Sign         string             `json:"sign"`
 }
@@ -403,9 +416,9 @@ type precreateResponse struct {
 }
 
 //===================================================
-type AliPayTradePageRefundResponse struct {
+type TradePageRefundResponse struct {
 	Response     *pageRefundResponse `json:"alipay_trade_page_refund_response,omitempty"`
-	AliPayCertSn string              `json:"alipay_cert_sn,omitempty"`
+	AlipayCertSn string              `json:"alipay_cert_sn,omitempty"`
 	SignData     string              `json:"-"`
 	Sign         string              `json:"sign"`
 }
@@ -422,9 +435,9 @@ type pageRefundResponse struct {
 }
 
 //===================================================
-type AliPayFundTransToaccountTransferResponse struct {
+type FundTransToaccountTransferResponse struct {
 	Response     *transToaccountTransferResponse `json:"alipay_fund_trans_toaccount_transfer_response,omitempty"`
-	AliPayCertSn string                          `json:"alipay_cert_sn,omitempty"`
+	AlipayCertSn string                          `json:"alipay_cert_sn,omitempty"`
 	SignData     string                          `json:"-"`
 	Sign         string                          `json:"sign"`
 }
@@ -442,7 +455,7 @@ type transToaccountTransferResponse struct {
 //===================================================
 type ZhimaCreditScoreGetResponse struct {
 	Response     *scoreGetResponse `json:"zhima_credit_score_get_response,omitempty"`
-	AliPayCertSn string            `json:"alipay_cert_sn,omitempty"`
+	AlipayCertSn string            `json:"alipay_cert_sn,omitempty"`
 	SignData     string            `json:"-"`
 	Sign         string            `json:"sign"`
 }
@@ -457,9 +470,9 @@ type scoreGetResponse struct {
 }
 
 //===================================================
-type AliPayOpenAuthTokenAppResponse struct {
+type OpenAuthTokenAppResponse struct {
 	Response     *authTokenAppResponse `json:"alipay_open_auth_token_app_response,omitempty"`
-	AliPayCertSn string                `json:"alipay_cert_sn,omitempty"`
+	AlipayCertSn string                `json:"alipay_cert_sn,omitempty"`
 	SignData     string                `json:"-"`
 	Sign         string                `json:"sign"`
 }
@@ -486,9 +499,9 @@ type authTokenAppResponse struct {
 }
 
 //===================================================
-type AliPayUserCertifyOpenInitResponse struct {
+type UserCertifyOpenInitResponse struct {
 	Response     *userCertifyOpenInitResponse `json:"alipay_user_certify_open_initialize_response,omitempty"`
-	AliPayCertSn string                       `json:"alipay_cert_sn,omitempty"`
+	AlipayCertSn string                       `json:"alipay_cert_sn,omitempty"`
 	SignData     string                       `json:"-"`
 	Sign         string                       `json:"sign"`
 }
@@ -502,9 +515,9 @@ type userCertifyOpenInitResponse struct {
 }
 
 //===================================================
-type AliPayUserCertifyOpenCertifyResponse struct {
+type UserCertifyOpenCertifyResponse struct {
 	Response     *userCertifyOpenCertifyResponse `json:"alipay_user_certify_open_certify_response,omitempty"`
-	AliPayCertSn string                          `json:"alipay_cert_sn,omitempty"`
+	AlipayCertSn string                          `json:"alipay_cert_sn,omitempty"`
 	SignData     string                          `json:"-"`
 	Sign         string                          `json:"sign"`
 }
@@ -517,9 +530,9 @@ type userCertifyOpenCertifyResponse struct {
 }
 
 //===================================================
-type AliPayUserCertifyOpenQueryResponse struct {
+type UserCertifyOpenQueryResponse struct {
 	Response     *userCertifyOpenQueryResponse `json:"alipay_user_certify_open_query_response,omitempty"`
-	AliPayCertSn string                        `json:"alipay_cert_sn,omitempty"`
+	AlipayCertSn string                        `json:"alipay_cert_sn,omitempty"`
 	SignData     string                        `json:"-"`
 	Sign         string                        `json:"sign"`
 }

+ 37 - 19
alipay_params.go → alipay/param.go

@@ -1,4 +1,4 @@
-package gopay
+package alipay
 
 import (
 	"crypto"
@@ -12,7 +12,11 @@ import (
 	"errors"
 	"fmt"
 	"hash"
+	"log"
 	"net/url"
+	"time"
+
+	"github.com/iGoogle-ink/gopay"
 )
 
 //	AppId      string `json:"app_id"`      //支付宝分配给开发者的应用ID
@@ -37,9 +41,23 @@ type OpenApiRoyaltyDetailInfoPojo struct {
 	Desc         string `json:"desc,omitempty"`
 }
 
+// 设置 时区,不设置或出错均为默认服务器时间
+func (a *Client) SetLocation(name string) (client *Client) {
+	location, err := time.LoadLocation(name)
+	if err != nil {
+		log.Println("set Location err, default UTC")
+		return a
+	}
+	a.mu.Lock()
+	a.LocationName = name
+	a.location = location
+	a.mu.Unlock()
+	return a
+}
+
 // 设置 应用公钥证书SN
-//    appCertSN:应用公钥证书SN,通过 gopay.GetCertSN() 获取
-func (a *AliPayClient) SetAppCertSN(appCertSN string) (client *AliPayClient) {
+//    appCertSN:应用公钥证书SN,通过 alipay.GetCertSN() 获取
+func (a *Client) SetAppCertSN(appCertSN string) (client *Client) {
 	a.mu.Lock()
 	a.AppCertSN = appCertSN
 	a.mu.Unlock()
@@ -47,8 +65,8 @@ func (a *AliPayClient) SetAppCertSN(appCertSN string) (client *AliPayClient) {
 }
 
 // 设置 支付宝公钥证书SN
-//    aliPayPublicCertSN:支付宝公钥证书SN,通过 gopay.GetCertSN() 获取
-func (a *AliPayClient) SetAliPayPublicCertSN(aliPayPublicCertSN string) (client *AliPayClient) {
+//    aliPayPublicCertSN:支付宝公钥证书SN,通过 alipay.GetCertSN() 获取
+func (a *Client) SetAliPayPublicCertSN(aliPayPublicCertSN string) (client *Client) {
 	a.mu.Lock()
 	a.AliPayPublicCertSN = aliPayPublicCertSN
 	a.mu.Unlock()
@@ -56,8 +74,8 @@ func (a *AliPayClient) SetAliPayPublicCertSN(aliPayPublicCertSN string) (client
 }
 
 // 设置 支付宝CA根证书SN
-//    aliPayRootCertSN:支付宝CA根证书SN,通过 gopay.GetRootCertSN() 获取
-func (a *AliPayClient) SetAliPayRootCertSN(aliPayRootCertSN string) (client *AliPayClient) {
+//    aliPayRootCertSN:支付宝CA根证书SN,通过 alipay.GetRootCertSN() 获取
+func (a *Client) SetAliPayRootCertSN(aliPayRootCertSN string) (client *Client) {
 	a.mu.Lock()
 	a.AliPayRootCertSN = aliPayRootCertSN
 	a.mu.Unlock()
@@ -68,7 +86,7 @@ func (a *AliPayClient) SetAliPayRootCertSN(aliPayRootCertSN string) (client *Ali
 //    appCertPath:应用公钥证书路径
 //    aliPayRootCertPath:支付宝根证书文件路径
 //    aliPayPublicCertPath:支付宝公钥证书文件路径
-func (a *AliPayClient) SetCertSnByPath(appCertPath, aliPayRootCertPath, aliPayPublicCertPath string) (err error) {
+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)
@@ -90,7 +108,7 @@ func (a *AliPayClient) SetCertSnByPath(appCertPath, aliPayRootCertPath, aliPayPu
 }
 
 // 设置支付后的ReturnUrl
-func (a *AliPayClient) SetReturnUrl(url string) (client *AliPayClient) {
+func (a *Client) SetReturnUrl(url string) (client *Client) {
 	a.mu.Lock()
 	a.ReturnUrl = url
 	a.mu.Unlock()
@@ -98,7 +116,7 @@ func (a *AliPayClient) SetReturnUrl(url string) (client *AliPayClient) {
 }
 
 // 设置支付宝服务器主动通知商户服务器里指定的页面http/https路径。
-func (a *AliPayClient) SetNotifyUrl(url string) (client *AliPayClient) {
+func (a *Client) SetNotifyUrl(url string) (client *Client) {
 	a.mu.Lock()
 	a.NotifyUrl = url
 	a.mu.Unlock()
@@ -106,9 +124,9 @@ func (a *AliPayClient) SetNotifyUrl(url string) (client *AliPayClient) {
 }
 
 // 设置编码格式,如utf-8,gbk,gb2312等,默认推荐使用 utf-8
-func (a *AliPayClient) SetCharset(charset string) (client *AliPayClient) {
+func (a *Client) SetCharset(charset string) (client *Client) {
 	a.mu.Lock()
-	if charset == null {
+	if charset == gopay.NULL {
 		a.Charset = "utf-8"
 	} else {
 		a.Charset = charset
@@ -118,9 +136,9 @@ func (a *AliPayClient) SetCharset(charset string) (client *AliPayClient) {
 }
 
 // 设置签名算法类型,目前支持RSA2和RSA,默认推荐使用 RSA2
-func (a *AliPayClient) SetSignType(signType string) (client *AliPayClient) {
+func (a *Client) SetSignType(signType string) (client *Client) {
 	a.mu.Lock()
-	if signType == null {
+	if signType == gopay.NULL {
 		a.SignType = "RSA2"
 	} else {
 		a.SignType = signType
@@ -130,7 +148,7 @@ func (a *AliPayClient) SetSignType(signType string) (client *AliPayClient) {
 }
 
 // 设置应用授权
-func (a *AliPayClient) SetAppAuthToken(appAuthToken string) (client *AliPayClient) {
+func (a *Client) SetAppAuthToken(appAuthToken string) (client *Client) {
 	a.mu.Lock()
 	a.AppAuthToken = appAuthToken
 	a.mu.Unlock()
@@ -138,7 +156,7 @@ func (a *AliPayClient) SetAppAuthToken(appAuthToken string) (client *AliPayClien
 }
 
 // 设置用户信息授权
-func (a *AliPayClient) SetAuthToken(authToken string) (client *AliPayClient) {
+func (a *Client) SetAuthToken(authToken string) (client *Client) {
 	a.mu.Lock()
 	a.AuthToken = authToken
 	a.mu.Unlock()
@@ -146,7 +164,7 @@ func (a *AliPayClient) SetAuthToken(authToken string) (client *AliPayClient) {
 }
 
 // 获取参数签名
-func getRsaSign(bm BodyMap, signType, privateKey string) (sign string, err error) {
+func getRsaSign(bm gopay.BodyMap, signType, privateKey string) (sign string, err error) {
 	var (
 		block          *pem.Block
 		h              hash.Hash
@@ -156,7 +174,7 @@ func getRsaSign(bm BodyMap, signType, privateKey string) (sign string, err error
 	)
 
 	if block, _ = pem.Decode([]byte(privateKey)); block == nil {
-		return null, errors.New("pem.Decode:privateKey decode error")
+		return gopay.NULL, errors.New("pem.Decode:privateKey decode error")
 	}
 	if key, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil {
 		return
@@ -183,7 +201,7 @@ func getRsaSign(bm BodyMap, signType, privateKey string) (sign string, err error
 }
 
 // 格式化请求URL参数
-func FormatAliPayURLParam(body BodyMap) (urlParam string) {
+func FormatURLParam(body gopay.BodyMap) (urlParam string) {
 	v := url.Values{}
 	for key, value := range body {
 		v.Add(key, value.(string))

+ 47 - 45
alipay_service_api.go → alipay/service_api.go

@@ -1,4 +1,4 @@
-package gopay
+package alipay
 
 import (
 	"crypto"
@@ -19,6 +19,8 @@ import (
 	"reflect"
 	"strings"
 	"time"
+
+	"github.com/iGoogle-ink/gopay"
 )
 
 // 允许进行 sn 提取的证书签名算法
@@ -39,12 +41,12 @@ var allowSignatureAlgorithm = map[string]bool{
 //    返回参数bm:Notify请求的参数
 //    返回参数err:错误信息
 //    文档:https://docs.open.alipay.com/203/105286/
-func ParseAliPayNotifyResultToBodyMap(req *http.Request) (bm BodyMap, err error) {
+func ParseNotifyResultToBodyMap(req *http.Request) (bm gopay.BodyMap, err error) {
 	if err = req.ParseForm(); err != nil {
 		return nil, err
 	}
 	var form map[string][]string = req.Form
-	bm = make(BodyMap, len(form))
+	bm = make(gopay.BodyMap, len(form))
 	for k, v := range form {
 		if len(v) == 1 {
 			bm.Set(k, v[0])
@@ -58,8 +60,8 @@ func ParseAliPayNotifyResultToBodyMap(req *http.Request) (bm BodyMap, err error)
 //    返回参数notifyReq:Notify请求的参数
 //    返回参数err:错误信息
 //    文档:https://docs.open.alipay.com/203/105286/
-func ParseAliPayNotifyResult(req *http.Request) (notifyReq *AliPayNotifyRequest, err error) {
-	notifyReq = new(AliPayNotifyRequest)
+func ParseNotifyResult(req *http.Request) (notifyReq *NotifyRequest, err error) {
+	notifyReq = new(NotifyRequest)
 	if err = req.ParseForm(); err != nil {
 		return
 	}
@@ -95,7 +97,7 @@ func ParseAliPayNotifyResult(req *http.Request) (notifyReq *AliPayNotifyRequest,
 	notifyReq.PassbackParams = req.Form.Get("passback_params")
 
 	billList := req.Form.Get("fund_bill_list")
-	if billList != null {
+	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())
@@ -106,7 +108,7 @@ func ParseAliPayNotifyResult(req *http.Request) (notifyReq *AliPayNotifyRequest,
 	}
 
 	detailList := req.Form.Get("voucher_detail_list")
-	if detailList != null {
+	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())
@@ -134,7 +136,7 @@ A:开发者上传自己的应用公钥证书后,开放平台会为开发者
 基于该机制可实现支付宝公钥证书变更时开发者无感知,当前开放平台提供的SDK已基于该机制实现对应功能。若开发者未通过SDK接入,须自行实现该功能。
 */
 
-// VerifyAliPaySyncSign 支付宝同步返回验签
+// VerifySyncSign 支付宝同步返回验签
 //    注意:APP支付,手机网站支付,电脑网站支付 暂不支持同步返回验签
 //    aliPayPublicKey:支付宝公钥
 //    signData:待验签参数,aliRsp.SignData
@@ -142,24 +144,24 @@ A:开发者上传自己的应用公钥证书后,开放平台会为开发者
 //    返回参数ok:是否验签通过
 //    返回参数err:错误信息
 //    验签文档:https://docs.open.alipay.com/200/106120
-func VerifyAliPaySyncSign(aliPayPublicKey, signData, sign string) (ok bool, err error) {
+func VerifySyncSign(aliPayPublicKey, signData, sign string) (ok bool, err error) {
 
 	// 支付宝公钥验签
-	pKey := FormatAliPayPublicKey(aliPayPublicKey)
-	if err = verifyAliPaySign(signData, sign, "RSA2", pKey); err != nil {
+	pKey := FormatPublicKey(aliPayPublicKey)
+	if err = verifySign(signData, sign, "RSA2", pKey); err != nil {
 		return false, err
 	}
 	return true, nil
 }
 
-// VerifyAliPaySign 支付宝异步通知验签
+// VerifySign 支付宝异步通知验签
 //    注意:APP支付,手机网站支付,电脑网站支付 暂不支持同步返回验签
 //    aliPayPublicKey:支付宝公钥
 //    bean:此参数为异步通知解析的结构体或BodyMap:notifyReq 或 bm
 //    返回参数ok:是否验签通过
 //    返回参数err:错误信息
 //    验签文档:https://docs.open.alipay.com/200/106120
-func VerifyAliPaySign(aliPayPublicKey string, bean interface{}) (ok bool, err error) {
+func VerifySign(aliPayPublicKey string, bean interface{}) (ok bool, err error) {
 	if bean == nil {
 		return false, errors.New("bean is nil")
 	}
@@ -167,10 +169,10 @@ func VerifyAliPaySign(aliPayPublicKey string, bean interface{}) (ok bool, err er
 		bodySign     string
 		bodySignType string
 		signData     string
-		bm           = make(BodyMap)
+		bm           = make(gopay.BodyMap)
 	)
 	if reflect.ValueOf(bean).Kind() == reflect.Map {
-		if bm, ok = bean.(BodyMap); ok {
+		if bm, ok = bean.(gopay.BodyMap); ok {
 			bodySign = bm.Get("sign")
 			bodySignType = bm.Get("sign_type")
 			bm.Remove("sign")
@@ -191,14 +193,14 @@ func VerifyAliPaySign(aliPayPublicKey string, bean interface{}) (ok bool, err er
 		bm.Remove("sign_type")
 		signData = bm.EncodeAliPaySignParams()
 	}
-	pKey := FormatAliPayPublicKey(aliPayPublicKey)
-	if err = verifyAliPaySign(signData, bodySign, bodySignType, pKey); err != nil {
+	pKey := FormatPublicKey(aliPayPublicKey)
+	if err = verifySign(signData, bodySign, bodySignType, pKey); err != nil {
 		return false, err
 	}
 	return true, nil
 }
 
-func verifyAliPaySign(signData, sign, signType, aliPayPublicKey string) (err error) {
+func verifySign(signData, sign, signType, aliPayPublicKey string) (err error) {
 	var (
 		h         hash.Hash
 		hashs     crypto.Hash
@@ -258,8 +260,8 @@ func FormatPrivateKey(privateKey string) (pKey string) {
 	return
 }
 
-// FormatAliPayPublicKey 格式化 普通支付宝公钥
-func FormatAliPayPublicKey(publicKey string) (pKey string) {
+// FormatPublicKey 格式化 普通支付宝公钥
+func FormatPublicKey(publicKey string) (pKey string) {
 	var buffer strings.Builder
 	buffer.WriteString("-----BEGIN PUBLIC KEY-----\n")
 	rawLen := 64
@@ -293,13 +295,13 @@ func FormatAliPayPublicKey(publicKey string) (pKey string) {
 func GetCertSN(certPath string) (sn string, err error) {
 	certData, err := ioutil.ReadFile(certPath)
 	if err != nil {
-		return null, err
+		return gopay.NULL, err
 	}
 
 	if block, _ := pem.Decode(certData); block != nil {
 		cert, err := x509.ParseCertificate(block.Bytes)
 		if err != nil {
-			return null, err
+			return gopay.NULL, err
 		}
 		name := cert.Issuer.String()
 		serialNumber := cert.SerialNumber.String()
@@ -308,8 +310,8 @@ func GetCertSN(certPath string) (sn string, err error) {
 		h.Write([]byte(serialNumber))
 		sn = hex.EncodeToString(h.Sum(nil))
 	}
-	if sn == null {
-		return null, errors.New("failed to get sn,please check your cert")
+	if sn == gopay.NULL {
+		return gopay.NULL, errors.New("failed to get sn,please check your cert")
 	}
 	return sn, nil
 }
@@ -323,7 +325,7 @@ func GetRootCertSN(rootCertPath string) (sn string, err error) {
 
 	certData, err := ioutil.ReadFile(rootCertPath)
 	if err != nil {
-		return null, err
+		return gopay.NULL, err
 	}
 
 	pems := strings.Split(string(certData), certEnd)
@@ -341,26 +343,26 @@ func GetRootCertSN(rootCertPath string) (sn string, err error) {
 			h := md5.New()
 			h.Write([]byte(name))
 			h.Write([]byte(serialNumber))
-			if sn == null {
+			if sn == gopay.NULL {
 				sn += hex.EncodeToString(h.Sum(nil))
 			} else {
 				sn += "_" + hex.EncodeToString(h.Sum(nil))
 			}
 		}
 	}
-	if sn == null {
-		return null, errors.New("failed to get sn,please check your cert")
+	if sn == gopay.NULL {
+		return gopay.NULL, errors.New("failed to get sn,please check your cert")
 	}
 	return sn, nil
 }
 
-// DecryptAliPayOpenDataToStruct 解密支付宝开放数据到 结构体
+// DecryptOpenDataToStruct 解密支付宝开放数据到 结构体
 //    encryptedData:包括敏感数据在内的完整用户信息的加密数据
 //    secretKey:AES密钥,支付宝管理平台配置
 //    beanPtr:需要解析到的结构体指针
 //    文档:https://docs.alipay.com/mini/introduce/aes
 //    文档:https://docs.open.alipay.com/common/104567
-func DecryptAliPayOpenDataToStruct(encryptedData, secretKey string, beanPtr interface{}) (err error) {
+func DecryptOpenDataToStruct(encryptedData, secretKey string, beanPtr interface{}) (err error) {
 	beanValue := reflect.ValueOf(beanPtr)
 	if beanValue.Kind() != reflect.Ptr {
 		return errors.New("传入参数类型必须是以指针形式")
@@ -386,7 +388,7 @@ func DecryptAliPayOpenDataToStruct(encryptedData, secretKey string, beanPtr inte
 	originData = make([]byte, len(secretData))
 	blockMode.CryptBlocks(originData, secretData)
 	if len(originData) > 0 {
-		originData = PKCS5UnPadding(originData)
+		originData = gopay.PKCS5UnPadding(originData)
 	}
 	if err = json.Unmarshal(originData, beanPtr); err != nil {
 		return fmt.Errorf("json.Unmarshal:%s", err.Error())
@@ -394,12 +396,12 @@ func DecryptAliPayOpenDataToStruct(encryptedData, secretKey string, beanPtr inte
 	return nil
 }
 
-// DecryptAliPayOpenDataToBodyMap 解密支付宝开放数据到 BodyMap
+// DecryptOpenDataToBodyMap 解密支付宝开放数据到 BodyMap
 //    encryptedData:包括敏感数据在内的完整用户信息的加密数据
 //    secretKey:AES密钥,支付宝管理平台配置
 //    文档:https://docs.alipay.com/mini/introduce/aes
 //    文档:https://docs.open.alipay.com/common/104567
-func DecryptAliPayOpenDataToBodyMap(encryptedData, secretKey string) (bm BodyMap, err error) {
+func DecryptOpenDataToBodyMap(encryptedData, secretKey string) (bm gopay.BodyMap, err error) {
 	var (
 		aesKey, originData []byte
 		ivKey              = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
@@ -418,24 +420,24 @@ func DecryptAliPayOpenDataToBodyMap(encryptedData, secretKey string) (bm BodyMap
 	originData = make([]byte, len(secretData))
 	blockMode.CryptBlocks(originData, secretData)
 	if len(originData) > 0 {
-		originData = PKCS5UnPadding(originData)
+		originData = gopay.PKCS5UnPadding(originData)
 	}
-	bm = make(BodyMap)
+	bm = make(gopay.BodyMap)
 	if err = json.Unmarshal(originData, &bm); err != nil {
 		return nil, fmt.Errorf("json.Unmarshal:%s", err.Error())
 	}
 	return
 }
 
-// AliPaySystemOauthToken 换取授权访问令牌(默认使用utf-8,RSA2)
+// SystemOauthToken 换取授权访问令牌(默认使用utf-8,RSA2)
 //    appId:应用ID
 //    PrivateKey:应用私钥
 //    grantType:值为 authorization_code 时,代表用code换取;值为 refresh_token 时,代表用refresh_token换取,传空默认code换取
 //    codeOrToken:支付宝授权码或refresh_token
 //    文档:https://docs.open.alipay.com/api_9/alipay.system.oauth.token
-func AliPaySystemOauthToken(appId, privateKey, grantType, codeOrToken string) (rsp *AliPaySystemOauthTokenResponse, err error) {
+func SystemOauthToken(appId, privateKey, grantType, codeOrToken string) (rsp *SystemOauthTokenResponse, err error) {
 	var bs []byte
-	bm := make(BodyMap)
+	bm := make(gopay.BodyMap)
 	if "authorization_code" == grantType {
 		bm.Set("grant_type", "authorization_code")
 		bm.Set("code", codeOrToken)
@@ -446,27 +448,27 @@ func AliPaySystemOauthToken(appId, privateKey, grantType, codeOrToken string) (r
 		bm.Set("grant_type", "authorization_code")
 		bm.Set("code", codeOrToken)
 	}
-	if bs, err = aliPaySystemOauthToken(appId, privateKey, bm, "alipay.system.oauth.token", true); err != nil {
+	if bs, err = systemOauthToken(appId, privateKey, bm, "alipay.system.oauth.token", true); err != nil {
 		return
 	}
-	rsp = new(AliPaySystemOauthTokenResponse)
+	rsp = new(SystemOauthTokenResponse)
 	if err = json.Unmarshal(bs, rsp); err != nil {
 		return nil, fmt.Errorf("json.Unmarshal:%s", err.Error())
 	}
 	if rsp.Response.AccessToken == "" {
-		return nil, errors.New("access_token is null")
+		return nil, errors.New("access_token is NULL")
 	}
 	return
 }
 
-// aliPaySystemOauthToken 向支付宝发送请求
-func aliPaySystemOauthToken(appId, privateKey string, body BodyMap, method string, isProd bool) (bs []byte, err error) {
+// systemOauthToken 向支付宝发送请求
+func systemOauthToken(appId, privateKey string, body gopay.BodyMap, method string, isProd bool) (bs []byte, err error) {
 	body.Set("app_id", appId)
 	body.Set("method", method)
 	body.Set("format", "JSON")
 	body.Set("charset", "utf-8")
 	body.Set("sign_type", "RSA2")
-	body.Set("timestamp", time.Now().Format(TimeLayout))
+	body.Set("timestamp", time.Now().Format(gopay.TimeLayout))
 	body.Set("version", "1.0")
 	var (
 		sign string
@@ -480,7 +482,7 @@ func aliPaySystemOauthToken(appId, privateKey string, body BodyMap, method strin
 	if !isProd {
 		url = zfbSandboxBaseUrlUtf8
 	}
-	_, bs, errs := NewHttpClient().Type(TypeForm).Post(url).SendString(FormatAliPayURLParam(body)).EndBytes()
+	_, bs, errs := gopay.NewHttpClient().Type(gopay.TypeForm).Post(url).SendString(FormatURLParam(body)).EndBytes()
 	if len(errs) > 0 {
 		return nil, errs[0]
 	}

+ 0 - 144
alipay_client_test.go

@@ -1,144 +0,0 @@
-package gopay
-
-import (
-	"encoding/json"
-	"fmt"
-	"strings"
-	"testing"
-)
-
-type List struct {
-	BillList []fundBillListInfo `json:"bill_list"`
-}
-
-func TestJsonToString(t *testing.T) {
-
-	list := new(List)
-	infos := make([]fundBillListInfo, 0)
-
-	infos = append(infos, fundBillListInfo{Amount: "1.0.0", FundChannel: "iguiyu"})
-	infos = append(infos, fundBillListInfo{Amount: "2.0.2", FundChannel: "Jerry"})
-
-	list.BillList = infos
-
-	bs, err := json.Marshal(list)
-	if err != nil {
-		fmt.Println("err:", err)
-		return
-	}
-	fmt.Println("string:", string(bs))
-}
-
-type People struct {
-	Name string `json:"name,omitempty"`
-	Age  int    `json:"age,omitempty"`
-	List []*struct {
-		Address string `json:"address,omitempty"`
-		Age     int    `json:"age,omitempty"`
-		Phone   string `json:"phone,omitempty"`
-	} `json:"list,omitempty"`
-}
-
-func TestAliPayParams(t *testing.T) {
-	bodyMap := make(BodyMap)
-
-	//people := new(People)
-	//people.Name = "Jerry"
-	//people.Age = 18
-	people := make(map[string]interface{})
-	people["name"] = "jerry"
-	people["age"] = 18
-	bodyMap.Set("people", people)
-
-	fmt.Println("result:", bodyMap.Get("people"))
-}
-
-func TestSyncVerifyAliPaySign(t *testing.T) {
-	signData := `{"code":"10000","msg":"Success","buyer_logon_id":"854***@qq.com","buyer_pay_amount":"0.01","buyer_user_id":"2088102363632794","fund_bill_list":[{"amount":"0.01","fund_channel":"PCREDIT"}],"gmt_payment":"2019-08-29 20:14:05","invoice_amount":"0.01","out_trade_no":"GZ201901301040361012","point_amount":"0.00","receipt_amount":"0.01","total_amount":"0.01","trade_no":"2019082922001432790585537960"}`
-	sign := "bk3SzX0CZRI811IJioS2XKQHcgMixUT8mYyGQj+vcOAQas7GIYi6LpykqqSc3m7+yvqoG0TdX/c2JjYnpw/J53JxtC2IC4vsLuIPIgghVo5qafsfSxEJ22w20RZDatI2dYqFVcj8Jp+4aesQ8zMMNw7cX9NLyk7kw3DecYeyQp+zrZMueZPqLh88Z+54G+e6QuSU++0ouqQVd4PkpPqy6YI+8MdMUX4Ve0jOQxMmYH8BC6n5ZsTH/uEaLEtzYVZdSw/xdSQ7K1SH73aEH8XbRYx6rL7RkKksrdvhezX+ThDjQ+fTWjvNFrGcg3fmqXRy2elvoalu+BQmqlkWWjEJYA=="
-	aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp8gueNlkbiDidz6FBQEBpqoRgH8h7JtsPtYW0nzAqy1MME4mFnDSMfSKlreUomS3a55gmBopL1eF4/Km/dEnaL5tCY9+24SKn1D4iyls+lvz/ZjvUjVwxoUYBh8kkcxMZSDeDz8//o+9qZTrICVP2a4sBB8T0XmU4gxfw8FsmtoomBH1nLk3AO7wgRN2a3+SRSAmxrhIGDmF1lljSlhY32eJpJ2TZQKaWNW+7yDBU/0Wt3kQVY84vr14yYagnSCiIfqyVFqePayRtmVJDr5qvSXr51tdqs2zKZCu+26X7JAF4BSsaq4gmY5DmDTm4TohCnBduI1+bPGD+igVmtl05wIDAQAB"
-	pKey := FormatAliPayPublicKey(aliPayPublicKey)
-	err := verifyAliPaySign(signData, sign, "RSA2", pKey)
-	if err != nil {
-		fmt.Println("err:", err)
-	}
-}
-
-func TestVerifyAliPaySign(t *testing.T) {
-	// 测试,假数据,无法验签通过
-	bm := make(BodyMap)
-	bm.Set("sign", "kPbQIjX+xQc8F0/A6/AocELIjhhZnGbcBN6G4MM/HmfWL4ZiHM6fWl5NQhzXJusaklZ1LFuMo+lHQUELAYeugH8LYFvxnNajOvZhuxNFbN2LhF0l/KL8ANtj8oyPM4NN7Qft2kWJTDJUpQOzCzNnV9hDxh5AaT9FPqRS6ZKxnzM=")
-	bm.Set("sign_type", "RSA2")
-	bm.Set("total_amount", "2.00")
-	bm.Set("buyer_id", "2088102116773037")
-	bm.Set("body", "大乐透2.1")
-	bm.Set("trade_no", "2016071921001003030200089909")
-	bm.Set("refund_fee", "0.00")
-	bm.Set("notify_time", "2016-07-19 14:10:49")
-	bm.Set("subject", "大乐透2.1")
-	bm.Set("charset", "utf-8")
-	bm.Set("notify_type", "trade_status_sync")
-	bm.Set("out_trade_no", "0719141034-6418")
-	bm.Set("gmt_close", "2016-07-19 14:10:46")
-	bm.Set("gmt_payment", "2016-07-19 14:10:47")
-	bm.Set("trade_status", "TRADE_SUCCESS")
-	bm.Set("version", "1.0")
-	bm.Set("gmt_create", "2016-07-19 14:10:44")
-	bm.Set("app_id", "2015102700040153")
-	bm.Set("seller_id", "2088102119685838")
-	bm.Set("notify_id", "4a91b7a78a503640467525113fb7d8bg8e")
-
-	ok, err := VerifyAliPaySign("aliPayPublicKey", bm)
-	if err != nil {
-		fmt.Println("err:", err)
-		return
-	}
-	fmt.Println("OK:", ok)
-}
-func TestSubString(t *testing.T) {
-	str := `{"alipay_trade_pay_response":{"code":"10000","msg":"Success","buyer_logon_id":"854***@qq.com","buyer_pay_amount":"0.01","buyer_user_id":"2088102363632794","fund_bill_list":[{"amount":"0.01","fund_channel":"PCREDIT"}],"gmt_payment":"2019-08-29 20:22:02","invoice_amount":"0.01","out_trade_no":"GZ201901301040361013","point_amount":"0.00","receipt_amount":"0.01","total_amount":"0.01","trade_no":"2019082922001432790585666965"},"sign":"DSX/wmE0nnuxQrWfJZtq0fNntcx5UYtVV35P2VZpoTC2KlIWr4eGNiXcetbb7AkI/1Tyd0+cNtcGMgB7SYzTB15/wDE0vJ+eT5ucqhNkER1kcuCC0k9OkZzU5w8wCJzOgAy52Wso9KnrwkY86mJWt3dC8DNCCi1rlf1a8bTGIBG/diJaKAgP1lGT3aW8jeGGM98zLabqDUNvck2qkgctGR49kBb0ZYmIzmY0x5goVyKnaCkcC/d1VTIIMz81mJbeqU8UZk6TqEplCC8J+dYEUj04pAO4/lwIg/YZdKj3Pz1136/+uy669Pew88+74J/u/zPsehC44PxcUk9YKmkNyw=="}`
-
-	index := strings.Index(str, `":`)
-	fmt.Println("index:", index)
-	indexEnd := strings.Index(str, `,"sign"`)
-	fmt.Println("indexEnd:", indexEnd)
-
-	fmt.Println("sub:", str[index+2:indexEnd])
-}
-
-func TestGetCertSN(t *testing.T) {
-	sn, err := GetCertSN("alipay_cert/alipayCertPublicKey_RSA2.crt")
-	if err != nil {
-		fmt.Println("err:", err)
-		return
-	}
-	// 04afd423ea5bd6f5c5482854ed73278c
-	fmt.Println("alipayCertPublicKey_RSA2:", sn)
-
-	sn, err = GetCertSN("alipay_cert/appCertPublicKey.crt")
-	if err != nil {
-		fmt.Println("err:", err)
-		return
-	}
-	// 4498aaa8ab0c8986c15c41b36186db7d
-	fmt.Println("appCertPublicKey:", sn)
-
-	sn, err = GetRootCertSN("alipay_cert/alipayRootCert.crt")
-	if err != nil {
-		fmt.Println("err:", err)
-		return
-	}
-	// 687b59193f3f462dd5336e5abf83c5d8_02941eef3187dddf3d3b83462e1dfcf6
-	fmt.Println("alipay_root_cert_sn:", sn)
-}
-
-func TestDecryptAliPayOpenDataToBodyMap(t *testing.T) {
-	data := "MkvuiIZsGOC8S038cu/JIpoRKnF+ZFjoIRGf5d/K4+ctYjCtb/eEkwgrdB5TeH/93bxff1Ylb+SE+UGStlpvcg=="
-	key := "TDftre9FpItr46e9BVNJcw=="
-	bm, err := DecryptAliPayOpenDataToBodyMap(data, key)
-	if err != nil {
-		fmt.Println("err:", err)
-		return
-	}
-	fmt.Println("bm:", bm)
-}

+ 41 - 18
body_map.go

@@ -3,47 +3,52 @@ package gopay
 import (
 	"encoding/json"
 	"encoding/xml"
+	"errors"
 	"io"
 	"sort"
 	"strings"
+	"sync"
 )
 
 type BodyMap map[string]interface{}
 
+var mu sync.RWMutex
+
 // 设置参数
 func (bm BodyMap) Set(key string, value interface{}) {
+	mu.Lock()
 	bm[key] = value
+	mu.Unlock()
 }
 
 // 获取参数
 func (bm BodyMap) Get(key string) string {
 	if bm == nil {
-		return null
+		return NULL
 	}
-	var (
-		value interface{}
-		ok    bool
-		v     string
-	)
-	if value, ok = bm[key]; !ok {
-		return null
+	mu.RLock()
+	defer mu.RUnlock()
+	value, ok := bm[key]
+	if !ok {
+		return NULL
 	}
-	if v, ok = value.(string); ok {
-		return v
+	v, ok := value.(string)
+	if !ok {
+		return convertToString(value)
 	}
-	return convertToString(value)
+	return v
 }
 
 func convertToString(v interface{}) (str string) {
 	if v == nil {
-		return null
+		return NULL
 	}
 	var (
 		bs  []byte
 		err error
 	)
 	if bs, err = json.Marshal(v); err != nil {
-		return null
+		return NULL
 	}
 	str = string(bs)
 	return
@@ -51,7 +56,9 @@ func convertToString(v interface{}) (str string) {
 
 // 删除参数
 func (bm BodyMap) Remove(key string) {
+	mu.Lock()
 	delete(bm, key)
+	mu.Unlock()
 }
 
 type xmlMapMarshal struct {
@@ -68,12 +75,12 @@ func (bm BodyMap) MarshalXML(e *xml.Encoder, start xml.StartElement) (err error)
 	if len(bm) == 0 {
 		return nil
 	}
-	start.Name = xml.Name{null, "xml"}
+	start.Name = xml.Name{NULL, "xml"}
 	if err = e.EncodeToken(start); err != nil {
 		return
 	}
 	for k := range bm {
-		if v := bm.Get(k); v != null {
+		if v := bm.Get(k); v != NULL {
 			e.Encode(xmlMapMarshal{XMLName: xml.Name{Local: k}, Value: v})
 		}
 	}
@@ -100,12 +107,14 @@ func (bm BodyMap) EncodeWeChatSignParams(apiKey string) string {
 		buf     strings.Builder
 		keyList []string
 	)
+	mu.RLock()
 	for k := range bm {
 		keyList = append(keyList, k)
 	}
 	sort.Strings(keyList)
+	mu.RUnlock()
 	for _, k := range keyList {
-		if v := bm.Get(k); v != null {
+		if v := bm.Get(k); v != NULL {
 			buf.WriteString(k)
 			buf.WriteByte('=')
 			buf.WriteString(v)
@@ -124,13 +133,14 @@ func (bm BodyMap) EncodeAliPaySignParams() string {
 		buf     strings.Builder
 		keyList []string
 	)
-	keyList = make([]string, 0, len(bm))
+	mu.RLock()
 	for k := range bm {
 		keyList = append(keyList, k)
 	}
 	sort.Strings(keyList)
+	mu.RUnlock()
 	for _, k := range keyList {
-		if v := bm.Get(k); v != null {
+		if v := bm.Get(k); v != NULL {
 			buf.WriteString(k)
 			buf.WriteByte('=')
 			buf.WriteString(v)
@@ -139,3 +149,16 @@ func (bm BodyMap) EncodeAliPaySignParams() string {
 	}
 	return buf.String()[:buf.Len()-1]
 }
+
+func (bm BodyMap) CheckEmptyError(keys ...string) error {
+	var emptyKeys []string
+	for _, k := range keys {
+		if v := bm.Get(k); v == NULL {
+			emptyKeys = append(emptyKeys, k)
+		}
+	}
+	if len(emptyKeys) > 0 {
+		return errors.New(strings.Join(emptyKeys, ", ") + " : cannot be empty")
+	}
+	return nil
+}

+ 0 - 75
constant.go

@@ -1,75 +0,0 @@
-package gopay
-
-const (
-	null       string = ""
-	TimeLayout string = "2006-01-02 15:04:05"
-	DateLayout string = "2006-01-02"
-	Version    string = "1.4.8"
-	// 微信
-	// ===========================================================================================
-
-	// 境外国家地区
-	China         Country = 1 // 中国国内
-	China2        Country = 2 // 中国国内(冗灾方案)
-	SoutheastAsia Country = 3 // 东南亚
-	Other         Country = 4 // 其他国家
-
-	// URL
-	wxBaseUrlCh  = "https://api.mch.weixin.qq.com/"   //中国国内
-	wxBaseUrlCh2 = "https://api2.mch.weixin.qq.com/"  //中国国内
-	wxBaseUrlHk  = "https://apihk.mch.weixin.qq.com/" //东南亚
-	wxBaseUrlUs  = "https://apius.mch.weixin.qq.com/" //其他
-
-	// 正式
-	wxMicropay          = "pay/micropay"                          //提交付款码支付
-	wxUnifiedorder      = "pay/unifiedorder"                      //统一下单
-	wxOrderquery        = "pay/orderquery"                        //查询订单
-	wxCloseorder        = "pay/closeorder"                        //关闭订单
-	wxRefund            = "secapi/pay/refund"                     //申请退款
-	wxReverse           = "secapi/pay/reverse"                    //撤销订单
-	wxRefundquery       = "pay/refundquery"                       //查询退款
-	wxDownloadbill      = "pay/downloadbill"                      //下载对账单
-	wxDownloadfundflow  = "pay/downloadfundflow"                  //下载资金账单
-	wxBatchquerycomment = "billcommentsp/batchquerycomment"       //拉取订单评价数据
-	wxTransfers         = "mmpaymkttransfers/promotion/transfers" //企业向微信用户个人付款
-	wxEntrustPublic     = "papay/entrustweb"                      //公众号纯签约
-	wxEntrustApp        = "papay/preentrustweb"                   //APP纯签约
-	wxEntrustH5         = "papay/h5entrustweb"                    //H5纯签约
-	wxEntrustQuery      = "papay/querycontract"                   //查询签约关系
-	wxEntrustDelete     = "papay/deletecontract"                  //申请解约
-	wxEntrustApplyPay   = "pay/pappayapply"                       //申请扣款
-	wxEntrustQueryOrder = "pay/paporderquery"                     //查询扣款订单
-
-	// SanBox
-	wxSandboxGetsignkey        = "https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey"
-	wxSandboxMicropay          = "sandboxnew/pay/micropay"
-	wxSandboxUnifiedorder      = "sandboxnew/pay/unifiedorder"
-	wxSandboxOrderquery        = "sandboxnew/pay/orderquery"
-	wxSandboxCloseorder        = "sandboxnew/pay/closeorder"
-	wxSandboxRefund            = "sandboxnew/pay/refund"
-	wxSandboxReverse           = "sandboxnew/pay/reverse"
-	wxSandboxRefundquery       = "sandboxnew/pay/refundquery"
-	wxSandboxDownloadbill      = "sandboxnew/pay/downloadbill"
-	wxSandboxDownloadfundflow  = "sandboxnew/pay/downloadfundflow"
-	wxSandboxBatchquerycomment = "sandboxnew/billcommentsp/batchquerycomment"
-
-	// 支付类型
-	TradeType_Mini   = "JSAPI"
-	TradeType_JsApi  = "JSAPI"
-	TradeType_App    = "APP"
-	TradeType_H5     = "MWEB"
-	TradeType_Native = "NATIVE"
-
-	// 签名方式
-	SignType_MD5         = "MD5"
-	SignType_HMAC_SHA256 = "HMAC-SHA256"
-
-	// 支付宝
-	// ==========================================================================================
-
-	// URL
-	zfbBaseUrl            = "https://openapi.alipay.com/gateway.do"
-	zfbSandboxBaseUrl     = "https://openapi.alipaydev.com/gateway.do"
-	zfbBaseUrlUtf8        = "https://openapi.alipay.com/gateway.do?charset=utf-8"
-	zfbSandboxBaseUrlUtf8 = "https://openapi.alipaydev.com/gateway.do?charset=utf-8"
-)

+ 6 - 4
examples/alipay/alipay_AlipayFundTransToaccountTransfer.go → examples/alipay/alipay_FundTransToaccountTransfer.go

@@ -4,18 +4,20 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayFundTransToaccountTransfer() {
+func FundTransToaccountTransfer() {
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2")
+
 	//请求参数
 	body := make(gopay.BodyMap)
 	out_biz_no := gopay.GetRandomString(32)
@@ -26,8 +28,8 @@ func AliPayFundTransToaccountTransfer() {
 	body.Set("payer_show_name", "发钱人名字")
 	body.Set("payee_real_name", "沙箱环境")
 	body.Set("remark", "转账测试")
-	//创建订单
-	aliRsp, err := client.AliPayFundTransToaccountTransfer(body)
+	//转账
+	aliRsp, err := client.FundTransToaccountTransfer(body)
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 5 - 3
examples/alipay/alipay_AlipayOpenAuthTokenApp.go → examples/alipay/alipay_OpenAuthTokenApp.go

@@ -4,25 +4,27 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayOpenAuthTokenApp() {
+func OpenAuthTokenApp() {
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//privateKey := "MIIEowIBAAKCAQEAu8U3O5C6g1KRyZySX1NiVbakSk6+rE5GBt7xEPsRXEtaRsL3YQQOC95+0pGaLTvGTkzZ2sfSZ6mvl9ryYQ1uBAAqSoGWm24djxpwm7JJrkbOsTiKCmB4JnI5xIvvoLZApwtC4USlNSytxXMoxSrTc6lo41ev0ENnh4+dhL9iokLH35uGjHyVi8ovCpo940X8BIlmta3WBGmLIU3s5xGwUwqRHFlWySxaCuEuhhQsodAoqWV9HpM549uVXZCiqkUDugUnfIaUM7vlgMgNa0ol81a7GdQnqmqyg7XMH81chPWWrUQCo5E7oXWXFwSMraNwZbw4qBZYMGLGuKqNqbscqwIDAQABAoIBAC9f38KYjmZJs9yxM0D30cycazEQUw04JnTfVOUa41Ns85b849tHYZ/fABJyh/q3pR3mR+TqG4zqBBKFPDf+Ym6B+CmaLnyCuNR9MEIoJmzhEo8mG7Xohwf0M90CDXB36zH6JmKdpi0XW7SAjJ3KY1VAPeV2Hzalev553p06iFE1pp4wtvF/XFeensGQG58tBCDuzhzxNMZfDqOJPx35Q5HIuW5CS1JdclY7SZol7i5HtgaSkjVQ/3wKRZCK4nTOoQW5uh4ogdI4KKDX7cFmQESxMNsCo+A9oQYOoD7yw9wsCkENlPyUDbAcFNFTDWpOAVXn/M0jQWQDzaT7GlhrqlkCgYEA+QFTewivhL+nmbcTrgscyzFNeoeBOct9MH8YJNWIblKT35Lg0HT1UAW9Jey46d6al+Xz/0sM0c+3nbYb9Va2oPahW70hmbTchBrqKAh/svb9yCeWw5i6NuzUNRZ5kz5ufr42XRRVNR2IJ2Av4RGfVA7W/uhAnIZBPngk5CoyfgcCgYEAwQuH9DH46fvKTB+B1kDngpKQw9Jn2ZXVz8dyYnhdH/SZgohwD/jTldx9ck42bFw4+3qHI6DJSxBxqeuaGQqmD5Y3YStP3Gb33EABACpLt1NV4AId8rWfrizJTxy5+PJONHNmDNL0Fyv53qtsG1rv+Unye6Pfeo6pkKmK49u/Az0CgYEAtR3Oz934dNFGohs1GFIC5pT86xPm3dfyPjUjpZ8ftkcgQe2+0kFQMZ2LACvYMFv3DGd5e4bmUzIIN5G/cktZWWkq4uSFrRyNjRVanjXYVJ8s5spM8gaD4/GNRPQNCBnQGyZVuoxQkeriHunqyYWc43JL1Wuvm2pXyI1xH/jFcz8CgYB1IN34mGmC7rcrwOIycWcGno8fgYZpSrRUQZtxi75VKUALJ2V3C261uvaSaEo1LS+Vxh5Ay8nWtb+BbeYt03w2cNphJrpp7D/vbxYsV31hWjr8k8w/+1tLfvkV+0QLfFlfEbWVill3xcLyC+ioIGECTI/H3QI3hl/z2irfXfFjsQKBgA+vBD22XWD1drUccPA0mMJdVMW/yrd3HVbHLVHaNqkdPFUAN8k27icXxdE2gKoHWmDeW0SZ5Wm7Hc+79f222ZS401vzlL78sIXBydYlsxn3zDowt5U9WTDPVxoqx+aStUriDPiV3fnxj9D/Q4IAEYlqI1gjRBF1o15zRFQZAkJv"
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2")
+
 	//请求参数
 	body := make(gopay.BodyMap)
 	body.Set("grant_type", "authorization_code")
 	body.Set("code", "866185490c4e40efa9f71efea6766X02")
 	//发起请求
-	aliRsp, err := client.AliPayOpenAuthTokenApp(body)
+	aliRsp, err := client.OpenAuthTokenApp(body)
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 26 - 17
examples/alipay/alipay_ServiceApi.go

@@ -5,38 +5,38 @@ import (
 	"log"
 	"net/http"
 
-	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
 func FormatPrivateKey() {
 	privateKey := "MIIEowIBAAKCAQEAxorj0SisU93LxawVWybZzDYfq8bxzw9VIOKDSW1M5ombl/MvZTT9IuBSGvqUxXFSWqY05e+CBlquFrOHTzKttmzeZJEKHpGAkW+4TsX6N4ZCHfz3Sz5MBAzBqQvscUD0FTZ+VlQbQ1HjQiKLbHaNY+fFVn3q2XL6dNtWwFhad592M1lCbzEjZ7yqFcxJ0jIDBh1lWwemHu52iW3YkvLD5lE8IXRiJedhgPFXCFAkX5HLcc0/jicRTarQ9gRNpHC6B87T2SDjKmgxqcws4CVdYJbztU1KLrsbMALFMOp24x8xsLgR88XeraQyUWe6V3lt1OYEOd9XLHWRx33bRHSwIDAQABAoIBAHjrGfjG1r11Nae8OH19WeRfikZqMdcztVsD2YWcxdsaL+MJPvJapVjaWecIehcN/2QqGcl4Zy5Lh/9Xc68uZFHYWFHTa+BWKYFqE0wWk1/Bqv7slAgFdvJ4enHkSypmrsFEoQkezEPh2ZDrzRJP2ajg/XTB14h72EHXXCxlIyP6q9ldlHyYSc+KOdC3WYOg1FoFXsliZHVKGZUxo4jck+xwdTGRAIKYpdLjpw7DqAWS6N25cx4XK9GuBYoV7AkIM0kpdjDDXAciG2aws6ef4kumWuW/JSbdrFWGLdiAN8GVpBx6+9WTeDKerS9KyDLNf6rsz9Hm3LNWOYCMLlrEFiECgYEA/XB6pZGrbmSebn2lZO+WFs3LYCXoCUy4ePouLYZO7lKsHNeTYRxCc6cbEmap0hpuMCYVPJkqK+nL/CDwBad1QChN5rPVFl2rLtLu0owvoAuTVjWjYNPgDfWb3spXh0p+lZ9oi53kZd4iDGe/jQJzAcpUa3Yj2me6XFFTD+8FNCkCgYEAyIxrkCo2oqGg1aJ7xc9+aBcpsrVg/upptdTgiMGSVZ3XuixufZV36lzJOdmCBoFGKwmLgKkStJSOm3SHUqdEKQBbHI95aG3HgnAMRXOtkn1exExfpAmCnAAnAx8RONorOTjrMrW0BO0/NII7O7NkLg/ocahr/lXEylsC8dLlMCgYBDiwiEu6/Oee5nUAEWR2veo/YBp9iRMeswAqzv4Q2EInBQN3vFs7xaCj0CyG2V2wlmt5+NSNyeW27LwRN2zkxHTvaD94VgspH+pqSTZF0E8FDR9vWVxqG91qk11QNCwS2/Pn6kRu4p3+t/Ft9L+00fOwcIpLGlcWOPWvUiF/dxEQKBgQCNEEhwpWC80FejLaFGKIdPjEtmSrKpXBV0rfTF+LkizuUBJ3/9zQNRyeGxnnuRj+nlvO1e3sWACySHRu4G53MvR8qqVr13ecfuuA0nOvPojuq4THKrlzVsUqGelXBrlEdiFFJMY7axfvBzoYIyqq+aoTxFjJ6Z/czFOZyp6tnpxQKBgClvDZ9pUc+WH28fDnDPd36bC6HmBq/fkxo92RJey1aRFSoCtKNW5Eaqem8iDD+WAVYak2Vg7xUHkhwIEyVVfHIxZBXc0X1w3jNFjG1/Fyul4hLjqCH2QI8gOjHXAcDZe+MJa8b33ZTiiilUu5A0N8+Xz8qpMQ84cXODHJcPMPYb"
 
-	pKey := gopay.FormatPrivateKey(privateKey)
+	pKey := alipay.FormatPrivateKey(privateKey)
 	fmt.Println(pKey)
 }
 
-func FormatAliPayPublicKey() {
+func FormatPublicKey() {
 	aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp8gueNlkbiDidz6FBQEBpqoRgH8h7JtsPtYW0nzAqy1MME4mFnDSMfSKlreUomS3a55gmBopL1eF4/Km/dEnaL5tCY9+24SKn1D4iyls+lvz/ZjvUjVwxoUYBh8kkcxMZSDeDz8//o+9qZTrICVP2a4sBB8T0XmU4gxfw8FsmtoomBH1nLk3AO7wgRN2a3+SRSAmxrhIGDmF1lljSlhY32eJpJ2TZQKaWNW+7yDBU/0Wt3kQVY84vr14yYagnSCiIfqyVFqePayRtmVJDr5qvSXr51tdqs2zKZCu+26X7JAF4BSsaq4gmY5DmDTm4TohCnBduI1+bPGD+igVmtl05wIDAQAB"
 
-	pKey := gopay.FormatAliPayPublicKey(aliPayPublicKey)
+	pKey := alipay.FormatPublicKey(aliPayPublicKey)
 	fmt.Println(pKey)
 }
 
-func AliPaySystemOauthToken2() {
+func SystemOauthToken2() {
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
-	rsp, err := gopay.AliPaySystemOauthToken("2016091200494382", privateKey, "", "06e8961891d647c0ac99bb1cebe7SE69")
+	rsp, err := alipay.SystemOauthToken("2016091200494382", privateKey, "", "06e8961891d647c0ac99bb1cebe7SE69")
 	if err != nil {
-		fmt.Println("gopay.AliPaySystemOauthToken:", err)
+		fmt.Println("SystemOauthToken:", err)
 		return
 	}
 	fmt.Println("rsp:", *rsp)
 }
 
-func DecryptAliPayOpenDataToStruct() {
+func DecryptOpenDataToStruct() {
 	data := "MkvuiIZsGOC8S038cu/JIpoRKnF+ZFjoIRGf5d/K4+ctYjCtb/eEkwgrdB5TeH/93bxff1Ylb+SE+UGStlpvcg=="
 	key := "TDftre9FpItr46e9BVNJcw=="
-	rsp := new(gopay.AliPayUserPhone)
-	err := gopay.DecryptAliPayOpenDataToStruct(data, key, rsp)
+	rsp := new(alipay.UserPhone)
+	err := alipay.DecryptOpenDataToStruct(data, key, rsp)
 	if err != nil {
 		fmt.Println("err:", err)
 		return
@@ -48,12 +48,12 @@ func DecryptAliPayOpenDataToStruct() {
 	fmt.Println("rsp.Mobile:", rsp.Mobile)
 }
 
-func VerifyAliPaySyncSign() {
+func VerifySyncSign() {
 	aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
 	signData := "aaaaaaaaaaaaaaaaaaaaaa"
 	sign := "asdkjsdhfgkjdshflksdjfl"
 
-	ok, err := gopay.VerifyAliPaySyncSign(aliPayPublicKey, signData, sign)
+	ok, err := alipay.VerifySyncSign(aliPayPublicKey, signData, sign)
 	if err != nil {
 		fmt.Println("err:", err)
 		return
@@ -61,11 +61,11 @@ func VerifyAliPaySyncSign() {
 	fmt.Println("ok:", ok)
 }
 
-func ParseAliPayNotifyResultAndVerifyAliPaySign(req *http.Request) {
+func ParseNotifyResultAndVerifySign(req *http.Request) {
 	aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
 
 	//解析请求参数
-	notifyReq, err := gopay.ParseAliPayNotifyResult(req)
+	notifyReq, err := alipay.ParseNotifyResult(req)
 	if err != nil {
 		fmt.Println("err:", err)
 		return
@@ -73,7 +73,7 @@ func ParseAliPayNotifyResultAndVerifyAliPaySign(req *http.Request) {
 	fmt.Println("notifyReq:", *notifyReq)
 
 	//验签
-	ok, err := gopay.VerifyAliPaySign(aliPayPublicKey, notifyReq)
+	ok, err := alipay.VerifySign(aliPayPublicKey, notifyReq)
 	if err != nil {
 		fmt.Println("err:", err)
 		return
@@ -82,14 +82,23 @@ func ParseAliPayNotifyResultAndVerifyAliPaySign(req *http.Request) {
 }
 
 func GetCertSN() {
-	sn, err := gopay.GetCertSN("alipay_cert/appCertPublicKey.crt")
+	sn, err := alipay.GetCertSN("cert/appCertPublicKey.crt")
 	if err != nil {
 		fmt.Println("err:", err)
 		return
 	}
 	fmt.Println("sn:", sn)
 
-	sn, err = gopay.GetCertSN("alipay_cert/alipayCertPublicKey_RSA2.crt")
+	sn, err = alipay.GetCertSN("cert/alipayCertPublicKey_RSA2.crt")
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("sn:", sn)
+}
+
+func GetRootCertSN() {
+	sn, err := alipay.GetRootCertSN("cert/alipayRootCert.crt")
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 6 - 4
examples/alipay/alipay_AliPaySystemOauthToken.go → examples/alipay/alipay_SystemOauthToken.go

@@ -4,26 +4,28 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPaySystemOauthToken() {
+func SystemOauthToken() {
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2").
 		SetNotifyUrl("https://www.gopay.ink")
+
 	//请求参数
 	body := make(gopay.BodyMap)
 	body.Set("grant_type", "authorization_code")
 	body.Set("code", "3a06216ac8f84b8c93507bb9774bWX11")
 
 	//发起请求
-	aliRsp, err := client.AliPaySystemOauthToken(body)
+	aliRsp, err := client.SystemOauthToken(body)
 	if err != nil {
 		fmt.Println("err:", err)
 		return
@@ -39,7 +41,7 @@ func AliPaySystemOauthToken() {
 	body2.Set("out_trade_no", "GZ201901301040355708")
 	body2.Set("total_amount", "0.01")
 
-	rsp, err := client.AliPayTradeCreate(body2)
+	rsp, err := client.TradeCreate(body2)
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 5 - 3
examples/alipay/alipay_AliPayTradeAppPay.go → examples/alipay/alipay_TradeAppPay.go

@@ -4,27 +4,29 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayTradeAppPay() {
+func TradeAppPay() {
 	//aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2").
 		SetNotifyUrl("https://www.gopay.ink")
+
 	//请求参数
 	body := make(gopay.BodyMap)
 	body.Set("subject", "测试APP支付")
 	body.Set("out_trade_no", "GZ201901301040355706100469")
 	body.Set("total_amount", "1.00")
 	//手机APP支付参数请求
-	payParam, err := client.AliPayTradeAppPay(body)
+	payParam, err := client.TradeAppPay(body)
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 5 - 3
examples/alipay/alipay_AliPayTradeCancel.go → examples/alipay/alipay_TradeCancel.go

@@ -4,25 +4,27 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayTradeCancel() {
+func TradeCancel() {
 	//aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2").
 		SetNotifyUrl("https://www.gopay.ink")
+
 	//请求参数
 	body := make(gopay.BodyMap)
 	body.Set("out_trade_no", "GYWX201901301040355706100457")
 	//撤销支付订单
-	aliRsp, err := client.AliPayTradeCancel(body)
+	aliRsp, err := client.TradeCancel(body)
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 5 - 3
examples/alipay/alipay_AliPayTradeClose.go → examples/alipay/alipay_TradeClose.go

@@ -4,25 +4,27 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayTradeClose() {
+func TradeClose() {
 	//aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2").
 		SetNotifyUrl("https://www.gopay.ink")
+
 	//请求参数
 	body := make(gopay.BodyMap)
 	body.Set("out_trade_no", "GYWX201901301040355706100459")
 	//条码支付
-	aliRsp, err := client.AliPayTradeClose(body)
+	aliRsp, err := client.TradeClose(body)
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 5 - 3
examples/alipay/alipay_AliPayTradeCreate.go → examples/alipay/alipay_TradeCreate.go

@@ -4,9 +4,10 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayTradeCreate() {
+func TradeCreate() {
 	//aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
 	//privateKey := "MIIEpgIBAAKCAQEA5JwIRwps/xrBFLCRHL727tofHEDE74I+NMkUkHCEd0qI7lOYrz72761hjw0/Np+io8DQDNf3AV0+HJGQAuMadhgmcLUnfB7BJwEL1wgc2Uk8oj8XBIJUKmc+APtJ3NhUgd7s4p63IVKjQfp8oMbGZS3/dJdamBEqGJn3bep7WlKyJy5bL3KY+fX5F1DNif8xfHBSygkniKhTt/pkKaEP6uiEvhZuorPKGTowU99cqJZAqNVGcZV/30UEerR9BHV5g3iZHRxebGNbC9WSBqVWoGhdo23Xl0QG6KmuZ1akF7mdq1e7Qlpm0SkYimqipRhSflu2N/mIW2pesypX2DRE8wIDAQABAoIBAQDDvkJsKaYoTI00nPaziWPAIm3u8BpwBbIj2mTMRDt4NQ7IGjYrH5uqn2dgaHRO3iMRWYAK70RlG6SaK50Gi9RVd9o6OTKk2WSDdCbiKOUiu826EpEv4DQW1q3Fg2S8P1MknG9yn3mog6ycStE5jNnFOrx35TzB5jiINhUhPVv/eh6iDkHCxfOh2R4+vPYjNXlzhgcR3qh19Rnd2uuzscbRtljoZpA3qE0tIawW7HmesKqjfHL3O/kHJGmZjK/uhNvZmPMzilmFb+q3R3BXbAPNc/efkv0GF1fS0Xy2h0YYfkNTDzewsU7Qwkw/iT29IUUn9uxAux6SYyubCdLRIMtpAoGBAP3uxgt0kX4AN0CUibkyvDlaw+amkjTgk9voH78CPUej58sIkWcaPJJwAFOhzNbsTlNp3mZ2xx58gqJU2Rm1/6bsQbYRjN9qVY8Fco7ClysOaf9bwDBqnIjv9eHZdw8EmR4qnPCH9yjBWDMODKxIhAhsuwm4D7GmsHrFAp5w7PlnAoGBAOZ4e2sOfVAiM9ZoHIlaNLW2Z1PKkc/1k+Hxoxl5dq9nHB9RAGqpO4vjbMc6d1wVRr02GZE8RaLSzS7WrAgSzsWgtql4P8TvrjPvIPEyN1B7/eqR6yNDGRHLkYbDg54SeRI/yUg7EwMARJqa24zP503IA40JZgaVHLti5XYCIoSVAoGBAIx/oXpTG/EQY4HK7czXgodlbgDfZwP0wjqpW29O6OMLkEOpUPIv9RW8/KFJY9IC22+RoykkTRXUJF92/MwaBAKys8TuPviamA5TIEhW6Fc9WW6dsF/ZjRTDWFOHBDX+AE5Nm5oGUL1vBMLy4hYs5UjYCEDfY2eS6BB1kvZhWuy/AoGBAKJHf4+YOkBsdNepoz5LmAXDE+p6HkWyA5j6jf9n+Vv0XGbooER6OQV886Es19Ks4IxmRYZwTBAkInmyipt8sr+RNE0L8Mr4gU7sN+Pdmfk/9UBv0oOXwVU4Y5XioRByrXFeHJqRjgd07tl15NW3poSsK2PplD9aS0rejfeT9T4pAoGBAKELHKfRAWILgkI/L5RrvaoUEkdy1hw9a+b+V1TKB+wDbrsomzL2BPnBYjqtw2ZhTffpxzS3ZpSzlMtgmcYhpyAvq5GlPw+wbsNXr4tCIu8eYLc6QoypmO8kE2FornyZfol5ygEu6HSUSwEHHjIQBDxtAlYgBPZOetDVdDVJD1nR"
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
@@ -14,11 +15,12 @@ func AliPayTradeCreate() {
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2").
 		SetNotifyUrl("https://www.gopay.ink")
+
 	//请求参数
 	body := make(gopay.BodyMap)
 	body.Set("subject", "创建订单")
@@ -26,7 +28,7 @@ func AliPayTradeCreate() {
 	body.Set("out_trade_no", "GZ201901301040355709")
 	body.Set("total_amount", "0.01")
 	//创建订单
-	aliRsp, err := client.AliPayTradeCreate(body)
+	aliRsp, err := client.TradeCreate(body)
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 5 - 3
examples/alipay/alipay_AliPayTradeFastPayRefundQuery.go → examples/alipay/alipay_TradeFastPayRefundQuery.go

@@ -4,25 +4,27 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayTradeFastPayRefundQuery() {
+func TradeFastPayRefundQuery() {
 	//aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2")
+
 	//请求参数
 	body := make(gopay.BodyMap)
 	body.Set("out_trade_no", "GZ201907301420334577")
 	body.Set("out_request_no", "GZ201907301420334577")
 	//发起退款查询请求
-	aliRsp, err := client.AliPayTradeFastPayRefundQuery(body)
+	aliRsp, err := client.TradeFastPayRefundQuery(body)
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 7 - 5
examples/alipay/alipay_AliPayTradeOrderSettle.go → examples/alipay/alipay_TradeOrderSettle.go

@@ -4,31 +4,33 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayTradeOrderSettle() {
+func TradeOrderSettle() {
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2")
+
 	//请求参数
 	body := make(gopay.BodyMap)
 	body.Set("out_request_no", "201907301518083384")
 	body.Set("trade_no", "2019072522001484690549776067")
 
-	var listParams []gopay.OpenApiRoyaltyDetailInfoPojo
-	listParams = append(listParams, gopay.OpenApiRoyaltyDetailInfoPojo{"transfer", "2088802095984694", "userId", "userId", "2088102363632794", "0.01", "分账给2088102363632794"})
+	var listParams []alipay.OpenApiRoyaltyDetailInfoPojo
+	listParams = append(listParams, alipay.OpenApiRoyaltyDetailInfoPojo{"transfer", "2088802095984694", "userId", "userId", "2088102363632794", "0.01", "分账给2088102363632794"})
 
 	body.Set("royalty_parameters", listParams)
 	fmt.Println("listParams:", body.Get("royalty_parameters"))
 
 	//发起交易结算接口
-	aliRsp, err := client.AliPayTradeOrderSettle(body)
+	aliRsp, err := client.TradeOrderSettle(body)
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 5 - 3
examples/alipay/alipay_AliPayTradePagePay.go → examples/alipay/alipay_TradePagePay.go

@@ -4,20 +4,22 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayTradePagePay() {
+func TradePagePay() {
 	//aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2").
 		SetNotifyUrl("https://www.gopay.ink")
+
 	//请求参数
 	body := make(gopay.BodyMap)
 	body.Set("subject", "网站测试支付")
@@ -26,7 +28,7 @@ func AliPayTradePagePay() {
 	body.Set("product_code", "FAST_INSTANT_TRADE_PAY")
 
 	//电脑网站支付请求
-	payUrl, err := client.AliPayTradePagePay(body)
+	payUrl, err := client.TradePagePay(body)
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 6 - 4
examples/alipay/alipay_AliPayTradePay.go → examples/alipay/alipay_TradePay.go

@@ -4,21 +4,23 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayTradePay() {
+func TradePay() {
 	//aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2").
 		//SetAppAuthToken("201908BB03f542de8ecc42b985900f5080407abc").
 		SetNotifyUrl("https://www.gopay.ink")
+
 	//请求参数
 	body := make(gopay.BodyMap)
 	body.Set("subject", "条码支付")
@@ -28,7 +30,7 @@ func AliPayTradePay() {
 	body.Set("total_amount", "0.01")
 	body.Set("timeout_express", "2m")
 	//条码支付
-	aliRsp, err := client.AliPayTradePay(body)
+	aliRsp, err := client.TradePay(body)
 	if err != nil {
 		fmt.Println("err:", err)
 		return
@@ -36,7 +38,7 @@ func AliPayTradePay() {
 	fmt.Println("aliRsp:", *aliRsp)
 	// 同步返回验签
 	alipayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp8gueNlkbiDidz6FBQEBpqoRgH8h7JtsPtYW0nzAqy1MME4mFnDSMfSKlreUomS3a55gmBopL1eF4/Km/dEnaL5tCY9+24SKn1D4iyls+lvz/ZjvUjVwxoUYBh8kkcxMZSDeDz8//o+9qZTrICVP2a4sBB8T0XmU4gxfw8FsmtoomBH1nLk3AO7wgRN2a3+SRSAmxrhIGDmF1lljSlhY32eJpJ2TZQKaWNW+7yDBU/0Wt3kQVY84vr14yYagnSCiIfqyVFqePayRtmVJDr5qvSXr51tdqs2zKZCu+26X7JAF4BSsaq4gmY5DmDTm4TohCnBduI1+bPGD+igVmtl05wIDAQAB"
-	ok, err := gopay.VerifyAliPaySyncSign(alipayPublicKey, aliRsp.SignData, aliRsp.Sign)
+	ok, err := alipay.VerifySyncSign(alipayPublicKey, aliRsp.SignData, aliRsp.Sign)
 	if err != nil {
 		fmt.Println("err:::", err)
 	}

+ 5 - 3
examples/alipay/alipay_AliPayTradePrecreate.go → examples/alipay/alipay_TradePrecreate.go

@@ -4,26 +4,28 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayTradePrecreate() {
+func TradePrecreate() {
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2").
 		SetNotifyUrl("https://www.gopay.ink")
+
 	//请求参数
 	body := make(gopay.BodyMap)
 	body.Set("subject", "预创建创建订单")
 	body.Set("out_trade_no", "GZ201907301040355704")
 	body.Set("total_amount", "100")
 	//创建订单
-	aliRsp, err := client.AliPayTradePrecreate(body)
+	aliRsp, err := client.TradePrecreate(body)
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 5 - 3
examples/alipay/alipay_AliPayTradeQuery.go → examples/alipay/alipay_TradeQuery.go

@@ -4,26 +4,28 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayTradeQuery() {
+func TradeQuery() {
 	//aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2").
 		SetAppAuthToken("201908BB03f542de8ecc42b985900f5080407abc")
+
 	//请求参数
 	body := make(gopay.BodyMap)
 	body.Set("out_trade_no", "GZ201909081743431443")
 
 	//查询订单
-	aliRsp, err := client.AliPayTradeQuery(body)
+	aliRsp, err := client.TradeQuery(body)
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 5 - 3
examples/alipay/alipay_AliPayTradeRefund.go → examples/alipay/alipay_TradeRefund.go

@@ -4,26 +4,28 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayTradeRefund() {
+func TradeRefund() {
 	//aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2")
+
 	//请求参数
 	body := make(gopay.BodyMap)
 	body.Set("out_trade_no", "GZ201907301420334577")
 	body.Set("refund_amount", "5")
 	body.Set("refund_reason", "测试退款")
 	//发起退款请求
-	aliRsp, err := client.AliPayTradeRefund(body)
+	aliRsp, err := client.TradeRefund(body)
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 4 - 3
examples/alipay/alipay_AliPayTradeWapPay.go → examples/alipay/alipay_TradeWapPay.go

@@ -4,16 +4,17 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayTradeWapPay() {
+func TradeWapPay() {
 	//aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2").
@@ -27,7 +28,7 @@ func AliPayTradeWapPay() {
 	body.Set("total_amount", "100.00")
 	body.Set("product_code", "QUICK_WAP_WAY")
 	//手机网站支付请求
-	payUrl, err := client.AliPayTradeWapPay(body)
+	payUrl, err := client.TradeWapPay(body)
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 5 - 4
examples/alipay/alipay_AliPayUserCertifyOpenCertify.go → examples/alipay/alipay_UserCertifyOpenCertify.go

@@ -4,27 +4,28 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayUserCertifyOpenCertify() {
+func UserCertifyOpenCertify() {
 	//aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2")
 
-	//请求参数
+	// 请求参数
 	bm := make(gopay.BodyMap)
 	// 本次申请操作的唯一标识,由开放认证初始化接口调用后生成,后续的操作都需要用到
 	bm.Set("certify_id", "OC201809253000000393900404029253")
 
 	//发起请求
-	certifyUrl, err := client.AliPayUserCertifyOpenCertify(bm)
+	certifyUrl, err := client.UserCertifyOpenCertify(bm)
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 5 - 4
examples/alipay/alipay_AliPayUserCertifyOpenInit.go → examples/alipay/alipay_UserCertifyOpenInit.go

@@ -4,21 +4,22 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayUserCertifyOpenInit() {
+func UserCertifyOpenInit() {
 	//aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2")
 
-	//请求参数
+	// 请求参数
 	bm := make(gopay.BodyMap)
 	bm.Set("outer_order_no", "ZGYD201809132323000001234")
 	// 认证场景码:FACE:多因子人脸认证,CERT_PHOTO:多因子证照认证,CERT_PHOTO_FACE :多因子证照和人脸认证,SMART_FACE:多因子快捷认证
@@ -36,7 +37,7 @@ func AliPayUserCertifyOpenInit() {
 	bm.Set("merchant_config", merchant)
 
 	//发起请求
-	aliRsp, err := client.AliPayUserCertifyOpenInit(bm)
+	aliRsp, err := client.UserCertifyOpenInit(bm)
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 5 - 4
examples/alipay/alipay_AliPayUserCertifyOpenQuery.go → examples/alipay/alipay_UserCertifyOpenQuery.go

@@ -4,27 +4,28 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayUserCertifyOpenQuery() {
+func UserCertifyOpenQuery() {
 	//aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2")
 
-	//请求参数
+	// 请求参数
 	bm := make(gopay.BodyMap)
 	// 本次申请操作的唯一标识,由开放认证初始化接口调用后生成,后续的操作都需要用到
 	bm.Set("certify_id", "OC201809253000000393900404029253")
 
 	//发起请求
-	aliRsp, err := client.AliPayUserCertifyOpenQuery(bm)
+	aliRsp, err := client.UserCertifyOpenQuery(bm)
 	if err != nil {
 		fmt.Println("err:", err)
 		return

+ 7 - 7
examples/alipay/alipay_AlipayUserInfoShare.go → examples/alipay/alipay_UserInfoShare.go

@@ -3,33 +3,33 @@ package alipay
 import (
 	"fmt"
 
-	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
-func AliPayUserInfoShare() {
+func UserInfoShare() {
 	aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
 	privateKey := "MIIEogIBAAKCAQEAy+CRzKw4krA2RzCDTqg5KJg92XkOY0RN3pW4sYInPqnGtHV7YDHu5nMuxY6un+dLfo91OFOEg+RI+WTOPoM4xJtsOaJwQ1lpjycoeLq1OyetGW5Q8wO+iLWJASaMQM/t/aXR/JHaguycJyqlHSlxANvKKs/tOHx9AhW3LqumaCwz71CDF/+70scYuZG/7wxSjmrbRBswxd1Sz9KHdcdjqT8pmieyPqnM24EKBexHDmQ0ySXvLJJy6eu1dJsPIz+ivX6HEfDXmSmJ71AZVqZyCI1MhK813R5E7XCv5NOtskTe3y8uiIhgGpZSdB77DOyPLcmVayzFVLAQ3AOBDmsY6wIDAQABAoIBAHjsNq31zAw9FcR9orQJlPVd7vlJEt6Pybvmg8hNESfanO+16rpwg2kOEkS8zxgqoJ1tSzJgXu23fgzl3Go5fHcoVDWPAhUAOFre9+M7onh2nPXDd6Hbq6v8OEmFapSaf2b9biHnBHq5Chk08v/r74l501w3PVVOiPqulJrK1oVb+0/YmCvVFpGatBcNaefKUEcA+vekWPL7Yl46k6XeUvRfTwomCD6jpYLUhsAKqZiQJhMGoaLglZvkokQMF/4G78K7FbbVLMM1+JDh8zJ/DDVdY2vHREUcCGhl4mCVQtkzIbpxG++vFg7/g/fDI+PquG22hFILTDdtt2g2fV/4wmkCgYEA6goRQYSiM03y8Tt/M4u1Mm7OWYCksqAsU7rzQllHekIN3WjD41Xrjv6uklsX3sTG1syo7Jr9PGE1xQgjDEIyO8h/3lDQyLyycYnyUPGNNMX8ZjmGwcM51DQ/QfIrY/CXjnnW+MVpmNclAva3L33KXCWjw20VsROV1EA8LCL94BUCgYEA3wH4ANpzo7NqXf+2WlPPMuyRrF0QPIRGlFBNtaKFy0mvoclkREPmK7+N4NIGtMf5JNODS5HkFRgmU4YNdupA2I8lIYpD+TsIobZxGUKUkYzRZYZ1m1ttL69YYvCVz9Xosw/VoQ+RrW0scS5yUKqFMIUOV2R/Imi//c5TdKx6VP8CgYAnJ1ADugC4vI2sNdvt7618pnT3HEJxb8J6r4gKzYzbszlGlURQQAuMfKcP7RVtO1ZYkRyhmLxM4aZxNA9I+boVrlFWDAchzg+8VuunBwIslgLHx0/4EoUWLzd1/OGtco6oU1HXhI9J9pRGjqfO1iiIifN/ujwqx7AFNknayG/YkQKBgD6yNgA/ak12rovYzXKdp14Axn+39k2dPp6J6R8MnyLlB3yruwW6NSbNhtzTD1GZ+wCQepQvYvlPPc8zm+t3tl1r+Rtx3ORf5XBZc3iPkGdPOLubTssrrAnA+U9vph61W+OjqwLJ9sHUNK9pSHhHSIS4k6ycM2YAHyIC9NGTgB0PAoGAJjwd1DgMaQldtWnuXjvohPOo8cQudxXYcs6zVRbx6vtjKe2v7e+eK1SSVrR5qFV9AqxDfGwq8THenRa0LC3vNNplqostuehLhkWCKE7Y75vXMR7N6KU1kdoVWgN4BhXSwuRxmHMQfSY7q3HG3rDGz7mzXo1FVMr/uE4iDGm0IXY="
 	//初始化支付宝客户端
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2").
 		SetAuthToken("authusrB3888b190f6df4aea964d66129f8a5X11")
 
-	//发起请求
-	aliRsp, err := client.AliPayUserInfoShare()
+	// 发起请求
+	aliRsp, err := client.UserInfoShare()
 	if err != nil {
 		fmt.Println("err:", err)
 		return
 	}
 	fmt.Println("aliRsp:", *aliRsp)
 	// 同步返回验签
-	ok, err := gopay.VerifyAliPaySyncSign(aliPayPublicKey, aliRsp.SignData, aliRsp.Sign)
+	ok, err := alipay.VerifySyncSign(aliPayPublicKey, aliRsp.SignData, aliRsp.Sign)
 	if err != nil {
-		fmt.Println("VerifyAliPaySign-err:", err)
+		fmt.Println("VerifySign-err:", err)
 		return
 	}
 	fmt.Println("ok:", ok)

+ 3 - 1
examples/alipay/alipay_ZhimaCreditScoreGet.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/alipay"
 )
 
 func ZhimaCreditScoreGet() {
@@ -12,11 +13,12 @@ func ZhimaCreditScoreGet() {
 	//    appId:应用ID
 	//    privateKey:应用秘钥
 	//    isProd:是否是正式环境
-	client := gopay.NewAliPayClient("2016091200494382", privateKey, false)
+	client := alipay.NewClient("2016091200494382", privateKey, false)
 	//配置公共参数
 	client.SetCharset("utf-8").
 		SetSignType("RSA2").
 		SetAuthToken("") //必须设置此参数
+
 	//请求参数
 	body := make(gopay.BodyMap)
 	transaction_id := gopay.GetRandomString(48)

+ 5 - 5
examples/wechat/wx_BatchQueryComment.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/wechat"
 )
 
 func BatchQueryComment() {
@@ -13,22 +14,21 @@ func BatchQueryComment() {
 	//    ApiKey:Key值
 	//    isProd:是否是正式环境
 	//    好像不支持沙箱环境,因为沙箱环境默认需要用MD5签名,但是此接口仅支持HMAC-SHA256签名
-	client := gopay.NewWeChatClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
+	client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
 
-	//初始化参数结构体
+	// 初始化参数结构体
 	body := make(gopay.BodyMap)
 	body.Set("nonce_str", gopay.GetRandomString(32))
-	body.Set("sign_type", gopay.SignType_HMAC_SHA256)
+	body.Set("sign_type", wechat.SignType_HMAC_SHA256)
 	body.Set("begin_time", "20190120000000")
 	body.Set("end_time", "20190122174000")
 	body.Set("offset", "0")
 
-	//请求拉取订单评价数据,成功后得到结果,沙箱环境下,证书路径参数可传空
+	// 请求拉取订单评价数据,成功后得到结果,沙箱环境下,证书路径参数可传空
 	wxRsp, err := client.BatchQueryComment(body, "", "", "")
 	if err != nil {
 		fmt.Println("Error:", err)
 		return
 	}
 	fmt.Println("Response:", wxRsp)
-
 }

+ 5 - 4
examples/wechat/wx_CloseOrder.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/wechat"
 )
 
 func CloseOrder() {
@@ -12,15 +13,15 @@ func CloseOrder() {
 	//    MchID:商户ID
 	//    ApiKey:Key值
 	//    isProd:是否是正式环境
-	client := gopay.NewWeChatClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
+	client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
 
-	//初始化参数结构体
+	// 初始化参数结构体
 	body := make(gopay.BodyMap)
 	body.Set("out_trade_no", "MfZC2segKxh0bnJSELbvKNeH3d9oWvvQ")
 	body.Set("nonce_str", gopay.GetRandomString(32))
-	body.Set("sign_type", gopay.SignType_MD5)
+	body.Set("sign_type", wechat.SignType_MD5)
 
-	//请求关闭订单,成功后得到结果
+	// 请求关闭订单,成功后得到结果
 	wxRsp, err := client.CloseOrder(body)
 	if err != nil {
 		fmt.Println("Error:", err)

+ 4 - 3
examples/wechat/wx_DownloadBill.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/wechat"
 )
 
 func DownloadBill() {
@@ -12,12 +13,12 @@ func DownloadBill() {
 	//    MchID:商户ID
 	//    ApiKey:Key值
 	//    isProd:是否是正式环境
-	client := gopay.NewWeChatClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
+	client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
 
-	//初始化参数结构体
+	// 初始化参数结构体
 	body := make(gopay.BodyMap)
 	body.Set("nonce_str", gopay.GetRandomString(32))
-	body.Set("sign_type", gopay.SignType_MD5)
+	body.Set("sign_type", wechat.SignType_MD5)
 	body.Set("bill_date", "20190722")
 	body.Set("bill_type", "ALL")
 

+ 5 - 4
examples/wechat/wx_DownloadFundFlow.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/wechat"
 )
 
 func DownloadFundFlow() {
@@ -13,16 +14,16 @@ func DownloadFundFlow() {
 	//    ApiKey:Key值
 	//    isProd:是否是正式环境
 	//    好像不支持沙箱环境,因为沙箱环境默认需要用MD5签名,但是此接口仅支持HMAC-SHA256签名
-	client := gopay.NewWeChatClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
+	client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
 
-	//初始化参数结构体
+	// 初始化参数结构体
 	body := make(gopay.BodyMap)
 	body.Set("nonce_str", gopay.GetRandomString(32))
-	body.Set("sign_type", gopay.SignType_HMAC_SHA256)
+	body.Set("sign_type", wechat.SignType_HMAC_SHA256)
 	body.Set("bill_date", "20190122")
 	body.Set("account_type", "Basic")
 
-	//请求下载资金账单,成功后得到结果,沙箱环境下,证书路径参数可传空
+	// 请求下载资金账单,成功后得到结果,沙箱环境下,证书路径参数可传空
 	wxRsp, err := client.DownloadFundFlow(body, "", "", "")
 	if err != nil {
 		fmt.Println("Error:", err)

+ 7 - 6
examples/wechat/wx_Micropay.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/wechat"
 )
 
 func Micropay() {
@@ -12,9 +13,9 @@ func Micropay() {
 	//    MchID:商户ID
 	//    ApiKey:Key值
 	//    isProd:是否是正式环境
-	client := gopay.NewWeChatClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
+	client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
 
-	//初始化参数Map
+	// 初始化参数Map
 	body := make(gopay.BodyMap)
 	body.Set("nonce_str", gopay.GetRandomString(32))
 	body.Set("body", "扫用户付款码支付")
@@ -24,10 +25,10 @@ func Micropay() {
 	body.Set("total_fee", 1)
 	body.Set("spbill_create_ip", "127.0.0.1")
 	body.Set("auth_code", "134595229789828537")
-	body.Set("sign_type", gopay.SignType_MD5)
+	body.Set("sign_type", wechat.SignType_MD5)
 
-	sign := gopay.GetWeChatParamSign("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", body)
-	//sign, _ := gopay.GetWeChatSanBoxParamSign("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", body)
+	sign := wechat.GetParamSign("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", body)
+	//sign, _ := gopay.GetSanBoxParamSign("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", body)
 
 	body.Set("sign", sign)
 	//请求支付,成功后得到结果
@@ -38,7 +39,7 @@ func Micropay() {
 	}
 	fmt.Println("Response:", *wxRsp)
 
-	ok, err := gopay.VerifyWeChatSign("GFDS8j98rewnmgl45wHTt980jg543abc", gopay.SignType_MD5, wxRsp)
+	ok, err := wechat.VerifySign("GFDS8j98rewnmgl45wHTt980jg543abc", wechat.SignType_MD5, wxRsp)
 	if err != nil {
 		fmt.Println("err:", err)
 	}

+ 5 - 4
examples/wechat/wx_QueryOrder.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/wechat"
 )
 
 func QueryOrder() {
@@ -12,15 +13,15 @@ func QueryOrder() {
 	//    MchID:商户ID
 	//    apiKey:API秘钥值
 	//    isProd:是否是正式环境
-	client := gopay.NewWeChatClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
+	client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
 
-	//初始化参数结构体
+	// 初始化参数结构体
 	body := make(gopay.BodyMap)
 	body.Set("out_trade_no", "GW201908091551421156")
 	body.Set("nonce_str", gopay.GetRandomString(32))
-	body.Set("sign_type", gopay.SignType_MD5)
+	body.Set("sign_type", wechat.SignType_MD5)
 
-	//请求订单查询,成功后得到结果
+	// 请求订单查询,成功后得到结果
 	wxRsp, err := client.QueryOrder(body)
 	if err != nil {
 		fmt.Println("Error:", err)

+ 4 - 3
examples/wechat/wx_QueryRefund.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/wechat"
 )
 
 func QueryRefund() {
@@ -12,16 +13,16 @@ func QueryRefund() {
 	//    MchID:商户ID
 	//    ApiKey:Key值
 	//    isProd:是否是正式环境
-	client := gopay.NewWeChatClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
+	client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
 
-	//初始化参数结构体
+	// 初始化参数结构体
 	body := make(gopay.BodyMap)
 	body.Set("out_trade_no", "97HiM5j6kGmM2fk7fYMc8MgKhPnEQ5Rk")
 	//body.Set("out_refund_no", "vk4264I1UQ3Hm3E4AKsavK8npylGSgQA092f9ckUxp8A2gXmnsLEdsupURVTcaC7")
 	//body.Set("transaction_id", "97HiM5j6kGmM2fk7fYMc8MgKhPnEQ5Rk")
 	//body.Set("refund_id", "97HiM5j6kGmM2fk7fYMc8MgKhPnEQ5Rk")
 	body.Set("nonce_str", gopay.GetRandomString(32))
-	body.Set("sign_type", gopay.SignType_MD5)
+	body.Set("sign_type", wechat.SignType_MD5)
 
 	//请求申请退款
 	wxRsp, err := client.QueryRefund(body)

+ 4 - 3
examples/wechat/wx_Refund.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/wechat"
 )
 
 func Refund() {
@@ -12,13 +13,13 @@ func Refund() {
 	//    MchID:商户ID
 	//    ApiKey:Key值
 	//    isProd:是否是正式环境
-	client := gopay.NewWeChatClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
+	client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
 
-	//初始化参数结构体
+	// 初始化参数结构体
 	body := make(gopay.BodyMap)
 	body.Set("out_trade_no", "SdZBAqJHBQGKVwb7aMR2mUwC588NG2Sd")
 	body.Set("nonce_str", gopay.GetRandomString(32))
-	body.Set("sign_type", gopay.SignType_MD5)
+	body.Set("sign_type", wechat.SignType_MD5)
 	s := gopay.GetRandomString(64)
 	fmt.Println("out_refund_no:", s)
 	body.Set("out_refund_no", s)

+ 4 - 3
examples/wechat/wx_Reverse.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/wechat"
 )
 
 func Reverse() {
@@ -12,13 +13,13 @@ func Reverse() {
 	//    MchID:商户ID
 	//    ApiKey:Key值
 	//    isProd:是否是正式环境
-	client := gopay.NewWeChatClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
+	client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
 
-	//初始化参数Map
+	// 初始化参数Map
 	body := make(gopay.BodyMap)
 	body.Set("nonce_str", gopay.GetRandomString(32))
 	body.Set("out_trade_no", "6aDCor1nUcAihrV5JBlI09tLvXbUp02B")
-	body.Set("sign_type", gopay.SignType_MD5)
+	body.Set("sign_type", wechat.SignType_MD5)
 
 	//请求撤销订单,成功后得到结果,沙箱环境下,证书路径参数可传空
 	wxRsp, err := client.Reverse(body, "", "", "")

+ 21 - 20
examples/wechat/wx_ServiceApi.go

@@ -5,6 +5,7 @@ import (
 	"net/http"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/wechat"
 )
 
 func Code2Session() {
@@ -12,7 +13,7 @@ func Code2Session() {
 	//    appId:APPID
 	//    appSecret:AppSecret
 	//    wxCode:小程序调用wx.login 获取的code
-	userIdRsp, err := gopay.Code2Session("AppID", "APPSecret", "011EZg6p0VO47n1p2W4p0mle6p0EZg6u")
+	userIdRsp, err := wechat.Code2Session("AppID", "APPSecret", "011EZg6p0VO47n1p2W4p0mle6p0EZg6u")
 	if err != nil {
 		fmt.Println("err:", err)
 		return
@@ -26,7 +27,7 @@ func Code2Session() {
 }
 
 func GetAppWeChatLoginAccessToken() {
-	accessToken, err := gopay.GetAppWeChatLoginAccessToken("AppID", "AppSecret", "code")
+	accessToken, err := wechat.GetAppLoginAccessToken("AppID", "AppSecret", "code")
 	if err != nil {
 		fmt.Println("err:", err)
 		return
@@ -41,7 +42,7 @@ func GetAppWeChatLoginAccessToken() {
 }
 
 func RefreshAppWeChatLoginAccessToken() {
-	accessToken, err := gopay.RefreshAppWeChatLoginAccessToken("AppID", "refreshToken")
+	accessToken, err := wechat.RefreshAppLoginAccessToken("AppID", "refreshToken")
 	if err != nil {
 		fmt.Println("err:", err)
 		return
@@ -58,7 +59,7 @@ func GetWeChatAppletAccessToken() {
 	//获取小程序全局唯一后台接口调用凭据(AccessToken:157字符)
 	//    appId:APPID
 	//    appSecret:AppSecret
-	accessToken, err := gopay.GetWeChatAppletAccessToken("AppID", "AppSecret")
+	accessToken, err := wechat.GetAppletAccessToken("AppID", "AppSecret")
 	if err != nil {
 		fmt.Println("err:", err)
 		return
@@ -75,7 +76,7 @@ func GetWeChatAppletPaidUnionId() {
 	//    accessToken:接口调用凭据
 	//    openId:用户的OpenID
 	//    transactionId:微信支付订单号
-	rsp, err := gopay.GetWeChatAppletPaidUnionId(accessToken, "o0Df70MSI4Ygv2KQ2cLnoMN5CXI8", "4200000326201905256499385970")
+	rsp, err := wechat.GetAppletPaidUnionId(accessToken, "o0Df70MSI4Ygv2KQ2cLnoMN5CXI8", "4200000326201905256499385970")
 	if err != nil {
 		fmt.Println("err:", err)
 		return
@@ -91,7 +92,7 @@ func GetWeChatUserInfo() {
 	//    accessToken:接口调用凭据
 	//    openId:用户的OpenID
 	//    lang:默认为 zh_CN ,可选填 zh_CN 简体,zh_TW 繁体,en 英语
-	userInfo, err := gopay.GetWeChatUserInfo(accessToken, "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")
+	userInfo, err := wechat.GetUserInfo(accessToken, "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")
 	if err != nil {
 		fmt.Println("err:", err)
 		return
@@ -105,13 +106,13 @@ func DecryptWeChatOpenDataToStruct() {
 	session := "lyY4HPQbaOYzZdG+JcYK9w=="
 
 	//微信小程序,手机号
-	phone := new(gopay.WeChatUserPhone)
+	phone := new(wechat.UserPhone)
 	//解密开放数据
 	//    encryptedData:包括敏感数据在内的完整用户信息的加密数据
 	//    iv:加密算法的初始向量
 	//    sessionKey:会话密钥
 	//    beanPtr:需要解析到的结构体指针
-	err := gopay.DecryptWeChatOpenDataToStruct(data, iv, session, phone)
+	err := wechat.DecryptOpenDataToStruct(data, iv, session, phone)
 	if err != nil {
 		fmt.Println("err:", err)
 		return
@@ -126,9 +127,9 @@ func DecryptWeChatOpenDataToStruct() {
 	iv2 := "r7BXXKkLb8qrSNn05n0qiA=="
 
 	//微信小程序 用户信息
-	userInfo := new(gopay.WeChatAppletUserInfo)
+	userInfo := new(wechat.AppletUserInfo)
 
-	err = gopay.DecryptWeChatOpenDataToStruct(encryptedData, iv2, sessionKey, userInfo)
+	err = wechat.DecryptOpenDataToStruct(encryptedData, iv2, sessionKey, userInfo)
 	if err != nil {
 		fmt.Println("err:", err)
 		return
@@ -153,7 +154,7 @@ func DecryptWeChatOpenDataToBodyMap() {
 	//    encryptedData:包括敏感数据在内的完整用户信息的加密数据
 	//    iv:加密算法的初始向量
 	//    sessionKey:会话密钥
-	bm, err := gopay.DecryptWeChatOpenDataToBodyMap(data, iv, session)
+	bm, err := wechat.DecryptOpenDataToBodyMap(data, iv, session)
 	if err != nil {
 		fmt.Println("err:", err)
 		return
@@ -168,7 +169,7 @@ func GetOpenIdByAuthCode() {
 	//    apiKey:ApiKey
 	//    authCode:用户授权码
 	//    nonceStr:随即字符串
-	openIdRsp, err := gopay.GetOpenIdByAuthCode("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", "135127679952609396", gopay.GetRandomString(32))
+	openIdRsp, err := wechat.GetOpenIdByAuthCode("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", "135127679952609396", gopay.GetRandomString(32))
 	if err != nil {
 		fmt.Println("err:", err)
 		return
@@ -185,17 +186,17 @@ func GetOpenIdByAuthCode() {
 
 //解析notify参数、验签、返回数据到微信
 func ParseWeChatNotifyResultAndVerifyWeChatSign(req *http.Request) string {
-	rsp := new(gopay.WeChatNotifyResponse)
+	rsp := new(wechat.NotifyResponse)
 
 	//解析参数
-	notifyReq, err := gopay.ParseWeChatNotifyResult(req)
+	notifyReq, err := wechat.ParseNotifyResult(req)
 	if err != nil {
 		fmt.Println("err:", err)
 	}
 	fmt.Println("notifyReq:", *notifyReq)
 
 	//验签
-	ok, err := gopay.VerifyWeChatSign("GFDS8j98rewnmgl45wHTt980jg543abc", gopay.SignType_MD5, notifyReq)
+	ok, err := wechat.VerifySign("GFDS8j98rewnmgl45wHTt980jg543abc", wechat.SignType_MD5, notifyReq)
 	if err != nil {
 		fmt.Println("err:", err)
 	}
@@ -203,13 +204,13 @@ func ParseWeChatNotifyResultAndVerifyWeChatSign(req *http.Request) string {
 
 	//或者
 
-	bodyMap, err := gopay.ParseWeChatNotifyResultToBodyMap(req)
+	bodyMap, err := wechat.ParseNotifyResultToBodyMap(req)
 	if err != nil {
 		fmt.Println("err:", err)
 	}
 	fmt.Println("bodyMap:", bodyMap)
 
-	ok, err = gopay.VerifyWeChatSign("GFDS8j98rewnmgl45wHTt980jg543abc", gopay.SignType_MD5, bodyMap)
+	ok, err = wechat.VerifySign("GFDS8j98rewnmgl45wHTt980jg543abc", wechat.SignType_MD5, bodyMap)
 	if err != nil {
 		fmt.Println("err:", err)
 	}
@@ -222,9 +223,9 @@ func ParseWeChatNotifyResultAndVerifyWeChatSign(req *http.Request) string {
 
 // 解析微信退款异步通知的参数,解析出来的 req_info 是加密数据,需解密
 func ParseWeChatRefundNotifyResult(req *http.Request) string {
-	rsp := new(gopay.WeChatNotifyResponse)
+	rsp := new(wechat.NotifyResponse)
 	// 解析参数
-	notifyReq, err := gopay.ParseWeChatRefundNotifyResult(req)
+	notifyReq, err := wechat.ParseRefundNotifyResult(req)
 	if err != nil {
 		fmt.Println("err:", err)
 	}
@@ -232,7 +233,7 @@ func ParseWeChatRefundNotifyResult(req *http.Request) string {
 	// 退款通知无sign,不用验签
 
 	// 解密退款异步通知的加密数据
-	refundNotify, err := gopay.DecryptRefundNotifyReqInfo(notifyReq.ReqInfo, "GFDS8j98rewnmgl45wHTt980jg543abc")
+	refundNotify, err := wechat.DecryptRefundNotifyReqInfo(notifyReq.ReqInfo, "GFDS8j98rewnmgl45wHTt980jg543abc")
 	if err != nil {
 		fmt.Println("err:", err)
 	}

+ 3 - 2
examples/wechat/wx_Transfer.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/wechat"
 )
 
 func Transfer() {
@@ -12,7 +13,7 @@ func Transfer() {
 	//    MchID:商户ID
 	//    ApiKey:Key值
 	//    isProd:是否是正式环境(企业转账到个人账户,默认正式环境)
-	client := gopay.NewWeChatClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
+	client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
 
 	err := client.AddCertFilePath("iguiyu_cert/apiclient_cert.pem", "iguiyu_cert/apiclient_key.pem", "iguiyu_cert/apiclient_cert.p12")
 	if err != nil {
@@ -31,7 +32,7 @@ func Transfer() {
 	body.Set("desc", "测试转账")              // 企业付款备注,必填。注意:备注中的敏感词会被转成字符*
 	body.Set("spbill_create_ip", "127.0.0.1")
 
-	// 请求申请退款(沙箱环境下,证书路径参数可传空
+	// 企业向微信用户个人付款(不支持沙箱环境
 	//    body:参数Body
 	//    certFilePath:cert证书路径
 	//    keyFilePath:Key证书路径

+ 7 - 5
examples/wechat/wx_UnifiedOrder.go

@@ -6,6 +6,7 @@ import (
 	"time"
 
 	"github.com/iGoogle-ink/gopay"
+	"github.com/iGoogle-ink/gopay/wechat"
 )
 
 func UnifiedOrder() {
@@ -14,13 +15,14 @@ func UnifiedOrder() {
 	//    mchId:商户ID
 	//    apiKey:API秘钥值
 	//    isProd:是否是正式环境
-	client := gopay.NewWeChatClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
+	client := wechat.NewClient("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", false)
 
 	//设置国家
-	client.SetCountry(gopay.China)
+	client.SetCountry(wechat.China)
 
 	number := gopay.GetRandomString(32)
 	fmt.Println("out_trade_no:", number)
+
 	//初始化参数Map
 	body := make(gopay.BodyMap)
 	body.Set("nonce_str", gopay.GetRandomString(32))
@@ -29,9 +31,9 @@ func UnifiedOrder() {
 	body.Set("total_fee", 1)
 	body.Set("spbill_create_ip", "127.0.0.1")
 	body.Set("notify_url", "http://www.gopay.ink")
-	body.Set("trade_type", gopay.TradeType_H5)
+	body.Set("trade_type", wechat.TradeType_H5)
 	body.Set("device_info", "WEB")
-	body.Set("sign_type", gopay.SignType_MD5)
+	body.Set("sign_type", wechat.SignType_MD5)
 
 	sceneInfo := make(map[string]map[string]string)
 	h5Info := make(map[string]string)
@@ -67,7 +69,7 @@ func UnifiedOrder() {
 
 	//获取H5支付需要的paySign
 	pac := "prepay_id=" + wxRsp.PrepayId
-	paySign := gopay.GetH5PaySign("wxdaa2ab9ef87b5497", wxRsp.NonceStr, pac, gopay.SignType_MD5, timeStamp, "GFDS8j98rewnmgl45wHTt980jg543abc")
+	paySign := wechat.GetH5PaySign("wxdaa2ab9ef87b5497", wxRsp.NonceStr, pac, wechat.SignType_MD5, timeStamp, "GFDS8j98rewnmgl45wHTt980jg543abc")
 	fmt.Println("paySign:", paySign)
 
 	//获取小程序需要的paySign

+ 20 - 0
gopay_test.go

@@ -0,0 +1,20 @@
+package gopay
+
+import (
+	"fmt"
+	"testing"
+)
+
+func TestBodyMap_CheckParamsNull(t *testing.T) {
+	bm := make(BodyMap)
+	bm.Set("name", "jerry")
+	bm.Set("age", 2)
+	bm.Set("phone", "")
+	bm.Set("pi", 3.14)
+
+	err := bm.CheckEmptyError("name", "age", "phone")
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+}

+ 2 - 2
http_client.go

@@ -132,7 +132,7 @@ func (c *Client) EndStruct(v interface{}) (res *http.Response, errs []error) {
 	case TypeXML:
 		err := xml.Unmarshal(bs, &v)
 		if err != nil {
-			c.Errors = append(c.Errors, fmt.Errorf("xml.Unmarshal:%s", err.Error()))
+			c.Errors = append(c.Errors, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error()))
 			return nil, c.Errors
 		}
 		return res, nil
@@ -145,7 +145,7 @@ func (c *Client) EndBytes() (res *http.Response, bs []byte, errs []error) {
 	if len(c.Errors) > 0 {
 		return nil, nil, c.Errors
 	}
-	var reader = strings.NewReader(null)
+	var reader = strings.NewReader(NULL)
 
 	req, err := func() (*http.Request, error) {
 		c.mu.RLock()

+ 0 - 12
message.go

@@ -1,12 +0,0 @@
-package gopay
-
-const (
-	SUCCESS = "SUCCESS"
-	FAIL    = "FAIL"
-	OK      = "OK"
-)
-
-type ReturnMessage struct {
-	ReturnCode string `json:"return_code"`
-	ReturnMsg  string `json:"return_msg"`
-}

+ 16 - 0
model.go

@@ -0,0 +1,16 @@
+package gopay
+
+const (
+	NULL       = ""
+	TimeLayout = "2006-01-02 15:04:05"
+	DateLayout = "2006-01-02"
+	SUCCESS    = "SUCCESS"
+	FAIL       = "FAIL"
+	OK         = "OK"
+	Version    = "2.0.0"
+)
+
+type ReturnMessage struct {
+	ReturnCode string `json:"return_code"`
+	ReturnMsg  string `json:"return_msg"`
+}

+ 243 - 0
qq/client.go

@@ -0,0 +1,243 @@
+package qq
+
+import (
+	"crypto/tls"
+	"encoding/xml"
+	"errors"
+	"fmt"
+	"strings"
+	"sync"
+
+	"github.com/iGoogle-ink/gopay"
+)
+
+type Client struct {
+	MchId      string
+	ApiKey     string
+	CertFile   []byte
+	KeyFile    []byte
+	Pkcs12File []byte
+	IsProd     bool
+	mu         sync.RWMutex
+}
+
+// 初始化QQ客户端(正式环境)
+//    mchId:商户ID
+//    ApiKey:API秘钥值
+func NewClient(mchId, apiKey string) (client *Client) {
+	if mchId != gopay.NULL && apiKey != gopay.NULL {
+		return &Client{
+			MchId:  mchId,
+			ApiKey: apiKey,
+		}
+	}
+	return nil
+}
+
+// 提交付款码支付
+//    文档地址:https://qpay.qq.com/buss/wiki/1/1122
+func (q *Client) MicroPay(bm gopay.BodyMap) (qqRsp *MicroPayResponse, err error) {
+	err = bm.CheckEmptyError("nonce_str", "body", "out_trade_no", "total_fee", "spbill_create_ip", "device_info", "auth_code")
+	if err != nil {
+		return nil, err
+	}
+	bm.Set("trade_type", TradeType_MicroPay)
+	bs, err := q.doQQ(bm, qqMicroPay, nil)
+	if err != nil {
+		return nil, err
+	}
+	qqRsp = new(MicroPayResponse)
+	if err = xml.Unmarshal(bs, qqRsp); err != nil {
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+	}
+	return qqRsp, nil
+}
+
+// 撤销订单
+//    文档地址:https://qpay.qq.com/buss/wiki/1/1125
+func (q *Client) Reverse(bm gopay.BodyMap) (qqRsp *ReverseResponse, err error) {
+	err = bm.CheckEmptyError("sub_mch_id", "nonce_str", "out_trade_no", "op_user_id", "op_user_passwd")
+	if err != nil {
+		return nil, err
+	}
+	bs, err := q.doQQ(bm, qqReverse, nil)
+	if err != nil {
+		return nil, err
+	}
+	qqRsp = new(ReverseResponse)
+	if err = xml.Unmarshal(bs, qqRsp); err != nil {
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+	}
+	return qqRsp, nil
+}
+
+// 统一下单
+//    文档地址:https://qpay.qq.com/buss/wiki/38/1203
+func (q *Client) UnifiedOrder(bm gopay.BodyMap) (qqRsp *UnifiedOrderResponse, err error) {
+	err = bm.CheckEmptyError("nonce_str", "body", "out_trade_no", "total_fee", "spbill_create_ip", "trade_type", "notify_url")
+	if err != nil {
+		return nil, err
+	}
+	bs, err := q.doQQ(bm, qqUnifiedOrder, nil)
+	if err != nil {
+		return nil, err
+	}
+	qqRsp = new(UnifiedOrderResponse)
+	if err = xml.Unmarshal(bs, qqRsp); err != nil {
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+	}
+	return qqRsp, nil
+}
+
+// 订单查询
+//    文档地址:https://qpay.qq.com/buss/wiki/38/1205
+func (q *Client) OrderQuery(bm gopay.BodyMap) (qqRsp *OrderQueryResponse, err error) {
+	err = bm.CheckEmptyError("nonce_str")
+	if err != nil {
+		return nil, err
+	}
+	if bm.Get("out_trade_no") == gopay.NULL && bm.Get("transaction_id") == gopay.NULL {
+		return nil, errors.New("out_trade_no and transaction_id are not allowed to be null at the same time")
+	}
+	bs, err := q.doQQ(bm, qqOrderQuery, nil)
+	if err != nil {
+		return nil, err
+	}
+	qqRsp = new(OrderQueryResponse)
+	if err = xml.Unmarshal(bs, qqRsp); err != nil {
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+	}
+	return qqRsp, nil
+}
+
+// 关闭订单
+//    文档地址:https://qpay.qq.com/buss/wiki/38/1206
+func (q *Client) CloseOrder(bm gopay.BodyMap) (qqRsp *CloseOrderResponse, err error) {
+	err = bm.CheckEmptyError("nonce_str", "out_trade_no")
+	if err != nil {
+		return nil, err
+	}
+	bs, err := q.doQQ(bm, qqOrderClose, nil)
+	if err != nil {
+		return nil, err
+	}
+	qqRsp = new(CloseOrderResponse)
+	if err = xml.Unmarshal(bs, qqRsp); err != nil {
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+	}
+	return qqRsp, nil
+}
+
+// 申请退款
+//    注意:如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数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")
+	if err != nil {
+		return nil, err
+	}
+	if bm.Get("out_trade_no") == gopay.NULL && bm.Get("transaction_id") == gopay.NULL {
+		return nil, errors.New("out_trade_no and transaction_id are not allowed to be null at the same time")
+	}
+	tlsConfig, err := q.addCertConfig(certFilePath, keyFilePath, pkcs12FilePath)
+	if err != nil {
+		return nil, err
+	}
+	bs, err := q.doQQ(bm, qqRefund, tlsConfig)
+	if err != nil {
+		return nil, err
+	}
+	qqRsp = new(RefundResponse)
+	if err = xml.Unmarshal(bs, qqRsp); err != nil {
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+	}
+	return qqRsp, nil
+}
+
+// 退款查询
+//    文档地址:https://qpay.qq.com/buss/wiki/38/1208
+func (q *Client) RefundQuery(bm gopay.BodyMap) (qqRsp *RefundQueryResponse, err error) {
+	err = bm.CheckEmptyError("nonce_str")
+	if err != nil {
+		return nil, err
+	}
+	if bm.Get("refund_id") == gopay.NULL && bm.Get("out_refund_no") == gopay.NULL && bm.Get("transaction_id") == gopay.NULL && bm.Get("out_trade_no") == gopay.NULL {
+		return nil, errors.New("refund_id, out_refund_no, out_trade_no, transaction_id are not allowed to be null at the same time")
+	}
+	bs, err := q.doQQ(bm, qqRefundQuery, nil)
+	if err != nil {
+		return nil, 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 qqRsp, nil
+}
+
+// 交易账单
+//    文档地址:https://qpay.qq.com/buss/wiki/38/1209
+func (q *Client) StatementDown(bm gopay.BodyMap) (qqRsp string, err error) {
+	err = bm.CheckEmptyError("nonce_str", "bill_date", "bill_type")
+	if err != nil {
+		return gopay.NULL, err
+	}
+	billType := bm.Get("bill_type")
+	if billType != "ALL" && billType != "SUCCESS" && billType != "REFUND" && billType != "RECHAR" {
+		return gopay.NULL, errors.New("bill_type error, please reference: https://qpay.qq.com/buss/wiki/38/1209")
+	}
+	bs, err := q.doQQ(bm, qqStatementDown, nil)
+	if err != nil {
+		return gopay.NULL, err
+	}
+	return string(bs), nil
+}
+
+// 资金账单
+//    文档地址:https://qpay.qq.com/buss/wiki/38/3089
+func (q *Client) AccRoll(bm gopay.BodyMap) (qqRsp string, err error) {
+	err = bm.CheckEmptyError("nonce_str", "bill_date", "acc_type")
+	if err != nil {
+		return gopay.NULL, err
+	}
+	accType := bm.Get("acc_type")
+	if accType != "CASH" && accType != "MARKETING" {
+		return gopay.NULL, errors.New("acc_type error, please reference: https://qpay.qq.com/buss/wiki/38/3089")
+	}
+	bs, err := q.doQQ(bm, qqAccRoll, nil)
+	if err != nil {
+		return gopay.NULL, err
+	}
+	return string(bs), nil
+}
+
+// 向QQ发送请求
+func (q *Client) doQQ(bm gopay.BodyMap, url string, tlsConfig *tls.Config) (bs []byte, err error) {
+	bm.Set("mch_id", q.MchId)
+	if bm.Get("fee_type") == gopay.NULL {
+		bm.Set("fee_type", "CNY")
+	}
+
+	if bm.Get("sign") == gopay.NULL {
+		var sign string
+		sign = getReleaseSign(q.ApiKey, bm.Get("sign_type"), bm)
+		bm.Set("sign", sign)
+	}
+
+	httpClient := gopay.NewHttpClient()
+	if tlsConfig != nil {
+		httpClient.SetTLSConfig(tlsConfig)
+	}
+
+	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") {
+		return nil, errors.New(string(bs))
+	}
+	return bs, nil
+}

+ 42 - 0
qq/client_test.go

@@ -0,0 +1,42 @@
+package qq
+
+import (
+	"fmt"
+	"os"
+	"testing"
+
+	"github.com/iGoogle-ink/gopay"
+)
+
+var (
+	client *Client
+	mchId  = "1368139502"
+	apiKey = "GFDS8j98rewnmgl45wHTt980jg543abc"
+)
+
+func TestMain(m *testing.M) {
+
+	// 初始化QQ客户端
+	//    mchId:商户ID
+	//    apiKey:API秘钥值
+	client = NewClient(mchId, apiKey)
+
+	//err := client.AddCertFilePath("", "", "")
+	//if err != nil {
+	//	panic(err)
+	//}
+
+	os.Exit(m.Run())
+}
+
+func TestClient_MicroPay(t *testing.T) {
+	bm := make(gopay.BodyMap)
+	bm.Set("nonce_str", gopay.GetRandomString(32))
+
+	qqRsp, err := client.MicroPay(bm)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("qqRsp:", *qqRsp)
+}

+ 207 - 0
qq/model.go

@@ -0,0 +1,207 @@
+package qq
+
+const (
+	// URL
+	qqUnifiedOrder  = "https://qpay.qq.com/cgi-bin/pay/qpay_unified_order.cgi"              // 统一下单
+	qqMicroPay      = "https://qpay.qq.com/cgi-bin/pay/qpay_micro_pay.cgi"                  // 提交付款码支付
+	qqOrderQuery    = "https://qpay.qq.com/cgi-bin/pay/qpay_order_query.cgi"                // 订单查询
+	qqOrderClose    = "https://qpay.qq.com/cgi-bin/pay/qpay_close_order.cgi"                // 关闭订单
+	qqRefundQuery   = "https://qpay.qq.com/cgi-bin/pay/qpay_refund_query.cgi"               // 退款查询
+	qqStatementDown = "https://qpay.qq.com/cgi-bin/sp_download/qpay_mch_statement_down.cgi" // 交易账单
+	qqAccRoll       = "https://qpay.qq.com/cgi-bin/sp_download/qpay_mch_acc_roll.cgi"       // 资金账单
+	qqReverse       = "https://api.qpay.qq.com/cgi-bin/pay/qpay_reverse.cgi"                // 撤销订单
+	qqRefund        = "https://api.qpay.qq.com/cgi-bin/pay/qpay_refund.cgi"                 // 申请退款
+
+	// 支付类型
+	TradeType_MicroPay = "MICROPAY" // 提交付款码支付
+	TradeType_JsApi    = "JSAPI"    // 公众号支付
+	TradeType_Native   = "NATIVE"   // 原生扫码支付
+	TradeType_App      = "APP"      // APP支付
+	TradeType_Mini     = "MINIAPP"  // QQ小程序支付
+
+	// 签名方式
+	SignType_MD5         = "MD5"
+	SignType_HMAC_SHA256 = "HMAC-SHA256"
+)
+
+type NotifyRequest struct {
+	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"`
+	DeviceInfo    string `xml:"device_info,omitempty" json:"device_info,omitempty"`
+	TradeType     string `xml:"trade_type,omitempty" json:"trade_type,omitempty"`
+	TradeState    string `xml:"trade_state,omitempty" json:"trade_state,omitempty"`
+	BankType      string `xml:"bank_type,omitempty" json:"bank_type,omitempty"`
+	FeeType       string `xml:"fee_type,omitempty" json:"fee_type,omitempty"`
+	TotalFee      int    `xml:"total_fee,omitempty" json:"total_fee,omitempty"`
+	CashFee       int    `xml:"cash_fee,omitempty" json:"cash_fee,omitempty"`
+	CouponFee     int    `xml:"coupon_fee,omitempty" json:"coupon_fee,omitempty"`
+	TransactionId string `xml:"transaction_id,omitempty" json:"transaction_id,omitempty"`
+	OutTradeNo    string `xml:"out_trade_no,omitempty" json:"out_trade_no,omitempty"`
+	Attach        string `xml:"attach,omitempty" json:"attach,omitempty"`
+	TimeEnd       string `xml:"time_end,omitempty" json:"time_end,omitempty"`
+	Openid        string `xml:"openid,omitempty" json:"openid,omitempty"`
+}
+
+type MicroPayResponse struct {
+	ReturnCode     string `xml:"return_code,omitempty" json:"return_code,omitempty"`
+	ReturnMsg      string `xml:"return_msg,omitempty" json:"return_msg,omitempty"`
+	RetCode        string `xml:"retcode,omitempty" json:"retcode,omitempty"`
+	RetMsg         string `xml:"retmsg,omitempty" json:"retmsg,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"`
+	ResultCode     string `xml:"result_code,omitempty" json:"result_code,omitempty"`
+	ErrCode        string `xml:"err_code,omitempty" json:"err_code,omitempty"`
+	ErrCodeDes     string `xml:"err_code_des,omitempty" json:"err_code_des,omitempty"`
+	NonceStr       string `xml:"nonce_str,omitempty" json:"nonce_str,omitempty"`
+	DeviceInfo     string `xml:"device_info,omitempty" json:"device_info,omitempty"`
+	TradeType      string `xml:"trade_type,omitempty" json:"trade_type,omitempty"`
+	TradeState     string `xml:"trade_state,omitempty" json:"trade_state,omitempty"`
+	BankType       string `xml:"bank_type,omitempty" json:"bank_type,omitempty"`
+	FeeType        string `xml:"fee_type,omitempty" json:"fee_type,omitempty"`
+	TotalFee       int    `xml:"total_fee,omitempty" json:"total_fee,omitempty"`
+	CashFee        int    `xml:"cash_fee,omitempty" json:"cash_fee,omitempty"`
+	CouponFee      int    `xml:"coupon_fee,omitempty" json:"coupon_fee,omitempty"`
+	CouponFee0     int    `xml:"coupon_fee_0,omitempty" json:"coupon_fee_0,omitempty"`
+	CouponFee1     int    `xml:"coupon_fee_1,omitempty" json:"coupon_fee_1,omitempty"`
+	TransactionId  string `xml:"transaction_id,omitempty" json:"transaction_id,omitempty"`
+	OutTradeNo     string `xml:"out_trade_no,omitempty" json:"out_trade_no,omitempty"`
+	Attach         string `xml:"attach,omitempty" json:"attach,omitempty"`
+	TimeEnd        string `xml:"time_end,omitempty" json:"time_end,omitempty"`
+	TradeStateDesc string `xml:"trade_state_desc,omitempty" json:"trade_state_desc,omitempty"`
+	Openid         string `xml:"openid,omitempty" json:"openid,omitempty"`
+}
+
+type ReverseResponse struct {
+	ReturnCode string `xml:"return_code,omitempty" json:"return_code,omitempty"`
+	ReturnMsg  string `xml:"return_msg,omitempty" json:"return_msg,omitempty"`
+	RetCode    string `xml:"retcode,omitempty" json:"retcode,omitempty"`
+	RetMsg     string `xml:"retmsg,omitempty" json:"retmsg,omitempty"`
+	Appid      string `xml:"appid,omitempty" json:"appid,omitempty"`
+	SubAppid   string `xml:"sub_appid,omitempty" json:"sub_appid,omitempty"`
+	MchId      string `xml:"mch_id,omitempty" json:"mch_id,omitempty"`
+	SubMchId   string `xml:"sub_mch_id,omitempty" json:"sub_mch_id,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"`
+	ErrCodeDes string `xml:"err_code_des,omitempty" json:"err_code_des,omitempty"`
+	NonceStr   string `xml:"nonce_str,omitempty" json:"nonce_str,omitempty"`
+	Recall     string `json:"recall,omitempty"`
+}
+
+type UnifiedOrderResponse struct {
+	ReturnCode string `xml:"return_code,omitempty" json:"return_code,omitempty"`
+	ReturnMsg  string `xml:"return_msg,omitempty" json:"return_msg,omitempty"`
+	RetCode    string `xml:"retcode,omitempty" json:"retcode,omitempty"`
+	RetMsg     string `xml:"retmsg,omitempty" json:"retmsg,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"`
+	ResultCode string `xml:"result_code,omitempty" json:"result_code,omitempty"`
+	ErrCode    string `xml:"err_code,omitempty" json:"err_code,omitempty"`
+	ErrCodeDes string `xml:"err_code_des,omitempty" json:"err_code_des,omitempty"`
+	NonceStr   string `xml:"nonce_str,omitempty" json:"nonce_str,omitempty"`
+	TradeType  string `xml:"trade_type,omitempty" json:"trade_type,omitempty"`
+	PrepayId   string `xml:"prepay_id,omitempty" json:"prepay_id,omitempty"`
+	CodeUrl    string `xml:"code_url,omitempty" json:"code_url,omitempty"`
+}
+
+type OrderQueryResponse struct {
+	ReturnCode     string `xml:"return_code,omitempty" json:"return_code,omitempty"`
+	ReturnMsg      string `xml:"return_msg,omitempty" json:"return_msg,omitempty"`
+	RetCode        string `xml:"retcode,omitempty" json:"retcode,omitempty"`
+	RetMsg         string `xml:"retmsg,omitempty" json:"retmsg,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"`
+	ResultCode     string `xml:"result_code,omitempty" json:"result_code,omitempty"`
+	ErrCode        string `xml:"err_code,omitempty" json:"err_code,omitempty"`
+	ErrCodeDes     string `xml:"err_code_des,omitempty" json:"err_code_des,omitempty"`
+	NonceStr       string `xml:"nonce_str,omitempty" json:"nonce_str,omitempty"`
+	DeviceInfo     string `xml:"device_info,omitempty" json:"device_info,omitempty"`
+	TradeType      string `xml:"trade_type,omitempty" json:"trade_type,omitempty"`
+	TradeState     string `xml:"trade_state,omitempty" json:"trade_state,omitempty"`
+	BankType       string `xml:"bank_type,omitempty" json:"bank_type,omitempty"`
+	FeeType        string `xml:"fee_type,omitempty" json:"fee_type,omitempty"`
+	TotalFee       int    `xml:"total_fee,omitempty" json:"total_fee,omitempty"`
+	CashFee        int    `xml:"cash_fee,omitempty" json:"cash_fee,omitempty"`
+	CouponFee      int    `xml:"coupon_fee,omitempty" json:"coupon_fee,omitempty"`
+	TransactionId  string `xml:"transaction_id,omitempty" json:"transaction_id,omitempty"`
+	OutTradeNo     string `xml:"out_trade_no,omitempty" json:"out_trade_no,omitempty"`
+	Attach         string `xml:"attach,omitempty" json:"attach,omitempty"`
+	TimeEnd        string `xml:"time_end,omitempty" json:"time_end,omitempty"`
+	TradeStateDesc string `xml:"trade_state_desc,omitempty" json:"trade_state_desc,omitempty"`
+	Openid         string `xml:"openid,omitempty" json:"openid,omitempty"`
+}
+
+type CloseOrderResponse struct {
+	ReturnCode string `xml:"return_code,omitempty" json:"return_code,omitempty"`
+	ReturnMsg  string `xml:"return_msg,omitempty" json:"return_msg,omitempty"`
+	RetCode    string `xml:"retcode,omitempty" json:"retcode,omitempty"`
+	RetMsg     string `xml:"retmsg,omitempty" json:"retmsg,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"`
+	ResultCode string `xml:"result_code,omitempty" json:"result_code,omitempty"`
+	ErrCode    string `xml:"err_code,omitempty" json:"err_code,omitempty"`
+	ErrCodeDes string `xml:"err_code_des,omitempty" json:"err_code_des,omitempty"`
+	NonceStr   string `xml:"nonce_str,omitempty" json:"nonce_str,omitempty"`
+}
+
+type RefundResponse struct {
+	ReturnCode    string `xml:"return_code,omitempty" json:"return_code,omitempty"`
+	ReturnMsg     string `xml:"return_msg,omitempty" json:"return_msg,omitempty"`
+	RetCode       string `xml:"retcode,omitempty" json:"retcode,omitempty"`
+	RetMsg        string `xml:"retmsg,omitempty" json:"retmsg,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"`
+	ResultCode    string `xml:"result_code,omitempty" json:"result_code,omitempty"`
+	ErrCode       string `xml:"err_code,omitempty" json:"err_code,omitempty"`
+	ErrCodeDes    string `xml:"err_code_des,omitempty" json:"err_code_des,omitempty"`
+	NonceStr      string `xml:"nonce_str,omitempty" json:"nonce_str,omitempty"`
+	TransactionId string `xml:"transaction_id,omitempty" json:"transaction_id,omitempty"`
+	OutTradeNo    string `xml:"out_trade_no,omitempty" json:"out_trade_no,omitempty"`
+	TotalFee      int    `xml:"total_fee,omitempty" json:"total_fee,omitempty"`
+	OutRefundNo   string `xml:"out_refund_no,omitempty" json:"out_refund_no,omitempty"`
+	RefundId      string `xml:"refund_id,omitempty" json:"refund_id,omitempty"`
+	RefundChannel string `xml:"refund_channel,omitempty" json:"refund_channel,omitempty"`
+	RefundFee     int    `xml:"refund_fee,omitempty" json:"refund_fee,omitempty"`
+}
+
+type RefundQueryResponse struct {
+	ReturnCode        string `xml:"return_code,omitempty" json:"return_code,omitempty"`
+	ReturnMsg         string `xml:"return_msg,omitempty" json:"return_msg,omitempty"`
+	RetCode           string `xml:"retcode,omitempty" json:"retcode,omitempty"`
+	RetMsg            string `xml:"retmsg,omitempty" json:"retmsg,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"`
+	ResultCode        string `xml:"result_code,omitempty" json:"result_code,omitempty"`
+	ErrCode           string `xml:"err_code,omitempty" json:"err_code,omitempty"`
+	ErrCodeDes        string `xml:"err_code_des,omitempty" json:"err_code_des,omitempty"`
+	NonceStr          string `xml:"nonce_str,omitempty" json:"nonce_str,omitempty"`
+	TransactionId     string `xml:"transaction_id,omitempty" json:"transaction_id,omitempty"`
+	OutTradeNo        string `xml:"out_trade_no,omitempty" json:"out_trade_no,omitempty"`
+	TotalFee          int    `xml:"total_fee,omitempty" json:"total_fee,omitempty"`
+	CashFee           int    `xml:"cash_fee,omitempty" json:"cash_fee,omitempty"`
+	FeeType           string `xml:"fee_type,omitempty" json:"fee_type,omitempty"`
+	OutRefundNo0      string `xml:"out_refund_no_0,omitempty" json:"out_refund_no_0,omitempty"`
+	OutRefundNo1      string `xml:"out_refund_no_1,omitempty" json:"out_refund_no_1,omitempty"`
+	RefundId0         string `xml:"refund_id_0,omitempty" json:"refund_id_0,omitempty"`
+	RefundId1         string `xml:"refund_id_1,omitempty" json:"refund_id_1,omitempty"`
+	RefundChannel0    string `xml:"refund_channel_0,omitempty" json:"refund_channel_0,omitempty"`
+	RefundChannel1    string `xml:"refund_channel_1,omitempty" json:"refund_channel_1,omitempty"`
+	RefundFee0        int    `xml:"refund_fee_0,omitempty" json:"refund_fee_0,omitempty"`
+	RefundFee1        int    `xml:"refund_fee_1,omitempty" json:"refund_fee_1,omitempty"`
+	CouponRefundFee0  int    `xml:"coupon_refund_fee_0,omitempty" json:"coupon_refund_fee_0,omitempty"`
+	CouponRefundFee1  int    `xml:"coupon_refund_fee_1,omitempty" json:"coupon_refund_fee_1,omitempty"`
+	CashRefundFee0    int    `xml:"cash_refund_fee_0,omitempty" json:"cash_refund_fee_0,omitempty"`
+	CashRefundFee1    int    `xml:"cash_refund_fee_1,omitempty" json:"cash_refund_fee_1,omitempty"`
+	RefundStatus0     string `xml:"refund_status_0,omitempty" json:"refund_status_0,omitempty"`
+	RefundStatus1     string `xml:"refund_status_1,omitempty" json:"refund_status_1,omitempty"`
+	RefundRecvAccout0 string `xml:"refund_recv_accout_0,omitempty" json:"refund_recv_accout_0,omitempty"`
+	RefundRecvAccout1 string `xml:"refund_recv_accout_1,omitempty" json:"refund_recv_accout_1,omitempty"`
+}

+ 117 - 0
qq/param.go

@@ -0,0 +1,117 @@
+package qq
+
+import (
+	"crypto/hmac"
+	"crypto/md5"
+	"crypto/sha256"
+	"crypto/tls"
+	"crypto/x509"
+	"encoding/hex"
+	"encoding/xml"
+	"errors"
+	"fmt"
+	"hash"
+	"io/ioutil"
+	"strings"
+
+	"github.com/iGoogle-ink/gopay"
+)
+
+// 添加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 路径
+//    pkcs12FilePath:apiclient_cert.p12 路径
+//    返回err
+func (q *Client) AddCertFilePath(certFilePath, keyFilePath, pkcs12FilePath string) (err error) {
+	cert, err := ioutil.ReadFile(certFilePath)
+	if err != nil {
+		return err
+	}
+	key, err := ioutil.ReadFile(keyFilePath)
+	if err != nil {
+		return err
+	}
+	pkcs, err := ioutil.ReadFile(pkcs12FilePath)
+	if err != nil {
+		return err
+	}
+	q.mu.Lock()
+	q.CertFile = cert
+	q.KeyFile = key
+	q.Pkcs12File = pkcs
+	q.mu.Unlock()
+	return nil
+}
+
+// 生成请求XML的Body体
+func generateXml(bm gopay.BodyMap) (reqXml string) {
+	bs, err := xml.Marshal(bm)
+	if err != nil {
+		return gopay.NULL
+	}
+	return string(bs)
+}
+
+// 获取QQ支付正式环境Sign值
+func getReleaseSign(apiKey string, signType string, bm gopay.BodyMap) (sign string) {
+	var h hash.Hash
+	if signType == SignType_HMAC_SHA256 {
+		h = hmac.New(sha256.New, []byte(apiKey))
+	} else {
+		h = md5.New()
+	}
+	h.Write([]byte(bm.EncodeWeChatSignParams(apiKey)))
+	return strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
+}
+
+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())
+		}
+		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())
+		}
+		pkcsPool.AppendCertsFromPEM(pkcs)
+		if certificate, err = tls.LoadX509KeyPair(certFilePath, keyFilePath); err != nil {
+			return nil, fmt.Errorf("tls.LoadX509KeyPair:%s", err.Error())
+		}
+		tlsConfig = &tls.Config{
+			Certificates:       []tls.Certificate{certificate},
+			RootCAs:            pkcsPool,
+			InsecureSkipVerify: true}
+		return tlsConfig, nil
+	}
+
+	return nil, errors.New("certificate file path must be all input or all input null")
+}

+ 39 - 0
qq/service_api.go

@@ -0,0 +1,39 @@
+package qq
+
+import (
+	"encoding/xml"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+
+	"github.com/iGoogle-ink/gopay"
+)
+
+// 解析QQ支付异步通知的结果到BodyMap
+//    req:*http.Request
+//    返回参数bm:Notify请求的参数
+//    返回参数err:错误信息
+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())
+	}
+	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
+}
+
+// 解析QQ支付异步通知的参数
+//    req:*http.Request
+//    返回参数notifyReq:Notify请求的参数
+//    返回参数err:错误信息
+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
+}

+ 10 - 1
release_note.txt

@@ -1,3 +1,12 @@
+版本号:Release 2.0.0
+发布时间:2019/12/12 18:22
+修改记录:
+   (1) 按支付渠道模块分包大调整
+   (2) 一大推细小改动,不一一描述了
+   (3) 支付宝:修改公共API方法:alipay.GetCertSN(),不再支持支付宝根证书的SN获取
+   (4) 支付宝:新增公共API方法:alipay.GetRootCertSN(),获取root证书序列号SN
+   (5) 支付宝:新增Client方法:alipay.SetLocation(),设置时区,不设置或出错均为默认服务器时间
+
 版本号:Release 1.4.8
 发布时间:2019/12/11 16:40
 修改记录:
@@ -31,7 +40,7 @@
    (2) 支付宝:修改公共API方法:gopay.VerifyAliPaySign(),支付宝异步验签支持传入 BodyMap
    (3) 微信:新增Client方法:client.AddCertFileByte(),添加微信证书 Byte 数组
    (4) 微信:新增Client方法:client.AddCertFilePath(),添加微信证书 Path 路径
-   (5) 微信:微信Client需要证书的方法,如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",如方法需单独使用证书,则传证书Path
+   (5) 微信:微信Client需要证书的方法,如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",否则,3证书Path均不可空
    (6) BodyMap 的Set方法去掉switch判断,直接赋值
    (7) WeChatClient、AliPayClient 加锁
    (8) 修改部分小问题和部分样式

+ 397 - 0
wechat/client.go

@@ -0,0 +1,397 @@
+package wechat
+
+import (
+	"crypto/tls"
+	"encoding/xml"
+	"errors"
+	"fmt"
+	"strings"
+	"sync"
+
+	"github.com/iGoogle-ink/gopay"
+)
+
+type Client struct {
+	AppId      string
+	MchId      string
+	ApiKey     string
+	BaseURL    string
+	CertFile   []byte
+	KeyFile    []byte
+	Pkcs12File []byte
+	IsProd     bool
+	mu         sync.RWMutex
+}
+
+// 初始化微信客户端
+//    appId:应用ID
+//    mchId:商户ID
+//    ApiKey:API秘钥值
+//    IsProd:是否是正式环境
+func NewClient(appId, mchId, apiKey string, isProd bool) (client *Client) {
+	return &Client{
+		AppId:  appId,
+		MchId:  mchId,
+		ApiKey: apiKey,
+		IsProd: isProd}
+}
+
+// 提交付款码支付
+//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1
+func (w *Client) Micropay(bm gopay.BodyMap) (wxRsp *MicropayResponse, err error) {
+	err = bm.CheckEmptyError("nonce_str", "body", "out_trade_no", "total_fee", "spbill_create_ip", "auth_code")
+	if err != nil {
+		return nil, err
+	}
+	var bs []byte
+	if w.IsProd {
+		bs, err = w.doWeChat(bm, wxMicropay, nil)
+	} else {
+		bs, err = w.doWeChat(bm, wxSandboxMicropay, nil)
+	}
+	if err != nil {
+		return
+	}
+	wxRsp = new(MicropayResponse)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+	}
+	return
+}
+
+// 统一下单
+//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
+func (w *Client) UnifiedOrder(bm gopay.BodyMap) (wxRsp *UnifiedOrderResponse, err error) {
+	err = bm.CheckEmptyError("nonce_str", "body", "out_trade_no", "total_fee", "spbill_create_ip", "notify_url", "trade_type")
+	if err != nil {
+		return nil, err
+	}
+	var bs []byte
+	if w.IsProd {
+		bs, err = w.doWeChat(bm, wxUnifiedorder, nil)
+	} else {
+		bm.Set("total_fee", 101)
+		bs, err = w.doWeChat(bm, wxSandboxUnifiedorder, nil)
+	}
+	if err != nil {
+		return
+	}
+	wxRsp = new(UnifiedOrderResponse)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+	}
+	return
+}
+
+// 查询订单
+//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2
+func (w *Client) QueryOrder(bm gopay.BodyMap) (wxRsp *QueryOrderResponse, err error) {
+	err = bm.CheckEmptyError("nonce_str")
+	if err != nil {
+		return nil, err
+	}
+	if bm.Get("out_trade_no") == gopay.NULL && bm.Get("transaction_id") == gopay.NULL {
+		return nil, errors.New("out_trade_no and transaction_id are not allowed to be null at the same time")
+	}
+	var bs []byte
+	if w.IsProd {
+		bs, err = w.doWeChat(bm, wxOrderquery, nil)
+	} else {
+		bs, err = w.doWeChat(bm, wxSandboxOrderquery, nil)
+	}
+	if err != nil {
+		return
+	}
+	wxRsp = new(QueryOrderResponse)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+	}
+	return
+}
+
+// 关闭订单
+//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3
+func (w *Client) CloseOrder(bm gopay.BodyMap) (wxRsp *CloseOrderResponse, err error) {
+	err = bm.CheckEmptyError("nonce_str", "out_trade_no")
+	if err != nil {
+		return nil, err
+	}
+	var bs []byte
+	if w.IsProd {
+		bs, err = w.doWeChat(bm, wxCloseorder, nil)
+	} else {
+		bs, err = w.doWeChat(bm, wxSandboxCloseorder, nil)
+	}
+	if err != nil {
+		return
+	}
+	wxRsp = new(CloseOrderResponse)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+	}
+	return
+}
+
+// 撤销订单
+//    注意:如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数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")
+	if err != nil {
+		return nil, err
+	}
+	var (
+		bs        []byte
+		tlsConfig *tls.Config
+	)
+	if w.IsProd {
+		if tlsConfig, err = w.addCertConfig(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
+			return nil, err
+		}
+		bs, err = w.doWeChat(bm, wxReverse, tlsConfig)
+	} else {
+		bs, err = w.doWeChat(bm, wxSandboxReverse, nil)
+	}
+	if err != nil {
+		return
+	}
+	wxRsp = new(ReverseResponse)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+	}
+	return
+}
+
+// 申请退款
+//    注意:如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数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")
+	if err != nil {
+		return nil, err
+	}
+	if bm.Get("out_trade_no") == gopay.NULL && bm.Get("transaction_id") == gopay.NULL {
+		return nil, errors.New("out_trade_no and transaction_id are not allowed to be null at the same time")
+	}
+	var (
+		bs        []byte
+		tlsConfig *tls.Config
+	)
+	if w.IsProd {
+		if tlsConfig, err = w.addCertConfig(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
+			return nil, err
+		}
+		bs, err = w.doWeChat(bm, wxRefund, tlsConfig)
+	} else {
+		bs, err = w.doWeChat(bm, wxSandboxRefund, nil)
+	}
+	if err != nil {
+		return
+	}
+	wxRsp = new(RefundResponse)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+	}
+	return
+}
+
+// 查询退款
+//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
+func (w *Client) QueryRefund(bm gopay.BodyMap) (wxRsp *QueryRefundResponse, err error) {
+	err = bm.CheckEmptyError("nonce_str")
+	if err != nil {
+		return nil, err
+	}
+	if bm.Get("refund_id") == gopay.NULL && bm.Get("out_refund_no") == gopay.NULL && bm.Get("transaction_id") == gopay.NULL && bm.Get("out_trade_no") == gopay.NULL {
+		return nil, errors.New("refund_id, out_refund_no, out_trade_no, transaction_id are not allowed to be null at the same time")
+	}
+	var bs []byte
+	if w.IsProd {
+		bs, err = w.doWeChat(bm, wxRefundquery, nil)
+	} else {
+		bs, err = w.doWeChat(bm, wxSandboxRefundquery, nil)
+	}
+	if err != nil {
+		return
+	}
+	wxRsp = new(QueryRefundResponse)
+	if err = xml.Unmarshal(bs, wxRsp); err != nil {
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
+	}
+	return
+}
+
+// 下载对账单
+//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6
+func (w *Client) DownloadBill(bm gopay.BodyMap) (wxRsp string, err error) {
+	err = bm.CheckEmptyError("nonce_str", "bill_date", "bill_type")
+	if err != nil {
+		return gopay.NULL, err
+	}
+	billType := bm.Get("bill_type")
+	if billType != "ALL" && billType != "SUCCESS" && billType != "REFUND" && billType != "RECHARGE_REFUND" {
+		return gopay.NULL, errors.New("bill_type error, please reference: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6")
+	}
+	var bs []byte
+	if w.IsProd {
+		bs, err = w.doWeChat(bm, wxDownloadbill, nil)
+	} else {
+		bs, err = w.doWeChat(bm, wxSandboxDownloadbill, nil)
+	}
+	if err != nil {
+		return
+	}
+	wxRsp = string(bs)
+	return
+}
+
+// 下载资金账单
+//    注意:如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数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) {
+	err = bm.CheckEmptyError("nonce_str", "bill_date", "account_type")
+	if err != nil {
+		return gopay.NULL, err
+	}
+	accountType := bm.Get("account_type")
+	if accountType != "Basic" && accountType != "Operation" && accountType != "Fees" {
+		return gopay.NULL, errors.New("account_type error, please reference: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_18&index=7")
+	}
+	var (
+		bs        []byte
+		tlsConfig *tls.Config
+	)
+	bm.Set("sign_type", SignType_HMAC_SHA256)
+	if w.IsProd {
+		if tlsConfig, err = w.addCertConfig(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
+			return gopay.NULL, err
+		}
+		bs, err = w.doWeChat(bm, wxDownloadfundflow, tlsConfig)
+	} else {
+		bs, err = w.doWeChat(bm, wxSandboxDownloadfundflow, nil)
+	}
+	if err != nil {
+		return
+	}
+	wxRsp = string(bs)
+	return
+}
+
+// 拉取订单评价数据
+//    注意:如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数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) {
+	err = bm.CheckEmptyError("nonce_str", "begin_time", "end_time", "offset")
+	if err != nil {
+		return gopay.NULL, err
+	}
+	var (
+		bs        []byte
+		tlsConfig *tls.Config
+	)
+	bm.Set("sign_type", SignType_HMAC_SHA256)
+	if w.IsProd {
+		if tlsConfig, err = w.addCertConfig(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
+			return gopay.NULL, err
+		}
+		bs, err = w.doWeChat(bm, wxBatchquerycomment, tlsConfig)
+	} else {
+		bs, err = w.doWeChat(bm, wxSandboxBatchquerycomment, nil)
+	}
+	if err != nil {
+		return
+	}
+	wxRsp = string(bs)
+	return
+}
+
+// 企业向微信用户个人付款
+//    注意:如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数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) {
+	err = bm.CheckEmptyError("nonce_str", "partner_trade_no", "openid", "check_name", "amount", "desc", "spbill_create_ip")
+	if err != nil {
+		return nil, err
+	}
+	bm.Set("mch_appid", w.AppId)
+	bm.Set("mchid", w.MchId)
+	var (
+		tlsConfig *tls.Config
+		url       = wxBaseUrlCh + wxTransfers
+	)
+	if tlsConfig, err = w.addCertConfig(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
+		return nil, err
+	}
+	bm.Set("sign", getReleaseSign(w.ApiKey, SignType_MD5, bm))
+
+	httpClient := gopay.NewHttpClient().SetTLSConfig(tlsConfig).Type(gopay.TypeXML)
+	if w.BaseURL != gopay.NULL {
+		w.mu.RLock()
+		url = w.BaseURL + wxTransfers
+		w.mu.RUnlock()
+	}
+	wxRsp = new(TransfersResponse)
+	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
+}
+
+// 公众号纯签约(未完成)
+//    文档地址: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, wxEntrustPublic, nil)
+
+	return nil, nil
+}
+
+// 向微信发送请求
+func (w *Client) doWeChat(bm gopay.BodyMap, path string, tlsConfig *tls.Config) (bs []byte, err error) {
+	var url = wxBaseUrlCh + path
+	bm.Set("appid", w.AppId)
+	bm.Set("mch_id", w.MchId)
+
+	if bm.Get("sign") == gopay.NULL {
+		var sign string
+		if !w.IsProd {
+			bm.Set("sign_type", SignType_MD5)
+			sign, err = getSignBoxSign(w.MchId, w.ApiKey, bm)
+			if err != nil {
+				return nil, err
+			}
+		} else {
+			sign = getReleaseSign(w.ApiKey, bm.Get("sign_type"), bm)
+		}
+		bm.Set("sign", sign)
+	}
+
+	httpClient := gopay.NewHttpClient()
+	if w.IsProd && tlsConfig != nil {
+		httpClient.SetTLSConfig(tlsConfig)
+	}
+
+	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()
+	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") {
+		return nil, errors.New(string(bs))
+	}
+	return bs, nil
+}

+ 375 - 0
wechat/client_test.go

@@ -0,0 +1,375 @@
+package wechat
+
+import (
+	"fmt"
+	"os"
+	"strconv"
+	"testing"
+	"time"
+
+	"github.com/iGoogle-ink/gopay"
+)
+
+var (
+	client *Client
+	appId  = "wxdaa2ab9ef87b5497"
+	mchId  = "1368139502"
+	apiKey = "GFDS8j98rewnmgl45wHTt980jg543abc"
+)
+
+func TestMain(m *testing.M) {
+
+	// 初始化微信客户端
+	//    appId:应用ID
+	//    mchId:商户ID
+	//    apiKey:API秘钥值
+	//    isProd:是否是正式环境
+	client = NewClient(appId, mchId, apiKey, false)
+
+	// 设置国家,不设置默认就是 China
+	client.SetCountry(China)
+
+	//err := client.AddCertFilePath("", "", "")
+	//if err != nil {
+	//	panic(err)
+	//}
+
+	os.Exit(m.Run())
+}
+
+func TestClient_UnifiedOrder(t *testing.T) {
+	number := gopay.GetRandomString(32)
+	fmt.Println("out_trade_no:", number)
+	// 初始化参数Map
+	bm := make(gopay.BodyMap)
+	bm.Set("nonce_str", gopay.GetRandomString(32))
+	bm.Set("body", "H5支付")
+	bm.Set("out_trade_no", number)
+	bm.Set("total_fee", 1)
+	bm.Set("spbill_create_ip", "127.0.0.1")
+	bm.Set("notify_url", "http://www.gopay.ink")
+	bm.Set("trade_type", TradeType_H5)
+	bm.Set("device_info", "WEB")
+	bm.Set("sign_type", SignType_MD5)
+
+	sceneInfo := make(map[string]map[string]string)
+	h5Info := make(map[string]string)
+	h5Info["type"] = "Wap"
+	h5Info["wap_url"] = "http://www.gopay.ink"
+	h5Info["wap_name"] = "H5测试支付"
+	sceneInfo["h5_info"] = h5Info
+	bm.Set("scene_info", sceneInfo)
+
+	//bm.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")
+
+	// 正式
+	//sign := gopay.GetWeChatParamSign("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", body)
+	// 沙箱
+	//sign, _ := gopay.GetWeChatSanBoxParamSign("wxdaa2ab9ef87b5497", "1368139502", "GFDS8j98rewnmgl45wHTt980jg543abc", body)
+	//body.Set("sign", sign)
+
+	// 请求支付下单,成功后得到结果
+	wxRsp, err := client.UnifiedOrder(bm)
+	if err != nil {
+		fmt.Println("Error:", err)
+		return
+	}
+	fmt.Println("wxRsp:", *wxRsp)
+	//fmt.Println("wxRsp.MwebUrl:", wxRsp.MwebUrl)
+
+	timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
+
+	// 获取小程序支付需要的paySign
+	//pac := "prepay_id=" + wxRsp.PrepayId
+	//paySign := GetMiniPaySign(appId, wxRsp.NonceStr, pac, SignType_MD5, timeStamp, apiKey)
+	//fmt.Println("paySign:", paySign)
+
+	// 获取H5支付需要的paySign
+	pac := "prepay_id=" + wxRsp.PrepayId
+	paySign := GetH5PaySign(appId, wxRsp.NonceStr, pac, SignType_MD5, timeStamp, apiKey)
+	fmt.Println("paySign:", paySign)
+
+	// 获取小程序需要的paySign
+	//paySign := GetAppPaySign(appId,"partnerid", wxRsp.NonceStr, wxRsp.PrepayId, SignType_MD5, timeStamp, apiKey)
+	//fmt.Println("paySign:", paySign)
+}
+
+func TestClient_QueryOrder(t *testing.T) {
+	// 初始化参数结构体
+	bm := make(gopay.BodyMap)
+	bm.Set("out_trade_no", "MfZC2segKxh0bnJSELbvKNeH3d9oWvvQ")
+	bm.Set("nonce_str", gopay.GetRandomString(32))
+	bm.Set("sign_type", SignType_MD5)
+
+	// 请求订单查询,成功后得到结果
+	wxRsp, err := client.QueryOrder(bm)
+	if err != nil {
+		fmt.Println("Error:", err)
+		return
+	}
+	fmt.Println("wxRsp:", *wxRsp)
+}
+
+func TestClient_CloseOrder(t *testing.T) {
+	// 初始化参数结构体
+	bm := make(gopay.BodyMap)
+	bm.Set("out_trade_no", "MfZC2segKxh0bnJSELbvKNeH3d9oWvvQ")
+	bm.Set("nonce_str", gopay.GetRandomString(32))
+	bm.Set("sign_type", SignType_MD5)
+
+	// 请求关闭订单,成功后得到结果
+	wxRsp, err := client.CloseOrder(bm)
+	if err != nil {
+		fmt.Println("Error:", err)
+		return
+	}
+	fmt.Println("wxRsp:", *wxRsp)
+}
+
+func TestClient_Micropay(t *testing.T) {
+	number := gopay.GetRandomString(32)
+	fmt.Println("out_trade_no:", number)
+	// 初始化参数Map
+	bm := make(gopay.BodyMap)
+	bm.Set("nonce_str", gopay.GetRandomString(32))
+	bm.Set("body", "扫用户付款码支付")
+	bm.Set("out_trade_no", number)
+	bm.Set("total_fee", 1)
+	bm.Set("spbill_create_ip", "127.0.0.1")
+	bm.Set("auth_code", "134622817080551492")
+	bm.Set("sign_type", SignType_MD5)
+
+	// 请求支付,成功后得到结果
+	wxRsp, err := client.Micropay(bm)
+	if err != nil {
+		fmt.Println("Error:", err)
+		return
+	}
+	fmt.Println("Response:", *wxRsp)
+
+	ok, err := VerifySign(apiKey, SignType_MD5, wxRsp)
+	if err != nil {
+		fmt.Println("err:", err)
+	}
+	fmt.Println("同步验签结果:", ok)
+}
+
+func TestClient_Refund(t *testing.T) {
+	// 初始化参数结构体
+	bm := make(gopay.BodyMap)
+	bm.Set("out_trade_no", "QRcTBTbJLoDrWSW9FtpSFlgWhft2QbaY")
+	bm.Set("nonce_str", gopay.GetRandomString(32))
+	bm.Set("sign_type", SignType_MD5)
+	s := gopay.GetRandomString(64)
+	fmt.Println("out_refund_no:", s)
+	bm.Set("out_refund_no", s)
+	bm.Set("total_fee", 101)
+	bm.Set("refund_fee", 101)
+	bm.Set("notify_url", "https://www.gopay.ink")
+
+	// 请求申请退款(沙箱环境下,证书路径参数可传空)
+	//    body:参数Body
+	//    certFilePath:cert证书路径
+	//    keyFilePath:Key证书路径
+	//    pkcs12FilePath:p12证书路径
+	wxRsp, err := client.Refund(bm, "", "", "")
+	if err != nil {
+		fmt.Println("Error:", err)
+		return
+	}
+	fmt.Println("wxRsp:", *wxRsp)
+}
+
+func TestClient_QueryRefund(t *testing.T) {
+	// 初始化参数结构体
+	bm := make(gopay.BodyMap)
+	bm.Set("out_trade_no", "97HiM5j6kGmM2fk7fYMc8MgKhPnEQ5Rk")
+	//bm.Set("out_refund_no", "vk4264I1UQ3Hm3E4AKsavK8npylGSgQA092f9ckUxp8A2gXmnsLEdsupURVTcaC7")
+	//bm.Set("transaction_id", "97HiM5j6kGmM2fk7fYMc8MgKhPnEQ5Rk")
+	//bm.Set("refund_id", "97HiM5j6kGmM2fk7fYMc8MgKhPnEQ5Rk")
+	bm.Set("nonce_str", gopay.GetRandomString(32))
+	bm.Set("sign_type", SignType_MD5)
+
+	// 请求申请退款
+	wxRsp, err := client.QueryRefund(bm)
+	if err != nil {
+		fmt.Println("Error:", err)
+		return
+	}
+	fmt.Println("wxRsp:", *wxRsp)
+}
+
+func TestClient_Reverse(t *testing.T) {
+	// 初始化参数Map
+	bm := make(gopay.BodyMap)
+	bm.Set("nonce_str", gopay.GetRandomString(32))
+	bm.Set("out_trade_no", "6aDCor1nUcAihrV5JBlI09tLvXbUp02B")
+	bm.Set("sign_type", SignType_MD5)
+
+	// 请求撤销订单,成功后得到结果,沙箱环境下,证书路径参数可传空
+	wxRsp, err := client.Reverse(bm, "", "", "")
+	if err != nil {
+		fmt.Println("Error:", err)
+		return
+	}
+	fmt.Println("Response:", wxRsp)
+}
+
+func TestClient_Transfer(t *testing.T) {
+	// 初始化参数结构体
+	bm := make(gopay.BodyMap)
+	bm.Set("nonce_str", gopay.GetRandomString(32))
+	bm.Set("partner_trade_no", gopay.GetRandomString(32))
+	bm.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")
+	bm.Set("check_name", "FORCE_CHECK") // NO_CHECK:不校验真实姓名 , FORCE_CHECK:强校验真实姓名
+	bm.Set("re_user_name", "付明明")       // 收款用户真实姓名。 如果check_name设置为FORCE_CHECK,则必填用户真实姓名
+	bm.Set("amount", 30)                // 企业付款金额,单位为分
+	bm.Set("desc", "测试转账")              // 企业付款备注,必填。注意:备注中的敏感词会被转成字符*
+	bm.Set("spbill_create_ip", "127.0.0.1")
+
+	// 企业向微信用户个人付款(不支持沙箱环境)
+	//    body:参数Body
+	//    certFilePath:cert证书路径
+	//    keyFilePath:Key证书路径
+	//    pkcs12FilePath:p12证书路径
+	wxRsp, err := client.Transfer(bm, "", "", "")
+	if err != nil {
+		fmt.Println("Error:", err)
+		return
+	}
+	fmt.Println("wxRsp:", *wxRsp)
+}
+
+func TestClient_DownloadBill(t *testing.T) {
+	// 初始化参数结构体
+	bm := make(gopay.BodyMap)
+	bm.Set("nonce_str", gopay.GetRandomString(32))
+	bm.Set("sign_type", SignType_MD5)
+	bm.Set("bill_date", "20190722")
+	bm.Set("bill_type", "ALL")
+
+	// 请求下载对账单,成功后得到结果(string类型字符串)
+	wxRsp, err := client.DownloadBill(bm)
+	if err != nil {
+		fmt.Println("Error:", err)
+		return
+	}
+	fmt.Println("wxRsp:", wxRsp)
+}
+
+func TestClient_DownloadFundFlow(t *testing.T) {
+	// 初始化参数结构体
+	bm := make(gopay.BodyMap)
+	bm.Set("nonce_str", gopay.GetRandomString(32))
+	bm.Set("sign_type", SignType_HMAC_SHA256)
+	bm.Set("bill_date", "20190122")
+	bm.Set("account_type", "Basic")
+
+	// 请求下载资金账单,成功后得到结果,沙箱环境下,证书路径参数可传空
+	wxRsp, err := client.DownloadFundFlow(bm, "", "", "")
+	if err != nil {
+		fmt.Println("Error:", err)
+		return
+	}
+	fmt.Println("wxRsp:", wxRsp)
+}
+
+func TestClient_BatchQueryComment(t *testing.T) {
+	// 初始化参数结构体
+	bm := make(gopay.BodyMap)
+	bm.Set("nonce_str", gopay.GetRandomString(32))
+	bm.Set("sign_type", SignType_HMAC_SHA256)
+	bm.Set("begin_time", "20190120000000")
+	bm.Set("end_time", "20190122174000")
+	bm.Set("offset", "0")
+
+	// 请求拉取订单评价数据,成功后得到结果,沙箱环境下,证书路径参数可传空
+	wxRsp, err := client.BatchQueryComment(bm, "", "", "")
+	if err != nil {
+		fmt.Println("Error:", err)
+		return
+	}
+	fmt.Println("wxRsp:", wxRsp)
+}
+
+// =======================
+
+func TestDecryptOpenDataToStruct(t *testing.T) {
+	data := "Kf3TdPbzEmhWMuPKtlKxIWDkijhn402w1bxoHL4kLdcKr6jT1jNcIhvDJfjXmJcgDWLjmBiIGJ5acUuSvxLws3WgAkERmtTuiCG10CKLsJiR+AXVk7B2TUQzsq88YVilDz/YAN3647REE7glGmeBPfvUmdbfDzhL9BzvEiuRhABuCYyTMz4iaM8hFjbLB1caaeoOlykYAFMWC5pZi9P8uw=="
+	iv := "Cds8j3VYoGvnTp1BrjXdJg=="
+	session := "lyY4HPQbaOYzZdG+JcYK9w=="
+	phone := new(UserPhone)
+	//解密开放数据
+	//    encryptedData:包括敏感数据在内的完整用户信息的加密数据
+	//    iv:加密算法的初始向量
+	//    sessionKey:会话密钥
+	//    beanPtr:需要解析到的结构体指针
+	err := DecryptOpenDataToStruct(data, iv, session, phone)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("PhoneNumber:", phone.PhoneNumber)
+	fmt.Println("PurePhoneNumber:", phone.PurePhoneNumber)
+	fmt.Println("CountryCode:", phone.CountryCode)
+	fmt.Println("Watermark:", phone.Watermark)
+
+	sessionKey := "tiihtNczf5v6AKRyjwEUhQ=="
+	encryptedData := "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZMQmRzooG2xrDcvSnxIMXFufNstNGTyaGS9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+3hVbJSRgv+4lGOETKUQz6OYStslQ142dNCuabNPGBzlooOmB231qMM85d2/fV6ChevvXvQP8Hkue1poOFtnEtpyxVLW1zAo6/1Xx1COxFvrc2d7UL/lmHInNlxuacJXwu0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn/Hz7saL8xz+W//FRAUid1OksQaQx4CMs8LOddcQhULW4ucetDf96JcR3g0gfRK4PC7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns/8wR2SiRS7MNACwTyrGvt9ts8p12PKFdlqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYVoKlaRv85IfVunYzO0IKXsyl7JCUjCpoG20f0a04COwfneQAGGwd5oa+T8yO5hzuyDb/XcxxmK01EpqOyuxINew=="
+	iv2 := "r7BXXKkLb8qrSNn05n0qiA=="
+
+	//微信小程序 用户信息
+	userInfo := new(AppletUserInfo)
+
+	err = DecryptOpenDataToStruct(encryptedData, iv2, sessionKey, userInfo)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("NickName:", userInfo.NickName)
+	fmt.Println("AvatarUrl:", userInfo.AvatarUrl)
+	fmt.Println("Country:", userInfo.Country)
+	fmt.Println("Province:", userInfo.Province)
+	fmt.Println("City:", userInfo.City)
+	fmt.Println("Gender:", userInfo.Gender)
+	fmt.Println("OpenId:", userInfo.OpenId)
+	fmt.Println("UnionId:", userInfo.UnionId)
+	fmt.Println("Watermark:", userInfo.Watermark)
+}
+
+func TestDecryptOpenDataToBodyMap(t *testing.T) {
+	data := "Kf3TdPbzEmhWMuPKtlKxIWDkijhn402w1bxoHL4kLdcKr6jT1jNcIhvDJfjXmJcgDWLjmBiIGJ5acUuSvxLws3WgAkERmtTuiCG10CKLsJiR+AXVk7B2TUQzsq88YVilDz/YAN3647REE7glGmeBPfvUmdbfDzhL9BzvEiuRhABuCYyTMz4iaM8hFjbLB1caaeoOlykYAFMWC5pZi9P8uw=="
+	iv := "Cds8j3VYoGvnTp1BrjXdJg=="
+	session := "lyY4HPQbaOYzZdG+JcYK9w=="
+
+	//解密开放数据
+	//    encryptedData:包括敏感数据在内的完整用户信息的加密数据
+	//    iv:加密算法的初始向量
+	//    sessionKey:会话密钥
+	bm, err := DecryptOpenDataToBodyMap(data, iv, session)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("WeChatUserPhone:", bm)
+}
+
+func TestDecryptRefundNotifyReqInfo(t *testing.T) {
+	key := "ziR0QKsTUfMOuochC9RfCdmfHECorQAP"
+	data := "YYwp8C48th0wnQzTqeI+41pflB26v+smFj9z6h9RPBgxTyZyxc+4YNEz7QEgZNWj/6rIb2MfyWMZmCc41CfjKSssoSZPXxOhUayb6KvNSZ1p6frOX1PDWzhyruXK7ouNND+gDsG4yZ0XXzsL4/pYNwLLba/71QrnkJ/BHcByk4EXnglju5DLup9pJQSnTxjomI9Rxu57m9jg5lLQFxMWXyeASZJNvof0ulnHlWJswS4OxKOkmW7VEyKyLGV6npoOm03Qsx2wkRxLsSa9gPpg4hdaReeUqh1FMbm7aWjyrVYT/MEZWg98p4GomEIYvz34XfDncTezX4bf/ZiSLXt79aE1/YTZrYfymXeCrGjlbe0rg/T2ezJHAC870u2vsVbY1/KcE2A443N+DEnAziXlBQ1AeWq3Rqk/O6/TMM0lomzgctAOiAMg+bh5+Gu1ubA9O3E+vehULydD5qx2o6i3+qA9ORbH415NyRrQdeFq5vmCiRikp5xYptWiGZA0tkoaLKMPQ4ndE5gWHqiBbGPfULZWokI+QjjhhBmwgbd6J0VqpRorwOuzC/BHdkP72DCdNcm7IDUpggnzBIy0+seWIkcHEryKjge3YDHpJeQCqrAH0CgxXHDt1xtbQbST1VqFyuhPhUjDXMXrknrGPN/oE1t0rLRq+78cI+k8xe5E6seeUXQsEe8r3358mpcDYSmXWSXVZxK6er9EF98APqHwcndyEJD2YyCh/mMVhERuX+7kjlRXSiNUWa/Cv/XAKFQuvUYA5ea2eYWtPRHa4DpyuF1SNsaqVKfgqKXZrJHfAgslVpSVqUpX4zkKszHF4kwMZO3M7J1P94Mxa7Tm9mTOJePOoHPXeEB+m9rX6pSfoi3mJDQ5inJ+Vc4gOkg/Wd/lqiy6TTyP/dHDN6/v+AuJx5AXBo/2NDD3fWhHjkqEKIuARr2ClZt9ZRQO4HkXdZo7CN06sGCHk48Tg8PmxnxKcMZm7Aoquv5yMIM2gWSWIRJhwJ8cUpafIHc+GesDlbF6Zbt+/KXkafJAQq2RklEN+WvZ/zFz113EPgWPjp16TwBoziq96MMekvWKY/vdhjol8VFtGH9F61Oy1Xwf6DJtPw=="
+	refundNotify, err := DecryptRefundNotifyReqInfo(data, key)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("refundNotify:", *refundNotify)
+}
+
+func TestGetAppletAccessToken(t *testing.T) {
+	token, err := GetAppletAccessToken("wxdaa2ab9ef87b5497", "AppSecret")
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+	fmt.Println("token:", token)
+}

+ 109 - 50
wechat_rsp.go → wechat/model.go

@@ -1,6 +1,100 @@
-package gopay
+package wechat
 
-type WeChatUnifiedOrderResponse struct {
+const (
+	// 境外国家地区
+	China         Country = 1 // 中国国内
+	China2        Country = 2 // 中国国内(冗灾方案)
+	SoutheastAsia Country = 3 // 东南亚
+	Other         Country = 4 // 其他国家
+
+	// URL
+	wxBaseUrlCh  = "https://api.mch.weixin.qq.com/"   //中国国内
+	wxBaseUrlCh2 = "https://api2.mch.weixin.qq.com/"  //中国国内
+	wxBaseUrlHk  = "https://apihk.mch.weixin.qq.com/" //东南亚
+	wxBaseUrlUs  = "https://apius.mch.weixin.qq.com/" //其他
+
+	// 正式
+	wxMicropay          = "pay/micropay"                          //提交付款码支付
+	wxUnifiedorder      = "pay/unifiedorder"                      //统一下单
+	wxOrderquery        = "pay/orderquery"                        //查询订单
+	wxCloseorder        = "pay/closeorder"                        //关闭订单
+	wxRefund            = "secapi/pay/refund"                     //申请退款
+	wxReverse           = "secapi/pay/reverse"                    //撤销订单
+	wxRefundquery       = "pay/refundquery"                       //查询退款
+	wxDownloadbill      = "pay/downloadbill"                      //下载对账单
+	wxDownloadfundflow  = "pay/downloadfundflow"                  //下载资金账单
+	wxBatchquerycomment = "billcommentsp/batchquerycomment"       //拉取订单评价数据
+	wxTransfers         = "mmpaymkttransfers/promotion/transfers" //企业向微信用户个人付款
+	wxEntrustPublic     = "papay/entrustweb"                      //公众号纯签约
+	wxEntrustApp        = "papay/preentrustweb"                   //APP纯签约
+	wxEntrustH5         = "papay/h5entrustweb"                    //H5纯签约
+	wxEntrustQuery      = "papay/querycontract"                   //查询签约关系
+	wxEntrustDelete     = "papay/deletecontract"                  //申请解约
+	wxEntrustApplyPay   = "pay/pappayapply"                       //申请扣款
+	wxEntrustQueryOrder = "pay/paporderquery"                     //查询扣款订单
+
+	// SanBox
+	wxSandboxGetsignkey        = "https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey"
+	wxSandboxMicropay          = "sandboxnew/pay/micropay"
+	wxSandboxUnifiedorder      = "sandboxnew/pay/unifiedorder"
+	wxSandboxOrderquery        = "sandboxnew/pay/orderquery"
+	wxSandboxCloseorder        = "sandboxnew/pay/closeorder"
+	wxSandboxRefund            = "sandboxnew/pay/refund"
+	wxSandboxReverse           = "sandboxnew/pay/reverse"
+	wxSandboxRefundquery       = "sandboxnew/pay/refundquery"
+	wxSandboxDownloadbill      = "sandboxnew/pay/downloadbill"
+	wxSandboxDownloadfundflow  = "sandboxnew/pay/downloadfundflow"
+	wxSandboxBatchquerycomment = "sandboxnew/billcommentsp/batchquerycomment"
+
+	// 支付类型
+	TradeType_Mini   = "JSAPI"  // 小程序支付
+	TradeType_JsApi  = "JSAPI"  // JSAPI支付
+	TradeType_App    = "APP"    // app支付
+	TradeType_H5     = "MWEB"   // H5支付
+	TradeType_Native = "NATIVE" // Native支付
+
+	// 签名方式
+	SignType_MD5         = "MD5"
+	SignType_HMAC_SHA256 = "HMAC-SHA256"
+)
+
+// Notify
+type NotifyRequest 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"`
+	ErrCodeDes         string `xml:"err_code_des,omitempty" json:"err_code_des,omitempty"`
+	Appid              string `xml:"appid,omitempty" json:"appid,omitempty"`
+	MchId              string `xml:"mch_id,omitempty" json:"mch_id,omitempty"`
+	DeviceInfo         string `xml:"device_info,omitempty" json:"device_info,omitempty"`
+	NonceStr           string `xml:"nonce_str,omitempty" json:"nonce_str,omitempty"`
+	Sign               string `xml:"sign,omitempty" json:"sign,omitempty"`
+	SignType           string `xml:"sign_type,omitempty" json:"sign_type,omitempty"`
+	Openid             string `xml:"openid,omitempty" json:"openid,omitempty"`
+	IsSubscribe        string `xml:"is_subscribe,omitempty" json:"is_subscribe,omitempty"`
+	TradeType          string `xml:"trade_type,omitempty" json:"trade_type,omitempty"`
+	BankType           string `xml:"bank_type,omitempty" json:"bank_type,omitempty"`
+	TotalFee           int    `xml:"total_fee,omitempty" json:"total_fee,omitempty"`
+	SettlementTotalFee int    `xml:"settlement_total_fee,omitempty" json:"settlement_total_fee,omitempty"`
+	FeeType            string `xml:"fee_type,omitempty" json:"fee_type,omitempty"`
+	CashFee            int    `xml:"cash_fee,omitempty" json:"cash_fee,omitempty"`
+	CashFeeType        string `xml:"cash_fee_type,omitempty" json:"cash_fee_type,omitempty"`
+	CouponFee          int    `xml:"coupon_fee,omitempty" json:"coupon_fee,omitempty"`
+	CouponCount        int    `xml:"coupon_count,omitempty" json:"coupon_count,omitempty"`
+	CouponType0        string `xml:"coupon_type_0,omitempty" json:"coupon_type_0,omitempty"`
+	CouponType1        string `xml:"coupon_type_1,omitempty" json:"coupon_type_1,omitempty"`
+	CouponId0          string `xml:"coupon_id_0,omitempty" json:"coupon_id_0,omitempty"`
+	CouponId1          string `xml:"coupon_id_1,omitempty" json:"coupon_id_1,omitempty"`
+	CouponFee0         int    `xml:"coupon_fee_0,omitempty" json:"coupon_fee_0,omitempty"`
+	CouponFee1         int    `xml:"coupon_fee_1,omitempty" json:"coupon_fee_1,omitempty"`
+	TransactionId      string `xml:"transaction_id,omitempty" json:"transaction_id,omitempty"`
+	OutTradeNo         string `xml:"out_trade_no,omitempty" json:"out_trade_no,omitempty"`
+	Attach             string `xml:"attach,omitempty" json:"attach,omitempty"`
+	TimeEnd            string `xml:"time_end,omitempty" json:"time_end,omitempty"`
+}
+
+type UnifiedOrderResponse 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"`
@@ -17,7 +111,7 @@ type WeChatUnifiedOrderResponse struct {
 	MwebUrl    string `xml:"mweb_url,omitempty" json:"mweb_url,omitempty"`
 }
 
-type WeChatQueryOrderResponse struct {
+type QueryOrderResponse 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"`
@@ -53,7 +147,7 @@ type WeChatQueryOrderResponse struct {
 	TradeStateDesc     string `xml:"trade_state_desc,omitempty" json:"trade_state_desc,omitempty"`
 }
 
-type WeChatCloseOrderResponse struct {
+type CloseOrderResponse 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"`
@@ -66,7 +160,7 @@ type WeChatCloseOrderResponse struct {
 	ErrCodeDes string `xml:"err_code_des,omitempty" json:"err_code_des,omitempty"`
 }
 
-type WeChatReverseResponse struct {
+type ReverseResponse 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"`
@@ -79,7 +173,7 @@ type WeChatReverseResponse struct {
 	Recall     string `xml:"recall,omitempty" json:"recall,omitempty"`
 }
 
-type WeChatRefundResponse struct {
+type RefundResponse 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"`
@@ -111,7 +205,7 @@ type WeChatRefundResponse struct {
 	CouponRefundId1     string `xml:"coupon_refund_id_1,omitempty" json:"coupon_refund_id_1,omitempty"`
 }
 
-type WeChatQueryRefundResponse struct {
+type QueryRefundResponse 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"`
@@ -166,7 +260,7 @@ type WeChatQueryRefundResponse struct {
 	RefundSuccessTime1   string `xml:"refund_success_time_1,omitempty" json:"refund_success_time_1,omitempty"`
 }
 
-type WeChatMicropayResponse struct {
+type MicropayResponse 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"`
@@ -194,7 +288,7 @@ type WeChatMicropayResponse struct {
 	PromotionDetail    string `xml:"promotion_detail,omitempty" json:"promotion_detail,omitempty"`
 }
 
-type WeChatTransfersResponse struct {
+type TransfersResponse struct {
 	ReturnCode     string `xml:"return_code,omitempty" json:"return_code,omitempty"`
 	ReturnMsg      string `xml:"return_msg,omitempty" json:"return_msg,omitempty"`
 	MchAppid       string `xml:"mch_appid,omitempty" json:"mch_appid,omitempty"`
@@ -216,42 +310,7 @@ type getSignKeyResponse struct {
 	SandboxSignkey string `xml:"sandbox_signkey,omitempty" json:"sandbox_signkey,omitempty"`
 }
 
-type WeChatNotifyRequest 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"`
-	ErrCodeDes         string `xml:"err_code_des,omitempty" json:"err_code_des,omitempty"`
-	Appid              string `xml:"appid,omitempty" json:"appid,omitempty"`
-	MchId              string `xml:"mch_id,omitempty" json:"mch_id,omitempty"`
-	DeviceInfo         string `xml:"device_info,omitempty" json:"device_info,omitempty"`
-	NonceStr           string `xml:"nonce_str,omitempty" json:"nonce_str,omitempty"`
-	Sign               string `xml:"sign,omitempty" json:"sign,omitempty"`
-	SignType           string `xml:"sign_type,omitempty" json:"sign_type,omitempty"`
-	Openid             string `xml:"openid,omitempty" json:"openid,omitempty"`
-	IsSubscribe        string `xml:"is_subscribe,omitempty" json:"is_subscribe,omitempty"`
-	TradeType          string `xml:"trade_type,omitempty" json:"trade_type,omitempty"`
-	BankType           string `xml:"bank_type,omitempty" json:"bank_type,omitempty"`
-	TotalFee           int    `xml:"total_fee,omitempty" json:"total_fee,omitempty"`
-	SettlementTotalFee int    `xml:"settlement_total_fee,omitempty" json:"settlement_total_fee,omitempty"`
-	FeeType            string `xml:"fee_type,omitempty" json:"fee_type,omitempty"`
-	CashFee            int    `xml:"cash_fee,omitempty" json:"cash_fee,omitempty"`
-	CashFeeType        string `xml:"cash_fee_type,omitempty" json:"cash_fee_type,omitempty"`
-	CouponFee          int    `xml:"coupon_fee,omitempty" json:"coupon_fee,omitempty"`
-	CouponCount        int    `xml:"coupon_count,omitempty" json:"coupon_count,omitempty"`
-	CouponType0        string `xml:"coupon_type_0,omitempty" json:"coupon_type_0,omitempty"`
-	CouponType1        string `xml:"coupon_type_1,omitempty" json:"coupon_type_1,omitempty"`
-	CouponId0          string `xml:"coupon_id_0,omitempty" json:"coupon_id_0,omitempty"`
-	CouponId1          string `xml:"coupon_id_1,omitempty" json:"coupon_id_1,omitempty"`
-	CouponFee0         int    `xml:"coupon_fee_0,omitempty" json:"coupon_fee_0,omitempty"`
-	CouponFee1         int    `xml:"coupon_fee_1,omitempty" json:"coupon_fee_1,omitempty"`
-	TransactionId      string `xml:"transaction_id,omitempty" json:"transaction_id,omitempty"`
-	OutTradeNo         string `xml:"out_trade_no,omitempty" json:"out_trade_no,omitempty"`
-	Attach             string `xml:"attach,omitempty" json:"attach,omitempty"`
-	TimeEnd            string `xml:"time_end,omitempty" json:"time_end,omitempty"`
-}
-
-type WeChatRefundNotifyRequest struct {
+type RefundNotifyRequest 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"`
@@ -298,7 +357,7 @@ type AccessToken struct {
 	Errmsg      string `json:"errmsg,omitempty"`       // 错误信息
 }
 
-type WeChatUserInfo struct {
+type UserInfo struct {
 	Subscribe      int    `json:"subscribe,omitempty"`       // 用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。
 	Openid         string `json:"openid,omitempty"`          // 用户唯一标识
 	Nickname       string `json:"nickname,omitempty"`        // 用户的昵称
@@ -321,7 +380,7 @@ type WeChatUserInfo struct {
 }
 
 // 微信小程序解密后 用户手机号结构体
-type WeChatUserPhone struct {
+type UserPhone struct {
 	PhoneNumber     string         `json:"phoneNumber,omitempty"`
 	PurePhoneNumber string         `json:"purePhoneNumber,omitempty"`
 	CountryCode     string         `json:"countryCode,omitempty"`
@@ -329,7 +388,7 @@ type WeChatUserPhone struct {
 }
 
 // 微信小程序解密后 用户信息结构体
-type WeChatAppletUserInfo struct {
+type AppletUserInfo struct {
 	OpenId    string         `json:"openId,omitempty"`
 	NickName  string         `json:"nickName,omitempty"`
 	Gender    int            `json:"gender,omitempty"`
@@ -360,7 +419,7 @@ type OpenIdByAuthCodeRsp struct {
 }
 
 // App应用微信第三方登录,code换取access_token
-type AppWeChatLoginAccessToken struct {
+type AppLoginAccessToken struct {
 	AccessToken  string `json:"access_token,omitempty"`
 	ExpiresIn    int    `json:"expires_in,omitempty"`
 	Openid       string `json:"openid,omitempty"`
@@ -372,7 +431,7 @@ type AppWeChatLoginAccessToken struct {
 }
 
 // 刷新App应用微信第三方登录后,获取的 access_token
-type RefreshAppWeChatLoginAccessTokenRsp struct {
+type RefreshAppLoginAccessTokenRsp struct {
 	AccessToken  string `json:"access_token,omitempty"`
 	ExpiresIn    int    `json:"expires_in,omitempty"`
 	Openid       string `json:"openid,omitempty"`

+ 31 - 30
wechat_params.go → wechat/param.go

@@ -1,4 +1,4 @@
-package gopay
+package wechat
 
 import (
 	"crypto/hmac"
@@ -13,6 +13,8 @@ import (
 	"hash"
 	"io/ioutil"
 	"strings"
+
+	"github.com/iGoogle-ink/gopay"
 )
 
 type Country int
@@ -20,7 +22,7 @@ type Country int
 // 设置支付国家(默认:中国国内)
 //    根据支付地区情况设置国家
 //    country:<China:中国国内,China2:中国国内(冗灾方案),SoutheastAsia:东南亚,Other:其他国家>
-func (w *WeChatClient) SetCountry(country Country) (client *WeChatClient) {
+func (w *Client) SetCountry(country Country) (client *Client) {
 	w.mu.Lock()
 	switch country {
 	case China:
@@ -42,7 +44,7 @@ func (w *WeChatClient) SetCountry(country Country) (client *WeChatClient) {
 //    certFile:apiclient_cert.pem byte数组
 //    keyFile:apiclient_key.pem byte数组
 //    pkcs12File:apiclient_cert.p12 byte数组
-func (w *WeChatClient) AddCertFileByte(certFile, keyFile, pkcs12File []byte) {
+func (w *Client) AddCertFileByte(certFile, keyFile, pkcs12File []byte) {
 	w.mu.Lock()
 	w.CertFile = certFile
 	w.KeyFile = keyFile
@@ -55,35 +57,35 @@ func (w *WeChatClient) AddCertFileByte(certFile, keyFile, pkcs12File []byte) {
 //    keyFilePath:apiclient_key.pem 路径
 //    pkcs12FilePath:apiclient_cert.p12 路径
 //    返回err
-func (w *WeChatClient) AddCertFilePath(certFilePath, keyFilePath, pkcs12FilePath string) (err error) {
-	var (
-		cert, key, pkcs []byte
-	)
-	if cert, err = ioutil.ReadFile(certFilePath); err != nil {
-		return
+func (w *Client) AddCertFilePath(certFilePath, keyFilePath, pkcs12FilePath string) (err error) {
+	cert, err := ioutil.ReadFile(certFilePath)
+	if err != nil {
+		return err
 	}
-	if key, err = ioutil.ReadFile(keyFilePath); err != nil {
-		return
+	key, err := ioutil.ReadFile(keyFilePath)
+	if err != nil {
+		return err
 	}
-	if pkcs, err = ioutil.ReadFile(pkcs12FilePath); err != nil {
-		return
+	pkcs, err := ioutil.ReadFile(pkcs12FilePath)
+	if err != nil {
+		return err
 	}
 	w.mu.Lock()
 	w.CertFile = cert
 	w.KeyFile = key
 	w.Pkcs12File = pkcs
 	w.mu.Unlock()
-	return
+	return nil
 }
 
-func (w *WeChatClient) addCertConfig(certFilePath, keyFilePath, pkcs12FilePath string) (tlsConfig *tls.Config, err error) {
+func (w *Client) addCertConfig(certFilePath, keyFilePath, pkcs12FilePath string) (tlsConfig *tls.Config, err error) {
 	var (
 		pkcs        []byte
 		certificate tls.Certificate
 		pkcsPool    = x509.NewCertPool()
 	)
 
-	if certFilePath == null && keyFilePath == null && pkcs12FilePath == null {
+	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)
@@ -98,7 +100,7 @@ func (w *WeChatClient) addCertConfig(certFilePath, keyFilePath, pkcs12FilePath s
 		return tlsConfig, nil
 	}
 
-	if certFilePath != null && keyFilePath != null && pkcs12FilePath != null {
+	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())
 		}
@@ -117,7 +119,7 @@ func (w *WeChatClient) addCertConfig(certFilePath, keyFilePath, pkcs12FilePath s
 }
 
 // 获取微信支付正式环境Sign值
-func getWeChatReleaseSign(apiKey string, signType string, bm BodyMap) (sign string) {
+func getReleaseSign(apiKey string, signType string, bm gopay.BodyMap) (sign string) {
 	var h hash.Hash
 	if signType == SignType_HMAC_SHA256 {
 		h = hmac.New(sha256.New, []byte(apiKey))
@@ -125,17 +127,16 @@ func getWeChatReleaseSign(apiKey string, signType string, bm BodyMap) (sign stri
 		h = md5.New()
 	}
 	h.Write([]byte(bm.EncodeWeChatSignParams(apiKey)))
-	sign = strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
-	return
+	return strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
 }
 
 // 获取微信支付沙箱环境Sign值
-func getWeChatSignBoxSign(mchId, apiKey string, bm BodyMap) (sign string, err error) {
+func getSignBoxSign(mchId, apiKey string, bm gopay.BodyMap) (sign string, err error) {
 	var (
 		sandBoxApiKey string
 		h             hash.Hash
 	)
-	if sandBoxApiKey, err = getSanBoxKey(mchId, GetRandomString(32), apiKey, SignType_MD5); err != nil {
+	if sandBoxApiKey, err = getSanBoxKey(mchId, gopay.GetRandomString(32), apiKey, SignType_MD5); err != nil {
 		return
 	}
 	h = md5.New()
@@ -146,11 +147,11 @@ func getWeChatSignBoxSign(mchId, apiKey string, bm BodyMap) (sign string, err er
 
 // 从微信提供的接口获取:SandboxSignKey
 func getSanBoxKey(mchId, nonceStr, apiKey, signType string) (key string, err error) {
-	bm := make(BodyMap)
+	bm := make(gopay.BodyMap)
 	bm.Set("mch_id", mchId)
 	bm.Set("nonce_str", nonceStr)
 	//沙箱环境:获取沙箱环境ApiKey
-	if key, err = getSanBoxSignKey(mchId, nonceStr, getWeChatReleaseSign(apiKey, signType, bm)); err != nil {
+	if key, err = getSanBoxSignKey(mchId, nonceStr, getReleaseSign(apiKey, signType, bm)); err != nil {
 		return
 	}
 	return
@@ -158,27 +159,27 @@ func getSanBoxKey(mchId, nonceStr, apiKey, signType string) (key string, err err
 
 // 从微信提供的接口获取:SandboxSignKey
 func getSanBoxSignKey(mchId, nonceStr, sign string) (key string, err error) {
-	reqs := make(BodyMap)
+	reqs := make(gopay.BodyMap)
 	reqs.Set("mch_id", mchId)
 	reqs.Set("nonce_str", nonceStr)
 	reqs.Set("sign", sign)
 
 	keyResponse := new(getSignKeyResponse)
-	_, errs := NewHttpClient().Type(TypeXML).Post(wxSandboxGetsignkey).SendString(generateXml(reqs)).EndStruct(keyResponse)
+	_, errs := gopay.NewHttpClient().Type(gopay.TypeXML).Post(wxSandboxGetsignkey).SendString(generateXml(reqs)).EndStruct(keyResponse)
 	if len(errs) > 0 {
-		return null, errs[0]
+		return gopay.NULL, errs[0]
 	}
 	if keyResponse.ReturnCode == "FAIL" {
-		return null, errors.New(keyResponse.ReturnMsg)
+		return gopay.NULL, errors.New(keyResponse.ReturnMsg)
 	}
 	return keyResponse.SandboxSignkey, nil
 }
 
 // 生成请求XML的Body体
-func generateXml(bm BodyMap) (reqXml string) {
+func generateXml(bm gopay.BodyMap) (reqXml string) {
 	bs, err := xml.Marshal(bm)
 	if err != nil {
-		return null
+		return gopay.NULL
 	}
 	return string(bs)
 }

+ 47 - 45
wechat_service_api.go → wechat/service_api.go

@@ -1,4 +1,4 @@
-package gopay
+package wechat
 
 import (
 	"crypto/aes"
@@ -18,6 +18,8 @@ import (
 	"net/http"
 	"reflect"
 	"strings"
+
+	"github.com/iGoogle-ink/gopay"
 )
 
 // 获取微信支付所需参数里的Sign值(通过支付参数计算Sign值)
@@ -26,7 +28,7 @@ import (
 //    mchId:商户ID
 //    ApiKey:API秘钥值
 //    返回参数 sign:通过Appid、MchId、ApiKey和BodyMap中的参数计算出的Sign值
-func GetWeChatParamSign(appId, mchId, apiKey string, bm BodyMap) (sign string) {
+func GetParamSign(appId, mchId, apiKey string, bm gopay.BodyMap) (sign string) {
 	bm.Set("appid", appId)
 	bm.Set("mch_id", mchId)
 	var (
@@ -34,7 +36,7 @@ func GetWeChatParamSign(appId, mchId, apiKey string, bm BodyMap) (sign string) {
 		h        hash.Hash
 	)
 	signType = bm.Get("sign_type")
-	if signType == null {
+	if signType == gopay.NULL {
 		bm.Set("sign_type", SignType_MD5)
 	}
 	if signType == SignType_HMAC_SHA256 {
@@ -53,7 +55,7 @@ func GetWeChatParamSign(appId, mchId, apiKey string, bm BodyMap) (sign string) {
 //    mchId:商户ID
 //    ApiKey:API秘钥值
 //    返回参数 sign:通过Appid、MchId、ApiKey和BodyMap中的参数计算出的Sign值
-func GetWeChatSanBoxParamSign(appId, mchId, apiKey string, bm BodyMap) (sign string, err error) {
+func GetSanBoxParamSign(appId, mchId, apiKey string, bm gopay.BodyMap) (sign string, err error) {
 	bm.Set("appid", appId)
 	bm.Set("mch_id", mchId)
 	bm.Set("sign_type", SignType_MD5)
@@ -62,7 +64,7 @@ func GetWeChatSanBoxParamSign(appId, mchId, apiKey string, bm BodyMap) (sign str
 		sandBoxApiKey string
 		hashMd5       hash.Hash
 	)
-	if sandBoxApiKey, err = getSanBoxKey(mchId, GetRandomString(32), apiKey, SignType_MD5); err != nil {
+	if sandBoxApiKey, err = getSanBoxKey(mchId, gopay.GetRandomString(32), apiKey, SignType_MD5); err != nil {
 		return
 	}
 	hashMd5 = md5.New()
@@ -75,14 +77,14 @@ func GetWeChatSanBoxParamSign(appId, mchId, apiKey string, bm BodyMap) (sign str
 //    req:*http.Request
 //    返回参数bm:Notify请求的参数
 //    返回参数err:错误信息
-func ParseWeChatNotifyResultToBodyMap(req *http.Request) (bm BodyMap, err error) {
+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())
 	}
-	bm = make(BodyMap)
+	bm = make(gopay.BodyMap)
 	if err = xml.Unmarshal(bs, &bm); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal:%s", err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
 	}
 	return
 }
@@ -91,8 +93,8 @@ func ParseWeChatNotifyResultToBodyMap(req *http.Request) (bm BodyMap, err error)
 //    req:*http.Request
 //    返回参数notifyReq:Notify请求的参数
 //    返回参数err:错误信息
-func ParseWeChatNotifyResult(req *http.Request) (notifyReq *WeChatNotifyRequest, err error) {
-	notifyReq = new(WeChatNotifyRequest)
+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())
 	}
@@ -103,8 +105,8 @@ func ParseWeChatNotifyResult(req *http.Request) (notifyReq *WeChatNotifyRequest,
 //    req:*http.Request
 //    返回参数notifyReq:Notify请求的参数
 //    返回参数err:错误信息
-func ParseWeChatRefundNotifyResult(req *http.Request) (notifyReq *WeChatRefundNotifyRequest, err error) {
-	notifyReq = new(WeChatRefundNotifyRequest)
+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())
 	}
@@ -112,7 +114,7 @@ func ParseWeChatRefundNotifyResult(req *http.Request) (notifyReq *WeChatRefundNo
 }
 
 // 解密微信退款异步通知的加密数据
-//    reqInfo:gopay.ParseWeChatRefundNotifyResult() 方法获取的加密数据 req_info
+//    reqInfo:gopay.ParseRefundNotifyResult() 方法获取的加密数据 req_info
 //    apiKey:API秘钥值
 //    返回参数refundNotify:RefundNotify请求的加密数据
 //    返回参数err:错误信息
@@ -149,10 +151,10 @@ func DecryptRefundNotifyReqInfo(reqInfo, apiKey string) (refundNotify *RefundNot
 			dst = dst[blockSize:]
 		}
 	}(encryptionB, encryptionB)
-	bs = PKCS7UnPadding(encryptionB)
+	bs = gopay.PKCS7UnPadding(encryptionB)
 	refundNotify = new(RefundNotify)
 	if err = xml.Unmarshal(bs, refundNotify); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal:%s", err.Error())
+		return nil, fmt.Errorf("xml.Unmarshal(%s):%s", string(bs), err.Error())
 	}
 	return
 }
@@ -163,41 +165,41 @@ func DecryptRefundNotifyReqInfo(reqInfo, apiKey string) (refundNotify *RefundNot
 //    bean:微信同步返回的结构体 wxRsp 或 异步通知解析的结构体 notifyReq
 //    返回参数ok:是否验签通过
 //    返回参数err:错误信息
-func VerifyWeChatSign(apiKey, signType string, bean interface{}) (ok bool, err error) {
+func VerifySign(apiKey, signType string, bean interface{}) (ok bool, err error) {
 	if bean == nil {
 		return false, errors.New("bean is nil")
 	}
 	var (
-		bm       BodyMap
+		bm       gopay.BodyMap
 		bs       []byte
 		kind     reflect.Kind
 		bodySign string
 	)
 	kind = reflect.ValueOf(bean).Kind()
 	if kind == reflect.Map {
-		bm = bean.(BodyMap)
+		bm = bean.(gopay.BodyMap)
 		goto Verify
 	}
 	if bs, err = json.Marshal(bean); err != nil {
 		return false, fmt.Errorf("json.Marshal:%s", err.Error())
 	}
-	bm = make(BodyMap)
+	bm = make(gopay.BodyMap)
 	if err = json.Unmarshal(bs, &bm); err != nil {
 		return false, fmt.Errorf("json.Unmarshal:%s", err.Error())
 	}
 Verify:
 	bodySign = bm.Get("sign")
 	bm.Remove("sign")
-	return getWeChatReleaseSign(apiKey, signType, bm) == bodySign, nil
+	return getReleaseSign(apiKey, signType, bm) == bodySign, nil
 }
 
-type WeChatNotifyResponse struct {
+type NotifyResponse struct {
 	ReturnCode string `xml:"return_code"`
 	ReturnMsg  string `xml:"return_msg"`
 }
 
 // 返回数据给微信
-func (w *WeChatNotifyResponse) ToXmlString() (xmlStr string) {
+func (w *NotifyResponse) ToXmlString() (xmlStr string) {
 	var buffer strings.Builder
 	buffer.WriteString("<xml><return_code><![CDATA[")
 	buffer.WriteString(w.ReturnCode)
@@ -322,7 +324,7 @@ func GetAppPaySign(appid, partnerid, noncestr, prepayid, signType, timestamp, ap
 //    sessionKey:会话密钥,通过  gopay.Code2Session() 方法获取到
 //    beanPtr:需要解析到的结构体指针,操作完后,声明的结构体会被赋值
 //    文档:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html
-func DecryptWeChatOpenDataToStruct(encryptedData, iv, sessionKey string, beanPtr interface{}) (err error) {
+func DecryptOpenDataToStruct(encryptedData, iv, sessionKey string, beanPtr interface{}) (err error) {
 	var (
 		cipherText, aesKey, ivKey, plainText []byte
 		block                                cipher.Block
@@ -348,7 +350,7 @@ func DecryptWeChatOpenDataToStruct(encryptedData, iv, sessionKey string, beanPtr
 	plainText = make([]byte, len(cipherText))
 	blockMode.CryptBlocks(plainText, cipherText)
 	if len(plainText) > 0 {
-		plainText = PKCS7UnPadding(plainText)
+		plainText = gopay.PKCS7UnPadding(plainText)
 	}
 	if err = json.Unmarshal(plainText, beanPtr); err != nil {
 		return fmt.Errorf("json.Unmarshal:%s", err.Error())
@@ -361,7 +363,7 @@ func DecryptWeChatOpenDataToStruct(encryptedData, iv, sessionKey string, beanPtr
 //    iv:加密算法的初始向量,小程序获取到
 //    sessionKey:会话密钥,通过  gopay.Code2Session() 方法获取到
 //    文档:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html
-func DecryptWeChatOpenDataToBodyMap(encryptedData, iv, sessionKey string) (bm BodyMap, err error) {
+func DecryptOpenDataToBodyMap(encryptedData, iv, sessionKey string) (bm gopay.BodyMap, err error) {
 	var (
 		cipherText, aesKey, ivKey, plainText []byte
 		block                                cipher.Block
@@ -380,9 +382,9 @@ func DecryptWeChatOpenDataToBodyMap(encryptedData, iv, sessionKey string) (bm Bo
 		plainText = make([]byte, len(cipherText))
 		blockMode.CryptBlocks(plainText, cipherText)
 		if len(plainText) > 0 {
-			plainText = PKCS7UnPadding(plainText)
+			plainText = gopay.PKCS7UnPadding(plainText)
 		}
-		bm = make(BodyMap)
+		bm = make(gopay.BodyMap)
 		if err = json.Unmarshal(plainText, &bm); err != nil {
 			return nil, fmt.Errorf("json.Unmarshal:%s", err.Error())
 		}
@@ -394,11 +396,11 @@ func DecryptWeChatOpenDataToBodyMap(encryptedData, iv, sessionKey string) (bm Bo
 //    appId:应用唯一标识,在微信开放平台提交应用审核通过后获得
 //    appSecret:应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
 //    code:App用户换取access_token的code
-func GetAppWeChatLoginAccessToken(appId, appSecret, code string) (accessToken *AppWeChatLoginAccessToken, err error) {
-	accessToken = new(AppWeChatLoginAccessToken)
+func GetAppLoginAccessToken(appId, appSecret, code string) (accessToken *AppLoginAccessToken, err error) {
+	accessToken = new(AppLoginAccessToken)
 	url := "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret=" + appSecret + "&code=" + code + "&grant_type=authorization_code"
 
-	_, errs := NewHttpClient().Get(url).EndStruct(accessToken)
+	_, errs := gopay.NewHttpClient().Get(url).EndStruct(accessToken)
 	if len(errs) > 0 {
 		return nil, errs[0]
 	}
@@ -409,11 +411,11 @@ func GetAppWeChatLoginAccessToken(appId, appSecret, code string) (accessToken *A
 //    appId:应用唯一标识,在微信开放平台提交应用审核通过后获得
 //    appSecret:应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
 //    code:App用户换取access_token的code
-func RefreshAppWeChatLoginAccessToken(appId, refreshToken string) (accessToken *RefreshAppWeChatLoginAccessTokenRsp, err error) {
-	accessToken = new(RefreshAppWeChatLoginAccessTokenRsp)
+func RefreshAppLoginAccessToken(appId, refreshToken string) (accessToken *RefreshAppLoginAccessTokenRsp, err error) {
+	accessToken = new(RefreshAppLoginAccessTokenRsp)
 	url := "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + appId + "&grant_type=refresh_token&refresh_token=" + refreshToken
 
-	_, errs := NewHttpClient().Get(url).EndStruct(accessToken)
+	_, errs := gopay.NewHttpClient().Get(url).EndStruct(accessToken)
 	if len(errs) > 0 {
 		return nil, errs[0]
 	}
@@ -428,7 +430,7 @@ func RefreshAppWeChatLoginAccessToken(appId, refreshToken string) (accessToken *
 func Code2Session(appId, appSecret, wxCode string) (sessionRsp *Code2SessionRsp, err error) {
 	sessionRsp = new(Code2SessionRsp)
 	url := "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + appSecret + "&js_code=" + wxCode + "&grant_type=authorization_code"
-	_, errs := NewHttpClient().Get(url).EndStruct(sessionRsp)
+	_, errs := gopay.NewHttpClient().Get(url).EndStruct(sessionRsp)
 	if len(errs) > 0 {
 		return nil, errs[0]
 	}
@@ -439,10 +441,10 @@ func Code2Session(appId, appSecret, wxCode string) (sessionRsp *Code2SessionRsp,
 //    appId:APPID
 //    appSecret:AppSecret
 //    获取access_token文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/access-token/auth.getAccessToken.html
-func GetWeChatAppletAccessToken(appId, appSecret string) (accessToken *AccessToken, err error) {
+func GetAppletAccessToken(appId, appSecret string) (accessToken *AccessToken, err error) {
 	accessToken = new(AccessToken)
 	url := "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret
-	_, errs := NewHttpClient().Get(url).EndStruct(accessToken)
+	_, errs := gopay.NewHttpClient().Get(url).EndStruct(accessToken)
 	if len(errs) > 0 {
 		return nil, errs[0]
 	}
@@ -459,18 +461,18 @@ func GetWeChatAppletAccessToken(appId, appSecret string) (accessToken *AccessTok
 func GetOpenIdByAuthCode(appId, mchId, apiKey, authCode, nonceStr string) (openIdRsp *OpenIdByAuthCodeRsp, err error) {
 	var (
 		url string
-		bm  BodyMap
+		bm  gopay.BodyMap
 	)
 	url = "https://api.mch.weixin.qq.com/tools/authcodetoopenid"
-	bm = make(BodyMap)
+	bm = make(gopay.BodyMap)
 	bm.Set("appid", appId)
 	bm.Set("mch_id", mchId)
 	bm.Set("auth_code", authCode)
 	bm.Set("nonce_str", nonceStr)
-	bm.Set("sign", getWeChatReleaseSign(apiKey, SignType_MD5, bm))
+	bm.Set("sign", getReleaseSign(apiKey, SignType_MD5, bm))
 
 	openIdRsp = new(OpenIdByAuthCodeRsp)
-	_, errs := NewHttpClient().Type(TypeXML).Post(url).SendString(generateXml(bm)).EndStruct(openIdRsp)
+	_, errs := gopay.NewHttpClient().Type(gopay.TypeXML).Post(url).SendString(generateXml(bm)).EndStruct(openIdRsp)
 	if len(errs) > 0 {
 		return nil, errs[0]
 	}
@@ -482,10 +484,10 @@ func GetOpenIdByAuthCode(appId, mchId, apiKey, authCode, nonceStr string) (openI
 //    openId:用户的OpenID
 //    transactionId:微信支付订单号
 //    文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/user-info/auth.getPaidUnionId.html
-func GetWeChatAppletPaidUnionId(accessToken, openId, transactionId string) (unionId *PaidUnionId, err error) {
+func GetAppletPaidUnionId(accessToken, openId, transactionId string) (unionId *PaidUnionId, err error) {
 	unionId = new(PaidUnionId)
 	url := "https://api.weixin.qq.com/wxa/getpaidunionid?access_token=" + accessToken + "&openid=" + openId + "&transaction_id=" + transactionId
-	_, errs := NewHttpClient().Get(url).EndStruct(unionId)
+	_, errs := gopay.NewHttpClient().Get(url).EndStruct(unionId)
 	if len(errs) > 0 {
 		return nil, errs[0]
 	}
@@ -497,13 +499,13 @@ func GetWeChatAppletPaidUnionId(accessToken, openId, transactionId string) (unio
 //    openId:用户的OpenID
 //    lang:默认为 zh_CN ,可选填 zh_CN 简体,zh_TW 繁体,en 英语
 //    获取用户基本信息(UnionID机制)文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140839
-func GetWeChatUserInfo(accessToken, openId string, lang ...string) (userInfo *WeChatUserInfo, err error) {
-	userInfo = new(WeChatUserInfo)
+func GetUserInfo(accessToken, openId string, lang ...string) (userInfo *UserInfo, err error) {
+	userInfo = new(UserInfo)
 	url := "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openId + "&lang=zh_CN"
 	if len(lang) > 0 {
 		url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openId + "&lang=" + lang[0]
 	}
-	_, errs := NewHttpClient().Get(url).EndStruct(userInfo)
+	_, errs := gopay.NewHttpClient().Get(url).EndStruct(userInfo)
 	if len(errs) > 0 {
 		return nil, errs[0]
 	}

+ 0 - 334
wechat_client.go

@@ -1,334 +0,0 @@
-package gopay
-
-import (
-	"crypto/tls"
-	"encoding/xml"
-	"errors"
-	"fmt"
-	"strings"
-	"sync"
-)
-
-type WeChatClient struct {
-	AppId      string
-	MchId      string
-	ApiKey     string
-	BaseURL    string
-	CertFile   []byte
-	KeyFile    []byte
-	Pkcs12File []byte
-	IsProd     bool
-	mu         sync.RWMutex
-}
-
-// 初始化微信客户端
-//    appId:应用ID
-//    mchId:商户ID
-//    ApiKey:API秘钥值
-//    IsProd:是否是正式环境
-func NewWeChatClient(appId, mchId, apiKey string, isProd bool) (client *WeChatClient) {
-	return &WeChatClient{
-		AppId:  appId,
-		MchId:  mchId,
-		ApiKey: apiKey,
-		IsProd: isProd}
-}
-
-// 提交付款码支付
-//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1
-func (w *WeChatClient) Micropay(body BodyMap) (wxRsp *WeChatMicropayResponse, err error) {
-	var bs []byte
-	if w.IsProd {
-		bs, err = w.doWeChat(body, wxMicropay)
-	} else {
-		bs, err = w.doWeChat(body, wxSandboxMicropay)
-	}
-	if err != nil {
-		return
-	}
-	wxRsp = new(WeChatMicropayResponse)
-	if err = xml.Unmarshal(bs, wxRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal:%s", err.Error())
-	}
-	return
-}
-
-// 统一下单
-//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
-func (w *WeChatClient) UnifiedOrder(body BodyMap) (wxRsp *WeChatUnifiedOrderResponse, err error) {
-	var bs []byte
-	if w.IsProd {
-		bs, err = w.doWeChat(body, wxUnifiedorder)
-	} else {
-		body.Set("total_fee", 101)
-		bs, err = w.doWeChat(body, wxSandboxUnifiedorder)
-	}
-	if err != nil {
-		return
-	}
-	wxRsp = new(WeChatUnifiedOrderResponse)
-	if err = xml.Unmarshal(bs, wxRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal:%s", err.Error())
-	}
-	return
-}
-
-// 查询订单
-//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2
-func (w *WeChatClient) QueryOrder(body BodyMap) (wxRsp *WeChatQueryOrderResponse, err error) {
-	var bs []byte
-	if w.IsProd {
-		bs, err = w.doWeChat(body, wxOrderquery)
-	} else {
-		bs, err = w.doWeChat(body, wxSandboxOrderquery)
-	}
-	if err != nil {
-		return
-	}
-	wxRsp = new(WeChatQueryOrderResponse)
-	if err = xml.Unmarshal(bs, wxRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal:%s", err.Error())
-	}
-	return
-}
-
-// 关闭订单
-//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3
-func (w *WeChatClient) CloseOrder(body BodyMap) (wxRsp *WeChatCloseOrderResponse, err error) {
-	var bs []byte
-	if w.IsProd {
-		bs, err = w.doWeChat(body, wxCloseorder)
-	} else {
-		bs, err = w.doWeChat(body, wxSandboxCloseorder)
-	}
-	if err != nil {
-		return
-	}
-	wxRsp = new(WeChatCloseOrderResponse)
-	if err = xml.Unmarshal(bs, wxRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal:%s", err.Error())
-	}
-	return
-}
-
-// 撤销订单
-//    注意:如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",如方法需单独使用证书,则传证书Path
-//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_11&index=3
-func (w *WeChatClient) Reverse(body BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp *WeChatReverseResponse, err error) {
-	var (
-		bs        []byte
-		tlsConfig *tls.Config
-	)
-	if w.IsProd {
-		if tlsConfig, err = w.addCertConfig(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
-			return nil, err
-		}
-		bs, err = w.doWeChat(body, wxReverse, tlsConfig)
-	} else {
-		bs, err = w.doWeChat(body, wxSandboxReverse)
-	}
-	if err != nil {
-		return
-	}
-	wxRsp = new(WeChatReverseResponse)
-	if err = xml.Unmarshal(bs, wxRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal:%s", err.Error())
-	}
-	return
-}
-
-// 申请退款
-//    注意:如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",如方法需单独使用证书,则传证书Path
-//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
-func (w *WeChatClient) Refund(body BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp *WeChatRefundResponse, err error) {
-	var (
-		bs        []byte
-		tlsConfig *tls.Config
-	)
-	if w.IsProd {
-		if tlsConfig, err = w.addCertConfig(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
-			return nil, err
-		}
-		bs, err = w.doWeChat(body, wxRefund, tlsConfig)
-	} else {
-		bs, err = w.doWeChat(body, wxSandboxRefund)
-	}
-	if err != nil {
-		return
-	}
-	wxRsp = new(WeChatRefundResponse)
-	if err = xml.Unmarshal(bs, wxRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal:%s", err.Error())
-	}
-	return
-}
-
-// 查询退款
-//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
-func (w *WeChatClient) QueryRefund(body BodyMap) (wxRsp *WeChatQueryRefundResponse, err error) {
-	var bs []byte
-	if w.IsProd {
-		bs, err = w.doWeChat(body, wxRefundquery)
-	} else {
-		bs, err = w.doWeChat(body, wxSandboxRefundquery)
-	}
-	if err != nil {
-		return
-	}
-	wxRsp = new(WeChatQueryRefundResponse)
-	if err = xml.Unmarshal(bs, wxRsp); err != nil {
-		return nil, fmt.Errorf("xml.Unmarshal:%s", err.Error())
-	}
-	return
-}
-
-// 下载对账单
-//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6
-func (w *WeChatClient) DownloadBill(body BodyMap) (wxRsp string, err error) {
-	var bs []byte
-	if w.IsProd {
-		bs, err = w.doWeChat(body, wxDownloadbill)
-	} else {
-		bs, err = w.doWeChat(body, wxSandboxDownloadbill)
-	}
-	if err != nil {
-		return
-	}
-	wxRsp = string(bs)
-	return
-}
-
-// 下载资金账单
-//    注意:如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",如方法需单独使用证书,则传证书Path
-//    貌似不支持沙箱环境,因为沙箱环境默认需要用MD5签名,但是此接口仅支持HMAC-SHA256签名
-//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_18&index=7
-func (w *WeChatClient) DownloadFundFlow(body BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp string, err error) {
-	var (
-		bs        []byte
-		tlsConfig *tls.Config
-	)
-	if w.IsProd {
-		if tlsConfig, err = w.addCertConfig(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
-			return null, err
-		}
-		bs, err = w.doWeChat(body, wxDownloadfundflow, tlsConfig)
-	} else {
-		bs, err = w.doWeChat(body, wxSandboxDownloadfundflow)
-	}
-	if err != nil {
-		return
-	}
-	wxRsp = string(bs)
-	return
-}
-
-// 拉取订单评价数据
-//    注意:如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",如方法需单独使用证书,则传证书Path
-//    貌似不支持沙箱环境,因为沙箱环境默认需要用MD5签名,但是此接口仅支持HMAC-SHA256签名
-//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_17&index=11
-func (w *WeChatClient) BatchQueryComment(body BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp string, err error) {
-	var (
-		bs        []byte
-		tlsConfig *tls.Config
-	)
-	if w.IsProd {
-		body.Set("sign_type", SignType_HMAC_SHA256)
-		if tlsConfig, err = w.addCertConfig(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
-			return null, err
-		}
-		bs, err = w.doWeChat(body, wxBatchquerycomment, tlsConfig)
-	} else {
-		bs, err = w.doWeChat(body, wxSandboxBatchquerycomment)
-	}
-	if err != nil {
-		return
-	}
-	wxRsp = string(bs)
-	return
-}
-
-// 企业向微信用户个人付款
-//    注意:如已使用client.AddCertFilePath()或client.AddCertFileByte()添加过证书,参数certFilePath、keyFilePath、pkcs12FilePath全传空字符串 "",如方法需单独使用证书,则传证书Path
-//    注意:此方法未支持沙箱环境,默认正式环境,转账请慎重
-//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1
-func (w *WeChatClient) Transfer(body BodyMap, certFilePath, keyFilePath, pkcs12FilePath string) (wxRsp *WeChatTransfersResponse, err error) {
-	body.Set("mch_appid", w.AppId)
-	body.Set("mchid", w.MchId)
-	var (
-		tlsConfig *tls.Config
-		url       = wxBaseUrlCh + wxTransfers
-	)
-	if tlsConfig, err = w.addCertConfig(certFilePath, keyFilePath, pkcs12FilePath); err != nil {
-		return nil, err
-	}
-	body.Set("sign", getWeChatReleaseSign(w.ApiKey, SignType_MD5, body))
-
-	httpClient := NewHttpClient().SetTLSConfig(tlsConfig).Type(TypeXML)
-	if w.BaseURL != null {
-		w.mu.RLock()
-		url = w.BaseURL + wxTransfers
-		w.mu.RUnlock()
-	}
-	wxRsp = new(WeChatTransfersResponse)
-	res, errs := httpClient.Post(url).SendString(generateXml(body)).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
-}
-
-// 公众号纯签约(未完成)
-//    文档地址:https://pay.weixin.qq.com/wiki/doc/api/pap.php?chapter=18_1&index=1
-func (w *WeChatClient) EntrustPublic(body BodyMap) (bs []byte, err error) {
-	bs, err = w.doWeChat(body, wxEntrustPublic)
-
-	return nil, nil
-}
-
-// 向微信发送请求
-func (w *WeChatClient) doWeChat(body BodyMap, path string, tlsConfig ...*tls.Config) (bs []byte, err error) {
-	body.Set("appid", w.AppId)
-	body.Set("mch_id", w.MchId)
-	var (
-		url = wxBaseUrlCh + path
-	)
-	if body.Get("sign") == null {
-		var sign string
-		if !w.IsProd {
-			body.Set("sign_type", SignType_MD5)
-			sign, err = getWeChatSignBoxSign(w.MchId, w.ApiKey, body)
-			if err != nil {
-				return nil, err
-			}
-		} else {
-			sign = getWeChatReleaseSign(w.ApiKey, body.Get("sign_type"), body)
-		}
-		body.Set("sign", sign)
-	}
-
-	httpClient := NewHttpClient()
-	if w.IsProd && tlsConfig != nil {
-		httpClient.SetTLSConfig(tlsConfig[0])
-	}
-
-	if w.BaseURL != null {
-		w.mu.RLock()
-		url = w.BaseURL + path
-		w.mu.RUnlock()
-	}
-
-	res, bs, errs := httpClient.Type(TypeXML).Post(url).SendString(generateXml(body)).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") {
-		return nil, errors.New(string(bs))
-	}
-	return bs, nil
-}

+ 0 - 171
wechat_client_test.go

@@ -1,171 +0,0 @@
-package gopay
-
-import (
-	"encoding/json"
-	"fmt"
-	"testing"
-)
-
-type Student struct {
-	Name  string `json:"name,omitempty"`
-	Age   int    `json:"age,omitempty"`
-	Sign  string `json:"sign,omitempty"`
-	Phone string `json:"phone,omitempty"`
-}
-
-func TestBodyMap_MarshalXML(t *testing.T) {
-
-	student := new(Student)
-	student.Name = "Jerry"
-	student.Age = 28
-	student.Phone = "18017448610"
-
-	marshal, err := json.Marshal(student)
-	if err != nil {
-		fmt.Println("err:", err)
-	}
-
-	fmt.Println("marshal:", string(marshal))
-
-	maps := make(map[string]interface{})
-
-	err = json.Unmarshal(marshal, &maps)
-	if err != nil {
-		fmt.Println("err2:", err)
-	}
-	fmt.Println("maps:", maps)
-
-	//maps := make(BodyMap)
-	//maps.Set("name", "jerry")
-	//maps.Set("age", 28)
-	//maps.Set("phone", "13212345678")
-	//
-	//bytes, err := xml.Marshal(&maps)
-	//if err != nil {
-	//	fmt.Println("err:", err)
-	//}
-	//fmt.Println("ssss:", string(bytes))
-}
-
-func TestVerifyWeChatResponseSign(t *testing.T) {
-	student := new(Student)
-	student.Name = "Jerry"
-	student.Age = 1
-	student.Sign = "544E55ED43B787B945FF0BF8344A4D69"
-	student.Phone = "18017448610"
-
-	maps := make(BodyMap)
-	maps["name"] = "Jerry"
-	maps["age"] = 1
-	maps["sign"] = "544E55ED43B787B945FF0BF8344A4D69"
-	maps["phone"] = "18017448610"
-
-	ok, err := VerifyWeChatSign("ABCDEFG", "MD5", student)
-	if err != nil {
-		fmt.Println("errrrr:", err)
-		return
-	}
-	fmt.Println("ok:", ok)
-}
-
-func TestDecryptWeChatOpenDataToStruct(t *testing.T) {
-	data := "Kf3TdPbzEmhWMuPKtlKxIWDkijhn402w1bxoHL4kLdcKr6jT1jNcIhvDJfjXmJcgDWLjmBiIGJ5acUuSvxLws3WgAkERmtTuiCG10CKLsJiR+AXVk7B2TUQzsq88YVilDz/YAN3647REE7glGmeBPfvUmdbfDzhL9BzvEiuRhABuCYyTMz4iaM8hFjbLB1caaeoOlykYAFMWC5pZi9P8uw=="
-	iv := "Cds8j3VYoGvnTp1BrjXdJg=="
-	session := "lyY4HPQbaOYzZdG+JcYK9w=="
-	phone := new(WeChatUserPhone)
-	//解密开放数据
-	//    encryptedData:包括敏感数据在内的完整用户信息的加密数据
-	//    iv:加密算法的初始向量
-	//    sessionKey:会话密钥
-	//    beanPtr:需要解析到的结构体指针
-	err := DecryptWeChatOpenDataToStruct(data, iv, session, phone)
-	if err != nil {
-		fmt.Println("err:", err)
-		return
-	}
-	fmt.Println("PhoneNumber:", phone.PhoneNumber)
-	fmt.Println("PurePhoneNumber:", phone.PurePhoneNumber)
-	fmt.Println("CountryCode:", phone.CountryCode)
-	fmt.Println("Watermark:", phone.Watermark)
-
-	sessionKey := "tiihtNczf5v6AKRyjwEUhQ=="
-	encryptedData := "CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZMQmRzooG2xrDcvSnxIMXFufNstNGTyaGS9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+3hVbJSRgv+4lGOETKUQz6OYStslQ142dNCuabNPGBzlooOmB231qMM85d2/fV6ChevvXvQP8Hkue1poOFtnEtpyxVLW1zAo6/1Xx1COxFvrc2d7UL/lmHInNlxuacJXwu0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn/Hz7saL8xz+W//FRAUid1OksQaQx4CMs8LOddcQhULW4ucetDf96JcR3g0gfRK4PC7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns/8wR2SiRS7MNACwTyrGvt9ts8p12PKFdlqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYVoKlaRv85IfVunYzO0IKXsyl7JCUjCpoG20f0a04COwfneQAGGwd5oa+T8yO5hzuyDb/XcxxmK01EpqOyuxINew=="
-	iv2 := "r7BXXKkLb8qrSNn05n0qiA=="
-
-	//微信小程序 用户信息
-	userInfo := new(WeChatAppletUserInfo)
-
-	err = DecryptWeChatOpenDataToStruct(encryptedData, iv2, sessionKey, userInfo)
-	if err != nil {
-		fmt.Println("err:", err)
-		return
-	}
-	fmt.Println("NickName:", userInfo.NickName)
-	fmt.Println("AvatarUrl:", userInfo.AvatarUrl)
-	fmt.Println("Country:", userInfo.Country)
-	fmt.Println("Province:", userInfo.Province)
-	fmt.Println("City:", userInfo.City)
-	fmt.Println("Gender:", userInfo.Gender)
-	fmt.Println("OpenId:", userInfo.OpenId)
-	fmt.Println("UnionId:", userInfo.UnionId)
-	fmt.Println("Watermark:", userInfo.Watermark)
-}
-
-func TestDecryptWeChatOpenDataToBodyMap(t *testing.T) {
-	data := "Kf3TdPbzEmhWMuPKtlKxIWDkijhn402w1bxoHL4kLdcKr6jT1jNcIhvDJfjXmJcgDWLjmBiIGJ5acUuSvxLws3WgAkERmtTuiCG10CKLsJiR+AXVk7B2TUQzsq88YVilDz/YAN3647REE7glGmeBPfvUmdbfDzhL9BzvEiuRhABuCYyTMz4iaM8hFjbLB1caaeoOlykYAFMWC5pZi9P8uw=="
-	iv := "Cds8j3VYoGvnTp1BrjXdJg=="
-	session := "lyY4HPQbaOYzZdG+JcYK9w=="
-
-	//解密开放数据
-	//    encryptedData:包括敏感数据在内的完整用户信息的加密数据
-	//    iv:加密算法的初始向量
-	//    sessionKey:会话密钥
-	bm, err := DecryptWeChatOpenDataToBodyMap(data, iv, session)
-	if err != nil {
-		fmt.Println("err:", err)
-		return
-	}
-	fmt.Println("WeChatUserPhone:", bm)
-}
-
-func TestDecryptRefundNotifyReqInfo(t *testing.T) {
-	key := "ziR0QKsTUfMOuochC9RfCdmfHECorQAP"
-	data := "YYwp8C48th0wnQzTqeI+41pflB26v+smFj9z6h9RPBgxTyZyxc+4YNEz7QEgZNWj/6rIb2MfyWMZmCc41CfjKSssoSZPXxOhUayb6KvNSZ1p6frOX1PDWzhyruXK7ouNND+gDsG4yZ0XXzsL4/pYNwLLba/71QrnkJ/BHcByk4EXnglju5DLup9pJQSnTxjomI9Rxu57m9jg5lLQFxMWXyeASZJNvof0ulnHlWJswS4OxKOkmW7VEyKyLGV6npoOm03Qsx2wkRxLsSa9gPpg4hdaReeUqh1FMbm7aWjyrVYT/MEZWg98p4GomEIYvz34XfDncTezX4bf/ZiSLXt79aE1/YTZrYfymXeCrGjlbe0rg/T2ezJHAC870u2vsVbY1/KcE2A443N+DEnAziXlBQ1AeWq3Rqk/O6/TMM0lomzgctAOiAMg+bh5+Gu1ubA9O3E+vehULydD5qx2o6i3+qA9ORbH415NyRrQdeFq5vmCiRikp5xYptWiGZA0tkoaLKMPQ4ndE5gWHqiBbGPfULZWokI+QjjhhBmwgbd6J0VqpRorwOuzC/BHdkP72DCdNcm7IDUpggnzBIy0+seWIkcHEryKjge3YDHpJeQCqrAH0CgxXHDt1xtbQbST1VqFyuhPhUjDXMXrknrGPN/oE1t0rLRq+78cI+k8xe5E6seeUXQsEe8r3358mpcDYSmXWSXVZxK6er9EF98APqHwcndyEJD2YyCh/mMVhERuX+7kjlRXSiNUWa/Cv/XAKFQuvUYA5ea2eYWtPRHa4DpyuF1SNsaqVKfgqKXZrJHfAgslVpSVqUpX4zkKszHF4kwMZO3M7J1P94Mxa7Tm9mTOJePOoHPXeEB+m9rX6pSfoi3mJDQ5inJ+Vc4gOkg/Wd/lqiy6TTyP/dHDN6/v+AuJx5AXBo/2NDD3fWhHjkqEKIuARr2ClZt9ZRQO4HkXdZo7CN06sGCHk48Tg8PmxnxKcMZm7Aoquv5yMIM2gWSWIRJhwJ8cUpafIHc+GesDlbF6Zbt+/KXkafJAQq2RklEN+WvZ/zFz113EPgWPjp16TwBoziq96MMekvWKY/vdhjol8VFtGH9F61Oy1Xwf6DJtPw=="
-	refundNotify, err := DecryptRefundNotifyReqInfo(data, key)
-	if err != nil {
-		fmt.Println("err:", err)
-		return
-	}
-	fmt.Println("refundNotify:", *refundNotify)
-}
-
-func TestBodyMap_Set_Get(t *testing.T) {
-	bm := make(BodyMap)
-	sceneInfo := make(map[string]map[string]string)
-	h5Info := make(map[string]string)
-	h5Info["type"] = "Wap"
-	h5Info["wap_url"] = "http://www.gopay.ink"
-	h5Info["wap_name"] = "H5测试支付"
-	sceneInfo["h5_info"] = h5Info
-	bm.Set("scene_info", sceneInfo)
-	fmt.Println("Get1:", bm.Get("scene_info"))
-
-	bm.Set("student", &Student{
-		Name:  "Jerry",
-		Age:   26,
-		Sign:  "123465",
-		Phone: "123654987",
-	})
-
-	fmt.Println("Get2:", bm.Get("student"))
-
-}
-
-func TestGetWeChatAppletAccessToken(t *testing.T) {
-	token, err := GetWeChatAppletAccessToken("wxdaa2ab9ef87b5497", "AppSecret")
-	if err != nil {
-		fmt.Println(err)
-		return
-	}
-	fmt.Println("token:", token)
-}