activemerchant 1.62.0 → 1.79.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +420 -2
  3. data/README.md +1 -2
  4. data/lib/active_merchant/billing/credit_card.rb +13 -14
  5. data/lib/active_merchant/billing/credit_card_methods.rb +3 -1
  6. data/lib/active_merchant/billing/gateway.rb +25 -9
  7. data/lib/active_merchant/billing/gateways/adyen.rb +299 -0
  8. data/lib/active_merchant/billing/gateways/authorize_net.rb +168 -56
  9. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +4 -2
  10. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +65 -22
  11. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +87 -7
  12. data/lib/active_merchant/billing/gateways/beanstream.rb +2 -0
  13. data/lib/active_merchant/billing/gateways/blue_snap.rb +3 -8
  14. data/lib/active_merchant/billing/gateways/borgun.rb +10 -10
  15. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +1 -0
  16. data/lib/active_merchant/billing/gateways/braintree_blue.rb +49 -15
  17. data/lib/active_merchant/billing/gateways/card_connect.rb +286 -0
  18. data/lib/active_merchant/billing/gateways/card_stream.rb +97 -2
  19. data/lib/active_merchant/billing/gateways/cardprocess.rb +254 -0
  20. data/lib/active_merchant/billing/gateways/cashnet.rb +14 -2
  21. data/lib/active_merchant/billing/gateways/cenpos.rb +1 -1
  22. data/lib/active_merchant/billing/gateways/checkout.rb +1 -1
  23. data/lib/active_merchant/billing/gateways/checkout_v2.rb +44 -14
  24. data/lib/active_merchant/billing/gateways/citrus_pay.rb +0 -1
  25. data/lib/active_merchant/billing/gateways/clearhaus.rb +0 -2
  26. data/lib/active_merchant/billing/gateways/conekta.rb +4 -4
  27. data/lib/active_merchant/billing/gateways/creditcall.rb +71 -9
  28. data/lib/active_merchant/billing/gateways/credorax.rb +117 -5
  29. data/lib/active_merchant/billing/gateways/culqi.rb +279 -0
  30. data/lib/active_merchant/billing/gateways/cyber_source.rb +54 -15
  31. data/lib/active_merchant/billing/gateways/data_cash.rb +12 -0
  32. data/lib/active_merchant/billing/gateways/dibs.rb +0 -1
  33. data/lib/active_merchant/billing/gateways/digitzs.rb +292 -0
  34. data/lib/active_merchant/billing/gateways/ebanx.rb +296 -0
  35. data/lib/active_merchant/billing/gateways/elavon.rb +37 -95
  36. data/lib/active_merchant/billing/gateways/element.rb +11 -1
  37. data/lib/active_merchant/billing/gateways/fat_zebra.rb +3 -29
  38. data/lib/active_merchant/billing/gateways/first_pay.rb +12 -10
  39. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +37 -20
  40. data/lib/active_merchant/billing/gateways/forte.rb +0 -1
  41. data/lib/active_merchant/billing/gateways/global_collect.rb +55 -16
  42. data/lib/active_merchant/billing/gateways/global_transport.rb +16 -2
  43. data/lib/active_merchant/billing/gateways/hps.rb +12 -1
  44. data/lib/active_merchant/billing/gateways/iats_payments.rb +2 -2
  45. data/lib/active_merchant/billing/gateways/iveri.rb +251 -0
  46. data/lib/active_merchant/billing/gateways/jetpay.rb +12 -9
  47. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +437 -0
  48. data/lib/active_merchant/billing/gateways/kushki.rb +227 -0
  49. data/lib/active_merchant/billing/gateways/linkpoint.rb +2 -2
  50. data/lib/active_merchant/billing/gateways/litle.rb +107 -30
  51. data/lib/active_merchant/billing/gateways/mercado_pago.rb +262 -0
  52. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +11 -0
  53. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +16 -4
  54. data/lib/active_merchant/billing/gateways/mercury.rb +14 -1
  55. data/lib/active_merchant/billing/gateways/migs.rb +28 -6
  56. data/lib/active_merchant/billing/gateways/moneris.rb +20 -12
  57. data/lib/active_merchant/billing/gateways/moneris_us.rb +11 -0
  58. data/lib/active_merchant/billing/gateways/mundipagg.rb +292 -0
  59. data/lib/active_merchant/billing/gateways/nab_transact.rb +4 -4
  60. data/lib/active_merchant/billing/gateways/netbanx.rb +60 -16
  61. data/lib/active_merchant/billing/gateways/netbilling.rb +0 -1
  62. data/lib/active_merchant/billing/gateways/nmi.rb +12 -1
  63. data/lib/active_merchant/billing/gateways/ogone.rb +1 -1
  64. data/lib/active_merchant/billing/gateways/omise.rb +9 -5
  65. data/lib/active_merchant/billing/gateways/openpay.rb +13 -0
  66. data/lib/active_merchant/billing/gateways/opp.rb +124 -114
  67. data/lib/active_merchant/billing/gateways/optimal_payment.rb +14 -1
  68. data/lib/active_merchant/billing/gateways/orbital.rb +83 -14
  69. data/lib/active_merchant/billing/gateways/pay_hub.rb +2 -2
  70. data/lib/active_merchant/billing/gateways/payeezy.rb +152 -46
  71. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +12 -2
  72. data/lib/active_merchant/billing/gateways/payflow.rb +24 -2
  73. data/lib/active_merchant/billing/gateways/payment_express.rb +3 -2
  74. data/lib/active_merchant/billing/gateways/paymentez.rb +276 -0
  75. data/lib/active_merchant/billing/gateways/paymill.rb +18 -10
  76. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +14 -0
  77. data/lib/active_merchant/billing/gateways/paypal.rb +0 -12
  78. data/lib/active_merchant/billing/gateways/paystation.rb +14 -1
  79. data/lib/active_merchant/billing/gateways/payu_latam.rb +102 -62
  80. data/lib/active_merchant/billing/gateways/pin.rb +5 -0
  81. data/lib/active_merchant/billing/gateways/pro_pay.rb +326 -0
  82. data/lib/active_merchant/billing/gateways/psigate.rb +12 -1
  83. data/lib/active_merchant/billing/gateways/qbms.rb +11 -0
  84. data/lib/active_merchant/billing/gateways/quickbooks.rb +10 -0
  85. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +21 -17
  86. data/lib/active_merchant/billing/gateways/quickpay.rb +3 -3
  87. data/lib/active_merchant/billing/gateways/qvalent.rb +60 -3
  88. data/lib/active_merchant/billing/gateways/realex.rb +16 -6
  89. data/lib/active_merchant/billing/gateways/redsys.rb +8 -2
  90. data/lib/active_merchant/billing/gateways/safe_charge.rb +262 -0
  91. data/lib/active_merchant/billing/gateways/sage.rb +8 -3
  92. data/lib/active_merchant/billing/gateways/sage_pay.rb +29 -13
  93. data/lib/active_merchant/billing/gateways/secure_net.rb +11 -1
  94. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +12 -0
  95. data/lib/active_merchant/billing/gateways/smart_ps.rb +1 -1
  96. data/lib/active_merchant/billing/gateways/spreedly_core.rb +53 -7
  97. data/lib/active_merchant/billing/gateways/stripe.rb +84 -26
  98. data/lib/active_merchant/billing/gateways/tns.rb +0 -1
  99. data/lib/active_merchant/billing/gateways/trans_first.rb +3 -2
  100. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +61 -26
  101. data/lib/active_merchant/billing/gateways/trexle.rb +217 -0
  102. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +114 -9
  103. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +45 -22
  104. data/lib/active_merchant/billing/gateways/vanco.rb +1 -1
  105. data/lib/active_merchant/billing/gateways/wepay.rb +79 -46
  106. data/lib/active_merchant/billing/gateways/wirecard.rb +5 -4
  107. data/lib/active_merchant/billing/gateways/worldpay.rb +85 -20
  108. data/lib/active_merchant/billing/gateways/worldpay_us.rb +27 -8
  109. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
  110. data/lib/active_merchant/connection.rb +48 -12
  111. data/lib/active_merchant/net_http_ssl_connection.rb +9 -0
  112. data/lib/active_merchant/network_connection_retries.rb +6 -4
  113. data/lib/active_merchant/posts_data.rb +11 -1
  114. data/lib/active_merchant/version.rb +1 -1
  115. data/lib/active_merchant.rb +2 -5
  116. data/lib/certs/cacert.pem +85 -0
  117. data/lib/support/ssl_version.rb +87 -0
  118. metadata +25 -9
  119. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +0 -314
@@ -20,7 +20,8 @@ module ActiveMerchant #:nodoc:
20
20
  :void => 'VOID',
21
21
  :abort => 'ABORT',
22
22
  :store => 'TOKEN',
23
- :unstore => 'REMOVETOKEN'
23
+ :unstore => 'REMOVETOKEN',
24
+ :repeat => 'REPEAT'
24
25
  }
25
26
 
26
27
  CREDIT_CARDS = {
@@ -36,13 +37,20 @@ module ActiveMerchant #:nodoc:
36
37
  :jcb => "JCB"
37
38
  }
38
39
 
39
- AVS_CVV_CODE = {
40
+ AVS_CODE = {
40
41
  "NOTPROVIDED" => nil,
41
42
  "NOTCHECKED" => 'X',
42
43
  "MATCHED" => 'Y',
43
44
  "NOTMATCHED" => 'N'
44
45
  }
45
46
 
47
+ CVV_CODE = {
48
+ "NOTPROVIDED" => 'S',
49
+ "NOTCHECKED" => 'X',
50
+ "MATCHED" => 'M',
51
+ "NOTMATCHED" => 'N'
52
+ }
53
+
46
54
  OPTIONAL_REQUEST_FIELDS = {
47
55
  paypal_callback_url: :PayPalCallbackURL,
48
56
  basket: :Basket,
@@ -87,7 +95,7 @@ module ActiveMerchant #:nodoc:
87
95
  add_customer_data(post, options)
88
96
  add_optional_data(post, options)
89
97
 
90
- commit(:purchase, post)
98
+ commit((past_purchase_reference?(payment_method) ? :repeat : :purchase), post)
91
99
  end
92
100
 
93
101
  def authorize(money, payment_method, options = {})
@@ -130,7 +138,7 @@ module ActiveMerchant #:nodoc:
130
138
 
131
139
  post = {}
132
140
 
133
- add_credit_reference(post, identification)
141
+ add_related_reference(post, identification)
134
142
  add_amount(post, money, options)
135
143
  add_invoice(post, options)
136
144
 
@@ -195,7 +203,7 @@ module ActiveMerchant #:nodoc:
195
203
  add_pair(post, :SecurityKey, security_key)
196
204
  end
197
205
 
198
- def add_credit_reference(post, identification)
206
+ def add_related_reference(post, identification)
199
207
  order_id, transaction_id, authorization, security_key = identification.split(';')
200
208
 
201
209
  add_pair(post, :RelatedVendorTxCode, order_id)
@@ -267,10 +275,14 @@ module ActiveMerchant #:nodoc:
267
275
  end
268
276
 
269
277
  def add_payment_method(post, payment_method, options)
270
- if payment_method.respond_to?(:number)
271
- add_credit_card(post, payment_method)
278
+ if payment_method.is_a?(String)
279
+ if past_purchase_reference?(payment_method)
280
+ add_related_reference(post, payment_method)
281
+ else
282
+ add_token_details(post, payment_method, options)
283
+ end
272
284
  else
273
- add_token_details(post, payment_method, options)
285
+ add_credit_card(post, payment_method)
274
286
  end
275
287
  end
276
288
 
@@ -343,10 +355,10 @@ module ActiveMerchant #:nodoc:
343
355
  :test => test?,
344
356
  :authorization => authorization_from(response, parameters, action),
345
357
  :avs_result => {
346
- :street_match => AVS_CVV_CODE[ response["AddressResult"] ],
347
- :postal_match => AVS_CVV_CODE[ response["PostCodeResult"] ],
358
+ :street_match => AVS_CODE[ response["AddressResult"] ],
359
+ :postal_match => AVS_CODE[ response["PostCodeResult"] ],
348
360
  },
349
- :cvv_result => AVS_CVV_CODE[ response["CV2Result"] ]
361
+ :cvv_result => CVV_CODE[ response["CV2Result"] ]
350
362
  )
351
363
  end
352
364
 
@@ -356,9 +368,9 @@ module ActiveMerchant #:nodoc:
356
368
  response['Token']
357
369
  else
358
370
  [ params[:VendorTxCode],
359
- response["VPSTxId"],
371
+ response["VPSTxId"] || params[:VPSTxId],
360
372
  response["TxAuthNo"],
361
- response["SecurityKey"],
373
+ response["SecurityKey"] || params[:SecurityKey],
362
374
  action ].join(";")
363
375
  end
364
376
  end
@@ -419,6 +431,10 @@ module ActiveMerchant #:nodoc:
419
431
  post[key] = value if !value.blank? || options[:required]
420
432
  end
421
433
 
434
+ def past_purchase_reference?(payment_method)
435
+ return false unless payment_method.is_a?(String)
436
+ payment_method.split(';').last == 'purchase'
437
+ end
422
438
  end
423
439
 
424
440
  end
@@ -61,8 +61,19 @@ module ActiveMerchant #:nodoc:
61
61
  refund(money, authorization, options)
62
62
  end
63
63
 
64
+ def supports_scrubbing?
65
+ true
66
+ end
67
+
68
+ def scrub(transcript)
69
+ transcript.
70
+ gsub(%r((<CARDNUMBER>)\d+(</CARDNUMBER>))i, '\1[FILTERED]\2').
71
+ gsub(%r((<CARDCODE>)\d+(</CARDCODE>))i, '\1[FILTERED]\2').
72
+ gsub(%r((<SECUREKEY>).+(</SECUREKEY>))i, '\1[FILTERED]\2')
73
+ end
64
74
 
65
75
  private
76
+
66
77
  def commit(request)
67
78
  xml = build_request(request)
68
79
  url = test? ? self.test_url : self.live_url
@@ -255,4 +266,3 @@ module ActiveMerchant #:nodoc:
255
266
  end
256
267
  end
257
268
  end
258
-
@@ -103,6 +103,18 @@ module ActiveMerchant #:nodoc:
103
103
  commit_periodic(build_periodic_item(:remove_triggered, options[:amount], nil, options))
104
104
  end
105
105
 
106
+ def supports_scrubbing?
107
+ true
108
+ end
109
+
110
+ def scrub(transcript)
111
+ transcript.
112
+ gsub(%r((<merchantID>).+(</merchantID>)), '\1[FILTERED]\2').
113
+ gsub(%r((<password>).+(</password>)), '\1[FILTERED]\2').
114
+ gsub(%r((<cardNumber>).+(</cardNumber>)), '\1[FILTERED]\2').
115
+ gsub(%r((<cvv>).+(</cvv>)), '\1[FILTERED]\2')
116
+ end
117
+
106
118
  private
107
119
 
108
120
  def build_purchase_request(money, credit_card, options)
@@ -229,7 +229,7 @@ module ActiveMerchant #:nodoc:
229
229
  end
230
230
 
231
231
  def commit(action, money, parameters)
232
- parameters[:amount] = amount(money) if money
232
+ parameters[:amount] = localized_amount(money, parameters[:currency] || default_currency) if money
233
233
  response = parse( ssl_post(self.live_url, post_data(action,parameters)) )
234
234
  Response.new(response["response"] == "1", message_from(response), response,
235
235
  :authorization => (response["transactionid"] || response["customer_vault_id"]),
@@ -44,7 +44,7 @@ module ActiveMerchant #:nodoc:
44
44
  purchase_with_token(money, payment_method, options)
45
45
  else
46
46
  MultiResponse.run do |r|
47
- r.process { save_card(false, payment_method, options) }
47
+ r.process { save_card(options[:store], payment_method, options) }
48
48
  r.process { purchase_with_token(money, r.authorization, options) }
49
49
  end
50
50
  end
@@ -62,7 +62,7 @@ module ActiveMerchant #:nodoc:
62
62
  authorize_with_token(money, payment_method, options)
63
63
  else
64
64
  MultiResponse.run do |r|
65
- r.process { save_card(false, payment_method, options) }
65
+ r.process { save_card(options[:store], payment_method, options) }
66
66
  r.process { authorize_with_token(money, r.authorization, options) }
67
67
  end
68
68
  end
@@ -88,6 +88,24 @@ module ActiveMerchant #:nodoc:
88
88
  commit("transactions/#{authorization}/void.xml", '')
89
89
  end
90
90
 
91
+
92
+ # Public: Determine whether a credit card is chargeable card and available for purchases.
93
+ #
94
+ # payment_method - The CreditCard or the Spreedly payment method token.
95
+ # options - A hash of options:
96
+ # :store - Retain the payment method if the verify
97
+ # succeeds. Defaults to false. (optional)
98
+ def verify(payment_method, options = {})
99
+ if payment_method.is_a?(String)
100
+ verify_with_token(payment_method, options)
101
+ else
102
+ MultiResponse.run do |r|
103
+ r.process { save_card(options[:store], payment_method, options) }
104
+ r.process { verify_with_token(r.authorization, options) }
105
+ end
106
+ end
107
+ end
108
+
91
109
  # Public: Store a credit card in the Spreedly vault and retain it.
92
110
  #
93
111
  # credit_card - The CreditCard to store
@@ -106,6 +124,25 @@ module ActiveMerchant #:nodoc:
106
124
  commit("payment_methods/#{authorization}/redact.xml", '', :put)
107
125
  end
108
126
 
127
+ # Public: Get the transaction with the given token.
128
+ def find(transaction_token)
129
+ commit("transactions/#{transaction_token}.xml", nil, :get)
130
+ end
131
+
132
+ alias_method :status, :find
133
+
134
+ def supports_scrubbing?
135
+ true
136
+ end
137
+
138
+ def scrub(transcript)
139
+ transcript.
140
+ gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
141
+ gsub(%r((<number>).+(</number>)), '\1[FILTERED]\2').
142
+ gsub(%r((<verification_value>).+(</verification_value>)), '\1[FILTERED]\2').
143
+ gsub(%r((<payment_method_token>).+(</payment_method_token>)), '\1[FILTERED]\2')
144
+ end
145
+
109
146
  private
110
147
 
111
148
  def save_card(retain, credit_card, options)
@@ -128,10 +165,20 @@ module ActiveMerchant #:nodoc:
128
165
  commit("gateways/#{@options[:gateway_token]}/authorize.xml", request)
129
166
  end
130
167
 
168
+ def verify_with_token(payment_method_token, options)
169
+ request = build_xml_request('transaction') do |doc|
170
+ add_invoice(doc, nil, options)
171
+ doc.payment_method_token(payment_method_token)
172
+ doc.retain_on_success(true) if options[:store]
173
+ add_extra_options(:gateway_specific_fields, doc, options)
174
+ end
175
+
176
+ commit("gateways/#{@options[:gateway_token]}/verify.xml", request)
177
+ end
178
+
131
179
  def auth_purchase_request(money, payment_method_token, options)
132
180
  build_xml_request('transaction') do |doc|
133
181
  add_invoice(doc, money, options)
134
- doc.ip(options[:ip])
135
182
  add_extra_options(:gateway_specific_fields, doc, options)
136
183
  doc.payment_method_token(payment_method_token)
137
184
  doc.retain_on_success(true) if options[:store]
@@ -139,11 +186,11 @@ module ActiveMerchant #:nodoc:
139
186
  end
140
187
 
141
188
  def add_invoice(doc, money, options)
142
- doc.amount amount(money)
189
+ doc.amount amount(money) unless money.nil?
143
190
  doc.currency_code(options[:currency] || currency(money) || default_currency)
144
191
  doc.order_id(options[:order_id])
145
- doc.ip(options[:ip])
146
- doc.description(options[:description])
192
+ doc.ip(options[:ip]) if options[:ip]
193
+ doc.description(options[:description]) if options[:description]
147
194
  end
148
195
 
149
196
  def add_credit_card(doc, credit_card, options)
@@ -244,4 +291,3 @@ module ActiveMerchant #:nodoc:
244
291
  end
245
292
  end
246
293
  end
247
-
@@ -25,7 +25,7 @@ module ActiveMerchant #:nodoc:
25
25
  self.default_currency = 'USD'
26
26
  self.money_format = :cents
27
27
  self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club, :maestro]
28
- self.currencies_without_fractions = %w(BIF CLP DJF GNF JPY KMF KRW MGA PYG RWF VND VUV XAF XOF XPF)
28
+ self.currencies_without_fractions = %w(BIF CLP DJF GNF JPY KMF KRW MGA PYG RWF VND VUV XAF XOF XPF UGX)
29
29
 
30
30
  self.homepage_url = 'https://stripe.com/'
31
31
  self.display_name = 'Stripe'
@@ -43,7 +43,8 @@ module ActiveMerchant #:nodoc:
43
43
  'call_issuer' => STANDARD_ERROR_CODE[:call_issuer],
44
44
  'processing_error' => STANDARD_ERROR_CODE[:processing_error],
45
45
  'incorrect_pin' => STANDARD_ERROR_CODE[:incorrect_pin],
46
- 'test_mode_live_card' => STANDARD_ERROR_CODE[:test_mode_live_card]
46
+ 'test_mode_live_card' => STANDARD_ERROR_CODE[:test_mode_live_card],
47
+ 'pickup_card' => STANDARD_ERROR_CODE[:pickup_card]
47
48
  }
