activemerchant 1.53.0 → 1.54.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a66a1463e2d11b64b17b7690b2fe48e97279a6b6
4
- data.tar.gz: 99be80349b8f54a9a07761c8b4b983c9353bf955
3
+ metadata.gz: 9fc6f0d2cdaee90794c21b2a864c1f388e137b7a
4
+ data.tar.gz: b8d2bdfb76e707aecd003b60ba388bd4e4c35b16
5
5
  SHA512:
6
- metadata.gz: ca1cae5f0c4cb904135e2464e36419f95383222408a45bd8e1fb02f91354701191a5c9ae34c95169e809effe08f093583c48b62477065d89860951e7921883f9
7
- data.tar.gz: 1b159f4b9bd19e5b80c20c7db233bbe10a54b92811e02c9f6cb4ea885e983b8fbb800c288bf919a20df3793a2e285b892483838ecc190be3214e336dc4d80bfd
6
+ metadata.gz: 7f022f77e95737535d03582cf5d79c3b93ef2ff44215e1343b73c574fe78269447c36bc8400ff1b4bacbdcf98a453a1dbffc3dce1b1452046fca6f4bb8230426
7
+ data.tar.gz: c4e19a130993eb296dddc128109873204078c2cf480d48c2cc47f57310ef79f1cd2b62a88cdc02af00791a7d1be08c78957bbc172df728ec18d6236369144a90
data/CHANGELOG CHANGED
@@ -1,6 +1,23 @@
1
1
  = ActiveMerchant CHANGELOG
2
2
 
3
3
 
4
+ == Version 1.54.0 (October 2, 2015)
5
+ * Beanstream: Add Network Tokenization support [girasquid]
6
+ * CenPOS: Allow order_id on void [duff]
7
+ * Provide better insight to CVV usage in requests [davidsantoso]
8
+ * Ogone: Add verify [duff]
9
+ * Beanstream: Add verify [mrezentes]
10
+ * PayPal: Map standard error codes [JakeCataford]
11
+ * Checkout.com: Fix an issue with empty phone numbers. [anotherjosmith]
12
+ * Quickpay: Edit store and add ability to purchase with stored card [anellis]
13
+ * Stripe: Set `receipt_email` to Stripe request if receipt delivery is requested [miccheng]
14
+ * Worldpay US: Add eCheck support [mrezentes]
15
+ * FirstData_e4: add level_3 data [mrezentes]
16
+ * Vanco: Support passing ip address [duff]
17
+ * Paybox Direct: Currency parsing fix [ivanfer]
18
+ * QuickpayV10: Remove currency requirement from store. [anellis]
19
+ * Raven: Use TLS 1.2 endpoint [bslobodin]
20
+
4
21
  == Version 1.53.0 (September 1, 2015)
5
22
 
6
23
  * Redsys: Add a number of currencies [agseco]
@@ -76,7 +76,10 @@ module ActiveMerchant #:nodoc:
76
76
  transcript.
77
77
  gsub(%r((Authorization: Bearer )[a-zA-Z0-9._-]+)i, '\1[FILTERED]').
78
78
  gsub(%r(("cardNumber\\?":\\?")[^"]*)i, '\1[FILTERED]').
