決済を行う

このページで扱うトピック

💳 Omise.jsによるカード情報の収集

この記事では、ウェブサイト上のページから直接カード情報を収集し、トークン化するためのフォームの構築方法について説明します。

Omise.jsを使用すると、カード情報を簡単に収集できます。Omise.jsは、お客様のブラウザ上で独自のHTMLフォームを実行できるクライアントサイドのJavaScriptライブラリです。機密性の高いカード情報をOmiseサーバーに送信し、その代わりにカードトークンを受け取ります。生成されたトークンを自社サーバーに転送して処理してください。これにより、自社サーバーが機密性の高いカード情報を直接扱う必要はありません。

🔒 PCI-DSSライセンスを保有し、サーバーサイドでのカード情報の取り扱いが認められている組織を除き、Omiseへカード情報を送信する唯一のサポート方法は、Omise.jsを使用したJavaScript経由です。

⚠️ 必須要件: チェックアウトページはHTTPS経由で配信する必要があります。Omise.jsは、通常のHTTPで配信されるページでは動作しません。チェックアウトページだけでなく、サイト全体でHTTPSを有効にすることを推奨します。(出典: docs.omise.co/ja/omise-js/japan)

トークンの概要

⚙️ 仕組み

大まかな流れは以下のとおりです。

  • Omise.jsと公開鍵(public key)を使用し、お客様のブラウザからカード情報をOmiseへ送信します。
  • Omiseのトークンサービスが、一度限り使用可能なカードトークンを返します。
  • 生成されたトークンを自社サーバーへ転送します。
  • トークンを使用してカードに対する操作を行います。カードへの請求新規顧客へのカードの保存既存顧客へのカードの紐付けのいずれかが可能です。

💡 トークンを保存しないことを推奨します。一度限りの使用を前提としているため、後で使うために保存しておくメリットはありません。取得したらすぐに使用し、破棄してください。

🧪 試してみる: Omiseトークンシミュレーター

Omiseトークンシミュレーター

📝 公開に関する注記: pkey_test_XXXXXXXXXXXXXXXXXXXXは本ドキュメント用にサニタイズ済みのプレースホルダーです。上記シミュレーターを実際に動作させるには、正式に発行されたテスト用公開鍵に置き換える必要があります。公開鍵はクライアントサイドでの使用を前提として設計されており、secret keyが必要な操作は実行できませんが、露出しても完全にリスクがないわけではありません(詳細は下記FAQを参照)。公開ドキュメントで使用が承認されているテスト鍵を確認したうえで、置き換えてください。

トークンAPIの詳細については、トークンAPIリファレンスをご覧ください。

💻 本格的な実装例

まず、Webページ内にOmise.jsを挿入します。</body>タグの直前に追加してください。

<script src="https://cdn.omise.co/omise.js"></script>

Omise.jsライブラリ自体はjQueryを必要としませんが、この例ではDOM操作を簡潔に行うためにjQueryを使用しています。jQueryへの依存を避けたい場合は、同様のフォーム送信処理およびDOM検索処理をバニラJavaScript(素のJavaScript)で記述することも可能です。

<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>

続いて、Omise.jsがOmise APIに対して認証できるよう、公開鍵(public key)を設定します。

<script>
  Omise.setPublicKey("pkey_test_XXXXXXXXXXXXXXXXXXXX");
</script>

次に、カード情報を収集するためのフォームを作成します。

<form action="/checkout" method="post" id="checkout">
  <div id="token_errors"></div>

  <input type="hidden" name="omise_token">

  <div>
    名前<br>
    <input type="text" data-omise="holder_name">
  </div>
  <div>
    カード番号<br>
    <input type="text" data-omise="number">
  </div>
  <div>
    有効期限<br>
    <input type="text" data-omise="expiration_month" size="4"> /
    <input type="text" data-omise="expiration_year" size="8">
  </div>
  <div>
    セキュリティコード<br>
    <input type="text" data-omise="security_code" size="8">
  </div>

  <input type="submit" id="create_token">
</form>

