activemerchant 1.48.0 → 1.49.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: 5ff9f55a9e47319466b22c9d9826ffb0d9c2d8a7
4
- data.tar.gz: cfe3110700b68bb12392232759ed730376435e3b
3
+ metadata.gz: 5057426f88d783e8a04528d24fb75c31011eca30
4
+ data.tar.gz: de26a0e5fff0c27aad8a96bd8b832e7cd1c53c1f
5
5
  SHA512:
6
- metadata.gz: 7bce2c57e79a9683a0c2d6557290efef7e2315b317158a4eb302b081d9c5e56f28a5a6102b30d39bfdbfd15acb88134094b0a11b6ea5e79b6d66a6cc1373e4d0
7
- data.tar.gz: 22b1046d34bdbd344a06a9b6bd3917216b738da94ce79ed64b586c5f9a1c0ac9314bf6650f57dc2dfd30a03e34c272d0e83180444612a617cb84bef81412e458
6
+ metadata.gz: 4d4df9ee441a742077ebc2109758b58ad76e76668d3e4a4169bf778e365fe300d9b8a1f977abc95df6e606fcd1d09491344453c79055771d7ba2ef4f44a1a52b
7
+ data.tar.gz: fdc30b7c943d11a2f7e505f2f978615b27cb4816360a7e5cde48598f8d3ff72ef58df2feb39a93d77984c0a6e44def9f11fd80ae590487e35dcd19482e99e406
checksums.yaml.gz.sig CHANGED
@@ -1,3 +1,2 @@
1
- ��j����&��h� t�4�N
2
- ����#�-�%���kFdn./B„���V���ھ"k=AU��N��(��8x�ݔ6"/KY��ۿ�
3
- |���+�$������
1
+ 8
2
+ ���� |��XRa|�� YsE���qͻ�h�~� �O�َ!y��5�=��%51�tB�M�Pl��h?{�?�� �h�l8�$�s��ݮ�.@�v�adX��U�(x��ރ/�7Q��bO8��)�9Oa5�?]�f�~|&��h�13��.�o��[�5h X�h���7T%�: ,w������z��2e=-�V�Yi��rJ
data.tar.gz.sig CHANGED
Binary file
data/CHANGELOG CHANGED
@@ -1,5 +1,28 @@
1
1
  = ActiveMerchant CHANGELOG
2
2
 
3
+ == Version 1.49.0 (May 1, 2015)
4
+
5
+ * Braintree: Add support for AVS error codes [ivanvfer]
6
+ * MerchantWarrior: Truncate description field [duff]
7
+ * Braintree: Add service_fee_amount option [duff]
8
+ * SecureNet: Allow shipping_address[:name] [duff]
9
+ * MonerisUS: Add verify [mrezentes]
10
+ * Ezic: Add gateway [duff]
11
+ * Stripe: Add destination field [cwise]
12
+ * SecureNet: Fix ordering of shipping field names [duff]
13
+ * SecurePayAu: Update API URL [girasquid]
14
+ * Stripe: Add EMV "chip & sign", "chip & offline PIN" and Maestro support [bizla]
15
+ * Add Errno::EHOSTUNREACH to NetworkConnectionRetries::DEFAULT_CONNECTION_ERRORS [randito78]
16
+ * Stripe: Add support for idempotency keys [michaelherold]
17
+ * WePay: Handle JSON::ParserError exceptions [duff]
18
+ * Borgun: Update country list and homepage url [mrezentes]
19
+ * AuthorizeNet: Add cvv to request only if it's valid [tjstankus]
20
+ * Stripe: Bug fix: add amounts only on non-EMV transactions, temporarily omit EMV testcases [bizla]
21
+ * Ezic: Add support for void [duff]
22
+ * iATS: Update supported countries [mrezentes]
23
+ * Ezic: Update supported countries [duff]
24
+ * AuthorizeNet: Truncate card number [tjstankus]
25
+
3
26
  == Version 1.48.0 (April 8, 2015)
4
27
 
5
28
  * Clean up `rake gateways:hosts` output [ntalbott]
data/README.md CHANGED
@@ -115,6 +115,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
115
115
  * [eWAY](http://www.eway.com.au/) - AU, NZ, GB
116
116
  * [eWAY Rapid](http://www.eway.com.au/) - AU, NZ, GB, SG
117
117
  * [E-xact](http://www.e-xact.com) - CA, US
118
+ * [Ezic](http://www.ezic.com/) - AU, CA, CN, FR, DE, GI, IL, MT, MU, MX, NL, NZ, PA, PH, RU, SG, KR, ES, KN, GB
118
119
  * [Fat Zebra](https://www.fatzebra.com.au/) - AU
119
120
  * [Federated Canada](http://www.federatedcanada.com/) - CA
120
121
  * [Finansbank WebPOS](https://www.fbwebpos.com/) - US, TR
@@ -138,6 +138,17 @@ module ActiveMerchant #:nodoc:
138
138
  # @return [String]
139
139
  attr_accessor :track_data
140
140
 
141
+ # Returns or sets the ICC/ASN1 credit card data for a EMV transaction, typically this is a BER-encoded TLV string.
142
+ #
143
+ # @return [String]
144
+ attr_accessor :icc_data
145
+
146
+ # Returns or sets a fallback reason for a EMV transaction whereby the customer's card entered a fallback scenario.
147
+ # This can be an arbitrary string.
148
+ #
149
+ # @return [String]
150
+ attr_accessor :fallback_reason
151
+
141
152
  def type
142
153
  ActiveMerchant.deprecated "CreditCard#type is deprecated and will be removed from a future release of ActiveMerchant. Please use CreditCard#brand instead."
143
154
  brand
@@ -253,6 +264,10 @@ module ActiveMerchant #:nodoc:
253
264
  require_name
254
265
  end
255
266
 
267
+ def emv?
268
+ icc_data.present?
269
+ end
270
+
256
271
  private
257
272
 
258
273
  def validate_essential_attributes #:nodoc:
@@ -3,7 +3,7 @@ module ActiveMerchant #:nodoc:
3
3
  # Convenience methods that can be included into a custom Credit Card object, such as an ActiveRecord based Credit Card object.
4
4
  module CreditCardMethods
5
5
  CARD_COMPANIES = {
6
- 'visa' => /^4\d{12}(\d{3})?$/,
6
+ 'visa' => /^4\d{12}(\d{3})?(\d{3})?$/,
7
7
  'master' => /^(5[1-5]\d{4}|677189)\d{10}$/,
8
8
  'discover' => /^(6011|65\d{2}|64[4-9]\d)\d{12}|(62\d{14})$/,
9
9
  'american_express' => /^3[47]\d{13}$/,
@@ -49,11 +49,11 @@ module ActiveMerchant #:nodoc:
49
49
  def valid_card_verification_value?(cvv, brand)
50
50
  cvv.to_s =~ /^\d{#{card_verification_value_length(brand)}}$/
51
51
  end
52
-
52
+
53
53
  def card_verification_value_length(brand)
54
54
  brand == 'american_express' ? 4 : 3
55
55
  end
56
-
56
+
57
57
  def valid_issue_number?(number)
58
58
  (number.to_s =~ /^\d{1,2}$/)
59
59
  end
@@ -254,6 +254,11 @@ module ActiveMerchant #:nodoc:
254
254
  money.respond_to?(:currency) ? money.currency : self.default_currency
255
255
  end
256
256
 
257
+ def truncate(value, max_size)
258
+ return nil unless value
259
+ value.to_s[0, max_size]
260
+ end
261
+
257
262
  def requires_start_date_or_issue_number?(credit_card)
258
263
  return false if card_brand(credit_card).blank?
259
264
  DEBIT_CARDS.include?(card_brand(credit_card).to_sym)
@@ -22,7 +22,7 @@ module ActiveMerchant #:nodoc:
22
22
  '2315' => STANDARD_ERROR_CODE[:invalid_number],
23
23
  '37' => STANDARD_ERROR_CODE[:invalid_expiry_date],
24
24
  '2316' => STANDARD_ERROR_CODE[:invalid_expiry_date],
25
- '378' => STANDARD_ERROR_CODE[:invalid_cvc],
25
+ '378' => STANDARD_ERROR_CODE[:invalid_cvc],
26
26
  '38' => STANDARD_ERROR_CODE[:expired_card],
27
27
  '2317' => STANDARD_ERROR_CODE[:expired_card],
28
28
  '244' => STANDARD_ERROR_CODE[:incorrect_cvc],
@@ -232,9 +232,9 @@ module ActiveMerchant #:nodoc:
232
232
  else
233
233
  xml.payment do
234
234
  xml.creditCard do
235
- xml.cardNumber(credit_card.number)
235
+ xml.cardNumber(truncate(credit_card.number, 16))
236
236
  xml.expirationDate(format(credit_card.month, :two_digits) + '/' + format(credit_card.year, :four_digits))
237
- unless empty?(credit_card.verification_value)
237
+ if credit_card.valid_card_verification_value?(credit_card.verification_value, credit_card.brand)
238
238
  xml.cardCode(credit_card.verification_value)
239
239
  end
240
240
  if credit_card.is_a?(NetworkTokenizationCreditCard)
@@ -486,10 +486,6 @@ module ActiveMerchant #:nodoc:
486
486
  (response[:response_code] == FRAUD_REVIEW)
487
487
  end
488
488
 
489
- def truncate(value, max_size)
490
- return nil unless value
491
- value.to_s[0, max_size]
492
- end
493
489
 
494
490
  def using_live_gateway_in_test_mode?(response)
495
491
  !test? && response[:test_request] == "1"
@@ -4,11 +4,12 @@ module ActiveMerchant #:nodoc:
4
4
  module Billing #:nodoc:
5
5
  class BorgunGateway < Gateway
6
6
  self.display_name = "Borgun"
7
+ self.homepage_url = 'http://www.borgun.com'
7
8
 
8
9
  self.test_url = 'https://gatewaytest.borgun.is/ws/Heimir.pub.ws:Authorization'
9
10
  self.live_url = 'https://gateway01.borgun.is/ws/Heimir.pub.ws:Authorization'
10
11
 
11
- self.supported_countries = ['IS']
12
+ self.supported_countries = ['IS', 'GB', 'HU', 'CZ', 'DE', 'DK', 'SE' ]
12
13
  self.default_currency = 'ISK'
13
14
  self.money_format = :cents
14
15
  self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :discover, :jcb]
@@ -335,7 +335,8 @@ module ActiveMerchant #:nodoc:
335
335
  end
336
336
 
337
337
  def avs_code_from(transaction)
338
- avs_mapping["street: #{transaction.avs_street_address_response_code}, zip: #{transaction.avs_postal_code_response_code}"]
338
+ transaction.avs_error_response_code ||
339
+ avs_mapping["street: #{transaction.avs_street_address_response_code}, zip: #{transaction.avs_postal_code_response_code}"]
339
340
  end
340
341
 
341
342
  def avs_mapping
@@ -518,6 +519,7 @@ module ActiveMerchant #:nodoc:
518
519
 
519
520
  parameters[:custom_fields] = options[:custom_fields]
520
521
  parameters[:device_data] = options[:device_data] if options[:device_data]
522
+ parameters[:service_fee_amount] = options[:service_fee_amount] if options[:service_fee_amount]
521
523
  if merchant_account_id = (options[:merchant_account_id] || @merchant_account_id)
522
524
  parameters[:merchant_account_id] = merchant_account_id
523
525
  end
@@ -186,7 +186,7 @@ module ActiveMerchant #:nodoc:
186
186
  currency_code = options[:currency] || currency(money)
187
187
  params[key] = {
188
188
  'TotalAmount' => localized_amount(money, currency_code),
189
- 'InvoiceReference' => truncate(options[:order_id]),
189
+ 'InvoiceReference' => truncate(options[:order_id], 50),
190
190
  'InvoiceNumber' => truncate(options[:order_id], 12),
191
191
  'InvoiceDescription' => truncate(options[:description], 64),
192
192
  'CurrencyCode' => currency_code,
@@ -214,9 +214,9 @@ module ActiveMerchant #:nodoc:
214
214
  end
215
215
  params['Title'] = address[:title]
216
216
  params['CompanyName'] = address[:company] unless options[:skip_company]
217
- params['Street1'] = truncate(address[:address1])
218
- params['Street2'] = truncate(address[:address2])
219
- params['City'] = truncate(address[:city])
217
+ params['Street1'] = truncate(address[:address1], 50)
218
+ params['Street2'] = truncate(address[:address2], 50)
219
+ params['City'] = truncate(address[:city], 50)
220
220
  params['State'] = address[:state]
221
221
  params['PostalCode'] = address[:zip]
222
222
  params['Country'] = address[:country].to_s.downcase
@@ -230,7 +230,7 @@ module ActiveMerchant #:nodoc:
230
230
  params['Customer'] ||= {}
231
231
  if credit_card.respond_to? :number
232
232
  card_details = params['Customer']['CardDetails'] = {}
233
- card_details['Name'] = truncate(credit_card.name)
233
+ card_details['Name'] = truncate(credit_card.name, 50)
234
234
  card_details['Number'] = credit_card.number
235
235
  card_details['ExpiryMonth'] = "%02d" % (credit_card.month || 0)
236
236
  card_details['ExpiryYear'] = "%02d" % (credit_card.year || 0)
@@ -337,11 +337,6 @@ module ActiveMerchant #:nodoc:
337
337
  end
338
338
  end
339
339
 
340
- def truncate(value, max_size = 50)
341
- return nil unless value
342
- value.to_s[0, max_size]
343
- end
344
-
345
340
  MESSAGES = {
346
341
  'A2000' => 'Transaction Approved Successful',
347
342
  'A2008' => 'Honour With Identification Successful',
@@ -0,0 +1,206 @@
1
+ module ActiveMerchant
2
+ module Billing
3
+ class EzicGateway < Gateway
4
+ self.live_url = 'https://secure-dm3.ezic.com/gw/sas/direct3.2'
5
+
6
+ self.supported_countries = %w(AU CA CN FR DE GI IL MT MU MX NL NZ PA PH RU SG KR ES KN GB US)
7
+ self.default_currency = 'USD'
8
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club]
9
+
10
+ self.homepage_url = 'http://www.ezic.com/'
11
+ self.display_name = 'Ezic'
12
+
13
+ def initialize(options={})
14
+ requires!(options, :account_id)
15
+ super
16
+ end
17
+
18
+ def purchase(money, payment, options={})
19
+ post = {}
20
+
21
+ add_account_id(post)
22
+ add_invoice(post, money, options)
23
+ add_payment(post, payment)
24
+ add_customer_data(post, options)
25
+
26
+ commit("S", post)
27
+ end
28
+
29
+ def authorize(money, payment, options={})
30
+ post = {}
31
+
32
+ add_account_id(post)
33
+ add_invoice(post, money, options)
34
+ add_payment(post, payment)
35
+ add_customer_data(post, options)
36
+
37
+ commit("A", post)
38
+ end
39
+
40
+ def capture(money, authorization, options={})
41
+ post = {}
42
+
43
+ add_account_id(post)
44
+ add_invoice(post, money, options)
45
+ add_authorization(post, authorization)
46
+ add_pay_type(post)
47
+
48
+ commit("D", post)
49
+ end
50
+
51
+ def refund(money, authorization, options={})
52
+ post = {}
53
+
54
+ add_account_id(post)
55
+ add_invoice(post, money, options)
56
+ add_authorization(post, authorization)
57
+ add_pay_type(post)
58
+
59
+ commit("R", post)
60
+ end
61
+
62
+ def void(authorization, options={})
63
+ post = {}
64
+
65
+ add_account_id(post)
66
+ add_authorization(post, authorization)
67
+ add_pay_type(post)
68
+
69
+ commit("U", post)
70
+ end
71
+
72
+ def verify(credit_card, options={})
73
+ MultiResponse.run(:use_first_response) do |r|
74
+ r.process { authorize(100, credit_card, options) }
75
+ r.process(:ignore_result) { void(r.authorization, options) }
76
+ end
77
+ end
78
+
79
+ def supports_scrubbing?
80
+ true
81
+ end
82
+
83
+ def scrub(transcript)
84
+ transcript.
85
+ gsub(%r((card_number=)\w+), '\1[FILTERED]').
86
+ gsub(%r((card_cvv2=)\w+), '\1[FILTERED]')
87
+ end
88
+
89
+ private
90
+
91
+ def add_account_id(post)
92
+ post[:account_id] = @options[:account_id]
93
+ end
94
+
95
+ def add_addresses(post, options)
96
+ add_billing_address(post, options)
97
+ add_shipping_address(post, options)
98
+ end
99
+
100
+ def add_billing_address(post, options)
101
+ address = options[:billing_address] || {}
102
+
103
+ if address[:name]
104
+ names = address[:name].split
105
+ post[:bill_name2] = names.pop
106
+ post[:bill_name1] = names.join(" ")
107
+ end
108
+
109
+ post[:bill_street] = address[:address1] if address[:address1]
110
+ post[:bill_city] = address[:city] if address[:city]
111
+ post[:bill_state] = address[:state] if address[:state]
112
+ post[:bill_zip] = address[:zip] if address[:zip]
113
+ post[:bill_country] = address[:country] if address[:country]
114
+ post[:cust_phone] = address[:phone] if address[:phone]
115
+ end
116
+
117
+ def add_shipping_address(post, options)
118
+ address = options[:shipping_address] || {}
119
+
120
+ if address[:name]
121
+ names = address[:name].split
122
+ post[:ship_name2] = names.pop
123
+ post[:ship_name1] = names.join(" ")
124
+ end
125
+
126
+ post[:ship_street] = address[:address1] if address[:address1]
127
+ post[:ship_city] = address[:city] if address[:city]
128
+ post[:ship_state] = address[:state] if address[:state]
129
+ post[:ship_zip] = address[:zip] if address[:zip]
130
+ post[:ship_country] = address[:country] if address[:country]
131
+ end
132
+
133
+ def add_customer_data(post, options)
134
+ post[:cust_ip] = options[:ip] if options[:ip]
135
+ post[:cust_email] = options[:email] if options[:email]
136
+ add_addresses(post, options)
137
+ end
138
+
139
+ def add_invoice(post, money, options)
140
+ post[:amount] = amount(money)
141
+ post[:description] = options[:description] if options[:description]
142
+ end
143
+
144
+ def add_payment(post, payment)
145
+ add_pay_type(post)
146
+ post[:card_number] = payment.number
147
+ post[:card_cvv2] = payment.verification_value
148
+ post[:card_expire] = expdate(payment)
149
+ end
150
+
151
+ def add_authorization(post, authorization)
152
+ post[:orig_id] = authorization
153
+ end
154
+
155
+ def add_pay_type(post)
156
+ post[:pay_type] = "C"
157
+ end
158
+
159
+ def parse(body)
160
+ CGI::parse(body).inject({}) { |hash, (key, value)| hash[key] = value.first; hash }
161
+ end
162
+
163
+ def commit(transaction_type, parameters)
164
+ parameters[:tran_type] = transaction_type
165
+
166
+ begin
167
+ response = parse(ssl_post(live_url, post_data(parameters), headers))
168
+ Response.new(
169
+ success_from(response),
170
+ message_from(response),
171
+ response,
172
+ authorization: authorization_from(response),
173
+ avs_result: AVSResult.new(code: response["avs_code"]),
174
+ cvv_result: CVVResult.new(response["cvv2_code"]),
175
+ test: test?
176
+ )
177
+ rescue ResponseError => e
178
+ Response.new(false, e.response.message)
179
+ end
180
+ end
181
+
182
+ def success_from(response)
183
+ response["status_code"] == "1" || response["status_code"] == "T"
184
+ end
185
+
186
+ def message_from(response)
187
+ response["auth_msg"]
188
+ end
189
+
190
+ def authorization_from(response)
191
+ response["trans_id"]
192
+ end
193
+
194
+ def post_data(parameters = {})
195
+ parameters.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
196
+ end
197
+
198
+ def headers
199
+ {
200
+ "User-Agent" => "ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
201
+ }
202
+ end
203
+ end
204
+
205
+ end
206
+ end
@@ -174,10 +174,6 @@ module ActiveMerchant #:nodoc:
174
174
  }
175
175
  end
176
176
 
177
- def truncate(value, max_size)
178
- return nil unless value
179
- value.to_s[0, max_size]
180
- end
181
177
  end
182
178
  end
183
179
  end
@@ -6,7 +6,7 @@ module ActiveMerchant #:nodoc:
6
6
  self.live_na_url = 'https://www.iatspayments.com/NetGate'
7
7
  self.live_uk_url = 'https://www.uk.iatspayments.com/NetGate'
8
8
 
9
- self.supported_countries = %w(AU BR CA CH DE DK ES FI FR GR HK IE IT NL NO PT SE SG TR GB US)
9
+ self.supported_countries = %w(AU BR CA CH DE DK ES FI FR GR HK IE IT NL NO PT SE SG TR GB US TH ID PH BE)
10
10
  self.default_currency = 'USD'
11
11
  self.supported_cardtypes = [:visa, :master, :american_express, :discover]
12
12
 
@@ -107,7 +107,7 @@ module ActiveMerchant #:nodoc:
107
107
  request = build_xml_request do |doc|
108
108
  add_authentication(doc)
109
109
  doc.registerTokenRequest(transaction_attributes(options)) do
110
- doc.orderId(truncated(options[:order_id]))
110
+ doc.orderId(truncate(options[:order_id], 24))
111
111
  doc.accountNumber(creditcard.number)
112
112
  end
113
113
  end
@@ -155,7 +155,7 @@ module ActiveMerchant #:nodoc:
155
155
  end
156
156
 
157
157
  def add_auth_purchase_params(doc, money, payment_method, options)
158
- doc.orderId(truncated(options[:order_id]))
158
+ doc.orderId(truncate(options[:order_id], 24))
159
159
  doc.amount(money)
160
160
  add_order_source(doc, payment_method, options)
161
161
  add_billing_address(doc, payment_method, options)
@@ -296,7 +296,7 @@ module ActiveMerchant #:nodoc:
296
296
 
297
297
  def transaction_attributes(options)
298
298
  attributes = {}
299
- attributes[:id] = truncated(options[:id] || options[:order_id])
299
+ attributes[:id] = truncate(options[:id] || options[:order_id], 24)
300
300
  attributes[:reportGroup] = options[:merchant] || 'Default Report Group'
301
301
  attributes[:customerId] = options[:customer]
302
302
  attributes.delete_if { |key, value| value == nil }
@@ -323,21 +323,6 @@ module ActiveMerchant #:nodoc:
323
323
  test? ? test_url : live_url
324
324
  end
325
325
 
326
- def truncated(value)
327
- return unless value
328
- value[0..24]
329
- end
330
-
331
- def truncated_order_id(options)
332
- return unless options[:order_id]
333
- options[:order_id][0..24]
334
- end
335
-
336
- def truncated_id(options)
337
- return unless options[:id]
338
- options[:id][0..24]
339
- end
340
-
341
326
  def headers
342
327
  {
343
328
  'Content-Type' => 'text/xml'
@@ -86,7 +86,7 @@ module ActiveMerchant #:nodoc:
86
86
  end
87
87
 
88
88
  def add_product(post, options)
89
- post['transactionProduct'] = options[:description]
89
+ post['transactionProduct'] = truncate(options[:description], 34)
90
90
  end
91
91
 
92
92
  def add_payment_method(post, payment_method)
@@ -38,6 +38,13 @@ module ActiveMerchant #:nodoc:
38
38
  super
39
39
  end
40
40
 
41
+ def verify(creditcard_or_datakey, options = {})
42
+ MultiResponse.run(:use_first_response) do |r|
43
+ r.process { authorize(100, creditcard_or_datakey, options) }
44
+ r.process(:ignore_result) { capture(0, r.authorization) }
45
+ end
46
+ end
47
+
41
48
  # Referred to as "PreAuth" in the Moneris integration guide, this action
42
49
  # verifies and locks funds on a customer's card, which then must be
43
50
  # captured at a later date.
@@ -264,11 +264,6 @@ module ActiveMerchant #:nodoc:
264
264
  truncate(cleansed, 20)
265
265
  end
266
266
 
267
- def truncate(value, max_size)
268
- return nil unless value
269
- value[0, max_size]
270
- end
271
-
272
267
  def is_usa(country)
273
268
  truncate(country, 2) == 'US'
274
269
  end
@@ -93,8 +93,7 @@ module ActiveMerchant #:nodoc:
93
93
 
94
94
  xml.tag! 'AMOUNT', amount(money)
95
95
  add_credit_card(xml, creditcard)
96
- add_params_in_required_order(xml, action, options)
97
- add_address(xml, creditcard, options)
96
+ add_params_in_required_order(xml, action, creditcard, options)
98
97
  add_more_required_params(xml, options)
99
98
 
100
99
  xml.target!
@@ -110,7 +109,7 @@ module ActiveMerchant #:nodoc:
110
109
  xml.tag! 'CARDNUMBER', last_four
111
110
  end
112
111
 
113
- add_params_in_required_order(xml, action, options)
112
+ add_params_in_required_order(xml, action, nil, options)
114
113
  xml.tag! 'REF_TRANSID', transaction_id
115
114
  add_more_required_params(xml, options)
116
115
 
@@ -136,6 +135,7 @@ module ActiveMerchant #:nodoc:
136
135
  end
137
136
 
138
137
  def add_address(xml, creditcard, options)
138
+ return unless creditcard
139
139
 
140
140
  if address = options[:billing_address] || options[:address]
141
141
  xml.tag!("CUSTOMER_BILL") do
@@ -161,8 +161,18 @@ module ActiveMerchant #:nodoc:
161
161
  xml.tag! 'CITY', address[:city].to_s
162
162
  xml.tag! 'COMPANY', address[:company].to_s
163
163
  xml.tag! 'COUNTRY', address[:country].to_s
164
- xml.tag! 'FIRSTNAME', address[:first_name].to_s
165
- xml.tag! 'LASTNAME', address[:last_name].to_s
164
+
165
+ if address[:name]
166
+ names = address[:name].split
167
+ last_name = names.pop
168
+ first_name = names.join(" ")
169
+ xml.tag! 'FIRSTNAME', first_name
170
+ xml.tag! 'LASTNAME', last_name
171
+ else
172
+ xml.tag! 'FIRSTNAME', address[:first_name].to_s
173
+ xml.tag! 'LASTNAME', address[:last_name].to_s
174
+ end
175
+
166
176
  xml.tag! 'STATE', address[:state].blank? ? 'n/a' : address[:state]
167
177
  xml.tag! 'ZIP', address[:zip].to_s
168
178
  end
@@ -182,9 +192,10 @@ module ActiveMerchant #:nodoc:
182
192
  end
183
193
 
184
194
  # SecureNet requires some of the xml params to be in a certain order. http://cl.ly/image/3K260E0p0a0n/content.png
185
- def add_params_in_required_order(xml, action, options)
195
+ def add_params_in_required_order(xml, action, creditcard, options)
186
196
  xml.tag! 'CODE', TRANSACTIONS[action]
187
197
  add_customer_data(xml, options)
198
+ add_address(xml, creditcard, options)
188
199
  xml.tag! 'DCI', 0 # No duplicate checking will be done, except for ORDERID
189
200
  xml.tag! 'INSTALLMENT_SEQUENCENUM', 1
190
201
  xml.tag! 'INVOICEDESC', options[:invoice_description] if options[:invoice_description]
@@ -8,8 +8,8 @@ module ActiveMerchant #:nodoc:
8
8
 
9
9
  class_attribute :test_periodic_url, :live_periodic_url
10
10
 
11
- self.test_url = 'https://www.securepay.com.au/test/payment'
12
- self.live_url = 'https://www.securepay.com.au/xmlapi/payment'
11
+ self.test_url = 'https://api.securepay.com.au/test/payment'
12
+ self.live_url = 'https://api.securepay.com.au/xmlapi/payment'
13
13
 
14
14
  self.test_periodic_url = 'https://test.securepay.com.au/xmlapi/periodic'
15
15
  self.live_periodic_url = 'https://api.securepay.com.au/xmlapi/periodic'
@@ -27,7 +27,7 @@ module ActiveMerchant #:nodoc:
27
27
  self.supported_countries = %w(AT AU BE CA CH DE DK ES FI FR GB IE IT LU NL NO SE US)
28
28
  self.default_currency = 'USD'
29
29
  self.money_format = :cents
30
- self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club]
30
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club, :maestro]
31
31
 
32
32
  self.homepage_url = 'https://stripe.com/'
33
33
  self.display_name = 'Stripe'
@@ -62,7 +62,7 @@ module ActiveMerchant #:nodoc:
62
62
  end
63
63
  r.process do
64
64
  post = create_post_for_auth_or_purchase(money, payment, options)
65
- post[:capture] = "false"
65
+ post[:capture] = "false" unless emv_payment?(payment)
66
66
  commit(:post, 'charges', post, options)
67
67
  end
68
68
  end.responses.last
@@ -90,10 +90,16 @@ module ActiveMerchant #:nodoc:
90
90
 
91
91
  def capture(money, authorization, options = {})
92
92
  post = {}
93
- add_amount(post, money, options)
93
+
94
94
  add_application_fee(post, options)
95
95
 
96
- commit(:post, "charges/#{CGI.escape(authorization)}/capture", post, options)
96
+ if emv_tc_response = options.delete(:icc_data)
97
+ post[:card] = { emv_approval_data: emv_tc_response }
98
+ commit(:post, "charges/#{CGI.escape(authorization)}", post, options)
99
+ else
100
+ add_amount(post, money, options)
101
+ commit(:post, "charges/#{CGI.escape(authorization)}/capture", post, options)
102
+ end
97
103
  end
98
104
 
99
105
  def void(identification, options = {})
@@ -226,24 +232,24 @@ module ActiveMerchant #:nodoc:
226
232
 
227
233
  def create_post_for_auth_or_purchase(money, payment, options)
228
234
  post = {}
229
- add_amount(post, money, options, true)
235
+
230
236
  if payment.is_a?(StripePaymentToken)
231
237
  add_payment_token(post, payment, options)
232
238
  else
233
239
  add_creditcard(post, payment, options)
234
240
  end
235
- add_customer(post, payment, options)
236
- add_customer_data(post, options)
237
- post[:description] = options[:description]
238
- post[:statement_description] = options[:statement_description]
239
-
240
- post[:metadata] = options[:metadata] || {}
241
- post[:metadata][:email] = options[:email] if options[:email]
242
- post[:metadata][:order_id] = options[:order_id] if options[:order_id]
243
- post.delete(:metadata) if post[:metadata].empty?
241
+ unless emv_payment?(payment)
242
+ add_amount(post, money, options, true)
243
+ add_customer_data(post, options)
244
+ add_metadata(post, options)
245
+ post[:description] = options[:description]
246
+ post[:statement_description] = options[:statement_description]
247
+ add_customer(post, payment, options)
248
+ add_flags(post, options)
249
+ end
244
250
 
245
- add_flags(post, options)
246
251
  add_application_fee(post, options)
252
+ add_destination(post, options)
247
253
  post
248
254
  end
249
255
 
@@ -257,6 +263,10 @@ module ActiveMerchant #:nodoc:
257
263
  post[:application_fee] = options[:application_fee] if options[:application_fee]
258
264
  end
259
265
 
266
+ def add_destination(post, options)
267
+ post[:destination] = options[:destination] if options[:destination]
268
+ end
269
+
260
270
  def add_expand_parameters(post, options)
261
271
  post[:expand] = Array.wrap(options[:expand])
262
272
  end
@@ -283,9 +293,12 @@ module ActiveMerchant #:nodoc:
283
293
 
284
294
  def add_creditcard(post, creditcard, options)
285
295
  card = {}
286
- if creditcard.respond_to?(:number)
296
+ if emv_payment?(creditcard)
297
+ add_emv_creditcard(post, creditcard.icc_data)
298
+ elsif creditcard.respond_to?(:number)
287
299
  if creditcard.respond_to?(:track_data) && creditcard.track_data.present?
288
300
  card[:swipe_data] = creditcard.track_data
301
+ card[:fallback_reason] = creditcard.fallback_reason if creditcard.fallback_reason
289
302
  else
290
303
  card[:number] = creditcard.number
291
304
  card[:exp_month] = creditcard.month
@@ -293,7 +306,6 @@ module ActiveMerchant #:nodoc:
293
306
  card[:cvc] = creditcard.verification_value if creditcard.verification_value?
294
307
  card[:name] = creditcard.name if creditcard.name
295
308
  end
296
-
297
309
  post[:card] = card
298
310
 
299
311
  if creditcard.is_a?(NetworkTokenizationCreditCard)
@@ -314,6 +326,10 @@ module ActiveMerchant #:nodoc:
314
326
  end
315
327
  end
316
328
 
329
+ def add_emv_creditcard(post, icc_data, options = {})
330
+ post[:card] = { emv_auth_data: icc_data }
331
+ end
332
+
317
333
  def add_payment_token(post, token, options = {})
318
334
  post[:card] = token.payment_data["id"]
319
335
  end
@@ -327,6 +343,13 @@ module ActiveMerchant #:nodoc:
327
343
  post[:recurring] = true if (options[:eci] == 'recurring' || options[:recurring])
328
344
  end
329
345
 
346
+ def add_metadata(post, options = {})
347
+ post[:metadata] = options[:metadata] || {}
348
+ post[:metadata][:email] = options[:email] if options[:email]
349
+ post[:metadata][:order_id] = options[:order_id] if options[:order_id]
350
+ post.delete(:metadata) if post[:metadata].empty?
351
+ end
352
+
330
353
  def fetch_application_fees(identification, options = {})
331
354
  options.merge!(:key => @fee_refund_api_key)
332
355
 
@@ -359,6 +382,7 @@ module ActiveMerchant #:nodoc:
359
382
  def headers(options = {})
360
383
  key = options[:key] || @api_key
361
384
  version = options[:version] || @version
385
+ idempotency_key = options[:idempotency_key]
362
386
 
363
387
  headers = {
364
388
  "Authorization" => "Basic " + Base64.encode64(key.to_s + ":").strip,
@@ -367,6 +391,7 @@ module ActiveMerchant #:nodoc:
367
391
  "X-Stripe-Client-User-Metadata" => {:ip => options[:ip]}.to_json
368
392
  }
369
393
  headers.merge!("Stripe-Version" => version) if version
394
+ headers.merge!("Idempotency-Key" => idempotency_key) if idempotency_key
370
395
  headers
371
396
  end
372
397
 
@@ -386,11 +411,11 @@ module ActiveMerchant #:nodoc:
386
411
 
387
412
  def commit(method, url, parameters = nil, options = {})
388
413
  add_expand_parameters(parameters, options) if parameters
389
-
390
414
  response = api_request(method, url, parameters, options)
415
+
391
416
  success = !response.key?("error")
392
417
 
393
- card = response["card"] || response["active_card"] || {}
418
+ card = response["card"] || response["active_card"] || response["source"] || {}
394
419
  avs_code = AVS_CODE_TRANSLATOR["line1: #{card["address_line1_check"]}, zip: #{card["address_zip_check"]}"]
395
420
  cvc_code = CVC_CODE_TRANSLATOR[card["cvc_check"]]
396
421
 
@@ -401,6 +426,7 @@ module ActiveMerchant #:nodoc:
401
426
  :authorization => success ? response["id"] : response["error"]["charge"],
402
427
  :avs_result => { :code => avs_code },
403
428
  :cvv_result => cvc_code,
429
+ :emv_authorization => card["emv_auth_data"],
404
430
  :error_code => success ? nil : STANDARD_ERROR_CODE_MAPPING[response["error"]["code"]]
405
431
  )
406
432
  end
@@ -426,6 +452,10 @@ module ActiveMerchant #:nodoc:
426
452
  def non_fractional_currency?(currency)
427
453
  CURRENCIES_WITHOUT_FRACTIONS.include?(currency.to_s)
428
454
  end
455
+
456
+ def emv_payment?(payment)
457
+ payment.respond_to?(:emv?) && payment.emv?
458
+ end
429
459
  end
430
460
  end
431
461
  end
@@ -148,13 +148,16 @@ module ActiveMerchant #:nodoc:
148
148
  response = parse(e.response.body)
149
149
  end
150
150
 
151
- Response.new(
151
+ return Response.new(
152
152
  success_from(response),
153
153
  message_from(response),
154
154
  response,
155
155
  authorization: authorization_from(response, params),
156
156
  test: test?
157
157
  )
158
+
159
+ rescue JSON::ParserError
160
+ return unparsable_response(response)
158
161
  end
159
162
 
160
163
  def success_from(response)
@@ -176,6 +179,12 @@ module ActiveMerchant #:nodoc:
176
179
  [auth, original_amount]
177
180
  end
178
181
 
182
+ def unparsable_response(raw_response)
183
+ message = "Invalid JSON response received from WePay. Please contact WePay support if you continue to receive this message."
184
+ message += " (The raw response returned by the API was #{raw_response.inspect})"
185
+ return Response.new(false, message)
186
+ end
187
+
179
188
  def headers
180
189
  {
181
190
  "Content-Type" => "application/json",
@@ -4,7 +4,7 @@ module ActiveMerchant #:nodoc:
4
4
  end
5
5
 
6
6
  class Response
7
- attr_reader :params, :message, :test, :authorization, :avs_result, :cvv_result, :error_code
7
+ attr_reader :params, :message, :test, :authorization, :avs_result, :cvv_result, :error_code, :emv_authorization
8
8
 
9
9
  def success?
10
10
  @success
@@ -24,6 +24,7 @@ module ActiveMerchant #:nodoc:
24
24
  @authorization = options[:authorization]
25
25
  @fraud_review = options[:fraud_review]
26
26
  @error_code = options[:error_code]
27
+ @emv_authorization = options[:emv_authorization]
27
28
 
28
29
  @avs_result = if options[:avs_result].kind_of?(AVSResult)
29
30
  options[:avs_result].to_hash
@@ -79,7 +80,7 @@ module ActiveMerchant #:nodoc:
79
80
  (primary_response ? primary_response.success? : true)
80
81
  end
81
82
 
82
- %w(params message test authorization avs_result cvv_result error_code test? fraud_review?).each do |m|
83
+ %w(params message test authorization avs_result cvv_result error_code emv_authorization test? fraud_review?).each do |m|
83
84
  class_eval %(
84
85
  def #{m}
85
86
  (@responses.empty? ? nil : primary_response.#{m})
@@ -7,6 +7,7 @@ module ActiveMerchant
7
7
  Timeout::Error => "The connection to the remote server timed out",
8
8
  Errno::ETIMEDOUT => "The connection to the remote server timed out",
9
9
  SocketError => "The connection to the remote server could not be established",
10
+ Errno::EHOSTUNREACH => "The connection to the remote server could not be established",
10
11
  OpenSSL::SSL::SSLError => "The SSL connection to the remote server could not be established"
11
12
  }
12
13
 
@@ -1,3 +1,3 @@
1
1
  module ActiveMerchant
2
- VERSION = "1.48.0"
2
+ VERSION = "1.49.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activemerchant
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.48.0
4
+ version: 1.49.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Luetke
@@ -30,7 +30,7 @@ cert_chain:
30
30
  fl3hbtVFTqbOlwL9vy1fudXcolIE/ZTcxQ+er07ZFZdKCXayR9PPs64heamfn0fp
31
31
  TConQSX2BnZdhIEYW+cKzEC/bLc=
32
32
  -----END CERTIFICATE-----
33
- date: 2015-04-08 00:00:00.000000000 Z
33
+ date: 2015-05-01 00:00:00.000000000 Z
34
34
  dependencies:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: activesupport
@@ -226,6 +226,7 @@ files:
226
226
  - lib/active_merchant/billing/gateways/eway_managed.rb
227
227
  - lib/active_merchant/billing/gateways/eway_rapid.rb
228
228
  - lib/active_merchant/billing/gateways/exact.rb
229
+ - lib/active_merchant/billing/gateways/ezic.rb
229
230
  - lib/active_merchant/billing/gateways/fat_zebra.rb
230
231
  - lib/active_merchant/billing/gateways/federated_canada.rb
231
232
  - lib/active_merchant/billing/gateways/finansbank.rb
metadata.gz.sig CHANGED
@@ -1 +1 @@
1
- �#�VurL��n S���.:d�@)��~>*���*ź���g�7��#�Rۏ>� c�D�t'��{��Q�ª?��Oߴh�_�Ԉo��v�rKĜ/������M�~f)�B#ŏ��F��s�V�֎�RkՂ;s�Z�nd�Q�J(�2��%C���9Z�sz�>+-$�"N�{O���ʥG7�� �q8c���C��
1
+ r���!��ꗐ��u试e0�8�)���qDLe���\�})XI֒�>\�<�Ce?r����÷z>g��EYL�2g�s&!��bE