WebPay Extend

WebPay ExtendはWebPayの提供するOAuth2機能です。 WebPay Extendを利用したアプリケーション(Extendアプリケーションと呼称します)では、他のWebPayのユーザの操作を代行することができます。

Extendアプリケーションを作成する

WebPay Extendを利用するには、アプリケーションの情報をWebPayに登録し、他のユーザから参照できるようにする必要があります。

  • ユーザ設定の下部「Extendアプリケーション管理」の項目から「Extendアプリケーションを追加する」を選択してください。
  • 「名前」には作成するExtendアプリケーションの名前を設定してください。
  • 「リダイレクト先URL」はWebPayのユーザがExtendアプリケーションを認可した後に、ブラウザ上でリダイレクトされる先のURLです。GETリクエストが受け取れるURLを指定してください。開発中は urn:ietf:wg:oauth:2.0:oob を指定しておくと、リダイレクトがおこなわれず認可した時に発行されるcodeを画面で見られます。 localhost など外部から参照できないアドレスも指定できます。
  • 「Webhook URL」は登録したユーザのアカウントで発生したイベントをWebhookで受け取りたい場合に指定する任意項目です。 利用しない場合は空欄のままにしてください。 このURLはWebPayのWebhookを処理するワーカから送信可能なアドレスである必要があるので、 localhost などを指定しても動作しません。ngrokなどのサービスを利用することでWebhookをローカルのサーバで受け取ることができます。
  • 無事にExtendアプリケーションが作成できると、アプリケーションを識別するための"client_id"と"client_secret"が表示されます。 これらは外部に公開しないよう注意してください。
次に、作成したExtendアプリケーション情報を用いて自分のWebPayのアカウントから認可してみましょう。

認可のフロー

通常はWebPayのユーザがあなたのExtendアプリケーションを認可(authorize)しますが、まずは認可する手順を実装する必要があります。 まずは認可フローのみを実装したExtendアプリケーションを作成し、自分のアカウントから認可してみましょう。

OAuth2の認可のフローは下図のようになります(RFC 6749より引用)。 WebPay Extendでは図中のそれぞれが次のように対応します。

Resource Owner
Extendアプリケーションを利用するユーザ
User-Agent
Extendアプリケーションを利用するユーザのブラウザ
Client
あなたの作成するExtendアプリケーション
Authorization Server
WebPay

  +----------+
  | Resource |
  |   Owner  |
  |          |
  +----------+
       ^
       |
      (B)
  +----|-----+          Client Identifier      +---------------+
  |         -+----(A)-- & Redirection URI ---->|               |
  |  User-   |                                 | Authorization |
  |  Agent  -+----(B)-- User authenticates --->|     Server    |
  |          |                                 |               |
  |         -+----(C)-- Authorization Code ---<|               |
  +-|----|---+                                 +---------------+
    |    |                                         ^      v
   (A)  (C)                                        |      |
    |    |                                         |      |
    ^    v                                         |      |
  +---------+                                      |      |
  |         |>---(D)-- Authorization Code ---------'      |
  |  Client |          & Redirection URI                  |
  |         |                                             |
  |         |<---(E)----- Access Token -------------------'
  +---------+       (w/ Optional Refresh Token)

Extendアプリケーションは

  • A. 認可を開始するリダイレクト処理
  • C. 認可されたときに生成されるgrant codeを受け取るコールバック
  • D,E. codeからaccess tokenを取得する処理
を実装する必要があります。

次のコードはRubyのOAuth2クライアントライブラリであるoauth2 gemとHTTPサーバ機能を提供するSinatra gemを使って上述のフローを実装したものです。 本質的なフローのみを解説するためにサニタイズやエラーハンドリングを省略している部分があります。 実際のExtendアプリケーションを作成する際は各言語のライブラリを適切に利用し、安全な実装を行ってください。

require 'sinatra'
require 'oauth2'
enable :sessions

# Extendアプリケーションの情報を持つクライアントオブジェクトを作成
client = OAuth2::Client.new('CLIENT_ID_HERE', 'CLIENT_SECRET_HERE', site: 'https://webpay.jp')

get '/' do
  '<a href="/request">テストのExtendアプリケーションを認可する</a>'
end

# A. 認可リクエストの開始
get '/request' do

  # CSRF 対策 (http://tools.ietf.org/html/rfc6749#section-10.12)
  oauth_session_id = SecureRandom.hex(32)
  session[:oauth_session_id] = oauth_session_id

  # response_type, client_id, redirect_uri, scope, state を指定して UA をリダイレクト
  # http://tools.ietf.org/html/rfc6749#section-4.1.1
  redirect to(client.auth_code.authorize_url(redirect_uri: to('/callback'), scope: 'read test', state: oauth_session_id))