79
- gsub(%r(("cVVCode\\?":\\?")[^"]*)i, '\1[FILTERED]')
79
+ gsub(%r(("cVVCode\\?":\\?")\d+[^"]*)i, '\1[FILTERED]').
80
+ gsub(%r(("cVVCode\\?":)null), '\1[BLANK]').
81
+ gsub(%r(("cVVCode\\?":\\?")\\?"), '\1[BLANK]"').
82
+ gsub(%r(("cVVCode\\?":\\?")\s+), '\1[BLANK]"')
80
83
  end
81
84
 
82
85
  private
@@ -99,6 +99,13 @@ module ActiveMerchant #:nodoc:
99
99
  commit(post)
100
100
  end
101
101
 
102
+ def verify(source, options={})
103
+ MultiResponse.run(:use_first_response) do |r|
104
+ r.process { authorize(100, source, options) }
105
+ r.process(:ignore_result) { void(r.authorization, options) }
106
+ end
107
+ end
108
+
102
109
  def success?(response)
103
110
  response[:trnApproved] == '1' || response[:responseCode] == '1'
104
111
  end
@@ -206,6 +206,11 @@ module ActiveMerchant #:nodoc:
206
206
  post[:trnExpMonth] = format(credit_card.month, :two_digits)
207
207
  post[:trnExpYear] = format(credit_card.year, :two_digits)
208
208
  post[:trnCardCvd] = credit_card.verification_value
209
+ if credit_card.is_a?(NetworkTokenizationCreditCard)
210
+ post[:"3DSecureXID"] = credit_card.transaction_id
211
+ post[:"3DSecureECI"] = credit_card.eci
212
+ post[:"3DSecureCAVV"] = credit_card.payment_cryptogram
213
+ end
209
214
  end
210
215
  end
211
216
 
@@ -51,6 +51,7 @@ module ActiveMerchant #:nodoc:
51
51
  add_reference(post, authorization)
52
52
  add_remembered_amount(post, authorization)
53
53
  add_tax(post, options)
54
+ add_order_id(post, options)
54
55
 
55
56
  commit("Void", post)
56
57
  end
@@ -95,9 +96,9 @@ module ActiveMerchant #:nodoc:
95
96
  def add_invoice(post, money, options)
96
97
  post[:Amount] = amount(money)
97
98
  post[:CurrencyCode] = options[:currency] || currency(money)
98
- post[:InvoiceNumber] = options[:order_id]
99
99
  post[:InvoiceDetail] = options[:invoice_detail] if options[:invoice_detail]
100
100
  post[:CustomerCode] = options[:customer_code] if options[:customer_code]
101
+ add_order_id(post, options)
101
102
  add_tax(post, options)
102
103
  end
103
104
 
@@ -126,6 +127,10 @@ module ActiveMerchant #:nodoc:
126
127
  post[:IMEI] = nil
127
128
  end
128
129
 
130
+ def add_order_id(post, options)
131
+ post[:InvoiceNumber] = options[:order_id]
132
+ end
133
+
129
134
  def add_tax(post, options)
130
135
  post[:TaxAmount] = amount(options[:tax] || 0)
131
136
  end
@@ -100,7 +100,7 @@ module ActiveMerchant #:nodoc:
100
100
  post[:card][:billingDetails][:state] = address[:state]
101
101
  post[:card][:billingDetails][:country] = address[:country]
102
102
  post[:card][:billingDetails][:postcode] = address[:zip]
103
- post[:card][:billingDetails][:phone] = { number: address[:phone] }
103
+ post[:card][:billingDetails][:phone] = { number: address[:phone] } unless address[:phone].blank?
104
104
  end
105
105
  end
106
106
 
@@ -172,6 +172,7 @@ module ActiveMerchant #:nodoc:
172
172
  add_customer_data(xml, options)
173
173
  add_invoice(xml, options)
174
174
  add_card_authentication_data(xml, options)
175
+ add_level_3(xml, options)
175
176
 
176
177
  xml.target!
177
178
  end
@@ -301,6 +302,12 @@ module ActiveMerchant #:nodoc:
301
302
  xml.tag! "Reference_3", options[:description] if options[:description]
302
303
  end
303
304
 
305
+ def add_level_3(xml, options)
306
+ if options[:level_3]
307
+ xml.level3 { |x| x << options[:level_3] }
308
+ end
309
+ end
310
+
304
311
  def expdate(credit_card)
305
312
  "#{format(credit_card.month, :two_digits)}#{format(credit_card.year, :two_digits)}"
306
313
  end
@@ -26,6 +26,7 @@ module ActiveMerchant #:nodoc:
26
26
  add_allow_dup(xml)
27
27
  add_customer_data(xml, card_or_token, options)
28
28
  add_details(xml, options)
29
+ add_descriptor_name(xml, options)
29
30
  add_payment(xml, card_or_token, options)
30
31
  end
31
32
  end
@@ -43,6 +44,7 @@ module ActiveMerchant #:nodoc:
43
44
  add_allow_dup(xml)
44
45
  add_customer_data(xml, card_or_token,options)
45
46
  add_details(xml, options)
47
+ add_descriptor_name(xml, options)
46
48
  add_payment(xml, card_or_token, options)
47
49
  end
48
50
  end
@@ -60,6 +62,7 @@ module ActiveMerchant #:nodoc:
60
62
  def verify(card_or_token, options={})
61
63
  commit('CreditAccountVerify') do |xml|
62
64
  add_customer_data(xml, card_or_token, options)
65
+ add_descriptor_name(xml, options)
63
66
  add_payment(xml, card_or_token, options)
64
67
  end
65
68
  end
@@ -146,6 +149,10 @@ module ActiveMerchant #:nodoc:
146
149
  xml.hps :AllowDup, 'Y'
147
150
  end
148
151
 
152
+ def add_descriptor_name(xml, options)
153
+ xml.hps :TxnDescriptor, options[:descriptor_name] if options[:descriptor_name]
154
+ end
155
+
149
156
  def build_request(action)
150
157
  xml = Builder::XmlMarkup.new(encoding: 'UTF-8')
151
158
  xml.instruct!(:xml, encoding: 'UTF-8')
@@ -1,6 +1,7 @@
1
1
  module ActiveMerchant #:nodoc:
2
2
  module Billing #:nodoc:
3
3
  class NmiGateway < Gateway
4
+ include Empty
4
5
 
5
6
  DUP_WINDOW_DEPRECATION_MESSAGE = "The class-level duplicate_window variable is deprecated. Please use the :dup_seconds transaction option instead."
6
7
 
@@ -140,7 +141,7 @@ module ActiveMerchant #:nodoc:
140
141
  post[:firstname] = payment_method.first_name
141
142
  post[:lastname] = payment_method.last_name
142
143
  post[:ccnumber] = payment_method.number
143
- post[:cvv] = payment_method.verification_value
144
+ post[:cvv] = payment_method.verification_value unless empty?(payment_method.verification_value)
144
145
  post[:ccexp] = exp_date(payment_method)
145
146
  end
146
147
  end
@@ -206,6 +206,13 @@ module ActiveMerchant #:nodoc:
206
206
  perform_reference_credit(money, reference, options)
207
207
  end
208
208
 
209
+ def verify(credit_card, options={})
210
+ MultiResponse.run(:use_first_response) do |r|
211
+ r.process { authorize(100, credit_card, options) }
212
+ r.process(:ignore_result) { void(r.authorization, options) }
213
+ end
214
+ end
215
+
209
216
  # Store a credit card by creating an Ogone Alias
210
217
  def store(payment_source, options = {})
211
218
  options.merge!(:alias_operation => 'BYPSP') unless(options.has_key?(:billing_id) || options.has_key?(:store))
@@ -423,8 +430,9 @@ module ActiveMerchant #:nodoc:
423
430
  raise "Unknown signature algorithm #{algorithm}"
424
431
  end
425
432
 
433
+ filtered_params = signed_parameters.select{|k,v| !v.blank?}
426
434
  sha_encryptor.hexdigest(
427
- signed_parameters.sort_by{|k,v| k.upcase}.map{|k, v| "#{k.upcase}=#{v}#{secret}"}.join("")
435
+ filtered_params.sort_by{|k,v| k.upcase}.map{|k, v| "#{k.upcase}=#{v}#{secret}"}.join("")
428
436
  ).upcase
429
437
  end
430
438
 
@@ -91,7 +91,10 @@ module ActiveMerchant #:nodoc:
91
91
  transcript.
92
92
  gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
93
93
  gsub(%r((card_number\\?":\\?")[^"\\]*)i, '\1[FILTERED]').
94
- gsub(%r((cvv2\\?":\\?")[^"\\]*)i, '\1[FILTERED]')
94
+ gsub(%r((cvv2\\?":\\?")\d+[^"\\]*)i, '\1[FILTERED]').
95
+ gsub(%r((cvv2\\?":)null), '\1[BLANK]').
96
+ gsub(%r((cvv2\\?":\\?")\\?"), '\1[BLANK]"').
97
+ gsub(%r((cvv2\\?":\\?")\s+), '\1[BLANK]')
95
98
  end
96
99
  private
97
100
 
@@ -25,14 +25,14 @@ module ActiveMerchant #:nodoc:
25
25
  'cvv2_not_checked' => 'X'
26
26
  }
27
27
 
28
- self.test_url = 'https://raven.deepcovelabs.com/realtime/'
29
- self.live_url = 'https://raven.deepcovelabs.com/realtime/'
28
+ self.live_url = 'https://raven.deepcovelabs.net/realtime/'
29
+ self.test_url = self.live_url
30
30
 
31
31
  self.supported_countries = ['US']
32
32
  self.supported_cardtypes = [:visa, :master]
33
33
  self.money_format = :cents
34
34
  self.default_currency = 'USD'
35
- self.homepage_url = 'http://www.deepcovelabs.com/raven'
35
+ self.homepage_url = 'https://www.deepcovelabs.com/raven'
36
36
  self.display_name = 'Raven'
37
37
 
38
38
  def initialize(options = {})
@@ -67,6 +67,8 @@ module ActiveMerchant #:nodoc:
67
67
  post = {}
68
68
  add_invoice(post, options)
69
69
  add_creditcard(post, creditcard)
70
+ add_amount(post, money, options)
71
+
70
72
  commit('authorization', money, post)
71
73
  end
72
74
 
@@ -74,6 +76,8 @@ module ActiveMerchant #:nodoc:
74
76
  post = {}
75
77
  add_invoice(post, options)
76
78
  add_creditcard(post, creditcard)
79
+ add_amount(post, money, options)
80
+
77
81
  commit('purchase', money, post)
78
82
  end
79
83
 
@@ -81,8 +85,10 @@ module ActiveMerchant #:nodoc:
81
85
  requires!(options, :order_id)
82
86
  post = {}
83
87
  add_invoice(post, options)
88
+ add_amount(post, money, options)
84
89
  post[:numappel] = authorization[0,10]
85
90
  post[:numtrans] = authorization[10,10]
91
+
86
92
  commit('capture', money, post)
87
93
  end
88
94
 
@@ -91,8 +97,10 @@ module ActiveMerchant #:nodoc:
91
97
  post ={}
92
98
  add_invoice(post, options)
93
99
  add_reference(post, identification)
100
+ add_amount(post, options[:amount], options)
94
101
  post[:porteur] = '000000000000000'
95
102
  post[:dateval] = '0000'
103
+
96
104
  commit('void', options[:amount], post)
97
105
  end
98
106
 
@@ -125,6 +133,11 @@ module ActiveMerchant #:nodoc:
125
133
  post[:numtrans] = identification[10,10]
126
134
  end
127
135
 
136
+ def add_amount(post, money, options)
137
+ post[:montant] = ('0000000000' + (money ? amount(money) : ''))[-10..-1]
138
+ post[:devise] = CURRENCY_CODES[options[:currency] || currency(money)]
139
+ end
140
+
128
141
  def parse(body)
129
142
  results = {}
130
143
  body.split(/&/).each do |pair|
@@ -135,8 +148,6 @@ module ActiveMerchant #:nodoc:
135
148
  end
136
149
 
137
150
  def commit(action, money = nil, parameters = nil)
138
- parameters[:montant] = ('0000000000' + (money ? amount(money) : ''))[-10..-1]
139
- parameters[:devise] = CURRENCY_CODES[options[:currency] || currency(money)]
140
151
  request_data = post_data(action,parameters)
141
152
  response = parse(ssl_post(test? ? self.test_url : self.live_url, request_data))
142
153
  response = parse(ssl_post(self.live_url_backup, request_data)) if service_unavailable?(response) && !test?
@@ -47,7 +47,7 @@ module ActiveMerchant #:nodoc:
47
47
  gsub(%r((<n1:Password>).+(</n1:Password>)), '\1[FILTERED]\2').
48
48
  gsub(%r((<n1:Username>).+(</n1:Username>)), '\1[FILTERED]\2').
49
49
  gsub(%r((<n2:CreditCardNumber>).+(</n2:CreditCardNumber)), '\1[FILTERED]\2').
50
- gsub(%r((<n2:CVV2>).+(</n2:CVV2)), '\1[FILTERED]\2')
50
+ gsub(%r((<n2:CVV2>)\d+(</n2:CVV2)), '\1[FILTERED]\2')
51
51
  end
52
52
 
53
53
  private
@@ -91,7 +91,7 @@ module ActiveMerchant #:nodoc:
91
91
  xml.tag! 'n2:CreditCardNumber', credit_card.number
92
92
  xml.tag! 'n2:ExpMonth', format(credit_card.month, :two_digits)
93
93
  xml.tag! 'n2:ExpYear', format(credit_card.year, :four_digits)
94
- xml.tag! 'n2:CVV2', credit_card.verification_value
94
+ xml.tag! 'n2:CVV2', credit_card.verification_value unless credit_card.verification_value.blank?
95
95
 
96
96
  if [ 'switch', 'solo' ].include?(card_brand(credit_card).to_s)
97
97
  xml.tag! 'n2:StartMonth', format(credit_card.start_month, :two_digits) unless credit_card.start_month.blank?
@@ -40,6 +40,20 @@ module ActiveMerchant #:nodoc:
40
40
 
41
41
  FRAUD_REVIEW_CODE = "11610"
42
42
 
43
+ STANDARD_ERROR_CODE_MAPPING = {
44
+ '15005' => :card_declined,
45
+ '10754' => :card_declined,
46
+ '10752' => :card_declined,
47
+ '10759' => :card_declined,
48
+ '10761' => :card_declined,
49
+ '15002' => :card_declined,
50
+ '11084' => :card_declined,
51
+ '15004' => :incorrect_cvc,
52
+ '10762' => :invalid_cvc,
53
+ }
54
+
55
+ STANDARD_ERROR_CODE_MAPPING.default = :processing_error
56
+
43
57
  def self.included(base)
44
58
  base.default_currency = 'USD'
45
59
  base.cattr_accessor :pem_file
@@ -637,11 +651,21 @@ module ActiveMerchant #:nodoc:
637
651
  :test => test?,
638
652
  :authorization => authorization_from(response),
639
653
  :fraud_review => fraud_review?(response),
654
+ :error_code => standardized_error_code(response),
640
655
  :avs_result => { :code => response[:avs_code] },
641
656
  :cvv_result => response[:cvv2_code]
642
657
  )
643
658
  end
644
659
 
660
+ def standardized_error_code(response)
661
+ STANDARD_ERROR_CODE_MAPPING[error_codes(response).first]
662
+ end
663
+
664
+ def error_codes(response)
665
+ return [] unless response.has_key?(:error_codes)
666
+ response[:error_codes].split(',')
667
+ end
668
+
645
669
  def fraud_review?(response)
646
670
  response[:error_codes] == FRAUD_REVIEW_CODE
647
671
  end
@@ -11,11 +11,11 @@ module ActiveMerchant
11
11
  end
12
12
  base.live_redirect_url = 'https://www.paypal.com/cgi-bin/webscr'
13
13
  end
14
-
14
+
15
15
  def redirect_url
16
16
  test? ? test_redirect_url : live_redirect_url
17
17
  end
18
-
18
+
19
19
  def redirect_url_for(token, options = {})
20
20
  options = {:review => true, :mobile => false}.update(options)
21
21
 
@@ -14,26 +14,26 @@ module ActiveMerchant
14
14
  super
15
15
  end
16
16
 
17
- def purchase(money, credit_card, options = {})
17
+ def purchase(money, credit_card_or_reference, options = {})
18
18
  MultiResponse.run(true) do |r|
19
19
  r.process { create_payment(money, options) }
20
20
  r.process {
21
- post = authorization_params(money, credit_card, options)
21
+ post = authorization_params(money, credit_card_or_reference, options)
22
22
  add_autocapture(post, false)
23
23
  commit(synchronized_path("/payments/#{r.authorization}/authorize"), post)
24
24
  }
25
25
  r.process {
26
- post = capture_params(money, credit_card, options)
26
+ post = capture_params(money, credit_card_or_reference, options)
27
27
  commit(synchronized_path("/payments/#{r.authorization}/capture"), post)
28
28
  }
29
29
  end
30
30
  end
31
31
 
32
- def authorize(money, credit_card, options = {})
32
+ def authorize(money, credit_card_or_reference, options = {})
33
33
  MultiResponse.run(true) do |r|
34
34
  r.process { create_payment(money, options) }
35
35
  r.process {
36
- post = authorization_params(money, credit_card, options)
36
+ post = authorization_params(money, credit_card_or_reference, options)
37
37
  commit(synchronized_path("/payments/#{r.authorization}/authorize"), post)
38
38
  }
39
39
  end
@@ -68,16 +68,16 @@ module ActiveMerchant
68
68
  end
69
69
 
70
70
  def store(credit_card, options = {})
71
- MultiResponse.run(true) do |r|
72
- r.process { create_subscription(options) }
73
- r.process {
74
- authorize_subscription(r.authorization, credit_card, options)
75
- }
71
+ MultiResponse.run do |r|
72
+ r.process { create_store(options) }
73
+ r.process { authorize_store(r.authorization, credit_card, options)}
74
+ r.process { create_token(r.authorization, options.merge({id: r.authorization}))}
76
75
  end
77
76
  end
78
77
 
79
78
  def unstore(identification)
80
- commit(synchronized_path "/subscriptions/#{identification}/cancel")
79
+ identification = identification.split(";").last
80
+ commit(synchronized_path "/cards/#{identification}/cancel")
81
81
  end
82
82
 
83
83
  def supports_scrubbing?
@@ -97,7 +97,7 @@ module ActiveMerchant
97
97
  post = {}
98
98
 
99
99
  add_amount(post, money, options)
100
- add_credit_card(post, credit_card)
100
+ add_credit_card_or_reference(post, credit_card)
101
101
  add_additional_params(:authorize, post, options)
102
102
 
103
103
  post
@@ -112,23 +112,24 @@ module ActiveMerchant
112
112
  post
113
113
  end
114
114
 
115
- def create_subscription(options = {})
116
- requires!(options, :currency)
115
+ def create_store(options = {})
117
116
  post = {}
118
-
119
- add_currency(post, nil, options)
120
- add_subscription_invoice(post, options)
121
- commit('/subscriptions', post)
117
+ commit('/cards', post)
122
118
  end
123
119
 
124
- def authorize_subscription(identification, credit_card, options = {})
120
+ def authorize_store(identification, credit_card, options = {})
125
121
  requires!(options, :amount)
126
122
  post = {}
127
123
 
128
124
  add_amount(post, nil, options)
129
- add_credit_card(post, credit_card, options)
130
- add_additional_params(:authorize_subscription, post, options)
131
- commit(synchronized_path("/subscriptions/#{identification}/authorize"), post)
125
+ add_credit_card_or_reference(post, credit_card, options)
126
+ commit(synchronized_path("/cards/#{identification}/authorize"), post)
127
+ end
128
+
129
+ def create_token(identification, options)
130
+ post = {}
131
+ post[:id] = options[:id]
132
+ commit(synchronized_path("/cards/#{identification}/tokens"), post)
132
133
  end
133
134
 
134
135
  def create_payment(money, options = {})
@@ -151,14 +152,16 @@ module ActiveMerchant
151
152
 
152
153
  Response.new(success, message_from(success, response), response,
153
154
  :test => test?,
154
- :authorization => response['id']
155
+ :authorization => authorization_from(response, params[:id])
155
156
  )
156
157
  end
157
158
 
158
- def add_subscription_invoice(post, options = {})
159
- requires!(options, :order_id, :description)
160
- post[:order_id] = options[:order_id]
161
- post[:description] = options[:description]
159
+ def authorization_from(response, auth_id)
160
+ if response["token"]
161
+ "#{response["token"]};#{auth_id}"
162
+ else
163
+ response["id"]
164
+ end
162
165
  end
163
166
 
164
167
  def add_currency(post, money, options)
@@ -201,12 +204,17 @@ module ActiveMerchant
201
204
  end
202
205
  end
203
206
 
204
- def add_credit_card(post, credit_card, options = {})
207
+ def add_credit_card_or_reference(post, credit_card_or_reference, options = {})
205
208
  post[:card] ||= {}
206
- post[:card][:number] = credit_card.number
207
- post[:card][:cvd] = credit_card.verification_value
208
- post[:card][:expiration] = expdate(credit_card)
209
- post[:card][:issued_to] = credit_card.name
209
+ if credit_card_or_reference.is_a?(String)
210
+ reference = credit_card_or_reference.split(";").first
211
+ post[:card][:token] = reference
212
+ else
213
+ post[:card][:number] = credit_card_or_reference.number
214
+ post[:card][:cvd] = credit_card_or_reference.verification_value
215
+ post[:card][:expiration] = expdate(credit_card_or_reference)
216
+ post[:card][:issued_to] = credit_card_or_reference.name
217
+ end
210
218
  end
211
219
 
212
220
  def parse(body)
@@ -245,7 +245,12 @@ module ActiveMerchant #:nodoc:
245
245
  gsub(%r((%3CDS_MERCHANT_PAN%3E)\d+(%3C%2FDS_MERCHANT_PAN%3E))i, '\1[FILTERED]\2').
246
246
  gsub(%r((%3CDS_MERCHANT_CVV2%3E)\d+(%3C%2FDS_MERCHANT_CVV2%3E))i, '\1[FILTERED]\2').
247
247
  gsub(%r((<DS_MERCHANT_PAN>)\d+(</DS_MERCHANT_PAN>))i, '\1[FILTERED]\2').
248
- gsub(%r((<DS_MERCHANT_CVV2>)\d+(</DS_MERCHANT_CVV2>))i, '\1[FILTERED]\2')
248
+ gsub(%r((<DS_MERCHANT_CVV2>)\d+(</DS_MERCHANT_CVV2>))i, '\1[FILTERED]\2').
249
+ gsub(%r((DS_MERCHANT_CVV2)%2F%3E%0A%3C%2F)i, '\1[BLANK]').
250
+ gsub(%r((DS_MERCHANT_CVV2%3E)(%3C%2FDS_MERCHANT_CVV2))i, '\1[BLANK]\2').
251
+ gsub(%r((<DS_MERCHANT_CVV2>)(</DS_MERCHANT_CVV2>))i, '\1[BLANK]\2').
252
+ gsub(%r((DS_MERCHANT_CVV2%3E)\++(%3C%2FDS_MERCHANT_CVV2))i, '\1[BLANK]\2').
253
+ gsub(%r((<DS_MERCHANT_CVV2>)\s+(</DS_MERCHANT_CVV2>))i, '\1[BLANK]\2')
249
254
  end
250
255
 
251
256
  private
@@ -254,6 +254,7 @@ module ActiveMerchant #:nodoc:
254
254
  add_metadata(post, options)
255
255
  post[:description] = options[:description]
256
256
  post[:statement_descriptor] = options[:statement_description]
257
+ post[:receipt_email] = options[:receipt_email] if options[:receipt_email]
257
258
  add_customer(post, payment, options)
258
259
  add_flags(post, options)
259
260
  end
@@ -132,6 +132,7 @@ module ActiveMerchant
132
132
  add_client_id(doc)
133
133
  add_amount(doc, money, options)
134
134
  add_payment_method(doc, payment_method, options)
135
+ add_options(doc, options)
135
136
  add_purchase_noise(doc)
136
137
  end
137
138
  end
@@ -238,6 +239,10 @@ module ActiveMerchant
238
239
  doc.ReasonForCredit("Refund requested")
239
240
  end
240
241
 
242
+ def add_options(doc, options)
243
+ doc.CustomerIPAddress(options[:ip]) if options[:ip]
244
+ end
245
+
241
246
  def add_client_id(doc)
242
247
  doc.ClientID(@options[:client_id])
243
248
  end
@@ -31,7 +31,7 @@ module ActiveMerchant #:nodoc:
31
31
  def authorize(money, payment, options={})
32
32
  post = {}
33
33
  add_invoice(post, money, options)
34
- add_payment_method(post, payment)
34
+ add_credit_card(post, payment)
35
35
  add_customer_data(post, options)
36
36
 
37
37
  commit('authorize', post)
@@ -103,6 +103,14 @@ module ActiveMerchant #:nodoc:
103
103
  end
104
104
 
105
105
  def add_payment_method(post, payment_method)
106
+ if card_brand(payment_method) == 'check'
107
+ add_check(post, payment_method)
108
+ else
109
+ add_credit_card(post, payment_method)
110
+ end
111
+ end
112
+
113
+ def add_credit_card(post, payment_method)
106
114
  post[:ccname] = payment_method.name
107
115
  post[:ccnum] = payment_method.number
108
116
  post[:cvv2] = payment_method.verification_value
@@ -110,6 +118,19 @@ module ActiveMerchant #:nodoc:
110
118
  post[:expmon] = format(payment_method.month, :two_digits)
111
119
  end
112
120
 
121
+ ACCOUNT_TYPES = {
122
+ "checking" => "1",
123
+ "savings" => "2",
124
+ }
125
+
126
+ def add_check(post, payment_method)
127
+ post[:action] = 'ns_quicksale_check'
128
+ post[:ckacct] = payment_method.account_number
129
+ post[:ckaba] = payment_method.routing_number
130
+ post[:ckno] = payment_method.number
131
+ post[:ckaccttype] = ACCOUNT_TYPES[payment_method.account_type] if ACCOUNT_TYPES[payment_method.account_type]
132
+ end
133
+
113
134
  def split_authorization(authorization)
114
135
  historyid, orderid = authorization.split("|")
115
136
  [historyid, orderid]
@@ -142,7 +163,7 @@ module ActiveMerchant #:nodoc:
142
163
  }
143
164
 
144
165
  def commit(action, post)
145
- post[:action] = ACTIONS[action] if ACTIONS[action]
166
+ post[:action] = ACTIONS[action] unless post[:action]
146
167
  post[:acctid] = @options[:acctid]
147
168
  post[:subid] = @options[:subid]
148
169
  post[:merchantpin] = @options[:merchantpin]
@@ -151,7 +172,7 @@ module ActiveMerchant #:nodoc:
151
172
 
152
173
  raw = parse(ssl_post(live_url, post.to_query))
153
174
 
154
- succeeded = success_from(raw['transresult'])
175
+ succeeded = success_from(raw['result'])
155
176
  Response.new(
156
177
  succeeded,
157
178
  message_from(succeeded, raw),
@@ -162,7 +183,7 @@ module ActiveMerchant #:nodoc:
162
183
  end
163
184
 
164
185
  def success_from(result)
165
- result == 'APPROVED'
186
+ result == '1'
166
187
  end
167
188
 
168
189
  def message_from(succeeded, response)
@@ -1,3 +1,3 @@
1
1
  module ActiveMerchant
2
- VERSION = "1.53.0"
2
+ VERSION = "1.54.0"
3
3
  end
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.53.0
4
+ version: 1.54.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: 2015-09-01 00:00:00.000000000 Z
11
+ date: 2015-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport