# 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