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で2回送信されていることがわかりました。 payment_status
を「保留中」として最初の支払い中に1回、eCheckが実際にpayment_status
を「完了」として処理する数日後にもう一度。
両方のトランザクションを保存したいのですが、重複を保存したくないのです。 IPNにはipn_track_id
という別のフィールドがあり、両方のトランザクションで異なりますが、このあいまいな説明を除いて、そのドキュメントを見つけることができません。
内部; MTSおよびDTSでのみ使用
他の誰かがipn_track_id
を使用してIPNメッセージを一意に識別していますか?
ipn_track_id
は使用しないでください。これは主に、前述のように内部使用のみであり、すべてのIPNメッセージに固有であるためです。txn_id
is各IPNメッセージではなくtransactionごとに一意です。
これが意味するのは; 1つのトランザクションに複数のIPNメッセージを含めることができます。たとえば、eCheckはデフォルトで「保留中」の状態になり、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 OKHTTPステータス応答を返す必要があります。
HTTP/1.1 200 OK応答を返さない場合、Paypalは個々のIPNメッセージごとに最大16回同じデータの送信を再試行します。
注:売り手のトランザクションIDは、買い手のトランザクションIDとは異なります。これは、2つの異なるアクション(1つの借方、1つの貸方)であるためです。
ipn_track_idは、定期的な支払いに対して一意ではありません。少なくとも分割払いの場合はそうではありません。顧客が分割払いプランを作成し、プランがチェックアウト時に最初の支払いを行う場合、同じipn_track_idを持つ2つの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
すべてのIPNメッセージに$ _POST ['txn_id']が含まれているわけではないため、txn_idのみをチェックする場合、このキーが含まれていないIPNメッセージを断続的にログに記録しない可能性があります。
私のPHP API呼び出しでは、これらのフィールドを使用してデータベースに保存します。
custom=xxxx
(またはinvoice=ZZZZZZ
)
次に、ページがIPNを受信すると、(データベースから)custom=xxxx
またはなど...