class ActiveMerchant::Billing::IdealBaseGateway

Implementation contains some simplifications

Constants

API_VERSION
AUTHENTICATION_TYPE

These constants will never change for most users

LANGUAGE
SUB_ID

Public Class Methods

new(options = {}) click to toggle source
Calls superclass method ActiveMerchant::Billing::Gateway::new
# File lib/active_merchant/billing/gateways/ideal/ideal_base.rb, line 22
def initialize(options = {})
  requires!(options, :login, :password, :pem)

  options[:pem_password] = options[:password]
  super
end

Public Instance Methods

capture(transaction, options = {}) click to toggle source

Check status of transaction and confirm payment transaction_id must be a valid transaction_id from a prior setup.

# File lib/active_merchant/billing/gateways/ideal/ideal_base.rb, line 38
def capture(transaction, options = {})
  options[:transaction_id] = transaction
  commit(build_status_request(options))
end
issuers() click to toggle source

Get list of issuers from response.issuer_list

# File lib/active_merchant/billing/gateways/ideal/ideal_base.rb, line 44
def issuers
  commit(build_directory_request)
end
setup_purchase(money, options = {}) click to toggle source

Setup transaction. Get redirect_url from response.service_url

# File lib/active_merchant/billing/gateways/ideal/ideal_base.rb, line 30
def setup_purchase(money, options = {})
  requires!(options, :issuer_id, :return_url, :order_id, :currency, :description, :entrance_code)

  commit(build_transaction_request(money, options))
end

Private Instance Methods

build_directory_request() click to toggle source

<?xml version=“1.0” encoding=“UTF-8”?> <DirectoryReq xmlns=“www.idealdesk.com/Message” version=“1.1.0”>

<createDateTimeStamp>2001-12-17T09:30:47.0Z</createDateTimeStamp>
<Merchant>
 <merchantID>000000001</merchantID>
 <subID>0</subID>
 <authentication>1</authentication>
 <token>hashkey</token>
 <tokenCode>WajqV1a3nDen0be2r196g9FGFF=</tokenCode>
</Merchant>

</DirectoryReq>

# File lib/active_merchant/billing/gateways/ideal/ideal_base.rb, line 174
def build_directory_request
  datetimestamp = create_time_stamp
  message = datetimestamp + @options[:login] + SUB_ID
  tokenCode = sign_message(@options[:pem], @options[:password], message)

  xml = Builder::XmlMarkup.new(:indent => 2)
  xml.instruct!
  xml.tag! 'DirectoryReq', 'xmlns' => 'http://www.idealdesk.com/Message', 'version' => API_VERSION do
    xml.tag! 'createDateTimeStamp', datetimestamp
    xml.tag! 'Merchant' do
      xml.tag! 'merchantID', @options[:login]
      xml.tag! 'subID', SUB_ID
      xml.tag! 'authentication', AUTHENTICATION_TYPE
      xml.tag! 'token', token
      xml.tag! 'tokenCode', tokenCode
    end
  end
  xml.target!
end
build_status_request(options) click to toggle source

<?xml version=“1.0” encoding=“UTF-8”?> <AcquirerStatusReq xmlns=“www.idealdesk.com/Message” version=“1.1.0”>

<createDateTimeStamp>2001-12-17T09:30:47.0Z</createDateTimeStamp>
<Merchant>
 <merchantID>000123456</merchantID>
 <subID>0</subID>
 <authentication>keyed hash</authentication>
 <token>1</token>
 <tokenCode>3823ad872eff23</tokenCode>
</Merchant>
<Transaction>
 <transactionID>0001023456789112</transactionID>
</Transaction>

</AcquirerStatusReq>

# File lib/active_merchant/billing/gateways/ideal/ideal_base.rb, line 140
def build_status_request(options)
  datetimestamp = create_time_stamp
  message = datetimestamp + @options[:login] + SUB_ID + options[:transaction_id]
  tokenCode = sign_message(@options[:pem], @options[:password], message)

  xml = Builder::XmlMarkup.new(:indent => 2)
  xml.instruct!
  xml.tag! 'AcquirerStatusReq', 'xmlns' => 'http://www.idealdesk.com/Message', 'version' => API_VERSION do
    xml.tag! 'createDateTimeStamp', datetimestamp
    xml.tag! 'Merchant' do
      xml.tag! 'merchantID', @options[:login]
      xml.tag! 'subID', SUB_ID
      xml.tag! 'authentication' , AUTHENTICATION_TYPE
      xml.tag! 'token', token
      xml.tag! 'tokenCode', tokenCode
    end
    xml.tag! 'Transaction' do
      xml.tag! 'transactionID', options[:transaction_id]
    end
  end
  xml.target!
end
build_transaction_request(money, options) click to toggle source

<?xml version=“1.0” encoding=“UTF-8”?> <AcquirerTrxReq xmlns=“www.idealdesk.com/Message” version=“1.1.0”>

<createDateTimeStamp>2001-12-17T09:30:47.0Z</createDateTimeStamp>
<Issuer>
 <issuerID>1003</issuerID>
