PayPal IPN唯一标识符

27
我一直认为通过IPN消息发送的txn_id是唯一的。 PayPal的指南似乎支持这个想法 - https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_admin_IPNIntro 避免重复的IPN消息。检查您是否已经处理了在IPN消息中返回的交易ID标识的交易。您可能需要将由IPN消息返回的交易ID存储在文件或数据库中,以便您可以检查重复项。如果PayPal发送的交易ID是重复的,则不应再次处理它。
然而,我发现PayPal的eCheck付款IPN会以相同的交易ID两次发送。一次是在初始付款时,payment_status为“Pending”,另一次是在实际处理eCheck时,payment_status为“Completed”。
我想存储这两个交易,但仍希望避免存储重复项。 IPN中还有一个名为ipn_track_id的字段,对于两个交易来说是不同的,但我找不到它的文档,除了这个含糊的描述:
内部使用;仅供MTS和DTS使用
还有其他人正在使用ipn_track_id来唯一标识IPN消息吗?

4
从逻辑上来说,这是一次交易,因此 txn_id 相同。如果将 payment_status 添加到(主)键中,问题就能解决了,不是吗?文档可能应该写成:不应该再处理相同状态的 txn_id。 - rene
1
值得注意的是,根据PayPal的IPN指南,您应仅处理付款状态为“已完成”的交易。 - steve cook
@steve 我依赖于 payment_status="Completed",这样我的 BIN 按钮就会被移除,交易进入我的数据库。希望这是一个好的方法。 - Ben Racicot
1
我有一种感觉,txn_id的唯一性应该只在payment_status='Completed'时进行检查。因为没有文档提到payment_status和txn_id组合的唯一性,如果两个具有相同txn_id的'pending'状态的支付请求同时访问你的数据库,你的程序可能会出错。正如我所说,这只是我的直觉,Paypal应该在文档中更明确地说明这一点。 - user1663023
5个回答

37

ipn_track_id不能使用,主要是因为它只用于内部使用并且对于每个IPN消息它都是唯一的。
txn_id 对于每个交易而言是唯一的,而不是每个IPN消息。

这意味着一个交易可以有多个IPN消息。例如,使用电子支票(eCheck)时,默认情况下会处于“挂起”状态,并在电子支票清除后变为“完成”状态。
但你还可能会看到针对同一txn_id的撤销、取消撤销、打开案件和退款。

伪代码:

If not empty txn_id and txn_type = web_accept and payment_status = Completed  
    // New payment received; completed. May have been a transaction which was pending earlier.
    Update database set payment_status = Completed and txn_id = $_POST['txn_id']  

If not empty txn_id and txn_type = web_accept and payment_status = Pending  
    // New payment received; completed  
    Update database set payment_status = Pending and payment_reason = $_POST['pending_reason'] and txn_id = $_POST['txn_id']
您可以在https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_html_IPNandPDTVariables#id08CTB0S055Z找到更多的IPN变量列表。 基本上,PayPal将生成唯一的卖家交易ID。 这个交易ID可能会经历各种阶段,直到完成,因此您需要能够处理这些异常情况。
至于PayPal文档中的说明:如果在传递过程中遇到错误,PayPal可能会重新发送单个IPN消息。例如,当PayPal向其POST IPN数据时,您的脚本必须返回正确的HTTP/1.1 200 OK HTTP状态响应。
如果您没有返回HTTP/1.1 200 OK响应,PayPal将尝试每个单独的IPN消息重新发送相同的数据最多16次。
请注意:卖家交易ID与买家交易ID不同,因为它们是两个不同的操作(一个借记,一个贷记)。

十年后,ipn_track_id 可以在一个月后重新使用:我有几个订阅被分配了相同的 ipn_track_id 三次:在 subscr_signup 和 subscr_payment 的注册日,然后一个月后再次使用相同的 ipn_track_id 进行第二次 subscr_payment!花了一段时间才弄清楚这个问题。 - kr37

9

对于循环付款,ipn_track_id不是唯一的。至少对于分期付款而言是如此。 当客户创建分期付款时,如果您的计划在结账时有第一笔付款,您将收到两个具有相同ipn_track_id的IPN消息(下面是示例)。

第一个通知是"recurring_payment_profile_created",第一个付款是"recurring_payment"

计划创建的IPN

 [txn_type] => recurring_payment_profile_created
 [recurring_payment_id] => I-57UAPHFJ3SBY
 [product_name] => Risk-Free Trial
 [time_created] => 06:24:39 Aug 15, 2013 PDT
 [ipn_track_id] => bdd94fdee935a

首次支付 IPN

 [txn_type] => recurring_payment
 [mc_gross] => 10.95
 [shipping] => 0.00
 [product_type] => 1
 [time_created] => 06:24:39 Aug 15, 2013 PDT
 [ipn_track_id] => bdd94fdee935a

3
这非常重要,应该在文档中明确列出。不能指望它在重复付款时是唯一的。 - Marc Fowler

3

并非所有的IPN消息都包含$_POST ['txn_id'],因此如果您仅检查txn_id,则可能会间歇性地未记录不包含此键的IPN消息。


1
在我的 PHP API 调用中,我使用这些字段并将它们存储在我的数据库中:
custom=xxxx  

当你的页面收到IPN时,应该检查(从数据库中)custom=xxxx等内容,以及invoice=ZZZZZZ(或)。


-1

IPN交易是独特的,而且更改付款的交易将生成新的txn_id。例如退款,因此最好将所有与单个购买相关的txn_id存储起来。截至目前,我不知道除退款之外的哪些交易会生成新的txn_id,可能撤销也会。


“IPN交易”并不存在。正如OP所证明的那样,PayPal的交易ID并不能唯一标识IPN消息。 - Dai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接