class ActiveMerchant::Billing::MoneiGateway

Monei gateway

This class implements Monei gateway for Active Merchant. For more information about Monei gateway please go to www.monei.com

Setup

In order to set-up the gateway you need only one paramater: the api_key Request that data to Monei.

Public Class Methods

new(options = {}) click to toggle source

Constructor

options - Hash containing the gateway credentials, ALL MANDATORY

:api_key      Account's API KEY
Calls superclass method ActiveMerchant::Billing::Gateway::new
# File lib/active_merchant/billing/gateways/monei.rb, line 29
def initialize(options = {})
  requires!(options, :api_key)
  super
end

Public Instance Methods

authorize(money, payment_method, options = {}) click to toggle source

Public: Performs authorization operation

money - Amount to authorize payment_method - Credit card options - Hash containing authorization options

:order_id         Merchant created id for the authorization
:billing_address  Hash with billing address information
:description      Merchant created authorization description (optional)
:currency         Sale currency to override money object or default (optional)

Returns Active Merchant response object

# File lib/active_merchant/billing/gateways/monei.rb, line 60
def authorize(money, payment_method, options = {})
  execute_new_order(:authorize, money, payment_method, options)
end
capture(money, authorization, options = {}) click to toggle source

Public: Performs capture operation on previous authorization

money - Amount to capture authorization - Reference to previous authorization, obtained from response object returned by authorize options - Hash containing capture options

:order_id         Merchant created id for the authorization (optional)
:description      Merchant created authorization description (optional)
:currency         Sale currency to override money object or default (optional)

Note: you should pass either order_id or description

Returns Active Merchant response object

# File lib/active_merchant/billing/gateways/monei.rb, line 76
def capture(money, authorization, options = {})
  execute_dependant(:capture, money, authorization, options)
end
purchase(money, payment_method, options = {}) click to toggle source

Public: Performs purchase operation

money - Amount of purchase payment_method - Credit card options - Hash containing purchase options

:order_id         Merchant created id for the purchase
:billing_address  Hash with billing address information
:description      Merchant created purchase description (optional)
:currency         Sale currency to override money object or default (optional)

Returns Active Merchant response object

# File lib/active_merchant/billing/gateways/monei.rb, line 45
def purchase(money, payment_method, options = {})
  execute_new_order(:purchase, money, payment_method, options)
end
refund(money, authorization, options = {}) click to toggle source

Public: Refunds from previous purchase

money - Amount to refund authorization - Reference to previous purchase, obtained from response object returned by purchase options - Hash containing refund options

:order_id         Merchant created id for the authorization (optional)
:description      Merchant created authorization description (optional)
:currency         Sale currency to override money object or default (optional)

Note: you should pass either order_id or description

Returns Active Merchant response object

# File lib/active_merchant/billing/gateways/monei.rb, line 92
def refund(money, authorization, options = {})
  execute_dependant(:refund, money, authorization, options)
end
scrub(transcript) click to toggle source
# File lib/active_merchant/billing/gateways/monei.rb, line 132
def scrub(transcript)
  transcript.
    gsub(%r((Authorization: )\w+), '\1[FILTERED]').
    gsub(%r(("number\\?":\\?")[^"]*)i, '\1[FILTERED]').
    gsub(%r(("cvc\\?":\\?")[^"]*)i, '\1[FILTERED]').
    gsub(%r(("cavv\\?":\\?")[^"]*)i, '\1[FILTERED]')
