activemerchant 1.126.0 → 1.129.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 (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