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
| @@ -20,7 +20,8 @@ module ActiveMerchant #:nodoc: | |
| 20 20 | 
             
                    :void => 'VOID',
         | 
| 21 21 | 
             
                    :abort => 'ABORT',
         | 
| 22 22 | 
             
                    :store => 'TOKEN',
         | 
| 23 | 
            -
                    :unstore => 'REMOVETOKEN'
         | 
| 23 | 
            +
                    :unstore => 'REMOVETOKEN',
         | 
| 24 | 
            +
                    :repeat => 'REPEAT'
         | 
| 24 25 | 
             
                  }
         | 
| 25 26 |  | 
| 26 27 | 
             
                  CREDIT_CARDS = {
         | 
| @@ -87,7 +88,7 @@ module ActiveMerchant #:nodoc: | |
| 87 88 | 
             
                    add_customer_data(post, options)
         | 
| 88 89 | 
             
                    add_optional_data(post, options)
         | 
| 89 90 |  | 
| 90 | 
            -
                    commit(:purchase, post)
         | 
| 91 | 
            +
                    commit((options[:repeat] ? :repeat : :purchase), post)
         | 
| 91 92 | 
             
                  end
         | 
| 92 93 |  | 
| 93 94 | 
             
                  def authorize(money, payment_method, options = {})
         | 
| @@ -130,7 +131,7 @@ module ActiveMerchant #:nodoc: | |
| 130 131 |  | 
| 131 132 | 
             
                    post = {}
         | 
| 132 133 |  | 
| 133 | 
            -
                     | 
| 134 | 
            +
                    add_related_reference(post, identification)
         | 
| 134 135 | 
             
                    add_amount(post, money, options)
         | 
| 135 136 | 
             
                    add_invoice(post, options)
         | 
| 136 137 |  | 
| @@ -195,7 +196,7 @@ module ActiveMerchant #:nodoc: | |
| 195 196 | 
             
                    add_pair(post, :SecurityKey, security_key)
         | 
| 196 197 | 
             
                  end
         | 
| 197 198 |  | 
| 198 | 
            -
                  def  | 
| 199 | 
            +
                  def add_related_reference(post, identification)
         | 
| 199 200 | 
             
                    order_id, transaction_id, authorization, security_key = identification.split(';')
         | 
| 200 201 |  | 
| 201 202 | 
             
                    add_pair(post, :RelatedVendorTxCode, order_id)
         | 
| @@ -267,7 +268,9 @@ module ActiveMerchant #:nodoc: | |
| 267 268 | 
             
                  end
         | 
| 268 269 |  | 
| 269 270 | 
             
                  def add_payment_method(post, payment_method, options)
         | 
| 270 | 
            -
                    if  | 
| 271 | 
            +
                    if options[:repeat]
         | 
| 272 | 
            +
                      add_related_reference(post, payment_method)
         | 
| 273 | 
            +
                    elsif payment_method.respond_to?(:number)
         | 
| 271 274 | 
             
                      add_credit_card(post, payment_method)
         | 
| 272 275 | 
             
                    else
         | 
| 273 276 | 
             
                      add_token_details(post, payment_method, options)
         | 
| @@ -475,7 +475,7 @@ module ActiveMerchant #:nodoc: | |
| 475 475 | 
             
                      "Authorization" => "Basic " + Base64.encode64(key.to_s + ":").strip,
         | 
| 476 476 | 
             
                      "User-Agent" => "Stripe/v1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
         | 
| 477 477 | 
             
                      "Stripe-Version" => api_version(options),
         | 
| 478 | 
            -
                      "X-Stripe-Client-User-Agent" =>  | 
| 478 | 
            +
                      "X-Stripe-Client-User-Agent" => stripe_client_user_agent(options),
         | 
| 479 479 | 
             
                      "X-Stripe-Client-User-Metadata" => {:ip => options[:ip]}.to_json
         | 
| 480 480 | 
             
                    }
         | 
| 481 481 | 
             
                    headers.merge!("Idempotency-Key" => idempotency_key) if idempotency_key
         | 
| @@ -483,6 +483,11 @@ module ActiveMerchant #:nodoc: | |
| 483 483 | 
             
                    headers
         | 
| 484 484 | 
             
                  end
         | 
| 485 485 |  | 
| 486 | 
            +
                  def stripe_client_user_agent(options)
         | 
| 487 | 
            +
                    return user_agent unless options[:application]
         | 
| 488 | 
            +
                    JSON.dump(JSON.parse(user_agent).merge!({application: options[:application]}))
         | 
| 489 | 
            +
                  end
         | 
| 490 | 
            +
             | 
| 486 491 | 
             
                  def api_version(options)
         | 
| 487 492 | 
             
                    options[:version] || @options[:version] || "2015-04-07"
         | 
| 488 493 | 
             
                  end
         | 
| @@ -175,6 +175,10 @@ module ActiveMerchant #:nodoc: | |
| 175 175 |  | 
| 176 176 | 
             
                    verify: 9,
         | 
