activemerchant 1.64.0 → 1.65.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.
- checksums.yaml +4 -4
- data/CHANGELOG +27 -0
- data/README.md +0 -1
- data/lib/active_merchant/billing/gateways/adyen.rb +228 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +9 -1
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +68 -2
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +10 -2
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +2 -2
- data/lib/active_merchant/billing/gateways/cyber_source.rb +2 -0
- data/lib/active_merchant/billing/gateways/global_collect.rb +17 -5
- data/lib/active_merchant/billing/gateways/jetpay.rb +12 -9
- data/lib/active_merchant/billing/gateways/openpay.rb +1 -0
- data/lib/active_merchant/billing/gateways/orbital.rb +5 -3
- data/lib/active_merchant/billing/gateways/payeezy.rb +7 -0
- data/lib/active_merchant/billing/gateways/payu_latam.rb +1 -1
- data/lib/active_merchant/billing/gateways/pin.rb +5 -0
- data/lib/active_merchant/billing/gateways/quickpay.rb +3 -3
- data/lib/active_merchant/billing/gateways/qvalent.rb +44 -1
- data/lib/active_merchant/billing/gateways/safe_charge.rb +211 -0
- data/lib/active_merchant/billing/gateways/sage_pay.rb +8 -5
- data/lib/active_merchant/billing/gateways/stripe.rb +6 -1
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +45 -11
- data/lib/active_merchant/billing/gateways/wepay.rb +1 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +8 -3
- data/lib/active_merchant/posts_data.rb +1 -1
- data/lib/active_merchant/version.rb +1 -1
- metadata +4 -3
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +0 -314
| @@ -686,6 +686,8 @@ module ActiveMerchant #:nodoc: | |
| 686 686 | 
             
                      response = parse(ssl_post(test? ? self.test_url : self.live_url, build_request(request, options)))
         | 
| 687 687 | 
             
                    rescue ResponseError => e
         | 
| 688 688 | 
             
                      response = parse(e.response.body)
         | 
| 689 | 
            +
                    rescue REXML::ParseException => e
         | 
| 690 | 
            +
                      response = { message: e.to_s }
         | 
| 689 691 | 
             
                    end
         | 
| 690 692 |  | 
| 691 693 | 
             
                    success = response[:decision] == "ACCEPT"
         | 
| @@ -131,8 +131,8 @@ module ActiveMerchant #:nodoc: | |
| 131 131 | 
             
                    if payment
         | 
| 132 132 | 
             
                      post["order"]["customer"]["personalInformation"] = {
         | 
| 133 133 | 
             
                        "name" => {
         | 
| 134 | 
            -
                          "firstName" => payment.first_name,
         | 
| 135 | 
            -
                          "surname" => payment.last_name
         | 
| 134 | 
            +
                          "firstName" => payment.first_name[0..14],
         | 
| 135 | 
            +
                          "surname" => payment.last_name[0..69]
         | 
| 136 136 | 
             
                        }
         | 
| 137 137 | 
             
                      }
         | 
| 138 138 | 
             
                    end
         | 
| @@ -262,14 +262,20 @@ EOS | |
| 262 262 | 
             
                  end
         | 
| 263 263 |  | 
| 264 264 | 
             
                  def success_from(response)
         | 
| 265 | 
            -
                    !response["errorId"]
         | 
| 265 | 
            +
                    !response["errorId"] && response["status"] != "REJECTED"
         | 
| 266 266 | 
             
                  end
         | 
| 267 267 |  | 
| 268 268 | 
             
                  def message_from(succeeded, response)
         | 
| 269 269 | 
             
                    if succeeded
         | 
| 270 270 | 
             
                      "Succeeded"
         | 
| 271 271 | 
             
                    else
         | 
| 272 | 
            -
                      response["errors"] | 
| 272 | 
            +
                      if errors = response["errors"]
         | 
| 273 | 
            +
                        errors.first.try(:[], "message")
         | 
| 274 | 
            +
                      elsif status = response["status"]
         | 
| 275 | 
            +
                        "Status: " + status
         | 
| 276 | 
            +
                      else
         | 
