client.go 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. package alipay
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "strings"
  7. "sync"
  8. "time"
  9. "github.com/iGoogle-ink/gopay"
  10. )
  11. type Client struct {
  12. AppId string
  13. PrivateKeyType PKCSType
  14. PrivateKey string
  15. LocationName string
  16. AppCertSN string
  17. AliPayPublicCertSN string
  18. AliPayRootCertSN string
  19. ReturnUrl string
  20. NotifyUrl string
  21. Charset string
  22. SignType string
  23. AppAuthToken string
  24. AuthToken string
  25. IsProd bool
  26. location *time.Location
  27. mu sync.RWMutex
  28. }
  29. // 初始化支付宝客户端
  30. // 注意:如果使用支付宝公钥证书验签,请设置 支付宝根证书SN(client.SetAlipayRootCertSN())、应用公钥证书SN(client.SetAppCertSN())
  31. // appId:应用ID
  32. // privateKey:应用私钥,支持PKCS1和PKCS8
  33. // isProd:是否是正式环境
  34. func NewClient(appId, privateKey string, isProd bool) (client *Client) {
  35. return &Client{
  36. AppId: appId,
  37. PrivateKey: privateKey,
  38. IsProd: isProd,
  39. }
  40. }
  41. // alipay.trade.fastpay.refund.query(统一收单交易退款查询)
  42. // 文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.fastpay.refund.query
  43. func (a *Client) TradeFastPayRefundQuery(bm gopay.BodyMap) (aliRsp *TradeFastpayRefundQueryResponse, err error) {
  44. if bm.Get("out_trade_no") == gopay.NULL && bm.Get("trade_no") == gopay.NULL {
  45. return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
  46. }
  47. err = bm.CheckEmptyError("out_request_no")
  48. if err != nil {
  49. return nil, err
  50. }
  51. var bs []byte
  52. if bs, err = a.doAliPay(bm, "alipay.trade.fastpay.refund.query"); err != nil {
  53. return nil, err
  54. }
  55. aliRsp = new(TradeFastpayRefundQueryResponse)
  56. if err = json.Unmarshal(bs, aliRsp); err != nil {
  57. return nil, err
  58. }
  59. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  60. info := aliRsp.Response
  61. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  62. }
  63. aliRsp.SignData = getSignData(bs)
  64. return aliRsp, nil
  65. }
  66. // alipay.trade.order.settle(统一收单交易结算接口)
  67. // 文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.order.settle
  68. func (a *Client) TradeOrderSettle(bm gopay.BodyMap) (aliRsp *TradeOrderSettleResponse, err error) {
  69. err = bm.CheckEmptyError("out_request_no", "trade_no", "royalty_parameters")
  70. if err != nil {
  71. return nil, err
  72. }
  73. var bs []byte
  74. if bs, err = a.doAliPay(bm, "alipay.trade.order.settle"); err != nil {
  75. return nil, err
  76. }
  77. aliRsp = new(TradeOrderSettleResponse)
  78. if err = json.Unmarshal(bs, aliRsp); err != nil {
  79. return nil, err
  80. }
  81. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  82. info := aliRsp.Response
  83. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  84. }
  85. aliRsp.SignData = getSignData(bs)
  86. return aliRsp, nil
  87. }
  88. // alipay.trade.create(统一收单交易创建接口)
  89. // 文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.create
  90. func (a *Client) TradeCreate(bm gopay.BodyMap) (aliRsp *TradeCreateResponse, err error) {
  91. err = bm.CheckEmptyError("out_trade_no", "total_amount", "subject")
  92. if err != nil {
  93. return nil, err
  94. }
  95. var bs []byte
  96. if bs, err = a.doAliPay(bm, "alipay.trade.create"); err != nil {
  97. return nil, err
  98. }
  99. aliRsp = new(TradeCreateResponse)
  100. if err = json.Unmarshal(bs, aliRsp); err != nil {
  101. return nil, err
  102. }
  103. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  104. info := aliRsp.Response
  105. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  106. }
  107. aliRsp.SignData = getSignData(bs)
  108. return aliRsp, nil
  109. }
  110. // alipay.trade.close(统一收单交易关闭接口)
  111. // 文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.close
  112. func (a *Client) TradeClose(bm gopay.BodyMap) (aliRsp *TradeCloseResponse, err error) {
  113. if bm.Get("out_trade_no") == gopay.NULL && bm.Get("trade_no") == gopay.NULL {
  114. return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
  115. }
  116. var bs []byte
  117. if bs, err = a.doAliPay(bm, "alipay.trade.close"); err != nil {
  118. return nil, err
  119. }
  120. aliRsp = new(TradeCloseResponse)
  121. if err = json.Unmarshal(bs, aliRsp); err != nil {
  122. return nil, err
  123. }
  124. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  125. info := aliRsp.Response
  126. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  127. }
  128. aliRsp.SignData = getSignData(bs)
  129. return aliRsp, nil
  130. }
  131. // alipay.trade.cancel(统一收单交易撤销接口)
  132. // 文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.cancel
  133. func (a *Client) TradeCancel(bm gopay.BodyMap) (aliRsp *TradeCancelResponse, err error) {
  134. if bm.Get("out_trade_no") == gopay.NULL && bm.Get("trade_no") == gopay.NULL {
  135. return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
  136. }
  137. var bs []byte
  138. if bs, err = a.doAliPay(bm, "alipay.trade.cancel"); err != nil {
  139. return nil, err
  140. }
  141. aliRsp = new(TradeCancelResponse)
  142. if err = json.Unmarshal(bs, aliRsp); err != nil {
  143. return nil, err
  144. }
  145. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  146. info := aliRsp.Response
  147. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  148. }
  149. aliRsp.SignData = getSignData(bs)
  150. return aliRsp, nil
  151. }
  152. // alipay.trade.refund(统一收单交易退款接口)
  153. // 文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.refund
  154. func (a *Client) TradeRefund(bm gopay.BodyMap) (aliRsp *TradeRefundResponse, err error) {
  155. if bm.Get("out_trade_no") == gopay.NULL && bm.Get("trade_no") == gopay.NULL {
  156. return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
  157. }
  158. err = bm.CheckEmptyError("refund_amount")
  159. if err != nil {
  160. return nil, err
  161. }
  162. var bs []byte
  163. if bs, err = a.doAliPay(bm, "alipay.trade.refund"); err != nil {
  164. return nil, err
  165. }
  166. aliRsp = new(TradeRefundResponse)
  167. if err = json.Unmarshal(bs, aliRsp); err != nil {
  168. return nil, err
  169. }
  170. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  171. info := aliRsp.Response
  172. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  173. }
  174. aliRsp.SignData = getSignData(bs)
  175. return aliRsp, nil
  176. }
  177. // alipay.trade.page.refund(统一收单退款页面接口)
  178. // 文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.page.refund
  179. func (a *Client) TradePageRefund(bm gopay.BodyMap) (aliRsp *TradePageRefundResponse, err error) {
  180. if bm.Get("out_trade_no") == gopay.NULL && bm.Get("trade_no") == gopay.NULL {
  181. return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
  182. }
  183. err = bm.CheckEmptyError("out_request_no", "refund_amount")
  184. if err != nil {
  185. return nil, err
  186. }
  187. var bs []byte
  188. if bs, err = a.doAliPay(bm, "alipay.trade.page.refund"); err != nil {
  189. return nil, err
  190. }
  191. aliRsp = new(TradePageRefundResponse)
  192. if err = json.Unmarshal(bs, aliRsp); err != nil {
  193. return nil, err
  194. }
  195. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  196. info := aliRsp.Response
  197. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  198. }
  199. aliRsp.SignData = getSignData(bs)
  200. return aliRsp, nil
  201. }
  202. // alipay.trade.precreate(统一收单线下交易预创建)
  203. // 文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.precreate
  204. func (a *Client) TradePrecreate(bm gopay.BodyMap) (aliRsp *TradePrecreateResponse, err error) {
  205. err = bm.CheckEmptyError("out_trade_no", "total_amount", "subject")
  206. if err != nil {
  207. return nil, err
  208. }
  209. var bs []byte
  210. if bs, err = a.doAliPay(bm, "alipay.trade.precreate"); err != nil {
  211. return nil, err
  212. }
  213. aliRsp = new(TradePrecreateResponse)
  214. if err = json.Unmarshal(bs, aliRsp); err != nil {
  215. return nil, err
  216. }
  217. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  218. info := aliRsp.Response
  219. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  220. }
  221. if aliRsp.NullResponse != nil {
  222. info := aliRsp.NullResponse
  223. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  224. }
  225. aliRsp.SignData = getSignData(bs)
  226. return aliRsp, nil
  227. }
  228. // alipay.trade.pay(统一收单交易支付接口)
  229. // 文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.pay
  230. func (a *Client) TradePay(bm gopay.BodyMap) (aliRsp *TradePayResponse, err error) {
  231. err = bm.CheckEmptyError("out_trade_no", "scene", "auth_code", "subject")
  232. if err != nil {
  233. return nil, err
  234. }
  235. var bs []byte
  236. if bs, err = a.doAliPay(bm, "alipay.trade.pay"); err != nil {
  237. return nil, err
  238. }
  239. aliRsp = new(TradePayResponse)
  240. if err = json.Unmarshal(bs, aliRsp); err != nil {
  241. return nil, err
  242. }
  243. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  244. info := aliRsp.Response
  245. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  246. }
  247. aliRsp.SignData = getSignData(bs)
  248. return aliRsp, nil
  249. }
  250. // alipay.trade.query(统一收单线下交易查询)
  251. // 文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.query
  252. func (a *Client) TradeQuery(bm gopay.BodyMap) (aliRsp *TradeQueryResponse, err error) {
  253. if bm.Get("out_trade_no") == gopay.NULL && bm.Get("trade_no") == gopay.NULL {
  254. return nil, errors.New("out_trade_no and trade_no are not allowed to be null at the same time")
  255. }
  256. var bs []byte
  257. if bs, err = a.doAliPay(bm, "alipay.trade.query"); err != nil {
  258. return nil, err
  259. }
  260. aliRsp = new(TradeQueryResponse)
  261. if err = json.Unmarshal(bs, aliRsp); err != nil {
  262. return nil, err
  263. }
  264. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  265. info := aliRsp.Response
  266. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  267. }
  268. aliRsp.SignData = getSignData(bs)
  269. return aliRsp, nil
  270. }
  271. // alipay.trade.app.pay(app支付接口2.0)
  272. // 文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.app.pay
  273. func (a *Client) TradeAppPay(bm gopay.BodyMap) (payParam string, err error) {
  274. err = bm.CheckEmptyError("out_trade_no", "total_amount", "subject")
  275. if err != nil {
  276. return gopay.NULL, err
  277. }
  278. var bs []byte
  279. if bs, err = a.doAliPay(bm, "alipay.trade.app.pay"); err != nil {
  280. return gopay.NULL, err
  281. }
  282. payParam = string(bs)
  283. return payParam, nil
  284. }
  285. // alipay.trade.wap.pay(手机网站支付接口2.0)
  286. // 文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.wap.pay
  287. func (a *Client) TradeWapPay(bm gopay.BodyMap) (payUrl string, err error) {
  288. bm.Set("product_code", "QUICK_WAP_WAY")
  289. err = bm.CheckEmptyError("out_trade_no", "total_amount", "subject")
  290. if err != nil {
  291. return gopay.NULL, err
  292. }
  293. var bs []byte
  294. if bs, err = a.doAliPay(bm, "alipay.trade.wap.pay"); err != nil {
  295. return gopay.NULL, err
  296. }
  297. payUrl = string(bs)
  298. return payUrl, nil
  299. }
  300. // alipay.trade.page.pay(统一收单下单并支付页面接口)
  301. // 文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.page.pay
  302. func (a *Client) TradePagePay(bm gopay.BodyMap) (payUrl string, err error) {
  303. bm.Set("product_code", "FAST_INSTANT_TRADE_PAY")
  304. err = bm.CheckEmptyError("out_trade_no", "total_amount", "subject")
  305. if err != nil {
  306. return gopay.NULL, err
  307. }
  308. var bs []byte
  309. if bs, err = a.doAliPay(bm, "alipay.trade.page.pay"); err != nil {
  310. return gopay.NULL, err
  311. }
  312. payUrl = string(bs)
  313. return payUrl, nil
  314. }
  315. // alipay.fund.trans.toaccount.transfer(单笔转账到支付宝账户接口)
  316. // 文档地址:https://opendocs.alipay.com/apis/api_28/alipay.fund.trans.toaccount.transfer
  317. // 注意:此接口官方以升级替换为 alipay.fund.trans.uni.transfer
  318. func (a *Client) FundTransToaccountTransfer(bm gopay.BodyMap) (aliRsp *FundTransToaccountTransferResponse, err error) {
  319. if bm.Get("out_biz_no") == gopay.NULL {
  320. return nil, errors.New("out_biz_no is not allowed to be null")
  321. }
  322. var bs []byte
  323. if bs, err = a.doAliPay(bm, "alipay.fund.trans.toaccount.transfer"); err != nil {
  324. return
  325. }
  326. aliRsp = new(FundTransToaccountTransferResponse)
  327. if err = json.Unmarshal(bs, aliRsp); err != nil {
  328. return nil, err
  329. }
  330. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  331. info := aliRsp.Response
  332. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  333. }
  334. aliRsp.SignData = getSignData(bs)
  335. return aliRsp, nil
  336. }
  337. // alipay.fund.trans.uni.transfer(单笔转账接口)
  338. // 文档地址:https://opendocs.alipay.com/apis/api_28/alipay.fund.trans.uni.transfer
  339. func (a *Client) FundTransUniTransfer(bm gopay.BodyMap) (aliRsp *FundTransUniTransferResponse, err error) {
  340. err = bm.CheckEmptyError("out_biz_no", "trans_amount", "product_code", "payee_info")
  341. if err != nil {
  342. return nil, err
  343. }
  344. var bs []byte
  345. if bs, err = a.doAliPay(bm, "alipay.fund.trans.uni.transfer"); err != nil {
  346. return nil, err
  347. }
  348. aliRsp = new(FundTransUniTransferResponse)
  349. if err = json.Unmarshal(bs, aliRsp); err != nil {
  350. return nil, err
  351. }
  352. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  353. info := aliRsp.Response
  354. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  355. }
  356. aliRsp.SignData = getSignData(bs)
  357. return aliRsp, nil
  358. }
  359. // alipay.fund.trans.common.query(转账业务单据查询接口)
  360. // 文档地址:https://opendocs.alipay.com/apis/api_28/alipay.fund.trans.common.query
  361. func (a *Client) FundTransCommonQuery(bm gopay.BodyMap) (aliRsp *FundTransCommonQueryResponse, err error) {
  362. var bs []byte
  363. if bs, err = a.doAliPay(bm, "alipay.fund.trans.common.query"); err != nil {
  364. return nil, err
  365. }
  366. aliRsp = new(FundTransCommonQueryResponse)
  367. if err = json.Unmarshal(bs, aliRsp); err != nil {
  368. return nil, err
  369. }
  370. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  371. info := aliRsp.Response
  372. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  373. }
  374. aliRsp.SignData = getSignData(bs)
  375. return aliRsp, nil
  376. }
  377. // alipay.fund.account.query(支付宝资金账户资产查询接口)
  378. // 文档地址:https://opendocs.alipay.com/apis/api_28/alipay.fund.account.query
  379. func (a *Client) FundAccountQuery(bm gopay.BodyMap) (aliRsp *FundAccountQueryResponse, err error) {
  380. err = bm.CheckEmptyError("alipay_user_id")
  381. if err != nil {
  382. return nil, err
  383. }
  384. var bs []byte
  385. if bs, err = a.doAliPay(bm, "alipay.fund.account.query"); err != nil {
  386. return nil, err
  387. }
  388. aliRsp = new(FundAccountQueryResponse)
  389. if err = json.Unmarshal(bs, aliRsp); err != nil {
  390. return nil, err
  391. }
  392. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  393. info := aliRsp.Response
  394. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  395. }
  396. aliRsp.SignData = getSignData(bs)
  397. return aliRsp, nil
  398. }
  399. // alipay.trade.orderinfo.sync(支付宝订单信息同步接口)
  400. // 文档地址:https://opendocs.alipay.com/apis/api_1/alipay.trade.orderinfo.sync
  401. func (a *Client) TradeOrderinfoSync(body gopay.BodyMap) {
  402. }
  403. // alipay.system.oauth.token(换取授权访问令牌)
  404. // 文档地址:https://opendocs.alipay.com/apis/api_9/alipay.system.oauth.token
  405. func (a *Client) SystemOauthToken(bm gopay.BodyMap) (aliRsp *SystemOauthTokenResponse, err error) {
  406. if bm.Get("code") == gopay.NULL && bm.Get("refresh_token") == gopay.NULL {
  407. return nil, errors.New("code and refresh_token are not allowed to be null at the same time")
  408. }
  409. err = bm.CheckEmptyError("grant_type")
  410. if err != nil {
  411. return nil, err
  412. }
  413. var bs []byte
  414. if bs, err = systemOauthToken(a.AppId, a.PrivateKeyType, a.PrivateKey, bm, "alipay.system.oauth.token", a.IsProd, a.SignType); err != nil {
  415. return nil, err
  416. }
  417. aliRsp = new(SystemOauthTokenResponse)
  418. if err = json.Unmarshal(bs, aliRsp); err != nil {
  419. return nil, err
  420. }
  421. if aliRsp.ErrorResponse != nil {
  422. info := aliRsp.ErrorResponse
  423. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  424. }
  425. aliRsp.SignData = getSignData(bs)
  426. return aliRsp, nil
  427. }
  428. // alipay.user.info.share(支付宝会员授权信息查询接口)
  429. // body:此接口无需body参数
  430. // 文档地址:https://opendocs.alipay.com/apis/api_2/alipay.user.info.share
  431. func (a *Client) UserInfoShare() (aliRsp *UserInfoShareResponse, err error) {
  432. var bs []byte
  433. if bs, err = a.doAliPay(nil, "alipay.user.info.share"); err != nil {
  434. return nil, err
  435. }
  436. aliRsp = new(UserInfoShareResponse)
  437. if err = json.Unmarshal(bs, aliRsp); err != nil {
  438. return nil, err
  439. }
  440. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  441. info := aliRsp.Response
  442. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  443. }
  444. aliRsp.SignData = getSignData(bs)
  445. return aliRsp, nil
  446. }
  447. // alipay.open.auth.token.app(换取应用授权令牌)
  448. // 文档地址:https://opendocs.alipay.com/apis/api_9/alipay.open.auth.token.app
  449. func (a *Client) OpenAuthTokenApp(bm gopay.BodyMap) (aliRsp *OpenAuthTokenAppResponse, err error) {
  450. if bm.Get("code") == gopay.NULL && bm.Get("refresh_token") == gopay.NULL {
  451. return nil, errors.New("code and refresh_token are not allowed to be null at the same time")
  452. }
  453. err = bm.CheckEmptyError("grant_type")
  454. if err != nil {
  455. return nil, err
  456. }
  457. var bs []byte
  458. if bs, err = a.doAliPay(bm, "alipay.open.auth.token.app"); err != nil {
  459. return nil, err
  460. }
  461. aliRsp = new(OpenAuthTokenAppResponse)
  462. if err = json.Unmarshal(bs, aliRsp); err != nil {
  463. return nil, err
  464. }
  465. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  466. info := aliRsp.Response
  467. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  468. }
  469. aliRsp.SignData = getSignData(bs)
  470. return aliRsp, nil
  471. }
  472. // zhima.credit.score.get(芝麻分)
  473. // 文档地址:https://opendocs.alipay.com/apis/api_8/zhima.credit.score.get
  474. func (a *Client) ZhimaCreditScoreGet(bm gopay.BodyMap) (aliRsp *ZhimaCreditScoreGetResponse, err error) {
  475. if bm.Get("product_code") == gopay.NULL {
  476. bm.Set("product_code", "w1010100100000000001")
  477. }
  478. err = bm.CheckEmptyError("transaction_id")
  479. if err != nil {
  480. return nil, err
  481. }
  482. var bs []byte
  483. if bs, err = a.doAliPay(bm, "zhima.credit.score.get"); err != nil {
  484. return nil, err
  485. }
  486. aliRsp = new(ZhimaCreditScoreGetResponse)
  487. if err = json.Unmarshal(bs, aliRsp); err != nil {
  488. return nil, err
  489. }
  490. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  491. info := aliRsp.Response
  492. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  493. }
  494. aliRsp.SignData = getSignData(bs)
  495. return aliRsp, nil
  496. }
  497. // alipay.user.certify.open.initialize(身份认证初始化服务)
  498. // 文档地址:https://opendocs.alipay.com/apis/api_2/alipay.user.certify.open.initialize
  499. func (a *Client) UserCertifyOpenInit(bm gopay.BodyMap) (aliRsp *UserCertifyOpenInitResponse, err error) {
  500. err = bm.CheckEmptyError("outer_order_no", "biz_code", "identity_param", "merchant_config")
  501. if err != nil {
  502. return nil, err
  503. }
  504. var bs []byte
  505. if bs, err = a.doAliPay(bm, "alipay.user.certify.open.initialize"); err != nil {
  506. return nil, err
  507. }
  508. aliRsp = new(UserCertifyOpenInitResponse)
  509. if err = json.Unmarshal(bs, aliRsp); err != nil {
  510. return nil, err
  511. }
  512. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  513. info := aliRsp.Response
  514. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  515. }
  516. aliRsp.SignData = getSignData(bs)
  517. return aliRsp, nil
  518. }
  519. // alipay.user.certify.open.certify(身份认证开始认证)
  520. // API文档地址:https://opendocs.alipay.com/apis/api_2/alipay.user.certify.open.certify
  521. // 产品文档地址:https://opendocs.alipay.com/open/20181012100420932508/quickstart
  522. func (a *Client) UserCertifyOpenCertify(bm gopay.BodyMap) (certifyUrl string, err error) {
  523. err = bm.CheckEmptyError("certify_id")
  524. if err != nil {
  525. return gopay.NULL, err
  526. }
  527. var bs []byte
  528. if bs, err = a.doAliPay(bm, "alipay.user.certify.open.certify"); err != nil {
  529. return gopay.NULL, err
  530. }
  531. certifyUrl = string(bs)
  532. return certifyUrl, nil
  533. }
  534. // alipay.user.certify.open.query(身份认证记录查询)
  535. // 文档地址:https://opendocs.alipay.com/apis/api_2/alipay.user.certify.open.query
  536. func (a *Client) UserCertifyOpenQuery(bm gopay.BodyMap) (aliRsp *UserCertifyOpenQueryResponse, err error) {
  537. err = bm.CheckEmptyError("certify_id")
  538. if err != nil {
  539. return nil, err
  540. }
  541. var bs []byte
  542. if bs, err = a.doAliPay(bm, "alipay.user.certify.open.query"); err != nil {
  543. return nil, err
  544. }
  545. aliRsp = new(UserCertifyOpenQueryResponse)
  546. if err = json.Unmarshal(bs, aliRsp); err != nil {
  547. return nil, err
  548. }
  549. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  550. info := aliRsp.Response
  551. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  552. }
  553. aliRsp.SignData = getSignData(bs)
  554. return aliRsp, nil
  555. }
  556. // alipay.user.info.auth(用户登陆授权)
  557. // 文档地址:https://opendocs.alipay.com/apis/api_9/alipay.user.info.auth
  558. func (a *Client) UserInfoAuth(bm gopay.BodyMap) (aliRsp *UserInfoAuthResponse, err error) {
  559. err = bm.CheckEmptyError("scopes", "state")
  560. if err != nil {
  561. return nil, err
  562. }
  563. var bs []byte
  564. if bs, err = a.doAliPay(bm, "alipay.user.info.auth"); err != nil {
  565. return nil, err
  566. }
  567. if strings.Contains(string(bs), "<head>") {
  568. return nil, errors.New(string(bs))
  569. }
  570. aliRsp = new(UserInfoAuthResponse)
  571. if err = json.Unmarshal(bs, aliRsp); err != nil {
  572. return nil, err
  573. }
  574. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  575. info := aliRsp.Response
  576. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  577. }
  578. aliRsp.SignData = getSignData(bs)
  579. return aliRsp, nil
  580. }
  581. // alipay.data.bill.balance.query(支付宝商家账户当前余额查询)
  582. // 文档地址:https://opendocs.alipay.com/apis/api_15/alipay.data.bill.balance.query
  583. func (a *Client) DataBillBalanceQuery(bm gopay.BodyMap) (aliRsp *DataBillBalanceQueryResponse, err error) {
  584. var bs []byte
  585. if bs, err = a.doAliPay(bm, "alipay.data.bill.balance.query"); err != nil {
  586. return nil, err
  587. }
  588. aliRsp = new(DataBillBalanceQueryResponse)
  589. if err = json.Unmarshal(bs, aliRsp); err != nil {
  590. return nil, err
  591. }
  592. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  593. info := aliRsp.Response
  594. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  595. }
  596. aliRsp.SignData = getSignData(bs)
  597. return aliRsp, nil
  598. }
  599. // alipay.data.dataservice.bill.downloadurl.query(查询对账单下载地址)
  600. // 文档地址:https://opendocs.alipay.com/apis/api_15/alipay.data.dataservice.bill.downloadurl.query
  601. func (a *Client) DataBillDownloadUrlQuery(bm gopay.BodyMap) (aliRsp *DataBillDownloadUrlQueryResponse, err error) {
  602. err = bm.CheckEmptyError("bill_type", "bill_date")
  603. if err != nil {
  604. return nil, err
  605. }
  606. var bs []byte
  607. if bs, err = a.doAliPay(bm, "alipay.data.dataservice.bill.downloadurl.query"); err != nil {
  608. return nil, err
  609. }
  610. aliRsp = new(DataBillDownloadUrlQueryResponse)
  611. if err = json.Unmarshal(bs, aliRsp); err != nil {
  612. return nil, err
  613. }
  614. if aliRsp.Response != nil && aliRsp.Response.Code != "10000" {
  615. info := aliRsp.Response
  616. return nil, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
  617. }
  618. aliRsp.SignData = getSignData(bs)
  619. return aliRsp, nil
  620. }
  621. // 向支付宝发送请求
  622. func (a *Client) doAliPay(bm gopay.BodyMap, method string) (bs []byte, err error) {
  623. var (
  624. bodyStr, url string
  625. bodyBs []byte
  626. )
  627. if bm != nil {
  628. if bodyBs, err = json.Marshal(bm); err != nil {
  629. return nil, fmt.Errorf("json.Marshal:%w", err)
  630. }
  631. bodyStr = string(bodyBs)
  632. }
  633. pubBody := make(gopay.BodyMap)
  634. pubBody.Set("app_id", a.AppId)
  635. pubBody.Set("method", method)
  636. pubBody.Set("format", "JSON")
  637. if a.AppCertSN != gopay.NULL {
  638. a.mu.RLock()
  639. pubBody.Set("app_cert_sn", a.AppCertSN)
  640. a.mu.RUnlock()
  641. }
  642. if a.AliPayRootCertSN != gopay.NULL {
  643. a.mu.RLock()
  644. pubBody.Set("alipay_root_cert_sn", a.AliPayRootCertSN)
  645. a.mu.RUnlock()
  646. }
  647. if a.ReturnUrl != gopay.NULL {
  648. a.mu.RLock()
  649. pubBody.Set("return_url", a.ReturnUrl)
  650. a.mu.RUnlock()
  651. }
  652. if a.Charset == gopay.NULL {
  653. pubBody.Set("charset", "utf-8")
  654. } else {
  655. a.mu.RLock()
  656. pubBody.Set("charset", a.Charset)
  657. a.mu.RUnlock()
  658. }
  659. if a.SignType == gopay.NULL {
  660. pubBody.Set("sign_type", RSA2)
  661. } else {
  662. a.mu.RLock()
  663. pubBody.Set("sign_type", a.SignType)
  664. a.mu.RUnlock()
  665. }
  666. if a.LocationName != gopay.NULL && a.location != nil {
  667. a.mu.RLock()
  668. pubBody.Set("timestamp", time.Now().In(a.location).Format(gopay.TimeLayout))
  669. a.mu.RUnlock()
  670. } else {
  671. pubBody.Set("timestamp", time.Now().Format(gopay.TimeLayout))
  672. }
  673. pubBody.Set("version", "1.0")
  674. if a.NotifyUrl != gopay.NULL {
  675. a.mu.RLock()
  676. pubBody.Set("notify_url", a.NotifyUrl)
  677. a.mu.RUnlock()
  678. }
  679. if a.AppAuthToken != gopay.NULL {
  680. a.mu.RLock()
  681. pubBody.Set("app_auth_token", a.AppAuthToken)
  682. a.mu.RUnlock()
  683. }
  684. if a.AuthToken != gopay.NULL {
  685. a.mu.RLock()
  686. pubBody.Set("auth_token", a.AuthToken)
  687. a.mu.RUnlock()
  688. }
  689. if bodyStr != gopay.NULL {
  690. pubBody.Set("biz_content", bodyStr)
  691. }
  692. sign, err := GetRsaSign(pubBody, pubBody.Get("sign_type"), a.PrivateKeyType, a.PrivateKey)
  693. if err != nil {
  694. return nil, fmt.Errorf("GetRsaSign Error: %v", err)
  695. }
  696. pubBody.Set("sign", sign)
  697. param := FormatURLParam(pubBody)
  698. switch method {
  699. case "alipay.trade.app.pay":
  700. return []byte(param), nil
  701. case "alipay.trade.wap.pay", "alipay.trade.page.pay", "alipay.user.certify.open.certify":
  702. if !a.IsProd {
  703. return []byte(sandboxBaseUrl + "?" + param), nil
  704. }
  705. return []byte(baseUrl + "?" + param), nil
  706. default:
  707. httpClient := gopay.NewHttpClient()
  708. if !a.IsProd {
  709. url = sandboxBaseUrlUtf8
  710. } else {
  711. url = baseUrlUtf8
  712. }
  713. res, bs, errs := httpClient.Type(gopay.TypeForm).Post(url).SendString(param).EndBytes()
  714. if len(errs) > 0 {
  715. return nil, errs[0]
  716. }
  717. if res.StatusCode != 200 {
  718. return nil, fmt.Errorf("HTTP Request Error, StatusCode = %d", res.StatusCode)
  719. }
  720. return bs, nil
  721. }
  722. }
  723. func getSignData(bs []byte) (signData string) {
  724. str := string(bs)
  725. indexStart := strings.Index(str, `":`)
  726. indexEnd := strings.Index(str, `,"sign"`)
  727. signData = str[indexStart+2 : indexEnd]
  728. return
  729. }