PAY IDを使ったQRコード支払いの流れ

PAY IDアプリを使うと、QRコードを通じた決済処理ができるようになります。決済時にクレジットカード番号を入力する必要がないのでとても簡単です。これは決済するユーザーはもちろん、サービス提供事業者にとっても簡単です。

そんな決済用QRコード生成方法はプロダクトと店舗で2パターン用意されています。今回はそれぞれの生成方法と、使い方を紹介します。

プロダクト用QRコード

まず管理画面でプロダクトを作成します。

f:id:goofmint:20171125183428p:plain

プロダクト作成時には金額が必須になっています。つまりプロダクト用QRコードは金額固定です。

f:id:goofmint:20171125183453p:plain

QRコードはプロダクト情報の詳細で確認できます。

f:id:goofmint:20171125183622p:plain

生成されたQRコードを印刷したり、Webページに掲載します。

f:id:goofmint:20171125183709p:plain

PAY IDアプリでQRコードを読み込むと決済確認画面になります。

f:id:goofmint:20171125183813p:plain

そして支払いするボタンを押すと決済が完了します。

店舗用QRコード

店舗用QRコードは設定メニューの下の方に用意されています。QRコードを印刷したり、Webサイトに掲載します。

f:id:goofmint:20171125183849p:plain

PAY IDアプリで読み込むと、決済金額の入力画面になります。ここが大きな違いになります。

f:id:goofmint:20171125184001p:plain

決済金額を入力し、確認画面に進みます。そして支払いをタップして処理完了です。

f:id:goofmint:20171125184046p:plain

注意点

プロダクト用QRコードはテスト用モードが用意されていますが、店舗用QRコードには用意されていません。店舗用QRコードでの決済データは本番環境に反映されますので、開発中は忘れずに返金しておきましょう。

PAY IDアプリは iOS / Android どちらでも利用可能です。

PAY ID - お支払いアプリ iOS版

PAY ID - お支払いアプリ Android版

PAY ID QRコード決済 | PAY.JP

クレジットカード入力フォームをカスタマイズしましょう

PAY.JPのクレジットカード入力フォームを使うと、サービス提供事業者はクレジットカード番号に触れることなく決済機能が提供できるようになります。クレジットカード番号は万一悪意を持ったユーザに盗み取られたりすると大きな事業リスクになります。そのため、カード番号にそもそも触れることがなければ安心です。

そんなカード番号入力フォームは次のような簡単なJavaScriptタグで導入できます。以下の情報はすべて必須です。 data-key にはPAY.JPの管理画面で取得できる公開鍵を指定してください。

<script
  type="text/javascript"
  src="https://checkout.pay.jp/"
  class="payjp-button"
  data-key="YOUR_PUBLIC_KEY"
></script>

そしてWebブラウザでアクセスすると以下のようなボタンが表示されます。

f:id:goofmint:20171120112553p:plain

しかしこれだけではありません。オプションとして様々なカスタマイズができます。今回はそれぞれのオプションについて紹介します。

PAY ID支払いに対応する

PAY.JPではクレジットカード支払いだけでなく、PAY IDを使った決済にも対応しています。この場合、 data-payjp を指定します。値は PAY IDの管理画面で取得できるOAuthクライアントIDを指定します。

<script
  type="text/javascript"
  src="https://checkout.pay.jp/"
  class="payjp-button"
  data-payjp=""
  data-key="YOUR_PUBLIC_KEY"
></script>

指定すると、以下のようにクレジットカード入力フォームにてPAY IDが選択できるようになります。

f:id:goofmint:20171106165535p:plain

すぐにフォーム送信しないようにする

デフォルトの動作ではクレジットカード番号を入力した後、すぐに提供サービスに対するフォーム送信が行われます。しかし確認画面につなげたい、もう一段階入力内容がある、といったケースもあるでしょう。そうした時に使えるのが data-partial です。

data-partial を true に指定すると、フォーム送信が行われずにクレジットカード番号を入力したモーダルが閉じるだけで終わります。

<script
  type="text/javascript"
  src="https://checkout.pay.jp/"
  class="payjp-button"
  data-key="YOUR_PUBLIC_KEY"
  data-partial="true"