| 277 | 
            +
                        "No message available"
         | 
| 278 | 
            +
                      end
         | 
| 273 279 | 
             
                    end
         | 
| 274 280 | 
             
                  end
         | 
| 275 281 |  | 
| @@ -283,7 +289,13 @@ EOS | |
| 283 289 |  | 
| 284 290 | 
             
                  def error_code_from(succeeded, response)
         | 
| 285 291 | 
             
                    unless succeeded
         | 
| 286 | 
            -
                      response["errors"] | 
| 292 | 
            +
                      if errors = response["errors"]
         | 
| 293 | 
            +
                        errors.first.try(:[], "code")
         | 
| 294 | 
            +
                      elsif status = response.try(:[], "statusOutput").try(:[], "statusCode")
         | 
| 295 | 
            +
                        status.to_s
         | 
| 296 | 
            +
                      else
         | 
| 297 | 
            +
                        "No error code available"
         | 
| 298 | 
            +
                      end
         | 
| 287 299 | 
             
                    end
         | 
| 288 300 | 
             
                  end
         | 
| 289 301 |  | 
| @@ -165,12 +165,15 @@ module ActiveMerchant #:nodoc: | |
| 165 165 | 
             
                  end
         | 
| 166 166 |  | 
| 167 167 | 
             
                  def capture(money, reference, options = {})
         | 
| 168 | 
            -
                     | 
| 168 | 
            +
                    split_authorization = reference.split(";")
         | 
| 169 | 
            +
                    transaction_id = split_authorization[0]
         | 
| 170 | 
            +
                    token = split_authorization[3]
         | 
| 171 | 
            +
                    commit(money, build_capture_request(transaction_id, money, options), token)
         | 
| 169 172 | 
             
                  end
         | 
| 170 173 |  | 
| 171 174 | 
             
                  def void(reference, options = {})
         | 
| 172 175 | 
             
                    transaction_id, approval, amount, token = reference.split(";")
         | 
| 173 | 
            -
                    commit(amount.to_i, build_void_request(amount.to_i, transaction_id, approval, token, options))
         | 
| 176 | 
            +
                    commit(amount.to_i, build_void_request(amount.to_i, transaction_id, approval, token, options), token)
         | 
| 174 177 | 
             
                  end
         | 
| 175 178 |  | 
| 176 179 | 
             
                  def credit(money, transaction_id_or_card, options = {})
         | 
| @@ -183,9 +186,9 @@ module ActiveMerchant #:nodoc: | |
| 183 186 | 
             
                  end
         | 
| 184 187 |  | 
| 185 188 | 
             
                  def refund(money, reference, options = {})
         | 
| 186 | 
            -
                     | 
| 187 | 
            -
                    transaction_id =  | 
| 188 | 
            -
                    token =  | 
| 189 | 
            +
                    split_authorization = reference.split(";")
         | 
| 190 | 
            +
                    transaction_id = split_authorization[0]
         | 
| 191 | 
            +
                    token = split_authorization[3]
         | 
| 189 192 | 
             
                    credit_card = options[:credit_card]
         | 
| 190 193 | 
             
                    commit(money, build_credit_request('CREDIT', money, transaction_id, credit_card, token, options))
         | 
| 191 194 | 
             
                  end
         | 
| @@ -279,7 +282,7 @@ module ActiveMerchant #:nodoc: | |
| 279 282 | 
             
                    end
         | 
| 280 283 | 
             
                  end
         | 
| 281 284 |  | 
| 282 | 
            -
                  def commit(money, request)
         | 
| 285 | 
            +
                  def commit(money, request, token = nil)
         | 
| 283 286 | 
             
                    response = parse(ssl_post(url, request))
         | 
| 284 287 |  | 
| 285 288 | 
             
                    success = success?(response)
         | 
| @@ -287,7 +290,7 @@ module ActiveMerchant #:nodoc: | |
| 287 290 | 
             
                      success ? 'APPROVED' : message_from(response),
         | 
| 288 291 | 
             
                      response,
         | 
| 289 292 | 
             
                      :test => test?,
         | 
