activemerchant 1.50.0 → 1.51.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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +39 -0
  3. data/README.md +6 -5
  4. data/lib/active_merchant/billing/credit_card.rb +22 -6
  5. data/lib/active_merchant/billing/gateway.rb +15 -1
  6. data/lib/active_merchant/billing/gateways/authorize_net.rb +413 -127
  7. data/lib/active_merchant/billing/gateways/banwire.rb +2 -2
  8. data/lib/active_merchant/billing/gateways/braintree_blue.rb +4 -0
  9. data/lib/active_merchant/billing/gateways/card_stream.rb +18 -0
  10. data/lib/active_merchant/billing/gateways/cenpos.rb +6 -2
  11. data/lib/active_merchant/billing/gateways/checkout.rb +4 -6
  12. data/lib/active_merchant/billing/gateways/checkout_v2.rb +200 -0
  13. data/lib/active_merchant/billing/gateways/cyber_source.rb +19 -1
  14. data/lib/active_merchant/billing/gateways/dibs.rb +1 -1
  15. data/lib/active_merchant/billing/gateways/epay.rb +1 -1
  16. data/lib/active_merchant/billing/gateways/eway_rapid.rb +5 -5
  17. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +4 -1
  18. data/lib/active_merchant/billing/gateways/garanti.rb +5 -1
  19. data/lib/active_merchant/billing/gateways/iats_payments.rb +29 -3
  20. data/lib/active_merchant/billing/gateways/litle.rb +12 -0
  21. data/lib/active_merchant/billing/gateways/paystation.rb +19 -23
  22. data/lib/active_merchant/billing/gateways/payu_in.rb +4 -0
  23. data/lib/active_merchant/billing/gateways/redsys.rb +4 -3
  24. data/lib/active_merchant/billing/gateways/s5.rb +3 -3
  25. data/lib/active_merchant/billing/gateways/sage.rb +8 -10
  26. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +7 -5
  27. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +3 -2
  28. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +0 -5
  29. data/lib/active_merchant/billing/gateways/stripe.rb +33 -4
  30. data/lib/active_merchant/billing/gateways/wepay.rb +13 -6
  31. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +1 -2
  32. data/lib/active_merchant/version.rb +1 -1
  33. metadata +3 -2
@@ -109,6 +109,7 @@ module ActiveMerchant #:nodoc:
109
109
  doc.registerTokenRequest(transaction_attributes(options)) do
110
110
  doc.orderId(truncate(options[:order_id], 24))
111
111
  doc.accountNumber(creditcard.number)
112
+ doc.cardValidationNum(creditcard.verification_value) if creditcard.verification_value
112
113
  end
113
114
  end
114
115
 
@@ -163,6 +164,7 @@ module ActiveMerchant #:nodoc:
163
164
  add_payment_method(doc, payment_method)
164
165
  add_pos(doc, payment_method)
165
166
  add_descriptor(doc, options)
167
+ add_debt_repayment(doc, options)
166
168
  end
167
169
 
168
170
  def add_descriptor(doc, options)
@@ -174,6 +176,10 @@ module ActiveMerchant #:nodoc:
174
176
  end
175
177
  end
176
178
 
179
+ def add_debt_repayment(doc, options)
180
+ doc.debtRepayment(true) if options[:debt_repayment] == true
181
+ end
182
+
177
183
  def add_payment_method(doc, payment_method)
178
184
  if payment_method.is_a?(String)
179
185
  doc.token do
@@ -264,6 +270,12 @@ module ActiveMerchant #:nodoc:
264
270
  end
265
271
  end
266
272
 
273
+ if parsed.empty?
274
+ %w(response message).each do |attribute|
275
+ parsed[attribute.to_sym] = doc.xpath("//litleOnlineResponse").attribute(attribute).value
276
+ end
277
+ end
278
+
267
279
  parsed
268
280
  end
269
281
 
@@ -32,9 +32,7 @@ module ActiveMerchant #:nodoc:
32
32
 
33
33
  add_invoice(post, options)
34
34
  add_amount(post, money, options)
35
-
36
35
  add_credit_card(post, credit_card)
37
-
38
36
  add_authorize_flag(post, options)
39
37
 
40
38
  commit(post)
@@ -45,7 +43,6 @@ module ActiveMerchant #:nodoc:
45
43
 
46
44
  add_invoice(post, options)
47
45
  add_amount(post, money, options)
