第554話:Web受付、だけどカード情報は非保持(1)

2017年9月25日

業務:決済カード登録の受付

「クレジットカード決済」を推進したい…。

サービス利用実績にあわせて自動的に「カード課金」できれば、非常にスムーズな決済が可能となる。もし「明細発行」も電子化できれば、売上回収コストは大幅に低減できるだろう。

電気会社・ガス会社・ケータイ会社のように「カード課金できる体制」を整えたい。

課題:カード情報の漏洩リスク

しかし、セキュリティ要件が厳しくなった今日、「クレジットカード番号を保有すること」は大きなリスクらしい。

ウチは、電力会社でもなければ、Google Facebook といった大会社でもない。つまり「PCI DSS」が言っているような要件は維持できそうにない。カード会社(アクワイアラー)も言っているが「持たないこと(非保持)が大切」なのだろう。

よし、、、日本政府が「2018年3月までに非保持化を目指す」と言う書類にあるように、PAN PIN CVC といったカード情報等は「決済代行業者」に預けようと思う・・・。(どうやって??)
  • PAN:Primary Account Number (カード番号)
  • PIN:Personal Identification Number (暗証番号)
  • CVC: Card Verification Code/Value (3桁数字。正確にはCVC2。CIDとも)
※参考: クレジット・カード業界データ・セキュリティ標準(PCI DSS Ver.3.2 2016-04)
※参考:EU の法改正(決済サービス指令 2015年)、日本の法改正(改正割賦販売法 2016年)

[クレジットカード情報の受付プロセス]

解決:ブラウザ上でのトークン化

ワークフローの先頭に「Form開始イベント」を置けば、公開Webフォームへのエントリがあれば、自動的にワークフローが開始されるようになります。

この例では、お客様の「サービス申込の入力」が完了されれば、社内の「申込受付フロー」が自動的に開始される仕組みとなっています。特筆すべきは「クレジットカード番号等」が、ワークフローシステムに届けられることはないという点です。

具体的には、お客様の「カード情報等」はお客様のブラウザと Stripe.com との JavaScript 通信 (CORS通信)によってトークン化され、ワークフローシステムにはそのトークン情報だけが送信される仕組みとなっています。(受付処理にかかわる社員はクレジットカード情報を目にすることはありません)

※ 課金業務については次回記事にて紹介する予定です。

考察:JavaScript の実装難易度

【お客様のブラウザ】から【加盟店サーバ】を通過させず、直接【決済代行業者】(PSP)にカード情報を送信する仕組みは「非保持の実現」に非常に有効です。この例では「カード情報等」は Stripe.com 社に預けられ、ワークフローにはその保管IDとしてのトークンが流れることになります。

いわゆる「クロスドメインアクセス」が必要になりますが、Stripe.com では2012年からCORS(2013年1月W3C勧告候補・2014年1月W3C勧告)がサポートされています。

※ なお、Stripe.com では『Checkout』(embedded payment form)と『Elements』(pre-built UI components)と呼ばれる2つのトークン化機構がありますが、ここでは「Form開始イベント」のカスタマイズを行うために、より自由度の高い『Elements』が利用されています。


一方で、クラウド型ワークフロー「Questetra BPM Suite」では HTML/JavaScript によって[処理フォーム画面](フォーム開始画面を含む)をデコレーションすることが可能です。(M213

しかしながら、(少なくともv11.4現在においては)、それらのコードはHTML文書の <body> 内に挿入される形となります。すなわち、外部 .js ファイルに定義される関数を使用したい場合は「動的読み込み」のプログラミングが必要となります。たとえば jQuery を利用する場合であれば、getScript() の第2引数にコールバック関数を設定すると言った手法で「js ファイルのロード完了」を担保します。


▼[ガイドパネル]の設定サンプル(HTML/JavaScript)
<script type='text/javascript'>
jQuery.getScript("https://js.stripe.com/v3/", function(){
  var stripe = Stripe('pk_test_6pRNASCoBOKtIshFeQd4XMUh'); // Create a Stripe client
  var elements = stripe.elements(); // Create an instance of Elements
  var card = elements.create('card', { hidePostalCode: true, style: {
    base: {
      iconColor: '#666EE8',
      color: '#31325F',
      lineHeight: '30px',
      fontWeight: 300,
      fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
      fontSize: '14px',
      '::placeholder': {
        color: '#CFD7E0',
      }
    },
    invalid: {
      color: '#fa755a',
      iconColor: '#fa755a'
    }
  }
});
card.mount('#card-element');

//// Handle real-time validation errors from the card Element
card.addEventListener('change', function(event) {
  var displayError = document.getElementById('carderror');
  if (event.error) { displayError.textContent = event.error.message;
  } else { displayError.textContent = ''; }
});


//////// Tokenize with Button Click
var tokenizeButton = document.getElementById('stripeTokenization');
tokenizeButton.addEventListener('click', function(event) {
  var extraDetails = {
    name: jQuery('input[name=cardholder-name]').val(),
  };
  stripe.createToken(card, extraDetails).then(function(result) {
    if (result.error) {
      // Inform the user if there was an error
      var errorElement = document.getElementById('carderror');
      errorElement.textContent = result.error.message;
    } else {
      jQuery("input[name='data\\[6\\].input']").val( result.token.id );
      jQuery("input[name='data\\[7\\].input']").val( result.token.card.last4 );
      var successElement = document.getElementById('cardsuccess');
      successElement.textContent = "Your Stripe token for use of Questetra is generated! : " + result.token.id;
    }
  });
});

}); // endof "jQuery.getScript( , function(){"

jQuery('input[name="data\\[6\\].input"]').attr( "readonly", true );
jQuery('input[name="data\\[7\\].input"]').attr( "readonly", true );
jQuery('input[name="data\\[6\\].input"]').css( "background-color", "#f2f2f2" );
jQuery('input[name="data\\[7\\].input"]').css( "background-color", "#f2f2f2" );

</script>

<div class="stripegroup">
  <label class="stripebox">
    <span>Cardholder</span>
    <input name="cardholder-name" class="field" placeholder="Jane Doe" />
  </label>
  <label class="stripebox">
    <span>CardNum</span>
    <div id="card-element" class="field"></div>
  </label>

  <div class="outcome">
    <div id="carderror" role="alert"></div>
  </div>

  <button type="button" id="stripeTokenization">Tokenization</button>
  <div id="stripenote"> * Tokenized by Stripe.com, your credit card details will Not be submitted to Questetra.</div>

  <div class="outcome">
    <div id="cardsuccess"></div>
  </div>
</div>

<フォーム開始画面>

<データ項目一覧画面>


[雛形ダウンロード (無料)]
<類似プロセス>
≪関連記事≫

[英文記事 (English Entry) ]

0 件のコメント :

コメントを投稿