</Issuer>
 <Merchant>
   <merchantID>000123456</merchantID>
   <subID>0</subID>
   <authentication>passkey</authentication>
   <token>1</token>
   <tokenCode>3823ad872eff23</tokenCode>
   <merchantReturnURL>https://www.mijnwinkel.nl/betaalafhandeling
    </merchantReturnURL>
 </Merchant>
 <Transaction>
   <purchaseID>iDEAL-aankoop 21</purchaseID>
   <amount>5999</amount>
   <currency>EUR</currency>
   <expirationPeriod>PT3M30S</expirationPeriod>
   <language>nl</language>
   <description>Documentensuite</description>
   <entranceCode>D67tyx6rw9IhY71</entranceCode>
 </Transaction>

</AcquirerTrxReq>

# File lib/active_merchant/billing/gateways/ideal/ideal_base.rb, line 83
def build_transaction_request(money, options)
  date_time_stamp = create_time_stamp
  message  = date_time_stamp +
             options[:issuer_id] +
             @options[:login] +
             SUB_ID +
             options[:return_url] +
             options[:order_id] +
             money.to_s +
             (options[:currency] || currency(money)) +
             LANGUAGE +
             options[:description] +
             options[:entrance_code]
  token_code = sign_message(@options[:pem], @options[:password], message)

  xml = Builder::XmlMarkup.new(:indent => 2)
  xml.instruct!
  xml.tag! 'AcquirerTrxReq', 'xmlns' => 'http://www.idealdesk.com/Message', 'version' => API_VERSION do
    xml.tag! 'createDateTimeStamp', date_time_stamp
    xml.tag! 'Issuer' do
      xml.tag! 'issuerID', options[:issuer_id]
    end
    xml.tag! 'Merchant' do
      xml.tag! 'merchantID', @options[:login]
      xml.tag! 'subID', SUB_ID
      xml.tag! 'authentication', AUTHENTICATION_TYPE
      xml.tag! 'token', token
      xml.tag! 'tokenCode', token_code
      xml.tag! 'merchantReturnURL', options[:return_url]
    end
    xml.tag! 'Transaction' do
      xml.tag! 'purchaseID', options[:order_id]
      xml.tag! 'amount', money
      xml.tag! 'currency', options[:currency]
      xml.tag! 'expirationPeriod', options[:expiration_period] || default_expiration_period
      xml.tag! 'language', LANGUAGE
      xml.tag! 'description', options[:description]
      xml.tag! 'entranceCode', options[:entrance_code]
    end
    xml.target!
  end
end
commit(request) click to toggle source
# File lib/active_merchant/billing/gateways/ideal/ideal_base.rb, line 194
def commit(request)
  raw_response = ssl_post(url, request)
  response = Hash.from_xml(raw_response.to_s)
  response_type = response.keys[0]

  case response_type
    when 'AcquirerTrxRes', 'DirectoryRes'
      success = true
    when 'ErrorRes'
      success = false
    when 'AcquirerStatusRes'
      raise SecurityError, "Message verification failed.", caller unless status_response_verified?(response)
      success = (response['AcquirerStatusRes']['Transaction']['status'] == 'Success')
    else
      raise ArgumentError, "Unknown response type.", caller
  end

  return IdealResponse.new(success, response.keys[0], response, :test => test?)
end
create_fingerprint(cert_file) click to toggle source
# File lib/active_merchant/billing/gateways/ideal/ideal_base.rb, line 214
def create_fingerprint(cert_file)
  cert_data   = OpenSSL::X509::Certificate.new(cert_file).to_s
  cert_data   = cert_data.sub(/-----BEGIN CERTIFICATE-----/, '')
  cert_data   = cert_data.sub(/-----END CERTIFICATE-----/, '')
  fingerprint = Base64.decode64(cert_data)
  fingerprint = Digest::SHA1.hexdigest(fingerprint)
  return fingerprint.upcase
end
create_time_stamp() click to toggle source
# File lib/active_merchant/billing/gateways/ideal/ideal_base.rb, line 241
def create_time_stamp
  Time.now.gmtime.strftime('%Y-%m-%dT%H:%M:%S.000Z')
end
sign_message(private_key_data, password, data) click to toggle source
# File lib/active_merchant/billing/gateways/ideal/ideal_base.rb, line 223
def sign_message(private_key_data, password, data)
  private_key  = OpenSSL::PKey::RSA.new(private_key_data, password)
  signature = private_key.sign(OpenSSL::Digest::SHA1.new, data.gsub('\s', ''))
  return Base64.encode64(signature).gsub(/\n/, '')
end
status_response_verified?(response) click to toggle source
# File lib/active_merchant/billing/gateways/ideal/ideal_base.rb, line 234
def status_response_verified?(response)
  transaction = response['AcquirerStatusRes']['Transaction']
  message = response['AcquirerStatusRes']['createDateTimeStamp'] + transaction['transactionID' ] + transaction['status']
  message << transaction['consumerAccountNumber'].to_s
  verify_message(server_pem, message, response['AcquirerStatusRes']['Signature']['signatureValue'])
end
token() click to toggle source
# File lib/active_merchant/billing/gateways/ideal/ideal_base.rb, line 54
def token
  @token ||= create_fingerprint(@options[:pem])
end
url() click to toggle source
# File lib/active_merchant/billing/gateways/ideal/ideal_base.rb, line 50
def url
  (test? ? test_url : live_url)
end
verify_message(cert_file, data, signature) click to toggle source
# File lib/active_merchant/billing/gateways/ideal/ideal_base.rb, line 229
def verify_message(cert_file, data, signature)
  public_key = OpenSSL::X509::Certificate.new(cert_file).public_key
  return public_key.verify(OpenSSL::Digest::SHA1.new, Base64.decode64(signature), data)
end