| 290 | 
            -
                      :authorization => authorization_from(response, money),
         | 
| 293 | 
            +
                      :authorization => authorization_from(response, money, token),
         | 
| 291 294 | 
             
                      :avs_result => { :code => response[:avs] },
         | 
| 292 295 | 
             
                      :cvv_result => response[:cvv2]
         | 
| 293 296 | 
             
                    )
         | 
| @@ -330,9 +333,9 @@ module ActiveMerchant #:nodoc: | |
| 330 333 | 
             
                    ACTION_CODE_MESSAGES[response[:action_code]]
         | 
| 331 334 | 
             
                  end
         | 
| 332 335 |  | 
| 333 | 
            -
                  def authorization_from(response, money)
         | 
| 336 | 
            +
                  def authorization_from(response, money, previous_token)
         | 
| 334 337 | 
             
                    original_amount = amount(money) if money
         | 
| 335 | 
            -
                    [ response[:transaction_id], response[:approval], original_amount, response[:token]].join(";")
         | 
| 338 | 
            +
                    [ response[:transaction_id], response[:approval], original_amount, (response[:token] || previous_token)].join(";")
         | 
| 336 339 | 
             
                  end
         | 
| 337 340 |  | 
| 338 341 | 
             
                  def add_credit_card(xml, credit_card)
         | 
| @@ -113,6 +113,7 @@ module ActiveMerchant #:nodoc: | |
| 113 113 | 
             
                    post[:order_id] = options[:order_id]
         | 
| 114 114 | 
             
                    post[:device_session_id] = options[:device_session_id]
         | 
| 115 115 | 
             
                    post[:currency] = (options[:currency] || currency(money)).upcase
         | 
| 116 | 
            +
                    post[:use_card_points] = options[:use_card_points] if options[:use_card_points]
         | 
| 116 117 | 
             
                    add_creditcard(post, creditcard, options)
         | 
| 117 118 | 
             
                    post
         | 
| 118 119 | 
             
                  end
         | 
| @@ -417,10 +417,12 @@ module ActiveMerchant #:nodoc: | |
| 417 417 | 
             
                    #   Do not submit the attribute at all.
         | 
| 418 418 | 
             
                    # - http://download.chasepaymentech.com/docs/orbital/orbital_gateway_xml_specification.pdf
         | 
| 419 419 | 
             
                    unless creditcard.nil?
         | 
| 420 | 
            -
                      if  | 
| 421 | 
            -
                         | 
| 420 | 
            +
                      if creditcard.verification_value?
         | 
| 421 | 
            +
                        if %w( visa discover ).include?(creditcard.brand)
         | 
| 422 | 
            +
                          xml.tag! :CardSecValInd, '1'
         | 
| 423 | 
            +
                        end
         | 
| 424 | 
            +
                        xml.tag! :CardSecVal,  creditcard.verification_value
         | 
| 422 425 | 
             
                      end
         | 
| 423 | 
            -
                      xml.tag! :CardSecVal,  creditcard.verification_value if creditcard.verification_value?
         | 
| 424 426 | 
             
                    end
         | 
| 425 427 | 
             
                  end
         | 
| 426 428 |  | 
| @@ -37,6 +37,7 @@ module ActiveMerchant | |
| 37 37 | 
             
                    add_payment_method(params, payment_method)
         | 
| 38 38 | 
             
                    add_address(params, options)
         | 
| 39 39 | 
             
                    add_amount(params, amount, options)
         | 
| 40 | 
            +
                    add_soft_descriptors(params, options)
         | 
| 40 41 |  | 
| 41 42 | 
             
                    commit(params, options)
         | 
| 42 43 | 
             
                  end
         | 
| @@ -48,6 +49,7 @@ module ActiveMerchant | |
| 48 49 | 
             
                    add_payment_method(params, payment_method)
         | 
| 49 50 | 
             
                    add_address(params, options)
         | 
| 50 51 | 
             
                    add_amount(params, amount, options)
         | 
| 52 | 
            +
                    add_soft_descriptors(params, options)
         | 
| 51 53 |  | 
| 52 54 | 
             
                    commit(params, options)
         | 
