activemerchant 1.25.0 → 1.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data.tar.gz.sig +0 -0
- data/CHANGELOG +11 -0
- data/CONTRIBUTORS +8 -0
- data/README.md +9 -7
- data/lib/active_merchant/billing/gateways/cyber_source.rb +102 -84
- data/lib/active_merchant/billing/gateways/netbilling.rb +76 -48
- data/lib/active_merchant/billing/gateways/orbital.rb +12 -17
- data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +266 -0
- data/lib/active_merchant/billing/gateways/payway.rb +213 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +17 -45
- data/lib/active_merchant/billing/response.rb +38 -6
- data/lib/active_merchant/version.rb +1 -1
- metadata +28 -26
- metadata.gz.sig +0 -0
    
        data.tar.gz.sig
    CHANGED
    
    | Binary file | 
    
        data/CHANGELOG
    CHANGED
    
    | @@ -1,5 +1,16 @@ | |
| 1 1 | 
             
            = ActiveMerchant CHANGELOG
         | 
| 2 2 |  | 
| 3 | 
            +
            == Version 1.26.0 (July 6, 2012)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            * Orbital gateway: fix broken requests by ensuring the order of XML elements matches their DTD [Soleone]
         | 
| 6 | 
            +
            * CyberSource gateway: clean up formatting [ntalbott]
         | 
| 7 | 
            +
            * Netbilling gateway: Add refund/credit/void support [ntalbott]
         | 
| 8 | 
            +
            * Add PayGate XML gateway [rubyisbeautiful]
         | 
| 9 | 
            +
            * Add PayWay gateway [BenZhang]
         | 
| 10 | 
            +
            * PayWay gateway: Tweaks to make more ActiveMerchant like [ntalbott]
         | 
| 11 | 
            +
            * Netbilling gateway: Fix error handling [ntalbott]
         | 
| 12 | 
            +
            * Netbilling gateway: Add refund/credit/void support [zenom, ntalbott]
         | 
| 13 | 
            +
             | 
| 3 14 | 
             
            == Version 1.25.0 (July 3, 2012)
         | 
| 4 15 |  | 
| 5 16 | 
             
            * eWAY gateway: Add support for Diners Club cards [Soleone]
         | 
    
        data/CONTRIBUTORS
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -45,18 +45,18 @@ credit card details. | |
| 45 45 |  | 
| 46 46 | 
             
            	require 'rubygems'
         | 
| 47 47 | 
             
            	require 'active_merchant'
         | 
| 48 | 
            -
             | 
| 48 | 
            +
             | 
| 49 49 | 
             
            	# Use the TrustCommerce test servers
         | 
| 50 50 | 
             
            	ActiveMerchant::Billing::Base.mode = :test
         | 
| 51 51 |  | 
| 52 52 | 
             
            	gateway = ActiveMerchant::Billing::TrustCommerceGateway.new(
         | 
| 53 53 | 
             
            	            :login => 'TestMerchant',
         | 
| 54 54 | 
             
            	            :password => 'password')
         | 
| 55 | 
            -
             | 
| 55 | 
            +
             | 
| 56 56 | 
             
            	# ActiveMerchant accepts all amounts as Integer values in cents
         | 
| 57 57 | 
             
            	amount = 1000  # $10.00
         | 
| 58 | 
            -
             | 
| 59 | 
            -
            	# The card verification value is also known as CVV2, CVC2, or CID | 
| 58 | 
            +
             | 
| 59 | 
            +
            	# The card verification value is also known as CVV2, CVC2, or CID
         | 
| 60 60 | 
             
            	credit_card = ActiveMerchant::Billing::CreditCard.new(
         | 
| 61 61 | 
             
            	                :first_name         => 'Bob',
         | 
| 62 62 | 
             
            	                :last_name          => 'Bobsen',
         | 
| @@ -64,16 +64,16 @@ credit card details. | |
| 64 64 | 
             
            	                :month              => '8',
         | 
| 65 65 | 
             
            	                :year               => '2012',
         | 
| 66 66 | 
             
            	                :verification_value => '123')
         | 
| 67 | 
            -
             | 
| 67 | 
            +
             | 
| 68 68 | 
             
            	# Validating the card automatically detects the card type
         | 
| 69 69 | 
             
            	if credit_card.valid?
         | 
| 70 70 | 
             
            	  # Capture $10 from the credit card
         | 
| 71 71 | 
             
            	  response = gateway.purchase(amount, credit_card)
         | 
| 72 | 
            -
             | 
| 72 | 
            +
             | 
| 73 73 | 
             
            	  if response.success?
         | 