48
49
 
49
50
  BANK_ACCOUNT_HOLDER_TYPE_MAPPING = {
@@ -71,7 +72,6 @@ module ActiveMerchant #:nodoc:
71
72
  requires!(options, :login)
72
73
  @api_key = options[:login]
73
74
  @fee_refund_api_key = options[:fee_refund_login]
74
-
75
75
  super
76
76
  end
77
77
 
@@ -113,6 +113,7 @@ module ActiveMerchant #:nodoc:
113
113
  end
114
114
  r.process do
115
115
  post = create_post_for_auth_or_purchase(money, payment, options)
116
+ post[:card][:processing_method] = 'quick_chip' if quickchip_payment?(payment)
116
117
  commit(:post, 'charges', post, options)
117
118
  end
118
119
  end.responses.last
@@ -127,6 +128,7 @@ module ActiveMerchant #:nodoc:
127
128
  else
128
129
  add_application_fee(post, options)
129
130
  add_amount(post, money, options)
131
+ add_exchange_rate(post, options)
130
132
  commit(:post, "charges/#{CGI.escape(authorization)}/capture", post, options)
131
133
  end
132
134
  end
@@ -149,25 +151,24 @@ module ActiveMerchant #:nodoc:
149
151
  MultiResponse.run(:first) do |r|
150
152
  r.process { commit(:post, "charges/#{CGI.escape(identification)}/refunds", post, options) }
151
153
 
152
- return r unless options[:refund_fee_amount]
153
-
154
- r.process { fetch_application_fees(identification, options) }
155
- r.process { refund_application_fee(options[:refund_fee_amount], application_fee_from_response(r.responses.last), options) }
154
+ if options[:refund_fee_amount] && options[:refund_fee_amount].to_s != '0'
155
+ r.process { fetch_application_fee(identification, options) }
156
+ r.process { refund_application_fee(options[:refund_fee_amount].to_i, application_fee_from_response(r.responses.last), options) }
157
+ end
156
158
  end
157
159
  end
158
160
 
159
161
  def verify(payment, options = {})
160
162
  MultiResponse.run(:use_first_response) do |r|
161
163
  r.process { authorize(auth_minimum_amount(options), payment, options) }
164
+ options[:idempotency_key] = nil
162
165
  r.process(:ignore_result) { void(r.authorization, options) }
163
166
  end
164
167
  end
165
168
 
166
169
  def application_fee_from_response(response)
167
170
  return unless response.success?
168
-
169
- application_fees = response.params["data"].select { |fee| fee["object"] == "application_fee" }
170
- application_fees.first["id"] unless application_fees.empty?
171
+ response.params["application_fee"] unless response.params["application_fee"].empty?
171
172
  end
172
173
 
173
174
  def refund_application_fee(money, identification, options = {})
@@ -175,9 +176,11 @@ module ActiveMerchant #:nodoc:
175
176
 
176
177
  post = {}
177
178
  add_amount(post, money, options)
178
- options.merge!(:key => @fee_refund_api_key)
179
+ options.merge!(:key => @fee_refund_api_key) if @fee_refund_api_key
180
+ options.delete(:stripe_account)
179
181
 
180
- commit(:post, "application_fees/#{CGI.escape(identification)}/refund", post, options)
182
+ refund_fee = commit(:post, "application_fees/#{CGI.escape(identification)}/refunds", post, options)
183
+ application_fee_response!(refund_fee, "Application fee could not be refunded: #{refund_fee.message}")
181
184
  end
182
185
 
183
186
  # Note: creating a new credit card will not change the customer's existing default credit card (use :set_default => true)
@@ -303,7 +306,10 @@ module ActiveMerchant #:nodoc:
303
306
  add_creditcard(post, payment, options)
304
307
  end
305
308
 
306
- unless emv_payment?(payment)
309
+ if emv_payment?(payment)
310
+ add_statement_address(post, options)
311
+ add_emv_metadata(post, payment)
312
+ else
307
313
  add_amount(post, money, options, true)
308
314
  add_customer_data(post, options)
309
315
  post[:description] = options[:description]
@@ -315,6 +321,7 @@ module ActiveMerchant #:nodoc:
315
321
 
316
322
  add_metadata(post, options)
317
323
  add_application_fee(post, options)
324
+ add_exchange_rate(post, options)
318
325
  add_destination(post, options)
319
326
  post
320
327
  end
@@ -329,8 +336,16 @@ module ActiveMerchant #:nodoc:
329
336
  post[:application_fee] = options[:application_fee] if options[:application_fee]
330
337
  end
331
338
 
339
+ def add_exchange_rate(post, options)
340
+ post[:exchange_rate] = options[:exchange_rate] if options[:exchange_rate]
341
+ end
342
+
332
343
  def add_destination(post, options)
333
- post[:destination] = options[:destination] if options[:destination]
344
+ if options[:destination]
345
+ post[:destination] = {}
346
+ post[:destination][:account] = options[:destination]
347
+ post[:destination][:amount] = options[:destination_amount] if options[:destination_amount]
348
+ end
334
349
  end
335
350
 
336
351
  def add_expand_parameters(post, options)
@@ -365,12 +380,23 @@ module ActiveMerchant #:nodoc:
365
380
  end
366
381
  end
367
382
 
383
+ def add_statement_address(post, options)
384
+ return unless statement_address = options[:statement_address]
385
+ return unless [:address1, :city, :zip, :state].all? { |key| statement_address[key].present? }
386
+
387
+ post[:statement_address] = {}
388
+ post[:statement_address][:line1] = statement_address[:address1]
389
+ post[:statement_address][:line2] = statement_address[:address2] if statement_address[:address2].present?
390
+ post[:statement_address][:city] = statement_address[:city]
391
+ post[:statement_address][:postal_code] = statement_address[:zip]
392
+ post[:statement_address][:state] = statement_address[:state]
393
+ end
394
+
368
395
  def add_creditcard(post, creditcard, options)
369
396
  card = {}
370
397
  if emv_payment?(creditcard)
371
398
  add_emv_creditcard(post, creditcard.icc_data)
372
- post[:card][:read_method] = "contactless" if creditcard.contactless_emv
373
- post[:card][:read_method] = "contactless_magstripe_mode" if creditcard.contactless_magstripe
399
+ post[:card][:read_method] = "contactless" if creditcard.read_method == 'contactless'
374
400
  if creditcard.encrypted_pin_cryptogram.present? && creditcard.encrypted_pin_ksn.present?
375
401
  post[:card][:encrypted_pin] = creditcard.encrypted_pin_cryptogram
376
402
  post[:card][:encrypted_pin_key_id] = creditcard.encrypted_pin_ksn
@@ -378,9 +404,11 @@ module ActiveMerchant #:nodoc:
378
404
  elsif creditcard.respond_to?(:number)
379
405
  if creditcard.respond_to?(:track_data) && creditcard.track_data.present?
380
406
  card[:swipe_data] = creditcard.track_data
381
- card[:fallback_reason] = creditcard.fallback_reason if creditcard.fallback_reason
382
- card[:read_method] = "contactless" if creditcard.contactless_emv
383
- post[:read_method] = "contactless_magstripe_mode" if creditcard.contactless_magstripe
407
+ if creditcard.respond_to?(:read_method)
408
+ card[:fallback_reason] = 'no_chip' if creditcard.read_method == 'fallback_no_chip'
409
+ card[:fallback_reason] = 'chip_error' if creditcard.read_method == 'fallback_chip_error'
410
+ card[:read_method] = "contactless_magstripe_mode" if creditcard.read_method == 'contactless_magstripe'
411
+ end
384
412
  else
385
413
  card[:number] = creditcard.number
386
414
  card[:exp_month] = creditcard.month
@@ -432,16 +460,27 @@ module ActiveMerchant #:nodoc:
432
460
  end
433
461
 
434
462
  def add_metadata(post, options = {})
435
- post[:metadata] = options[:metadata] || {}
463
+ post[:metadata] ||= {}
464
+ post[:metadata].merge!(options[:metadata]) if options[:metadata]
436
465
  post[:metadata][:email] = options[:email] if options[:email]
437
466
  post[:metadata][:order_id] = options[:order_id] if options[:order_id]
438
467
  post.delete(:metadata) if post[:metadata].empty?
439
468
  end
440
469
 
441
- def fetch_application_fees(identification, options = {})
470
+ def add_emv_metadata(post, creditcard)
471
+ post[:metadata] ||= {}
472
+ post[:metadata][:card_read_method] = creditcard.read_method if creditcard.respond_to?(:read_method)
473
+ end
474
+
475
+ def fetch_application_fee(identification, options = {})
442
476
  options.merge!(:key => @fee_refund_api_key)
443
477
 
444
- commit(:get, "application_fees?charge=#{identification}", nil, options)
478
+ fetch_charge = commit(:get, "charges/#{CGI.escape(identification)}", nil, options)
479
+ application_fee_response!(fetch_charge, "Application fee id could not be retrieved: #{fetch_charge.message}")
480
+ end
481
+
482
+ def application_fee_response!(response, message)
483
+ response.success? ? response : Response.new(false, message)
445
484
  end
446
485
 
447
486
  def parse(body)
@@ -475,7 +514,7 @@ module ActiveMerchant #:nodoc:
475
514
  "Authorization" => "Basic " + Base64.encode64(key.to_s + ":").strip,
476
515
  "User-Agent" => "Stripe/v1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
477
516
  "Stripe-Version" => api_version(options),
478
- "X-Stripe-Client-User-Agent" => user_agent,
517
+ "X-Stripe-Client-User-Agent" => stripe_client_user_agent(options),
479
518
  "X-Stripe-Client-User-Metadata" => {:ip => options[:ip]}.to_json
480
519
  }
