Test server location
Live server location
The Namespaces are not really needed, because it just tells the System, that there’s actually no namespace used. It’s just specified here for completeness.
Wirecard only allows phone numbers with a format like this: +xxx(yyy)zzz-zzzz-ppp, where:
xxx = Country code yyy = Area or city code zzz-zzzz = Local number ppp = PBX extension
For example, a typical U.S. or Canadian number would be “+1(202)555-1234-739” indicating PBX extension 739 at phone number 5551234 within area code 202 (country code 1).
# File lib/active_merchant/billing/gateways/wirecard.rb, line 56 56: def initialize(options = {}) 57: # verify that username and password are supplied 58: requires!(options, :login, :password) 59: # unfortunately Wirecard also requires a BusinessCaseSignature in the XML request 60: requires!(options, :signature) 61: @options = options 62: super 63: end
Capture Authorization
# File lib/active_merchant/billing/gateways/wirecard.rb, line 80 80: def capture(money, authorization, options = {}) 81: prepare_options_hash(options) 82: @options[:authorization] = authorization 83: request = build_request(:capture_authorization, money, @options) 84: commit(request) 85: end
Purchase
# File lib/active_merchant/billing/gateways/wirecard.rb, line 89 89: def purchase(money, creditcard, options = {}) 90: prepare_options_hash(options) 91: @options[:credit_card] = creditcard 92: request = build_request(:purchase, money, @options) 93: commit(request) 94: end
Includes the address to the transaction-xml
# File lib/active_merchant/billing/gateways/wirecard.rb, line 206 206: def add_address(xml, address) 207: return if address.nil? 208: xml.tag! 'CORPTRUSTCENTER_DATA' do 209: xml.tag! 'ADDRESS' do 210: xml.tag! 'Address1', address[:address1] 211: xml.tag! 'Address2', address[:address2] if address[:address2] 212: xml.tag! 'City', address[:city] 213: xml.tag! 'ZipCode', address[:zip] 214: 215: if address[:state] =~ /[A-Za-z]{2}/ && address[:country] =~ /^(us|ca)$/ 216: xml.tag! 'State', address[:state].upcase 217: end 218: 219: xml.tag! 'Country', address[:country] 220: xml.tag! 'Phone', address[:phone] if address[:phone] =~ VALID_PHONE_FORMAT 221: xml.tag! 'Email', address[:email] 222: end 223: end 224: end
Includes the credit-card data to the transaction-xml
# File lib/active_merchant/billing/gateways/wirecard.rb, line 186 186: def add_creditcard(xml, creditcard) 187: raise "Creditcard must be supplied!" if creditcard.nil? 188: xml.tag! 'CREDIT_CARD_DATA' do 189: xml.tag! 'CreditCardNumber', creditcard.number 190: xml.tag! 'CVC2', creditcard.verification_value 191: xml.tag! 'ExpirationYear', creditcard.year 192: xml.tag! 'ExpirationMonth', format(creditcard.month, :two_digits) 193: xml.tag! 'CardHolderName', [creditcard.first_name, creditcard.last_name].join(' ') 194: end 195: end
Includes the IP address of the customer to the transaction-xml
# File lib/active_merchant/billing/gateways/wirecard.rb, line 198 198: def add_customer_data(xml, options) 199: return unless options[:ip] 200: xml.tag! 'CONTACT_DATA' do 201: xml.tag! 'IPAddress', options[:ip] 202: end 203: end
Includes the payment (amount, currency, country) to the transaction-xml
# File lib/active_merchant/billing/gateways/wirecard.rb, line 176 176: def add_invoice(xml, money, options) 177: xml.tag! 'Amount', amount(money) 178: xml.tag! 'Currency', options[:currency] || currency(money) 179: xml.tag! 'CountryCode', options[:billing_address][:country] 180: xml.tag! 'RECURRING_TRANSACTION' do 181: xml.tag! 'Type', options[:recurring] || 'Single' 182: end 183: end
Includes the whole transaction data (payment, creditcard, address)
# File lib/active_merchant/billing/gateways/wirecard.rb, line 152 152: def add_transaction_data(xml, action, money, options = {}) 153: options[:action] = action 154: # TODO: require order_id instead of auto-generating it if not supplied 155: options[:order_id] ||= generate_unique_id 156: transaction_type = action.to_s.upcase 157: 158: xml.tag! "FNC_CC_#{transaction_type}" do 159: # TODO: OPTIONAL, check which param should be used here 160: xml.tag! 'FunctionID', options[:description] || 'Test dummy FunctionID' 161: 162: xml.tag! 'CC_TRANSACTION' do 163: xml.tag! 'TransactionID', options[:order_id] 164: if [:authorization, :purchase].include?(action) 165: add_invoice(xml, money, options) 166: add_creditcard(xml, options[:credit_card]) 167: add_address(xml, options[:billing_address]) 168: elsif action == :capture_authorization 169: xml.tag! 'GuWID', options[:authorization] if options[:authorization] 170: end 171: end 172: end 173: end
Generates the complete xml-message, that gets sent to the gateway
# File lib/active_merchant/billing/gateways/wirecard.rb, line 133 133: def build_request(action, money, options = {}) 134: xml = Builder::XmlMarkup.new :indent => 2 135: xml.instruct! 136: xml.tag! 'WIRECARD_BXML' do 137: xml.tag! 'W_REQUEST' do 138: xml.tag! 'W_JOB' do 139: # TODO: OPTIONAL, check what value needs to be insert here 140: xml.tag! 'JobID', 'test dummy data' 141: # UserID for this transaction 142: xml.tag! 'BusinessCaseSignature', options[:signature] || options[:login] 143: # Create the whole rest of the message 144: add_transaction_data(xml, action, money, options) 145: end 146: end 147: end 148: xml.target! 149: end
Contact WireCard, make the XML request, and parse the reply into a Response object
# File lib/active_merchant/billing/gateways/wirecard.rb, line 114 114: def commit(request) 115: headers = { 'Content-Type' => 'text/xml', 116: 'Authorization' => encoded_credentials } 117: 118: response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, request, headers)) 119: # Pending Status also means Acknowledged (as stated in their specification) 120: success = response[:FunctionResult] == "ACK" || response[:FunctionResult] == "PENDING" 121: message = response[:Message] 122: authorization = (success && @options[:action] == :authorization) ? response[:GuWID] : nil 123: 124: Response.new(success, message, response, 125: :test => test?, 126: :authorization => authorization, 127: :avs_result => { :code => response[:avsCode] }, 128: :cvv_result => response[:cvCode] 129: ) 130: end
Encode login and password in Base64 to supply as HTTP header (for http basic authentication)
# File lib/active_merchant/billing/gateways/wirecard.rb, line 310 310: def encoded_credentials 311: credentials = [@options[:login], @options[:password]].join(':') 312: "Basic " << Base64.encode64(credentials).strip 313: end
Parses all
# File lib/active_merchant/billing/gateways/wirecard.rb, line 282 282: def errors_to_string(root) 283: # Get context error messages (can be 0..*) 284: errors = [] 285: REXML::XPath.each(root, "//ERROR") do |error_elem| 286: error = {} 287: error[:Advice] = [] 288: error[:Message] = error_elem.elements['Message'].text 289: error_elem.elements.each('Advice') do |advice| 290: error[:Advice] << advice.text 291: end 292: errors << error 293: end 294: # Convert all messages to a single string 295: string = '' 296: errors.each do |error| 297: string << error[:Message] 298: error[:Advice].each_with_index do |advice, index| 299: string << ' (' if index == 0 300: string << "#{index+1}. #{advice}" 301: string << ' and ' if index < error[:Advice].size - 1 302: string << ')' if index == error[:Advice].size - 1 303: end 304: end 305: string 306: end
Read the XML message from the gateway and check if it was successful, and also extract required return values from the response.
# File lib/active_merchant/billing/gateways/wirecard.rb, line 229 229: def parse(xml) 230: basepath = '/WIRECARD_BXML/W_RESPONSE' 231: response = {} 232: 233: xml = REXML::Document.new(xml) 234: if root = REXML::XPath.first(xml, "#{basepath}/W_JOB") 235: parse_response(response, root) 236: elsif root = REXML::XPath.first(xml, "//ERROR") 237: parse_error(response, root) 238: else 239: response[:Message] = "No valid XML response message received. \ 240: Propably wrong credentials supplied with HTTP header." 241: end 242: 243: response 244: end
Parse a generic error response from the gateway
# File lib/active_merchant/billing/gateways/wirecard.rb, line 270 270: def parse_error(root, message = "") 271: # Get errors if available and append them to the message 272: errors = errors_to_string(root) 273: unless errors.strip.blank? 274: message << ' - ' unless message.strip.blank? 275: message << errors 276: end 277: message 278: end
Parse the
# File lib/active_merchant/billing/gateways/wirecard.rb, line 247 247: def parse_response(response, root) 248: status = nil 249: # get the root element for this Transaction 250: root.elements.to_a.each do |node| 251: if node.name =~ /FNC_CC_/ 252: status = REXML::XPath.first(node, "CC_TRANSACTION/PROCESSING_STATUS") 253: end 254: end 255: message = "" 256: if status 257: if info = status.elements['Info'] 258: message << info.text 259: end 260: # Get basic response information 261: status.elements.to_a.each do |node| 262: response[node.name.to_sym] = (node.text || '').strip 263: end 264: end 265: parse_error(root, message) 266: response[:Message] = message 267: end
# File lib/active_merchant/billing/gateways/wirecard.rb, line 98 98: def prepare_options_hash(options) 99: @options.update(options) 100: setup_address_hash!(options) 101: end
Create all address hash key value pairs so that it still works if only provided with one or two of them
# File lib/active_merchant/billing/gateways/wirecard.rb, line 105 105: def setup_address_hash!(options) 106: options[:billing_address] = options[:billing_address] || options[:address] || {} 107: options[:shipping_address] = options[:shipping_address] || {} 108: # Include Email in address-hash from options-hash 109: options[:billing_address][:email] = options[:email] if options[:email] 110: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.