PayPalの使い方 その2 - Express Checkout APIによる課金システムの実装 解説

前回の記事「PayPal APIの使い方 - SandboxのアカウントでCheckout Expressを試してみた」でPayPalサンドボックスでアカウントを作成して、Express CheckoutのIntegration Wizardを利用してシンプルな課金アプリケーションのサンプルを作成してみました。

サンプルを動かしただけだと応用が効かないので、Express Checkoutを使うために読む必要のある以下のドキュメントの内容を簡単にまとめてみました。

PayPal Documentation and Manuals:全マニュアルのリンク集
 https://www.x.com/community/ppx/documentation#ec

Express Checkout Integration Guide:Express Checkoutの概要と実装のスタートガイド、NVP APIの基本的な使い方について説明されています。
https://cms.paypal.com/cms_content/US/en_US/files/developer/PP_ExpressCheckout_IntegrationGuide.pdf

HTML版はもあります。
1.Introducing Express Checkout
https://cms.paypal.com/ca/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_ECGettingStarted
2.Getting Started With Express Checkout
https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_ECSimpleIntegration

Name-Value Pair (NVP) API Developer Guide and Reference: NVPのAPIリファレンス、Integration Wizardで作成したサンプルはNVP APIを利用しています*1。
 https://cms.paypal.com/cms_content/US/en_US/files/developer/PP_NVPAPI_DeveloperGuide.pdf

Express Checkoutとはそもそも何か?

実装の説明の前に、PayPalの決済ソリューションと各APIの関係がいまいち分からなかったので整理してみました。
主なAPIについてのみ解説しています。

Adaptive Payments API

TechCrunchに解説があります。
http://jp.techcrunch.com/archives/20090723the-online-payment-wars-continue-paypal-officially-announces-flexible-api/
Adaptive Payments APIを利用するとPaypalと同様の送金システムを自分のサイト上に構築することができるようです。

Website Payments Standard API

日本のサイトの決済ソリューション一覧では「ウェブ ペイメント スタンダード」と紹介されている機能を提供するAPIです。
PayPalボタンからPayPalの画面のみで支払いが完結する、一番シンプルな実装方法です。

Express Checkout API

ショッピングカートの決済処理を、APIを利用して作る場合はExpress Checkout APIを利用します。
単純な物の売り買いや寄付なら「ウェブ ペイメント スタンダード」でも実装可能ですが、「定期支払い*2」や「リファレンストランザクション」(PayPalの承認が必要)を実装したい場合には、Express Checkout APIで実装する必要があります。

Express Checkoutを実装したサイトの例を動画付きで解説しているページがあったので、参考にさせていただきました。
「PayPal Express Checkout ペイパルのエクスプレスチェックアウトとは?」
http://www.ds-style.com/blog/2009/08/19/paypal-express-checkout/

20110615日追記
定期支払いはウェブペイメントスタンダードでもSubscribeボタンで実装できました。
https://www.paypal.com/cgi-bin/webscr?cmd=_pdn_subscr_techview_outside

Website Payments Pro API

日本のサイトで決済ソリューション「ウェブ ペイメント プラス」と紹介されている機能、Express Checkoutの機能に加えてPayPalの画面もカスタマイズできるようです。

その他、Mobile用のAPIなどがあります。

Express Checkoutの実装の流れ

では、ここから前回のブログで作成したサンプルアプリケーションを例に実装解説をしていきます。

前回のブログで作成したソースコードはGithubを参照ください。
ソースコード:https://github.com/hrendoh/PayPal-Express-Checkout-example

0. NVP APIの基本

PayPal APIはNVP APIとSOAP APIがありますが、今回のIntegration Wizardで作成したサンプルはNVP APIを利用します。
Express Checkout APIを利用するためには、まずNVP APIについて理解しておく必要があります。

NVP APIのリクエスト形式
NVPは、Name Value Pareの略です。つまりAPIの形式はシンプルなクエリーパラメータ形式になります。

FIRSTNAME=Robert&MIDDLENAME=Herbert&LASTNAME=Moore

APIエンドポイント
APIのリクエストURL以下になります。

APIの実行は、このURLに対してパラメータをPOSTします。

