class ActiveMerchant::Billing::OptimalPaymentGateway

Public Class Methods

new(options = {}) click to toggle source
Calls superclass method ActiveMerchant::Billing::Gateway::new
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 21
def initialize(options = {})
  if options[:login]
    ActiveMerchant.deprecated("The 'login' option is deprecated in favor of 'store_id' and will be removed in a future version.")
    options[:store_id] = options[:login]
  end

  if options[:account]
    ActiveMerchant.deprecated("The 'account' option is deprecated in favor of 'account_number' and will be removed in a future version.")
    options[:account_number] = options[:account]
  end

  requires!(options, :account_number, :store_id, :password)
  super
end

Public Instance Methods

authorize(money, card_or_auth, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 36
def authorize(money, card_or_auth, options = {})
  parse_card_or_auth(card_or_auth, options)
  commit("cc#{@stored_data}Authorize", money, options)
end
Also aliased as: stored_authorize
capture(money, authorization, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 58
def capture(money, authorization, options = {})
  options[:confirmationNumber] = authorization
  commit('ccSettlement', money, options)
end
purchase(money, card_or_auth, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 42
def purchase(money, card_or_auth, options = {})
  parse_card_or_auth(card_or_auth, options)
  commit("cc#{@stored_data}Purchase", money, options)
end
Also aliased as: stored_purchase
refund(money, authorization, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 48
def refund(money, authorization, options = {})
  options[:confirmationNumber] = authorization
  commit('ccCredit', money, options)
end
scrub(transcript) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 76
def scrub(transcript)
  transcript.
    gsub(%r((%3CstorePwd%3E).*(%3C(%2F|/)storePwd%3E))i, '\1[FILTERED]\2').
    gsub(%r((%3CcardNum%3E)\d*(%3C(%2F|/)cardNum%3E))i, '\1[FILTERED]\2').
    gsub(%r((%3Ccvd%3E)\d*(%3C(%2F|/)cvd%3E))i, '\1[FILTERED]\2')
end
store(credit_card, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 68
def store(credit_card, options = {})
  verify(credit_card, options)
end
stored_authorize(money, card_or_auth, options = {})
Alias for: authorize
stored_purchase(money, card_or_auth, options = {})
Alias for: purchase
supports_scrubbing?() click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 72
def supports_scrubbing?
  true
end
verify(credit_card, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 63
def verify(credit_card, options = {})
  parse_card_or_auth(credit_card, options)
  commit('ccVerification', 0, options)
end
void(authorization, options = {}) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 53
def void(authorization, options = {})
  options[:confirmationNumber] = authorization
  commit('ccAuthorizeReversal', nil, options)
end

Private Instance Methods

authorization_from(response) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 151
def authorization_from(response)
  get_text_from_document(response, '//confirmationNumber')
end
avs_result_from(response) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 155
def avs_result_from(response)
  get_text_from_document(response, '//avsResponse')
end
build_address(xml, addr) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 308
def build_address(xml, addr)
  if addr[:name]
    first_name, last_name = split_names(addr[:name])
    xml.tag! 'firstName', first_name
    xml.tag! 'lastName', last_name
  end
  xml.tag! 'street', addr[:address1] if addr[:address1].present?
  xml.tag! 'street2', addr[:address2] if addr[:address2].present?
  xml.tag! 'city', addr[:city] if addr[:city].present?
  if addr[:state].present?
    state_tag = %w(US CA).include?(addr[:country]) ? 'state' : 'region'
    xml.tag! state_tag, addr[:state]
  end
  xml.tag! 'country', addr[:country] if addr[:country].present?
  xml.tag! 'zip', addr[:zip] if addr[:zip].present?
  xml.tag! 'phone', addr[:phone] if addr[:phone].present?
end
build_billing_details(xml, opts) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 293
def build_billing_details(xml, opts)
  xml.tag! 'billingDetails' do
    xml.tag! 'cardPayMethod', 'WEB'
    build_address(xml, opts[:billing_address]) if opts[:billing_address]
    xml.tag! 'email', opts[:email] if opts[:email]
  end
end
build_card(xml, opts) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 274
def build_card(xml, opts)
  xml.tag! 'card' do
    xml.tag! 'cardNum', @credit_card.number
    xml.tag! 'cardExpiry' do
      xml.tag! 'month', @credit_card.month
      xml.tag! 'year', @credit_card.year
    end
    if brand = card_type(@credit_card.brand)
      xml.tag! 'cardType', brand
    end
    if @credit_card.verification_value?
      xml.tag! 'cvdIndicator', '1' # Value Provided
      xml.tag! 'cvd', @credit_card.verification_value
    else
      xml.tag! 'cvdIndicator', '0'
    end
  end
end
build_merchant_account(xml) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 266
def build_merchant_account(xml)
  xml.tag! 'merchantAccount' do
    xml.tag! 'accountNum', @options[:account_number]
    xml.tag! 'storeID',    @options[:store_id]
    xml.tag! 'storePwd',   @options[:password]
  end
end
build_shipping_details(xml, opts) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 301
def build_shipping_details(xml, opts)
  xml.tag! 'shippingDetails' do
    build_address(xml, opts[:shipping_address])
    xml.tag! 'email', opts[:email] if opts[:email]
  end if opts[:shipping_address].present?
end
card_type(key) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 326
def card_type(key)
  { 'visa'            => 'VI',
    'master'          => 'MC',
    'american_express' => 'AM',
    'discover'        => 'DI',
    'diners_club'     => 'DC' }[key]
end
cc_auth_request(money, opts) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 195
def cc_auth_request(money, opts)
  xml_document('ccAuthRequestV1') do |xml|
    build_merchant_account(xml)
    xml.merchantRefNum opts[:order_id]
    xml.amount(money / 100.0)
    build_card(xml, opts)
    build_billing_details(xml, opts)
    build_shipping_details(xml, opts)
    xml.customerIP opts[:ip] if opts[:ip]
  end
end
cc_auth_reversal_request(opts) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 207
def cc_auth_reversal_request(opts)
  xml_document('ccAuthReversalRequestV1') do |xml|
    build_merchant_account(xml)
    xml.confirmationNumber opts[:confirmationNumber]
    xml.merchantRefNum opts[:order_id]
  end
end
cc_post_auth_request(money, opts) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 215
def cc_post_auth_request(money, opts)
  xml_document('ccPostAuthRequestV1') do |xml|
    build_merchant_account(xml)
    xml.confirmationNumber opts[:confirmationNumber]
    xml.merchantRefNum opts[:order_id]
    xml.amount(money / 100.0)
  end
end
cc_stored_data_request(money, opts) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 224
def cc_stored_data_request(money, opts)
  xml_document('ccStoredDataRequestV1') do |xml|
    build_merchant_account(xml)
    xml.merchantRefNum opts[:order_id]
    xml.confirmationNumber opts[:confirmationNumber]
    xml.amount(money / 100.0)
  end
end
commit(action, money, post) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 99
def commit(action, money, post)
  post[:order_id] ||= 'order_id'

  xml =
    case action
    when 'ccAuthorize', 'ccPurchase', 'ccVerification'
      cc_auth_request(money, post)
    when 'ccCredit', 'ccSettlement'
      cc_post_auth_request(money, post)
    when 'ccStoredDataAuthorize', 'ccStoredDataPurchase'
      cc_stored_data_request(money, post)
    when 'ccAuthorizeReversal'
      cc_auth_reversal_request(post)
    # when 'ccCancelSettle', 'ccCancelCredit', 'ccCancelPayment'
    #  cc_cancel_request(money, post)
    # when 'ccPayment'
    #  cc_payment_request(money, post)
    # when 'ccAuthenticate'
    #  cc_authenticate_request(money, post)
    else
      raise 'Unknown Action'
    end
  txnRequest = escape_uri(xml)
  response = parse(ssl_post(test? ? self.test_url : self.live_url, "txnMode=#{action}&txnRequest=#{txnRequest}"))

  Response.new(
    successful?(response),
    message_from(response),
    hash_from_xml(response),
    test: test?,
    authorization: authorization_from(response),
    avs_result: { code: avs_result_from(response) },
    cvv_result: cvv_result_from(response)
  )
end
cvv_result_from(response) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 159
def cvv_result_from(response)
  get_text_from_document(response, '//cvdResponse')
end
escape_uri(uri) click to toggle source

The upstream is picky and so we can’t use CGI.escape like we want to

# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 136
def escape_uri(uri)
  URI::DEFAULT_PARSER.escape(uri)
end
get_text_from_document(document, node) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 190
def get_text_from_document(document, node)
  node = REXML::XPath.first(document, node)
  node&.text
end
hash_from_xml(response) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 163
def hash_from_xml(response)
  hsh = {}
  %w(confirmationNumber authCode
     decision code description
     actionCode avsResponse cvdResponse
     txnTime duplicateFound).each do |tag|
    node = REXML::XPath.first(response, "//#{tag}")
    hsh[tag] = node.text if node
  end
  REXML::XPath.each(response, '//detail') do |detail|
    next unless detail.is_a?(REXML::Element)

    tag = detail.elements['tag'].text
    value = detail.elements['value'].text
    hsh[tag] = value
  end
  hsh
end
message_from(response) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 144
def message_from(response)
  REXML::XPath.each(response, '//detail') do |detail|
    return detail.elements['value'].text if detail.is_a?(REXML::Element) && detail.elements['tag'].text == 'InternalResponseDescription'
  end
  nil
end
parse(body) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 95
def parse(body)
  REXML::Document.new(body || '')
end
parse_card_or_auth(card_or_auth, options) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 85
def parse_card_or_auth(card_or_auth, options)
  if card_or_auth.respond_to?(:number)
    @credit_card = card_or_auth
    @stored_data = ''
  else
    options[:confirmationNumber] = card_or_auth
    @stored_data = 'StoredData'
  end
end
schema() click to toggle source

untested

def cc_cancel_request(opts)

xml_document('ccCancelRequestV1') do |xml|
  build_merchant_account(xml)
  xml.confirmationNumber opts[:confirmationNumber]
end

end

def cc_payment_request(money, opts)

xml_document('ccPaymentRequestV1') do |xml|
  build_merchant_account(xml)
  xml.merchantRefNum opts[:order_id]
  xml.amount(money/100.0)
  build_card(xml, opts)
  build_billing_details(xml, opts)
end

end

def cc_authenticate_request(opts)

xml_document('ccAuthenticateRequestV1') do |xml|
  build_merchant_account(xml)
  xml.confirmationNumber opts[:confirmationNumber]
  xml.paymentResponse 'myPaymentResponse'
end

end

# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 260
def schema
  { 'xmlns' => 'http://www.optimalpayments.com/creditcard/xmlschema/v1',
    'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
    'xsi:schemaLocation' => 'http://www.optimalpayments.com/creditcard/xmlschema/v1' }
end
successful?(response) click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 140
def successful?(response)
  REXML::XPath.first(response, '//decision').text == 'ACCEPTED' rescue false
end
xml_document(root_tag) { |xml| ... } click to toggle source
# File lib/active_merchant/billing/gateways/optimal_payment.rb, line 182
def xml_document(root_tag)
  xml = Builder::XmlMarkup.new indent: 2
  xml.tag!(root_tag, schema) do
    yield xml
  end
  xml.target!
end