PayPalのIn-Context CheckoutをRestAPIで再現する

[PayPalのエクスプレスチェックアウトをRestAPIで再現する](http://qiita.com/keigohtr/items/61cfb9a6ac3d924959ee)の続編。

## はじめに
PayPalが新しい機能をリリースしたという情報を頂いたので、さっそく使ってみる。新しい機能は[In-Context Checkout](https://developer.paypal.com/docs/classic/express-checkout/in-context/)と言って、Express Checkoutと違って自分のサイト内で決済ができる。Express Checkoutからの変更は簡単ということ（[参照](https://developer.paypal.com/docs/classic/express-checkout/in-context/integration/#advanced-settings)）だったが、予想通り簡単じゃなかった。

## 公式の手順
Express Checkoutを既に使っていれば、以下の２つを変更・追記するだけで完了する。
- Update your redirect URL to: https://www.paypal.com/checkoutnow/.
- Include the basic integration checkout.js.

## 実際の手順
（将来的に使わなくなると言われている）ClassicAPIは使いたくないので、今回もRestAPIでやってみた。苦労してなんとか動作確認も出来たが、In-Context Checkoutの正しい使い方じゃないかもしれない。

とりあえず、新しいライブラリが出てたのでアップデートする。たぶん、今回の件には関係がない。

```
<dependency>
  <groupId>com.paypal.sdk</groupId>
  <artifactId>rest-api-sdk</artifactId>
  <version>1.4.2</version>
</dependency>
```

それで、最初から躓く。
「すいません。`your redirect URL`って何でしょう？」

ここから回答編。
[前回の記事](http://qiita.com/keigohtr/items/61cfb9a6ac3d924959ee)でこのようなコードを書いた。

```
Payment createdPayment = payment.create(apiContext);
for (Links links : createdPayment.getLinks()) {
  if (links.getRel().equals("approval_url")) {
    return "redirect:"+links.getHref();
  }
}
```

この`approval_url`の`links.getHref()`こそが`your redirect URL`である。すなわち
`return "redirect:https://www.paypal.com/checkoutnow/"`
とすれば良いのである・・・と思いきや、ここにも落とし穴がある。これではダメなのだ。

そもそも、`approval_url`の`links.getHref()`には`token=EC-xxxxxx`というリクエストパラメータが含まれている。このリクエストパラメータをIn-Context CheckoutのAPIエンドポイントに含める必要があるのだ。ちなみにこの情報は公式には載っていない（はず）。PayPalが提供している[デモ](http://plnkr.co/edit/3vfNSVRyq86pDR5mH4HH?p=preview)を実際に動かして、そのリクエストパラメータを調査して見つけ出した。

実際に動かせるコードは以下になる。

```
Payment createdPayment = payment.create(apiContext);
for (Links links : createdPayment.getLinks()) {
  if (links.getRel().equals("approval_url")) {
    String tmp = links.getHref();
    tmp = tmp.replace("https://www.sandbox.paypal.com/cgi-bin/webscr", "https://www.sandbox.paypal.com/checkoutnow"); //sandbox用。本番では"sandbox"を取る。
    return "redirect:"+links.getHref();
  }
}
```

これだと`EC-xxxx`以外に余計なものも送ってしまうのだが、`EC-xxxx`だけ取り出せるようになっていないし、パースするの面倒なのでこうした。ちゃんと動くからいいでしょ。ちなみに、残りは前回の記事と同様で良い。

あとは対応するHTMLに以下を追記する。

```
<script>
  window.paypalCheckoutReady = function () {
    paypal.checkout.setup('Your-Merchant-ID', {
        environment: 'sandbox',
        button: 'paypalButton'
      });
  };
</script>
<script src="//www.paypalobjects.com/api/checkout.js" async="async"></script>
```

私は`button`をsubmit属性にしているのでこのようになるが、`form`や`a`を使っている場合はやり方が変わる。詳しくは公式を参照（ここはちゃんと情報あるよ、少なくともbuttonとformとaは）。`Your-Merchant-ID`は[PayPalのアカウント](https://www.paypal.com/)にログインして、「個人設定」を押下すればページの下の方で確認できる。本番では`environment: 'sandbox',`を削除する。


## さいごに
個人的にイケてないと思う所（素人目線）を挙げる。

言わずもがな、やはり公式の通りにやってもうまくはいかなかった。Classic APIユーザーだとすんなりいくのかもしれない。最近PayPalは長年のユーザーの不満（API関係の情報のわかりにくさ等）を解消しようと色々と努力しているらしい。今回の場合、王道を使っていなかった私に問題があるかもしれない。

個人的に、Javascriptに`environment: 'sandbox'`とわざわざ書くのはイケてないと思う。Javaプログラムの方は設定ファイルでsandboxと本番を簡単に切り替えられるように実装できるが、Javascriptはわざわざ書きなおさなければいけない。sandboxと本番の切り替えをする際、なるべく編集するところは少なくしたい。ただ、前述のとおり、もしかしたら私のIn-Context Checkoutの使い方が間違っているのかもしれない。・・・が、少なくとも私の実装方法においては`environment`の存在意義はないし、もっと言うと`Your-Merchant-ID`も不要である。あくまで素人意見です。

In-Context Checkoutについてはポップアップ型のチェックアウトということなので、たしかにその通りに動作する。Express Checkoutとの違いはポップアップするかどうかである。・・・たぶん、この微妙な差が購買活動において大きな差を生むのだと思う。そんな記事か論文を読んだことがある。個人的には、苦労して実装したもののUXの違いが微々たるものだったので感動はあまりなかった。・・・が、売上が上がれば正義なので、売上向上の役に立って欲しい（そもそも何も売ったことないので比較はできないのだけど）。