end

# C. 認可コードの受取
get '/callback' do
  if session[:oauth_session_id].nil? || params[:state] != session[:oauth_session_id]
    return '認可に失敗しました'
  end

  # code をもとに access token を取得
  # http://tools.ietf.org/html/rfc6749#section-4.1.3
  code = params[:code]
  token = client.auth_code.get_token(code, redirect_uri: to('/callback'))

  # 結果を表示
  token.params.inspect
end

認可に成功すると、Sinatraアプリケーションがアクセストークンの内容を表示します。WebPay Extendのアクセストークンは次の情報を含みます。

access_token
OAuthのアクセストークンです。アプリケーションでは通常利用しません
token_type
つねに"bearer"です
scope
認可リクエスト時に要請し、ユーザが許可したscopeを示します。詳細はスコープについてを見てください。
webpay_user_id
WebPayのアカウントIDです。"acct_"で始まる文字列です
test_secret_key
通常のテスト環境用非公開鍵に相当するものですが、scopeに応じて一部の操作が制限されます。"oauth_test_secret_"で始まる文字列です
test_publishable_key
通常のテスト環境用公開可能鍵に相当するものです。 "read_write"のscopeでのみ与えられます。 与えられない場合はキーが存在しません。 "oauth_test_public_"で始まる文字列です
live_secret_key
通常の商用環境用非公開鍵に相当するものです。"live"のscopeで、かつ認可したユーザが商用環境を利用中の場合のみ与えられます。"oauth_live_secret_"で始まる文字列です
live_publishable_key
通常の商用環境用公開可能鍵に相当するものです。"live"かつ"read_write"のscopeで、認可したユーザが商用環境を利用中の場合のみ与えられます。"oauth_live_public_"で始まる文字列です

それぞれの処理の内容はコードコメントの通りです。 より詳細な通信内容の規定に関してはRFC 6749をご覧ください。

なお、RFC 6749 4.1.3. Access Token Requestにはありませんが、WebPay ExtendではAccess Token Requestにおいてclient_secretを送信することが必須になっています。

スコープ

スコープは、Extendアプリケーションがどのような操作を行うかを表現します。 Extendアプリケーションを作成する時には、機能に応じて必要最小限のスコープを指定してください。 ユーザがExtendアプリケーションを認可する時に、どのスコープが要求されているか表示されます。

WebPay Extendが提供しているスコープは次のとおりです。 Extendアプリケーションは認可リクエストを開始する時にスコープを指定します。 スコープには、次のスコープ名のいくつかをスペース区切りで複数指定できます。 上のサンプルでは"read test"を指定していることを確認してください。

test
テスト環境でのみExtendアプリケーションを有効にします。アプリケーションはテスト環境のデータにのみアクセスでき、テスト環境のWebhookのみ受信できます。
live
テスト環境、商用環境の両方でExtendアプリケーションを有効にします。アプリケーションはAPIキーを使いわけることで両方のデータにアクセスでき、両方のWebhookを受信できます。
read
データの読取のみ可能です。 オブジェクトの作成や更新をともなう操作は実行できません。 WebPayにあるデータを元に機能を提供し、データの変更が不要な場合は"read"スコープを指定してください。
read_write
すべての操作が可能です。 publishable_keyは現状クレジットカード情報のトークン化のフローでしか利用されないため、"read_write"スコープでのみ提供されます。

Extendアプリケーションはユーザがアプリケーションの動作を安全に試せるように、testのみを認可できる方法を提供して下さい。 例えば認可を開始する画面で「テスト環境でのみ有効にする」「テスト環境、商用環境両方で有効にする」の2つのボタンを表示するなどです。

Application Webhook

基本的には、各ユーザが自分の環境での更新を受信できるWebhook機能と同様の機能です。 WebPay Extendで要求される機能を提供するためにいくつかの変更がほどこされています。 このWebhookを通常のWebhookと区別して、Application Webhookと呼んでいます。

WebPay Extendでは複数のユーザの環境からの更新通知を識別する必要があるので、 X-Webpay-Owner-Account-Id HTTPヘッダが追加されています。 認可された時にExtendアプリケーションのデータベースにアカウントIDとAPIキーを保存し、Webhookを受信した時により詳細な内容を取得するためにアカウントIDに対応するAPIキーをデータベースから取得してAPIリクエストを行うフローを想定しています。