| 53 55 | 
             
                  end
         | 
| @@ -57,6 +59,7 @@ module ActiveMerchant | |
| 57 59 |  | 
| 58 60 | 
             
                    add_authorization_info(params, authorization)
         | 
| 59 61 | 
             
                    add_amount(params, amount, options)
         | 
| 62 | 
            +
                    add_soft_descriptors(params, options)
         | 
| 60 63 |  | 
| 61 64 | 
             
                    commit(params, options)
         | 
| 62 65 | 
             
                  end
         | 
| @@ -169,6 +172,10 @@ module ActiveMerchant | |
| 169 172 | 
             
                    params[:amount] = amount(money)
         | 
| 170 173 | 
             
                  end
         | 
| 171 174 |  | 
| 175 | 
            +
                  def add_soft_descriptors(params, options)
         | 
| 176 | 
            +
                    params[:soft_descriptors] = options[:soft_descriptors] if options[:soft_descriptors]
         | 
| 177 | 
            +
                  end
         | 
| 178 | 
            +
             | 
| 172 179 | 
             
                  def commit(params, options)
         | 
| 173 180 | 
             
                    url = if options[:integration]
         | 
| 174 181 | 
             
                      integration_url
         | 
| @@ -29,6 +29,7 @@ module ActiveMerchant #:nodoc: | |
| 29 29 | 
             
                    add_creditcard(post, creditcard)
         | 
| 30 30 | 
             
                    add_address(post, creditcard, options)
         | 
| 31 31 | 
             
                    add_capture(post, options)
         | 
| 32 | 
            +
                    add_metadata(post, options)
         | 
| 32 33 |  | 
| 33 34 | 
             
                    commit(:post, 'charges', post, options)
         | 
| 34 35 | 
             
                  end
         | 
| @@ -141,6 +142,10 @@ module ActiveMerchant #:nodoc: | |
| 141 142 | 
             
                    end
         | 
| 142 143 | 
             
                  end
         | 
| 143 144 |  | 
| 145 | 
            +
                  def add_metadata(post, options)
         | 
| 146 | 
            +
                    post[:metadata] = options[:metadata] if options[:metadata]
         | 
| 147 | 
            +
                  end
         | 
| 148 | 
            +
             | 
| 144 149 | 
             
                  def headers(params = {})
         | 
| 145 150 | 
             
                    result = {
         | 
| 146 151 | 
             
                      "Content-Type" => "application/json",
         | 
| @@ -10,16 +10,16 @@ module ActiveMerchant #:nodoc: | |
| 10 10 | 
             
                  self.abstract_class = true
         | 
| 11 11 |  | 
| 12 12 | 
             
                  def self.new(options = {})
         | 
| 13 | 
            -
                    options.fetch(:login)  | 
| 13 | 
            +
                    options.fetch(:login) { raise ArgumentError.new("Missing required parameter: login") }
         | 
| 14 14 |  | 
| 15 15 | 
             
                    version = options[:login].to_i < 10000000 ? 10 : 7
         | 
| 16 16 | 
             
                    if version <= 7
         | 
| 17 17 | 
             
                      QuickpayV4to7Gateway.new(options)
         | 
| 18 18 | 
             
                    else
         | 
| 19 | 
            -
                      QuickpayV10Gateway.new(options) | 
| 19 | 
            +
                      QuickpayV10Gateway.new(options)
         | 
| 20 20 | 
             
                    end
         | 
| 21 21 | 
             
                  end
         | 
| 22 | 
            -
             | 
| 22 | 
            +
             | 
| 23 23 | 
             
                end
         | 
| 24 24 | 
             
              end
         | 
| 25 25 | 
             
            end
         | 
| @@ -13,7 +13,7 @@ module ActiveMerchant #:nodoc: | |
| 13 13 | 
             
                  self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners]
         | 
| 14 14 |  | 
| 15 15 | 
             
                  def initialize(options={})
         | 
| 16 | 
            -
                    requires!(options, :username, :password, :merchant)
         | 
| 16 | 
            +
                    requires!(options, :username, :password, :merchant, :pem, :pem_password)
         | 