API認証パラメータ
APIの認証は、API Signature(署名)またはAPI Certitificate(証明書)の2つの方法がありますが、Integration Wizardで作成したサンプルはSignature(署名)の方を利用を前提としています。

Signatureを利用した認証は、以下のパラメータが必須項目となります。

USER=apiUsername
&PWD=apiPassword
&SIGNATURE=apiSignature 
&VERSION=56.0
  • USER: API ユーザ名
  • PWD: API パスワード
  • SIGNATURE: API 署名
  • VERSION: APIのバージョン

API Signatureの取得は、Sandboxの場合、メニューの[API Credentials]で確認できます。

また、アカウントの画面では以下の手順で確認できます。

  1. [My Account]->[Profile]->[API Access]を開く
  2. Option2の[View API Signature]リンクをクリック

NVP API送信の共通処理
API実行の共通処理はpaypalfunctions.phpに記述されています。
APIの認証パラメータもこのファイルにセットします。

  $API_UserName="";
  $API_Password="";
  $API_Signature="";

...
  function hash_call($methodName,$nvpStr)
  {
    //setting the curl parameters.
    $ch = curl_init();
    ...
    //NVPRequest for submitting to server
    $nvpreq="METHOD=" . urlencode($methodName) . "&VERSION=" . urlencode($version) 
       . "&PWD=". urlencode($API_Password) . "&USER=" . urlencode($API_UserName)
       . "&SIGNATURE=" . urlencode($API_Signature) . $nvpStr . "&BUTTONSOURCE=" . urlencode($sBNCode);

    //setting the nvpreq as POST FIELD to curl
    curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);

    //getting response from server
    $response = curl_exec($ch);
    ...
  }

hash_call関数は、実行するメソッドとメソッドのパラメータを受けて、必須パラメータを追加しAPIのエンドポイントにPOSTリクエストを実行しています。

以降、「Express Checkout Integration Guide」の「2. Getting Started With Express Checkout」の解説を参考に、下図の実装フローをベースに解説していきます。

1. PayPalボタンを配置

まず、カートの最後のページindex.phpでは、SubmitにPayPalボタンの画像を指定しています。

<form action='expresscheckout.php' METHOD='POST'>
  ...
  <input type='image' name='submit' src='https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif' border='0' align='top' alt='Check out with PayPal'/>
</form>

PayPalボタンの作り方は「付録1. PayPalボタンの作り方」を参照ください。

2. SetExpressCheckoutを実行してPayPal画面にリダイレクト

PayPalボタンがクリックされるとexpresscheckout.phpが実行され、その中でPayPalトランザクションを開始します。
PayPalトランザクションを開始するにはSetExpressCheckoutメソッドを呼び出します。

expresscheckout.phpでは、paypalfunctions.phpをインクルードしていますが、このpaypalfunctions.phpにはSetExpressCheckoutAPIをラップするCallShortcutExpressCheckout関数が用意されています。

expresscheckout.phpでは、このCallShortcutExpressCheckout関数を呼び出します。

require_once ("paypalfunctions.php");

$paymentAmount = $_POST["Payment_Amount"];
$currencyCodeType = "USD";
$paymentType = "Sale";
$returnURL = "http://localhost/testpaypal/review.php";
$cancelURL = "http://localhost/testpaypal/index.php";

$resArray = CallShortcutExpressCheckout ($paymentAmount, $currencyCodeType, $paymentType, $returnURL, $cancelURL);
...

以下のコードは、paypalfunctions.phpのCallShortcutExpressCheckout関数の一部です。

function CallShortcutExpressCheckout( $paymentAmount, $currencyCodeType, $paymentType, $returnURL, $cancelURL) 
  {
    $nvpstr="&PAYMENTREQUEST_0_AMT=". $paymentAmount;
    $nvpstr = $nvpstr . "&PAYMENTREQUEST_0_PAYMENTACTION=" . $paymentType;
    $nvpstr = $nvpstr . "&RETURNURL=" . $returnURL;
    $nvpstr = $nvpstr . "&CANCELURL=" . $cancelURL;
    $nvpstr = $nvpstr . "&PAYMENTREQUEST_0_CURRENCYCODE=" . $currencyCodeType;

    ...

    $resArray=hash_call("SetExpressCheckout", $nvpstr);
    $ack = strtoupper($resArray["ACK"]);
    if($ack=="SUCCESS" || $ack=="SUCCESSWITHWARNING")
    {
      $token = urldecode($resArray["TOKEN"]);
      $_SESSION['TOKEN']=$token;
    }
    return $resArray;
  }

