class ActiveMerchant::Billing::MigsGateway

Constants

API_VERSION

Public Class Methods

new(options = {}) click to toggle source

Creates a new MigsGateway The advanced_login/advanced_password fields are needed for advanced methods such as the capture, refund and status methods

Options

  • :login – The MiGS Merchant ID (REQUIRED)

  • :password – The MiGS Access Code (REQUIRED)

  • :secure_hash – The MiGS Secure Hash

(Required for Server Hosted payments)

  • :advanced_login – The MiGS AMA User

  • :advanced_password – The MiGS AMA User's password

Calls superclass method ActiveMerchant::Billing::Gateway::new
# File lib/active_merchant/billing/gateways/migs.rb, line 46
def initialize(options = {})
  requires!(options, :login, :password)
  super
end

Public Instance Methods

authorize(money, creditcard, options = {})

MiGS works by merchants being either purchase only or authorize/capture So authorize is the same as purchase when in authorize mode

Alias for: purchase
capture(money, authorization, options = {}) click to toggle source

Options

  • :unique_id – A unique id for this request (Max 40 chars).

If not supplied one will be generated.

# File lib/active_merchant/billing/gateways/migs.rb, line 79
def capture(money, authorization, options = {})
  requires!(@options, :advanced_login, :advanced_password)

  post = options.merge(:TransNo => authorization)

  add_amount(post, money, options)
  add_advanced_user(post)
  add_standard_parameters('capture', post, options[:unique_id])
  add_tx_source(post, options)

  commit(post)