次に、送信ボタンが押されたタイミングでトークンの生成をトリガーします。成功時にはトークンフィールドに値を設定し、機密情報を含むフィールドをクリアして自社サーバーへ送信されないようにします。

$("#checkout").submit(function () {

  var form = $(this);

  // 連続クリックを防ぐため、送信ボタンを無効化します。
  form.find("input[type=submit]").prop("disabled", true);

  // フォームの各項目を、有効なcardオブジェクトへシリアライズします。
  var card = {
    "name": form.find("[data-omise=holder_name]").val(),
    "number": form.find("[data-omise=number]").val(),
    "expiration_month": form.find("[data-omise=expiration_month]").val(),
    "expiration_year": form.find("[data-omise=expiration_year]").val(),
    "security_code": form.find("[data-omise=security_code]").val()
  };

  // トークン生成リクエストを送信し、Omiseからレスポンスを受け取り次第
  // コールバック関数を実行します。
  //
  // レスポンスがエラーになる場合もあるため、コールバック内で
  // 適切にハンドリングする必要がある点に注意してください。
  Omise.createToken("card", card, function (statusCode, response) {
    if (response.object == "error" || !response.card.security_code_check) {
      // エラーメッセージを表示します。
      var message_text = "ここにセキュリティコードチェック失敗時のメッセージを設定してください";
      if (response.object == "error") {
        message_text = response.message;
      }
      $("#token_errors").html(message_text);

      // 送信ボタンを再度有効化します。
      form.find("input[type=submit]").prop("disabled", false);
    } else {
      // omise_tokenフィールドに値を設定します。
      form.find("[name=omise_token]").val(response.id);

      // サーバーへ送信する前に、フォームからカード番号とセキュリティコードを削除します。
      form.find("[data-omise=number]").val("");
      form.find("[data-omise=security_code]").val("");

      // トークンをサーバーへ送信します。
      form.get(0).submit();
    }
  });

  // カード情報の生データがそのまま送信されないよう、フォームの送信をキャンセルします。
  return false;

});

以上で完了です。Omise.jsがクレジットカード情報を収集し、トークンを返却します。このトークンを使用してカードに対する操作を行うことができます。

ℹ️ 注記: 上記の例には、エラー判定の一部として!response.card.security_code_checkが含まれています。2020年4月1日以降、OmiseはToken APIおよびCard APIのレスポンスにおいてsecurity_code_checkを常にtrueとして固定的に返すようになりました。これは、CVVの総当たり攻撃(ブルートフォース)を防ぐための意図的な対応です。そのため、この条件部分は現在ではtrueとして評価されることがなく、実質的に機能していません。エラー判定にはresponse.object == "error"(またはstatusCode !== 200)のみを使用してください。カードの実際の有効性は、トークン生成時点ではなく、そのトークンを使ってチャージを作成した時点で判定されます。(出典: docs.omise.co/ja/protecting-you-against-fraudsters/japan)

❓ よくある質問(FAQ)

自社サーバーがカード情報の生データを受け取ることはありますか? いいえ。カード情報はお客様のブラウザからOmise.jsを介して直接Omiseへ送信されます。自社サーバーが受け取るのは生成されたトークンのみであり、カード番号、有効期限、セキュリティコードを受け取ることはありません。

後で使用するためにトークンを保存しておくべきですか? いいえ。トークンは一度限りの使用を前提としています。カードへの請求、顧客への保存、既存顧客への紐付けのいずれかにトークンを使用した時点で、その役目は終わります。取得したらすぐに使用し、破棄してください。保存しておくメリットはありません。

