class Pay2go::Client

Constants

CREDITCARD_COLLECT_REFUND_API_ENDPOINTS
CREDITCARD_DEAUTHORIZE_API_ENDPOINTS
NEED_CHECK_VALUE_APIS
TRANSACTION_API_ENDPOINTS

Attributes

options[R]

Public Class Methods

new(options = {}) click to toggle source
# File lib/pay2go/client.rb, line 27
def initialize options = {}
  @options = { mode: :production }.merge!(options)

  case @options[:mode]
  when :test, :production
    option_required! :merchant_id, :hash_key, :hash_iv
  else
    raise InvalidMode, %Q{option :mode is either :test or :production}
  end

  @options.freeze
end

Public Instance Methods

credit_card_collect_refund(params = {}) click to toggle source
# File lib/pay2go/client.rb, line 108
def credit_card_collect_refund params = {}
  param_required! params, [:Amt, :IndexType, :CloseType]

  raise MissingOption, %Q{One of the following param is required: MerchantOrderNo, TradeNo} if params[:MerchantOrderNo].nil? and params[:TradeNo].nil?

  post_params = {
    RespondType: 'String',
    Version: '1.0',
    TimeStamp: Time.now.to_i
  }.merge!(params)

  res = request :credit_card_collect_refund, post_params
  Hash[res.body.split('&').map!{|i| URI::decode(i.force_encoding('ASCII-8BIT').force_encoding('UTF-8')).split('=')}]
end
credit_card_collect_refund_by_merchant_order_no(params = {}) click to toggle source
# File lib/pay2go/client.rb, line 123
def credit_card_collect_refund_by_merchant_order_no params = {}
  param_required! params, [:Amt, :MerchantOrderNo, :CloseType]

  post_params = {
    IndexType: 1
  }.merge!(params)

  credit_card_collect_refund post_params
end
credit_card_collect_refund_by_trade_no(params = {}) click to toggle source
# File lib/pay2go/client.rb, line 133
def credit_card_collect_refund_by_trade_no params = {}
  param_required! params, [:Amt, :TradeNo, :CloseType]

  post_params = {
    IndexType: 1
  }.merge!(params)

  credit_card_collect_refund post_params
end
credit_card_deauthorize(params = {}) click to toggle source
# File lib/pay2go/client.rb, line 71
def credit_card_deauthorize params = {}
  param_required! params, [:Amt, :IndexType]

  raise MissingOption, %Q{One of the following param is required: MerchantOrderNo, TradeNo} if params[:MerchantOrderNo].nil? and params[:TradeNo].nil?

  post_params = {
    RespondType: 'String',
    Version: '1.0',
    TimeStamp: Time.now.to_i
  }.merge!(params)

  post_params.delete_if { |key, value| value.nil? }

  res = request :credit_card_deauthorize, post_params
  Hash[res.body.split('&').map!{|i| URI::decode(i.force_encoding('ASCII-8BIT').force_encoding('UTF-8')).split('=')}]
end
credit_card_deauthorize_by_merchant_order_no(params = {}) click to toggle source
# File lib/pay2go/client.rb, line 88
def credit_card_deauthorize_by_merchant_order_no params = {}
  param_required! params, [:Amt, :MerchantOrderNo]

  post_params = {
    IndexType: 1
  }.merge!(params)

  credit_card_deauthorize post_params
end
credit_card_deauthorize_by_trade_no(params = {}) click to toggle source
# File lib/pay2go/client.rb, line 98
def credit_card_deauthorize_by_trade_no params = {}
  param_required! params, [:Amt, :TradeNo]

  post_params = {
    IndexType: 2
  }.merge!(params)

  credit_card_deauthorize post_params
end
encode_post_data(data) click to toggle source
# File lib/pay2go/client.rb, line 178
def encode_post_data data
  cipher = OpenSSL::Cipher::AES256.new(:CBC)
  cipher.encrypt
  cipher.padding = 0
  cipher.key = @options[:hash_key]
  cipher.iv = @options[:hash_iv]
  data = add_padding(data)
  encrypted = cipher.update(data) + cipher.final
  encrypted.unpack('H*').first
end
generate_credit_card_period_params(params = {}) click to toggle source
# File lib/pay2go/client.rb, line 143
def generate_credit_card_period_params params = {}
  param_required! params, [:MerchantOrderNo, :ProdDesc, :PeriodAmt, :PeriodAmtMode, :PeriodType, :PeriodPoint, :PeriodStartType, :PeriodTimes]

  generate_params(:credit_card_period, {
    RespondType: 'String',
    TimeStamp: Time.now.to_i,
    Version: '1.0'
  }.merge!(params))
