paypal と 電子書籍のダウンロード販売(その2)

その0.
購入ボタンはこんな感じ
<form name="_xclick" action="PAYPALSERVER" method="post">
<input type="hidden" name="cmd" value="_xclick" />
<input type="hidden" name="business" value="EMAILADDR" />
<input type="hidden" name="currnecy_code" value="JPY" />
<input type="hidden" name="item_name" value="ITEMNAME" />
<input type="hidden" name="item_number" value="ITEMNUMBER" />
<input type="hidden" name="amount" value="100.00" />
<input type="image" src="PAYPAL PURCHASE BUTTON" />
</form>
item_number以外は必須。item_numberも、商品IDとして使うので、わたしの場合は必須。ユーザーがPaypalから戻ってきたとき・Paypalから即時通知があったときに、この商品IDでデータベースに照合する。
あらかじめ、Paypalで個人設定を仕込む。(以下とは別に、文字コードを日本語、UTF8に設定しておいた)
その1.
「ウェブペイメントの設定」
→自動復帰 オン
→復帰URL ユーザーが帰ってくるURLを設定
→支払いデータ転送(PDT) オン
→暗号化されていないウェブペイメントの受領拒否 オフ
購入ボタン自動生成で暗号化してないので、最後の設定はオフにしておく。
購入ボタンをクリックしてPaypalにいったユーザーが支払いを完了して「マーチャントに戻る」リンクをクリックしたら、復帰URLにパラメータを持って戻ってくる。それをスクリプトで解析する。以下はほぼほぼPaypalにあるサンプルコード(perl版)まんま。
my $query = join(’&’, "cmd=_notify-synch", "tx=$form->{tx}", "at=PAYPAL_AUTH_TOKEN");
my $ua = new LWP::UserAgent;
my $req = new HTTP::Request("POST", PAYPAL_SERVER);
$req->content_type("application/x-www-form-urlencoded");
$req->content($query);
my $res = $ua->request($req);
return if($res->is_error);
my @response = split("\n", $self->html_decode($res->content) );
my $status = shift(@response);
my %tx;
if($status eq "SUCCESS"){
foreach( @response){
my ($key, $val) = split("=", $_);
$tx{$key} = $val;
}
return \%tx;
}
else{
return;
}
戻ってきたら、GET でパラメータ=トランザクションIDを取得して、Paypalの管理ページ、個人設定にある、auth tokenと、定型のコマンドとともに、PaypalのサーバーにPOSTでアクセス。
そこで取得できるcontentを改行でばらして一行ずつ、って先頭の行がSUCCESSであればOK。それ以外だと決済が完了していないので、どうなってるのか調べる必要がある。
というのが「PDT」というヤツ。
ところが、これはユーザーが「マーチャントに戻る」というリンクで戻ってくれないと、情報が何も取得できない。もちろん、Paypalの方からメールがくるし、Paypalの管理画面を見れば、取引状況はわかるので、調べてユーザーに返事を出すこともできる。
でも、今回やりたいのはダウンロード販売。
支払いが終わったらすぐにダウンロードページに行きたいよね…といいつつ、Paypalの「マーチャントに戻る」リンクがまるで目立たない。これじゃ、ユーザーはここでブラウザを閉じて終了、だろう。現に戻ってくる率は20%もない、という記事もどこかで見かけた。なので、こちらは、もしユーザーが戻ってきたら、ありがとうございましたとか、確認にしばらくお時間くださいとか、表示を選択するためのモノとして使う程度。
そこで、以下のIPN(支払い即時通知)の出番。
その2.
「即時支払い通知(IPN)」
→通知URLを設定
支払いが生じたらPaypalから、通知URLあてに、パラメータを抱えてアクセスがある。それをスクリプトで解析。以下はサンプルコード(以下同文)
my $query;
read (STDIN, $query, $ENV{’CONTENT_LENGTH’});
$query .= ’&cmd=_notify-validate’;
my $ua = new LWP::UserAgent;
my $req = new HTTP::Request("POST" , PAYPAL_SERVER);
$req->content_type("application/x-www-form-urlencoded");
$req->content($query);
my $res = $ua->request($req);
my $cnt = 0;
my %ipn;
my @pairs = split(/&/,$query);
foreach my $pair ( @pairs ){
my ($key, $val) = split(/=/,$pair);
$val =~ tr/+/ /;
$val =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
$ipn{$key} = $val;
$cnt++;
}
if( $res->content eq ’VERIFIED’ ){
my $err;
$err = 1 if($ipn{’payment_status’} ne ’Completed’);
$err = 1 if($ipn{’receiver_email’} ne MY_PAYPAL_EMAILADDR});
$err = 1 if($ipn{’mc_currency’} ne ’JPY’);
料金などのチェック
if( $err ){
open(OUT, ’>>’ . ’_err.txt’) || die;
foreach (keys %ipn){ printf OUT qq{[KEY]%s ::: [VAL]%s\n}, $_, $ipn{$_}; }
close(OUT);
}
else{
エラーがなければデータベースに登録したり
ユーザーにメールを出したり
}
}
else{
open(OUT, ’>>’ . ’_err.txt’) || die;
foreach (keys %ipn){ printf OUT qq{[KEY]%s ::: [VAL]%s\n}, $_, $ipn{$_}; }
close(OUT);
}
POSTされたパラメータをそのままに、コマンドを付加して、Papalに返すと、パラメータが正しいか間違ってるかだけ教えてくれる。パラメータが正しければ、料金を確認したり、トランザクションIDをチェックしたり。エラーがあったら、ログを吐き出し、正しければデータベースに登録してユーザーにダウンロードURL案内のメールを出す。
わたしはperlが少しわかる程度。それでもサンプルコードどおりに書けばほぼOK。ダウンロード販売ということで、データを受けてデータベースを使って商品を特定したり、ダウンロードURLを作ったり、というところがちょっと面倒だけど、難しいもんじゃない。
最悪、うまくいかないケースが生じても、Paypalからメールが来るし、Paypalの管理ページに行けば履歴を確認したりキャンセル処理ができるので致命的なことにはならない、はず。
それに、ダウンロード販売なので、面倒な在庫管理は不要。
ちなみに、無責任なことに、これを書いてる時点ではまだ本番でのテストはやってないので、あしからずご了承いただきたく。忘れないうちに自分メモ。
原稿があるなら、Paypalを使って、ダウンロード販売ですよ。たぶん、儲けるのは無理だけど、原稿を塩漬けにしてるぐらいなら、ネットに並べておいてもいいんじゃね、と。個人書店があちこちにできて相互にリンクできれば宣伝にもなって面白いんだろうから、お手伝いしますよー。
| << | 2026/1 | >> | ||||
|---|---|---|---|---|---|---|
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
【最近の20件】
- 20260129 ブログをレスポンシブ対応にリニューアル
- 20260126 ブログのふり返り
- 20260121 小ネタ:ed25519秘密鍵公開鍵とJson serialized canonical
- 20260120 ActivityPubは自作実装しよう!
- 20260117 RFC9421版HTTP Signatureに対応
- 20260111 HTTP Signatureの署名対象文字列
- 20260109 web本棚のActivityPub対応
- 20260106 web本棚のソースコード公開
- 20260104 web本棚
- 20260101 謹賀新年2026
- 20251231 2025年ふりかえり
- 20251213 perlと30年
- 20251210 ActivityPubの投稿削除
- 20251101 日常雑感
- 20251026 テキトーフェッチメール
- 20251014 ActivityPubサーバーで投稿の編集
- 20251008 元WINDOWS10のノパソにlinux mint
- 20251002 GBLシーズン「変わりゆく物語」でACE到達
- 20250925 ブログのアクセス制限
- 20250922 ActivityPubサーバーに引用を実装