48
-
49
46
  add_authorization_token(post, authorization_token, options[:credit_card_verification])
50
47
 
51
48
  commit(post)
@@ -78,6 +75,16 @@ module ActiveMerchant #:nodoc:
78
75
  commit(post)
79
76
  end
80
77
 
78
+
79
+ def refund(money, authorization, options={})
80
+ post = new_request
81
+ add_amount(post, money, options)
82
+ add_invoice(post, options)
83
+ add_refund_specific_fields(post, authorization)
84
+
85
+ commit(post)
86
+ end
87
+
81
88
  private
82
89
 
83
90
  def new_request
@@ -95,40 +102,38 @@ module ActiveMerchant #:nodoc:
95
102
  end
96
103
 
97
104
  def add_invoice(post, options)
98
- requires!(options, :order_id)
99
-
100
- post[:ms] = options[:order_id] # "Merchant Session", must be unique per request
101
- post[:mo] = options[:invoice] # "Order Details", displayed in Paystation Admin
102
- post[:mr] = options[:description] # "Merchant Reference Code", seen from Paystation Admin
105
+ post[:ms] = options[:order_id] || generate_unique_id
106
+ post[:mo] = options[:invoice]
107
+ post[:mr] = options[:description]
103
108
  end
104
109
 
105
110
  def add_credit_card(post, credit_card)
106
-
107
111
  post[:cn] = credit_card.number
108
112
  post[:ct] = credit_card.brand
109
113
  post[:ex] = format_date(credit_card.month, credit_card.year)
110
114
  post[:cc] = credit_card.verification_value if credit_card.verification_value?
111
-
112
115
  end
113
116
 
114
- # bill a token (stored via "store") rather than a Credit Card
115
117
  def add_token(post, token)
116
118
  post[:fp] = "t" # turn on "future payments" - what paystation calls Token Billing
117
119
  post[:ft] = token
118
120
  end
119
121
 
120
122
  def store_credit_card(post, options)
121
-
122
123
  post[:fp] = "t" # turn on "future payments" - what paystation calls Token Billing
123
124
  post[:fs] = "t" # tells paystation to store right now, not bill
124
125
  post[:ft] = options[:token] if options[:token] # specify a token to use that, or let Paystation generate one
125
-
126
126
  end
127
127
 
128
128
  def add_authorize_flag(post, options)
129
129
  post[:pa] = "t" # tells Paystation that this is a pre-auth authorisation payment (account must be in pre-auth mode)
130
130
  end
131
131
 
132
+ def add_refund_specific_fields(post, authorization)
133
+ post[:rc] = "t"
134
+ post[:rt] = authorization
135
+ end
136
+
132
137
  def add_authorization_token(post, auth_token, verification_value = nil)
133
138
  post[:cp] = "t" # Capture Payment flag – tells Paystation this transaction should be treated as a capture payment
134
139
  post[:cx] = auth_token
@@ -136,10 +141,8 @@ module ActiveMerchant #:nodoc:
136
141
  end
137
142
 
138
143
  def add_amount(post, money, options)
139
-
140
144
  post[:am] = amount(money)
141
145
  post[:cu] = options[:currency] || currency(money)
142
-
143
146
  end
144
147
 
145
148
  def parse(xml_response)
@@ -147,8 +150,6 @@ module ActiveMerchant #:nodoc:
147
150
 
148
151
  xml = REXML::Document.new(xml_response)
149
152
 
150
- # for normal payments, the root node is <Response>
151
- # for "future payments", it's <PaystationFuturePaymentResponse>
152
153
  xml.elements.each("#{xml.root.name}/*") do |element|
153
154
  response[element.name.underscore.to_sym] = element.text
154
155
  end
@@ -157,12 +158,9 @@ module ActiveMerchant #:nodoc:
157
158
  end
158
159
 
159
160
  def commit(post)
160
-
161
- post[:tm] = "T" if test? # test mode
162
-
161
+ post[:tm] = "T" if test?
163
162
  pstn_prefix_params = post.collect { |key, value| "pstn_#{key}=#{CGI.escape(value.to_s)}" }.join("&")
164
163
 
165
- # need include paystation param as "initiator flag for payment engine"
166
164
  data = ssl_post(self.live_url, "#{pstn_prefix_params}&paystation=_empty")
167
165
  response = parse(data)
168
166
  message = message_from(response)
