蛋蛋星球-制度模式
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

481 line
16 KiB

  1. package paypal
  2. import (
  3. "context"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "net/http"
  8. "strconv"
  9. "github.com/go-pay/gopay"
  10. )
  11. // 生成下一个发票号码(Generate invoice number)
  12. // Code = 0 is success
  13. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#invoices_generate-next-invoice-number
  14. func (c *Client) InvoiceNumberGenerate(ctx context.Context, invoiceNumber string) (ppRsp *InvoiceNumberGenerateRsp, err error) {
  15. bm := make(gopay.BodyMap)
  16. bm.Set("invoice_number", invoiceNumber)
  17. res, bs, err := c.doPayPalPost(ctx, bm, generateInvoiceNumber)
  18. if err != nil {
  19. return nil, err
  20. }
  21. ppRsp = &InvoiceNumberGenerateRsp{Code: Success}
  22. ppRsp.Response = new(InvoiceNumber)
  23. if err = json.Unmarshal(bs, ppRsp.Response); err != nil {
  24. return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
  25. }
  26. if res.StatusCode != http.StatusOK {
  27. ppRsp.Code = res.StatusCode
  28. ppRsp.Error = string(bs)
  29. ppRsp.ErrorResponse = new(ErrorResponse)
  30. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  31. }
  32. return ppRsp, nil
  33. }
  34. // 发票列表(List invoices)
  35. // Code = 0 is success
  36. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#invoices_list
  37. func (c *Client) InvoiceList(ctx context.Context, query gopay.BodyMap) (ppRsp *InvoiceListRsp, err error) {
  38. uri := invoiceList + "?" + query.EncodeURLParams()
  39. res, bs, err := c.doPayPalGet(ctx, uri)
  40. if err != nil {
  41. return nil, err
  42. }
  43. ppRsp = &InvoiceListRsp{Code: Success}
  44. ppRsp.Response = new(InvoiceList)
  45. if err = json.Unmarshal(bs, ppRsp.Response); err != nil {
  46. return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
  47. }
  48. if res.StatusCode != http.StatusOK {
  49. ppRsp.Code = res.StatusCode
  50. ppRsp.Error = string(bs)
  51. ppRsp.ErrorResponse = new(ErrorResponse)
  52. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  53. }
  54. return ppRsp, nil
  55. }
  56. // 创建虚拟发票(Create draft invoice)
  57. // Code = 0 is success
  58. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#invoices_create
  59. func (c *Client) InvoiceCreate(ctx context.Context, body gopay.BodyMap) (ppRsp *InvoiceCreateRsp, err error) {
  60. res, bs, err := c.doPayPalPost(ctx, body, createDraftInvoice)
  61. if err != nil {
  62. return nil, err
  63. }
  64. ppRsp = &InvoiceCreateRsp{Code: Success}
  65. ppRsp.Response = new(Invoice)
  66. if err = json.Unmarshal(bs, ppRsp.Response); err != nil {
  67. return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
  68. }
  69. if res.StatusCode != http.StatusCreated {
  70. ppRsp.Code = res.StatusCode
  71. ppRsp.Error = string(bs)
  72. ppRsp.ErrorResponse = new(ErrorResponse)
  73. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  74. }
  75. return ppRsp, nil
  76. }
  77. // 删除发票(Delete invoice)
  78. // Code = 0 is success
  79. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#invoices_delete
  80. func (c *Client) InvoiceDelete(ctx context.Context, invoiceId string) (ppRsp *EmptyRsp, err error) {
  81. if invoiceId == gopay.NULL {
  82. return nil, errors.New("invoice_id is empty")
  83. }
  84. url := fmt.Sprintf(deleteInvoice, invoiceId)
  85. res, bs, err := c.doPayPalDelete(ctx, url)
  86. if err != nil {
  87. return nil, err
  88. }
  89. ppRsp = &EmptyRsp{Code: Success}
  90. if res.StatusCode != http.StatusNoContent {
  91. ppRsp.Code = res.StatusCode
  92. ppRsp.Error = string(bs)
  93. ppRsp.ErrorResponse = new(ErrorResponse)
  94. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  95. }
  96. return ppRsp, nil
  97. }
  98. // 更新发票(Fully update invoice)
  99. // Code = 0 is success
  100. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#invoices_update
  101. func (c *Client) InvoiceUpdate(ctx context.Context, invoiceId string, sendToInvoicer, sendToRecipient bool, body gopay.BodyMap) (ppRsp *InvoiceUpdateRsp, err error) {
  102. if invoiceId == gopay.NULL {
  103. return nil, errors.New("invoice_id is empty")
  104. }
  105. url := fmt.Sprintf(fullyUpdateInvoice, invoiceId)
  106. if sendToInvoicer {
  107. url = url + "?send_to_invoicer=true"
  108. }
  109. if sendToRecipient {
  110. if sendToInvoicer {
  111. url = url + "&send_to_recipient=true"
  112. } else {
  113. url = url + "?send_to_recipient=true"
  114. }
  115. }
  116. res, bs, err := c.doPayPalPut(ctx, body, url)
  117. if err != nil {
  118. return nil, err
  119. }
  120. ppRsp = &InvoiceUpdateRsp{Code: Success}
  121. ppRsp.Response = new(Invoice)
  122. if err = json.Unmarshal(bs, ppRsp.Response); err != nil {
  123. return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
  124. }
  125. if res.StatusCode != http.StatusOK {
  126. ppRsp.Code = res.StatusCode
  127. ppRsp.Error = string(bs)
  128. ppRsp.ErrorResponse = new(ErrorResponse)
  129. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  130. }
  131. return ppRsp, nil
  132. }
  133. // 获取发票详情(Show invoice details)
  134. // Code = 0 is success
  135. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#invoices_get
  136. func (c *Client) InvoiceDetail(ctx context.Context, invoiceId string) (ppRsp *InvoiceDetailRsp, err error) {
  137. if invoiceId == gopay.NULL {
  138. return nil, errors.New("invoice_id is empty")
  139. }
  140. url := fmt.Sprintf(showInvoiceDetail, invoiceId)
  141. res, bs, err := c.doPayPalGet(ctx, url)
  142. if err != nil {
  143. return nil, err
  144. }
  145. ppRsp = &InvoiceDetailRsp{Code: Success}
  146. ppRsp.Response = new(Invoice)
  147. if err = json.Unmarshal(bs, ppRsp.Response); err != nil {
  148. return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
  149. }
  150. if res.StatusCode != http.StatusOK {
  151. ppRsp.Code = res.StatusCode
  152. ppRsp.Error = string(bs)
  153. ppRsp.ErrorResponse = new(ErrorResponse)
  154. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  155. }
  156. return ppRsp, nil
  157. }
  158. // 取消已发送发票(Cancel sent invoice)
  159. // Code = 0 is success
  160. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#invoices_cancel
  161. func (c *Client) InvoiceCancel(ctx context.Context, invoiceId string, body gopay.BodyMap) (ppRsp *EmptyRsp, err error) {
  162. if invoiceId == gopay.NULL {
  163. return nil, errors.New("invoice_id is empty")
  164. }
  165. url := fmt.Sprintf(cancelSentInvoice, invoiceId)
  166. res, bs, err := c.doPayPalPost(ctx, body, url)
  167. if err != nil {
  168. return nil, err
  169. }
  170. ppRsp = &EmptyRsp{Code: Success}
  171. if res.StatusCode != http.StatusNoContent {
  172. ppRsp.Code = res.StatusCode
  173. ppRsp.Error = string(bs)
  174. ppRsp.ErrorResponse = new(ErrorResponse)
  175. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  176. }
  177. return ppRsp, nil
  178. }
  179. // 生成发票二维码(Generate QR code)
  180. // Code = 0 is success
  181. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#invoices_generate-qr-code
  182. func (c *Client) InvoiceGenerateQRCode(ctx context.Context, invoiceId string, body gopay.BodyMap) (ppRsp *InvoiceGenerateQRCodeRsp, err error) {
  183. if invoiceId == gopay.NULL {
  184. return nil, errors.New("invoice_id is empty")
  185. }
  186. url := fmt.Sprintf(generateInvoiceQRCode, invoiceId)
  187. res, bs, err := c.doPayPalPost(ctx, body, url)
  188. if err != nil {
  189. return nil, err
  190. }
  191. ppRsp = &InvoiceGenerateQRCodeRsp{Code: Success}
  192. ppRsp.Response = &QRCodeBase64{Base64Image: string(bs)}
  193. if res.StatusCode != http.StatusOK {
  194. ppRsp.Code = res.StatusCode
  195. ppRsp.Error = string(bs)
  196. ppRsp.ErrorResponse = new(ErrorResponse)
  197. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  198. }
  199. return ppRsp, nil
  200. }
  201. // 发票付款记录(Record payment for invoice)
  202. // Code = 0 is success
  203. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#invoices_payments
  204. func (c *Client) InvoicePaymentRecord(ctx context.Context, invoiceId string, body gopay.BodyMap) (ppRsp *InvoicePaymentRsp, err error) {
  205. if invoiceId == gopay.NULL {
  206. return nil, errors.New("invoice_id is empty")
  207. }
  208. url := fmt.Sprintf(recordPaymentForInvoice, invoiceId)
  209. res, bs, err := c.doPayPalPost(ctx, body, url)
  210. if err != nil {
  211. return nil, err
  212. }
  213. ppRsp = &InvoicePaymentRsp{Code: Success}
  214. ppRsp.Response = new(InvoicePayment)
  215. if err = json.Unmarshal(bs, ppRsp.Response); err != nil {
  216. return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
  217. }
  218. if res.StatusCode != http.StatusOK {
  219. ppRsp.Code = res.StatusCode
  220. ppRsp.Error = string(bs)
  221. ppRsp.ErrorResponse = new(ErrorResponse)
  222. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  223. }
  224. return ppRsp, nil
  225. }
  226. // 发票付款删除(Delete external payment)
  227. // Code = 0 is success
  228. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#invoices_payments-delete
  229. func (c *Client) InvoicePaymentDelete(ctx context.Context, invoiceId, transactionId string) (ppRsp *EmptyRsp, err error) {
  230. if invoiceId == gopay.NULL || transactionId == gopay.NULL {
  231. return nil, errors.New("invoice_id or transaction_id is empty")
  232. }
  233. url := fmt.Sprintf(deleteExternalPayment, invoiceId, transactionId)
  234. res, bs, err := c.doPayPalDelete(ctx, url)
  235. if err != nil {
  236. return nil, err
  237. }
  238. ppRsp = &EmptyRsp{Code: Success}
  239. if res.StatusCode != http.StatusNoContent {
  240. ppRsp.Code = res.StatusCode
  241. ppRsp.Error = string(bs)
  242. ppRsp.ErrorResponse = new(ErrorResponse)
  243. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  244. }
  245. return ppRsp, nil
  246. }
  247. // 发票退款记录(Record refund for invoice)
  248. // Code = 0 is success
  249. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#invoices_refunds
  250. func (c *Client) InvoiceRefundRecord(ctx context.Context, invoiceId string, body gopay.BodyMap) (ppRsp *InvoiceRefundRsp, err error) {
  251. if invoiceId == gopay.NULL {
  252. return nil, errors.New("invoice_id is empty")
  253. }
  254. url := fmt.Sprintf(recordRefundForInvoice, invoiceId)
  255. res, bs, err := c.doPayPalPost(ctx, body, url)
  256. if err != nil {
  257. return nil, err
  258. }
  259. ppRsp = &InvoiceRefundRsp{Code: Success}
  260. ppRsp.Response = new(InvoiceRefund)
  261. if err = json.Unmarshal(bs, ppRsp.Response); err != nil {
  262. return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
  263. }
  264. if res.StatusCode != http.StatusOK {
  265. ppRsp.Code = res.StatusCode
  266. ppRsp.Error = string(bs)
  267. ppRsp.ErrorResponse = new(ErrorResponse)
  268. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  269. }
  270. return ppRsp, nil
  271. }
  272. // 发票退款删除(Delete external refund)
  273. // Code = 0 is success
  274. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#invoices_refunds-delete
  275. func (c *Client) InvoiceRefundDelete(ctx context.Context, invoiceId, transactionId string) (ppRsp *EmptyRsp, err error) {
  276. if invoiceId == gopay.NULL || transactionId == gopay.NULL {
  277. return nil, errors.New("invoice_id or transaction_id is empty")
  278. }
  279. url := fmt.Sprintf(deleteExternalRefund, invoiceId, transactionId)
  280. res, bs, err := c.doPayPalDelete(ctx, url)
  281. if err != nil {
  282. return nil, err
  283. }
  284. ppRsp = &EmptyRsp{Code: Success}
  285. if res.StatusCode != http.StatusNoContent {
  286. ppRsp.Code = res.StatusCode
  287. ppRsp.Error = string(bs)
  288. ppRsp.ErrorResponse = new(ErrorResponse)
  289. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  290. }
  291. return ppRsp, nil
  292. }
  293. // 发送发票提醒(Send invoice reminder)
  294. // Code = 0 is success
  295. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#invoices_remind
  296. func (c *Client) InvoiceSendRemind(ctx context.Context, invoiceId string, body gopay.BodyMap) (ppRsp *EmptyRsp, err error) {
  297. if invoiceId == gopay.NULL {
  298. return nil, errors.New("invoice_id is empty")
  299. }
  300. url := fmt.Sprintf(sendInvoiceReminder, invoiceId)
  301. res, bs, err := c.doPayPalPost(ctx, body, url)
  302. if err != nil {
  303. return nil, err
  304. }
  305. ppRsp = &EmptyRsp{Code: Success}
  306. if res.StatusCode != http.StatusNoContent {
  307. ppRsp.Code = res.StatusCode
  308. ppRsp.Error = string(bs)
  309. ppRsp.ErrorResponse = new(ErrorResponse)
  310. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  311. }
  312. return ppRsp, nil
  313. }
  314. // 发送发票(Send invoice)
  315. // Code = 0 is success
  316. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#invoices_send
  317. func (c *Client) InvoiceSend(ctx context.Context, invoiceId string, body gopay.BodyMap) (ppRsp *InvoiceSendRsp, err error) {
  318. if invoiceId == gopay.NULL {
  319. return nil, errors.New("invoice_id is empty")
  320. }
  321. url := fmt.Sprintf(sendInvoice, invoiceId)
  322. res, bs, err := c.doPayPalPost(ctx, body, url)
  323. if err != nil {
  324. return nil, err
  325. }
  326. ppRsp = &InvoiceSendRsp{Code: Success}
  327. ppRsp.Response = new(InvoiceSend)
  328. if err = json.Unmarshal(bs, ppRsp.Response); err != nil {
  329. return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
  330. }
  331. if res.StatusCode != http.StatusAccepted {
  332. ppRsp.Code = res.StatusCode
  333. ppRsp.Error = string(bs)
  334. ppRsp.ErrorResponse = new(ErrorResponse)
  335. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  336. }
  337. return ppRsp, nil
  338. }
  339. // 发票搜索(Search for invoices)
  340. // Code = 0 is success
  341. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#search-invoices_search-invoices
  342. func (c *Client) InvoiceSearch(ctx context.Context, page, pageSize int, totalRequired bool, body gopay.BodyMap) (ppRsp *InvoiceSearchRsp, err error) {
  343. uri := searchInvoice
  344. if page != 0 && pageSize != 0 {
  345. uri += uri + "?page=" + strconv.Itoa(page) + "&page_size=" + strconv.Itoa(pageSize)
  346. }
  347. if totalRequired {
  348. if page != 0 && pageSize != 0 {
  349. uri += uri + "&total_required=true"
  350. } else {
  351. uri += uri + "?total_required=true"
  352. }
  353. }
  354. res, bs, err := c.doPayPalPost(ctx, body, uri)
  355. if err != nil {
  356. return nil, err
  357. }
  358. ppRsp = &InvoiceSearchRsp{Code: Success}
  359. ppRsp.Response = new(InvoiceSearch)
  360. if err = json.Unmarshal(bs, ppRsp.Response); err != nil {
  361. return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
  362. }
  363. if res.StatusCode != http.StatusOK {
  364. ppRsp.Code = res.StatusCode
  365. ppRsp.Error = string(bs)
  366. ppRsp.ErrorResponse = new(ErrorResponse)
  367. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  368. }
  369. return ppRsp, nil
  370. }
  371. // 发票模板列表(List templates)
  372. // Code = 0 is success
  373. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#templates_list
  374. func (c *Client) InvoiceTemplateList(ctx context.Context, query gopay.BodyMap) (ppRsp *InvoiceTemplateListRsp, err error) {
  375. uri := invoiceTemplateList + "?" + query.EncodeURLParams()
  376. res, bs, err := c.doPayPalGet(ctx, uri)
  377. if err != nil {
  378. return nil, err
  379. }
  380. ppRsp = &InvoiceTemplateListRsp{Code: Success}
  381. ppRsp.Response = new(InvoiceTemplate)
  382. if err = json.Unmarshal(bs, ppRsp.Response); err != nil {
  383. return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
  384. }
  385. if res.StatusCode != http.StatusOK {
  386. ppRsp.Code = res.StatusCode
  387. ppRsp.Error = string(bs)
  388. ppRsp.ErrorResponse = new(ErrorResponse)
  389. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  390. }
  391. return ppRsp, nil
  392. }
  393. // 创建发票模板(Create template)
  394. // Code = 0 is success
  395. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#templates_create
  396. func (c *Client) InvoiceTemplateCreate(ctx context.Context, body gopay.BodyMap) (ppRsp *InvoiceTemplateCreateRsp, err error) {
  397. res, bs, err := c.doPayPalPost(ctx, body, createInvoiceTemplate)
  398. if err != nil {
  399. return nil, err
  400. }
  401. ppRsp = &InvoiceTemplateCreateRsp{Code: Success}
  402. ppRsp.Response = new(Template)
  403. if err = json.Unmarshal(bs, ppRsp.Response); err != nil {
  404. return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
  405. }
  406. if res.StatusCode != http.StatusCreated {
  407. ppRsp.Code = res.StatusCode
  408. ppRsp.Error = string(bs)
  409. ppRsp.ErrorResponse = new(ErrorResponse)
  410. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  411. }
  412. return ppRsp, nil
  413. }
  414. // 删除发票模板(Delete template)
  415. // Code = 0 is success
  416. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#templates_delete
  417. func (c *Client) InvoiceTemplateDelete(ctx context.Context, templateId string) (ppRsp *EmptyRsp, err error) {
  418. if templateId == gopay.NULL {
  419. return nil, errors.New("template_id is empty")
  420. }
  421. url := fmt.Sprintf(deleteInvoiceTemplate, templateId)
  422. res, bs, err := c.doPayPalDelete(ctx, url)
  423. if err != nil {
  424. return nil, err
  425. }
  426. ppRsp = &EmptyRsp{Code: Success}
  427. if res.StatusCode != http.StatusNoContent {
  428. ppRsp.Code = res.StatusCode
  429. ppRsp.Error = string(bs)
  430. ppRsp.ErrorResponse = new(ErrorResponse)
  431. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  432. }
  433. return ppRsp, nil
  434. }
  435. // 更新发票模板(Fully update template)
  436. // Code = 0 is success
  437. // 文档:https://developer.paypal.com/docs/api/invoicing/v2/#templates_update
  438. func (c *Client) InvoiceTemplateUpdate(ctx context.Context, templateId string, body gopay.BodyMap) (ppRsp *InvoiceTemplateUpdateRsp, err error) {
  439. if templateId == gopay.NULL {
  440. return nil, errors.New("template_id is empty")
  441. }
  442. url := fmt.Sprintf(fullyUpdateInvoiceTemplate, templateId)
  443. res, bs, err := c.doPayPalPut(ctx, body, url)
  444. if err != nil {
  445. return nil, err
  446. }
  447. ppRsp = &InvoiceTemplateUpdateRsp{Code: Success}
  448. ppRsp.Response = new(Template)
  449. if err = json.Unmarshal(bs, ppRsp.Response); err != nil {
  450. return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
  451. }
  452. if res.StatusCode != http.StatusOK {
  453. ppRsp.Code = res.StatusCode
  454. ppRsp.Error = string(bs)
  455. ppRsp.ErrorResponse = new(ErrorResponse)
  456. _ = json.Unmarshal(bs, ppRsp.ErrorResponse)
  457. }
  458. return ppRsp, nil
  459. }