#gmo ペイメント決済 トークン仕様

ペイメントトークンの特徴

  • 一度利用すると無効になる
  • 発行後、有効期限は 30 分

#処理結果コード一覧

コード意味
000トークン取得正常終了
100カード番号必須チェックエラー
101カード番号フォーマットエラー(数字以外を含む)
102カード番号フォーマットエラー(10-16 桁の範囲外)
110有効期限必須チェックエラー
111有効期限フォーマットエラー(数字以外を含む)
112有効期限フォーマットエラー(6 又は 4 桁以外)
113有効期限フォーマットエラー(月が 13 以上)
121セキュリティコードフォーマットエラー(数字以外を含む)
122セキュリティコード桁数エラー
131名義人フォーマットエラー(半角英数字、一部の記号以外を含む)
132名義人フォーマットエラー(51 桁以上)
141発行数フォーマットエラー(数字以外を含む)
142発行数フォーマットエラー(1-10 の範囲外)
150カード情報を暗号化した情報必須チェックエラー
160ショップ ID 必須チェックエラー
161ショップ ID フォーマットエラー(14 桁以上)
162ショップ ID フォーマットエラー(半角英数字以外)
170公開鍵ハッシュ値必須チェックエラー
180ショップ ID または公開鍵ハッシュ値がマスターに存在しない
190カード情報(Encrypted)が復号できない
191カード情報(Encrypted)復号化後フォーマットエラー
501トークン用パラメータ(id)が送信されていない
502トークン用パラメータ(id)がマスターに存在しない
511トークン用パラメータ(cardInfo)が送信されていない
512トークン用パラメータ(cardInfo)が復号できない
521トークン用パラメータ(key)が送信されていない
522トークン用パラメータ(key)が復号できない
531トークン用パラメータ(callBack)が送信されていない
541トークン用パラメータ(hash)が存在しない
551トークン用 apikey が存在しない ID
552トークン用 apikey が有効ではない
901マルチペイメント内部のシステムエラー
902処理が混み合っている

#112:有効期限フォーマットエラー(6 又は 4 桁以外)

カード有効期限のフォーマットは expire_year + expire_month

例えば、カード期限が 01 月 24 年 の場合

202401
2401

のどれかになります。

#551:トークン用 apikey が存在しない ID

肉まんエラーは基本的に本番環境とテスト環境の js 切り替えミスった時に発生するもの

#Multipayment マルチペイメントオブジェクト使ってトークン取得

本番とテスト用のライブラリがある

環境URL
本番https://p01.mul-pay.jp/ext/js/token.js
テストhttps://pt01.mul-pay.jp/ext/js/token.js

テスト環境は一文字長い。。。tって