| 17 17 | 
             
                    super
         | 
| 18 18 | 
             
                  end
         | 
| 19 19 |  | 
| @@ -24,19 +24,52 @@ module ActiveMerchant #:nodoc: | |
| 24 24 | 
             
                    add_payment_method(post, payment_method)
         | 
| 25 25 | 
             
                    add_verification_value(post, payment_method)
         | 
| 26 26 | 
             
                    add_customer_data(post, options)
         | 
| 27 | 
            +
                    add_soft_descriptors(post, options)
         | 
| 27 28 |  | 
| 28 29 | 
             
                    commit("capture", post)
         | 
| 29 30 | 
             
                  end
         | 
| 30 31 |  | 
| 32 | 
            +
                  def authorize(amount, payment_method, options={})
         | 
| 33 | 
            +
                    post = {}
         | 
| 34 | 
            +
                    add_invoice(post, amount, options)
         | 
| 35 | 
            +
                    add_order_number(post, options)
         | 
| 36 | 
            +
                    add_payment_method(post, payment_method)
         | 
| 37 | 
            +
                    add_verification_value(post, payment_method)
         | 
| 38 | 
            +
                    add_customer_data(post, options)
         | 
| 39 | 
            +
                    add_soft_descriptors(post, options)
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    commit("preauth", post)
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  def capture(amount, authorization, options={})
         | 
| 45 | 
            +
                    post = {}
         | 
| 46 | 
            +
                    add_invoice(post, amount, options)
         | 
| 47 | 
            +
                    add_reference(post, authorization, options)
         | 
| 48 | 
            +
                    add_customer_data(post, options)
         | 
| 49 | 
            +
                    add_soft_descriptors(post, options)
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    commit("captureWithoutAuth", post)
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
             | 
| 31 54 | 
             
                  def refund(amount, authorization, options={})
         | 
| 32 55 | 
             
                    post = {}
         | 
| 33 56 | 
             
                    add_invoice(post, amount, options)
         | 
| 34 57 | 
             
                    add_reference(post, authorization, options)
         | 
| 35 58 | 
             
                    add_customer_data(post, options)
         | 
| 59 | 
            +
                    add_soft_descriptors(post, options)
         | 
| 36 60 |  | 
| 37 61 | 
             
                    commit("refund", post)
         | 
| 38 62 | 
             
                  end
         | 
| 39 63 |  | 
| 64 | 
            +
                  def void(authorization, options={})
         | 
| 65 | 
            +
                    post = {}
         | 
| 66 | 
            +
                    add_reference(post, authorization, options)
         | 
| 67 | 
            +
                    add_customer_data(post, options)
         | 
| 68 | 
            +
                    add_soft_descriptors(post, options)
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                    commit("reversal", post)
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
             | 
| 40 73 | 
             
                  def store(payment_method, options = {})
         | 
| 41 74 | 
             
                    post = {}
         | 
| 42 75 | 
             
                    add_payment_method(post, payment_method)
         | 
| @@ -62,6 +95,16 @@ module ActiveMerchant #:nodoc: | |
| 62 95 | 
             
                  CURRENCY_CODES["AUD"] = "AUD"
         | 
| 63 96 | 
             
                  CURRENCY_CODES["INR"] = "INR"
         | 
| 64 97 |  | 
| 98 | 
            +
                  def add_soft_descriptors(post, options)
         | 
| 99 | 
            +
                    post["customer.merchantName"] = options[:customer_merchant_name] if options[:customer_merchant_name]
         | 
| 100 | 
            +
                    post["customer.merchantStreetAddress"] = options[:customer_merchant_street_address] if options[:customer_merchant_street_address]
         | 
| 101 | 
            +
                    post["customer.merchantLocation"] = options[:customer_merchant_location] if options[:customer_merchant_location]
         | 
| 102 | 
            +
                    post["customer.merchantState"] = options[:customer_merchant_state] if options[:customer_merchant_state]
         | 
| 103 | 
            +
                    post["customer.merchantCountry"] = options[:customer_merchant_country] if options[:customer_merchant_country]
         | 
