少しのコードでWebPayを導入する Python Ver.

# 更新のおしらせ

本記事はwebpay-pythonのバージョン1系(できたて)に即して記述しています。
その後、メジャーバージョンアップを行いました。

ほとんどの内容はそのまま利用できますが、メソッド名などが一部変更になっています。
最新の情報は[WebPay公式サイトのPython APIドキュメント](https://webpay.jp/docs/api/python)を参照してください。

また、メジャーバージョンアップに合わせてgithub上のリポジトリは更新を停止しました。
ライブラリ情報は[ライブラリドキュメント](https://webpay.jp/docs/libraries#python)をご覧ください。

<hr>

WebPayアドベントカレンダーも後半戦に突入しました。じわりじわりと増える皆様のストック数を励みに頑張っております。

今日は「少しのコードで[WebPay](https://webpay.jp)を導入する」シリーズです。

これまで[Ruby](http://qiita.com/hmsk/items/744f9a7e37638340a992)、[PHP](http://qiita.com/sowawa/items/576930dbb175e8b83ba5)バージョンが登場していましたが、満を持して登場するのはPythonバージョンです。しかも、しかも、なんとですね、動かす環境にはGoogle App Engineを使ってみました。

昨今ではたくさんのPaaSが世の中を賑わせていて、便利なプログラミング環境が溢れているのでGAEなんて忘れてしまった人もいると思いますが、GAEは老舗の中の老舗ともいえる歴史あるPaaSです。たまにはGAEのことも思い出してあげてくださいね。

# webpay-python

WebPayの公式Pythonライブラリ([webpay-python](https://github.com/webpay/webpay-python))がリリースされました！

**祝**リリース

さて、このPythonライブラリを使ってGAE上に爆速でWebPayを導入していきましょう。

# webpay meets GAE

さっそくプログラミングを開始しましょう。GAEの大きな特徴はローカル開発向けのSDKが提供されていて、GAEの環境をローカルに再現できるところです。しかし、環境がプリセットされている反面、GAEが提供しているライブラリやバージョンに制限があるため自由にライブラリを読み込んで使うことができません。基礎的なフレームワークであればメジャーバージョンがサポートされていますが、決済ゲートウェイのライブラリなどはもちろん組み込まれていません。

今どきのプログラマーの皆さんは、車輪の再発明や自由にライブラリが使えない世界なんて耐え難い世界だと思います。私だって耐えれません。

そこでGAEで外部ライブラリを使うときのポイントも一緒に解説していくのでぜひ参考にしてください。

今回はGAEに組み込まれている`webapp2`と外部ライブラリとして`webpay-python`を利用します。

# SDKをインストールする

手元にMervericsのMacをお持ちの方であれば、
[GAE SDK](https://developers.google.com/appengine/downloads?hl=ja&csw=1)から`GoogleAppEngineLauncher-1.8.8.dmg`をダウンロードして、開いたファイル（GoogleAppEngineLauncher.app）をApplicationフォルダに配置するだけでオッケイです。GoogleAppEngineLauncher.appを起動するとGAEのローカル開発環境用のpythonスクリプトを`/usr/local/bin`にインストールしてくれます。

# PythonからWebPayを使う

プロジェクト用に適当なディレクトリを用意します。そこにapp.yamlとappengine_config.pyを用意します。下のようなディレクトリ構成になっていると思います。

```
webpay-sample
├── app.yaml
└── appengine_config.py
```

app.yamlの内容は、

```app.yaml
application: webpay-sample
version: 1
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /.*
  script: main.app
```

このように`runtime`には`python27`を設定しておきましょう。GAEも2.7の時代へと移ってきています。applicationにはGAEの[ダッシュボード](https://appengine.google.com/)で作成したapplication_idを指定しましょう。ローカルだけで試す場合はGAEのダッシュボードでアプリケーションの作成は不要です。threadsafeのパラメータは、昔GAEを使っていた人には馴染みが無いかもしれませんが、python27が使えるようになってからは明示的に指定するようになりました。（本題からそれるので詳しく解説しませんが、`threadsafe: true`と設定するとprint等で標準出力を使ってクライアントにデータを返すことができなくなります。）

次は、`appengine_config.py`です。

```appengine_config.py
import os
import sys
ROOTPATH = os.path.dirname(__file__)
LIBPATH = os.path.join(ROOTPATH, 'lib')
sys.path.append(LIBPATH)
```

appengine_config.pyは特別なファイルで、プロジェクト内で共通して使われるような設定やライブラリパスの設定などに使います。今回は外部ライブラリを`lib`以下に保存するので、`lib`ディレクトリをライブラリパスに追加します。

いよいよメインのプログラム部分を作成します。今回は、`app.yaml`で`script: main.app`と指定したので、`main.py`というファイル名で作成しましょう。加えて、`main.py`で読み込むテンプレートとして`index.html`と`succeeded.html`の2つのファイルを用意します。

```
webpay-sample
├── app.yaml
├── lib
├── main.py
├── index.html
├── succeeded.html
└── appengine_config.py
```

それぞれのファイルを見てみましょう。

```main.py
# -*- coding: utf-8 -*-
import os
import webapp2
from google.appengine.ext.webapp import template
from webpay import WebPay

SECRET_KEY = 'test_secret_eHn4TTgsGguBcW764a2KA8Yd'
PUBLIC_KEY = 'test_public_19DdUs78k2lV8PO8ZCaYX3JT'

class MainPage(webapp2.RequestHandler):
  def get(self):
      template_values = {
        'public_key': PUBLIC_KEY
      }
      path = os.path.join(os.path.dirname(__file__), 'index.html')
      self.response.out.write(template.render(path, template_values))

  def post(self):
    amount = self.request.POST.get('amount')
    token  = self.request.POST.get('webpay-token')
    webpay = WebPay(SECRET_KEY)
    try:
      # webpay-pythonライブラリを利用したWebPayへのアクセス
      charge = webpay.charges.create(
        amount=amount,
        currency="jpy",
        card=token
      )
      template_values = {
        'charge': charge
      }
      path = os.path.join(os.path.dirname(__file__), 'succeeded.html')
      self.response.out.write(template.render(path, template_values))
    except webpay.errors.CardError, e:
      # カードが拒否された場合
      self.response.headers['Content-Type'] = 'text/plain'
      self.response.out.write("CardException")
      self.response.out.write("Status is: %d" % e.status)
      self.response.out.write("Type is: %s" % e.type)
      self.response.out.write("Code is: %s" % e.code)
      self.response.out.write("Param is: %s" % e.param)
      self.response.out.write("Message is: %s" % e)
    except webpay.errors.InvalidRequestError, e:
      # リクエストで指定したパラメータが不正な場合
      self.response.headers['Content-Type'] = 'text/plain'
      self.response.out.write("InvalidRequestException")
    except webpay.errors.AuthenticationError, e:
      # 認証に失敗した場合
      self.response.headers['Content-Type'] = 'text/plain'
      self.response.out.write("AuthenticationException")
      pass
    except webpay.errors.ApiConnectionError, e:
      # APIへの接続エラーが起きた場合
      self.response.headers['Content-Type'] = 'text/plain'
      self.response.out.write("APIConnectionException")
      pass
    except webpay.errors.WebpayError, e:
      # WebPayのサーバでエラーが起きた場合
      self.response.headers['Content-Type'] = 'text/plain'
      self.response.out.write("APIException")
      pass
    except Exception, e:
      self.response.headers['Content-Type'] = 'text/plain'
      self.response.out.write("Unexpected exception")

app = webapp2.WSGIApplication([('/', MainPage)],
                              debug=True)
```

main.pyは`MainPage`クラスに`get`と`post`メソッドを実装した`webapp2`アプリです。

1つ目の`get`メソッドでは、`path = os.path.join(os.path.dirname(__file__), 'index.html')`でテンプレートのパスを作成して`self.response.out.write(template.render(path, template_values))`でhtmlをレンダリングしています。[CheckoutHelper](https://webpay.jp/docs/checkout)で使う`public_key`はテンプレート変数としてアサインしておきます。

```python
      charge = webpay.charges.create(
        amount=amount,
        currency="jpy",
        card=token
      )
```

2つ目の`post`メソッドでは、上に示している`webpay.charges.create()`を使って課金処理を行っています。[CheckoutHelper](https://webpay.jp/docs/checkout)で作ったトークンがクライアントから送られてくるので`token  = self.request.POST.get('webpay-token')`のようなコードでPOSTされた値を取得します。

最後に`index.html`と`succeeded.html`のテンプレートの中身を確認しましょう。`index.html`では、[Ruby](http://qiita.com/hmsk/items/744f9a7e37638340a992)や[PHP](http://qiita.com/sowawa/items/576930dbb175e8b83ba5)のアドベントカレンダーの時と同様に、カード番号を入力させるためのダイアログを表示させる[CheckoutHelper](https://webpay.jp/docs/checkout)というJavascriptのライブラリを利用しています。

```index.html
<html>
  <head>
    <meta charset="utf-8">
    <title>WebPay Google App Engine Python sample</title>
  </head>
  <body>
    <h1>WebPay Google App Engine Python sample</h1>
    <form action="/" method="post">
      <input type="number" name="amount" value="300" /> 円を支払います。<br />

<!-- 御自身のサーバにクレジットカード情報を送信すると、クレジットカード情報を適切に扱う義務が生じます。
     JavaScript を利用して webpay token を生成することで、クレジットカード情報を直接あつかわずに済みます。
     webpay-token という name を持つ input が自動的に追加されます。 -->
      <script src="https://checkout.webpay.jp/v1/" class="webpay-button"
              data-text="カード情報を入力して支払う"
              data-key="{{ public_key }}"></script>
    </form>
  </body>
</html>
```

`succeeded.html`は結果を表示するだけのシンプルなテンプレートです。

```succeeded.html
<html>
  <head>
    <meta charset="utf-8">
    <title>WebPay PHP sample</title>
  </head>
  <body>
    <h1>お支払いありがとうございました</h1>
    <ul>
      <li>お支払い金額: {{charge.amount}}</li>
      <li>カード名義: {{charge.card.name}}</li>
      <li>カード番号: ****-****-****-{{charge.card.last4}}</li>
    </ul>
  </body>
</html>
```

ここまでで、プログラミングは終了です。

さて、いよいよライブラリの組み込みを行いましょう。

pythonのライブラリはpipやeasy_installで管理することが一般的です。しかし、それは通常のPython環境の場合であってGAE環境では異なります。今回は最初に作成した`lib`ディレクトリに`webpay-python`とその依存ライブラリを配置しましょう。

まずライブラリを`git clone`します。（別の方法でライブラリを手元に用意してもいいです。 zipとかeggとか。）

```
mkdir tmp && cd tmp
git clone git@github.com:webpay/webpay-python.git
git clone https://github.com/kennethreitz/requests.git
```

cloneが完了したらライブラリをbuildします。buildが終わったら以下の様に`lib`ディレクトリにbuild済みのファイルを移動します。

```
cd webpay-python
python setup.py build
cd ../requests
python setup.py build
cd ../../
mv tmp/webpay-python/build/lib/webpay lib/
mv tmp/requests/build/lib/requests lib/
```

最終的には以下の様なディレクトリ構成になっていると思います

```
webpay-sample
├── app.yaml
├── lib
    ├── webpay
    └── requests
├── tmp
├── main.py
├── index.html
├── succeeded.html
└── appengine_config.py
```

ではローカル開発環境で動かしてみましょう。`webpay-sample`ディレクトリの中で以下のコマンドを実行します。

```bash
dev_appserver.py .
```

http://localhost:8080/ へアクセスしてみましょう。

どうですか？表示されましたか？

うまく表示された人は、Google App Engineにデプロイしましょう。

```bash
appcfg.py update .
```

デプロイが終われば

https://webpay-sample.appspot.com/

のようなページが見えていると思います。rubyやphpの記事に比べると少し分量が多くなってしまいましたが、簡単かつ誰でも使うことができる代表的なPaaSであるGAEでも公式ライブラリを使ってWebPayを導入できることを体験して頂けたのではないでしょうか。

# おわりに

クラウド時代の幕開けとなった懐かしのGAEでもWebPayを動かすことが出来ましたね。