activemerchant 1.53.0 → 1.54.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 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