lib/active_merchant/billing/gateways/blue_snap.rb in activemerchant-1.112.0 vs lib/active_merchant/billing/gateways/blue_snap.rb in activemerchant-1.113.0

- old
+ new

@@ -56,11 +56,11 @@ 'line1: N, zip: M, name: U' => 'W', 'line1: N, zip: M, name: M' => 'L', 'line1: N, zip: M, name: N' => 'W', 'line1: N, zip: N, name: U' => 'N', 'line1: N, zip: N, name: M' => 'K', - 'line1: N, zip: N, name: N' => 'N', + 'line1: N, zip: N, name: N' => 'N' } BANK_ACCOUNT_TYPE_MAPPING = { 'personal_checking' => 'CONSUMER_CHECKING', 'personal_savings' => 'CONSUMER_SAVINGS', @@ -210,24 +210,40 @@ doc.send('expiration-month', card.month) doc.send('expiration-year', card.year) end end - def add_description(doc, description) + def add_metadata(doc, options) + transaction_meta_data = options.fetch(:transaction_meta_data, {}) + return if transaction_meta_data.empty? && !options[:description] + doc.send('transaction-meta-data') do - doc.send('meta-data') do - doc.send('meta-key', 'description') - doc.send('meta-value', truncate(description, 500)) - doc.send('meta-description', 'Description') + # ensure backwards compatibility for calls expecting :description + # to become meta-data fields. + if options[:description] + doc.send('meta-data') do + doc.send('meta-key', 'description') + doc.send('meta-value', truncate(options[:description], 500)) + doc.send('meta-description', 'Description') + end end + + # https://developers.bluesnap.com/v8976-XML/docs/meta-data + transaction_meta_data.each do |entry| + doc.send('meta-data') do + doc.send('meta-key', truncate(entry[:meta_key], 40)) + doc.send('meta-value', truncate(entry[:meta_value], 500)) + doc.send('meta-description', truncate(entry[:meta_description], 40)) + end + end end end def add_order(doc, options) doc.send('merchant-transaction-id', truncate(options[:order_id], 50)) if options[:order_id] doc.send('soft-descriptor', options[:soft_descriptor]) if options[:soft_descriptor] - add_description(doc, options[:description]) if options[:description] + add_metadata(doc, options) add_3ds(doc, options[:three_d_secure]) if options[:three_d_secure] add_level_3_data(doc, options) end def add_address(doc, options) @@ -313,11 +329,11 @@ doc.send('vaulted-shopper-id', vaulted_shopper_id) if vaulted_shopper_id add_echeck_transaction(doc, payment_method_details.payment_method, options, vaulted_shopper_id.present?) if payment_method_details.check? add_fraud_info(doc, options) - add_description(doc, options) + add_metadata(doc, options) end def add_echeck_transaction(doc, check, options, vaulted_shopper) unless vaulted_shopper doc.send('payer-info') do @@ -348,23 +364,44 @@ return forbidden_response(response.body) if response.code.to_i == 403 parsed = {} doc = Nokogiri::XML(response.body) doc.root.xpath('*').each do |node| + name = node.name.downcase + if node.elements.empty? - parsed[node.name.downcase] = node.text + parsed[name] = node.text + elsif name == 'transaction-meta-data' + metadata = [] + node.elements.each { |m| + metadata.push parse_metadata_entry(m) + } + + parsed['transaction-meta-data'] = metadata else - node.elements.each do |childnode| + node.elements.each { |childnode| parse_element(parsed, childnode) - end + } end end parsed['content-location-header'] = response['content-location'] parsed end + def parse_metadata_entry(node) + entry = {} + + node.elements.each { |e| + entry = entry.merge({ + e.name => e.text + }) + } + + entry + end + def parse_element(parsed, node) if !node.elements.empty? node.elements.each { |e| parse_element(parsed, e) } else parsed[node.name.downcase] = node.text @@ -474,10 +511,10 @@ end def headers { 'Content-Type' => 'application/xml', - 'Authorization' => ('Basic ' + Base64.strict_encode64("#{@options[:api_username]}:#{@options[:api_password]}").strip), + 'Authorization' => ('Basic ' + Base64.strict_encode64("#{@options[:api_username]}:#{@options[:api_password]}").strip) } end def build_xml_request(action, payment_method_details) builder = Nokogiri::XML::Builder.new