#token.js ってなにやってるの?

    config: {
        api: {
            host: "https://p01.mul-pay.jp",
            context: "/ext/api/getToken"
        },
        version: "5",
        key: "",
        type: "",
        test: !1,
        Pubkey: "...省略..."
    },
    init: function(t) {
        this.config.key = t
    },
    getToken: function(cardObj, callback) {
        var callbackName, callbackObj = null;
        if ("function" == typeof callback) this._callbackOrg = callback, callbackObj = callback, void 0 != callback.name && "" != callback.name ? callbackName = callback.name : (callbackName = new String(" " + callback).replace(/^\s*function\s*([^\( ]+)[\S\s]+$/im, "$1"), callbackName.match(/\(/) && (callbackName = "Multipayment._callback"));
        else {
            if ("string" != typeof callback) return;
            this._callbackOrg = eval(callback), callbackName = callback
        }
        var checkResult = this._checkCardObj(cardObj);
        if (0 != checkResult.resultStatus) return void(null == callbackObj ? eval(callbackName + "( { resultCode: " + checkResult.resultStatus + "} )") : callbackObj({
            resultCode: checkResult.resultStatus
        }));
        var encryptedParam = this._createEncryptedParam(cardObj),
            keySource = "iv=" + encryptedParam.iv + "&salt=" + encryptedParam.salt,
            enc = new JSEncrypt;
        enc.setPublicKey(this.config.Pubkey);
        var encryptedKeySource = enc.encrypt(keySource),
            signature = CryptoJS.SHA1(this.config.key + "|" + encryptedKeySource + "|" + encryptedParam.paramString + "|" + callbackName),
            url = this.config.api.host + this.config.api.context + "?key=" + encodeURIComponent(encryptedKeySource) + "&callback=" + encodeURIComponent(callbackName) + "&publicKey=" + encodeURIComponent(this.config.key) + "&encrypted=" + encodeURIComponent(encryptedParam.paramString) + "&seal=" + encodeURIComponent(signature) + "&version=" + this.config.version;
        this._jsonp(url)
    },

test: !1って勉強になる

因みに!-1!0!1!別の出力

console.log(!-1); // false

console.log(!0); // true

console.log(!1); // false

console.log(!);  // Error: Unexpected token ')'

当たり前だけど、!はエラーになる

#Multipayment 関数使うリクエスト

#ライブラリ読み込む

<!-- テスト環境 -->
<script src="https://pt01.mul-pay.jp/ext/js/token.js"></script>

<!-- 本番環境 -->
<script src="https://p01.mul-pay.jp/ext/js/token.js"></script>

間違うと肉まんエラー

#Multipayment 登場

仕様

Multipayment.init(ショップID);
Multipayment.getToken(オブジェクト, コールバックファンクション);

getToken が大事

  • オブジェクト
    • cardno カード番号
    • expire 有効期限
    • securitycode セキュリティーコード
    • holdername カード名義
    • tokennumber トークン取得数(1-10 まで設定できる・設定なしは 1 と見なす)
  • コールバックファンクション 結果受け取り
Multipayment.getToken(
  {
    cardno: cardno,
    expire: expire,
    securitycode: securitycode,
    holdername: holdername,
    tokennumber: tokennumber
  },
  execPurchase
);

#レスポンス返却結果

カテゴリ

項目意味
resultCode処理結果コード
tokenObject返却トークンオブジェクト

tokenObject 構造

  • maskedCardNo 一部マスターされたカード番号
  • toBeExpiredAt 取得タイムスタンプ
  • isSecurityCodeSet セキュリティーコードありなし
  • token 発行したトークン配列

こんな感じサンプル

{
  "tokenObject": {
    "maskedCardNo": "411112*******111",
    "toBeExpiredAt": "2020-03-04-05-06-07",
    "isSecurityCodeSet": true,
    "token": [
      "cd3834b816884ffab8a310c00f085599150a11f820566d16a8d120efad378394"
    ]
  },
  "resultCode": "000"
}

#demo コード

#クレカ html フォーム

<!-- クレジットカード入力フォーム -->
<form id="getTokenForm">
  <p>カード番号: <input type="text" value="" name="cardno" id="cardno" /></p>
  <p>
    カード有効期限:
    <input type="text" value="" name="expire_year" id="expire_year" />/
    <input type="text" value="" name="expire_month" id="expire_month" />
  </p>
  <p>
    カード名義人:
    <input type="text" value="" name="holdername" id="holdername" />
  </p>
  <p>
    セキュリティコード:
    <input type="text" value="" name="securitycode" id="securitycode" />
  </p>

  <p><input type="button" value="購入" onclick="doPurchase()" /></p>
</form>

<!-- サブミットフォーム -->
<form id="purchaseForm" action="" method="post">
  <p>
    <!-- トークン -->
    <input type="hidden" value="" id="token" name="token" />
  </p>
</form>

#javascript

ヘッダーにライブラリ読み込んでからの話



















 















































 
 









var Multipayment,
  CryptoJS,
  JSEncryptExports,
  JSEncrypt,
  ASN1,
  Base64,
  Hex,
  KJUR;
function doPurchase() {
  var cardno, expire, securitycode, holdername;

  var cardno = document.getElementById("cardno").value;
  var expire =
    document.getElementById("expire_year").value +
    document.getElementById("expire_month").value;
  var securitycode = document.getElementById("securitycode").value;
  var holdername = document.getElementById("holdername").value;
  var tokennumber = 1;
  Multipayment.init("<?php echo env('SHOP_ID'); ?>");

  Multipayment.getToken(
    {
      cardno: cardno,
      expire: expire,
      securitycode: securitycode,
      holdername: holdername,
      tokennumber: tokennumber
    },
    response => {
      var tokenError = {
        "000": "トークン取得正常終了",
        "100": "カード番号必須チェックエラー",
        "101": "カード番号フォーマットエラー(数字以外を含む)",
        "102": "カード番号フォーマットエラー(10-16 桁の範囲外)",
        "110": "有効期限必須チェックエラー",
        "111": "有効期限フォーマットエラー(数字以外を含む)",
        "112": "有効期限フォーマットエラー(6 又は 4 桁以外)",
        "113": "有効期限フォーマットエラー(月が 13 以上)",
        "121": "セキュリティコードフォーマットエラー(数字以外を含む)",
        "122": "セキュリティコード桁数エラー",
        "131": "名義人フォーマットエラー(半角英数字、一部の記号以外を含む)",
        "132": "名義人フォーマットエラー(51 桁以上)",
        "141": "発行数フォーマットエラー(数字以外を含む)",
        "142": "発行数フォーマットエラー(1-10 の範囲外)",
        "150": "カード情報を暗号化した情報必須チェックエラー",
        "160": "ショップ ID 必須チェックエラー",
        "161": "ショップ ID フォーマットエラー(14 桁以上)",
        "162": "ショップ ID フォーマットエラー(半角英数字以外)",
        "170": "公開鍵ハッシュ値必須チェックエラー",
        "180": "ショップ ID または公開鍵ハッシュ値がマスターに存在しない",
        "190": "カード情報(Encrypted)が復号できない",
        "191": "カード情報(Encrypted)復号化後フォーマットエラー",
        "501": "トークン用パラメータ(id)が送信されていない",
        "502": "トークン用パラメータ(id)がマスターに存在しない",
        "511": "トークン用パラメータ(cardInfo)が送信されていない",
        "512": "トークン用パラメータ(cardInfo)が復号できない",
        "521": "トークン用パラメータ(key)が送信されていない",
        "522": "トークン用パラメータ(key)が復号できない",
        "531": "トークン用パラメータ(callBack)が送信されていない",
        "541": "トークン用パラメータ(hash)が存在しない",
        "551": "トークン用 apikey が存在しない ID",
        "552": "トークン用 apikey が有効ではない",
        "901": "マルチペイメント内部のシステムエラー",
        "902": "処理が混み合っている"
      };
      if (response.resultCode == "000") {
        $("#token").val(response.tokenObject.token);
        $("#purchaseForm").submit();
      } else if (response.resultCode in tokenError) {
        alert(tokenError[response.resultCode]);
      } else {
        alert("エラー発生しました。");
      }
    }
  );
}
2020-03-06
  • gmo