481
520
  headers.merge!("Idempotency-Key" => idempotency_key) if idempotency_key
@@ -483,6 +522,11 @@ module ActiveMerchant #:nodoc:
483
522
  headers
484
523
  end
485
524
 
525
+ def stripe_client_user_agent(options)
526
+ return user_agent unless options[:application]
527
+ JSON.dump(JSON.parse(user_agent).merge!({application: options[:application]}))
528
+ end
529
+
486
530
  def api_version(options)
487
531
  options[:version] || @options[:version] || "2015-04-07"
488
532
  end
@@ -505,14 +549,14 @@ module ActiveMerchant #:nodoc:
505
549
  add_expand_parameters(parameters, options) if parameters
506
550
  response = api_request(method, url, parameters, options)
507
551
 
508
- success = !response.key?("error")
552
+ success = success_from(response)
509
553
 
510
554
  card = card_from_response(response)
511
555
  avs_code = AVS_CODE_TRANSLATOR["line1: #{card["address_line1_check"]}, zip: #{card["address_zip_check"]}"]
512
556
  cvc_code = CVC_CODE_TRANSLATOR[card["cvc_check"]]
513
557
 
514
558
  Response.new(success,
515
- success ? "Transaction approved" : response["error"]["message"],
559
+ message_from(success, response),
516
560
  response,
517
561
  :test => response_is_test?(response),
518
562
  :authorization => authorization_from(success, url, method, response),
@@ -524,7 +568,7 @@ module ActiveMerchant #:nodoc:
524
568
  end
525
569
 
526
570
  def authorization_from(success, url, method, response)
527
- return response["error"]["charge"] unless success
571
+ return response.fetch("error", {})["charge"] unless success
528
572
 
529
573
  if url == "customers"
530
574
  [response["id"], response["sources"]["data"].first["id"]].join("|")
@@ -535,6 +579,14 @@ module ActiveMerchant #:nodoc:
535
579
  end
536
580
  end
537
581
 
582
+ def message_from(success, response)
583
+ success ? "Transaction approved" : response.fetch("error", {"message" => "No error details"})["message"]
584
+ end
585
+
586
+ def success_from(response)
587
+ !response.key?("error") && response["status"] != "failed"
588
+ end
589
+
538
590
  def response_error(raw_response)
539
591
  begin
540
592
  parse(raw_response)
@@ -567,6 +619,10 @@ module ActiveMerchant #:nodoc:
567
619
  payment.respond_to?(:emv?) && payment.emv?
568
620
  end
569
621
 
622
+ def quickchip_payment?(payment)
623
+ payment.respond_to?(:read_method) && payment.read_method == 'contact_quickchip'
624
+ end
625
+
570
626
  def card_from_response(response)
571
627
  response["card"] || response["active_card"] || response["source"] || {}
572
628
  end
@@ -578,6 +634,8 @@ module ActiveMerchant #:nodoc:
578
634
  end
579
635
 
580
636
  def error_code_from(response)
637
+ return STANDARD_ERROR_CODE_MAPPING['processing_error'] unless response['error']
638
+
581
639
  code = response['error']['code']
582
640
  decline_code = response['error']['decline_code'] if code == 'card_declined'
583
641
 
@@ -16,7 +16,6 @@ module ActiveMerchant
16
16
  self.supported_countries = %w(AR AU BR FR DE HK MX NZ SG GB US)
17
17
  self.default_currency = 'USD'
18
18
  self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :maestro, :laser]