></script>

data-partial を true にすると、ボタンのラベルが「カードで支払う」から「カード番号を入力する」に変化します(後述のオプションで変更可能です)。

f:id:goofmint:20171120112442p:plain

そしてクレジットカード番号を入力すると、ボタンが緑になって「カード情報入力済み」と表示されます。

f:id:goofmint:20171120112607p:plain

ボタンのラベルを変える

ボタンのラベルはデフォルトで「カードで支払う」ですが、これを変更できます。利用するのは data-text です。以下は「カード番号の登録」というラベルに変更する例です。

<script
  type="text/javascript"
  src="https://checkout.pay.jp/"
  class="payjp-button"
  data-key="YOUR_PUBLIC_KEY"
  data-text="カード番号の登録"
></script>

f:id:goofmint:20171120112622p:plain

クレジットカード入力フォームのボタンのラベルを変える

クレジットカード入力フォームの一番下にあるボタンのラベルも変更できます。これは `` で指定できます。

<script
  type="text/javascript"
  src="https://checkout.pay.jp/"
  class="payjp-button"
  data-key="YOUR_PUBLIC_KEY"
  data-submit-text="カード番号を登録して閉じる"
></script>

f:id:goofmint:20171120112634p:plain

サーバに送信するパラメータ名を変更する

PAY.JPではクレジットカード情報をトークンに変換し、そのトークンを使って実際の決済処理を行いますが、このトークンは payjp-token というパラメータで取得できます。例えばPHPであれば $_POST['payjp-token'] といった形になるでしょう。しかし場合によってはこれを変更したい時もあります。その時に使うのが data-token-name になります。

例えば以下の例ではパラメータ名を nonce に変更します。

<script
  type="text/javascript"
  src="https://checkout.pay.jp/"
  class="payjp-button"
  data-key="YOUR_PUBLIC_KEY"
  data-token-name="nonce"
></script>

data-partial と組み合わせて、フォームをすぐに送信しないようにした場合で確認すると分かりやすいです。まず以下はデフォルトの場合で、HTML構造を見ると payjp-token という名前の変数で確認できます。

<div id="payjp_checkout_box">
  <input type="button" value="✔ カード情報入力済み" class="has-token">
  <input type="hidden" name="payjp-token" value="tok_95b...19c">
</div>

それが data-token-name="nonce" を指定すると次のように変化します。

<div id="payjp_checkout_box">
  <input type="button" value="✔ カード情報入力済み" class="has-token">
  <input type="hidden" name="nonce" value="tok_ca3...65b">
</div>

クレジットカード番号を登録した際にコールバックを受け取る

クレジットカード番号を登録した際に、JavaScriptで何らかの処理をしたい時もあるでしょう。そうした時には data-on-created を指定します。例えば以下の例では onCreated という関数を呼び出します。

<script
  type="text/javascript"
  src="https://checkout.pay.jp/"
  class="payjp-button"
  data-key="YOUR_PUBLIC_KEY"
  data-on-created="onCreated"
></script>

関数の一つ目の引数にカード情報が送られてきます。

function onCreated(card) {
  console.log(card);
}

この時の card の内容は次のようになります。確認画面で下4桁や有効期限を表示するといったことも可能です。

{
  "card": {
    "address_city": null, 
    "address_line1": null, 
    "address_line2": null, 
    "address_state": null, 
    "address_zip": null, 
    "address_zip_check": "unchecked", 
    "brand": "Visa", 
    "country": null, 
    "created": 1510968184, 
    "customer": null, 
    "cvc_check": "passed", 
    "exp_month": 10, 
    "exp_year": 2020, 
    "fingerprint": "e1d8225886e3a7211127df751c86787f", 
    "id": "car_98e4b31486f42f296710df14efc7", 
    "last4": "4242", 
    "livemode": false, 
    "metadata": {}, 
    "name": "ATSUSHI", 
    "object": "card"
  }, 
  "created": 1510968184, 
  "id": "tok_8f5...b66", 
  "livemode": false, 
  "object": "token", 
  "used": false
}

登録失敗した時のコールバックを受け取る