| 74 74 | 
             
            	    puts "Successfully charged $#{sprintf("%.2f", amount / 100)} to the credit card #{credit_card.display_number}"
         | 
| 75 75 | 
             
            	  else
         | 
| 76 | 
            -
            	    raise StandardError, response.message | 
| 76 | 
            +
            	    raise StandardError, response.message
         | 
| 77 77 | 
             
            	  end
         | 
| 78 78 | 
             
            	end
         | 
| 79 79 |  | 
| @@ -126,6 +126,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta | |
| 126 126 | 
             
            * [Optimal Payments](http://www.optimalpayments.com/) - CA, US, UK
         | 
| 127 127 | 
             
            * [Orbital Paymentech](http://chasepaymentech.com/) - CA, US
         | 
| 128 128 | 
             
            * [PayBox Direct](http://www.paybox.com) - FR
         | 
| 129 | 
            +
            * [PayGate PayXML](http://paygate.co.za/) - US, ZA
         | 
| 129 130 | 
             
            * [PayJunction](http://www.payjunction.com/) - US
         | 
| 130 131 | 
             
            * [PaymentExpress](http://www.paymentexpress.com/) - AU, MY, NZ, SG, ZA, UK, US
         | 
| 131 132 | 
             
            * [PayPal Express Checkout](https://www.paypal.com/cgi-bin/webscr?cmd=xpt/merchant/ExpressCheckoutIntro-outside) - US, CA, SG, AU
         | 
| @@ -135,6 +136,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta | |
| 135 136 | 
             
            * [PayPal Express Checkout](https://www.paypal.com/cgi-bin/webscr?cmd=xpt/merchant/ExpressCheckoutIntro-outside) - US
         | 
| 136 137 | 
             
            * [PayPal Website Payments Pro (US)](https://www.paypal.com/cgi-bin/webscr?cmd=_wp-pro-overview-outside) - US
         | 
| 137 138 | 
             
            * [PaySecure](http://www.commsecure.com.au/paysecure.shtml) - AU
         | 
| 139 | 
            +
            * [PayWay](https://www.payway.com.au) - AU
         | 
| 138 140 | 
             
            * [Plug'n Pay](http://www.plugnpay.com/) - US
         | 
| 139 141 | 
             
            * [Psigate](http://www.psigate.com/) - CA
         | 
| 140 142 | 
             
            * [PSL Payment Solutions](http://www.paymentsolutionsltd.com/) - UK
         | 
| @@ -1,39 +1,48 @@ | |
| 1 1 | 
             
            module ActiveMerchant #:nodoc:
         | 
| 2 2 | 
             
              module Billing #:nodoc:
         | 
| 3 | 
            -
                # See the remote and mocked unit test files for example usage.  Pay special | 
| 3 | 
            +
                # See the remote and mocked unit test files for example usage.  Pay special
         | 
| 4 | 
            +
                # attention to the contents of the options hash.
         | 
| 4 5 | 
             
                #
         | 
| 5 | 
            -
                # Initial setup instructions can be found in | 
| 6 | 
            -
                # 
         | 
| 7 | 
            -
                # | 
| 8 | 
            -
                #  | 
| 9 | 
            -
                #  | 
| 6 | 
            +
                # Initial setup instructions can be found in
         | 
| 7 | 
            +
                # http://cybersource.com/support_center/implementation/downloads/soap_api/SOAP_toolkits.pdf
         | 
| 8 | 
            +
                #
         | 
| 9 | 
            +
                # Debugging
         | 
| 10 | 
            +
                # If you experience an issue with this gateway be sure to examine the
         | 
| 11 | 
            +
                # transaction information from a general transaction search inside the
         | 
| 12 | 
            +
                # CyberSource Business Center for the full error messages including field
         | 
| 13 | 
            +
                # names.
         | 
| 10 14 | 
             
                #
         | 
| 11 15 | 
             
                # Important Notes
         | 
| 12 | 
            -
                # * AVS and CVV only work against the production server.  You will always | 
| 13 | 
            -
                #  | 
| 14 | 
            -
                # *  | 
| 15 | 
            -
                #  | 
| 16 | 
            +
                # * AVS and CVV only work against the production server.  You will always
         | 
| 17 | 
            +
                #   get back X for AVS and no response for CVV against the test server.
         | 
| 18 | 
            +
                # * Nexus is the list of states or provinces where you have a physical
         | 
| 19 | 
            +
                #   presence.  Nexus is used to calculate tax.  Leave blank to tax everyone.
         | 
| 20 | 
            +
                # * If you want to calculate VAT for overseas customers you must supply a
         | 
| 21 | 
            +
                #   registration number in the options hash as vat_reg_number.
         | 
| 22 | 
            +
                # * productCode is a value in the line_items hash that is used to tell
         | 
| 23 | 
            +
                #   CyberSource what kind of item you are selling.  It is used when
         | 
| 24 | 
            +
                #   calculating tax/VAT.
         | 
| 16 25 | 
             
                # * All transactions use dollar values.
         | 
| 17 26 | 
             
                class CyberSourceGateway < Gateway
         | 
| 18 27 | 
             
                  TEST_URL = 'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor'
         | 
| 19 28 | 
             
                  LIVE_URL = 'https://ics2ws.ic3.com/commerce/1.x/transactionProcessor'
         | 
| 20 29 |  | 
| 21 30 | 
             
                  XSD_VERSION = "1.69"
         | 
| 22 | 
            -
             | 
| 31 | 
            +
             | 
| 23 32 | 
             
                  # visa, master, american_express, discover
         | 
| 24 33 | 
             
                  self.supported_cardtypes = [:visa, :master, :american_express, :discover]
         | 
| 25 34 | 
             
                  self.supported_countries = ['US']
         | 
| 26 35 | 
             
                  self.default_currency = 'USD'
         | 
| 27 36 | 
             
                  self.homepage_url = 'http://www.cybersource.com'
         | 
| 28 37 | 
             
                  self.display_name = 'CyberSource'
         | 
| 29 | 
            -
             | 
| 38 | 
            +
             | 
| 30 39 | 
             
                  # map credit card to the CyberSource expected representation
         | 
| 31 40 | 
             
                  @@credit_card_codes = {
         | 
| 32 41 | 
             
                    :visa  => '001',
         | 
| 33 42 | 
             
                    :master => '002',
         | 
| 34 43 | 
             
                    :american_express => '003',
         | 
| 35 44 | 
             
                    :discover => '004'
         | 
| 36 | 
            -
                  } | 
| 45 | 
            +
                  }
         | 
| 37 46 |  | 
| 38 47 | 
             
                  # map response codes to something humans can read
         | 
| 39 48 | 
             
                  @@response_codes = {
         | 
| @@ -45,17 +54,17 @@ module ActiveMerchant #:nodoc: | |
| 45 54 | 
             
                    :r152 => "The request was received, but a service timed out",
         | 
| 46 55 | 
             
                    :r200 => "The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the AVS check",
         | 
| 47 56 | 
             
                    :r201 => "The issuing bank has questions about the request",
         | 
| 48 | 
            -
                    :r202 => "Expired card", | 
| 49 | 
            -
                    :r203 => "General decline of the card", | 
| 50 | 
            -
                    :r204 => "Insufficient funds in the account", | 
| 51 | 
            -
                    :r205 => "Stolen or lost card", | 
| 52 | 
            -
                    :r207 => "Issuing bank unavailable", | 
| 53 | 
            -
                    :r208 => "Inactive card or card not authorized for card-not-present transactions", | 
| 54 | 
            -
                    :r209 => "American Express Card Identifiction Digits (CID) did not match", | 
| 55 | 
            -
                    :r210 => "The card has reached the credit limit", | 
| 56 | 
            -
                    :r211 => "Invalid card verification number", | 
| 57 | 
            -
                    :r221 => "The customer matched an entry on the processor's negative file", | 
| 58 | 
            -
                    :r230 => "The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the card verification check", | 
| 57 | 
            +
                    :r202 => "Expired card",
         | 
| 58 | 
            +
                    :r203 => "General decline of the card",
         | 
| 59 | 
            +
                    :r204 => "Insufficient funds in the account",
         | 
| 60 | 
            +
                    :r205 => "Stolen or lost card",
         | 
| 61 | 
            +
                    :r207 => "Issuing bank unavailable",
         | 
| 62 | 
            +
                    :r208 => "Inactive card or card not authorized for card-not-present transactions",
         | 
| 63 | 
            +
                    :r209 => "American Express Card Identifiction Digits (CID) did not match",
         | 
| 64 | 
            +
                    :r210 => "The card has reached the credit limit",
         | 
| 65 | 
            +
                    :r211 => "Invalid card verification number",
         | 
| 66 | 
            +
                    :r221 => "The customer matched an entry on the processor's negative file",
         | 
| 67 | 
            +
                    :r230 => "The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the card verification check",
         | 
| 59 68 | 
             
                    :r231 => "Invalid account number",
         | 
| 60 69 | 
             
                    :r232 => "The card type is not accepted by the payment processor",
         | 
| 61 70 | 
             
                    :r233 => "General decline by the processor",
         | 
| @@ -74,44 +83,48 @@ module ActiveMerchant #:nodoc: | |
| 74 83 | 
             
                    :r247 => "You requested a credit for a capture that was previously voided",
         | 
| 75 84 | 
             
                    :r250 => "The request was received, but a time-out occurred with the payment processor",
         | 
| 76 85 | 
             
                    :r254 => "Your CyberSource account is prohibited from processing stand-alone refunds",
         | 
| 77 | 
            -
                    :r255 => "Your CyberSource account is not configured to process the service in the country you specified" | 
| 86 | 
            +
                    :r255 => "Your CyberSource account is not configured to process the service in the country you specified"
         | 
| 78 87 | 
             
                  }
         | 
| 79 88 |  | 
| 80 | 
            -
                  # These are the options that can be used when creating a new CyberSource | 
| 81 | 
            -
                  # 
         | 
| 82 | 
            -
                  # :login =>  your username 
         | 
| 89 | 
            +
                  # These are the options that can be used when creating a new CyberSource
         | 
| 90 | 
            +
                  # Gateway object.
         | 
| 83 91 | 
             
                  #
         | 
| 84 | 
            -
                  # : | 
| 92 | 
            +
                  # :login =>  your username
         | 
| 93 | 
            +
                  #
         | 
| 94 | 
            +
                  # :password =>  the transaction key you generated in the Business Center
         | 
| 85 95 | 
             
                  #
         | 
| 86 96 | 
             
                  # :test => true   sets the gateway to test mode
         | 
| 87 97 | 
             
                  #
         | 
| 88 | 
            -
                  # :vat_reg_number => your VAT registration number | 
| 98 | 
            +
                  # :vat_reg_number => your VAT registration number
         | 
| 89 99 | 
             
                  #
         | 
| 90 | 
            -
                  # :nexus => "WI CA QC" sets the states/provinces where you have a physical | 
| 100 | 
            +
                  # :nexus => "WI CA QC" sets the states/provinces where you have a physical
         | 
| 101 | 
            +
                  #           presense for tax purposes
         | 
| 91 102 | 
             
                  #
         | 
| 92 | 
            -
                  # :ignore_avs => true   don't want to use AVS so continue processing even | 
| 103 | 
            +
                  # :ignore_avs => true   don't want to use AVS so continue processing even
         | 
| 104 | 
            +
                  #                       if AVS would have failed
         | 
| 93 105 | 
             
                  #
         | 
| 94 | 
            -
                  # :ignore_cvv => true   don't want to use CVV so continue processing even | 
| 106 | 
            +
                  # :ignore_cvv => true   don't want to use CVV so continue processing even
         | 
| 107 | 
            +
                  #                       if CVV would have failed
         | 
| 95 108 | 
             
                  def initialize(options = {})
         | 
| 96 109 | 
             
                    requires!(options, :login, :password)
         | 
| 97 110 | 
             
                    @options = options
         | 
| 98 111 | 
             
                    super
         | 
| 99 | 
            -
                  end | 
| 112 | 
            +
                  end
         | 
| 100 113 |  | 
| 101 114 | 
             
                  # Should run against the test servers or not?
         | 
| 102 115 | 
             
                  def test?
         | 
| 103 116 | 
             
                    @options[:test] || Base.gateway_mode == :test
         | 
| 104 117 | 
             
                  end
         | 
| 105 | 
            -
             | 
| 106 | 
            -
                  # Request an authorization for an amount from CyberSource | 
| 118 | 
            +
             | 
| 119 | 
            +
                  # Request an authorization for an amount from CyberSource
         | 
| 107 120 | 
             
                  #
         | 
| 108 | 
            -
                  # You must supply an :order_id in the options hash | 
| 121 | 
            +
                  # You must supply an :order_id in the options hash
         | 
| 109 122 | 
             
                  def authorize(money, creditcard_or_reference, options = {})
         | 
| 110 123 | 
             
                    requires!(options,  :order_id)
         | 
| 111 124 | 
             
                    setup_address_hash(options)
         | 
| 112 125 | 
             
                    commit(build_auth_request(money, creditcard_or_reference, options), options )
         | 
| 113 126 | 
             
                  end
         | 
| 114 | 
            -
             | 
| 127 | 
            +
             | 
| 115 128 | 
             
                  def auth_reversal(money, identification, options = {})
         | 
| 116 129 | 
             
                    commit(build_auth_reversal_request(money, identification, options), options)
         | 
| 117 130 | 
             
                  end
         | 
| @@ -123,13 +136,13 @@ module ActiveMerchant #:nodoc: | |
| 123 136 | 
             
                  end
         | 
| 124 137 |  | 
| 125 138 | 
             
                  # Purchase is an auth followed by a capture
         | 
| 126 | 
            -
                  # You must supply an order_id in the options hash | 
| 139 | 
            +
                  # You must supply an order_id in the options hash
         | 
| 127 140 | 
             
                  def purchase(money, creditcard_or_reference, options = {})
         | 
| 128 141 | 
             
                    requires!(options, :order_id)
         | 
| 129 142 | 
             
                    setup_address_hash(options)
         | 
| 130 143 | 
             
                    commit(build_purchase_request(money, creditcard_or_reference, options), options)
         | 
| 131 144 | 
             
                  end
         | 
| 132 | 
            -
             | 
| 145 | 
            +
             | 
| 133 146 | 
             
                  def void(identification, options = {})
         | 
| 134 147 | 
             
                    commit(build_void_request(identification, options), options)
         | 
| 135 148 | 
             
                  end
         | 
| @@ -137,14 +150,15 @@ module ActiveMerchant #:nodoc: | |
| 137 150 | 
             
                  def refund(money, identification, options = {})
         | 
| 138 151 | 
             
                    commit(build_credit_request(money, identification, options), options)
         | 
| 139 152 | 
             
                  end
         | 
| 140 | 
            -
             | 
| 153 | 
            +
             | 
| 141 154 | 
             
                  def credit(money, identification, options = {})
         | 
| 142 155 | 
             
                    deprecated CREDIT_DEPRECATION_MESSAGE
         | 
| 143 156 | 
             
                    refund(money, identification, options)
         | 
| 144 157 | 
             
                  end
         | 
| 145 158 |  | 
| 146 159 | 
             
                  # Stores a customer subscription/profile with type "on-demand".
         | 
| 147 | 
            -
                  # To charge the card while creating a profile, pass | 
| 160 | 
            +
                  # To charge the card while creating a profile, pass
         | 
| 161 | 
            +
                  # options[:setup_fee] => money
         | 
| 148 162 | 
             
                  def store(creditcard, options = {})
         | 
| 149 163 | 
             
                    requires!(options, :order_id)
         | 
| 150 164 | 
             
                    setup_address_hash(options)
         | 
| @@ -170,11 +184,13 @@ module ActiveMerchant #:nodoc: | |
| 170 184 | 
             
                    commit(build_retrieve_subscription_request(reference, options), options)
         | 
| 171 185 | 
             
                  end
         | 
| 172 186 |  | 
| 173 | 
            -
                  # CyberSource requires that you provide line item information for tax | 
| 174 | 
            -
                  # If you do not have prices for each item or want to | 
| 187 | 
            +
                  # CyberSource requires that you provide line item information for tax
         | 
| 188 | 
            +
                  # calculations. If you do not have prices for each item or want to
         | 
| 189 | 
            +
                  # simplify the situation then pass in one fake line item that costs the
         | 
| 190 | 
            +
                  # subtotal of the order
         | 
| 191 | 
            +
                  #
         | 
| 192 | 
            +
                  # The line_item hash goes in the options hash and should look like
         | 
| 175 193 | 
             
                  #
         | 
| 176 | 
            -
                  # The line_item hash goes in the options hash and should look like 
         | 
| 177 | 
            -
                  # 
         | 
| 178 194 | 
             
                  #         :line_items => [
         | 
| 179 195 | 
             
                  #           {
         | 
| 180 196 | 
             
                  #             :declared_value => '1',
         | 
| @@ -197,17 +213,18 @@ module ActiveMerchant #:nodoc: | |
| 197 213 | 
             
                  def calculate_tax(creditcard, options)
         | 
| 198 214 | 
             
                    requires!(options,  :line_items)
         | 
| 199 215 | 
             
                    setup_address_hash(options)
         | 
| 200 | 
            -
                    commit(build_tax_calculation_request(creditcard, options), options) | 
| 216 | 
            +
                    commit(build_tax_calculation_request(creditcard, options), options)
         | 
| 201 217 | 
             
                  end
         | 
| 202 | 
            -
             | 
| 218 | 
            +
             | 
| 203 219 | 
             
                  private
         | 
| 204 220 |  | 
| 205 | 
            -
                  # Create all address hash key value pairs so that we still function if we | 
| 221 | 
            +
                  # Create all address hash key value pairs so that we still function if we
         | 
| 222 | 
            +
                  # were only provided with one or two of them
         | 
| 206 223 | 
             
                  def setup_address_hash(options)
         | 
| 207 224 | 
             
                    options[:billing_address] = options[:billing_address] || options[:address] || {}
         | 
| 208 225 | 
             
                    options[:shipping_address] = options[:shipping_address] || {}
         | 
| 209 226 | 
             
                  end
         | 
| 210 | 
            -
             | 
| 227 | 
            +
             | 
| 211 228 | 
             
                  def build_auth_request(money, creditcard_or_reference, options)
         | 
| 212 229 | 
             
                    xml = Builder::XmlMarkup.new :indent => 2
         | 
| 213 230 | 
             
                    add_creditcard_or_subscription(xml, money, creditcard_or_reference, options)
         | 
| @@ -226,7 +243,7 @@ module ActiveMerchant #:nodoc: | |
| 226 243 | 
             
                    add_business_rules_data(xml)
         | 
| 227 244 | 
             
                    xml.target!
         | 
| 228 245 | 
             
                  end
         | 
| 229 | 
            -
             | 
| 246 | 
            +
             | 
| 230 247 | 
             
                  def build_capture_request(money, authorization, options)
         | 
| 231 248 | 
             
                    order_id, request_id, request_token = authorization.split(";")
         | 
| 232 249 | 
             
                    options[:order_id] = order_id
         | 
| @@ -236,7 +253,7 @@ module ActiveMerchant #:nodoc: | |
| 236 253 | 
             
                    add_capture_service(xml, request_id, request_token)
         | 
| 237 254 | 
             
                    add_business_rules_data(xml)
         | 
| 238 255 | 
             
                    xml.target!
         | 
| 239 | 
            -
                  end | 
| 256 | 
            +
                  end
         | 
| 240 257 |  | 
| 241 258 | 
             
                  def build_purchase_request(money, creditcard_or_reference, options)
         | 
| 242 259 | 
             
                    xml = Builder::XmlMarkup.new :indent => 2
         | 
| @@ -245,11 +262,11 @@ module ActiveMerchant #:nodoc: | |
| 245 262 | 
             
                    add_business_rules_data(xml)
         | 
| 246 263 | 
             
                    xml.target!
         | 
| 247 264 | 
             
                  end
         | 
| 248 | 
            -
             | 
| 265 | 
            +
             | 
| 249 266 | 
             
                  def build_void_request(identification, options)
         | 
| 250 267 | 
             
                    order_id, request_id, request_token = identification.split(";")
         | 
| 251 268 | 
             
                    options[:order_id] = order_id
         | 
| 252 | 
            -
             | 
| 269 | 
            +
             | 
| 253 270 | 
             
                    xml = Builder::XmlMarkup.new :indent => 2
         | 
| 254 271 | 
             
                    add_void_service(xml, request_id, request_token)
         | 
| 255 272 | 
             
                    xml.target!
         | 
| @@ -267,11 +284,11 @@ module ActiveMerchant #:nodoc: | |
| 267 284 | 
             
                  def build_credit_request(money, identification, options)
         | 
| 268 285 | 
             
                    order_id, request_id, request_token = identification.split(";")
         | 
| 269 286 | 
             
                    options[:order_id] = order_id
         | 
| 270 | 
            -
             | 
| 287 | 
            +
             | 
| 271 288 | 
             
                    xml = Builder::XmlMarkup.new :indent => 2
         | 
| 272 289 | 
             
                    add_purchase_data(xml, money, true, options)
         | 
| 273 290 | 
             
                    add_credit_service(xml, request_id, request_token)
         | 
| 274 | 
            -
             | 
| 291 | 
            +
             | 
| 275 292 | 
             
                    xml.target!
         | 
| 276 293 | 
             
                  end
         | 
| 277 294 |  | 
| @@ -320,13 +337,13 @@ module ActiveMerchant #:nodoc: | |
| 320 337 | 
             
                    xml.tag! 'businessRules' do
         | 
| 321 338 | 
             
                      xml.tag!('ignoreAVSResult', 'true') if @options[:ignore_avs]
         | 
| 322 339 | 
             
                      xml.tag!('ignoreCVResult', 'true') if @options[:ignore_cvv]
         | 
| 323 | 
            -
                    end | 
| 340 | 
            +
                    end
         | 
| 324 341 | 
             
                  end
         | 
| 325 | 
            -
             | 
| 342 | 
            +
             | 
| 326 343 | 
             
                  def add_line_item_data(xml, options)
         | 
| 327 344 | 
             
                    options[:line_items].each_with_index do |value, index|
         | 
| 328 345 | 
             
                      xml.tag! 'item', {'id' => index} do
         | 
| 329 | 
            -
                        xml.tag! 'unitPrice', amount(value[:declared_value]) | 
| 346 | 
            +
                        xml.tag! 'unitPrice', amount(value[:declared_value])
         | 
| 330 347 | 
             
                        xml.tag! 'quantity', value[:quantity]
         | 
| 331 348 | 
             
                        xml.tag! 'productCode', value[:code] || 'shipping_only'
         | 
| 332 349 | 
             
                        xml.tag! 'productName', value[:description]
         | 
| @@ -334,7 +351,7 @@ module ActiveMerchant #:nodoc: | |
| 334 351 | 
             
                      end
         | 
| 335 352 | 
             
                    end
         | 
| 336 353 | 
             
                  end
         | 
| 337 | 
            -
             | 
| 354 | 
            +
             | 
| 338 355 | 
             
                  def add_merchant_data(xml, options)
         | 
| 339 356 | 
             
                    xml.tag! 'merchantID', @options[:login]
         | 
| 340 357 | 
             
                    xml.tag! 'merchantReferenceCode', options[:order_id]
         | 
| @@ -346,7 +363,7 @@ module ActiveMerchant #:nodoc: | |
| 346 363 | 
             
                  def add_purchase_data(xml, money = 0, include_grand_total = false, options={})
         | 
| 347 364 | 
             
                    xml.tag! 'purchaseTotals' do
         | 
| 348 365 | 
             
                      xml.tag! 'currency', options[:currency] || currency(money)
         | 
| 349 | 
            -
                      xml.tag!('grandTotalAmount', amount(money))  if include_grand_total | 
| 366 | 
            +
                      xml.tag!('grandTotalAmount', amount(money))  if include_grand_total
         | 
| 350 367 | 
             
                    end
         | 
| 351 368 | 
             
                  end
         | 
| 352 369 |  | 
| @@ -368,10 +385,10 @@ module ActiveMerchant #:nodoc: | |
| 368 385 | 
             
                      xml.tag! 'email',                 options[:email]
         | 
| 369 386 | 
             
                      xml.tag! 'driversLicenseNumber',  options[:drivers_license_number]  unless options[:drivers_license_number].blank?
         | 
| 370 387 | 
             
                      xml.tag! 'driversLicenseState',   options[:drivers_license_state]   unless options[:drivers_license_state].blank?
         | 
| 371 | 
            -
                    end | 
| 388 | 
            +
                    end
         | 
| 372 389 | 
             
                  end
         | 
| 373 390 |  | 
| 374 | 
            -
                  def add_creditcard(xml, creditcard) | 
| 391 | 
            +
                  def add_creditcard(xml, creditcard)
         | 
| 375 392 | 
             
                    xml.tag! 'card' do
         | 
| 376 393 | 
             
                      xml.tag! 'accountNumber', creditcard.number
         | 
| 377 394 | 
             
                      xml.tag! 'expirationMonth', format(creditcard.month, :two_digits)
         | 
| @@ -389,7 +406,7 @@ module ActiveMerchant #:nodoc: | |
| 389 406 | 
             
                  end
         | 
| 390 407 |  | 
| 391 408 | 
             
                  def add_auth_service(xml)
         | 
| 392 | 
            -
                    xml.tag! 'ccAuthService', {'run' => 'true'} | 
| 409 | 
            +
                    xml.tag! 'ccAuthService', {'run' => 'true'}
         | 
| 393 410 | 
             
                  end
         | 
| 394 411 |  | 
| 395 412 | 
             
                  def add_capture_service(xml, request_id, request_token)
         | 
| @@ -446,7 +463,7 @@ module ActiveMerchant #:nodoc: | |
| 446 463 |  | 
| 447 464 | 
             
                    xml.tag! 'recurringSubscriptionInfo' do
         | 
| 448 465 | 
             
                      if reference
         | 
| 449 | 
            -
                         | 
| 466 | 
            +
                        _, subscription_id, _ = reference.split(";")
         | 
| 450 467 | 
             
                        xml.tag! 'subscriptionID',  subscription_id
         | 
| 451 468 | 
             
                      end
         | 
| 452 469 |  | 
| @@ -479,7 +496,7 @@ module ActiveMerchant #:nodoc: | |
| 479 496 | 
             
                      add_creditcard(xml, creditcard_or_reference)
         | 
| 480 497 | 
             
                    end
         | 
| 481 498 | 
             
                  end
         | 
| 482 | 
            -
             | 
| 499 | 
            +
             | 
| 483 500 | 
             
                  # Where we actually build the full SOAP request using builder
         | 
| 484 501 | 
             
                  def build_request(body, options)
         | 
| 485 502 | 
             
                    xml = Builder::XmlMarkup.new :indent => 2
         | 
| @@ -500,25 +517,26 @@ module ActiveMerchant #:nodoc: | |
| 500 517 | 
             
                          end
         | 
| 501 518 | 
             
                        end
         | 
| 502 519 | 
             
                      end
         | 
| 503 | 
            -
                    xml.target! | 
| 520 | 
            +
                    xml.target!
         | 
| 504 521 | 
             
                  end
         | 
| 505 | 
            -
             | 
| 506 | 
            -
                  # Contact CyberSource, make the SOAP request, and parse the reply into a | 
| 522 | 
            +
             | 
| 523 | 
            +
                  # Contact CyberSource, make the SOAP request, and parse the reply into a
         | 
| 524 | 
            +
                  # Response object
         | 
| 507 525 | 
             
                  def commit(request, options)
         | 
| 508 | 
            -
             | 
| 509 | 
            -
             | 
| 510 | 
            -
             | 
| 511 | 
            -
             | 
| 526 | 
            +
                    response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, build_request(request, options)))
         | 
| 527 | 
            +
             | 
| 528 | 
            +
                    success = response[:decision] == "ACCEPT"
         | 
| 529 | 
            +
                    message = @@response_codes[('r' + response[:reasonCode]).to_sym] rescue response[:message]
         | 
| 512 530 | 
             
                    authorization = success ? [ options[:order_id], response[:requestID], response[:requestToken] ].compact.join(";") : nil
         | 
| 513 | 
            -
             | 
| 514 | 
            -
                    Response.new(success, message, response, | 
| 515 | 
            -
                      :test => test?, | 
| 531 | 
            +
             | 
| 532 | 
            +
                    Response.new(success, message, response,
         | 
| 533 | 
            +
                      :test => test?,
         | 
| 516 534 | 
             
                      :authorization => authorization,
         | 
| 517 535 | 
             
                      :avs_result => { :code => response[:avsCode] },
         | 
| 518 536 | 
             
                      :cvv_result => response[:cvCode]
         | 
| 519 537 | 
             
                    )
         | 
| 520 538 | 
             
                  end
         | 
| 521 | 
            -
             | 
| 539 | 
            +
             | 
| 522 540 | 
             
                  # Parse the SOAP response
         | 
| 523 541 | 
             
                  # Technique inspired by the Paypal Gateway
         | 
| 524 542 | 
             
                  def parse(xml)
         | 
| @@ -526,19 +544,19 @@ module ActiveMerchant #:nodoc: | |
| 526 544 | 
             
                    xml = REXML::Document.new(xml)
         | 
| 527 545 | 
             
                    if root = REXML::XPath.first(xml, "//c:replyMessage")
         | 
| 528 546 | 
             
                      root.elements.to_a.each do |node|
         | 
| 529 | 
            -
                        case node.name | 
| 547 | 
            +
                        case node.name
         | 
| 530 548 | 
             
                        when 'c:reasonCode'
         | 
| 531 549 | 
             
                          reply[:message] = reply(node.text)
         | 
| 532 550 | 
             
                        else
         | 
| 533 551 | 
             
                          parse_element(reply, node)
         | 
| 534 552 | 
             
                        end
         | 
| 535 553 | 
             
                      end
         | 
| 536 | 
            -
                    elsif root = REXML::XPath.first(xml, "//soap:Fault") | 
| 554 | 
            +
                    elsif root = REXML::XPath.first(xml, "//soap:Fault")
         | 
| 537 555 | 
             
                      parse_element(reply, root)
         | 
| 538 556 | 
             
                      reply[:message] = "#{reply[:faultcode]}: #{reply[:faultstring]}"
         | 
| 539 557 | 
             
                    end
         | 
| 540 558 | 
             
                    return reply
         | 
| 541 | 
            -
                  end | 
| 559 | 
            +
                  end
         | 
| 542 560 |  | 
| 543 561 | 
             
                  def parse_element(reply, node)
         | 
| 544 562 | 
             
                    if node.has_elements?
         | 
| @@ -547,12 +565,12 @@ module ActiveMerchant #:nodoc: | |
| 547 565 | 
             
                      if node.parent.name =~ /item/
         | 
| 548 566 | 
             
                        parent = node.parent.name + (node.parent.attributes["id"] ? "_" + node.parent.attributes["id"] : '')
         | 
| 549 567 | 
             
                        reply[(parent + '_' + node.name).to_sym] = node.text
         | 
| 550 | 
            -
                      else | 
| 568 | 
            +
                      else
         | 
| 551 569 | 
             
                        reply[node.name.to_sym] = node.text
         | 
| 552 570 | 
             
                      end
         | 
| 553 571 | 
             
                    end
         | 
| 554 572 | 
             
                    return reply
         | 
| 555 573 | 
             
                  end
         | 
| 556 | 
            -
                end | 
| 557 | 
            -
              end | 
| 558 | 
            -
            end | 
| 574 | 
            +
                end
         | 
| 575 | 
            +
              end
         | 
| 576 | 
            +
            end
         |