19
- self.ssl_version = :TLSv1
20
19
 
21
20
  end
22
21
  end
@@ -1,4 +1,5 @@
1
1
  module ActiveMerchant #:nodoc:
2
+
2
3
  module Billing #:nodoc:
3
4
  class TransFirstGateway < Gateway
4
5
  self.test_url = 'https://ws.cert.transfirst.com'
@@ -16,7 +17,7 @@ module ActiveMerchant #:nodoc:
16
17
  ACTIONS = {
17
18
  purchase: "CCSale",
18
19
  purchase_echeck: "ACHDebit",
19
- refund: "CreditCardAutoRefundorVoid",
20
+ refund: "CreditCardCredit",
20
21
  refund_echeck: "ACHVoidTransaction",
21
22
  void: "CreditCardAutoRefundorVoid",
22
23
  }
@@ -52,6 +53,7 @@ module ActiveMerchant #:nodoc:
52
53
  transaction_id, payment_type = split_authorization(authorization)
53
54
  add_amount(post, money)
54
55
  add_pair(post, :TransID, transaction_id)
56
+ add_pair(post, :RefID, options[:order_id], required: true)
55
57
 
56
58
  commit((payment_type == "check" ? :refund_echeck : :refund), post)
57
59
  end
@@ -169,7 +171,6 @@ module ActiveMerchant #:nodoc:
169
171
 
170
172
  def commit(action, params)
171
173
  response = parse(ssl_post(url(action), post_data(action, params)))
172
-
173
174
  Response.new(
174
175
  success_from(response),
175
176
  message_from(response),