決済処理をサーバレスアーキテクチャで実装する

## 概要
[会員登録機能をサーバレスアーキテクチャで実装する](http://qiita.com/horike37/items/6f2575d6a061216fe019)
[ログイン・ログアウト機能をサーバレスアーキテクチャで実装する](http://qiita.com/horike37/items/dc81442d5d1b8ea89325)
に続いて今回は決済機能をサーバレスアーキテクチャで実装します。

## アーキテクチャ
決済はPayPalの定期購読処理を使います。PayPal APIとのやり取りをLambdaで実装する形です。
![決済.png](https://qiita-image-store.s3.amazonaws.com/0/65478/9d4144b7-2984-4af7-eb76-ec380bba8a11.png)

## PayPal APIとのやり取りの流れ
- 注文画面でSetExpressCheckoutリクエストを送信
- SetExpressCheckoutで作られたトークンを保存して、注文内容の確認画面にリダイレクト
- ユーザが注文を確定するとCreateRecurringPaymentsProfileを使用して定期購読
![PayPalAPI.png](https://qiita-image-store.s3.amazonaws.com/0/65478/67cfae0f-ec86-b7df-dbb3-c151d6141264.png)

## SetExpressCheckout
[paypal-ec](https://www.npmjs.com/package/paypal-ec)のnodeモジュールを使用します。注文リクエストがユーザから送られるとAPI Gatewayを通してこのLambdaファンクションに処理を投げます。

```js:SetExpressCheckout.js
var cred = {
  username  : '<APIユーザ名>',
  password  : '<APIパスワード>',
  signature : '<API署名>'
};

var opts = {
  sandbox : true,
  version : '124.0'
};

var PayPalEC = require( 'paypal-ec' );
var ec       = new PayPalEC( cred, opts );


exports.handler = function(event, context) {
  var params = {
    returnUrl : '<注文確認画面のURL>',
    cancelUrl : '<キャンセルされた時のリダイレクト先>',
    BILLINGTYPE : 'RecurringPayments',
    BILLINGAGREEMENTDESCRIPTION : 'elasticommerceservices'
  };

  ec.set( params, function ( err, data ){
    if (err) {
    	context.fail(err);
    } else {
    	context.succeed(data);
    }
  });
};
```

## CreateRecurringPaymentsProfile
注文確認画面でユーザが最終的に購入を決定すればこのAPIに処理をなげて定期購読を確定させます。
SetExpressCheckoutで発行したTokenを渡す必要があります。

```js:CreateRecurringPaymentsProfile.js
var cred = {
  username  : '<APIユーザ名>',
  password  : '<APIパスワード>',
  signature : '<API署名>'
};

var opts = {
  sandbox : true,
  version : '124.0'
};

var PayPalEC = require( 'paypal-ec' );
var ec       = new PayPalEC( cred, opts );


exports.handler = function(event, context) {
  var params = {
    TOKEN : event.token,
    PROFILESTARTDATE : '2016-7-1T00:00:00Z',
    DESC : 'elasticommerceservices',
    BILLINGPERIOD : 'Month',
    BILLINGFREQUENCY : 1,
    AMT : 1,
    CURRENCYCODE : 'JPY'
  };

  ec.create_rpp( params, function ( err, data ){
    if (err) {
    	context.fail(err);
    } else {
    	context.succeed(data);
    }
  });
};
```
## ユーザ画面
ユーザ画面側にAPIを埋め込みます。以下はwebサイトを想定してJavaScriptで処理させています。

``` html:order.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <script src="https://code.jquery.com/jquery-2.2.3.min.js"   integrity="sha256-a23g1Nt4dtEYOj7bR+vTu7+T8VP13humZFBJNIYoEJo="   crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.js"></script>
<script type="text/javascript">
  jQuery(document).ready(function($){
	  if ( !$.cookie('serverless_website_session_id') ) {
	    location.href = "/login";
	  }
	
	  $("#buy").on( "click", function(){
	    var data = { 
				token:$.cookie('serverless_website_token_id')
		      }
		$.ajax( {
			    url:'<API Gateway エンドポイント>',
			    method: "POST",
			    crossDomain: true,
			    data: JSON.stringify(data),
			    success: function(response) {
			      console.log(response);
			      if ( response.ACK === 'Success' ) {
			        $("#message").text('購入完了しました')
			      }
			    }
			  });
	  } );
	});
</script>
    </script>
  </head>
  <body>
    <h1>購入確認画面</h1>
    <p id="message">購入処理進めますけど、よろしいですか？よろしければ「はい」を押してください</p>
    <p ><input type="button" id="buy" value="はい" /></p>
  </body>
</html>
```

## 結果
出来たAPIをそれぞれ画面に配置して動かした結果、以下のようにPayPalで定期購読が完了しました。
<img width="630" alt="スクリーンショット 2016-04-17 13.54.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/65478/61bcf9ec-2476-2d4b-c891-4799ec6923f2.png">

され、これでサーバレスアーキテクチャで会員管理、ログイン、ログアウト、決済の処理を作ることが出来ました。これで激安ECサイトとか作れたり出来そうです。