CallShortcutExpressCheckout関数では、SetExpressCheckoutメソッドに必要なパラメータを用意しhash_call関数を呼び出しています。
実際に送信されるPOSTパラメータは以下の用な文字列になります。

METHOD=SetExpressCheckout&VERSION=64&PWD=xxxx&USER=shop6_1303088870_biz_api1.gmail.com&SIGNATURE=yyyyyyyy&PAYMENTREQUEST_0_AMT=18&PAYMENTREQUEST_0_PAYMENTACTION=Sale&RETURNURL=http://www.example.com/review.php&CANCELURL=http://www.example.com/index.php&PAYMENTREQUEST_0_CURRENCYCODE=USD&BUTTONSOURCE=PP-ECWizard

以下、SetExcpressCheckoutメソッドの各パラメータについて説明します。

  • PAYMENTREQUEST_0_AMT

金額を指定します。
PAYMENTREQUEST_n_AMTのnは支払いの番号で、0から9まで一度に最大10まで支払いをまとめて行えます。
ドル立て以外の場合はPAYMENTREQUEST_n_CURRENCYCODEを指定する必要があります。円の場合は以下を追加します。
PAYMENTREQUEST_0_CURRENCYCODE=JPY

  • PAYMENTREQUEST_0_PAYMENTACTION

Payment Actionは以下の物を指定します。

Sale: デフォルト、決済処理が終了した時点で、商店側のPayPal口座に送金される。
Authorization: 決済処理終了後、商店がPayPalにログインして回収(Capture)処理をするまで送金されない(Pendingになる)。
Order: Authorizationをされあにまとめて処理できる?ようなことが書いてありますが、PayPal sandboxで動作を確認できなかったので詳細は不明です。

AuthorizationとOrderについては、PayPal利用規約「支払いポリシー」の「XII.マーチャントによる処理遅延の場合の支払い承認」に書いてある内容に該当するようです。
https://cms.paypal.com/jp/cgi-bin/?cmd=_render-content&content_ID=ua/Payments_full&locale.x=ja_JP

ドキュメントもありました(2011年7月1日追記)
https://cms.paypal.com/jp/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_html_authcapture

その他参考:
https://merchant.paypal.com/us/cgi-bin/?&cmd=_render-content&content_ID=developer/e_howto_api_ECSettlements
http://blog.ecommercesoftwaresolutionsonline.com/archives/366/paypal-online-payment-action-sale-authorization.html

  • RETURNURL

購入者がPayPalの画面で支払いを承認した後に戻ってくるURLを指定します。
サンプルでは「http://localhost/testpaypal/review.php"」を指定しています。

  • CANCELURL

購入者がPayPalの画面で支払いを承認しなかった場合に戻ってくるURLを指定します。
サンプルでは適当に「http://localhost/testpaypal/index.php"」を指定しています。

  • API実行

hash_callは上記に説明した通り、APIを利用するために必要なパラメータをさらに追加してPOSTします。

  • PayPalにリダイレクト

リダイレクト先は、APIエンドポイントと同様にSandboxと実際の環境によって異なります。

Sandbox: https://www.sandbox.paypal.com/webscr?cmd=_express-checkout&token=
Live: https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=

パラメータ「token」には、SetExpressCheckoutのレスポンスに含まれる値を指定します。

CallShortcutExpressCheckout関数の戻り値$resArrayの値は以下の様になっています。

array(6) { ["TOKEN"]=> string(20) "EC-6C584982VW639902L" ["TIMESTAMP"]=> string(20) "2011-06-11T03:45:32Z" ["CORRELATIONID"]=> string(13) "39f0cadbd3294" ["ACK"]=> string(7) "Success" ["VERSION"]=> string(2) "64" ["BUILD"]=> string(7) "1882144" }

expresscheckout.phpでTOKENをpaypalfunctions.phpのRedirectToPayPalに渡すとその中で上記のURLにTOKENを追加してリダイレクトしてくれます。

