如何使用 PayPal REST API 和 IPN 验证销售

How to validate a sale with PayPal REST API and IPN

我目前有一个完全可用的购物车和通过 PayPal _xcart 方法结帐的流程,但我想将其迁移到 REST API,主要是因为我想降低价格劫持的可能性。目前,我的 IPN 确实会检查价格插孔并设置相应的标志,因此不会下载产品(仅销售数字产品)。更重要的是,我发现 PayPal 文档非常混乱,我正在努力完全掌握它。

这是我目前理解和解决的。

  1. 使用我的 PHP 脚本(我们称之为页面 A)我创建了购物车内容,然后我创建了一个新的 PayPal 销售并将客户重定向到 PayPal 进行身份验证

  2. PayPal 上的客户端验证,然后它被重定向回我的站点到页面 B(页面 B 在页面 A 中定义)

  3. 页面B需要获取PaymentID(来自页面A)并使用它来有效地完成交易。一旦完成结帐。

下面是我的问题:

a) 我看了很多论坛和教程,他们都提到我应该使用会话来存储页面 A 的 PaymentId,然后在页面 B 中使用它来完成交易。 SO 上的一些线程建议 PayPal 实际上应该在对页面 B 的调用中包含 PaymentID,以及令牌和 PayerID。这些都是将近 3 年前的帖子,在我的测试过程中,我发现 PayPal 现在也可以 return PaymentID。

b) 在页面 B 上,当我执行付款时,我得到一个很好的 JSON 作为响应,但同时我的 IPN 侦听器也被调用,这让我很困惑。 Can/Should 我只信任 JSON 响应中的所有数据,或多或少地忽略了 IPN 侦听器?这对于即时下载来说是有意义的,例如,更容易处理,或者我仍然应该依赖 IPN 进行数据验证吗?

Can/Should I just trust all the data which is in the JSON response and more or less ignore the IPN listener?

是的,也不是。按照这个顺序。

简而言之,您不能信任调用“页面 B”时的支付 ID(它可能是伪造的、伪造的、重复的等等),但您可以信任 YourServer->PayPalServer 的响应,因为它可以。不会被最终用户拦截和伪造。

所以你的过程是(如你上面描述的)

  1. 页面 A:创建会话 ID(cookie)、金额、购物车详细信息等并存储在本地 database/storage。您还可以创建一个“自定义”字段来存储您自己的 saleID
  2. 将金额等发送到 Paypal,returns 您将......
  3. 页面 B:获取 PayPal TransactionID 并将(服务器->服务器)发送回 PayPal。 Paypal returns 金额、状态等。然后检查您的数据库,确认金额相同并且属于 sessionID。如果您还使用自定义字段,请也检查一下。如果一切都结婚了,你就很好。如果没有,就看你怎么处理了。

此时对于简单的销售,状态应该是“完成”;但是(与下面的 IPN 一样)您应该验证这一点。

请检查金额,以防万一。它们应该匹配,但如果不匹配,PayPal 将是您收到的,您可以接受、标记(和 phone)或通过 API 退款并拒绝订单等.

那么为什么要有IPN呢?

用户可能在 Paypal 上完成交易,然后在调用“页面 B”之前关闭了浏览器。在这种情况下,您了解订单的唯一方式是通过 IPN。

如果您的 IPN 处理程序收到 IPN 通知,IPN 仍然可以伪造,但验证方式略有不同。

您实际上将 IPN 信息发送回 Paypal(服务器到服务器),Paypal 会确认它是正确的还是错误的 (https://developer.paypal.com/docs/classic/ipn/integration-guide/IPNIntro/)。然后您的 IPN 处理程序将检查事务 ID(是的,这就是您使用的)并验证数据库中的所有匹配项(就像您在“页面 B”中所做的那样)。如果是,则在状态为已完成的情况下将订单标记为已完成(如果尚未在“页面 B”中标记为已完成)。

显然,此时您不能向用户显示任何内容,因为他们不是调用该页面的用户。

上面的文档警告您可以为同一笔交易获得多个 IPN,因此您还需要检查状态。

(注意:您可以像在“页面 B”中那样使用 API 来验证交易 ID)。

为什么不在 IPN 上回复?

Paypal 警告 IPN 可能无法到达。贝宝解释得最好:

Although PayPal usually processes IPN messages immediately, IPN is not synchronized with actions on your website. Internet connectivity is not always 100% reliable and IPN messages can be lost or delayed. The IPN service automatically resends messages until the listener acknowledges them. The service resends messages for up to 4 days.

Because IPN is not a real-time service, your checkout flow should not wait for the IPN message before it is allowed to complete. If the checkout flow is dependent on receiving an IPN message, processing can be delayed by system load or other reasons. You should configure your checkout flow to handle a possible delay.

所以回到原来的问题

是:依靠您进行的 JSON(服务器-> 服务器)调用来验证“页面 B”的参数(如果您选择,则在和 IPN 处理程序中)

否:不要忽略 IPN,以防永远不会调用页面 B。但仍然 运行 验证也会在这里检查。

是:“页面 B”和“IPN 处理程序”的检查状态 = 完成

是:使用 Paypal TransactionID,但使用自定义字段或 sessionID 混合到您自己的数据库中。

是的,您 can/will 同时收到页面 B 和 IPN 通知,如果付款已标记为已完成,我建议忽略 IPN,否则请妥善处理。他们应该使用相同的数据库。