@@ -188,8 +186,6 @@ module ActiveMerchant #:nodoc:
188
186
  end
189
187
 
190
188
  class PaystationResponse < Response
191
- # add a method to response so we can easily get the token
192
- # for Validate transactions
193
189
  def token
194
190
  @params["future_payment_token"]
195
191
  end
@@ -192,6 +192,10 @@ module ActiveMerchant #:nodoc:
192
192
  end
193
193
 
194
194
  top
195
+ rescue JSON::ParserError
196
+ {
197
+ "error" => "Invalid response received from the PayU API. (The raw response was `#{body}`)."
198
+ }
195
199
  end
196
200
 
197
201
  def commit(url, parameters)
@@ -38,10 +38,10 @@ module ActiveMerchant #:nodoc:
38
38
  self.display_name = "Redsys"
39
39
 
40
40
  CURRENCY_CODES = {
41
- "ARS" => '032',
42
- "AUD" => '036',
41
+ "ARS" => '32',
42
+ "AUD" => '36',
43
43
  "BRL" => '986',
44
- "BOB" => '068',
44
+ "BOB" => '68',
45
45
  "CAD" => '124',
46
46
  "CHF" => '756',
47
47
  "CLP" => '152',
@@ -50,6 +50,7 @@ module ActiveMerchant #:nodoc:
50
50
  "GBP" => '826',
51
51
  "GTQ" => '320',
52
52
  "JPY" => '392',
53
+ "MYR" => '458',
53
54
  "MXN" => '484',
54
55
  "NZD" => '554',
55
56
  "PEN" => '604',
@@ -88,9 +88,9 @@ module ActiveMerchant #:nodoc:
88
88
 
89
89
  def scrub(transcript)
90
90
  transcript.
91
- gsub(%r((pwd=).+(/>))i, '\1[FILTERED]\2').
92
- gsub(%r((<Number>).+(</Number>))i, '\1[FILTERED]\2').
93
- gsub(%r((<Verification>).+(</Verification>))i, '\1[FILTERED]\2')
91
+ gsub(%r((pwd=).+?(/>))i, '\1[FILTERED]\2').
92
+ gsub(%r((<Number>).+?(</Number>))i, '\1[FILTERED]\2').
93
+ gsub(%r((<Verification>).+?(</Verification>))i, '\1[FILTERED]\2')
94
94
  end
95
95
 
96
96
  private
@@ -120,25 +120,23 @@ module ActiveMerchant #:nodoc:
120
120
  end
121
121
  end
122
122
 
123
- def credit(money, source, options = {})
124
- ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
125
- refund(money, source, options)
126
- end
127
-
128
- # Performs a refund transaction.
129
123
  #
130
124
  # ==== Parameters
131
125
  #
132
126
  # * <tt>money</tt> - The amount to be authorized as an integer value in cents.
133
- # * <tt>source</tt> - The CreditCard or Check object to be used as the target for the refund.
134
- def refund(money, source, options = {})
127
+ # * <tt>source</tt> - The CreditCard or Check object to be used as the target for the credit.
128
+ def credit(money, source, options = {})
135
129
  if card_brand(source) == "check"
136
- virtual_check.refund(money, source, options)
130
+ virtual_check.credit(money, source, options)
137
131
  else
138
- bankcard.refund(money, source, options)
132
+ bankcard.credit(money, source, options)
139
133
  end
140
134
  end
141
135
 
136
+ def refund(money, reference, options={})
137
+ bankcard.refund(money, reference, options)
138
+ end
139
+
142
140
  # Stores a credit card in the Sage vault.
143
141
  #
144
142
  # ==== Parameters
@@ -47,17 +47,19 @@ module ActiveMerchant #:nodoc:
47
47
  end
48
48
 
49
49
  def credit(money, credit_card, options = {})
50
- ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
51
- refund(money, credit_card, options)
52
- end
53
-
54
- def refund(money, credit_card, options = {})
55
50
  post = {}
56
51
  add_credit_card(post, credit_card)
57
52
  add_transaction_data(post, money, options)
58
53
  commit(:credit, post)
59
54
  end
60
55
 
56
+ def refund(money, reference, options={})
57
+ post = {}
58
+ add_reference(post, reference)
59
+ add_transaction_data(post, money, options)
60
+ commit(:refund, post)
61
+ end
62
+
61
63
  private
62
64
 
63
65
  def add_credit_card(post, credit_card)
@@ -20,7 +20,8 @@ module ActiveMerchant #:nodoc:
20
20
  :authorization => '02',
21
21
  :capture => '11',
22
22
  :void => '04',
23
- :credit => '06'
23
+ :credit => '06',
24
+ :refund => '10'
24
25
  }
