alipay_client.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. package gopay
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "log"
  7. "time"
  8. )
  9. type aliPayClient struct {
  10. AppId string
  11. privateKey string
  12. ReturnUrl string
  13. NotifyUrl string
  14. Charset string
  15. SignType string
  16. AppAuthToken string
  17. isProd bool
  18. }
  19. //初始化支付宝客户端
  20. // appId:应用ID
  21. // privateKey:应用私钥
  22. // isProd:是否是正式环境
  23. func NewAliPayClient(appId, privateKey string, isProd bool) (client *aliPayClient) {
  24. client = new(aliPayClient)
  25. client.AppId = appId
  26. client.privateKey = privateKey
  27. client.isProd = isProd
  28. return client
  29. }
  30. //alipay.trade.fastpay.refund.query(统一收单交易退款查询)
  31. func (this *aliPayClient) AliPayTradeFastPayRefundQuery(body BodyMap) {
  32. }
  33. //alipay.trade.order.settle(统一收单交易结算接口)
  34. func (this *aliPayClient) AliPayTradeOrderSettle(body BodyMap) {
  35. }
  36. //alipay.trade.create(统一收单交易创建接口)
  37. func (this *aliPayClient) AliPayTradeCreate(body BodyMap) (aliRsp *AliPayTradeCreateResponse, err error) {
  38. var bytes []byte
  39. trade1 := body.Get("out_trade_no")
  40. trade2 := body.Get("buyer_id")
  41. if trade1 == null && trade2 == null {
  42. return nil, errors.New("out_trade_no and buyer_id are not allowed to be null at the same time")
  43. }
  44. //===============product_code值===================
  45. bytes, err = this.doAliPay(body, "alipay.trade.create")
  46. if err != nil {
  47. return nil, err
  48. }
  49. //convertBytes, _ := simplifiedchinese.GBK.NewDecoder().Bytes(bytes)
  50. //log.Println("AliPayTradeCreate::::", string(convertBytes))
  51. aliRsp = new(AliPayTradeCreateResponse)
  52. err = json.Unmarshal(bytes, aliRsp)
  53. if err != nil {
  54. return nil, err
  55. }
  56. if aliRsp.AliPayTradeCreateResponse.Code != "10000" {
  57. info := aliRsp.AliPayTradeCreateResponse
  58. return nil, fmt.Errorf("code:%v,msg:%v,sub_code:%v,sub_msg:%v.", info.Code, info.Msg, info.SubCode, info.SubMsg)
  59. }
  60. return aliRsp, nil
  61. }
  62. //alipay.trade.close(统一收单交易关闭接口)
  63. func (this *aliPayClient) AliPayTradeClose(body BodyMap) (aliRsp *AliPayTradeCloseResponse, err error) {
  64. var bytes []byte
  65. trade1 := body.Get("out_trade_no")
  66. trade2 := body.Get("trade_no")
  67. if trade1 == null && trade2 == null {
  68. return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
  69. }
  70. bytes, err = this.doAliPay(body, "alipay.trade.close")
  71. if err != nil {
  72. return nil, err
  73. }
  74. //convertBytes, _ := simplifiedchinese.GBK.NewDecoder().Bytes(bytes)
  75. //log.Println("AliPayTradeClose::::", string(convertBytes))
  76. aliRsp = new(AliPayTradeCloseResponse)
  77. err = json.Unmarshal(bytes, aliRsp)
  78. if err != nil {
  79. return nil, err
  80. }
  81. if aliRsp.AlipayTradeCloseResponse.Code != "10000" {
  82. info := aliRsp.AlipayTradeCloseResponse
  83. return nil, fmt.Errorf("code:%v,msg:%v,sub_code:%v,sub_msg:%v.", info.Code, info.Msg, info.SubCode, info.SubMsg)
  84. }
  85. return aliRsp, nil
  86. }
  87. //alipay.trade.cancel(统一收单交易撤销接口)
  88. func (this *aliPayClient) AliPayTradeCancel(body BodyMap) (aliRsp *AliPayTradeCancelResponse, err error) {
  89. var bytes []byte
  90. trade1 := body.Get("out_trade_no")
  91. trade2 := body.Get("trade_no")
  92. if trade1 == null && trade2 == null {
  93. return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
  94. }
  95. bytes, err = this.doAliPay(body, "alipay.trade.cancel")
  96. if err != nil {
  97. return nil, err
  98. }
  99. //convertBytes, _ := simplifiedchinese.GBK.NewDecoder().Bytes(bytes)
  100. //log.Println("AliPayTradeCancel::::", string(convertBytes))
  101. aliRsp = new(AliPayTradeCancelResponse)
  102. err = json.Unmarshal(bytes, aliRsp)
  103. if err != nil {
  104. return nil, err
  105. }
  106. if aliRsp.AliPayTradeCancelResponse.Code != "10000" {
  107. info := aliRsp.AliPayTradeCancelResponse
  108. return nil, fmt.Errorf("code:%v,msg:%v,sub_code:%v,sub_msg:%v.", info.Code, info.Msg, info.SubCode, info.SubMsg)
  109. }
  110. return aliRsp, nil
  111. }
  112. //alipay.trade.refund(统一收单交易退款接口)
  113. func (this *aliPayClient) AliPayTradeRefund(body BodyMap) {
  114. }
  115. //alipay.trade.precreate(统一收单线下交易预创建)
  116. func (this *aliPayClient) AliPayTradePrecreate(body BodyMap) {
  117. }
  118. //alipay.trade.pay(统一收单交易支付接口)
  119. func (this *aliPayClient) AliPayTradePay(body BodyMap) (aliRsp *AliPayTradePayResponse, err error) {
  120. var bytes []byte
  121. trade := body.Get("out_trade_no")
  122. if trade == null {
  123. return nil, errors.New("out_trade_no is not allowed to be null")
  124. }
  125. //===============product_code值===================
  126. //body.Set("product_code", "FACE_TO_FACE_PAYMENT")
  127. bytes, err = this.doAliPay(body, "alipay.trade.pay")
  128. if err != nil {
  129. return nil, err
  130. }
  131. //convertBytes, _ := simplifiedchinese.GBK.NewDecoder().Bytes(bytes)
  132. //log.Println("convertBytes::::", string(convertBytes))
  133. aliRsp = new(AliPayTradePayResponse)
  134. err = json.Unmarshal(bytes, aliRsp)
  135. if err != nil {
  136. return nil, err
  137. }
  138. if aliRsp.AlipayTradePayResponse.Code != "10000" {
  139. info := aliRsp.AlipayTradePayResponse
  140. return nil, fmt.Errorf("code:%v,msg:%v,sub_code:%v,sub_msg:%v.", info.Code, info.Msg, info.SubCode, info.SubMsg)
  141. }
  142. return aliRsp, nil
  143. }
  144. //alipay.trade.query(统一收单线下交易查询)
  145. func (this *aliPayClient) AliPayTradeQuery(body BodyMap) (aliRsp *AliPayTradeQueryResponse, err error) {
  146. var bytes []byte
  147. trade1 := body.Get("out_trade_no")
  148. trade2 := body.Get("trade_no")
  149. if trade1 == null && trade2 == null {
  150. return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
  151. }
  152. bytes, err = this.doAliPay(body, "alipay.trade.query")
  153. if err != nil {
  154. return nil, err
  155. }
  156. //convertBytes, _ := simplifiedchinese.GBK.NewDecoder().Bytes(bytes)
  157. //log.Println("AliPayTradeQuery::::", string(convertBytes))
  158. aliRsp = new(AliPayTradeQueryResponse)
  159. err = json.Unmarshal(bytes, aliRsp)
  160. if err != nil {
  161. return nil, err
  162. }
  163. if aliRsp.AlipayTradeQueryResponse.Code != "10000" {
  164. info := aliRsp.AlipayTradeQueryResponse
  165. return nil, fmt.Errorf("code:%v,msg:%v,sub_code:%v,sub_msg:%v.", info.Code, info.Msg, info.SubCode, info.SubMsg)
  166. }
  167. return aliRsp, nil
  168. }
  169. //alipay.trade.app.pay(app支付接口2.0)
  170. func (this *aliPayClient) AliPayTradeAppPay(body BodyMap) (payParam string, err error) {
  171. var bytes []byte
  172. trade := body.Get("out_trade_no")
  173. if trade == null {
  174. return null, errors.New("out_trade_no is not allowed to be null")
  175. }
  176. //===============product_code值===================
  177. //body.Set("product_code", "QUICK_MSECURITY_PAY")
  178. bytes, err = this.doAliPay(body, "alipay.trade.app.pay")
  179. if err != nil {
  180. return null, err
  181. }
  182. payParam = string(bytes)
  183. return payParam, nil
  184. }
  185. //alipay.trade.wap.pay(手机网站支付接口2.0)
  186. func (this *aliPayClient) AliPayTradeWapPay(body BodyMap) (payUrl string, err error) {
  187. var bytes []byte
  188. trade := body.Get("out_trade_no")
  189. if trade == null {
  190. return null, errors.New("out_trade_no is not allowed to be null")
  191. }
  192. //===============product_code值===================
  193. body.Set("product_code", "QUICK_WAP_WAY")
  194. bytes, err = this.doAliPay(body, "alipay.trade.wap.pay")
  195. if err != nil {
  196. //log.Println("err::", err.Error())
  197. return null, err
  198. }
  199. payUrl = string(bytes)
  200. //fmt.Println("URL::", payUrl)
  201. if payUrl == zfb_sanbox_base_url || payUrl == zfb_base_url {
  202. return null, errors.New("请求失败,请查看文档并检查参数")
  203. }
  204. return payUrl, nil
  205. }
  206. //alipay.trade.page.pay(统一收单下单并支付页面接口)
  207. func (this *aliPayClient) AliPayTradePagePay(body BodyMap) (payUrl string, err error) {
  208. var bytes []byte
  209. trade := body.Get("out_trade_no")
  210. if trade == null {
  211. return null, errors.New("out_trade_no is not allowed to be null")
  212. }
  213. //===============product_code值===================
  214. body.Set("product_code", "FAST_INSTANT_TRADE_PAY")
  215. bytes, err = this.doAliPay(body, "alipay.trade.page.pay")
  216. if err != nil {
  217. //log.Println("err::", err.Error())
  218. return null, err
  219. }
  220. payUrl = string(bytes)
  221. if payUrl == zfb_sanbox_base_url || payUrl == zfb_base_url {
  222. return null, errors.New("请求失败,请查看文档并检查参数")
  223. }
  224. return payUrl, nil
  225. }
  226. //alipay.trade.orderinfo.sync(支付宝订单信息同步接口)
  227. func (this *aliPayClient) AliPayTradeOrderinfoSync(body BodyMap) {
  228. }
  229. //zhima.credit.score.brief.get(芝麻分普惠版)
  230. func (this *aliPayClient) ZhimaCreditScoreBriefGet(body BodyMap) {
  231. }
  232. //zhima.credit.score.get(芝麻分)
  233. func (this *aliPayClient) ZhimaCreditScoreGet(body BodyMap) {
  234. }
  235. //向支付宝发送请求
  236. func (this *aliPayClient) doAliPay(body BodyMap, method string) (bytes []byte, err error) {
  237. //===============转换body参数===================
  238. bodyStr, err := json.Marshal(body)
  239. if err != nil {
  240. log.Println("json.Marshal:", err)
  241. return nil, err
  242. }
  243. //fmt.Println(string(bodyStr))
  244. //===============生成参数===================
  245. pubBody := make(BodyMap)
  246. pubBody.Set("app_id", this.AppId)
  247. pubBody.Set("method", method)
  248. pubBody.Set("format", "JSON")
  249. if this.ReturnUrl != null {
  250. pubBody.Set("return_url", this.ReturnUrl)
  251. }
  252. if this.Charset == null {
  253. pubBody.Set("charset", "utf-8")
  254. } else {
  255. pubBody.Set("charset", this.Charset)
  256. }
  257. if this.SignType == null {
  258. pubBody.Set("sign_type", "RSA2")
  259. } else {
  260. pubBody.Set("sign_type", this.SignType)
  261. }
  262. pubBody.Set("timestamp", time.Now().Format(TimeLayout))
  263. pubBody.Set("version", "1.0")
  264. if this.NotifyUrl != null {
  265. pubBody.Set("notify_url", this.NotifyUrl)
  266. }
  267. if this.AppAuthToken != null {
  268. pubBody.Set("app_auth_token", this.AppAuthToken)
  269. }
  270. pubBody.Set("biz_content", string(bodyStr))
  271. //===============获取签名===================
  272. pKey := FormatPrivateKey(this.privateKey)
  273. sign, err := getRsaSign(pubBody, pubBody.Get("sign_type"), pKey)
  274. if err != nil {
  275. return nil, err
  276. }
  277. pubBody.Set("sign", sign)
  278. //fmt.Println("rsaSign:", sign)
  279. //===============发起请求===================
  280. urlParam := FormatAliPayURLParam(pubBody)
  281. //fmt.Println("urlParam:", urlParam)
  282. if method == "alipay.trade.app.pay" {
  283. return []byte(urlParam), nil
  284. }
  285. if method == "alipay.trade.page.pay" {
  286. if !this.isProd {
  287. //沙箱环境
  288. return []byte(zfb_sanbox_base_url + "?" + urlParam), nil
  289. } else {
  290. //正式环境
  291. return []byte(zfb_base_url + "?" + urlParam), nil
  292. }
  293. }
  294. var url string
  295. agent := HttpAgent()
  296. if !this.isProd {
  297. //沙箱环境
  298. url = zfb_sanbox_base_url
  299. //fmt.Println(url)
  300. agent.Post(url)
  301. } else {
  302. //正式环境
  303. url = zfb_base_url
  304. //fmt.Println(url)
  305. agent.Post(url)
  306. }
  307. rsp, bs, errs := agent.
  308. Type("form-data").
  309. SendString(urlParam).
  310. EndBytes()
  311. if len(errs) > 0 {
  312. return nil, errs[0]
  313. }
  314. if method == "alipay.trade.wap.pay" {
  315. //fmt.Println("rsp:::", rsp.Body)
  316. if rsp.Request.URL.String() == zfb_base_url || rsp.Request.URL.String() == zfb_sanbox_base_url {
  317. return nil, errors.New("请求手机网站支付出错,请检查各个参数或秘钥是否正确")
  318. }
  319. return []byte(rsp.Request.URL.String()), nil
  320. }
  321. return bs, nil
  322. }