| 104 | 
            +
                    post["customer.merchantPostCode"] = options[:customer_merchant_post_code] if options[:customer_merchant_post_code]
         | 
| 105 | 
            +
                    post["customer.subMerchantId"] = options[:customer_sub_merchant_id] if options[:customer_sub_merchant_id]
         | 
| 106 | 
            +
                  end
         | 
| 107 | 
            +
             | 
| 65 108 | 
             
                  def add_invoice(post, money, options)
         | 
| 66 109 | 
             
                    post["order.amount"] = amount(money)
         | 
| 67 110 | 
             
                    post["card.currency"] = CURRENCY_CODES[options[:currency] || currency(money)]
         | 
| @@ -0,0 +1,211 @@ | |
| 1 | 
            +
            require 'nokogiri'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module ActiveMerchant #:nodoc:
         | 
| 4 | 
            +
              module Billing #:nodoc:
         | 
| 5 | 
            +
                class SafeChargeGateway < Gateway
         | 
| 6 | 
            +
                  self.test_url = 'https://process.sandbox.safecharge.com/service.asmx/Process'
         | 
| 7 | 
            +
                  self.live_url = 'https://process.safecharge.com/service.asmx/Process'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  self.supported_countries = ['US']
         | 
| 10 | 
            +
                  self.default_currency = 'USD'
         | 
| 11 | 
            +
                  self.supported_cardtypes = [:visa, :master]
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  self.homepage_url = 'https://www.safecharge.com'
         | 
| 14 | 
            +
                  self.display_name = 'SafeCharge'
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  VERSION = '4.0.4'
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  def initialize(options={})
         | 
| 19 | 
            +
                    requires!(options, :client_login_id, :client_password)
         | 
| 20 | 
            +
                    super
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  def purchase(money, payment, options={})
         | 
| 24 | 
            +
                    post = {}
         | 
| 25 | 
            +
                    add_transaction_data("Sale", post, money, options)
         | 
| 26 | 
            +
                    add_payment(post, payment)
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    commit(post)
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  def authorize(money, payment, options={})
         | 
| 32 | 
            +
                    post = {}
         | 
| 33 | 
            +
                    add_transaction_data("Auth", post, money, options)
         | 
| 34 | 
            +
                    add_payment(post, payment)
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                    commit(post)
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  def capture(money, authorization, options={})
         | 
| 40 | 
            +
                    post = {}
         | 
| 41 | 
            +
                    add_transaction_data("Settle", post, money, options)
         | 
| 42 | 
            +
                    auth, transaction_id, token, exp_month, exp_year, _ = authorization.split("|")
         | 
| 43 | 
            +
                    post[:sg_AuthCode] = auth
         | 
| 44 | 
            +
                    post[:sg_TransactionID] = transaction_id
         | 
| 45 | 
            +
                    post[:sg_CCToken] = token
         | 
| 46 | 
            +
                    post[:sg_ExpMonth] = exp_month
         | 
| 47 | 
            +
                    post[:sg_ExpYear] = exp_year
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    commit(post)
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  def refund(money, authorization, options={})
         | 
| 53 | 
            +
                    post = {}
         | 
| 54 | 
            +
                    add_transaction_data("Credit", post, money, options)
         | 
| 55 | 
            +
                    auth, transaction_id, token, exp_month, exp_year, _ = authorization.split("|")
         | 
| 56 | 
            +
                    post[:sg_CreditType] = 2
         | 
| 57 | 
            +
                    post[:sg_AuthCode] = auth
         | 
| 58 | 
            +
                    post[:sg_TransactionID] = transaction_id
         | 
| 59 | 
            +
                    post[:sg_CCToken] = token
         | 
| 60 | 
            +
                    post[:sg_ExpMonth] = exp_month
         | 
| 61 | 
            +
                    post[:sg_ExpYear] = exp_year
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                    commit(post)
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  def void(authorization, options={})
         | 
| 67 | 
            +
                    post = {}
         | 
| 68 | 
            +
                    auth, transaction_id, token, exp_month, exp_year, original_amount = authorization.split("|")
         | 
| 69 | 
            +
                    add_transaction_data("Void", post, (original_amount.to_f * 100), options)
         | 