| 177 177 |  | 
| 178 | 
            +
                    purchase_echeck: 11,
         | 
| 179 | 
            +
                    refund_echeck: 16,
         | 
| 180 | 
            +
                    void_echeck: 16,
         | 
| 181 | 
            +
             | 
| 178 182 | 
             
                    wallet_sale: 14,
         | 
| 179 183 | 
             
                  }
         | 
| 180 184 |  | 
| @@ -187,7 +191,15 @@ module ActiveMerchant #:nodoc: | |
| 187 191 | 
             
                    if credit_card?(payment_method)
         | 
| 188 192 | 
             
                      action = :purchase
         | 
| 189 193 | 
             
                      request = build_xml_transaction_request do |doc|
         | 
| 190 | 
            -
                         | 
| 194 | 
            +
                        add_credit_card(doc, payment_method)
         | 
| 195 | 
            +
                        add_contact(doc, payment_method.name, options)
         | 
| 196 | 
            +
                        add_amount(doc, amount)
         | 
| 197 | 
            +
                        add_order_number(doc, options)
         | 
| 198 | 
            +
                      end
         | 
| 199 | 
            +
                    elsif echeck?(payment_method)
         | 
| 200 | 
            +
                      action = :purchase_echeck
         | 
| 201 | 
            +
                      request = build_xml_transaction_request do |doc|
         | 
| 202 | 
            +
                        add_echeck(doc, payment_method)
         | 
| 191 203 | 
             
                        add_contact(doc, payment_method.name, options)
         | 
| 192 204 | 
             
                        add_amount(doc, amount)
         | 
| 193 205 | 
             
                        add_order_number(doc, options)
         | 
| @@ -207,7 +219,7 @@ module ActiveMerchant #:nodoc: | |
| 207 219 | 
             
                  def authorize(amount, payment_method, options={})
         | 
| 208 220 | 
             
                    if credit_card?(payment_method)
         | 
| 209 221 | 
             
                      request = build_xml_transaction_request do |doc|
         | 
| 210 | 
            -
                         | 
| 222 | 
            +
                        add_credit_card(doc, payment_method)
         | 
| 211 223 | 
             
                        add_contact(doc, payment_method.name, options)
         | 
| 212 224 | 
             
                        add_amount(doc, amount)
         | 
| 213 225 | 
             
                      end
         | 
| @@ -243,14 +255,14 @@ module ActiveMerchant #:nodoc: | |
| 243 255 | 
             
                  end
         | 
| 244 256 |  | 
| 245 257 | 
             
                  def refund(amount, authorization, options={})
         | 
| 246 | 
            -
                    transaction_id = split_authorization(authorization) | 
| 258 | 
            +
                    action, transaction_id = split_authorization(authorization)
         | 
| 247 259 |  | 
| 248 260 | 
             
                    request = build_xml_transaction_request do |doc|
         | 
| 249 | 
            -
                      add_amount(doc, amount)
         | 
| 261 | 
            +
                      add_amount(doc, amount) unless action == 'purchase_echeck'
         | 
| 250 262 | 
             
                      add_original_transaction_data(doc, transaction_id)
         | 
| 251 263 | 
             
                    end
         | 