何らかのエラー(ユーザが入力フォームを閉じた場合は除きます)が発生した際にコールバックを受け取りたい場合は data-on-failed を指定します。以下の例では onFailed が呼び出されます。

<script
  type="text/javascript"
  src="https://checkout.pay.jp/"
  class="payjp-button"
  data-key="YOUR_PUBLIC_KEY"
  data-on-failed="onFailed"
></script>

この時、一つ目の引数にステータスコード、二つ目の引数にエラー内容が送られてきます。

function onFailed(status, error) {
  console.log(status);
  // -> 0
  console.log(error);
  // -> {"description": "token を取得できません"}
}

表示言語を変更する

PAY.JPのクレジットカード入力フォームは日本語と英語に対応しています。英語にする場合は data-lang を指定します。以下は英語に変更する例です。

<script
  type="text/javascript"
  src="https://checkout.pay.jp/"
  class="payjp-button"
  data-key="YOUR_PUBLIC_KEY"
  data-lang="en"
></script>

ボタンはもちろん、入力フォームのラベルもすべて英語になります。

f:id:goofmint:20171120112652p:plain

名前のデフォルト表示(プレースホルダー)を変更する

クレジットカード入力フォームでは名前のところに「TARO YAMADA」とデフォルト表示(プレースホルダー)されています。これを変更したい場合には data-name-placeholder を指定します。

<script
  type="text/javascript"
  src="https://checkout.pay.jp/"
  class="payjp-button"
  data-key="YOUR_PUBLIC_KEY"
  data-name-placeholder="名前を英語で入力してください"
></script>

f:id:goofmint:20171120112702p:plain


このようにPAY.JPのクレジットカード入力フォームは細かなカスタマイズができます。ぜひ皆さんのサービスに合わせて変更してください。

Checkout | PAY.JP

クレジットカード情報をトークン化するpayjp.jsの使い方

2018年03月に迫ったPCI DSS準拠に向けて、クレジットカード情報をいかに所持せずに決済処理を提供するかが必要になっています。(via カード情報非保持化対応のお願い - PAY.JP Announcement )

PAY.JPのチェックアウトボタンを付けるだけでクレジットカード番号をトークン化できますが、よりカスタマイズしたフォームで自社サイトと親和性高く提供したいと考える方も多いでしょう。

そこで使えるのがpayjp.jsになります。Webブラウザ上でクレジットカード番号を入力してもらい、それをトークン化する流れをJavaScriptで提供する機能です。

payjp.jsの準備

payjp.jsは以下のJavaScriptコードを追加するだけで利用できます。

<script type="text/javascript" src="https://js.pay.jp/"></script>

クレジットカード番号入力フォームの用意

次にクレジットカード番号を入力する項目を用意します。これはHTMLで直接記述します。この時、カード番号/有効期限(年および月)は必須です。処理としてはトークン作成処理になりますので、請求先住所やカード保有者といった情報も送信できます。

<form>
  <div class="form-group">
    <label for="inputCardNumber">カード番号</label>
    <input type="text" class="form-control" id="card_number" placeholder="カード番号">
  </div>
  <div class="form-group">
    <label for="inputCVV">CVV/セキュリティコード</label>
    <input type="text" class="form-control" id="cvv" placeholder="CVV">
  </div>
  <div class="form-group">
    <label for="inputExp">有効期限</label>
    <div class="row">
      <div class="col-md-6">
        <input type="text" class="form-control" id="exp_year" placeholder="年">
      </div>
      <div class="col-md-6">
        <input type="text" class="form-control" id="exp_month" placeholder="月">
      </div>
    </div>
  </div>
  <button id="token">トークン化</button>
</form>
<!-- 今回はHTML上に結果を表示します -->
生成されたトークン:<div id="card_token"></div>

JavaScriptでの処理

そしてボタンを押したタイミングなどでJavaScriptの処理を実行します。 payjp.js の処理としては公開鍵の設定( setPublicKey )とトークンの生成( createToken )くらいしか処理はいりません。

