activemerchant 1.126.0 → 1.129.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +241 -0
  3. data/lib/active_merchant/billing/check.rb +40 -8
  4. data/lib/active_merchant/billing/credit_card.rb +28 -1
  5. data/lib/active_merchant/billing/credit_card_methods.rb +79 -23
  6. data/lib/active_merchant/billing/gateways/adyen.rb +67 -8
  7. data/lib/active_merchant/billing/gateways/airwallex.rb +40 -11
  8. data/lib/active_merchant/billing/gateways/alelo.rb +256 -0
  9. data/lib/active_merchant/billing/gateways/authorize_net.rb +21 -4
  10. data/lib/active_merchant/billing/gateways/beanstream.rb +18 -0
  11. data/lib/active_merchant/billing/gateways/blue_snap.rb +22 -1
  12. data/lib/active_merchant/billing/gateways/bogus.rb +4 -0
  13. data/lib/active_merchant/billing/gateways/borgun.rb +56 -16
  14. data/lib/active_merchant/billing/gateways/braintree_blue.rb +64 -17
  15. data/lib/active_merchant/billing/gateways/card_connect.rb +27 -9
  16. data/lib/active_merchant/billing/gateways/card_stream.rb +23 -0
  17. data/lib/active_merchant/billing/gateways/checkout_v2.rb +228 -57
  18. data/lib/active_merchant/billing/gateways/commerce_hub.rb +361 -0
  19. data/lib/active_merchant/billing/gateways/credorax.rb +47 -27
  20. data/lib/active_merchant/billing/gateways/cyber_source/cyber_source_common.rb +36 -0
  21. data/lib/active_merchant/billing/gateways/cyber_source.rb +100 -26
  22. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +456 -0
  23. data/lib/active_merchant/billing/gateways/d_local.rb +44 -5
  24. data/lib/active_merchant/billing/gateways/decidir.rb +15 -4
  25. data/lib/active_merchant/billing/gateways/ebanx.rb +36 -24
  26. data/lib/active_merchant/billing/gateways/element.rb +21 -1
  27. data/lib/active_merchant/billing/gateways/global_collect.rb +73 -22
  28. data/lib/active_merchant/billing/gateways/ipg.rb +13 -8
  29. data/lib/active_merchant/billing/gateways/iveri.rb +39 -3
  30. data/lib/active_merchant/billing/gateways/kushki.rb +21 -1
  31. data/lib/active_merchant/billing/gateways/litle.rb +25 -5
  32. data/lib/active_merchant/billing/gateways/mastercard.rb +1 -8
  33. data/lib/active_merchant/billing/gateways/mercado_pago.rb +17 -0
  34. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +44 -10
  35. data/lib/active_merchant/billing/gateways/monei.rb +2 -0
  36. data/lib/active_merchant/billing/gateways/moneris.rb +20 -5
  37. data/lib/active_merchant/billing/gateways/mundipagg.rb +3 -0
  38. data/lib/active_merchant/billing/gateways/ogone.rb +35 -7
  39. data/lib/active_merchant/billing/gateways/openpay.rb +20 -3
  40. data/lib/active_merchant/billing/gateways/orbital.rb +43 -22
  41. data/lib/active_merchant/billing/gateways/pay_trace.rb +64 -18
  42. data/lib/active_merchant/billing/gateways/payeezy.rb +59 -4
  43. data/lib/active_merchant/billing/gateways/paymentez.rb +18 -6
  44. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +4 -0
  45. data/lib/active_merchant/billing/gateways/paysafe.rb +22 -14
  46. data/lib/active_merchant/billing/gateways/payu_latam.rb +3 -0
  47. data/lib/active_merchant/billing/gateways/plexo.rb +308 -0
  48. data/lib/active_merchant/billing/gateways/priority.rb +29 -6
  49. data/lib/active_merchant/billing/gateways/rapyd.rb +110 -49
  50. data/lib/active_merchant/billing/gateways/reach.rb +277 -0
  51. data/lib/active_merchant/billing/gateways/redsys.rb +9 -5
  52. data/lib/active_merchant/billing/gateways/sage_pay.rb +1 -1
  53. data/lib/active_merchant/billing/gateways/securion_pay.rb +40 -0
  54. data/lib/active_merchant/billing/gateways/shift4.rb +342 -0
  55. data/lib/active_merchant/billing/gateways/simetrik.rb +28 -22
  56. data/lib/active_merchant/billing/gateways/stripe.rb +21 -1
  57. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +62 -22
  58. data/lib/active_merchant/billing/gateways/tns.rb +2 -5
  59. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +1 -1
  60. data/lib/active_merchant/billing/gateways/trust_commerce.rb +14 -3
  61. data/lib/active_merchant/billing/gateways/vanco.rb +12 -3
  62. data/lib/active_merchant/billing/gateways/visanet_peru.rb +1 -1
  63. data/lib/active_merchant/billing/gateways/vpos.rb +7 -4
  64. data/lib/active_merchant/billing/gateways/wompi.rb +8 -4
  65. data/lib/active_merchant/billing/gateways/worldpay.rb +117 -9
  66. data/lib/active_merchant/billing/response.rb +15 -1
  67. data/lib/active_merchant/connection.rb +0 -2
  68. data/lib/active_merchant/country.rb +1 -0
  69. data/lib/active_merchant/errors.rb +4 -1
  70. data/lib/active_merchant/version.rb +1 -1
  71. metadata +24 -3