Application Webhookでは認可が取り消されたことも通知されます。 ユーザが認可を取り消すと、"type"に"account.application.deauthorized"が指定されたイベントを受信します。 ユーザのAPIキーは使えなくなり、以降のWebhookも受信しません。 通常のウェブサービスの退会に相当する操作ですので、該当のユーザに関連する情報をデータベースから適切に削除してください。

Shared customer(顧客情報の共有)

Shared customerは、Extendアプリケーションの提供者のアカウントの顧客のカード情報を、認可したアカウントで利用する機能です。

例えば、様々なWebPayのユーザが商品を販売出来るECプラットフォームサービス(Extendアプリケーション)上で、あるWebPayのユーザ向けに作成された顧客オブジェクトのカード情報を 他のWebPayのユーザ向けに再利用することができます。これを用いて購入者が行うカード情報の入力がそのプラットフォーム上では一度で済むようになります。

実際のカード情報の共有は、Extendアプリケーションの提供者の顧客IDを指定し、そのカード情報をもとに利用者のアカウントにトークンを作成する形で行います。 このとき、商用環境で利用するトークンを作るためには、顧客も商用環境のものでなければいけません。 また、トークンの作成という更新操作を伴うため、スコープに read_write を含む必要があります。 顧客の共有機能を利用したアプリケーションを商用環境にも提供するには、Extendアプリケーションの作成者が商用環境を利用できる状態である必要があります。

実際には元々の顧客を、クライアントサイドでのトークン化で得たトークンを元にして作成します。 一連の操作をcurlを使って行うと、次のようになります。 詳細はトークン作成APIを参照してください。

curl "https://api.webpay.jp/v1/customers" \
    -u "Extendアプリケーション提供者の非公開鍵": \
    -d "card=tok_SampleCardToken"

curl "https://api.webpay.jp/v1/tokens" \
    -u "OAuth2で取得したExtendアプリケーションの利用者の非公開鍵": \
    -d "customer=前のリクエストで作成された顧客ID"

実装上の注意

WebPay Extendを利用すると登録したユーザのアカウントに対して自由な操作が可能になります。 その分、Extendアプリケーションの実装者には重大な責任があります。 ガイドラインに掲げているクレジットカード情報と金銭を扱うウェブアプリケーションを作成する上で遵守すべき事項はすべて実施してください。 WebPay Extendが独自に定義している制限もあります。 Extendアプリケーションの実装者はWebPay Extend利用規約の全条項および、このページに記載している制限をすべて満たすように実装しなければいけません。

登録され、公開されているExtendアプリケーションが不適切な実装を行っていることを発見した場合、他のユーザや購入者を保護するため、 該当のExtendアプリケーションを事前の承認なく削除します。

困ったときは

「クライアントが認証できませんでした。Extendアプリケーションの開発者に連絡してください」 というエラーが表示される場合、設定画面から作成したExtendアプリケーションの情報が、開発中のシステムに正しく設定できていない可能性が高いです。 Extendアプリケーションのページに表示されている client_idclient_secret が合致しているかどうか再度確認してください。 OAuthの認可フローを自身で実装している場合、仕様を満たしていない箇所がないか確認してください。

「無効なGrantです。再度やりなおしてください」 というエラーが表示される場合、上述のフローにおいて、Extendアプリケーションの利用者から受け取ったauthorization codeに関連する処理が適切に動作していないことがあります。 また、Extendアプリケーションの認可をしてからaccess tokenを取得するまでに長い時間がかかった場合もこれに該当します。 まずは再度認可処理をやりなおして、うまくいかない場合はリダイレクトを受信してaccess tokenを取得する箇所の実装をチェックします。 とくにリダイレクトURIの指定が無かったり、間違っていないことを確認してください。

その他のエラーでお困りの場合は、フォーラム等にお問い合わせください。

サンプルのExtendアプリケーション

Extendアプリケーションを実装する際の参考にしていただくため、WebPay Receiptというサンプルとなるサービスを作成し、コードを公開しています。 このサービスは認可したWebPayのアカウントにおけるtypeプロパティがcharge.succeededであるイベントをWebhookで受信し、成功した課金に顧客が紐付けられていて、その顧客のメールアドレスが登録されている場合、顧客のメールアドレスあてに入金があった旨を通知する機能を提供します。 詳しくはwebpay-receiptのGitHubリポジトリをご覧ください。