| 70 | 
            +
                    post[:sg_CreditType] = 2
         | 
| 71 | 
            +
                    post[:sg_AuthCode] = auth
         | 
| 72 | 
            +
                    post[:sg_TransactionID] = transaction_id
         | 
| 73 | 
            +
                    post[:sg_CCToken] = token
         | 
| 74 | 
            +
                    post[:sg_ExpMonth] = exp_month
         | 
| 75 | 
            +
                    post[:sg_ExpYear] = exp_year
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                    commit(post)
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  def verify(credit_card, options={})
         | 
| 81 | 
            +
                    MultiResponse.run(:use_first_response) do |r|
         | 
| 82 | 
            +
                      r.process { authorize(100, credit_card, options) }
         | 
| 83 | 
            +
                      r.process(:ignore_result) { void(r.authorization, options) }
         | 
| 84 | 
            +
                    end
         | 
| 85 | 
            +
                  end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                  def supports_scrubbing?
         | 
| 88 | 
            +
                    true
         | 
| 89 | 
            +
                  end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                  def scrub(transcript)
         | 
| 92 | 
            +
                    transcript.
         | 
| 93 | 
            +
                      gsub(%r((sg_ClientPassword=)[^&]+(&?)), '\1[FILTERED]\2').
         | 
| 94 | 
            +
                      gsub(%r((sg_CardNumber=)[^&]+(&?)), '\1[FILTERED]\2').
         | 
| 95 | 
            +
                      gsub(%r((sg_CVV2=)\d+), '\1[FILTERED]')
         | 
| 96 | 
            +
                  end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                  private
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                  def add_transaction_data(trans_type, post, money, options)
         | 
| 101 | 
            +
                    post[:sg_TransType] = trans_type
         | 
| 102 | 
            +
                    post[:sg_Currency] = (options[:currency] || currency(money))
         | 
| 103 | 
            +
                    post[:sg_Amount] = amount(money)
         | 
| 104 | 
            +
                    post[:sg_ClientLoginID] = @options[:client_login_id]
         | 
| 105 | 
            +
                    post[:sg_ClientPassword] = @options[:client_password]
         | 
| 106 | 
            +
                    post[:sg_ResponseFormat] = "4"
         | 
| 107 | 
            +
                    post[:sg_Version] = VERSION
         | 
| 108 | 
            +
                  end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                  def add_payment(post, payment)
         | 
| 111 | 
            +
                    post[:sg_NameOnCard] = payment.name
         | 
| 112 | 
            +
                    post[:sg_CardNumber] = payment.number
         | 
| 113 | 
            +
                    post[:sg_ExpMonth] = format(payment.month, :two_digits)
         | 
| 114 | 
            +
                    post[:sg_ExpYear] = format(payment.year, :two_digits)
         | 
| 115 | 
            +
                    post[:sg_CVV2] = payment.verification_value
         | 
| 116 | 
            +
                  end
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                  def parse(xml)
         | 
| 119 | 
            +
                    response = {}
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                    doc = Nokogiri::XML(xml)
         | 
| 122 | 
            +
                    doc.root.xpath('*').each do |node|
         | 
| 123 | 
            +
                      response[node.name.underscore.downcase.to_sym] = node.text
         | 
| 124 | 
            +
                    end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                    response
         | 
| 127 | 
            +
                  end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                  def childnode_to_response(response, node, childnode)
         | 
| 130 | 
            +
                    name = "#{node.name.downcase}_#{childnode.name.downcase}"
         | 
| 131 | 
            +
                    if name == 'payment_method_data' && !childnode.elements.empty?
         | 
| 132 | 
            +
                      response[name.to_sym] = Hash.from_xml(childnode.to_s).values.first
         | 
| 133 | 
            +
                    else
         | 
| 134 | 
            +
                      response[name.to_sym] = childnode.text
         | 
| 135 | 
            +
                    end
         | 
| 136 | 
            +
                  end
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                  def commit(parameters)
         | 
| 139 | 
            +
                    url = (test? ? test_url : live_url)
         | 