@@ -9,12 +9,24 @@ module ActiveMerchant #:nodoc:
9
9
  self.supported_countries = %w[AD AE AR AT AU BE BG BH BR CH CL CN CO CY CZ DE DK EE EG ES FI FR GB GR HK HR HU IE IS IT JO JP KW LI LT LU LV MC MT MX MY NL NO NZ OM PE PL PT QA RO SA SE SG SI SK SM TR US]
10
10
  self.default_currency = 'USD'
11
11
  self.money_format = :cents
12
- self.supported_cardtypes = %i[visa master american_express diners_club maestro discover jcb]
12
+ self.supported_cardtypes = %i[visa master american_express diners_club maestro discover jcb mada bp_plus]
13
13
  self.currencies_without_fractions = %w(BIF DJF GNF ISK KMF XAF CLF XPF JPY PYG RWF KRW VUV VND XOF)
14
14
  self.currencies_with_three_decimal_places = %w(BHD LYD JOD KWD OMR TND)
15
15
 
16
+ LIVE_ACCESS_TOKEN_URL = 'https://access.checkout.com/connect/token'
17
+ TEST_ACCESS_TOKEN_URL = 'https://access.sandbox.checkout.com/connect/token'
18
+
16
19
  def initialize(options = {})
17
- requires!(options, :secret_key)
20
+ @options = options
21
+ @access_token = nil
22
+
23
+ if options.has_key?(:secret_key)
24
+ requires!(options, :secret_key)
25
+ else
26
+ requires!(options, :client_id, :client_secret)
27
+ @access_token = setup_access_token
28
+ end
29
+
18
30
  super
19
31
  end
20
32
 
@@ -22,31 +34,44 @@ module ActiveMerchant #:nodoc:
22
34
  post = {}
23
35
  build_auth_or_purchase(post, amount, payment_method, options)
24
36
 
25
- commit(:purchase, post)
37
+ commit(:purchase, post, options)
26
38
  end
27
39
 
28
40
  def authorize(amount, payment_method, options = {})
29
41
  post = {}
30
42
  post[:capture] = false
31
43
  build_auth_or_purchase(post, amount, payment_method, options)
32
-
33
- commit(:authorize, post)
44
+ options[:incremental_authorization] ? commit(:incremental_authorize, post, options, options[:incremental_authorization]) : commit(:authorize, post, options)
34
45
  end
35
46
 
36
47
  def capture(amount, authorization, options = {})
37
48
  post = {}
49
+ post[:capture_type] = options[:capture_type] || 'Final'
38
50
  add_invoice(post, amount, options)
39
51
  add_customer_data(post, options)
52
+ add_shipping_address(post, options)
40
53
  add_metadata(post, options)
41
54
 
42
- commit(:capture, post, authorization)
55
+ commit(:capture, post, options, authorization)
56
+ end
57
+
58
+ def credit(amount, payment, options = {})
59
+ post = {}
60
+ post[:instruction] = {}
61
+ post[:instruction][:funds_transfer_type] = options[:funds_transfer_type] || 'FD'
62
+ add_processing_channel(post, options)
63
+ add_invoice(post, amount, options)
64
+ add_payment_method(post, payment, options, :destination)
65
+ add_source(post, options)
66
+
67
+ commit(:credit, post, options)
43
68
  end
44
69
 
45
70
  def void(authorization, _options = {})