25
26
 
26
27
  def initialize(options = {})
@@ -30,7 +31,7 @@ module ActiveMerchant #:nodoc:
30
31
 
31
32
  private
32
33
  def add_invoice(post, options)
33
- post[:T_ordernum] = options[:order_id].slice(0, 20)
34
+ post[:T_ordernum] = (options[:order_id] || generate_unique_id).slice(0, 20)
34
35
  post[:T_tax] = amount(options[:tax]) unless options[:tax].blank?
35
36
  post[:T_shipping] = amount(options[:shipping]) unless options[:shipping].blank?
36
37
  end
@@ -22,11 +22,6 @@ module ActiveMerchant #:nodoc:
22
22
  end
23
23
 
24
24
  def credit(money, credit_card, options = {})
25
- ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
26
- refund(money, source, options)
27
- end
28
-
29
- def refund(money, credit_card, options = {})
30
25
  post = {}
31
26
  add_check(post, credit_card)
32
27
  add_check_customer_data(post, options)
@@ -42,6 +42,7 @@ module ActiveMerchant #:nodoc:
42
42
  'incorrect_cvc' => STANDARD_ERROR_CODE[:incorrect_cvc],
43
43
  'incorrect_zip' => STANDARD_ERROR_CODE[:incorrect_zip],
44
44
  'card_declined' => STANDARD_ERROR_CODE[:card_declined],
45
+ 'call_issuer' => STANDARD_ERROR_CODE[:call_issuer],
45
46
  'processing_error' => STANDARD_ERROR_CODE[:processing_error]
46
47
  }
47
48
 
@@ -123,7 +124,7 @@ module ActiveMerchant #:nodoc:
123
124
 
124
125
  def verify(payment, options = {})
125
126
  MultiResponse.run(:use_first_response) do |r|
126
- r.process { authorize(50, payment, options.merge(currency: "USD")) }
127
+ r.process { authorize(50, payment, options) }
127
128
  r.process(:ignore_result) { void(r.authorization, options) }
128
129
  end
129
130
  end
@@ -222,6 +223,10 @@ module ActiveMerchant #:nodoc:
222
223
  gsub(%r((&?three_d_secure\[cryptogram\]=)[\w=]*(&?)), '\1[FILTERED]\2')
223
224
  end
224
225
 
226
+ def supports_network_tokenization?
227
+ true
228
+ end
229
+
225
230
  private
226
231
 
227
232
  class StripePaymentToken < PaymentToken
@@ -295,6 +300,11 @@ module ActiveMerchant #:nodoc:
295
300
  card = {}
296
301
  if emv_payment?(creditcard)
297
302
  add_emv_creditcard(post, creditcard.icc_data)
303
+ post[:card][:read_method] = "contactless" if creditcard.contactless
304
+ if creditcard.encrypted_pin_cryptogram.present? && creditcard.encrypted_pin_ksn.present?
305
+ post[:card][:encrypted_pin] = creditcard.encrypted_pin_cryptogram
306
+ post[:card][:encrypted_pin_key_id] = creditcard.encrypted_pin_ksn
307
+ end
298
308
  elsif creditcard.respond_to?(:number)
299
309
  if creditcard.respond_to?(:track_data) && creditcard.track_data.present?
300
310
  card[:swipe_data] = creditcard.track_data
@@ -418,7 +428,7 @@ module ActiveMerchant #:nodoc:
418
428
 
419
429
  success = !response.key?("error")
420
430
 
421
- card = response["card"] || response["active_card"] || response["source"] || {}
431
+ card = card_from_response(response)
422
432
  avs_code = AVS_CODE_TRANSLATOR["line1: #{card["address_line1_check"]}, zip: #{card["address_zip_check"]}"]
423
433
  cvc_code = CVC_CODE_TRANSLATOR[card["cvc_check"]]
424
434
 
@@ -429,8 +439,8 @@ module ActiveMerchant #:nodoc:
429
439
  :authorization => success ? response["id"] : response["error"]["charge"],
430
440
  :avs_result => { :code => avs_code },
431
441
  :cvv_result => cvc_code,
