module Veritrans::Tercerog::Mdk::MdkMerchantUtility

MdkMerchantUtility モジュール

Public Class Methods

analyze_merchant_data(merchant_data) click to toggle source

マーチャントデータ(MD)をユーザ定義のキーと値に戻します。

@param

merchant_data マーチャントデータ

@return

ユーザ定義のキーと値 検証エラー時は、nil

# File tgMdk/lib/tg_mdk/mdk_merchant_utility.rb, line 171
def analyze_merchant_data(merchant_data)
  unless merchant_data.is_a? String
    raise ArgumentError
  end

  dec_md = merchant_data.unpack('m').first  # Base64 decode
  matchdata = dec_md.match(/(^.+?)&(.*$)/).to_a  # 最初の'&'で分割する
  org_digest = matchdata[1]
  source = matchdata[2] ? matchdata[2] : ""


  # 検証
  merchant_secret_key = Veritrans::Tercerog::Mdk::MdkConfig.instance.merchant_secret_key
  unless verify_sign(source, merchant_secret_key, org_digest)
    return nil
  end

  # 戻りのHashを生成
  source.split('&').inject({}) do |result, kv|
    key, value = kv.split('=')
    next if key.empty?

    key = CGI.unescape(key)
    value = CGI.unescape(value)

    key = key[1, key.size-1].intern if key[0].chr == ':'
    result[key] = value
    result
  end
end
calc_hmac(merchant_secret_key, message_body) click to toggle source

設定ファイルの秘密鍵を用いてメッセージのダイジェストを取得します。

@param

merchant_secret_key マーチャント認証鍵

@param

message_body メッセージ

@return

ダイジェスト

# File tgMdk/lib/tg_mdk/mdk_merchant_utility.rb, line 90
def calc_hmac(merchant_secret_key, message_body)
  key = [merchant_secret_key].pack("H*")
  OpenSSL::HMAC::hexdigest(OpenSSL::Digest::SHA256.new, key, message_body)
end
check_message?(message_body, content_hmac) click to toggle source

署名を検証します。

@param

message_body メッセージ

@param

content_hmac 検証用に利用する署名

@return

true: 検証成功、 false: 検証失敗

# File tgMdk/lib/tg_mdk/mdk_merchant_utility.rb, line 43
def check_message?(message_body, content_hmac)
  merchant_secret_key = Veritrans::Tercerog::Mdk::MdkConfig.instance.merchant_secret_key
  return self::check_message_by_secret_key?(merchant_secret_key, message_body, content_hmac)
end
check_message_by_secret_key?(merchant_secret_key, message_body, content_hmac) click to toggle source

署名を検証します。

@param

merchant_secret_key マーチャント認証鍵

@param

message_body メッセージ

@param

content_hmac 検証用に利用する署名

@return

true: 検証成功、 false: 検証失敗

# File tgMdk/lib/tg_mdk/mdk_merchant_utility.rb, line 56
def check_message_by_secret_key?(merchant_secret_key, message_body, content_hmac)

  if merchant_secret_key.nil? || merchant_secret_key.empty?
    return false
  end

  if message_body.nil? || message_body.empty?
    return false
  end

  if content_hmac.nil? || content_hmac.empty?
    return false
  end

  param_hmac = content_hmac.split(";v=")[1]
  unless param_hmac
    return false
  end

  hmac = self::calc_hmac(merchant_secret_key, message_body)
  unless hmac
    return false
  end

  hmac == param_hmac
end
create_merchant_data(user_hash_data={}) click to toggle source

マーチャントデータ(MD)を生成します。

@param

user_hash_data マーチャントデータ生成用のユーザ定義のキーと値

@return

マーチャントデータ

# File tgMdk/lib/tg_mdk/mdk_merchant_utility.rb, line 141
def create_merchant_data(user_hash_data={})
  unless user_hash_data.is_a? Hash
    raise ArgumentError
  end

  str_md = user_hash_data.reject {|key, value|
    key.nil? || key.to_s.empty?

  }.inject([]) {|amd, (key, value)|
    key = ":" + key.to_s if key.is_a? Symbol
    amd << [CGI.escape(key), CGI.escape(value ? value : "")].join('=')

  }.join('&')

  merchant_secret_key = Veritrans::Tercerog::Mdk::MdkConfig.instance.merchant_secret_key
  digest = self::sign(str_md, merchant_secret_key)

  str_md = str_md.empty? ? digest : [digest, str_md].join('&')

  [str_md].pack('m').gsub(/\n/, '')
