class ActiveMerchant::Billing::GlobalCollectGateway

Constants

BRAND_MAP

Public Class Methods

new(options={}) click to toggle source
Calls superclass method ActiveMerchant::Billing::Gateway::new
# File lib/active_merchant/billing/gateways/global_collect.rb, line 15
def initialize(options={})
  requires!(options, :merchant_id, :api_key_id, :secret_api_key)
  super
end

Public Instance Methods

authorize(money, payment, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 27
def authorize(money, payment, options={})
  post = nestable_hash
  add_order(post, money, options)
  add_payment(post, payment, options)
  add_customer_data(post, options, payment)
  add_address(post, payment, options)
  add_creator_info(post, options)
  add_fraud_fields(post, options)

  commit(:authorize, post)
end
capture(money, authorization, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 39
def capture(money, authorization, options={})
  post = nestable_hash
  add_order(post, money, options, capture: true)
  add_customer_data(post, options)
  add_creator_info(post, options)
  commit(:capture, post, authorization)
end
purchase(money, payment, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 20
def purchase(money, payment, options={})
  MultiResponse.run do |r|
    r.process { authorize(money, payment, options) }
    r.process { capture(money, r.authorization, options) } unless capture_requested?(r)
  end
end
refund(money, authorization, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 47
def refund(money, authorization, options={})
  post = nestable_hash
  add_amount(post, money, options)
  add_refund_customer_data(post, options)
  add_creator_info(post, options)
  commit(:refund, post, authorization)
end
scrub(transcript) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 72
def scrub(transcript)
  transcript.
    gsub(%r((Authorization: )[^\\]*)i, '\1[FILTERED]').
    gsub(%r(("cardNumber\\+":\\+")\d+), '\1[FILTERED]').
    gsub(%r(("cvv\\+":\\+")\d+), '\1[FILTERED]')
end
supports_scrubbing?() click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 68
def supports_scrubbing?
  true
end
verify(payment, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 61
def verify(payment, options={})
  MultiResponse.run(:use_first_response) do |r|
    r.process { authorize(100, payment, options) }
    r.process { void(r.authorization, options) }
  end
end
void(authorization, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 55
def void(authorization, options={})
  post = nestable_hash
  add_creator_info(post, options)
  commit(:void, post, authorization)
end

Private Instance Methods

add_address(post, creditcard, options) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 168
def add_address(post, creditcard, options)
  shipping_address = options[:shipping_address]
  if billing_address = options[:billing_address] || options[:address]
    post['order']['customer']['billingAddress'] = {
      'street' => billing_address[:address1],
      'additionalInfo' => billing_address[:address2],
      'zip' => billing_address[:zip],
      'city' => billing_address[:city],
      'state' => billing_address[:state],
      'countryCode' => billing_address[:country]
    }
  end
  if shipping_address
    post['order']['customer']['shippingAddress'] = {
      'street' => shipping_address[:address1],
      'additionalInfo' => shipping_address[:address2],
      'zip' => shipping_address[:zip],
      'city' => shipping_address[:city],
      'state' => shipping_address[:state],
      'countryCode' => shipping_address[:country]
    }
    post['order']['customer']['shippingAddress']['name'] = {
      'firstName' => shipping_address[:firstname],
      'surname' => shipping_address[:lastname]
    }
  end
end
add_amount(post, money, options={}) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 116
def add_amount(post, money, options={})
  post['amountOfMoney'] = {
    'amount' => amount(money),
    'currencyCode' => options[:currency] || currency(money)
  }
end
add_creator_info(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 105
def add_creator_info(post, options)
  post['sdkIdentifier'] = options[:sdk_identifier] if options[:sdk_identifier]
  post['sdkCreator'] = options[:sdk_creator] if options[:sdk_creator]
  post['integrator'] = options[:integrator] if options[:integrator]
  post['shoppingCartExtension'] = {}
  post['shoppingCartExtension']['creator'] = options[:creator] if options[:creator]
  post['shoppingCartExtension']['name'] = options[:name] if options[:name]
  post['shoppingCartExtension']['version'] = options[:version] if options[:version]
  post['shoppingCartExtension']['extensionID'] = options[:extension_ID] if options[:extension_ID]
end
add_customer_data(post, options, payment = nil) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 143
def add_customer_data(post, options, payment = nil)
  if payment
    post['order']['customer']['personalInformation']['name']['firstName'] = payment.first_name[0..14] if payment.first_name
    post['order']['customer']['personalInformation']['name']['surname'] = payment.last_name[0..69] if payment.last_name
  end
  post['order']['customer']['merchantCustomerId'] = options[:customer] if options[:customer]
  post['order']['customer']['companyInformation']['name'] = options[:company] if options[:company]
  post['order']['customer']['contactDetails']['emailAddress'] = options[:email] if options[:email]
  if address = options[:billing_address] || options[:address]
    post['order']['customer']['contactDetails']['phoneNumber'] = address[:phone] if address[:phone]
  end
end
add_fraud_fields(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 196
def add_fraud_fields(post, options)
  fraud_fields = {}
  fraud_fields.merge!(options[:fraud_fields]) if options[:fraud_fields]
  fraud_fields[:customerIpAddress] = options[:ip] if options[:ip]

  post['fraudFields'] = fraud_fields unless fraud_fields.empty?
end
add_order(post, money, options, capture: false) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 90
def add_order(post, money, options, capture: false)
  if capture
    post['amount'] = amount(money)
  else
    add_amount(post['order'], money, options)
  end
  post['order']['references'] = {
    'merchantReference' => options[:order_id],
    'descriptor' => options[:description] # Max 256 chars
  }
  post['order']['references']['invoiceData'] = {
    'invoiceNumber' => options[:invoice]
  }
end
add_payment(post, payment, options) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 123
def add_payment(post, payment, options)
  year  = format(payment.year, :two_digits)
  month = format(payment.month, :two_digits)
  expirydate =   "#{month}#{year}"
  pre_authorization = options[:pre_authorization] ? 'PRE_AUTHORIZATION' : 'FINAL_AUTHORIZATION'

  post['cardPaymentMethodSpecificInput'] = {
      'paymentProductId' => BRAND_MAP[payment.brand],
      'skipAuthentication' => 'true', # refers to 3DSecure
      'skipFraudService' => 'true',
      'authorizationMode' => pre_authorization
  }
  post['cardPaymentMethodSpecificInput']['card'] = {
      'cvv' => payment.verification_value,
      'cardNumber' => payment.number,
      'expiryDate' => expirydate,
      'cardholderName' => payment.name
  }
end
add_refund_customer_data(post, options) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 156
def add_refund_customer_data(post, options)
  if address = options[:billing_address] || options[:address]
    post['customer']['address'] = {
      'countryCode' => address[:country]
    }
    post['customer']['contactDetails']['emailAddress'] = options[:email] if options[:email]
    if address = options[:billing_address] || options[:address]
      post['customer']['contactDetails']['phoneNumber'] = address[:phone] if address[:phone]
    end
  end
end
auth_digest(action, post, authorization = nil) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 265
      def auth_digest(action, post, authorization = nil)
        data = <<-EOS
POST
#{content_type}
#{date}
#{uri(action, authorization)}
EOS
        digest = OpenSSL::Digest.new('sha256')
        key = @options[:secret_api_key]
        "GCS v1HMAC:#{@options[:api_key_id]}:#{Base64.strict_encode64(OpenSSL::HMAC.digest(digest, key, data))}"
      end
authorization_from(succeeded, response) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 305
def authorization_from(succeeded, response)
  if succeeded
    response['id'] || response['payment']['id'] || response['paymentResult']['payment']['id']
  elsif response['errorId']
    response['errorId']
  else
    'GATEWAY ERROR'
  end
end
capture_requested?(response) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 331
def capture_requested?(response)
  response.params.try(:[], 'payment').try(:[], 'status') == 'CAPTURE_REQUESTED'
end
commit(action, post, authorization = nil) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 226
def commit(action, post, authorization = nil)
  begin
    raw_response = ssl_post(url(action, authorization), post.to_json, headers(action, post, authorization))
    response = parse(raw_response)
  rescue ResponseError => e
    if e.response.code.to_i >= 400
      response = parse(e.response.body)
    end
  rescue JSON::ParserError
    response = json_error(raw_response)
  end

  succeeded = success_from(response)
  Response.new(
    succeeded,
    message_from(succeeded, response),
    response,
    authorization: authorization_from(succeeded, response),
    error_code: error_code_from(succeeded, response),
    test: test?
  )
end
content_type() click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 281
def content_type
  'application/json'
end
date() click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 277
def date
  @date ||= Time.now.strftime('%a, %d %b %Y %H:%M:%S %Z') # Must be same in digest and HTTP header
end
error_code_from(succeeded, response) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 315
def error_code_from(succeeded, response)
  unless succeeded
    if errors = response['errors']
      errors.first.try(:[], 'code')
    elsif status = response.try(:[], 'statusOutput').try(:[], 'statusCode')
      status.to_s
    else
      'No error code available'
    end
  end
end
headers(action, post, authorization = nil) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 257
def headers(action, post, authorization = nil)
  {
    'Content-Type'  => content_type,
    'Authorization' => auth_digest(action, post, authorization),
    'Date' => date
  }
end
json_error(raw_response) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 249
def json_error(raw_response)
  {
    'error_message' => 'Invalid response received from the Ingenico ePayments (formerly GlobalCollect) API.  Please contact Ingenico ePayments if you continue to receive this message.' \
      "  (The raw response returned by the API was #{raw_response.inspect})",
    'status' => 'REJECTED'
  }
end
message_from(succeeded, response) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 289
def message_from(succeeded, response)
  if succeeded
    'Succeeded'
  else
    if errors = response['errors']
      errors.first.try(:[], 'message')
    elsif response['error_message']
      response['error_message']
    elsif response['status']
      'Status: ' + response['status']
    else
      'No message available'
    end
  end
end
nestable_hash() click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 327
def nestable_hash
  Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }
end
parse(body) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 204
def parse(body)
  JSON.parse(body)
end
success_from(response) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 285
def success_from(response)
  !response['errorId'] && response['status'] != 'REJECTED'
end
uri(action, authorization) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 212
def uri(action, authorization)
  uri = "/v1/#{@options[:merchant_id]}/"
  case action
  when :authorize
    uri + 'payments'
  when :capture
    uri + "payments/#{authorization}/approve"
  when :refund
    uri + "payments/#{authorization}/refund"
  when :void
    uri + "payments/#{authorization}/cancel"
  end
end
url(action, authorization) click to toggle source
# File lib/active_merchant/billing/gateways/global_collect.rb, line 208
def url(action, authorization)
  (test? ? test_url : live_url) + uri(action, authorization)
end