end
credit(money, authorization, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 121
def credit(money, authorization, options = {})
  ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
  refund(money, authorization, options)
end
purchase(money, creditcard, options = {}) click to toggle source

Options

  • :order_id – A reference for tracking the order (REQUIRED)

  • :unique_id – A unique id for this request (Max 40 chars).

If not supplied one will be generated.

# File lib/active_merchant/billing/gateways/migs.rb, line 56
def purchase(money, creditcard, options = {})
  requires!(options, :order_id)

  post = {}

  add_amount(post, money, options)
  add_invoice(post, options)
  add_creditcard(post, creditcard)
  add_standard_parameters('pay', post, options[:unique_id])
  add_3ds(post, options)
  add_tx_source(post, options)

  commit(post)
end
Also aliased as: authorize
purchase_offsite_response(data) click to toggle source

Parses a response from purchase_offsite_url once user is redirected back

Parameters

  • data – All params when offsite payment returns

e.g. returns to company.com/return?a=1&b=2, then input “a=1&b=2”

# File lib/active_merchant/billing/gateways/migs.rb, line 192
def purchase_offsite_response(data)
  requires!(@options, :secure_hash)

  response_hash = parse(data)

  expected_secure_hash = calculate_secure_hash(response_hash, @options[:secure_hash])
  unless response_hash[:SecureHash] == expected_secure_hash
    raise SecurityError, 'Secure Hash mismatch, response may be tampered with'
  end

  response_object(response_hash)
end
purchase_offsite_url(money, options = {}) click to toggle source

Generates a URL to redirect user to MiGS to process payment Once user is finished MiGS will redirect back to specified URL With a response hash which can be turned into a Response object with purchase_offsite_response

Options

  • :order_id – A reference for tracking the order (REQUIRED)

  • :locale – Change the language of the redirected page Values are 2 digit locale, e.g. en, es

  • :return_url – the URL to return to once the payment is complete

  • :card_type – Providing this skips the card type step. Values are ActiveMerchant formats: e.g. master, visa, american_express, diners_club

  • :unique_id – Unique id of transaction to find. If not supplied one will be generated.

# File lib/active_merchant/billing/gateways/migs.rb, line 166
def purchase_offsite_url(money, options = {})
  requires!(options, :order_id, :return_url)
  requires!(@options, :secure_hash)

  post = {}

  add_amount(post, money, options)
  add_invoice(post, options)
  add_creditcard_type(post, options[:card_type]) if options[:card_type]

  post[:Locale] = options[:locale] || 'en'
  post[:ReturnURL] = options[:return_url]

  add_standard_parameters('pay', post, options[:unique_id])

  add_secure_hash(post)

  self.server_hosted_url + '?' + post_data(post)
end
refund(money, authorization, options = {}) click to toggle source

Options

  • :unique_id – A unique id for this request (Max 40 chars).

If not supplied one will be generated.

# File lib/active_merchant/billing/gateways/migs.rb, line 96
def refund(money, authorization, options = {})
  requires!(@options, :advanced_login, :advanced_password)

  post = options.merge(:TransNo => authorization)

  add_amount(post, money, options)
  add_advanced_user(post)
  add_standard_parameters('refund', post, options[:unique_id])
  add_tx_source(post, options)

  commit(post)
end
scrub(transcript) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 213
def scrub(transcript)
  transcript.
    gsub(%r((&?CardNum=)\d*(&?)), '\1[FILTERED]\2').
    gsub(%r((&?CardSecurityCode=)\d*(&?)), '\1[FILTERED]\2').
    gsub(%r((&?AccessCode=)[^&]*(&?)), '\1[FILTERED]\2').
    gsub(%r((&?Password=)[^&]*(&?)), '\1[FILTERED]\2').
    gsub(%r((&?3DSXID=)[^&]*(&?)), '\1[FILTERED]\2').
    gsub(%r((&?VerToken=)[^&]*(&?)), '\1[FILTERED]\2')
end
status(unique_id) click to toggle source

Checks the status of a previous transaction This can be useful when a response is not received due to network issues

Parameters

  • unique_id – Unique id of transaction to find. This is the value of the option supplied in other methods or if not supplied is returned with key :MerchTxnRef

# File lib/active_merchant/billing/gateways/migs.rb, line 141
def status(unique_id)
  requires!(@options, :advanced_login, :advanced_password)

  post = {}
  add_advanced_user(post)
  add_standard_parameters('queryDR', post, unique_id)

  commit(post)
end
supports_scrubbing?() click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 209
def supports_scrubbing?
  true
end
test?() click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 205
def test?
  @options[:login].start_with?('TEST')
end
verify(credit_card, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 126
def verify(credit_card, options={})
  MultiResponse.run do |r|
    r.process { authorize(100, credit_card, options) }
    r.process(:ignore_result) { void(r.authorization, options) }
  end
end
void(authorization, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 109
def void(authorization, options = {})
  requires!(@options, :advanced_login, :advanced_password)

  post = options.merge(:TransNo => authorization)

  add_advanced_user(post)
  add_standard_parameters('voidAuthorisation', post, options[:unique_id])
  add_tx_source(post, options)

  commit(post)
end

Private Instance Methods

add_3ds(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 239
def add_3ds(post, options)
  post[:VerType] = options[:ver_type] if options[:ver_type]
  post[:VerToken] = options[:ver_token] if options[:ver_token]
  post['3DSXID'] = options[:three_ds_xid] if options[:three_ds_xid]
  post['3DSECI'] = options[:three_ds_eci] if options[:three_ds_eci]
  post['3DSenrolled'] = options[:three_ds_enrolled] if options[:three_ds_enrolled]
  post['3DSstatus'] = options[:three_ds_status] if options[:three_ds_status]
end
add_advanced_user(post) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 230
def add_advanced_user(post)
  post[:User] = @options[:advanced_login]
  post[:Password] = @options[:advanced_password]
end
add_amount(post, money, options) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 225
def add_amount(post, money, options)
  post[:Amount] = localized_amount(money, options[:currency])
  post[:Currency] = options[:currency] if options[:currency]
end
add_creditcard(post, creditcard) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 252
def add_creditcard(post, creditcard)
  post[:CardNum] = creditcard.number
  post[:CardSecurityCode] = creditcard.verification_value if creditcard.verification_value?
  post[:CardExp] = format(creditcard.year, :two_digits) + format(creditcard.month, :two_digits)
end
add_creditcard_type(post, card_type) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 258
def add_creditcard_type(post, card_type)
  post[:Gateway]  = 'ssl'
  post[:card] = CARD_TYPES.detect { |ct| ct.am_code == card_type }.migs_long_code
end
add_invoice(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 235
def add_invoice(post, options)
  post[:OrderInfo] = options[:order_id]
end
add_secure_hash(post) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 317
def add_secure_hash(post)
  post[:SecureHash] = calculate_secure_hash(post, @options[:secure_hash])
  post[:SecureHashType] = 'SHA256'
end
add_standard_parameters(action, post, unique_id = nil) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 303
def add_standard_parameters(action, post, unique_id = nil)
  post.merge!(
    :Version     => API_VERSION,
    :Merchant    => @options[:login],
    :AccessCode  => @options[:password],
    :Command     => action,
    :MerchTxnRef => unique_id || generate_unique_id.slice(0, 40)
  )
end
add_tx_source(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 248
def add_tx_source(post, options)
  post[:TxSource] = options[:tx_source] if options[:tx_source]
end
calculate_secure_hash(post, secure_hash) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 322
def calculate_secure_hash(post, secure_hash)
  input = post.
          reject { |k| %i[SecureHash SecureHashType].include?(k) }.
          sort.
          map { |(k, v)| "vpc_#{k}=#{v}" }.
          join('&')
  OpenSSL::HMAC.hexdigest('SHA256', [secure_hash].pack('H*'), input).upcase
end
commit(post) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 272
def commit(post)
  add_secure_hash(post) if @options[:secure_hash]
  data = ssl_post self.merchant_hosted_url, post_data(post)
  response_hash = parse(data)
  response_object(response_hash)
end
fraud_review?(response) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 299
def fraud_review?(response)
  ISSUER_RESPONSE_CODES[response[:AcqResponseCode]] == 'Suspected Fraud'
end
parse(body) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 263
def parse(body)
  params = CGI::parse(body)
  hash = {}
  params.each do |key, value|
    hash[key.gsub('vpc_', '').to_sym] = value[0]
  end
  hash
end
post_data(post) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 313
def post_data(post)
  post.collect { |key, value| "vpc_#{key}=#{CGI.escape(value.to_s)}" }.join('&')
end
response_object(response) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 279
def response_object(response)
  avs_response_code = response[:AVSResultCode]
  avs_response_code = 'S' if avs_response_code == 'Unsupported'

  cvv_result_code = response[:CSCResultCode]
  cvv_result_code = 'P' if cvv_result_code == 'Unsupported'

  Response.new(success?(response), response[:Message], response,
    :test => test?,
    :authorization => response[:TransactionNo],
    :fraud_review => fraud_review?(response),
    :avs_result => { :code => avs_response_code },
    :cvv_result => cvv_result_code
  )
end
success?(response) click to toggle source
# File lib/active_merchant/billing/gateways/migs.rb, line 295
def success?(response)
  response[:TxnResponseCode] == '0'
end