alipay_client.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  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. // 文档地址:https://docs.open.alipay.com/api_1/alipay.trade.fastpay.refund.query
  32. func (this *aliPayClient) AliPayTradeFastPayRefundQuery(body BodyMap) (aliRsp *AliPayTradeFastpayRefundQueryResponse, err error) {
  33. var bytes []byte
  34. trade1 := body.Get("out_trade_no")
  35. trade2 := body.Get("trade_no")
  36. if trade1 == null && trade2 == null {
  37. return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
  38. }
  39. bytes, err = this.doAliPay(body, "alipay.trade.fastpay.refund.query")
  40. if err != nil {
  41. return nil, err
  42. }
  43. //log.Println("AliPayTradeFastPayRefundQuery::::", string(bytes))
  44. aliRsp = new(AliPayTradeFastpayRefundQueryResponse)
  45. err = json.Unmarshal(bytes, aliRsp)
  46. if err != nil {
  47. return nil, err
  48. }
  49. if aliRsp.AliPayTradeFastpayRefundQueryResponse.Code != "10000" {
  50. info := aliRsp.AliPayTradeFastpayRefundQueryResponse
  51. return nil, fmt.Errorf(`{"code":"%v","msg":"%v","sub_code":"%v","sub_msg":"%v"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  52. }
  53. return aliRsp, nil
  54. }
  55. //alipay.trade.order.settle(统一收单交易结算接口)
  56. // 文档地址:https://docs.open.alipay.com/api_1/alipay.trade.order.settle
  57. func (this *aliPayClient) AliPayTradeOrderSettle(body BodyMap) (aliRsp *AliPayTradeOrderSettleResponse, err error) {
  58. var bytes []byte
  59. trade1 := body.Get("out_request_no")
  60. trade2 := body.Get("trade_no")
  61. if trade1 == null || trade2 == null {
  62. return nil, errors.New("out_request_no or trade_no are not allowed to be null")
  63. }
  64. bytes, err = this.doAliPay(body, "alipay.trade.order.settle")
  65. if err != nil {
  66. return nil, err
  67. }
  68. //log.Println("AliPayTradeOrderSettle::::", string(bytes))
  69. aliRsp = new(AliPayTradeOrderSettleResponse)
  70. err = json.Unmarshal(bytes, aliRsp)
  71. if err != nil {
  72. return nil, err
  73. }
  74. if aliRsp.AliPayTradeOrderSettleResponse.Code != "10000" {
  75. info := aliRsp.AliPayTradeOrderSettleResponse
  76. return nil, fmt.Errorf(`{"code":"%v","msg":"%v","sub_code":"%v","sub_msg":"%v"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  77. }
  78. return aliRsp, nil
  79. }
  80. //alipay.trade.create(统一收单交易创建接口)
  81. // 文档地址:https://docs.open.alipay.com/api_1/alipay.trade.create
  82. func (this *aliPayClient) AliPayTradeCreate(body BodyMap) (aliRsp *AliPayTradeCreateResponse, err error) {
  83. var bytes []byte
  84. trade1 := body.Get("out_trade_no")
  85. trade2 := body.Get("buyer_id")
  86. if trade1 == null && trade2 == null {
  87. return nil, errors.New("out_trade_no and buyer_id are not allowed to be null at the same time")
  88. }
  89. bytes, err = this.doAliPay(body, "alipay.trade.create")
  90. if err != nil {
  91. return nil, err
  92. }
  93. //log.Println("AliPayTradeCreateResponse::::", string(convertBytes))
  94. aliRsp = new(AliPayTradeCreateResponse)
  95. err = json.Unmarshal(bytes, aliRsp)
  96. if err != nil {
  97. return nil, err
  98. }
  99. if aliRsp.AliPayTradeCreateResponse.Code != "10000" {
  100. info := aliRsp.AliPayTradeCreateResponse
  101. return nil, fmt.Errorf(`{"code":"%v","msg":"%v","sub_code":"%v","sub_msg":"%v"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  102. }
  103. return aliRsp, nil
  104. }
  105. //alipay.trade.close(统一收单交易关闭接口)
  106. // 文档地址:https://docs.open.alipay.com/api_1/alipay.trade.close
  107. func (this *aliPayClient) AliPayTradeClose(body BodyMap) (aliRsp *AliPayTradeCloseResponse, err error) {
  108. var bytes []byte
  109. trade1 := body.Get("out_trade_no")
  110. trade2 := body.Get("trade_no")
  111. if trade1 == null && trade2 == null {
  112. return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
  113. }
  114. bytes, err = this.doAliPay(body, "alipay.trade.close")
  115. if err != nil {
  116. return nil, err
  117. }
  118. //log.Println("AliPayTradeCloseResponse::::", string(bytes))
  119. aliRsp = new(AliPayTradeCloseResponse)
  120. err = json.Unmarshal(bytes, aliRsp)
  121. if err != nil {
  122. return nil, err
  123. }
  124. if aliRsp.AliPayTradeCloseResponse.Code != "10000" {
  125. info := aliRsp.AliPayTradeCloseResponse
  126. return nil, fmt.Errorf(`{"code":"%v","msg":"%v","sub_code":"%v","sub_msg":"%v"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  127. }
  128. return aliRsp, nil
  129. }
  130. //alipay.trade.cancel(统一收单交易撤销接口)
  131. // 文档地址:https://docs.open.alipay.com/api_1/alipay.trade.cancel
  132. func (this *aliPayClient) AliPayTradeCancel(body BodyMap) (aliRsp *AliPayTradeCancelResponse, err error) {
  133. var bytes []byte
  134. trade1 := body.Get("out_trade_no")
  135. trade2 := body.Get("trade_no")
  136. if trade1 == null && trade2 == null {
  137. return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
  138. }
  139. bytes, err = this.doAliPay(body, "alipay.trade.cancel")
  140. if err != nil {
  141. return nil, err
  142. }
  143. //log.Println("AliPayTradeCancel::::", string(bytes))
  144. aliRsp = new(AliPayTradeCancelResponse)
  145. err = json.Unmarshal(bytes, aliRsp)
  146. if err != nil {
  147. return nil, err
  148. }
  149. if aliRsp.AliPayTradeCancelResponse.Code != "10000" {
  150. info := aliRsp.AliPayTradeCancelResponse
  151. return nil, fmt.Errorf(`{"code":"%v","msg":"%v","sub_code":"%v","sub_msg":"%v"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  152. }
  153. return aliRsp, nil
  154. }
  155. //alipay.trade.refund(统一收单交易退款接口)
  156. // 文档地址:https://docs.open.alipay.com/api_1/alipay.trade.refund
  157. func (this *aliPayClient) AliPayTradeRefund(body BodyMap) (aliRsp *AliPayTradeRefundResponse, err error) {
  158. var bytes []byte
  159. trade1 := body.Get("out_trade_no")
  160. trade2 := body.Get("trade_no")
  161. if trade1 == null && trade2 == null {
  162. return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
  163. }
  164. bytes, err = this.doAliPay(body, "alipay.trade.refund")
  165. if err != nil {
  166. return nil, err
  167. }
  168. //log.Println("AliPayTradeRefundResponse::::", string(bytes))
  169. aliRsp = new(AliPayTradeRefundResponse)
  170. err = json.Unmarshal(bytes, aliRsp)
  171. if err != nil {
  172. return nil, err
  173. }
  174. if aliRsp.AlipayTradeRefundResponse.Code != "10000" {
  175. info := aliRsp.AlipayTradeRefundResponse
  176. return nil, fmt.Errorf(`{"code":"%v","msg":"%v","sub_code":"%v","sub_msg":"%v"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  177. }
  178. return aliRsp, nil
  179. }
  180. //alipay.trade.refund(统一收单退款页面接口)
  181. // 文档地址:https://docs.open.alipay.com/api_1/alipay.trade.page.refund
  182. func (this *aliPayClient) AliPayTradePageRefund(body BodyMap) (aliRsp *AliPayTradePageRefundResponse, err error) {
  183. var bytes []byte
  184. trade1 := body.Get("out_trade_no")
  185. trade2 := body.Get("trade_no")
  186. if trade1 == null && trade2 == null {
  187. return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
  188. }
  189. bytes, err = this.doAliPay(body, " alipay.trade.page.refund")
  190. if err != nil {
  191. return nil, err
  192. }
  193. //log.Println("AliPayTradePageRefundResponse::::", string(bytes))
  194. aliRsp = new(AliPayTradePageRefundResponse)
  195. err = json.Unmarshal(bytes, aliRsp)
  196. if err != nil {
  197. return nil, err
  198. }
  199. if aliRsp.AliPayTradePageRefundResponse.Code != "10000" {
  200. info := aliRsp.AliPayTradePageRefundResponse
  201. return nil, fmt.Errorf(`{"code":"%v","msg":"%v","sub_code":"%v","sub_msg":"%v"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  202. }
  203. return aliRsp, nil
  204. }
  205. //alipay.trade.precreate(统一收单线下交易预创建)
  206. // 文档地址:https://docs.open.alipay.com/api_1/alipay.trade.precreate
  207. func (this *aliPayClient) AliPayTradePrecreate(body BodyMap) (aliRsp *AlipayTradePrecreateResponse, err error) {
  208. var bytes []byte
  209. trade1 := body.Get("out_trade_no")
  210. if trade1 == null {
  211. return nil, errors.New("out_trade_no is not allowed to be null")
  212. }
  213. bytes, err = this.doAliPay(body, "alipay.trade.precreate")
  214. if err != nil {
  215. return nil, err
  216. }
  217. //log.Println("AlipayTradePrecreateResponse::::", string(convertBytes))
  218. aliRsp = new(AlipayTradePrecreateResponse)
  219. err = json.Unmarshal(bytes, aliRsp)
  220. if err != nil {
  221. return nil, err
  222. }
  223. if aliRsp.AlipayTradePrecreateResponse.Code != "10000" {
  224. info := aliRsp.AlipayTradePrecreateResponse
  225. return nil, fmt.Errorf(`{"code":"%v","msg":"%v","sub_code":"%v","sub_msg":"%v"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  226. }
  227. return aliRsp, nil
  228. }
  229. //alipay.trade.pay(统一收单交易支付接口)
  230. // 文档地址:https://docs.open.alipay.com/api_1/alipay.trade.pay
  231. func (this *aliPayClient) AliPayTradePay(body BodyMap) (aliRsp *AliPayTradePayResponse, err error) {
  232. var bytes []byte
  233. trade := body.Get("out_trade_no")
  234. if trade == null {
  235. return nil, errors.New("out_trade_no is not allowed to be null")
  236. }
  237. //===============product_code值===================
  238. //body.Set("product_code", "FACE_TO_FACE_PAYMENT")
  239. bytes, err = this.doAliPay(body, "alipay.trade.pay")
  240. if err != nil {
  241. return nil, err
  242. }
  243. //log.Println("AliPayTradePayResponse::::", string(bytes))
  244. aliRsp = new(AliPayTradePayResponse)
  245. err = json.Unmarshal(bytes, aliRsp)
  246. if err != nil {
  247. return nil, err
  248. }
  249. if aliRsp.AliPayTradePayResponse.Code != "10000" {
  250. info := aliRsp.AliPayTradePayResponse
  251. return nil, fmt.Errorf(`{"code":"%v","msg":"%v","sub_code":"%v","sub_msg":"%v"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  252. }
  253. return aliRsp, nil
  254. }
  255. //alipay.trade.query(统一收单线下交易查询)
  256. // 文档地址:https://docs.open.alipay.com/api_1/alipay.trade.query
  257. func (this *aliPayClient) AliPayTradeQuery(body BodyMap) (aliRsp *AliPayTradeQueryResponse, err error) {
  258. var bytes []byte
  259. trade1 := body.Get("out_trade_no")
  260. trade2 := body.Get("trade_no")
  261. if trade1 == null && trade2 == null {
  262. return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
  263. }
  264. bytes, err = this.doAliPay(body, "alipay.trade.query")
  265. if err != nil {
  266. return nil, err
  267. }
  268. //log.Println("AliPayTradeQueryResponse::::", string(bytes))
  269. aliRsp = new(AliPayTradeQueryResponse)
  270. err = json.Unmarshal(bytes, aliRsp)
  271. if err != nil {
  272. return nil, err
  273. }
  274. if aliRsp.AliPayTradeQueryResponse.Code != "10000" {
  275. info := aliRsp.AliPayTradeQueryResponse
  276. return nil, fmt.Errorf(`{"code":"%v","msg":"%v","sub_code":"%v","sub_msg":"%v"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  277. }
  278. return aliRsp, nil
  279. }
  280. //alipay.trade.app.pay(app支付接口2.0)
  281. // 文档地址:https://docs.open.alipay.com/api_1/alipay.trade.app.pay
  282. func (this *aliPayClient) AliPayTradeAppPay(body BodyMap) (payParam string, err error) {
  283. var bytes []byte
  284. trade := body.Get("out_trade_no")
  285. if trade == null {
  286. return null, errors.New("out_trade_no is not allowed to be null")
  287. }
  288. //===============product_code值===================
  289. //body.Set("product_code", "QUICK_MSECURITY_PAY")
  290. bytes, err = this.doAliPay(body, "alipay.trade.app.pay")
  291. if err != nil {
  292. return null, err
  293. }
  294. payParam = string(bytes)
  295. return payParam, nil
  296. }
  297. //alipay.trade.wap.pay(手机网站支付接口2.0)
  298. // 文档地址:https://docs.open.alipay.com/api_1/alipay.trade.wap.pay
  299. func (this *aliPayClient) AliPayTradeWapPay(body BodyMap) (payUrl string, err error) {
  300. var bytes []byte
  301. trade := body.Get("out_trade_no")
  302. if trade == null {
  303. return null, errors.New("out_trade_no is not allowed to be null")
  304. }
  305. //===============product_code值===================
  306. body.Set("product_code", "QUICK_WAP_WAY")
  307. bytes, err = this.doAliPay(body, "alipay.trade.wap.pay")
  308. if err != nil {
  309. //log.Println("err::", err.Error())
  310. return null, err
  311. }
  312. payUrl = string(bytes)
  313. //fmt.Println("URL::", payUrl)
  314. if payUrl == zfb_sanbox_base_url || payUrl == zfb_base_url {
  315. return null, errors.New("请求失败,请查看文档并检查参数")
  316. }
  317. return payUrl, nil
  318. }
  319. //alipay.trade.page.pay(统一收单下单并支付页面接口)
  320. // 文档地址:https://docs.open.alipay.com/api_1/alipay.trade.page.pay
  321. func (this *aliPayClient) AliPayTradePagePay(body BodyMap) (payUrl string, err error) {
  322. var bytes []byte
  323. trade := body.Get("out_trade_no")
  324. if trade == null {
  325. return null, errors.New("out_trade_no is not allowed to be null")
  326. }
  327. //===============product_code值===================
  328. body.Set("product_code", "FAST_INSTANT_TRADE_PAY")
  329. bytes, err = this.doAliPay(body, "alipay.trade.page.pay")
  330. if err != nil {
  331. //log.Println("err::", err.Error())
  332. return null, err
  333. }
  334. payUrl = string(bytes)
  335. if payUrl == zfb_sanbox_base_url_2 || payUrl == zfb_base_url_2 {
  336. return null, errors.New("请求失败,请查看文档并检查参数")
  337. }
  338. return payUrl, nil
  339. }
  340. //alipay.trade.orderinfo.sync(支付宝订单信息同步接口)
  341. func (this *aliPayClient) AliPayTradeOrderinfoSync(body BodyMap) {
  342. }
  343. //zhima.credit.score.brief.get(芝麻分普惠版)
  344. func (this *aliPayClient) ZhimaCreditScoreBriefGet(body BodyMap) {
  345. }
  346. //zhima.credit.score.get(芝麻分)
  347. func (this *aliPayClient) ZhimaCreditScoreGet(body BodyMap) {
  348. }
  349. //向支付宝发送请求
  350. func (this *aliPayClient) doAliPay(body BodyMap, method string) (bytes []byte, err error) {
  351. //===============转换body参数===================
  352. bodyStr, err := json.Marshal(body)
  353. if err != nil {
  354. log.Println("json.Marshal:", err)
  355. return nil, err
  356. }
  357. //fmt.Println(string(bodyStr))
  358. //===============生成参数===================
  359. pubBody := make(BodyMap)
  360. pubBody.Set("app_id", this.AppId)
  361. pubBody.Set("method", method)
  362. pubBody.Set("format", "JSON")
  363. if this.ReturnUrl != null {
  364. pubBody.Set("return_url", this.ReturnUrl)
  365. }
  366. if this.Charset == null {
  367. pubBody.Set("charset", "utf-8")
  368. } else {
  369. pubBody.Set("charset", this.Charset)
  370. }
  371. if this.SignType == null {
  372. pubBody.Set("sign_type", "RSA2")
  373. } else {
  374. pubBody.Set("sign_type", this.SignType)
  375. }
  376. pubBody.Set("timestamp", time.Now().Format(TimeLayout))
  377. pubBody.Set("version", "1.0")
  378. if this.NotifyUrl != null {
  379. pubBody.Set("notify_url", this.NotifyUrl)
  380. }
  381. if this.AppAuthToken != null {
  382. pubBody.Set("app_auth_token", this.AppAuthToken)
  383. }
  384. //fmt.Println("biz_content", string(bodyStr))
  385. pubBody.Set("biz_content", string(bodyStr))
  386. //===============获取签名===================
  387. pKey := FormatPrivateKey(this.privateKey)
  388. sign, err := getRsaSign(pubBody, pubBody.Get("sign_type"), pKey)
  389. if err != nil {
  390. return nil, err
  391. }
  392. pubBody.Set("sign", sign)
  393. //fmt.Println("rsaSign:", sign)
  394. //===============发起请求===================
  395. urlParam := FormatAliPayURLParam(pubBody)
  396. //fmt.Println("urlParam:", urlParam)
  397. if method == "alipay.trade.app.pay" {
  398. return []byte(urlParam), nil
  399. }
  400. if method == "alipay.trade.page.pay" {
  401. if !this.isProd {
  402. //沙箱环境
  403. return []byte(zfb_sanbox_base_url_2 + "?" + urlParam), nil
  404. } else {
  405. //正式环境
  406. return []byte(zfb_base_url_2 + "?" + urlParam), nil
  407. }
  408. }
  409. var url string
  410. agent := HttpAgent()
  411. if !this.isProd {
  412. //沙箱环境
  413. url = zfb_sanbox_base_url
  414. //fmt.Println(url)
  415. agent.Post(url)
  416. } else {
  417. //正式环境
  418. url = zfb_base_url
  419. //fmt.Println(url)
  420. agent.Post(url)
  421. }
  422. rsp, bs, errs := agent.
  423. Type("form-data").
  424. SendString(urlParam).
  425. EndBytes()
  426. if len(errs) > 0 {
  427. return nil, errs[0]
  428. }
  429. if method == "alipay.trade.wap.pay" {
  430. //fmt.Println("rsp:::", rsp.Body)
  431. if rsp.Request.URL.String() == zfb_sanbox_base_url_2 || rsp.Request.URL.String() == zfb_base_url_2 {
  432. return nil, errors.New("请求手机网站支付出错,请检查各个参数或秘钥是否正确")
  433. }
  434. return []byte(rsp.Request.URL.String()), nil
  435. }
  436. return bs, nil
  437. }