end
get_tripartite_auth_hash() click to toggle source

3者間通信用メッセージダイジェストを取得します。

# File tgMdk/lib/tg_mdk/mdk_merchant_utility.rb, line 21
def get_tripartite_auth_hash
  conf = Veritrans::Tercerog::Mdk::MdkConfig.instance

  merchant_cc_id = conf.merchant_cc_id
  gmnow = Veritrans::Tercerog::Mdk::MdkUtils::mdk_gmtime
  merchant_secret_key = conf.merchant_secret_key
  hash = Veritrans::Tercerog::Mdk::MdkUtils::mdk_digest(merchant_cc_id + gmnow + merchant_secret_key)

  [
    Veritrans::Tercerog::Mdk::MdkUtils::mdk_base64_encode(merchant_cc_id),
    Veritrans::Tercerog::Mdk::MdkUtils::mdk_base64_encode(gmnow),
    Veritrans::Tercerog::Mdk::MdkUtils::mdk_base64_encode(hash),
  ].join('-')
end
sign(value, key) click to toggle source

キー、値、マーチャントCC IDのダイジェストを取得します。

@param

value 値

@param

key キー

@return

ダイジェスト

# File tgMdk/lib/tg_mdk/mdk_merchant_utility.rb, line 103
def sign(value, key)
  if value.nil? || value.empty?
    return nil #return false
  end

  if key.nil? || key.empty?
    return nil #return false
  end

  merchant_cc_id = Veritrans::Tercerog::Mdk::MdkConfig.instance.merchant_cc_id
  message = [merchant_cc_id, key, value].join(':')

  OpenSSL::Digest.hexdigest('sha1', message)
end
verify_sign(value, key, original_digest) click to toggle source

キーと値のダイジェストを検証します。

@param

value 値

@param

key キー

@param

original_digest 取得済みダイジェスト

@return

true: 検証成功、 false: 検証失敗

# File tgMdk/lib/tg_mdk/mdk_merchant_utility.rb, line 126
def verify_sign(value, key, original_digest)
  if original_digest.nil? || original_digest.empty?
    return false
  end

  digest = self::sign(value, key)
  digest == original_digest
end

Private Instance Methods

analyze_merchant_data(merchant_data) click to toggle source

マーチャントデータ(MD)をユーザ定義のキーと値に戻します。

@param

merchant_data マーチャントデータ

@return

ユーザ定義のキーと値 検証エラー時は、nil

# File tgMdk/lib/tg_mdk/mdk_merchant_utility.rb, line 171
def analyze_merchant_data(merchant_data)
  unless merchant_data.is_a? String
    raise ArgumentError
  end

  dec_md = merchant_data.unpack('m').first  # Base64 decode
  matchdata = dec_md.match(/(^.+?)&(.*$)/).to_a  # 最初の'&'で分割する
  org_digest = matchdata[1]
  source = matchdata[2] ? matchdata[2] : ""


  # 検証
  merchant_secret_key = Veritrans::Tercerog::Mdk::MdkConfig.instance.merchant_secret_key
  unless verify_sign(source, merchant_secret_key, org_digest)
    return nil
  end

  # 戻りのHashを生成
  source.split('&').inject({}) do |result, kv|
    key, value = kv.split('=')
    next if key.empty?

    key = CGI.unescape(key)
    value = CGI.unescape(value)

    key = key[1, key.size-1].intern if key[0].chr == ':'
    result[key] = value
    result
  end
end
calc_hmac(merchant_secret_key, message_body) click to toggle source

設定ファイルの秘密鍵を用いてメッセージのダイジェストを取得します。

@param

merchant_secret_key マーチャント認証鍵

@param

message_body メッセージ

@return

ダイジェスト

# File tgMdk/lib/tg_mdk/mdk_merchant_utility.rb, line 90
def calc_hmac(merchant_secret_key, message_body)
  key = [merchant_secret_key].pack("H*")
  OpenSSL::HMAC::hexdigest(OpenSSL::Digest::SHA256.new, key, message_body)
end
check_message?(message_body, content_hmac) click to toggle source

署名を検証します。

@param

message_body メッセージ

@param

content_hmac 検証用に利用する署名

@return

true: 検証成功、 false: 検証失敗