432
- :emv_authorization => card["emv_auth_data"],
433
- :error_code => success ? nil : STANDARD_ERROR_CODE_MAPPING[response["error"]["code"]]
442
+ :emv_authorization => emv_authorization_from_response(response),
443
+ :error_code => success ? nil : error_code_from(response)
434
444
  )
435
445
  end
436
446
 
@@ -459,6 +469,25 @@ module ActiveMerchant #:nodoc:
459
469
  def emv_payment?(payment)
460
470
  payment.respond_to?(:emv?) && payment.emv?
461
471
  end
472
+
473
+ def card_from_response(response)
474
+ response["card"] || response["active_card"] || response["source"] || {}
475
+ end
476
+
477
+ def emv_authorization_from_response(response)
478
+ return response["error"]["emv_auth_data"] if response["error"]
479
+
480
+ card_from_response(response)["emv_auth_data"]
481
+ end
482
+
483
+ def error_code_from(response)
484
+ code = response['error']['code']
485
+ decline_code = response['error']['decline_code'] if code == 'card_declined'
486
+
487
+ error_code = STANDARD_ERROR_CODE_MAPPING[decline_code]
488
+ error_code ||= STANDARD_ERROR_CODE_MAPPING[code]
489
+ error_code
490
+ end
462
491
  end
463
492
  end
464
493
  end
@@ -73,27 +73,34 @@ module ActiveMerchant #:nodoc:
73
73
  post = {}
74
74
  post[:client_id] = @options[:client_id]
75
75
  post[:user_name] = "#{creditcard.first_name} #{creditcard.last_name}"
76
- post[:email] = options[:email]
76
+ post[:email] = options[:email] || "unspecified@example.com"
77
77
  post[:cc_number] = creditcard.number
78
- post[:cvv] = creditcard.verification_value
79
- post[:expiration_month] = creditcard.month
80
- post[:expiration_year] = creditcard.year
78
+ post[:cvv] = creditcard.verification_value unless options[:recurring]
79
+ post[:expiration_month] = "#{creditcard.month}"
80
+ post[:expiration_year] = "#{creditcard.year}"
81
81
  post[:original_ip] = options[:ip] if options[:ip]
82
82
  post[:original_device] = options[:device_fingerprint] if options[:device_fingerprint]
83
83
  if(billing_address = (options[:billing_address] || options[:address]))
84
84
  post[:address] = {
85
85
  "address1" => billing_address[:address1],
86
86
  "city" => billing_address[:city],
87
- "state" => billing_address[:state],
88
87
  "country" => billing_address[:country]
89
88
  }
90
89
  if(post[:country] == "US")
91
90
  post[:address]["zip"] = billing_address[:zip]
91
+ post[:address]["state"] = billing_address[:state]
92
92
  else
93
+ post[:address]["region"] = billing_address[:state]
93
94
  post[:address]["postcode"] = billing_address[:zip]
94
95
  end
95
96
  end
96
- commit('/credit_card/create', post)
97
+
98
+ if options[:recurring] == true
99
+ post[:client_secret] = @options[:client_secret]
100
+ commit('/credit_card/transfer', post)
101
+ else
102
+ commit('/credit_card/create', post)
103
+ end
97
104
  end
98
105
 
99
106
  private
@@ -22,7 +22,6 @@ module ActiveMerchant #:nodoc:
22
22
 
23
23
  def authorize(money, credit_card, options={})
24
24
  response = create_token(true, credit_card.first_name+' '+credit_card.last_name, credit_card.month, credit_card.year, credit_card.number, credit_card.verification_value)
25
-
26
25
  if response.success?
27
26
  options[:authorizeOnly] = true
28
27
  post = create_post_for_auth_or_purchase(response.authorization, money, options)
@@ -95,7 +94,7 @@ module ActiveMerchant #:nodoc:
95
94
  def create_post_for_auth_or_purchase(token, money, options)
96
95
  {
97
96
  "token" => token,
98
- "orderDescription" => options[:description],
97
+ "orderDescription" => options[:description] || 'Worldpay Order',
99
98
  "amount" => money,
100
99
  "currencyCode" => options[:currency] || default_currency,
101
100
  "name" => options[:billing_address]&&options[:billing_address][:name] ? options[:billing_address][:name] : '',
@@ -1,3 +1,3 @@
1
1
  module ActiveMerchant
2
- VERSION = "1.50.0"
2
+ VERSION = "1.51.0"
3
3
  end