// DOM読み込みが完了したら実行
document.addEventListener('DOMContentLoaded', (e) => {
  // payjp.jsの初期化
  Payjp.setPublicKey('YOUR_PUBLIC_KEY');
  
  // ボタンのイベントハンドリング
  const btn = document.getElementById('token');
  btn.addEventListener('click', (e) => {
    e.preventDefault();
    
    // カード情報生成
    const card = {
      number: document.getElementById('card_number').value,
      cvc: document.getElementById('cvv').value,
      exp_month: document.getElementById('exp_month').value,
      exp_year: document.getElementById('exp_year').value
    };
    
    // トークン生成
    Payjp.createToken(card, (status, response) => {
      if (status === 200) {
        // 出力(本来はサーバへ送信)
        document.getElementById('card_token').innerHTML = response.card.id;
      }
    });
  });
}, false);

実際に処理を行ってみると、ボタンを押したタイミングで PAY.JP のサーバにクレジットカード情報を送信し、結果としてトークンなどの情報を受け取っているのが分かります。

f:id:goofmint:20171125183207g:plain

後はこのトークンをサーバに送信し、課金額と一緒に決済処理を行えば良いでしょう。

payjp.js を使うことでクレジットカード入力画面の自由度は飛躍的に高まります。サーバへクレジットカード番号が送られないのでPCI DSSへの対応も不要です。ぜひ使ってみてください。

payjp.js | PAY.JP

PAY.JPで発生したイベントをWebhookで受け取る

Webサービスというのは基本的にプル型です。クライアント側からアクセスしてはじめてデータを受け取ったり、逆に登録したりします。しかし購入が発生した時や、何からのイベントが発生したときにそれをすぐに知りたいというニーズは強くあります。

それを可能にするのがWebhookです。通常はWeb API利用側がサーバにアクセスするところを、逆にサーバからWeb API利用者側の指定するURLにアクセスしてもらう仕組みです。簡単なシーケンス図は次のようになります。

f:id:goofmint:20171121161313p:plain

有名なところではGitHubのWebhookがあって、リポジトリへのコードプッシュがあったり、マージした時に通知を受け取れる仕組みがあります。またSlackもチャットメッセージが来た時にWebhookで通知してもらえます。同様にPAY.JPでもWebhookが用意されていますので、取引が発生したり、定期課金が作成されたタイミングなどで通知を受け取れます。

Webhook | PAY.JP

注意点として、Webhookを完全に信用するのは危険です。100%確実に届くとは言い切れません。Webhookを受け取るサーバが落ちているケースもあるでしょう。PAY.JPのWebhookでは400または500系エラーを受け取った際には3分間隔で3回までリトライしますが、それを超えると通知を行いませんので注意してください。これはWebhookをサポートするサービス全般に言えるもので、データをすべて受け取るのはWebhookではなく通常のWeb APIを用いるのが良いでしょう。

この記事ではそんなWebhookを実装するための方法を紹介します。

サーバの準備

WebhookはPAY.JPからあらかじめ指定したサーバを呼び出す仕組みです。つまりサーバはインターネット上に公開されている必要があります。クラウドなどを使ってサーバを立ち上げるのが一番良いのですが、開発時には ngrok を使うのが便利です。これは ngrok のサービスとローカルのHTTPサーバがつながり、ローカルコンピュータをインターネット上に公開できる仕組みです(厳密には違いますが、ここでは簡略化しています)。昔はダイナミックDNSで同様の仕組みが提供されていましたが、もっと手軽に使える技術になります。

今回のサンプルは Node.js + Express で作成してあります。Node.js はJavaScriptをサーバ上で実行する技術で、ExpressはNode.jsでよく使われるWebアプ リケーションフレームワークです。そして、PAY.JPで取引が発生すると /hooks が呼ばれるようになっています。コードは後で解説します。

router.post('/hooks', (req, res, next) => {
  // Webhook処理
  if (req.headers['x-payjp-webhook-token'] !== config.webhook_token) {
    // 不正なアクセス
    return res.status(401).send({});
  }
  if (req.body.type === 'charge.succeeded') {
    const charge = req.body.data;
    console.log('決済が成功しました');
    console.log(`id => ${charge.id}`);
    console.log(`card.last4e => ${charge.card.last4}`);
    console.log(`card.exp => ${charge.card.exp_year}/${charge.card.exp_month}`);
    console.log(`price => ${charge.amount}(${charge.currency})`);
  }
  res.send({});
});

