{"id":19022044,"url":"https://github.com/smartwalle/paypal","last_synced_at":"2025-03-17T07:09:59.892Z","repository":{"id":57484212,"uuid":"78542356","full_name":"smartwalle/paypal","owner":"smartwalle","description":"PayPal SDK for Go","archived":false,"fork":false,"pushed_at":"2024-09-05T10:03:47.000Z","size":90,"stargazers_count":63,"open_issues_count":1,"forks_count":9,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-04T08:07:35.890Z","etag":null,"topics":["go","golang","paypal"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/smartwalle.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-01-10T14:43:23.000Z","updated_at":"2024-12-28T05:18:55.000Z","dependencies_parsed_at":"2024-06-18T22:59:33.438Z","dependency_job_id":"460cb1fd-60ff-41e5-b734-4b730cb60150","html_url":"https://github.com/smartwalle/paypal","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartwalle%2Fpaypal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartwalle%2Fpaypal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartwalle%2Fpaypal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smartwalle%2Fpaypal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smartwalle","download_url":"https://codeload.github.com/smartwalle/paypal/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243989576,"owners_count":20379648,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","golang","paypal"],"created_at":"2024-11-08T20:24:38.318Z","updated_at":"2025-03-17T07:09:59.873Z","avatar_url":"https://github.com/smartwalle.png","language":"Go","funding_links":["https://developer.paypal.com/developer/accounts/","https://www.sandbox.paypal.com/cn/","https://www.paypal.com/cn/","https://developer.paypal.com/","https://developer.paypal.com/developer/applications/"],"categories":[],"sub_categories":[],"readme":"PayPal SDK for Golang\n\n## 帮助\n\n在集成的过程中有遇到问题，欢迎加 QQ 群 203357977 讨论。\n\n## 已实现接口\n\n#### PaymentS API\n\n* **Get an access token (获取 Access Token)**\n\n\tPOST /v1/oauth2/token\n\n* **Create a payment (创建账单)**\n\n\tPOST /v1/payments/payment\n\t\n* **Execute approved PayPal payment (核准账单支付信息)**\n\n\tPOST /v1/payments/payment/#payment_id/execute\n\t\n* **Show payment details (获取账单详情)**\n\n\tGET /v1/payments/payment/#payment_id \n\t\n* **List payments (获取账单列表)**\n\n\tGET /v1/payments/payment\n\t\n* **Show sale details (获取交易详情)**\n\t\n\tGET /v1/payments/sale/#sale_id\n\t\n* **Refund sale (发起退款)**\n\n\tPOST /v1/payments/sale/#sale_id/refund\n\t\n* **Show refund details (获取退款详情)**\n\n\tGET /v1/payments/refund/#refund_id\n\t\n#### Webhooks API\n\n* **Create webhook (创建钩子)**\n\n\tPOST /v1/notifications/webhooks\n\t\n* **Show webhook details (获取钩子详情)**\n\n\tPOST /v1/notifications/webhooks/#webhook_id\n\t\n* **List all webhooks (获取所有的钩子)**\n\n\tGET /v1/notifications/webhooks\n\t\n* **Delete webhook (删除钩子)**\n\n\tDELETE /v1/notifications/webhooks/#webhook_id\n\t\n## 集成流程\n\n#### Sandbox 账户\n\n从网页 [Sandbox - Accounts](https://developer.paypal.com/developer/accounts/) 可以创建和查看 Sandbox 环境的用户，这样就可以使用测试环境进行实际的支付和收款操作了。\n\n大家在创建 Sandbox 账户的时候，要注意账户有两种类型，即商户和个人，实际测试的时候，应该创建一个商户账户和一个个人账户，商户账户和 App 进行关联，这样个人账户向 App 支付的时候，款项将转入商户的账户中。\n\nSandbox 账户有专门测试网站 [https://www.sandbox.paypal.com/cn/](https://www.sandbox.paypal.com/cn/)，该网站提供的功能和网站 [https://www.paypal.com/cn/](https://www.paypal.com/cn/) 提供的功能是一致的，比如收入、支出、退款操作等，只不过里面的数据都是测试数据。\n\n#### 创建 App\n\n访问网站 [https://developer.paypal.com/](https://developer.paypal.com/), 使用 PayPal 的账号登录，进入 [My Apps \u0026 Credentials](https://developer.paypal.com/developer/applications/) 页面, 找到 **REST API apps**，点击 **Create App** 创建一个新的 App，创建成功之后可以获取到 **Client ID** 和 **Secret**，我们后续在进行认证的时候会用到这两个参数。\n\n创建 App 的时候，需要关联一个 Sanbox 环境的商户账户。\n\n#### 获取 Access Token \n\n```Golang\n\nimport \"github.com/smartwalle/paypal\"\n\nvar client = paypal.New(\"ClientID\", \"Secret\", false) // 第三个参数用于标记是否为生产环境，true 为生产环境，false 为 Sandbox 环境。\n\nvar token, err = client.GetAccessToken() // 获取 Access Token\n\n```\n\n在实际使用过程中，一般不需要单独调用此方法获取 Access Token，除非你有需要。\n\n在访问其它需要认证的接口的时候，组件会自动判断当前是否有正常可用的 Access Token，如果没有，会先向 PayPal 请求 Access Token, 然后再进行业务接口的访问。\n\n#### 创建账单\n\n创建账单提供了两种方式：\n\n##### 1. 快速创建账单\n\n```Golang\nvar payment, err = client.ExpressCreatePayment(invoiceNumber, total, currency, cancelURL, returnURL)\n...\n```\n\n##### 2. 高级接口\n\n```Golang\nvar p = \u0026paypal.Payment{}\np.Intent = paypal.PaymentIntentSale\np.Payer = \u0026paypal.Payer{}\np.Payer.PaymentMethod = \"paypal\"\np.RedirectURLs = \u0026paypal.RedirectURLs{}\np.RedirectURLs.CancelURL = \"http://www.baidu.com\"\np.RedirectURLs.ReturnURL = \"http://127.0.0.1:9001/paypal\"\n\nvar transaction = \u0026paypal.Transaction{}\np.Transactions = []*paypal.Transaction{transaction}\n\ntransaction.Amount = \u0026paypal.Amount{}\ntransaction.Amount.Total = \"30.11\"\ntransaction.Amount.Currency = \"USD\"\ntransaction.Amount.Details = \u0026paypal.AmountDetails{}\ntransaction.Amount.Details.Subtotal = \"30.00\"\ntransaction.Amount.Details.Tax = \"0.07\"\ntransaction.Amount.Details.Shipping = \"0.03\"\ntransaction.Amount.Details.HandlingFee = \"1.00\"\ntransaction.Amount.Details.ShippingDiscount = \"-1.00\"\ntransaction.Amount.Details.Insurance = \"0.01\"\n\ntransaction.Description = \"This is the payment transaction description.\"\ntransaction.Custom = \"EBAY_EMS_90048630024435\"\ntransaction.InvoiceNumber = uuid.New() // 随机生成一串 Invoice Number\n\ntransaction.PaymentOptions = \u0026paypal.PaymentOptions{}\ntransaction.PaymentOptions.AllowedPaymentMethod = \"INSTANT_FUNDING_SOURCE\"\ntransaction.SoftDescriptor = \"ECHI5786786\"\n\ntransaction.ItemList = \u0026paypal.ItemList{}\ntransaction.ItemList.ShippingAddress = \u0026paypal.ShippingAddress{}\ntransaction.ItemList.ShippingAddress.RecipientName = \"Hello World\"\ntransaction.ItemList.ShippingAddress.Line1 = \"4thFloor\"\ntransaction.ItemList.ShippingAddress.Line2 = \"unit#34\"\ntransaction.ItemList.ShippingAddress.City = \"SAn Jose\"\ntransaction.ItemList.ShippingAddress.CountryCode = \"US\"\ntransaction.ItemList.ShippingAddress.PostalCode = \"95131\"\ntransaction.ItemList.ShippingAddress.Phone = \"011862212345678\"\ntransaction.ItemList.ShippingAddress.State = \"CA\"\n\nvar i1, i2 = \u0026paypal.Item{}, \u0026paypal.Item{}\ntransaction.ItemList.Items = []*paypal.Item{i1, i2}\n\ni1.Name = \"hat\"\ni1.Description = \"Brown color hat\"\ni1.Quantity = \"5\"\ni1.Price = \"3\"\ni1.Tax = \"0.01\"\ni1.SKU = \"1\"\ni1.Currency = \"USD\"\n\ni2.Name = \"handbag\"\ni2.Description = \"Black color hand bag\"\ni2.Quantity = \"1\"\ni2.Price = \"15\"\ni2.Tax = \"0.02\"\ni2.SKU = \"product34\"\ni2.Currency = \"USD\"\n\np.NoteToPayer = \"Contact us for any questions on your order.\"\n\nvar payment, err = client.CreatePayment(p)\nfmt.Println(payment, err)\n\n```\n\n这种创建账单的方式虽然会比较复杂，但是信息也比较全面，用户在支付的时候，也能够看到详细的商品清单信息，会显得更加的友好。\n\n#### 支付\n\n从创建账单返回的 Payment 信息中，我们会得到一个 Link 类型的数组 payment.Links，该数组一般含有三个数据，我们要取出其中一个 **rel** 属性的值为 **approval_url** 的 Link，然后在浏览器里面打开其 href 属性对应的链接地址，这样就可以进行登录并支付了。\n\nOK，PayPal 显示支付成功了，也成功跳转到了我们设置的 ReturnURL，这时候进入商户账户，但是还是没有任何的入账信息，这是为什么呢？\n\n创建账单的时候，Payment 有一个 RedirectURLs 属性，该属性有两个值，一个为 CancelURL，另一个为 ReturnURL。\n\nCancelURL 为用户取消支付跳转的 URL；ReturnURL 为用户支付成功跳转的 URL；\n\n当我们支付成功之后，浏览器将跳转到 ReturnURL，跳转到该 URL 之后，我们还要进行一步工作，这样才能保证支付完成。\n\n#### 核准账单支付信息\n\n支付成功之后，浏览器跳转到 ReturnURL 的时候，附带了几个参数：paymentId、token 和 PayerID。\n\n```\nhttp://192.168.192.250:3000/paypal?paymentId=PAY-37A82711YL064934DLB4G3AQ\u0026token=EC-0DG12278CE6129333\u0026PayerID=XV9HF9K25FB38\n```\n\n核准账单支付信息的时候，需要用到 paymentId 和 payerID。\n\n我们在提供的 ReturnURL 接口中应执行核准账单支付信息的操作。\n\n```Golang\nvar payment, err = client.ExecuteApprovedPayment(paymentId, payerID)\n...\n\n```\n\n如果返回的 payment 的 State 为 “approved”，则表示核准账单支付成功（注意：不能以此来判断是否支付成功，即实际到账）。\n\n**如果要判断是否实际到账，需要判断返回结果中的 transactions[xx].related_resources[xx].sale.state 的值，当该字段的值为 completed 的时候，才能说明已到账。**\n\n到此，可以算是完成了一个完整的收款流程，如果想要更加严谨，还需要加上 webhook。\n\n#### 总结\n\n一个简单的支付流程：\n\n1. 初始化 paypal 信息:\n\t\n\t```\n\tvar client = paypal.New(...)\n\t```\n\t\n2. 创建账单\n\n\t```\n\tvar p = \u0026Payment{}\n\t...\n\tclient.CreatePayment(p)\n\t```\n\n3. 从账单中获取类型为 approval_url 的 URL，浏览器打开进行支付\n4. ReturnURL 接口中进行核准账单支付\n\n\t```\n\tvar client = paypal.New(...)\n\tvar p, err = client.ExecuteApprovedPayment(paymentId, payerID)\n\t...\n\t```\n\t\n\n## Webhook (钩子)\n\n待续...","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmartwalle%2Fpaypal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmartwalle%2Fpaypal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmartwalle%2Fpaypal/lists"}