end
generate_mpg_params(params = {}) click to toggle source
# File lib/pay2go/client.rb, line 46
def generate_mpg_params params = {}
  param_required! params, [:MerchantOrderNo, :Amt, :ItemDesc, :Email, :LoginType]

  post_params = {
    RespondType: 'String',
    TimeStamp: Time.now.to_i,
    Version: '1.2'
  }.merge!(params)

  generate_params(:mpg, post_params)
end
make_check_value(type, params = {}) click to toggle source
# File lib/pay2go/client.rb, line 153
def make_check_value type, params = {}
  case type
  when :mpg
    check_value_fields = [:Amt, :MerchantID, :MerchantOrderNo, :TimeStamp, :Version]
    padded = "HashKey=#{@options[:hash_key]}&%s&HashIV=#{@options[:hash_iv]}"
  when :query_trade_info
    check_value_fields = [:Amt, :MerchantID, :MerchantOrderNo]
    padded = "IV=#{@options[:hash_iv]}&%s&Key=#{@options[:hash_key]}"
  when :credit_card_period
    check_value_fields = [:MerchantID, :MerchantOrderNo, :PeriodAmt, :PeriodType, :TimeStamp]
    padded = "HashKey=#{@options[:hash_key]}&%s&HashIV=#{@options[:hash_iv]}"
  else
    raise UnsupportedType, "Unsupported API type."
  end

  param_required! params, check_value_fields

  raw = params.select { |key, value| key.to_s.match(/^(#{check_value_fields.join('|')})$/) }
    .sort_by{ |k, v| k.downcase }.map!{ |k, v| "#{k}=#{v}" }.join('&')

  padded = padded % raw

  Digest::SHA256.hexdigest(padded).upcase!
end
query_trade_info(params = {}) click to toggle source
# File lib/pay2go/client.rb, line 58
def query_trade_info params = {}
  param_required! params, [:MerchantOrderNo, :Amt]

  post_params = {
    Version: '1.1',
    RespondType: 'String',
    TimeStamp: Time.now.to_i
  }.merge!(params)

  res = request :query_trade_info, post_params
  Hash[res.body.split('&').map!{|i| URI::decode(i).split('=')}]
end
verify_check_code(params = {}) click to toggle source
# File lib/pay2go/client.rb, line 40
def verify_check_code params = {}
  stringified_keys = params.stringify_keys
  check_code = stringified_keys.delete('CheckCode')
  make_check_code(stringified_keys) == check_code
end

Private Instance Methods

add_padding(text, size = 32) click to toggle source
# File lib/pay2go/client.rb, line 239
def add_padding text, size = 32
  len = text.length
  pad = size - (len % size)
  text = text + (pad.chr * pad)
end
generate_params(type, overwrite_params = {}) click to toggle source
# File lib/pay2go/client.rb, line 210
def generate_params type, overwrite_params = {}
  result = overwrite_params.clone
  result[:MerchantID] = @options[:merchant_id]
  result[:CheckValue] = make_check_value(type, result)
  result
end
make_check_code(params = {}) click to toggle source
# File lib/pay2go/client.rb, line 203
def make_check_code params = {}
  raw = params.select { |key, value| key.to_s.match(/^(Amt|MerchantID|MerchantOrderNo|TradeNo)$/) }
    .sort_by{ |k, v| k.downcase }.map!{ |k, v| "#{k}=#{v}" }.join('&')
  padded = "HashIV=#{@options[:hash_iv]}&#{raw}&HashKey=#{@options[:hash_key]}"
  Digest::SHA256.hexdigest(padded).upcase!
end
option_required!(*option_names) click to toggle source
# File lib/pay2go/client.rb, line 191
def option_required! *option_names
  option_names.each do |option_name|
    raise MissingOption, %Q{option "#{option_name}" is required.} if @options[option_name].nil?
  end
end
param_required!(params, param_names) click to toggle source
# File lib/pay2go/client.rb, line 197
def param_required! params, param_names
  param_names.each do |param_name|
    raise MissingParameter, %Q{param "#{param_name}" is required.} if params[param_name].nil?
  end
end
request(type, params = {}) click to toggle source
# File lib/pay2go/client.rb, line 217
def request type, params = {}
  case type
  when :query_trade_info
    api_url = TRANSACTION_API_ENDPOINTS[@options[:mode]]
  when :credit_card_deauthorize
    api_url = CREDITCARD_DEAUTHORIZE_API_ENDPOINTS[@options[:mode]]
  when :credit_card_collect_refund
    api_url = CREDITCARD_COLLECT_REFUND_API_ENDPOINTS[@options[:mode]]
  end

  if NEED_CHECK_VALUE_APIS.include?(type)
    post_params = generate_params(type, params)
  else
    post_params = {
      MerchantID_: @options[:merchant_id],
      PostData_: encode_post_data(URI.encode(params.map{ |key, value| "#{key}=#{value}" }.join("&")))
    }
  end

  Net::HTTP.post_form URI(api_url), post_params
end