end
store(payment_method, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/monei.rb, line 124
def store(payment_method, options = {})
  execute_new_order(:store, 0, payment_method, options)
end
supports_scrubbing?() click to toggle source
# File lib/active_merchant/billing/gateways/monei.rb, line 128
def supports_scrubbing?
  true
end
verify(payment_method, options = {}) click to toggle source

Public: Verifies credit card. Does this by doing a authorization of 1.00 Euro and then voiding it.

payment_method - Credit card options - Hash containing authorization options

:order_id         Merchant created id for the authorization
:billing_address  Hash with billing address information
:description      Merchant created authorization description (optional)
:currency         Sale currency to override money object or default (optional)

Returns Active Merchant response object of Authorization operation

# File lib/active_merchant/billing/gateways/monei.rb, line 117
def verify(payment_method, options = {})
  MultiResponse.run(:use_first_response) do |r|
    r.process { authorize(100, payment_method, options) }
    r.process(:ignore_result) { void(r.authorization, options) }
  end
end
void(authorization, options = {}) click to toggle source

Public: Voids previous authorization

authorization - Reference to previous authorization, obtained from response object returned by authorize options - Hash containing capture options

:order_id         Merchant created id for the authorization (optional)

Returns Active Merchant response object

# File lib/active_merchant/billing/gateways/monei.rb, line 103
def void(authorization, options = {})
  execute_dependant(:void, nil, authorization, options)
end

Private Instance Methods

add_3ds1_authenticated_data(request, options) click to toggle source
# File lib/active_merchant/billing/gateways/monei.rb, line 264
def add_3ds1_authenticated_data(request, options)
  three_d_secure_options = options[:three_d_secure]
  request[:paymentMethod][:card][:auth] = {
    cavv: three_d_secure_options[:cavv],
    cavvAlgorithm: three_d_secure_options[:cavv_algorithm],
    eci: three_d_secure_options[:eci],
    xid: three_d_secure_options[:xid],
    directoryResponse: three_d_secure_options[:enrolled],
    authenticationResponse: three_d_secure_options[:authentication_response_status]
  }
end
add_3ds2_authenticated_data(request, options) click to toggle source
# File lib/active_merchant/billing/gateways/monei.rb, line 276
def add_3ds2_authenticated_data(request, options)
  three_d_secure_options = options[:three_d_secure]
  # If the transaction was authenticated in a frictionless flow, send the transStatus from the ARes.
  if three_d_secure_options[:authentication_response_status].nil?
    authentication_response = three_d_secure_options[:directory_response_status]
  else
    authentication_response = three_d_secure_options[:authentication_response_status]
  end
  request[:paymentMethod][:card][:auth] = {
    threeDSVersion: three_d_secure_options[:version],
    eci: three_d_secure_options[:eci],
    cavv: three_d_secure_options[:cavv],
    dsTransID: three_d_secure_options[:ds_transaction_id],
    directoryResponse: three_d_secure_options[:directory_response_status],
    authenticationResponse: authentication_response
  }
end
add_3ds_authenticated_data(request, options) click to toggle source

Private: add the already validated 3DSecure info to request

# File lib/active_merchant/billing/gateways/monei.rb, line 256
def add_3ds_authenticated_data(request, options)
  if options[:three_d_secure] && options[:three_d_secure][:eci] && options[:three_d_secure][:xid]
    add_3ds1_authenticated_data(request, options)
  elsif options[:three_d_secure]
    add_3ds2_authenticated_data(request, options)
  end
end
add_browser_info(request, options) click to toggle source
# File lib/active_merchant/billing/gateways/monei.rb, line 294
def add_browser_info(request, options)
  request[:sessionDetails][:ip] = options[:ip] if options[:ip]
  request[:sessionDetails][:userAgent] = options[:user_agent] if options[:user_agent]
  request[:sessionDetails][:lang] = options[:lang] if options[:lang]
end
add_customer(request, payment_method, options) click to toggle source

Private: Add customer part to request

# File lib/active_merchant/billing/gateways/monei.rb, line 209
def add_customer(request, payment_method, options)
  address = options[:billing_address] || options[:address]

  request[:customer] = {}
  request[:customer][:email] = options[:email] || 'support@monei.net'

  if address
    request[:customer][:name] = address[:name].to_s if address[:name]

    request[:billingDetails] = {}
    request[:billingDetails][:email] = options[:email] if options[:email]
    request[:billingDetails][:name] = address[:name] if address[:name]
    request[:billingDetails][:company] = address[:company] if address[:company]
    request[:billingDetails][:phone] = address[:phone] if address[:phone]
    request[:billingDetails][:address] = {}
    request[:billingDetails][:address][:line1] = address[:address1] if address[:address1]
    request[:billingDetails][:address][:line2] = address[:address2] if address[:address2]
    request[:billingDetails][:address][:city] = address[:city] if address[:city]
    request[:billingDetails][:address][:state] = address[:state] if address[:state].present?
    request[:billingDetails][:address][:zip] = address[:zip].to_s if address[:zip]
    request[:billingDetails][:address][:country] = address[:country] if address[:country]
  end

  request[:sessionDetails] = {}
  request[:sessionDetails][:ip] = options[:ip] if options[:ip]
end
add_identification_authorization(request, authorization, options) click to toggle source

Private: Add identification part to request for orders that depend on authorization from previous operation

# File lib/active_merchant/billing/gateways/monei.rb, line 178
def add_identification_authorization(request, authorization, options)
  options[:paymentId] = authorization
  request[:orderId] = options[:order_id] if options[:order_id]
end
add_identification_new_order(request, options) click to toggle source

Private: Add identification part to request for new orders

# File lib/active_merchant/billing/gateways/monei.rb, line 172
def add_identification_new_order(request, options)
  requires!(options, :order_id)
  request[:orderId] = options[:order_id]
end
add_payment(request, payment_method) click to toggle source

Private: Add payment method to request

# File lib/active_merchant/billing/gateways/monei.rb, line 194
def add_payment(request, payment_method)
  if payment_method.is_a? String
    request[:paymentToken] = payment_method
  else
    request[:paymentMethod] = {}
    request[:paymentMethod][:card] = {}
    request[:paymentMethod][:card][:number] = payment_method.number
    request[:paymentMethod][:card][:expMonth] = format(payment_method.month, :two_digits)
    request[:paymentMethod][:card][:expYear] = format(payment_method.year, :two_digits)
    request[:paymentMethod][:card][:cvc] = payment_method.verification_value.to_s
    request[:paymentMethod][:card][:cardholderName] = payment_method.name
  end
end
add_transaction(request, action, money, options) click to toggle source

Private: Add payment part to request

# File lib/active_merchant/billing/gateways/monei.rb, line 184
def add_transaction(request, action, money, options)
  request[:transactionType] = translate_payment_code(action)
  request[:description] = options[:description] || options[:order_id]
  unless money.nil?
    request[:amount] = amount(money).to_i
    request[:currency] = options[:currency] || currency(money)
  end
end
api_request(url, parameters, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/monei.rb, line 320
def api_request(url, parameters, options = {})
  raw_response = response = nil
  begin
    raw_response = ssl_post(url, post_data(parameters), options)
    response = parse(raw_response)
  rescue ResponseError => e
    raw_response = e.response.body
    response = response_error(raw_response)
  rescue JSON::ParserError
    response = json_error(raw_response)
  end
  response
end
authorization_from(response, action) click to toggle source

Private: Get authorization code from servers response

# File lib/active_merchant/billing/gateways/monei.rb, line 379
def authorization_from(response, action)
  case action
  when :store
    return response['paymentToken']
  else
    return response['id']
  end
end
build_request() click to toggle source

Private: Build request object

# File lib/active_merchant/billing/gateways/monei.rb, line 165
def build_request
  request = {}
  request[:livemode] = test? ? 'false' : 'true'
  request
end
commit(request, action, options) click to toggle source

Private: Send transaction to Monei servers and create AM response

# File lib/active_merchant/billing/gateways/monei.rb, line 335
def commit(request, action, options)
  url = (test? ? test_url : live_url)
  endpoint = translate_action_endpoint(action, options)
  headers = {
    'Content-Type': 'application/json;charset=UTF-8',
    Authorization: @options[:api_key],
    'User-Agent': 'MONEI/Shopify/0.1.0'
  }

  response = api_request(url + endpoint, params(request, action), headers)
  success = success_from(response)

  Response.new(
    success,
    message_from(response, success),
    response,
    authorization: authorization_from(response, action),
    test: test?,
    error_code: error_code_from(response, success)
  )
end
eci_to_result_indicator(eci) click to toggle source

Private : Convert ECI to ResultIndicator Possible ECI values: 02 or 05 - Fully Authenticated Transaction 00 or 07 - Non 3D Secure Transaction Possible ResultIndicator values: 01 = MASTER_3D_ATTEMPT 02 = MASTER_3D_SUCCESS 05 = VISA_3D_SUCCESS 06 = VISA_3D_ATTEMPT 07 = DEFAULT_E_COMMERCE

# File lib/active_merchant/billing/gateways/monei.rb, line 246
def eci_to_result_indicator(eci)
  case eci
  when '02', '05'
    return eci
  else
    return '07'
  end
end
error_code_from(response, success) click to toggle source

Private: Get error code from servers response

# File lib/active_merchant/billing/gateways/monei.rb, line 374
def error_code_from(response, success)
  success ? nil : STANDARD_ERROR_CODE[:card_declined]
end
execute_dependant(action, money, authorization, options) click to toggle source

Private: Execute operation that depends on authorization code from previous purchase or authorize operation

# File lib/active_merchant/billing/gateways/monei.rb, line 155
def execute_dependant(action, money, authorization, options)
  request = build_request

  add_identification_authorization(request, authorization, options)
  add_transaction(request, action, money, options)

  commit(request, action, options)
end
execute_new_order(action, money, payment_method, options) click to toggle source

Private: Execute purchase or authorize operation

# File lib/active_merchant/billing/gateways/monei.rb, line 143
def execute_new_order(action, money, payment_method, options)
  request = build_request
  add_identification_new_order(request, options)
  add_transaction(request, action, money, options)
  add_payment(request, payment_method)
  add_customer(request, payment_method, options)
  add_3ds_authenticated_data(request, options)
  add_browser_info(request, options)
  commit(request, action, options)
end
json_error(raw_response) click to toggle source
# File lib/active_merchant/billing/gateways/monei.rb, line 305
def json_error(raw_response)
  msg = 'Invalid response received from the MONEI API. Please contact support@monei.net if you continue to receive this message.'
  msg += " (The raw response returned by the API was #{raw_response.inspect})"
  {
    'status' => 'error',
    'message' => msg
  }
end
message_from(response, success) click to toggle source

Private: Get message from servers response

# File lib/active_merchant/billing/gateways/monei.rb, line 369
def message_from(response, success)
  success ? 'Transaction approved' : response.fetch('statusMessage', response.fetch('message', 'No error details'))
end
params(request, action) click to toggle source

Private: generate request params depending on action

# File lib/active_merchant/billing/gateways/monei.rb, line 394
def params(request, action)
  request[:generatePaymentToken] = true if action == :store
  request
end
parse(body) click to toggle source

Private: Parse JSON response from Monei servers

# File lib/active_merchant/billing/gateways/monei.rb, line 301
def parse(body)
  JSON.parse(body)
end
post_data(params) click to toggle source

Private: Encode POST parameters

# File lib/active_merchant/billing/gateways/monei.rb, line 389
def post_data(params)
  params.clone.to_json
end
response_error(raw_response) click to toggle source
# File lib/active_merchant/billing/gateways/monei.rb, line 314
def response_error(raw_response)
  parse(raw_response)
rescue JSON::ParserError
  json_error(raw_response)
end
success_from(response) click to toggle source

Private: Decide success from servers response

# File lib/active_merchant/billing/gateways/monei.rb, line 358
def success_from(response)
  %w[
    SUCCEEDED
    AUTHORIZED
    REFUNDED
    PARTIALLY_REFUNDED
    CANCELED
  ].include? response['status']
end
translate_action_endpoint(action, options) click to toggle source

Private: Translate AM operations to Monei endpoints

# File lib/active_merchant/billing/gateways/monei.rb, line 412
def translate_action_endpoint(action, options)
  {
    purchase: '',
    store: '',
    authorize: '',
    capture: "/#{options[:paymentId]}/capture",
    refund: "/#{options[:paymentId]}/refund",
    void: "/#{options[:paymentId]}/cancel"
  }[action]
end
translate_payment_code(action) click to toggle source

Private: Translate AM operations to Monei operations codes

# File lib/active_merchant/billing/gateways/monei.rb, line 400
def translate_payment_code(action)
  {
    purchase: 'SALE',
    store: 'SALE',
    authorize: 'AUTH',
    capture: 'CAPTURE',
    refund: 'REFUND',
    void: 'CANCEL'
  }[action]
end