PaypalのIPNリスナーを設定

wordpressでpaypalからのIPN通知を受信可能にするやり方

PHP PayPal IPNを利用

wordpressのマルチサイト構成でpaypal決済を統合する際のIPN回りについてエントリーしてみる。

paypalのサイトやネット上でIPN関連のプログラムは複数公開されている。そのなかで、PHP PayPal IPNというものを利用してwordpressにIPNリスナーを実装してみたい。

https://github.com/Quixotix/PHP-PayPal-IPN

上のコードをダウンロードすると、

ipnlistener.php

というファイルがあるので、そのファイルをwordpressのルート直下にlibというディレクトリを作成し、その中にコピーした。次に、PHP PayPal IPNの

example/ipn.php

というファイルをwordpressのルート下に

paypal.php

というファイル名にしてコピーした。

paypal.php内では、ipnlistener.phpのインクルード設定を行っているので、パスを以下のように修正する。

include('./lib/ipnlistener.php');

個人的にエラーログのファイル名を以下のように変更した。

ini_set('error_log', './ipn.log');

paypal.phpの下の方にメールアドレスを設定する部分があるので、

YOUR EMAIL ADDRESS

という部分を

自身のアドレスに変更しておく。

パスやメールアドレスを修正したら、paypal.phpにブラウザでアクセスしてみる。blog.netというマルチサイト構成のwordpressを想定し、

sub1.blog.net/paypal.php

にブラウザからアクセスしてみる。画面が真っ白で何も表示されないことを確認する。画面には何も表示されないが、wordpressルート直下に

ipn.log

というファイルが新しく生成されたことを確認できる。ファイルを開くと、

[08-Feb-2014 09:24:10] Invalid HTTP request method.

とログが残っていることを確認できる。POSTリクエストでないと上のエラーになるようだ。paypalからのipn通知はPOSTで送信されてくる、そのためPOST以外のリクエストは上のエラーになるように設定されているようだ。

それでは、POSTリクエストをテストとして受け付けるにはどうしたらよいか?

IPN simulator

IPN simulator

という開発ツールがpaypalのサイトに用意されているので、それを利用して自分のサイトに通知する。

サイトにアクセスすると、IPN handler URLという項目があるので、そこにIPNリスナーのURLを入力する。今回の場合であれば、

sub1.blog.net/paypal.php

が該当する。このURLはsub1.blog.net専用のIPNリスナーになるが、sub2.blog.netなどマルチサイト環境のそのほかのブログサイトとpaypal.phpを共有することになる。IPNリスナーを共有するが、リクエストURLは、個々のブログサイトで専用のURLを割り当てるとログ管理上有利になることがあるので、そのような想定で進めていく。リクエストURLの設定は、paypalの管理画面から行うことができるが、

<input type="hidden" value="http://sub1.blog.net/paypal.php" name="notify_url">

というコードを購入ボタンのフォーム内に定義することで、リクエストURLを設定することもできる。各ブログサイトでリクエストURLが異なる場合にはこの方法が有効となる。

IPN handler URLを入力したら、そのほかの項目はデフォルトの状態で、下の方にあるSend IPNのボタンを押してみる。ボタンを押すと、

  • paypalからのIPN通知
  • blog.netがIPN通知を受信
  • blog.netがIPNの内容をポストバック
  • paypalがポストバックの内容を検証し結果をblog.netに返す
  • blog.netが検証結果を受信

という流れで処理が行われる。そのため、上で設定したメールアドレスに検証結果が届くことになっている。しかし、メールは届かない。もう一度、ipn.logを確認してみると、以下のエラーが記録されていることに気づく。

[08-Feb-2014 09:38:00] cURL error: [60] SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

これはCurl接続で利用しているセキュリティ証明書が無効であるためエラーになったという内容のエラーになる。このエラーを回避するためには有効な証明書を設定するか、証明書の検証処理をスルーするように設定する必要がある。今回は、以下のように検証処理を回避する方法で対応した。

lib/ipnlistener.php

でCurlの接続オプションを設定しているので、その一部を変更する。

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);

以下のように変更

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

変更したら再度IPN simulatorでIPN通知を送ってみる。今度はメールが届く。

メールには$_POSTで取得できるデータが記入されている

メールには、主題として検証結果の

  • VERIFIED
  • INVALID

が書かれていて、本文にはIPN simulatorから送信した購入に関する情報が書いてある。これらの情報がpaypal側の購入ステータスが変化するたびに送信されてくる。そのため、paypal.phpでメールを送信するタイミングでデータベース処理を行い、検証結果や購入に関するデータを追加・アップデートを行うことになる。

データベーステーブルの定義

paypalから返されるデータを$_POSTで扱うことができることがわかった。それらのデータを管理するデータベーステーブルが必要になる。レスポンスされるデータが多いためとまどうかもしれないが、効率的にテーブルを定義する方法がある。

PHP PayPal IPNモジュールには、データベース連携の処理は含まれていないが、db連携を含むIPN関連のプログラムが公開されている。それらのプログラムには、テーブル定義のためのSQLが含まれているので、そのSQLを参考にどのようにpaypalのデータを管理しているのか調べてみるのがおすすめ。以下のモジュールはテーブル定義用のSQLが含まれている。

https://github.com/webtechnick/CakePHP-Paypal-IPN-Plugin
https://github.com/orderly/codeigniter-paypal-ipn

CakePHP-Paypal-IPN-Pluginの場合であれば、ルート直下にpaypal_ipn.sqlというDDLが配置されている。文字コードの変更などは必要になるが、効率的にpaypalのテーブルを作成するための助けになるはず。

paypal.phpでwordpress関数を利用可能にする

paypal.phpは、wordpress直下に配置した。この状態では、wordpressの機能を利用することができない。データを管理する際には、wordpressのwpdbを利用して効率的にデータを追加できるようにしたい。wordpress関数を利用可能にするためには、以下の一行を追加する。

require( dirname(__FILE__) . '/wp-load.php' );

この一行で$wpdbが利用可能になる。IPNの検証結果をデータベースに挿入してみる。

global $wpdb;
$wpdb->insert('instant_payment_notifications', 
	array(
		'id' => sha1(uniqid(mt_rand(), true)),
		'payment_status' => $_POST['payment_status'],
		'txn_id' => $_POST['txn_id'],
		'receiver_email' => $_POST['receiver_email'],
		'mc_gross' => $_POST['mc_gross']
	),
	array( '%s', '%s', '%s', '%s', '%d' )
);

メール送信前に上のコードをpaypal.phpに追加しIPN simulatorでリクエストしてみるとinstant_payment_notificationsテーブルにデータが追加されていくことを確認できる。今回は、必ず検証すべきデータとされているものだけをinsertするコードを書いてみた。

参考

wordpress paypal決済のインテグレーション方法

Webエンジニアブログにコメント

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

PaypalのIPNリスナーを設定の記事にコメントを投稿