| 252 264 |  | 
| 253 | 
            -
                    commit( | 
| 265 | 
            +
                    commit(refund_type(action), request)
         | 
| 254 266 | 
             
                  end
         | 
| 255 267 |  | 
| 256 268 | 
             
                  def credit(amount, payment_method, options={})
         | 
| @@ -264,7 +276,7 @@ module ActiveMerchant #:nodoc: | |
| 264 276 |  | 
| 265 277 | 
             
                  def verify(credit_card, options={})
         | 
| 266 278 | 
             
                    request = build_xml_transaction_request do |doc|
         | 
| 267 | 
            -
                       | 
| 279 | 
            +
                      add_credit_card(doc, credit_card)
         | 
| 268 280 | 
             
                      add_contact(doc, credit_card.name, options)
         | 
| 269 281 | 
             
                    end
         | 
| 270 282 |  | 
| @@ -286,7 +298,7 @@ module ActiveMerchant #:nodoc: | |
| 286 298 | 
             
                          add_customer_id(doc, customer_id)
         | 
| 287 299 | 
             
                          doc["v1"].pmt do
         | 
| 288 300 | 
             
                            doc["v1"].type 0 # add
         | 
| 289 | 
            -
                             | 
| 301 | 
            +
                            add_credit_card(doc, payment_method)
         | 
| 290 302 | 
             
                          end
         | 
| 291 303 | 
             
                        end
         | 
| 292 304 | 
             
                      end
         | 
| @@ -383,8 +395,9 @@ module ActiveMerchant #:nodoc: | |
| 383 395 |  | 
| 384 396 | 
             
                      message = RESPONSE_MESSAGES[code]
         | 
| 385 397 | 
             
                      extended = EXTENDED_RESPONSE_MESSAGES[extended_code]
         | 
| 398 | 
            +
                      ach_response = response["achResponse"]
         | 
| 386 399 |  | 
| 387 | 
            -
                      [message, extended].compact.join('. ')
         | 
| 400 | 
            +
                      [message, extended, ach_response].compact.join('. ')
         | 
| 388 401 | 
             
                    else
         | 
| 389 402 | 
             
                      response["faultstring"]
         | 
| 390 403 | 
             
                    end
         | 
| @@ -401,7 +414,11 @@ module ActiveMerchant #:nodoc: | |
| 401 414 |  | 
| 402 415 | 
             
                  # -- helper methods ----------------------------------------------------
         | 
| 403 416 | 
             
                  def credit_card?(payment_method)
         | 
| 404 | 
            -
                    payment_method.respond_to?(: | 
| 417 | 
            +
                    payment_method.respond_to?(:verification_value)
         | 
| 418 | 
            +
                  end
         | 
| 419 | 
            +
             | 
| 420 | 
            +
                  def echeck?(payment_method)
         | 
| 421 | 
            +
                    payment_method.respond_to?(:routing_number)
         | 
| 405 422 | 
             
                  end
         | 
| 406 423 |  | 
| 407 424 | 
             
                  def split_authorization(authorization)
         | 
| @@ -409,7 +426,11 @@ module ActiveMerchant #:nodoc: | |
| 409 426 | 
             
                  end
         | 
| 410 427 |  | 
| 411 428 | 
             
                  def void_type(action)
         | 
| 412 | 
            -
                    :"void_#{action}"
         | 
| 429 | 
            +
                    action == 'purchase_echeck' ? :void_echeck : :"void_#{action}"
         | 
| 430 | 
            +
                  end
         | 
| 431 | 
            +
             | 
| 432 | 
            +
                  def refund_type(action)
         | 
| 433 | 
            +
                    action == 'purchase_echeck' ? :refund_echeck : :refund
         | 
| 413 434 | 
             
                  end
         | 
| 414 435 |  | 
| 415 436 | 
             
                  # -- request methods ---------------------------------------------------
         | 
| @@ -482,7 +503,7 @@ module ActiveMerchant #:nodoc: | |
| 482 503 | 
             
                    }
         | 
| 483 504 | 
             
                  end
         | 
| 484 505 |  | 
| 485 | 
            -
                  def  | 
| 506 | 
            +
                  def add_credit_card(doc, payment_method)
         | 
| 486 507 | 
             
                    doc["v1"].card {
         | 
| 487 508 | 
             
                      doc["v1"].pan payment_method.number
         | 
| 488 509 | 
             
                      doc["v1"].sec payment_method.verification_value if payment_method.verification_value?
         | 
| @@ -490,6 +511,13 @@ module ActiveMerchant #:nodoc: | |
| 490 511 | 
             
                    }
         | 
| 491 512 | 
             
                  end
         | 
| 492 513 |  | 
| 514 | 
            +
                  def add_echeck(doc, payment_method)
         | 
| 515 | 
            +
                    doc["v1"].achEcheck {
         | 
| 516 | 
            +
                      doc["v1"].bankRtNr payment_method.routing_number
         | 
| 517 | 
            +
                      doc["v1"].acctNr payment_method.account_number
         | 
| 518 | 
            +
                    }
         | 
| 519 | 
            +
                  end
         | 
| 520 | 
            +
             | 
| 493 521 | 
             
                  def expiration_date(payment_method)
         | 
| 494 522 | 
             
                    yy = format(payment_method.year, :two_digits)
         | 
| 495 523 | 
             
                    mm = format(payment_method.month, :two_digits)
         | 
| @@ -540,6 +568,12 @@ module ActiveMerchant #:nodoc: | |
| 540 568 | 
             
                    end
         | 
| 541 569 | 
             
                  end
         | 
| 542 570 |  | 
| 571 | 
            +
                  def add_name(doc, payment_method)
         | 
| 572 | 
            +
                    doc["v1"].contact do
         | 
| 573 | 
            +
                      doc["v1"].fullName payment_method.name
         | 
| 574 | 
            +
                    end
         | 
| 575 | 
            +
                  end
         | 
| 576 | 
            +
             | 
| 543 577 | 
             
                  def add_original_transaction_data(doc, authorization)
         | 
| 544 578 | 
             
                    doc["v1"].origTranData do
         | 
| 545 579 | 
             
                      doc["v1"].tranNr authorization
         | 
| @@ -126,6 +126,7 @@ module ActiveMerchant #:nodoc: | |
| 126 126 | 
             
                    post[:payer_email_message] = options[:payer_email_message] if options[:payer_email_message]
         | 
| 127 127 | 
             
                    post[:payee_email_message] = options[:payee_email_message] if options[:payee_email_message]
         | 
| 128 128 | 
             
                    post[:reference_id] = options[:order_id] if options[:order_id]
         | 
| 129 | 
            +
                    post[:unique_id] = options[:unique_id] if options[:unique_id]
         | 
| 129 130 | 
             
                    post[:redirect_uri] = options[:redirect_uri] if options[:redirect_uri]
         | 
| 130 131 | 
             
                    post[:callback_uri] = options[:callback_uri] if options[:callback_uri]
         | 
| 131 132 | 
             
                    post[:fallback_uri] = options[:fallback_uri] if options[:fallback_uri]
         | 
| @@ -60,10 +60,15 @@ module ActiveMerchant #:nodoc: | |
| 60 60 | 
             
                  end
         | 
| 61 61 |  | 
| 62 62 | 
             
                  def refund(money, authorization, options = {})
         | 
| 63 | 
            -
                    MultiResponse.run do |r|
         | 
| 64 | 
            -
                      r.process{inquire_request(authorization, options, "CAPTURED", "SETTLED", "SETTLED_BY_MERCHANT")}
         | 
| 65 | 
            -
                      r.process{refund_request(money, authorization, options)}
         | 
| 63 | 
            +
                    response = MultiResponse.run do |r|
         | 
| 64 | 
            +
                      r.process { inquire_request(authorization, options, "CAPTURED", "SETTLED", "SETTLED_BY_MERCHANT") }
         | 
| 65 | 
            +
                      r.process { refund_request(money, authorization, options) }
         | 
| 66 66 | 
             
                    end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                    return response if response.success?
         | 
| 69 | 
            +
                    return response unless options[:force_full_refund_if_unsettled]
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                    void(authorization, options ) if response.params["last_event"] == "AUTHORISED"
         | 
| 67 72 | 
             
                  end
         | 
| 68 73 |  | 
| 69 74 | 
             
                  def verify(credit_card, options={})
         | 
| @@ -41,7 +41,7 @@ module ActiveMerchant #:nodoc: | |
| 41 41 |  | 
| 42 42 | 
             
                def raw_ssl_request(method, endpoint, data, headers = {})
         | 
| 43 43 | 
             
                  logger.warn "#{self.class} using ssl_strict=false, which is insecure" if logger unless ssl_strict
         | 
| 44 | 
            -
                  logger.warn "#{self.class} posting to plaintext endpoint, which is insecure" if logger unless endpoint =~ /^https:/
         | 
| 44 | 
            +
                  logger.warn "#{self.class} posting to plaintext endpoint, which is insecure" if logger unless endpoint.to_s =~ /^https:/
         | 
| 45 45 |  | 
| 46 46 | 
             
                  connection = new_connection(endpoint)
         | 
| 47 47 | 
             
                  connection.open_timeout = open_timeout
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: activemerchant
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1. | 
| 4 | 
            +
              version: 1.65.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Tobias Luetke
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2017- | 
| 11 | 
            +
            date: 2017-04-26 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: activesupport
         | 
| @@ -161,6 +161,7 @@ files: | |
| 161 161 | 
             
            - lib/active_merchant/billing/cvv_result.rb
         | 
| 162 162 | 
             
            - lib/active_merchant/billing/gateway.rb
         | 
| 163 163 | 
             
            - lib/active_merchant/billing/gateways.rb
         | 
| 164 | 
            +
            - lib/active_merchant/billing/gateways/adyen.rb
         | 
| 164 165 | 
             
            - lib/active_merchant/billing/gateways/allied_wallet.rb
         | 
| 165 166 | 
             
            - lib/active_merchant/billing/gateways/authorize_net.rb
         | 
| 166 167 | 
             
            - lib/active_merchant/billing/gateways/authorize_net_arb.rb
         | 
| @@ -170,7 +171,6 @@ files: | |
| 170 171 | 
             
            - lib/active_merchant/billing/gateways/bank_frick.rb
         | 
| 171 172 | 
             
            - lib/active_merchant/billing/gateways/banwire.rb
         | 
| 172 173 | 
             
            - lib/active_merchant/billing/gateways/barclaycard_smartpay.rb
         | 
| 173 | 
            -
            - lib/active_merchant/billing/gateways/barclays_epdq.rb
         | 
| 174 174 | 
             
            - lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb
         | 
| 175 175 | 
             
            - lib/active_merchant/billing/gateways/be2bill.rb
         | 
| 176 176 | 
             
            - lib/active_merchant/billing/gateways/beanstream.rb
         | 
| @@ -332,6 +332,7 @@ files: | |
| 332 332 | 
             
            - lib/active_merchant/billing/gateways/realex.rb
         | 
| 333 333 | 
             
            - lib/active_merchant/billing/gateways/redsys.rb
         | 
| 334 334 | 
             
            - lib/active_merchant/billing/gateways/s5.rb
         | 
| 335 | 
            +
            - lib/active_merchant/billing/gateways/safe_charge.rb
         | 
| 335 336 | 
             
            - lib/active_merchant/billing/gateways/sage.rb
         | 
| 336 337 | 
             
            - lib/active_merchant/billing/gateways/sage_pay.rb
         | 
| 337 338 | 
             
            - lib/active_merchant/billing/gateways/sallie_mae.rb
         | 
| @@ -1,314 +0,0 @@ | |
| 1 | 
            -
            module ActiveMerchant #:nodoc:
         | 
| 2 | 
            -
              module Billing #:nodoc:
         | 
| 3 | 
            -
                class BarclaysEpdqGateway < Gateway
         | 
| 4 | 
            -
                  self.test_url = 'https://secure2.mde.epdq.co.uk:11500'
         | 
| 5 | 
            -
                  self.live_url = 'https://secure2.epdq.co.uk:11500'
         | 
| 6 | 
            -
             | 
| 7 | 
            -
                  self.supported_countries = ['GB']
         | 
| 8 | 
            -
                  self.default_currency = 'GBP'
         | 
| 9 | 
            -
                  self.supported_cardtypes = [:visa, :master, :american_express, :maestro, :switch ]
         | 
| 10 | 
            -
                  self.money_format = :cents
         | 
| 11 | 
            -
                  self.homepage_url = 'http://www.barclaycard.co.uk/business/accepting-payments/epdq-mpi/'
         | 
| 12 | 
            -
                  self.display_name = 'Barclays ePDQ MPI'
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                  def initialize(options = {})
         | 
| 15 | 
            -
                    requires!(options, :login, :password, :client_id)
         | 
| 16 | 
            -
                    super
         | 
| 17 | 
            -
                  end
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                  def authorize(money, creditcard, options = {})
         | 
| 20 | 
            -
                    document = Document.new(self, @options) do
         | 
| 21 | 
            -
                      add_order_form(options[:order_id]) do
         | 
| 22 | 
            -
                        add_consumer(options) do
         | 
| 23 | 
            -
                          add_creditcard(creditcard)
         | 
| 24 | 
            -
                        end
         | 
| 25 | 
            -
                        add_transaction(:PreAuth, money)
         | 
| 26 | 
            -
                      end
         | 
| 27 | 
            -
                    end
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                    commit(document)
         | 
| 30 | 
            -
                  end
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                  def purchase(money, creditcard, options = {})
         | 
| 33 | 
            -
                    # disable fraud checks if this is a repeat order:
         | 
| 34 | 
            -
                    if options[:payment_number] && (options[:payment_number] > 1)
         | 
| 35 | 
            -
                      no_fraud = true
         | 
| 36 | 
            -
                    else
         | 
| 37 | 
            -
                      no_fraud = options[:no_fraud]
         | 
| 38 | 
            -
                    end
         | 
| 39 | 
            -
                    document = Document.new(self, @options, :no_fraud => no_fraud) do
         | 
| 40 | 
            -
                      add_order_form(options[:order_id], options[:group_id]) do
         | 
| 41 | 
            -
                        add_consumer(options) do
         | 
| 42 | 
            -
                          add_creditcard(creditcard)
         | 
| 43 | 
            -
                        end
         | 
| 44 | 
            -
                        add_transaction(:Auth, money, options)
         | 
| 45 | 
            -
                      end
         | 
| 46 | 
            -
                    end
         | 
| 47 | 
            -
                    commit(document)
         | 
| 48 | 
            -
                  end
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                  # authorization is your unique order ID, not the authorization
         | 
| 51 | 
            -
                  # code returned by ePDQ
         | 
| 52 | 
            -
                  def capture(money, authorization, options = {})
         | 
| 53 | 
            -
                    document = Document.new(self, @options) do
         | 
| 54 | 
            -
                      add_order_form(authorization) do
         | 
| 55 | 
            -
                        add_transaction(:PostAuth, money)
         | 
| 56 | 
            -
                      end
         | 
| 57 | 
            -
                    end
         | 
| 58 | 
            -
             | 
| 59 | 
            -
                    commit(document)
         | 
| 60 | 
            -
                  end
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                  # authorization is your unique order ID, not the authorization
         | 
| 63 | 
            -
                  # code returned by ePDQ
         | 
| 64 | 
            -
                  def credit(money, creditcard_or_authorization, options = {})
         | 
| 65 | 
            -
                    if creditcard_or_authorization.is_a?(String)
         | 
| 66 | 
            -
                      ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
         | 
| 67 | 
            -
                      refund(money, creditcard_or_authorization, options)
         | 
| 68 | 
            -
                    else
         | 
| 69 | 
            -
                      credit_new_order(money, creditcard_or_authorization, options)
         | 
| 70 | 
            -
                    end
         | 
| 71 | 
            -
                  end
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                  def refund(money, authorization, options = {})
         | 
| 74 | 
            -
                    credit_existing_order(money, authorization, options)
         | 
| 75 | 
            -
                  end
         | 
| 76 | 
            -
             | 
| 77 | 
            -
                  def void(authorization, options = {})
         | 
| 78 | 
            -
                    document = Document.new(self, @options) do
         | 
| 79 | 
            -
                      add_order_form(authorization) do
         | 
| 80 | 
            -
                        add_transaction(:Void)
         | 
| 81 | 
            -
                      end
         | 
| 82 | 
            -
                    end
         | 
| 83 | 
            -
             | 
| 84 | 
            -
                    commit(document)
         | 
| 85 | 
            -
                  end
         | 
| 86 | 
            -
             | 
| 87 | 
            -
                  private
         | 
| 88 | 
            -
                  def credit_new_order(money, creditcard, options)
         | 
| 89 | 
            -
                    document = Document.new(self, @options) do
         | 
| 90 | 
            -
                      add_order_form do
         | 
| 91 | 
            -
                        add_consumer(options) do
         | 
| 92 | 
            -
                          add_creditcard(creditcard)
         | 
| 93 | 
            -
                        end
         | 
| 94 | 
            -
                        add_transaction(:Credit, money)
         | 
| 95 | 
            -
                      end
         | 
| 96 | 
            -
                    end
         | 
| 97 | 
            -
             | 
| 98 | 
            -
                    commit(document)
         | 
| 99 | 
            -
                  end
         | 
| 100 | 
            -
             | 
| 101 | 
            -
                  def credit_existing_order(money, authorization, options)
         | 
| 102 | 
            -
                    order_id, _ = authorization.split(":")
         | 
| 103 | 
            -
                    document = Document.new(self, @options) do
         | 
| 104 | 
            -
                      add_order_form(order_id) do
         | 
| 105 | 
            -
                        add_transaction(:Credit, money)
         | 
| 106 | 
            -
                      end
         | 
| 107 | 
            -
                    end
         | 
| 108 | 
            -
             | 
| 109 | 
            -
                    commit(document)
         | 
| 110 | 
            -
                  end
         | 
| 111 | 
            -
             | 
| 112 | 
            -
                  def parse(body)
         | 
| 113 | 
            -
                    parser = Parser.new(body)
         | 
| 114 | 
            -
                    response = parser.parse
         | 
| 115 | 
            -
                    Response.new(response[:success], response[:message], response,
         | 
| 116 | 
            -
                      :test => test?,
         | 
| 117 | 
            -
                      :authorization => response[:authorization],
         | 
| 118 | 
            -
                      :avs_result => response[:avsresponse],
         | 
| 119 | 
            -
                      :cvv_result => response[:cvv_result],
         | 
| 120 | 
            -
                      :order_id => response[:order_id],
         | 
| 121 | 
            -
                      :raw_response => response[:raw_response]
         | 
| 122 | 
            -
                    )
         | 
| 123 | 
            -
                  end
         | 
| 124 | 
            -
             | 
| 125 | 
            -
                  def commit(document)
         | 
| 126 | 
            -
                    url = (test? ? self.test_url : self.live_url)
         | 
| 127 | 
            -
                    data = ssl_post(url, document.to_xml)
         | 
| 128 | 
            -
                    parse(data)
         | 
| 129 | 
            -
                  end
         | 
| 130 | 
            -
             | 
| 131 | 
            -
                  class Parser
         | 
| 132 | 
            -
                    def initialize(response)
         | 
| 133 | 
            -
                      @response = response
         | 
| 134 | 
            -
                    end
         | 
| 135 | 
            -
             | 
| 136 | 
            -
                    def parse
         | 
| 137 | 
            -
                      require 'iconv' unless String.method_defined?(:encode)
         | 
| 138 | 
            -
                      if String.method_defined?(:encode)
         | 
| 139 | 
            -
                        doc = REXML::Document.new(@response.encode("UTF-8", "ISO-8859-1"))
         | 
| 140 | 
            -
                      else
         | 
| 141 | 
            -
                        ic = Iconv.new('UTF-8', 'ISO-8859-1')
         | 
| 142 | 
            -
                        doc = REXML::Document.new(ic.iconv(@response))
         | 
| 143 | 
            -
                      end
         | 
| 144 | 
            -
             | 
| 145 | 
            -
                      auth_type = find(doc, "//Transaction/Type").to_s
         | 
| 146 | 
            -
             | 
| 147 | 
            -
                      message = find(doc, "//Message/Text")
         | 
| 148 | 
            -
                      if message.blank?
         | 
| 149 | 
            -
                        message = find(doc, "//Transaction/CardProcResp/CcReturnMsg")
         | 
| 150 | 
            -
                      end
         | 
| 151 | 
            -
             | 
| 152 | 
            -
                      case auth_type
         | 
| 153 | 
            -
                      when 'Credit', 'Void'
         | 
| 154 | 
            -
                        success = find(doc, "//CcReturnMsg") == "Approved."
         | 
| 155 | 
            -
                      else
         | 
| 156 | 
            -
                        success = find(doc, "//Transaction/AuthCode").present?
         | 
| 157 | 
            -
                      end
         | 
| 158 | 
            -
             | 
| 159 | 
            -
                      {
         | 
| 160 | 
            -
                        :success => success,
         | 
| 161 | 
            -
                        :message => message,
         | 
| 162 | 
            -
                        :transaction_id => find(doc, "//Transaction/Id"),
         | 
| 163 | 
            -
                        :avs_result => find(doc, "//Transaction/AvsRespCode"),
         | 
| 164 | 
            -
                        :cvv_result => find(doc, "//Transaction/Cvv2Resp"),
         | 
| 165 | 
            -
                        :authorization => find(doc, "//OrderFormDoc/Id"),
         | 
| 166 | 
            -
                        :raw_response => @response
         | 
| 167 | 
            -
                      }
         | 
| 168 | 
            -
                    end
         | 
| 169 | 
            -
             | 
| 170 | 
            -
                    def find(doc, xpath)
         | 
| 171 | 
            -
                      REXML::XPath.first(doc, xpath).try(:text)
         | 
| 172 | 
            -
                    end
         | 
| 173 | 
            -
                  end
         | 
| 174 | 
            -
             | 
| 175 | 
            -
                  class Document
         | 
| 176 | 
            -
                    attr_reader :type, :xml
         | 
| 177 | 
            -
             | 
| 178 | 
            -
                    PAYMENT_INTERVALS = {
         | 
| 179 | 
            -
                      :days => 'D',
         | 
| 180 | 
            -
                      :months => 'M'
         | 
| 181 | 
            -
                    }
         | 
| 182 | 
            -
             | 
| 183 | 
            -
                    EPDQ_CARD_TYPES = {
         | 
| 184 | 
            -
                      :visa => 1,
         | 
| 185 | 
            -
                      :master => 2,
         | 
| 186 | 
            -
                      :switch => 9,
         | 
| 187 | 
            -
                      :maestro => 10,
         | 
| 188 | 
            -
                    }
         | 
| 189 | 
            -
             | 
| 190 | 
            -
                    def initialize(gateway, options = {}, document_options = {}, &block)
         | 
| 191 | 
            -
                      @gateway = gateway
         | 
| 192 | 
            -
                      @options = options
         | 
| 193 | 
            -
                      @document_options = document_options
         | 
| 194 | 
            -
                      @xml = Builder::XmlMarkup.new(:indent => 2)
         | 
| 195 | 
            -
                      build(&block)
         | 
| 196 | 
            -
                    end
         | 
| 197 | 
            -
             | 
| 198 | 
            -
                    def to_xml
         | 
| 199 | 
            -
                      @xml.target!
         | 
| 200 | 
            -
                    end
         | 
| 201 | 
            -
             | 
| 202 | 
            -
                    def build(&block)
         | 
| 203 | 
            -
                      xml.instruct!(:xml, :version => '1.0')
         | 
| 204 | 
            -
                      xml.EngineDocList do
         | 
| 205 | 
            -
                        xml.DocVersion "1.0"
         | 
| 206 | 
            -
                        xml.EngineDoc do
         | 
| 207 | 
            -
                          xml.ContentType "OrderFormDoc"
         | 
| 208 | 
            -
                          xml.User do
         | 
| 209 | 
            -
                            xml.Name(@options[:login])
         | 
| 210 | 
            -
                            xml.Password(@options[:password])
         | 
| 211 | 
            -
                            xml.ClientId({ :DataType => "S32" }, @options[:client_id])
         | 
| 212 | 
            -
                          end
         | 
| 213 | 
            -
                          xml.Instructions do
         | 
| 214 | 
            -
                            if @document_options[:no_fraud]
         | 
| 215 | 
            -
                              xml.Pipeline "PaymentNoFraud"
         | 
| 216 | 
            -
                            else
         | 
| 217 | 
            -
                              xml.Pipeline "Payment"
         | 
| 218 | 
            -
                            end
         | 
| 219 | 
            -
                          end
         | 
| 220 | 
            -
                          instance_eval(&block)
         | 
| 221 | 
            -
                        end
         | 
| 222 | 
            -
                      end
         | 
| 223 | 
            -
                    end
         | 
| 224 | 
            -
             | 
| 225 | 
            -
                    def add_order_form(order_id=nil, group_id=nil, &block)
         | 
| 226 | 
            -
                      xml.OrderFormDoc do
         | 
| 227 | 
            -
                        xml.Mode 'P'
         | 
| 228 | 
            -
                        xml.Id(order_id) if order_id
         | 
| 229 | 
            -
                        xml.GroupId(group_id) if group_id
         | 
| 230 | 
            -
                        instance_eval(&block)
         | 
| 231 | 
            -
                      end
         | 
| 232 | 
            -
                    end
         | 
| 233 | 
            -
             | 
| 234 | 
            -
                    def add_consumer(options=nil, &block)
         | 
| 235 | 
            -
                      xml.Consumer do
         | 
| 236 | 
            -
                        if options
         | 
| 237 | 
            -
                          xml.Email(options[:email]) if options[:email]
         | 
| 238 | 
            -
                          billing_address = options[:billing_address] || options[:address]
         | 
| 239 | 
            -
                          if billing_address
         | 
| 240 | 
            -
                            xml.BillTo do
         | 
| 241 | 
            -
                              xml.Location do
         | 
| 242 | 
            -
                                xml.Address do
         | 
| 243 | 
            -
                                  xml.Street1 billing_address[:address1]
         | 
| 244 | 
            -
                                  xml.Street2 billing_address[:address2]
         | 
| 245 | 
            -
                                  xml.City billing_address[:city]
         | 
| 246 | 
            -
                                  xml.StateProv billing_address[:state]
         | 
| 247 | 
            -
                                  xml.PostalCode billing_address[:zip]
         | 
| 248 | 
            -
                                  xml.Country billing_address[:country_code]
         | 
| 249 | 
            -
                                end
         | 
| 250 | 
            -
                              end
         | 
| 251 | 
            -
                            end
         | 
| 252 | 
            -
                          end
         | 
| 253 | 
            -
                        end
         | 
| 254 | 
            -
                        instance_eval(&block)
         | 
| 255 | 
            -
                      end
         | 
| 256 | 
            -
                    end
         | 
| 257 | 
            -
             | 
| 258 | 
            -
                    def add_creditcard(creditcard)
         | 
| 259 | 
            -
                      xml.PaymentMech do
         | 
| 260 | 
            -
                        xml.CreditCard do
         | 
| 261 | 
            -
                          xml.Type({ :DataType => 'S32' }, EPDQ_CARD_TYPES[creditcard.brand.to_sym])
         | 
| 262 | 
            -
                          xml.Number creditcard.number
         | 
| 263 | 
            -
                          xml.Expires({ :DataType => 'ExpirationDate', :Locale => 826 }, format_expiry_date(creditcard))
         | 
| 264 | 
            -
                          if creditcard.verification_value.present?
         | 
| 265 | 
            -
                            xml.Cvv2Indicator 1
         | 
| 266 | 
            -
                            xml.Cvv2Val creditcard.verification_value
         | 
| 267 | 
            -
                          else
         | 
| 268 | 
            -
                            xml.Cvv2Indicator 5
         | 
| 269 | 
            -
                          end
         | 
| 270 | 
            -
                          xml.IssueNum(creditcard.issue_number) if creditcard.issue_number.present?
         | 
| 271 | 
            -
                        end
         | 
| 272 | 
            -
                      end
         | 
| 273 | 
            -
                    end
         | 
| 274 | 
            -
             | 
| 275 | 
            -
                    def add_transaction(auth_type, amount = nil, options = {})
         | 
| 276 | 
            -
                      @auth_type = auth_type
         | 
| 277 | 
            -
                      xml.Transaction do
         | 
| 278 | 
            -
                        xml.Type @auth_type.to_s
         | 
| 279 | 
            -
                        if options[:payment_number] && options[:payment_number] > 1
         | 
| 280 | 
            -
                          xml.CardholderPresentCode({ :DataType => 'S32' }, 8)
         | 
| 281 | 
            -
                        else
         | 
| 282 | 
            -
                          xml.CardholderPresentCode({ :DataType => 'S32' }, 7)
         | 
| 283 | 
            -
                        end
         | 
| 284 | 
            -
                        if options[:payment_number]
         | 
| 285 | 
            -
                          xml.PaymentNumber({ :DataType => 'S32' }, options[:payment_number])
         | 
| 286 | 
            -
                        end
         | 
| 287 | 
            -
                        if options[:total_payments]
         | 
| 288 | 
            -
                          xml.TotalNumberPayments({ :DataType => 'S32' }, options[:total_payments])
         | 
| 289 | 
            -
                        end
         | 
| 290 | 
            -
                        if amount
         | 
| 291 | 
            -
                          xml.CurrentTotals do
         | 
| 292 | 
            -
                            xml.Totals do
         | 
| 293 | 
            -
                              xml.Total({ :DataType => 'Money', :Currency => 826 }, amount)
         | 
| 294 | 
            -
                            end
         | 
| 295 | 
            -
                          end
         | 
| 296 | 
            -
                        end
         | 
| 297 | 
            -
                      end
         | 
| 298 | 
            -
                    end
         | 
| 299 | 
            -
             | 
| 300 | 
            -
                    # date must be formatted MM/YY
         | 
| 301 | 
            -
                    def format_expiry_date(creditcard)
         | 
| 302 | 
            -
                      month_str = "%02d" % creditcard.month
         | 
| 303 | 
            -
                      if match = creditcard.year.to_s.match(/^\d{2}(\d{2})$/)
         | 
| 304 | 
            -
                        year_str = "%02d" % match[1].to_i
         | 
| 305 | 
            -
                      else
         | 
| 306 | 
            -
                        year_str = "%02d" % creditcard.year
         | 
| 307 | 
            -
                      end
         | 
| 308 | 
            -
                      "#{month_str}/#{year_str}"
         | 
| 309 | 
            -
                    end
         | 
| 310 | 
            -
                  end
         | 
| 311 | 
            -
                end
         | 
| 312 | 
            -
              end
         | 
| 313 | 
            -
            end
         | 
| 314 | 
            -
             |