公開鍵(pkey_test_... / pkey_...)をクライアントサイドのJavaScriptに含めても安全ですか? 基本的には安全ですが、「公開しても安全」であることと「リスクがゼロ」であることは同じではありません。公開鍵はクライアントサイドでの使用を前提として設計されており、トークンおよびソースの作成のみに権限が限定されています。チャージの作成や資金の移動など、秘密鍵(secret key)が必要な操作を行うことはできません。ただし、Omiseは公開鍵の露出を悪用した実際の攻撃事例を文書化しています。盗まれたカード番号と組み合わせることで、公開鍵を使ってトークン生成リクエストを繰り返し送信し、各レスポンスのsecurity_code_checkフィールドを確認することでカードのCVVを総当たりで割り出す、という手口です。Omiseは2020年4月1日にこの問題に対応し、security_code_checkを常にtrueとして固定的に返すようにしました。つまり、鍵そのものが資金を動かすことはできませんが、盗まれたカード情報と組み合わされた場合、公開鍵の露出はカードテスティング(不正利用の試行)などの悪用に利用される可能性があります。これが、Omiseが鍵のスコープ制限に加えて、事前オーソリ、IPジオロケーション、行動分析による不正検知を多層的に導入している理由の一つです。(出典: docs.omise.co/ja/protecting-you-against-fraudsters/japandocs.omise.co/ja/api-authentication/japan)

Omise.jsの利用にjQueryは必要ですか? いいえ。これらのサンプルでjQueryを使用しているのは、DOM操作やフォームの送信イベント処理を簡潔に行うためです。Omise.js自体はjQueryに依存しておらず、同様の処理はバニラJavaScript(素のJavaScript)でも記述可能です。

未使用のトークンはどのくらいの期間有効ですか? トークンは一度限り使用可能で、未使用のまま一定時間が経過すると失効します。目安として数分程度です。トークンを取得したら速やかに使用し、キャッシュしたり保持し続けたりしないでください。(出典: docs.omise.co/ja/omise-js/japan)

既に使用済みのトークンを再利用しようとするとどうなりますか? APIはused_tokenエラーを返し、メッセージとして「token was already used」が返されます。トークンは一度限りの使用に限定されており、チャージの作成やカードの紐付けに一度使用されたトークンは、そのチャージが成功したかどうかにかかわらず、再度使用することはできません。(出典: docs.omise.co/ja/api-errors/japan)

他の一部のAPIのように、クライアントサイドの鍵を特定のドメインに限定することはできますか? いいえ。Omiseはドメイン単位での鍵の制限機能を提供していません。公開鍵をクライアントサイドで安全に使用できるのは、権限の範囲がトークンおよびソースの作成・参照のみに限定されているためであり、秘密鍵が必要な操作は一切実行できません。(出典: docs.omise.co/ja/api-authentication/japan)

作成できるトークンの数にレート制限はありますか? はい。OmiseのVault(トークン化用エンドポイント)におけるトークン生成には、メインAPIと比較して大幅に低いレート制限が設けられています。具体的な数値は公開されていません。短時間に多数のリクエストを送信する必要がある場合は、並列で一斉に送信するのではなく、時間を分散させて送信してください。セール等のアクセス集中が見込まれるイベントの前には、事前にsupport@omise.coまでご連絡ください。(出典: docs.omise.co/ja/api-rate-limiting/japan)

トークンを使ってチャージを作成した後、3D Secureへの対応は別途必要ですか? 場合によっては必要です。アカウントで3D Secureが有効になっている場合、チャージのレスポンスにauthorize_uriが含まれることがあり、決済を完了する前にカード保有者をこのURLへリダイレクトして銀行側での本人認証を行う必要があります。3D Secureは、旅行、デジタルコンテンツ、ゲームなど、不正利用やチャージバックが発生しやすい特定の業種では必須とされており、これはOmiseの不正対策チームが判断します。それ以外の加盟店にとっては任意ですが、高額または高リスクな取引には利用が推奨されます。2022年10月以降、3D Secure 1(3DS1)は廃止され、3D Secure 2(3DS2)のみがサポートされています。そのため、authorize_uriへのリダイレクト処理と、それに伴うフリクションレス認証・チャレンジ認証の両方のフローに対応しておく必要があります。(出典: docs.omise.co/3d-secure)

🚀 次のステップ

Omiseは、お客様のウェブサイト全般における利便性を向上するためにクッキーを利用し、お客様のアクセス、閲覧履歴に関する情報を収集します。 当社のウェブサイトを閲覧し続けることにより、お客様は当社のプライバシーポリシーに同意することとします。 詳細はこちら