# File tgMdk/lib/tg_mdk/mdk_merchant_utility.rb, line 43
def check_message?(message_body, content_hmac)
  merchant_secret_key = Veritrans::Tercerog::Mdk::MdkConfig.instance.merchant_secret_key
  return self::check_message_by_secret_key?(merchant_secret_key, message_body, content_hmac)
end
check_message_by_secret_key?(merchant_secret_key, message_body, content_hmac) click to toggle source

署名を検証します。

@param

merchant_secret_key マーチャント認証鍵

@param

message_body メッセージ

@param

content_hmac 検証用に利用する署名

@return

true: 検証成功、 false: 検証失敗

# File tgMdk/lib/tg_mdk/mdk_merchant_utility.rb, line 56
def check_message_by_secret_key?(merchant_secret_key, message_body, content_hmac)

  if merchant_secret_key.nil? || merchant_secret_key.empty?
    return false
  end

  if message_body.nil? || message_body.empty?
    return false
  end

  if content_hmac.nil? || content_hmac.empty?
    return false
  end

  param_hmac = content_hmac.split(";v=")[1]
  unless param_hmac
    return false
  end

  hmac = self::calc_hmac(merchant_secret_key, message_body)
  unless hmac
    return false
  end

  hmac == param_hmac
end
create_merchant_data(user_hash_data={}) click to toggle source

マーチャントデータ(MD)を生成します。

@param

user_hash_data マーチャントデータ生成用のユーザ定義のキーと値

@return

マーチャントデータ

# File tgMdk/lib/tg_mdk/mdk_merchant_utility.rb, line 141
def create_merchant_data(user_hash_data={})
  unless user_hash_data.is_a? Hash
    raise ArgumentError
  end

  str_md = user_hash_data.reject {|key, value|
    key.nil? || key.to_s.empty?

  }.inject([]) {|amd, (key, value)|
    key = ":" + key.to_s if key.is_a? Symbol
    amd << [CGI.escape(key), CGI.escape(value ? value : "")].join('=')

  }.join('&')

  merchant_secret_key = Veritrans::Tercerog::Mdk::MdkConfig.instance.merchant_secret_key
  digest = self::sign(str_md, merchant_secret_key)

  str_md = str_md.empty? ? digest : [digest, str_md].join('&')

  [str_md].pack('m').gsub(/\n/, '')
end
get_tripartite_auth_hash() click to toggle source

3者間通信用メッセージダイジェストを取得します。

# File tgMdk/lib/tg_mdk/mdk_merchant_utility.rb, line 21
def get_tripartite_auth_hash
  conf = Veritrans::Tercerog::Mdk::MdkConfig.instance

  merchant_cc_id = conf.merchant_cc_id
  gmnow = Veritrans::Tercerog::Mdk::MdkUtils::mdk_gmtime
  merchant_secret_key = conf.merchant_secret_key
  hash = Veritrans::Tercerog::Mdk::MdkUtils::mdk_digest(merchant_cc_id + gmnow + merchant_secret_key)

  [
    Veritrans::Tercerog::Mdk::MdkUtils::mdk_base64_encode(merchant_cc_id),
    Veritrans::Tercerog::Mdk::MdkUtils::mdk_base64_encode(gmnow),
    Veritrans::Tercerog::Mdk::MdkUtils::mdk_base64_encode(hash),
  ].join('-')
end
sign(value, key) click to toggle source

キー、値、マーチャントCC IDのダイジェストを取得します。

@param

value 値

@param

key キー

@return

ダイジェスト

# File tgMdk/lib/tg_mdk/mdk_merchant_utility.rb, line 103
def sign(value, key)
  if value.nil? || value.empty?
    return nil #return false
  end

  if key.nil? || key.empty?
    return nil #return false
  end

  merchant_cc_id = Veritrans::Tercerog::Mdk::MdkConfig.instance.merchant_cc_id
  message = [merchant_cc_id, key, value].join(':')

  OpenSSL::Digest.hexdigest('sha1', message)
end
verify_sign(value, key, original_digest) click to toggle source

キーと値のダイジェストを検証します。

@param

value 値

@param

key キー

@param

original_digest 取得済みダイジェスト

@return

true: 検証成功、 false: 検証失敗

# File tgMdk/lib/tg_mdk/mdk_merchant_utility.rb, line 126
def verify_sign(value, key, original_digest)
  if original_digest.nil? || original_digest.empty?
    return false
  end

  digest = self::sign(value, key)
  digest == original_digest
end