| 140 | 
            +
                    response = parse(ssl_post(url, post_data(parameters)))
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                    Response.new(
         | 
| 143 | 
            +
                      success_from(response),
         | 
| 144 | 
            +
                      message_from(response),
         | 
| 145 | 
            +
                      response,
         | 
| 146 | 
            +
                      authorization: authorization_from(response, parameters),
         | 
| 147 | 
            +
                      avs_result: AVSResult.new(code: response[:avs_code]),
         | 
| 148 | 
            +
                      cvv_result: CVVResult.new(response[:cvv2_reply]),
         | 
| 149 | 
            +
                      test: test?,
         | 
| 150 | 
            +
                      error_code: error_code_from(response)
         | 
| 151 | 
            +
                    )
         | 
| 152 | 
            +
                  end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                  def success_from(response)
         | 
| 155 | 
            +
                    response[:status] == "APPROVED"
         | 
| 156 | 
            +
                  end
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                  def message_from(response)
         | 
| 159 | 
            +
                    return "Success" if success_from(response)
         | 
| 160 | 
            +
                    response[:reason_codes] || response[:reason]
         | 
| 161 | 
            +
                  end
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                  def authorization_from(response, parameters)
         | 
| 164 | 
            +
                    [
         | 
| 165 | 
            +
                      response[:auth_code],
         | 
| 166 | 
            +
                      response[:transaction_id],
         | 
| 167 | 
            +
                      response[:token],
         | 
| 168 | 
            +
                      parameters[:sg_ExpMonth],
         | 
| 169 | 
            +
                      parameters[:sg_ExpYear],
         | 
| 170 | 
            +
                      parameters[:sg_Amount]
         | 
| 171 | 
            +
                    ].join("|")
         | 
| 172 | 
            +
                  end
         | 
| 173 | 
            +
             | 
| 174 | 
            +
                  def split_authorization(authorization)
         | 
| 175 | 
            +
                    auth_code, transaction_id, token, month, year, original_amount = authorization.split("|")
         | 
| 176 | 
            +
             | 
| 177 | 
            +
                    {
         | 
| 178 | 
            +
                      auth_code: auth_code,
         | 
| 179 | 
            +
                      transaction_id: transaction_id,
         | 
| 180 | 
            +
                      token: token,
         | 
| 181 | 
            +
                      exp_month: month,
         | 
| 182 | 
            +
                      exp_year: year,
         | 
| 183 | 
            +
                      original_amount: amount(original_amount.to_f * 100)
         | 
| 184 | 
            +
                    }
         | 
| 185 | 
            +
                  end
         | 
| 186 | 
            +
             | 
| 187 | 
            +
                  def post_data(params)
         | 
| 188 | 
            +
                    return nil unless params
         | 
| 189 | 
            +
             | 
| 190 | 
            +
                    params.map do |key, value|
         | 
| 191 | 
            +
                      next if value != false && value.blank?
         | 
| 192 | 
            +
                      "#{key}=#{CGI.escape(value.to_s)}"
         | 
| 193 | 
            +
                    end.compact.join("&")
         | 
| 194 | 
            +
                  end
         | 
| 195 | 
            +
             | 
| 196 | 
            +
                  def error_code_from(response)
         | 
| 197 | 
            +
                    unless success_from(response)
         | 
| 198 | 
            +
                      response[:ex_err_code] || response[:err_code]
         | 
| 199 | 
            +
                    end
         | 
| 200 | 
            +
                  end
         | 
| 201 | 
            +
             | 
| 202 | 
            +
                  def underscore(camel_cased_word)
         | 
| 203 | 
            +
                    camel_cased_word.to_s.gsub(/::/, '/').
         | 
| 204 | 
            +
                      gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
         | 
| 205 | 
            +
                      gsub(/([a-z\d])([A-Z])/,'\1_\2').
         | 
| 206 | 
            +
                      tr("-", "_").
         | 
| 207 | 
            +
                      downcase
         | 
| 208 | 
            +
                  end
         | 
| 209 | 
            +
                end
         | 
| 210 | 
            +
              end
         | 
| 211 | 
            +
            end
         |