設定を変更する

PAY.JPの管理画面で取得できる各種設定情報を config.json の中に記述します。config.example.json というファイルがあるので、 config.json に名前を変更してください。内容は最初、次のようになっているはずです。

{
  "public_key": "YOUR_PUBLIC_KEY",
  "secret_key": "YOUR_SECRET_KEY",
  "webhook_token": "YOUR_WEBHOOK_TOKEN"
}

これのテスト公開鍵、テスト秘密鍵をそれぞれ書き換えてください。

{
  "public_key": "pk_...e5",
  "secret_key": "sk_...24",
  "webhook_token": "whook_4a...f8"
}

次にローカルコンピュータでサーバを立ち上げます。

$ node ./bin/www

そして ngrok をインストールします。

brew install cask ngrok

インストールしたら、以下のコマンドでローカルコンピュータにインターネット上からアクセスできるようになります。

$ ngrok http 3000
ngrok by @inconshreveable                                       (Ctrl+C to quit)
                                                                                
Session Status                online                                            
Account                       Atsushi Mint Nakatsugawa (Plan: Free)             
Version                       2.2.8                                             
Region                        United States (us)                                
Web Interface                 http://127.0.0.1:4040                             
Forwarding                    http://001ca638.ngrok.io -> localhost:3000        
Forwarding                    https://001ca638.ngrok.io -> localhost:3000       
                                                                                
Connections                   ttl     opn     rt1     rt5     p50     p90       

