lib/active_merchant/billing/gateways/borgun.rb in activemerchant-1.126.0 vs lib/active_merchant/billing/gateways/borgun.rb in activemerchant-1.129.0

- old
+ new

@@ -21,22 +21,38 @@ super end def purchase(money, payment, options = {}) post = {} - post[:TransType] = '1' + action = '' + if options[:apply_3d_secure] == '1' + add_3ds_preauth_fields(post, options) + action = '3ds_preauth' + else + post[:TransType] = '1' + add_3ds_fields(post, options) + action = 'sale' + end add_invoice(post, money, options) add_payment_method(post, payment) - commit('sale', post) + commit(action, post, options) end def authorize(money, payment, options = {}) post = {} - post[:TransType] = '5' + action = '' + if options[:apply_3d_secure] == '1' + add_3ds_preauth_fields(post, options) + action = '3ds_preauth' + else + post[:TransType] = '5' + add_3ds_fields(post, options) + action = 'authonly' + end add_invoice(post, money, options) add_payment_method(post, payment) - commit('authonly', post, options) + commit(action, post, options) end def capture(money, authorization, options = {}) post = {} post[:TransType] = '1' @@ -79,13 +95,30 @@ CURRENCY_CODES = Hash.new { |_h, k| raise ArgumentError.new("Unsupported currency for HDFC: #{k}") } CURRENCY_CODES['ISK'] = '352' CURRENCY_CODES['EUR'] = '978' CURRENCY_CODES['USD'] = '840' + def add_3ds_fields(post, options) + post[:ThreeDSMessageId] = options[:three_ds_message_id] if options[:three_ds_message_id] + post[:ThreeDS_PARes] = options[:three_ds_pares] if options[:three_ds_pares] + post[:ThreeDS_CRes] = options[:three_ds_cres] if options[:three_ds_cres] + end + + def add_3ds_preauth_fields(post, options) + post[:SaleDescription] = options[:sale_description] || '' + post[:MerchantReturnURL] = options[:merchant_return_url] if options[:merchant_return_url] + end + def add_invoice(post, money, options) post[:TrAmount] = amount(money) post[:TrCurrency] = CURRENCY_CODES[options[:currency] || currency(money)] + # The ISK currency must have a currency exponent of 2 on the 3DS request but not on the auth request + if post[:TrCurrency] == '352' && options[:apply_3d_secure] == '1' + post[:TrCurrencyExponent] = 2 + else + post[:TrCurrencyExponent] = 0 + end post[:TerminalID] = options[:terminal_id] || '1' end def add_payment_method(post, payment_method) post[:PAN] = payment_method.number @@ -101,15 +134,15 @@ post[:Transaction] = transaction post[:RRN] = rrn post[:AuthCode] = authcode end - def parse(xml) + def parse(xml, options = nil) response = {} doc = Nokogiri::XML(CGI.unescapeHTML(xml)) - body = doc.xpath('//getAuthorizationReply') + body = options[:apply_3d_secure] == '1' ? doc.xpath('//get3DSAuthenticationReply') : doc.xpath('//getAuthorizationReply') body = doc.xpath('//cancelAuthorizationReply') if body.length == 0 body.children.each do |node| if node.text? next elsif node.elements.size == 0 @@ -119,22 +152,21 @@ name = "#{node.name.downcase}_#{childnode.name.downcase}" response[name.to_sym] = childnode.text end end end - response end def commit(action, post, options = {}) post[:Version] = '1000' post[:Processor] = @options[:processor] post[:MerchantID] = @options[:merchant_id] request = build_request(action, post, options) raw = ssl_post(url(action), request, headers) - pairs = parse(raw) + pairs = parse(raw, options) success = success_from(pairs) Response.new( success, message_from(success, pairs), @@ -143,11 +175,11 @@ test: test? ) end def success_from(response) - (response[:actioncode] == '000') + (response[:actioncode] == '000') || (response[:status_resultcode] == '0') end def message_from(succeeded, response) if succeeded 'Succeeded' @@ -180,20 +212,21 @@ } end def build_request(action, post, options = {}) mode = action == 'void' ? 'cancel' : 'get' + transaction_type = action == '3ds_preauth' ? '3DSAuthentication' : 'Authorization' xml = Builder::XmlMarkup.new indent: 18 xml.instruct!(:xml, version: '1.0', encoding: 'utf-8') - xml.tag!("#{mode}Authorization") do + xml.tag!("#{mode}#{transaction_type}") do post.each do |field, value| xml.tag!(field, value) end build_airline_xml(xml, options[:passenger_itinerary_data]) if options[:passenger_itinerary_data] end inner = CGI.escapeHTML(xml.target!) - envelope(mode).sub(/{{ :body }}/, inner) + envelope(mode, action).sub(/{{ :body }}/, inner) end def build_airline_xml(xml, airline_data) xml.tag!('PassengerItineraryData') do xml.tag!('A1') do @@ -202,19 +235,26 @@ end end end end - def envelope(mode) + def envelope(mode, action) + if action == '3ds_preauth' + transaction_action = "#{mode}3DSAuthentication" + request_action = "#{mode}Auth3DSReqXml" + else + transaction_action = "#{mode}AuthorizationInput" + request_action = "#{mode}AuthReqXml" + end <<-XML <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:aut="http://Borgun/Heimir/pub/ws/Authorization"> <soapenv:Header/> <soapenv:Body> - <aut:#{mode}AuthorizationInput> - <#{mode}AuthReqXml> + <aut:#{transaction_action}> + <#{request_action}> {{ :body }} - </#{mode}AuthReqXml> - </aut:#{mode}AuthorizationInput> + </#{request_action}> + </aut:#{transaction_action}> </soapenv:Body> </soapenv:Envelope> XML end