46
71
  post = {}
47
72
  add_metadata(post, options)
48
73
 
49
- commit(:void, post, authorization)
74
+ commit(:void, post, options, authorization)
50
75
  end
51
76
 
52
77
  def refund(amount, authorization, options = {})
@@ -55,7 +80,7 @@ module ActiveMerchant #:nodoc:
55
80
  add_customer_data(post, options)
56
81
  add_metadata(post, options)
57
82
 
58
- commit(:refund, post, authorization)
83
+ commit(:refund, post, options, authorization)
59
84
  end
60
85
 
61
86
  def verify(credit_card, options = {})
@@ -63,7 +88,7 @@ module ActiveMerchant #:nodoc:
63
88
  end
64
89
 
65
90
  def verify_payment(authorization, option = {})
66
- commit(:verify_payment, authorization)
91
+ commit(:verify_payment, nil, options, authorization, :get)
67
92
  end
68
93
 
69
94
  def supports_scrubbing?
@@ -74,19 +99,51 @@ module ActiveMerchant #:nodoc:
74
99
  transcript.
75
100
  gsub(/(Authorization: )[^\\]*/i, '\1[FILTERED]').
76
101
  gsub(/("number\\":\\")\d+/, '\1[FILTERED]').
77
- gsub(/("cvv\\":\\")\d+/, '\1[FILTERED]')
102
+ gsub(/("cvv\\":\\")\d+/, '\1[FILTERED]').
103
+ gsub(/("cryptogram\\":\\")\w+/, '\1[FILTERED]').
104
+ gsub(/(source\\":\{.*\\"token\\":\\")\d+/, '\1[FILTERED]').
105
+ gsub(/("token\\":\\")\w+/, '\1[FILTERED]')
106
+ end
107
+
108
+ def store(payment_method, options = {})
109
+ post = {}
110
+ MultiResponse.run do |r|
111
+ if payment_method.is_a?(NetworkTokenizationCreditCard)
112
+ r.process { verify(payment_method, options) }
113
+ break r unless r.success?
114
+
115
+ r.params['source']['customer'] = r.params['customer']
116
+ r.process { response(:store, true, r.params['source']) }
117
+ else
118
+ r.process { tokenize(payment_method, options) }
119
+ break r unless r.success?
120
+
121
+ token = r.params['token']
122
+ add_payment_method(post, token, options)
123
+ post.merge!(post.delete(:source))
124
+ add_customer_data(post, options)
125
+ add_shipping_address(post, options)
126
+ r.process { commit(:store, post, options) }
127
+ end
128
+ end
129
+ end
130
+
131
+ def unstore(id, options = {})
132
+ commit(:unstore, nil, options, id, :delete)
78
133
  end
79
134
 
80
135
  private
81
136
 
82
137
  def build_auth_or_purchase(post, amount, payment_method, options)
83
138
  add_invoice(post, amount, options)
139
+ add_authorization_type(post, options)
84
140
  add_payment_method(post, payment_method, options)
85
141
  add_customer_data(post, options)
142
+ add_shipping_address(post, options)
86
143
  add_stored_credential_options(post, options)
87
144
  add_transaction_data(post, options)
88
145
  add_3ds(post, options)
89
- add_metadata(post, options)
146
+ add_metadata(post, options, payment_method)
90
147
  add_processing_channel(post, options)
91
148
  add_marketplace_data(post, options)
92
149
  end
@@ -104,33 +161,66 @@ module ActiveMerchant #:nodoc:
104
161
  post[:metadata][:udf5] = application_id || 'ActiveMerchant'
105
162
  end
106
163
 
107
- def add_metadata(post, options)
164
+ def add_authorization_type(post, options)
165
+ post[:authorization_type] = options[:authorization_type] if options[:authorization_type]
166
+ end
167
+
168
+ def add_metadata(post, options, payment_method = nil)
108
169
  post[:metadata] = {} unless post[:metadata]
109
170
  post[:metadata].merge!(options[:metadata]) if options[:metadata]
171
+ post[:metadata][:udf1] = 'mada' if payment_method.try(:brand) == 'mada'
110
172
  end
111
173
 
112
- def add_payment_method(post, payment_method, options)
113
- post[:source] = {}
114
- if payment_method.is_a?(NetworkTokenizationCreditCard)
174
+ def add_payment_method(post, payment_method, options, key = :source)
175
+ post[key] = {}
176
+ case payment_method
177
+ when NetworkTokenizationCreditCard
115
178
  token_type = token_type_from(payment_method)
116
179
  cryptogram = payment_method.payment_cryptogram
117
180
  eci = payment_method.eci || options[:eci]
118
181
  eci ||= '05' if token_type == 'vts'
119
182
 
120
- post[:source][:type] = 'network_token'
121
- post[:source][:token] = payment_method.number
122
- post[:source][:token_type] = token_type
123
- post[:source][:cryptogram] = cryptogram if cryptogram
124
- post[:source][:eci] = eci if eci
125
- else
126
- post[:source][:type] = 'card'
127
- post[:source][:name] = payment_method.name
128
- post[:source][:number] = payment_method.number
129
- post[:source][:cvv] = payment_method.verification_value
130
- post[:source][:stored] = 'true' if options[:card_on_file] == true
183
+ post[key][:type] = 'network_token'
184
+ post[key][:token] = payment_method.number
185
+ post[key][:token_type] = token_type
186
+ post[key][:cryptogram] = cryptogram if cryptogram
187
+ post[key][:eci] = eci if eci
188
+ when CreditCard
189
+ post[key][:type] = 'card'
190
+ post[key][:name] = payment_method.name
191
+ post[key][:number] = payment_method.number
192
+ post[key][:cvv] = payment_method.verification_value
193
+ post[key][:stored] = 'true' if options[:card_on_file] == true
194
+ if options[:account_holder_type]
195
+ post[key][:account_holder] = {}
196
+ post[key][:account_holder][:type] = options[:account_holder_type]
197
+ post[key][:account_holder][:first_name] = payment_method.first_name if payment_method.first_name
198
+ post[key][:account_holder][:last_name] = payment_method.last_name if payment_method.last_name
199
+ else
200
+ post[key][:first_name] = payment_method.first_name if payment_method.first_name
201
+ post[key][:last_name] = payment_method.last_name if payment_method.last_name
202
+ end
203
+ end
204
+ if payment_method.is_a?(String)
205
+ if /tok/.match?(payment_method)
206
+ post[:type] = 'token'
207
+ post[:token] = payment_method
208
+ elsif /src/.match?(payment_method)
209
+ post[key][:type] = 'id'
210
+ post[key][:id] = payment_method
211
+ else
212
+ add_source(post, options)
213
+ end
214
+ elsif payment_method.try(:year)
215
+ post[key][:expiry_year] = format(payment_method.year, :four_digits)
216
+ post[key][:expiry_month] = format(payment_method.month, :two_digits)
131
217
  end
132
- post[:source][:expiry_year] = format(payment_method.year, :four_digits)
133
- post[:source][:expiry_month] = format(payment_method.month, :two_digits)
218
+ end
219
+
220
+ def add_source(post, options)
221
+ post[:source] = {}
222
+ post[:source][:type] = options[:source_type] if options[:source_type]
223
+ post[:source][:id] = options[:source_id] if options[:source_id]
134
224
  end
135
225
 
136
226
  def add_customer_data(post, options)
@@ -149,6 +239,19 @@ module ActiveMerchant #:nodoc:
149
239
  end
150
240
  end
151
241
 
242
+ def add_shipping_address(post, options)
243
+ if address = options[:shipping_address]
244
+ post[:shipping] = {}
245
+ post[:shipping][:address] = {}
246
+ post[:shipping][:address][:address_line1] = address[:address1] unless address[:address1].blank?
247
+ post[:shipping][:address][:address_line2] = address[:address2] unless address[:address2].blank?
248
+ post[:shipping][:address][:city] = address[:city] unless address[:city].blank?
249
+ post[:shipping][:address][:state] = address[:state] unless address[:state].blank?
250
+ post[:shipping][:address][:country] = address[:country] unless address[:country].blank?
251
+ post[:shipping][:address][:zip] = address[:zip] unless address[:zip].blank?
252
+ end
253
+ end
254
+
152
255
  def add_transaction_data(post, options = {})
153
256
  post[:payment_type] = 'Regular' if options[:transaction_indicator] == 1
154
257
  post[:payment_type] = 'Recurring' if options[:transaction_indicator] == 2
@@ -156,23 +259,31 @@ module ActiveMerchant #:nodoc:
156
259
  post[:previous_payment_id] = options[:previous_charge_id] if options[:previous_charge_id]
157
260
  end
158
261
 
159
- def add_stored_credential_options(post, options = {})
160
- return unless options[:stored_credential]
262
+ def merchant_initiated_override(post, options)
263
+ post[:merchant_initiated] = true
264
+ post[:source][:stored] = true
265
+ post[:previous_payment_id] = options[:merchant_initiated_transaction_id]
266
+ end
161
267
 
162
- case options[:stored_credential][:initial_transaction]
163
- when true
268
+ def add_stored_credentials_using_normalized_fields(post, options)
269
+ if options[:stored_credential][:initial_transaction] == true
164
270
  post[:merchant_initiated] = false
165
- when false
166
- post[:'source.stored'] = true
271
+ else
272
+ post[:source][:stored] = true
167
273
  post[:previous_payment_id] = options[:stored_credential][:network_transaction_id] if options[:stored_credential][:network_transaction_id]
168
274
  post[:merchant_initiated] = true
169
275
  end
276
+ end
277
+
278
+ def add_stored_credential_options(post, options = {})
279
+ return unless options[:stored_credential]
280
+
281
+ post[:payment_type] = 'Recurring' if %w(recurring installment).include? options[:stored_credential][:reason_type]
170
282
 
171
- case options[:stored_credential][:reason_type]
172
- when 'recurring', 'installment'
173
- post[:payment_type] = 'Recurring'
174
- when 'unscheduled'
175
- return
283
+ if options[:merchant_initiated_transaction_id]
284
+ merchant_initiated_override(post, options)
285
+ else
286
+ add_stored_credentials_using_normalized_fields(post, options)
176
287
  end
177
288
  end
178
289
 
@@ -183,6 +294,8 @@ module ActiveMerchant #:nodoc:
183
294
  post[:success_url] = options[:callback_url] if options[:callback_url]
184
295
  post[:failure_url] = options[:callback_url] if options[:callback_url]
185
296
  post[:'3ds'][:attempt_n3d] = options[:attempt_n3d] if options[:attempt_n3d]
297
+ post[:'3ds'][:challenge_indicator] = options[:challenge_indicator] if options[:challenge_indicator]
298
+ post[:'3ds'][:exemption] = options[:exemption] if options[:exemption]
186
299
  end
187
300
 
188
301
  if options[:three_d_secure]
@@ -190,6 +303,7 @@ module ActiveMerchant #:nodoc:
190
303
  post[:'3ds'][:cryptogram] = options[:three_d_secure][:cavv] if options[:three_d_secure][:cavv]
191
304
  post[:'3ds'][:version] = options[:three_d_secure][:version] if options[:three_d_secure][:version]
192
305
  post[:'3ds'][:xid] = options[:three_d_secure][:ds_transaction_id] || options[:three_d_secure][:xid]
306
+ post[:'3ds'][:status] = options[:three_d_secure][:authentication_response_status]
193
307
  end
194
308
  end
195
309
 
@@ -204,55 +318,95 @@ module ActiveMerchant #:nodoc:
204
318
  end
205
319
  end
206
320
 
207
- def commit(action, post, authorization = nil)
321
+ def access_token_header
322
+ {
323
+ 'Authorization' => "Basic #{Base64.encode64("#{@options[:client_id]}:#{@options[:client_secret]}").delete("\n")}",
324
+ 'Content-Type' => 'application/x-www-form-urlencoded'
325
+ }
326
+ end
327
+
328
+ def access_token_url
329
+ test? ? TEST_ACCESS_TOKEN_URL : LIVE_ACCESS_TOKEN_URL
330
+ end
331
+
332
+ def setup_access_token
333
+ request = 'grant_type=client_credentials'
334
+ response = parse(ssl_post(access_token_url, request, access_token_header))
335
+ response['access_token']
336
+ end
337
+
338
+ def commit(action, post, options, authorization = nil, method = :post)
208
339
  begin
209
- raw_response = (action == :verify_payment ? ssl_get("#{base_url}/payments/#{post}", headers) : ssl_post(url(post, action, authorization), post.to_json, headers))
340
+ raw_response = ssl_request(method, url(action, authorization), post.nil? || post.empty? ? nil : post.to_json, headers(action, options))
210
341
  response = parse(raw_response)
211
342
  response['id'] = response['_links']['payment']['href'].split('/')[-1] if action == :capture && response.key?('_links')
343
+ source_id = authorization if action == :unstore
212
344
  rescue ResponseError => e
213
345
  raise unless e.response.code.to_s =~ /4\d\d/
214
346
 
215
347
  response = parse(e.response.body, error: e.response)
216
348
  end
217
349
 
218
- succeeded = success_from(response)
350
+ succeeded = success_from(action, response)
219
351
 
220
- response(action, succeeded, response)
352
+ response(action, succeeded, response, source_id)
221
353
  end
222
354
 
223
- def response(action, succeeded, response)
355
+ def response(action, succeeded, response, source_id = nil)
224
356
  successful_response = succeeded && action == :purchase || action == :authorize
225
357
  avs_result = successful_response ? avs_result(response) : nil
226
358
  cvv_result = successful_response ? cvv_result(response) : nil
227
-
359
+ authorization = authorization_from(response) unless action == :unstore
360
+ body = action == :unstore ? { response_code: response.to_s } : response
228
361
  Response.new(
229
362
  succeeded,
230
363
  message_from(succeeded, response),
231
- response,
232
- authorization: authorization_from(response),
233
- error_code: error_code_from(succeeded, response),
364
+ body,
365
+ authorization: authorization,
366
+ error_code: error_code_from(succeeded, body),
234
367
  test: test?,
235
368
  avs_result: avs_result,
236
369
  cvv_result: cvv_result
237
370
  )
238
371
  end
239
372
 
240
- def headers
241
- {
242
- 'Authorization' => @options[:secret_key],
373
+ def headers(action, options)
374
+ auth_token = @access_token ? "Bearer #{@access_token}" : @options[:secret_key]
375
+ auth_token = @options[:public_key] if action == :tokens
376
+ headers = {
377
+ 'Authorization' => auth_token,
243
378
  'Content-Type' => 'application/json;charset=UTF-8'
244
379
  }
380
+ headers['Cko-Idempotency-Key'] = options[:idempotency_key] if options[:idempotency_key]
381
+ headers
245
382
  end
246
383
 
247
- def url(_post, action, authorization)
248
- if %i[authorize purchase].include?(action)
384
+ def tokenize(payment_method, options = {})
385
+ post = {}
386
+ add_authorization_type(post, options)
387
+ add_payment_method(post, payment_method, options)
388
+ add_customer_data(post, options)
389
+ commit(:tokens, post[:source], options)
390
+ end
391
+
392
+ def url(action, authorization)
393
+ case action
394
+ when :authorize, :purchase, :credit
249
395
  "#{base_url}/payments"
250
- elsif action == :capture
396
+ when :unstore, :store
397
+ "#{base_url}/instruments/#{authorization}"
398
+ when :capture
251
399
  "#{base_url}/payments/#{authorization}/captures"
252
- elsif action == :refund
400
+ when :refund
253
401
  "#{base_url}/payments/#{authorization}/refunds"
254
- elsif action == :void
402
+ when :void
255
403
  "#{base_url}/payments/#{authorization}/voids"
404
+ when :incremental_authorize
405
+ "#{base_url}/payments/#{authorization}/authorizations"
406
+ when :tokens
407
+ "#{base_url}/tokens"
408
+ when :verify_payment
409
+ "#{base_url}/payments/#{authorization}"
256
410
  else
257
411
  "#{base_url}/payments/#{authorization}/#{action}"
258
412
  end
@@ -282,7 +436,14 @@ module ActiveMerchant #:nodoc:
282
436
  response
283
437
  end
284
438
 
285
- def success_from(response)
439
+ def success_from(action, response)
440
+ return response['status'] == 'Pending' if action == :credit
441
+ return true if action == :unstore && response == 204
442
+
443
+ store_response = response['token'] || response['id']
444
+ if store_response
445
+ return true if (action == :tokens && store_response.match(/tok/)) || (action == :store && store_response.match(/src_/))
446
+ end
286
447
  response['response_summary'] == 'Approved' || response['approved'] == true || !response.key?('response_summary') && response.key?('action_id')
287
448
  end
288
449
 
@@ -335,6 +496,16 @@ module ActiveMerchant #:nodoc:
335
496
  'applepay'
336
497
  end
337
498
  end
499
+
500
+ def handle_response(response)
501
+ case response.code.to_i
502
+ # to get the response code after unstore(delete instrument), because the body is nil
503
+ when 200...300
504
+ response.body || response.code
505
+ else
506
+ raise ResponseError.new(response)
507
+ end
508
+ end
338
509
  end
339
510
  end
340
511
  end