一時的に使えるURL(今回の場合は https://001ca638.ngrok.io)ができましたので、このURL + /hooks をPAY.JPの管理画面にてWebhookするURLとして登録します。

f:id:goofmint:20171121161330p:plain

これで準備完了です。

取引を行う

ではテストで決済を行ってみます。決済は http://localhost:3000/ でできるようになっています。アクセスすると 100円支払うという表示とボタンが'確認できるはずです。

f:id:goofmint:20171121161348p:plain

ボタンを押すとPAY.JPのクレジットカード入力フォームが表示されます。テストのカード番号はこちらを参考にしてください。

f:id:goofmint:20171121161359p:plain

クレジットカード番号を入力すると、 http://localhost:3000/pay が呼ばれて1000円の決済処理が行われます。決済処理が無事完了すると、次のような場面が表示されるでしょう。

f:id:goofmint:20171121161410p:plain

Webhookが呼ばれる

そして少し待つとPAY.JPからWebhookが呼ばれます。ターミナルなどの画面に次のように表示されたら成功です。

決済が成功しました
id => ch_84970e95eb7f66e21a41a4dac60ae
card.last4e => 4242
card.exp => 2020/10
price => 1000(jpy)

Webhookの検証

WebhookのURLには特にセキュリティがありません。外部から誰でも呼べてしまうアドレスになります。そこで、呼ばれた内容が正しいことを検証する方法としてリクエストの X-Payjp-Webhook-Token ヘッダーを確認してください。この内容はPAY.JPの管理画面で確認できますので、リクエストに踏まれるヘッダーと同じものであればPAY.JPからの正当なWebhookだと確認できます。

イベントの種類

なお、PAY.JPでは以下のイベントの際にWebhookを呼び出します。詳細はこちらで確認できます。それぞれにイベント種別(type)が設定されていますので、それを見て何のイベントであるかを知ることができます。

  • 支払い関係
    • 成功
    • 失敗
    • 更新
    • 返金
    • 確定
  • トークン関係
    • 作成
  • 顧客関係
    • 作成
    • 更新
    • 削除
    • カード作成
    • カード更新
    • カード削除
  • プラン関係
    • 作成
    • 更新
    • 削除
  • 定期課金
    • 作成
    • 更新
    • 削除
    • 停止
    • 再開
    • キャンセル
    • 期間更新
  • 入金関係
    • 内容確定

PAY.JPから送られてきたデータを使って、チャットにメッセージを流したり、メールを送信するといった処理につなげるのも良いでしょう。前述の通り、100%の信頼性を前提にするのはお勧めしませんが、通知を使うことで業務の生産性をさらに高めることができるはずです。

Webhook | PAY.JP

PAY.JPで支払いを与信、期限延長、売り上げ確定させる

レストランやお店で商品を購入する場合、クレジットカードでの支払いはその場で確定します。内部的に見ると、次の2つの処理を同時に行っています。

  • 与信枠を確保(オーソリ)
  • 支払いを確定

与信というのはお金を受け取れる保証と言えます。与信枠はクレジットカード会社が保証しており、その枠の範囲内であればオーソリが成功します。そして、そのオーソリを売り上げ確定することでクレジットカード会社は店舗にお金を払ったり、カード保有者の口座からお金を引き落とします。

では、このオーソリと支払い確定がずれる場合はどんな形があるかというと、例えば予約商品があります。Eコマースサイトの場合、多くは支払い確定を出荷ベースにしています。そのため、いざ商品を出荷するタイミングでクレジットカード決済がエラーになると非常に困ります。かといって注文時に支払いを確定させてしまった場合、商品の入荷が1ヶ月以上先だと先にお金だけ引き落とされます。これは消費者にとってよくありません。他にもここ数年流行っているクラウドファンディングがあります。こちらは出資額が一定以上に達しないとプロジェクトが失敗します。賛同者が集まるまではあくまでも架空の決済状態(与信を確保した状態)でなければいけません。

そこでどちらにも納得のいく仕組みとして、オーソリという形が存在します。オーソリで決済枠を確保できていれば、支払いを確定するタイミングを遅らせることができます。今回はそんな与信を使った支払い方法をPAY.JP APIで実現する方法を紹介します。なお、今回はRubyで行っています。

SDKのインストール

PAY.JPではRuby向けにSDKを提供しています。インストールはRubygemsでできます。

gem install payjp

初期設定

PAY.JPにてアカウントを作成すると、公開鍵と秘密鍵が得られます。この秘密鍵を使ってSDKを初期設定します。

require "payjp"
Payjp.api_key = "sk_live_708...e76"

支払いの作成

次に支払いデータを作成します。これはChargeクラスを使います。クレジットカード番号を直接扱うのはPAY.JPでは推奨されないため、クレジットカード番号をトークン化し、さらに顧客と結びつけてあることとします。そちらの実装についてはこちらの記事をご覧ください。

例えば以下は100円の決済を行った場合なのですが、capture=false としているのがポイントです。これによって支払い処理の確定はせず、オーソリのみを実行します。

charge = Payjp::Charge.create(
  amount: 100,
  customer: customer_id,
  capture: false,
  currency: 'jpy',
)

管理画面では次のように表示されます。この有効期限はデフォルトで7日、最長で60日となっています。

f:id:payjp:20171127103202p:plain

期限を延長する

もし有効期限が足りない場合、さらに延長できます。こちらもデフォルトで7日、最長で60日となっています。

charge.reauth
# または
charge.reauth(expiry_days: 10)

支払いをキャンセルする

もし商品が出荷できなくなったり、クラウドファンディングで出資が集まらなかった場合は支払いデータをキャンセルしなければなりません。そうしないと枠をずっと確保し続けることになり、消費者のクレジットカード決済に影響が出てしまうでしょう。支払いのキャンセルは refund メソッドでできます。 後述する支払い確定された処理に対しては amount オプションを使うことで一部キャンセルも可能です。(オーソリ状態の処理に対して一部キャンセルはできません)

charge.refund
# または
charge.refund(amount: 20)

支払いを確定する

そして支払いを確定する処理です。これは capture メソッドを使います。元の金額のまま確定することもできますが、金額を変更することもできます。この時には amount オプションを指定します。

charge.capture
# または
charge.capture(amount: 20)

これで支払いが確定し、店舗側は入金されることになります。


このようなフローで与信を使った取引が実現できます。なお、支払い確定であったり、逆にキャンセルは必要になったタイミングで早めに行うのが良いでしょう。キャンセルしないまま放置していると、枠を確保し続けてしまうのでクレジットカード決済が失敗する可能性が高まってしまいます。

なおデビットカードやプリペイドカードでは、与信枠の確保のタイミングで引き落とし処理が発生いたしますので、購入者が利用する際の説明などに留意ください。

以上、ビジネスフローによりますが、与信を使った決済を行う場合の参考にしてください。

PAY.JP API リファレンス

ごく基本的なPAY.JPの使い方(Ruby編)

PAY.JPはREST APIを使ってクレジットカード決済ができるサービスです。

f:id:goofmint:20171108144034p:plain

PAY.JP - クレジットカード決済サービス

多数のプログラミング言語(Ruby/Java/PHP/Python/Perl/Go/Swift/Node.js)などに対してSDKを提供しています。

そんなPAY.JPのごくごく基本的なコードをRubyで書いてみます。

インストール

まずSDKをインストールします。 gem コマンドまたはGemfileを使います。ライブラリはGitHubにて公開されています(ライセンスはMIT Licenseです)。

$ gem install payjp

インストールが終わったらRubyスクリプト(今回は test.rb としています)で読み込みます。

require 'payjp'

APIキーの取得

PAY.JPでユーザ登録して、ダッシュボードに入ると設定の中にAPIキー情報があります。

f:id:goofmint:20171108144053p:plain

今回はデモなのでテスト秘密鍵を使います。これを api_key として使います。

api_key = 'YOUR_API_KEY'

初期化

APIキーを使ってPayjpクラスを初期化します。

Payjp.api_key = api_key

カードトークンの取得

ここで処理の流れを紹介します。PAY.JPではクレジットカード番号を一旦トークン化し、そのトークンを使って決済処理を行います。通常、このトークンはテンポラリトークン(一回しか使えない有効期限付きトークン)ですが、顧客と紐付けを行うことで繰り返し使えるようになります。

このトークンの仕組みでは、クレジットカード番号自体、サービスサイト側で触らないようにするJavaScriptの仕組みを用意しております。トークンだけがサーバに送られるようになります。シーケンス図にすると次のようになります。

f:id:goofmint:20171108144122p:plain

本記事ではこちらを使った実装を紹介します。カード番号はテストカード | PAY.JPよりピックアップしています。CVC(セキュリティコード)や有効期限は適当です。

まずHTMLのフォームに対して script タグを追加します。 YOUR_PUBLIC_KEY には公開鍵を指定してください。

<form action="/pay" method="post">
  <!-- 注文情報などの情報ここから -->
    :
  <!-- 注文情報などの情報ここまで -->
  <script src="https://checkout.pay.jp/" class="payjp-button" data-key="YOUR_PUBLIC_KEY"></script>
</form>

そしてボタンを押すとクレジットカード番号を入力するモーダルウィンドウが表示されます。

入力を完了すると、元々のフォームの送信先である /pay に対して payjp-token という名前でテンポラリトークンが送信されます。

決済処理の実行

続いてこの取得したトークンを使って決済処理を行います。これは簡単で、金額とトークンを渡すだけです。

charge = Payjp::Charge.create(
  :amount => 3500,
  :card => payjp_token, // 先ほど送られてきたテンポラリトークン
  :currency => 'jpy',
)

結果は次のように返ってきます。

{
  "id": "ch_feb4b38692995e28859c5d0c21004",
  "amount": 5000,
  "amount_refunded": 0,
  "captured": true,
  "captured_at": 1508198383,
  "card":   { /*(トークン取得時のカード情報と同じ) */ },
  "created": 1508198383,
  "currency": "jpy",
  "customer": null,
  "description": null,
  "expired_at": null,
  "failure_code": null,
  "failure_message": null,
  "livemode": false,
  "metadata": {},
  "object": "charge",
  "paid": true,
  "refund_reason": null,
  "refunded": false,
  "subscription": null
}

このレスポンスの id を使うとダッシュボードで該当する取引を探せます。

f:id:goofmint:20171108144137p:plain


こんな感じでごく簡単に実装できます。なお、PAY.JPではクレジットカード情報をサーバから送信してトークン化することもできますが、その方式では経産省が2018年3月までにPCIDSSへ対応しなければならないと決定しており、PAY.JPでも非推奨の実装方法としております(via カード情報非保持化対応のお願い - PAY.JP Announcement)。これから実装される場合にはJavaScriptでトークンを生成する方法を採用いただくようご留意ください。

PAY.JPのオンライン決済にPAY IDを組み込む

PAY.JPはオンライン決済を提供しています。クレジットカード決済に加え、あらかじめクレジットカードを登録しておくことでカード番号の入力をしなくて済むPAY IDも提供しています。これはオンライン決済の他、リアル店舗や個人間決済でも使えます。

すでにPAY.JPのオンライン決済を導入している場合、すぐにPAY ID決済を組み込めます。

決済画面を表示する

PAY.JPのCheckoutを使った場合、元々の決済フォームは次のようになっているかと思います。 YOUR_PUBLIC_KEY はPAY.JPの管理画面で取得できる公開鍵です。

<form action="/pay" method="post">
    :
  <script class="payjp-button"
    src="https://checkout.pay.jp/"
    data-key="YOUR_PUBLIC_KEY">
  </script>
</form>

そのscriptタグに要素を一つ追加します。それが data-payjp です(取得方法はこれから説明します)。

<form action="/pay" method="post">
  <script class="payjp-button"
    src="https://checkout.pay.jp/"
    data-key="YOUR_PUBLIC_KEY"
    data-payjp="YOUR_CLIENT_ID"> <!-- これを追加 -->
  </script>
</form>

OAuthクライアントを作る

管理画面の設定に移動すると、OAuth クライアントという項目があります。このOAuthクライアントを追加します。

f:id:goofmint:20171106165457p:plain

Redirect URIは今回の場合は http://localhost/ で構いません。作成した後、OAuthクライアント一覧の中から詳細ボタンを押すとClient IDという項目が確認できます。

f:id:goofmint:20171106165509p:plain

これをHTMLフォームのYOUR_CLIENT_IDを書き換えてください。

<form action="/pay" method="post">
  <script class="payjp-button"
    src="https://checkout.pay.jp/"
    data-key="YOUR_PUBLIC_KEY"
    data-payjp="YOUR_CLIENT_ID"> <!-- これを書き換えます -->
  </script>
</form>

これで準備完了です。

PAY.JPでの処理

そしてボタンを押すとモーダルでPAY.JPの決済フォームが表示されます。テストで行う場合にはテストカード | PAY.JPからテスト用のクレジットカード番号を選んでください。テストの場合、有効期限やCVC、名前は適当で問題ありません。

f:id:goofmint:20171106165522p:plain

クレジットカードの他にPAY ID決済が選択できるようになります。なお、テストモードの場合はどんなメールアドレスとパスワードの組み合わせでもログインできます(ただしバリデーションは行われます)。ログインするとあからじめ一枚のクレジットカードと紐付いているのでそのまま決済ができます。

f:id:goofmint:20171106165535p:plain

そして処理が完了すると、フォームの送信イベントがすぐに呼ばれます。

サーバでの処理

PAY.JPでクレジットカード番号からトークンに変換されると、その情報は payjp-token という名前でPOSTされてきます。そのまま使うこともできますし、今後繰り返し使っていくのであれば顧客情報と結びつけることもできます。

以下は顧客情報と結びつける場合です(Rubyの場合)。

customer = Payjp::Customer.create(
  :email => 'example@pay.jp',
  :card  => params['payjp-token']
)

レスポンスであるcustomer.idを自社のデータベースに保存しておきます。こうするとトークンが繰り返し使えるようになります。

実際の決済処理は次のようになります。トークンではなく、customer.id を指定しているのが特徴です。

amount = 1000
Payjp::Charge.create(
    :amount => amount,
    :currency => 'jpy',
    :customer => customer.id,
    :description => '決済に関する説明'
)

例えばECコマースのユーザ情報と結びつけることで、二度目以降はクレジットカード番号の入力を不要にできます。


仕組みの違いはHTMLタグの要素追加だけなので、ユーザにとってはカード番号を入力しないで済むという利点が活かせます。すでにPAY.JPでCheckoutを導入されている方はぜひ追加してみてください。