IPN, 即時支払い通知って何?
IPN は PayPal のトランザクションに関連するイベントに関する通知を送ってくれる仕組みです。
ざっと説明すると、
- PayPal 上のいろんなトランザクションの実行を通知してくれる
- 通知を受け取る仕組みを実装する必要がある
- リアルタイムとは限らない
支払いを受け取ったり、クレジットカードの認証や定期購入、払い戻しなどのイベントが発生したときに通知されます。この通知を受け取ってバックエンドでの処理をすることで、データを更新したり、購入確認のメールを送ったりができるようになります。
この機能を使うには、IPN リスナーを実装して、エンドポイントの URL を PayPal アカウントに設定する必要があります。このエンドポイントに通知が送られます。リスナーはメッセージを待ち受け、PayPal からの通知であることを検証し、バックエンド処理に渡すような実装が必要です。
IPN メッセージはすぐに処理されますが、ウェブサイト上のアクションとは同期しません。インターネット接続は常に100%信頼できるわけではないので、IPN メッセージは送れたり届かないこともあります。そのため、IPN サービスは、リスナーから反応があるまで自動的に再送信する仕組みになっています。最大4日間送られます。
IPN はリアルタイムサービスではないので、決済処理は IPN メッセージが来るのを待つべきではありません。受信を待ってしまうと処理が遅れる可能性があります。IPN のディレイを考慮して決済処理を実装してください。
リスナーを実装する
リスナーのサンプルコードはこちら:
リスナーの基本的な流れは次のようになります。
- HTTPS POST リクエストをリッスンします
- リクエストを受け取ったら、まず空の HTTP 200 レスポンスを返します
- 送られてきたのと完全に同じメッセージを Paypal に POST します
- 返すメッセージには cmd=_notify-validate をつけます。それ以外は中身も順番もエンコードも変更してはいけません。
- User-Agent ヘッダに IPN リスナーであることを示すようにします
- PayPal から VERIFIED または INVALID が返ってきます
IPN を受け取ったよというレスポンスをしないと4日間メッセージが送られてきます。メッセージを受け取ったあとの処理を実行する前に、正常に受け取ったレスポンスを返します。
IPNメッセージはどの URL に送られてくるか?
PayPal アカウントにログインして「アカウント設定」-「ウェブペイメント」-「即時支払い通知」-「更新」を見ると、IPNの有効化・無効化や通知 URL を変更することができます。
あるいは、決済時に PayPal に送信するデータに notify_url を設定することで URL を指定することができます。
IPN シミュレーター
PayPal は IPN シミュレーター・ツールを提供しています。このツールでは、sandbox からリスナーが起動している URL にテストメッセージを送信することができます。このツールを使って、リスナーが想定通りに IPN メッセージを受信して処理するかを検証できます。(実際の決済全体をテストしなくて済む)
シミュレーターでは test_ipn という変数を含むので、実際の IPN メッセージと区別することができます。
エンコード方式、Shit_JIS vs UTF-8
言語設定が日本語の場合、PayPal のデフォルトのエンコードは Shift_JIS になっているかと思います。これが思わぬエラーを起こすので UTF-8 に設定しおくのが良いです。
エンコード方式の設定方法
PayPal アカウントにログインして「アカウント設定」-「ウェブペイメント」-「PayPalボタンの言語のエンコーディング」-「更新」と辿ります。
まず、「ウェブサイトの言語」を設定することができます。この言語によってデータのエンコード方式が決定されます。もっと細かく設定するには「詳細オプション」を見ます。
詳細オプションに進むとエンコード方式を指定することができます。 IPN メッセージに使われるエンコード方式は「PayPalから送信されたデータと同じエンコード方式を使用しますか」で変更できます。
西欧言語(英語を含む)
上記の設定で「ウェブサイトの言語」を日本語にすると、詳細オプションのエンコード方式は「Shift_JIS」に変更されます。逆に、詳細オプションのほうで「UTF-8」を指定すると「ウェブサイトの言語」が「西欧言語(英語を含む)」に勝手に変更されます。
この2つは対応してるみたいです。日本語のページなのに「西欧言語(英語を含む)」になってしまいますが、これで問題ありません。
違和感ありますが「日本語」に変更してしまうと詳細オプションも変更されてしまうので注意。
事例
paypalのsandboxでipnのvalidateでINVALIDになる は Sandbox の話ですが Shift_JIS と UTF-8 問題が発生していて、エンコード設定の変更で解決しています。
PayPal のIPNでハマった では、ウェブサイトのエンコード方式を「Shift_JIS」、PayPalから送信されたデータと同じエンコード方式を使用しますかで「いいえ」を選び「UTF-8」に設定するという方法で INVALID を回避してます。
検証環境 Sandbox
- 決済サービスの動作確認ができるテスト環境として Sandbox がある
- テスト用の買い手アカウント(お金を支払う方、PERSONALアカウント)と売り手アカウント(お金を受け取る方、BUSINESSアカウント)を作成して、決済をシミュレーションできる
- 本番環境のアカウントが必要
- 参考
- PayPal テスト環境 Sandboxの使い方 – paypal公式のqiita
文献
- Paypalの定期支払導入の覚書 – IPN の説明と実装について書いてある
- IPNの概要 – IPNの概要という名のPDF。バージョンや出典が不明