RedirectToPayPal ( $resArray["TOKEN"] );
3. 支払い承認後、GetExpressCheckoutDetails

PayPalの画面で支払いが承認されたら、購入者の詳細情報をGetExpressCheckoutDetailsメソッドで取得します。

PayPal画面で支払いが承認をすると、RETURNURLに指定したreview.phpに戻されます。
review.phpではpaypalfunctions.phpのGetShippingDetails関数を呼び出していますが、この中でGetExpressCheckoutDetailsが実行されます。

function GetShippingDetails( $token )
    {
        $nvpstr="&TOKEN=" . $token;

        $resArray=hash_call("GetExpressCheckoutDetails",$nvpstr);
        $ack = strtoupper($resArray["ACK"]);
        if($ack == "SUCCESS" || $ack=="SUCCESSWITHWARNING")
        {    
            $_SESSION['payer_id'] =    $resArray['PAYERID'];
        } 
        return $resArray;
    }

GetExpressCheckoutDetailsメソッドのパラメータはTOKENのみです。
TOKENの値はPayPalからリダイレクトされるURLのパラメータで返されます。

review.phpでは、ユーザの情報と、合計金額を表示して[Review]ボタンをクリックするとorder_confirm.phpが呼ばれ決済されます。

4. DoExpressCheckoutPayment

支払いを確定してトランザクションを終了するためには、DoExpressCheckoutPaymentメソッドを呼びます。

サンプルでは、order_confirm.phpから呼び出されるpaypalfunctions.phpのConfirmPayment関数の中でDoExpressCheckoutPaymentの処理が記述しています。

function ConfirmPayment( $FinalPaymentAmt )
    {
        //Format the other parameters that were stored in the session from the previous calls    
        $token                 = urlencode($_SESSION['TOKEN']);
        $paymentType         = urlencode($_SESSION['PaymentType']);
        $currencyCodeType     = urlencode($_SESSION['currencyCodeType']);
        $payerID             = urlencode($_SESSION['payer_id']);

        $serverName         = urlencode($_SERVER['SERVER_NAME']);

        $nvpstr  = '&TOKEN=' . $token . '&PAYERID=' . $payerID 
       . '&PAYMENTREQUEST_0_PAYMENTACTION=' . $paymentType . '&PAYMENTREQUEST_0_AMT=' . $FinalPaymentAmt;
        $nvpstr .= '&PAYMENTREQUEST_0_CURRENCYCODE=' . $currencyCodeType . '&IPADDRESS=' . $serverName; 

        $resArray=hash_call("DoExpressCheckoutPayment",$nvpstr);

        $ack = strtoupper($resArray["ACK"]);

        return $resArray;
    }
  • TOKEN

PayPalからリダイレクトされるURLのパラメータに含まれます。
review.phpで取得した値を指定します。

  • PAYERID

購入者のIDです。この値もreview.phpにPayPalからリダイレクトされた際のURLのパラメータに含まれます。

  • PAYMENTREQUEST_0_AMT

SetExpressCheckoutのパラメータと同様です。
確定した金額をしています。

  • PAYMENTREQUEST_0_CURRENCYCODE

SetExpressCheckoutのパラメータと同様です。
確定した金額の通貨をしていします。

  • IPADDRESS

購入者のブラウザのIPアドレスを指定します。

サンドボックスでテストした場合の処理フロー

以上で、基本的なExpress Checkoutを実装した前回のブログのサンプルの解説は以上になります。
Sandboxを利用した場合の処理フローは以下の様になります。

https://www.x.com/docs/DOC-1326

付録 PayPalボタンの作り方

PayPalボタンについては、以下に解説があります。
https://www.paypal.com/jp/cgi-bin/webscr?cmd=xpt/Merchant/merchant/ExpressCheckoutButtonCode-outside
ペイパルボタンのURLは「https://www.paypal.com/ja_JP/i/btn/btn_xpressCheckout.gif」です。


URLの国コード「ja_JP」の部分を「en_US」に替えると英語のボタンになります。


またPayPal支払いとクレジットカード支払いのどちらかを選択できる用にする場合はペイパルマークを使用します。

安全・簡単にお支払い

*1:PayPal APIはNVP形式とSOAP形式があります

*2:定期支払いはウェブペイメントスタンダードでも可能でした。