PayPal APIをcakePHPで使う
PayPal APIに関する日本語の情報は少ないから頑張ってイングリッシュを読みながら勉強する。
classic apiとrest apiというのがあるが名前的にrest apiを使いたい。japanもPayPal Account Paymentsに対応できているらしいのでrest apiを勉強していこうと思う。
REST APIsというところに、マニュアルというかチュートリアル的な情報がのっているようだ。
RestApiはOauth2.0をつかっている。まずはAccessTokenをゲットする必要がある。サンプルはcurlで書いてある。curlの使い方はここに書いてある。ちなみにcakePHPのこんな記事もあった。ひととおりPayPalのサイトで勉強したら読んでみよう。
ちなみに、PayPalのエクスプレスチェックアウトというのは、下記のようなフローになっているらしい。このページわかりやすいな。 
AccessTokenのゲット
access tokenは簡単にゲットできる。cakePHPのHttpSocketを使ってゲットすると下記のような感じになる。
public $paypal_info = array( 'endpoint' => 'https://api.sandbox.paypal.com/', 'client_id' => 'クライアントID', 'secret' => 'シークレット',);
public function get_access_token(){ $url = $this->paypal_info['endpoint'] . 'v1/oauth2/token'; $request = array( 'header' => array( 'Accept' => 'application/json', 'Accept-Language' => 'en_US', ), ); $data = 'grant_type=client_credentials'; $http = new HttpSocket(); $http->configAuth('Basic', $this->paypal_info['client_id'], $this->paypal_info['secret']); $response = $http->post($url, $data, $request); if($response->isOk()){ $body = json_decode($response->body()); $access_token = $body->access_token; $this->Session->write('paypal_access_token', $access_token); $this->set(compact('access_token')); }}アクセストークンをゲットしたら、決済できるようになる。ここのMake the API callというのをしてみる。
Make the API call
public function hoge(){ $access_token = $this->Session->read('paypal_access_token'); if(! $access_token) return;
$url = $this->paypal_info['endpoint'] . 'v1/payments/payment'; $request = array( 'header' => array( 'Content-Type' => 'application/json', 'Authorization' => 'Bearer ' . $access_token, ), ); $data = array( 'intent' => 'sale', 'redirect_urls' => array( 'return_url' => 'http://example.com/your_redirect_url/', 'cancel_url' => 'http://example.com/your_cancel_url/' ), 'payer' => array( 'payment_method' => 'paypal' ), 'transactions' => array(array( 'amount' => array( 'total' => '7.58', 'currency' => 'USD' ), 'description' => 'This is the payment transaction description.' )) ); $http = new HttpSocket(); $response = $http->post($url, json_encode($data), $request); $this->set(compact('response'));}なんとこんな豪華なマニュアルを発見した。しかし、これはどうもRestApiじゃないみたいんだな。NVP APIって書いてあるな。クラシックAPIとかあるしAPIが沢山あって困るわ。まあでもRestAPIでも同じような流れでやれるということだろう。
さて、上記を実行すると、こんなものが返ってくる
stdClass Object( [id] => PAY-7X444568MY9201029KIPB4MI [create_time] => 2013-08-28T15:58:41Z [update_time] => 2013-08-28T15:58:42Z [state] => created [intent] => sale [payer] => stdClass Object ( [payment_method] => paypal )
[transactions] => Array ( [0] => stdClass Object ( [amount] => stdClass Object ( [total] => 7.58 [currency] => USD [details] => stdClass Object ( [subtotal] => 7.58 )
)
[description] => This is the payment transaction description. )
)
[links] => Array ( [0] => stdClass Object ( [href] => https://api.sandbox.paypal.com/v1/payments/payment/PAY-7X444568MY9201029KIPB4MI [rel] => self [method] => GET )
[1] => stdClass Object ( [href] => https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-4E796703EY174481M [rel] => approval_url [method] => REDIRECT )
[2] => stdClass Object ( [href] => https://api.sandbox.paypal.com/v1/payments/payment/PAY-7X444568MY9201029KIPB4MI/execute [rel] => execute [method] => POST )
)
)paypalはお会計的何かをつくってくれたようだ。作った中身とおそらく次ぎに進むべきリンクをつくって返してくれたんじゃないでしょうか?この次に進んで行くフローは上記のエクスプレスチェックアウトと同じか似てるはずだと思っています。3つのリンクをcakePHPに取り込んでアクセスしてみよう。approval_urlはアクセスするとpaypalログインして支払い方法とか住所とかの確認があり、設定したリダイレクト先にリダイレクトされるが、それ以外はアクセスしても真っ白なページであり、参考にならない。
Accept a PayPal paymentにやり方が書いてある。3ステップある。最初に決済情報をつくって、その後でuserに承認してもらって、最後に決済を実行するのだ。上記でやっていたのは決済情報をつくっていたので、承認してもらうとreturn_urlに戻ってくるが、その際に色々パラメタがくっついてくる。そこにuserを特定するpayer_idというのもくっついてくるので、これと一緒にexecuteすれば動きそうだ。
実際のPaypal決済しかできないカートの動きを考えると、カートに入れて、購入ボタンを押すと、内部でcreateされて、得られたapproval_urlにリダイレクトさせて、(リダイレクトする前にexecute_urlをセッションとかに入れておくのかも)、返ってきたらpayer_idを記録しつつ、最終確認画面を表示して、確定ボタンを押したらexecuteするみたいな感じになるのだろうか。どこかでサイトのログインユーザ情報とがっちゃんこしたりする必要もあるし、approvlが終了した後に、paypalでログインした、名前、住所、メールなどについて情報を得る必要があるはずである。そういうメソッドを探してみよう。
Look up a saleをすれば、URLは後からでもゲットできるっぽい。saleのIDをしっかりもっておけばいいのかな。Get user informationというのがあるみたいだから、やっぱゲットできるみたいだな。でもAPIみてもぱっとみよくわからない。
さて、ということで、とりあえずexecuteしてみよう。
public function execute(){ if(isset($this->request->query['PayerID'])){ $payer_id = $this->request->query['PayerID'];
$access_token = $this->Session->read('paypal_access_token'); $url = $this->Session->read('paypal_execute_url'); $request = array( 'header' => array( 'Content-Type' => 'application/json', 'Authorization' => 'Bearer ' . $access_token, ), );
$data = array('payer_id' => $payer_id);
$http = new HttpSocket(); $response = $http->post($url, json_encode($data), $request);
$this->set(compact('response'));
}}