# File lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb, line 4 4: def self.included(base) 5: base.default_currency = 'USD' 6: 7: base.class_attribute :partner 8: 9: # Set the default partner to PayPal 10: base.partner = 'PayPal' 11: 12: base.supported_countries = ['US', 'CA', 'SG', 'AU'] 13: 14: base.class_attribute :timeout 15: base.timeout = 60 16: 17: # Enable safe retry of failed connections 18: # Payflow is safe to retry because retried transactions use the same 19: # X-VPS-Request-ID header. If a transaction is detected as a duplicate 20: # only the original transaction data will be used by Payflow, and the 21: # subsequent Responses will have a :duplicate parameter set in the params 22: # hash. 23: base.retry_safe = true 24: end
# File lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb, line 56 56: def initialize(options = {}) 57: requires!(options, :login, :password) 58: 59: @options = options 60: @options[:partner] = partner if @options[:partner].blank? 61: super 62: end
# File lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb, line 68 68: def capture(money, authorization, options = {}) 69: request = build_reference_request(:capture, money, authorization, options) 70: commit(request, options) 71: end
# File lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb, line 122 122: def add_address(xml, tag, address, options) 123: return if address.nil? 124: xml.tag! tag do 125: xml.tag! 'Name', address[:name] unless address[:name].blank? 126: xml.tag! 'EMail', options[:email] unless options[:email].blank? 127: xml.tag! 'Phone', address[:phone] unless address[:phone].blank? 128: xml.tag! 'CustCode', options[:customer] if !options[:customer].blank? && tag == 'BillTo' 129: 130: xml.tag! 'Address' do 131: xml.tag! 'Street', address[:address1] unless address[:address1].blank? 132: xml.tag! 'City', address[:city] unless address[:city].blank? 133: xml.tag! 'State', address[:state].blank? ? "N/A" : address[:state] 134: xml.tag! 'Country', address[:country] unless address[:country].blank? 135: xml.tag! 'Zip', address[:zip] unless address[:zip].blank? 136: end 137: end 138: end
# File lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb, line 181 181: def build_headers(content_length) 182: { 183: "Content-Type" => "text/xml", 184: "Content-Length" => content_length.to_s, 185: "X-VPS-Client-Timeout" => timeout.to_s, 186: "X-VPS-VIT-Integration-Product" => "ActiveMerchant", 187: "X-VPS-VIT-Runtime-Version" => RUBY_VERSION, 188: "X-VPS-Request-ID" => Utils.generate_unique_id 189: } 190: end
# File lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb, line 107 107: def build_reference_request(action, money, authorization, options) 108: xml = Builder::XmlMarkup.new 109: xml.tag! TRANSACTIONS[action] do 110: xml.tag! 'PNRef', authorization 111: 112: unless money.nil? 113: xml.tag! 'Invoice' do 114: xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money) 115: end 116: end 117: end 118: 119: xml.target! 120: end
# File lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb, line 79 79: def build_request(body, options = {}) 80: xml = Builder::XmlMarkup.new 81: xml.instruct! 82: xml.tag! 'XMLPayRequest', 'Timeout' => timeout.to_s, 'version' => "2.1", "xmlns" => XMLNS do 83: xml.tag! 'RequestData' do 84: xml.tag! 'Vendor', @options[:login] 85: xml.tag! 'Partner', @options[:partner] 86: if options[:request_type] == :recurring 87: xml << body 88: else 89: xml.tag! 'Transactions' do 90: xml.tag! 'Transaction', 'CustRef' => options[:customer] do 91: xml.tag! 'Verbosity', 'MEDIUM' 92: xml << body 93: end 94: end 95: end 96: end 97: xml.tag! 'RequestAuth' do 98: xml.tag! 'UserPass' do 99: xml.tag! 'User', !@options[:user].blank? ? @options[:user] : @options[:login] 100: xml.tag! 'Password', @options[:password] 101: end 102: end 103: end 104: xml.target! 105: end
# File lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb, line 192 192: def commit(request_body, options = {}) 193: request = build_request(request_body, options) 194: headers = build_headers(request.size) 195: 196: response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, request, headers)) 197: 198: build_response(response[:result] == "0", response[:message], response, 199: :test => test?, 200: :authorization => response[:pn_ref] || response[:rp_ref], 201: :cvv_result => CVV_CODE[response[:cv_result]], 202: :avs_result => { :code => response[:avs_result] } 203: ) 204: end
# File lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb, line 140 140: def parse(data) 141: response = {} 142: xml = REXML::Document.new(data) 143: root = REXML::XPath.first(xml, "//ResponseData") 144: 145: # REXML::XPath in Ruby 1.8.6 is now unable to match nodes based on their attributes 146: tx_result = REXML::XPath.first(root, "//TransactionResult") 147: 148: if tx_result && tx_result.attributes['Duplicate'] == "true" 149: response[:duplicate] = true 150: end 151: 152: root.elements.to_a.each do |node| 153: parse_element(response, node) 154: end 155: 156: response 157: end
# File lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb, line 159 159: def parse_element(response, node) 160: node_name = node.name.underscore.to_sym 161: case 162: when node_name == :rp_payment_result 163: # Since we'll have multiple history items, we can't just flatten everything 164: # down as we do everywhere else. RPPaymentResult elements are not contained 165: # in an RPPaymentResults element so we'll come here multiple times 166: response[node_name] ||= [] 167: response[node_name] << ( payment_result_response = {} ) 168: node.elements.each{ |e| parse_element(payment_result_response, e) } 169: when node.has_elements? 170: node.elements.each{|e| parse_element(response, e) } 171: when node_name.to_s =~ /amt$/ 172: # *Amt elements don't put the value in the #text - instead they use a Currency attribute 173: response[node_name] = node.attributes['Currency'] 174: when node_name == :ext_data 175: response[node.attributes['Name'].underscore.to_sym] = node.attributes['Value'] 176: else 177: response[node_name] = node.text 178: end 179: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.