activemerchant 1.121.0 → 1.123.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.
- checksums.yaml +4 -4
- data/CHANGELOG +86 -0
- data/README.md +1 -1
- data/lib/active_merchant/billing/check.rb +13 -16
- data/lib/active_merchant/billing/credit_card.rb +3 -0
- data/lib/active_merchant/billing/credit_card_formatting.rb +1 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +21 -12
- data/lib/active_merchant/billing/gateways/adyen.rb +15 -19
- data/lib/active_merchant/billing/gateways/authorize_net.rb +10 -8
- data/lib/active_merchant/billing/gateways/blue_pay.rb +29 -0
- data/lib/active_merchant/billing/gateways/blue_snap.rb +2 -2
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +6 -3
- data/lib/active_merchant/billing/gateways/credorax.rb +2 -1
- data/lib/active_merchant/billing/gateways/cyber_source.rb +30 -3
- data/lib/active_merchant/billing/gateways/decidir.rb +7 -1
- data/lib/active_merchant/billing/gateways/elavon.rb +60 -28
- data/lib/active_merchant/billing/gateways/element.rb +2 -0
- data/lib/active_merchant/billing/gateways/global_collect.rb +19 -10
- data/lib/active_merchant/billing/gateways/kushki.rb +23 -0
- data/lib/active_merchant/billing/gateways/mercado_pago.rb +3 -2
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -0
- data/lib/active_merchant/billing/gateways/moka.rb +277 -0
- data/lib/active_merchant/billing/gateways/monei.rb +228 -144
- data/lib/active_merchant/billing/gateways/mundipagg.rb +14 -5
- data/lib/active_merchant/billing/gateways/nmi.rb +14 -9
- data/lib/active_merchant/billing/gateways/orbital.rb +28 -6
- data/lib/active_merchant/billing/gateways/pay_arc.rb +390 -0
- data/lib/active_merchant/billing/gateways/pay_trace.rb +404 -0
- data/lib/active_merchant/billing/gateways/payeezy.rb +4 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +9 -0
- data/lib/active_merchant/billing/gateways/payment_express.rb +2 -2
- data/lib/active_merchant/billing/gateways/paymentez.rb +5 -0
- data/lib/active_merchant/billing/gateways/paysafe.rb +291 -0
- data/lib/active_merchant/billing/gateways/payu_latam.rb +3 -3
- data/lib/active_merchant/billing/gateways/redsys.rb +35 -32
- data/lib/active_merchant/billing/gateways/safe_charge.rb +2 -0
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +13 -4
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +19 -1
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +1 -1
- data/lib/active_merchant/billing/gateways/vpos.rb +49 -6
- data/lib/active_merchant/billing/gateways/worldpay.rb +39 -7
- data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
- data/lib/active_merchant/billing.rb +1 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +8 -3
@@ -386,7 +386,7 @@ module ActiveMerchant
|
|
386
386
|
|
387
387
|
def parse(response)
|
388
388
|
return bad_authentication_response if response.code.to_i == 401
|
389
|
-
return
|
389
|
+
return generic_error_response(response.body) if [403, 429].include?(response.code.to_i)
|
390
390
|
|
391
391
|
parsed = {}
|
392
392
|
doc = Nokogiri::XML(response.body)
|
@@ -564,7 +564,7 @@ module ActiveMerchant
|
|
564
564
|
{ 'description' => 'Unable to authenticate. Please check your credentials.' }
|
565
565
|
end
|
566
566
|
|
567
|
-
def
|
567
|
+
def generic_error_response(body)
|
568
568
|
{ 'description' => body }
|
569
569
|
end
|
570
570
|
end
|
@@ -135,8 +135,8 @@ module ActiveMerchant #:nodoc:
|
|
135
135
|
result = @braintree_gateway.verification.create(payload)
|
136
136
|
response = Response.new(result.success?, message_from_transaction_result(result), response_options(result))
|
137
137
|
response.cvv_result['message'] = ''
|
138
|
-
response.cvv_result['code'] = response.params['cvv_result']
|
139
|
-
response.avs_result['code'] = response.params['avs_result'][:code]
|
138
|
+
response.cvv_result['code'] = response.params['cvv_result'] if response.params['cvv_result']
|
139
|
+
response.avs_result['code'] = response.params['avs_result'][:code] if response.params.dig('avs_result', :code)
|
140
140
|
response
|
141
141
|
end
|
142
142
|
|
@@ -588,7 +588,8 @@ module ActiveMerchant #:nodoc:
|
|
588
588
|
'merchant_account_id' => transaction.merchant_account_id,
|
589
589
|
'risk_data' => risk_data,
|
590
590
|
'network_transaction_id' => transaction.network_transaction_id || nil,
|
591
|
-
'processor_response_code' => response_code_from_result(result)
|
591
|
+
'processor_response_code' => response_code_from_result(result),
|
592
|
+
'recurring' => transaction.recurring
|
592
593
|
}
|
593
594
|
end
|
594
595
|
|
@@ -770,6 +771,8 @@ module ActiveMerchant #:nodoc:
|
|
770
771
|
else
|
771
772
|
parameters[:transaction_source] = stored_credential[:reason_type]
|
772
773
|
end
|
774
|
+
elsif %w(recurring_first moto).include?(stored_credential[:reason_type])
|
775
|
+
parameters[:transaction_source] = stored_credential[:reason_type]
|
773
776
|
else
|
774
777
|
parameters[:transaction_source] = ''
|
775
778
|
end
|
@@ -20,8 +20,9 @@ module ActiveMerchant #:nodoc:
|
|
20
20
|
self.live_url = 'https://assigned-subdomain.credorax.net/crax_gate/service/gateway'
|
21
21
|
|
22
22
|
self.supported_countries = %w(AD AT BE BG HR CY CZ DK EE FR DE GI GR GG HU IS IE IM IT JE LV LI LT LU MT MC NO PL PT RO SM SK ES SE CH GB)
|
23
|
+
|
23
24
|
self.default_currency = 'EUR'
|
24
|
-
self.currencies_without_fractions = %w(BIF CLP DJF GNF JPY KMF KRW PYG RWF VND VUV XAF XOF XPF)
|
25
|
+
self.currencies_without_fractions = %w(BIF CLP DJF GNF ISK JPY KMF KRW PYG RWF VND VUV XAF XOF XPF)
|
25
26
|
self.currencies_with_three_decimal_places = %w(BHD IQD JOD KWD LYD OMR TND)
|
26
27
|
|
27
28
|
self.money_format = :cents
|
@@ -153,6 +153,10 @@ module ActiveMerchant #:nodoc:
|
|
153
153
|
commit(build_refund_request(money, identification, options), :refund, money, options)
|
154
154
|
end
|
155
155
|
|
156
|
+
def adjust(money, authorization, options = {})
|
157
|
+
commit(build_adjust_request(money, authorization, options), :adjust, money, options)
|
158
|
+
end
|
159
|
+
|
156
160
|
def verify(payment, options = {})
|
157
161
|
MultiResponse.run(:use_first_response) do |r|
|
158
162
|
r.process { authorize(100, payment, options) }
|
@@ -285,6 +289,7 @@ module ActiveMerchant #:nodoc:
|
|
285
289
|
|
286
290
|
def build_auth_request(money, creditcard_or_reference, options)
|
287
291
|
xml = Builder::XmlMarkup.new indent: 2
|
292
|
+
add_customer_id(xml, options)
|
288
293
|
add_payment_method_or_subscription(xml, money, creditcard_or_reference, options)
|
289
294
|
add_threeds_2_ucaf_data(xml, creditcard_or_reference, options)
|
290
295
|
add_decision_manager_fields(xml, options)
|
@@ -300,7 +305,15 @@ module ActiveMerchant #:nodoc:
|
|
300
305
|
add_merchant_description(xml, options)
|
301
306
|
add_sales_slip_number(xml, options)
|
302
307
|
add_airline_data(xml, options)
|
308
|
+
xml.target!
|
309
|
+
end
|
303
310
|
|
311
|
+
def build_adjust_request(money, authorization, options)
|
312
|
+
_, request_id = authorization.split(';')
|
313
|
+
|
314
|
+
xml = Builder::XmlMarkup.new indent: 2
|
315
|
+
add_purchase_data(xml, money, true, options)
|
316
|
+
add_incremental_auth_service(xml, request_id, options)
|
304
317
|
xml.target!
|
305
318
|
end
|
306
319
|
|
@@ -334,6 +347,7 @@ module ActiveMerchant #:nodoc:
|
|
334
347
|
|
335
348
|
def build_purchase_request(money, payment_method_or_reference, options)
|
336
349
|
xml = Builder::XmlMarkup.new indent: 2
|
350
|
+
add_customer_id(xml, options)
|
337
351
|
add_payment_method_or_subscription(xml, money, payment_method_or_reference, options)
|
338
352
|
add_threeds_2_ucaf_data(xml, payment_method_or_reference, options)
|
339
353
|
add_decision_manager_fields(xml, options)
|
@@ -472,8 +486,8 @@ module ActiveMerchant #:nodoc:
|
|
472
486
|
|
473
487
|
unless network_tokenization?(payment_method)
|
474
488
|
xml.tag! 'businessRules' do
|
475
|
-
xml.tag!('ignoreAVSResult', 'true') if extract_option(prioritized_options, :ignore_avs)
|
476
|
-
xml.tag!('ignoreCVResult', 'true') if extract_option(prioritized_options, :ignore_cvv)
|
489
|
+
xml.tag!('ignoreAVSResult', 'true') if extract_option(prioritized_options, :ignore_avs).to_s == 'true'
|
490
|
+
xml.tag!('ignoreCVResult', 'true') if extract_option(prioritized_options, :ignore_cvv).to_s == 'true'
|
477
491
|
end
|
478
492
|
end
|
479
493
|
end
|
@@ -515,6 +529,12 @@ module ActiveMerchant #:nodoc:
|
|
515
529
|
end
|
516
530
|
end
|
517
531
|
|
532
|
+
def add_customer_id(xml, options)
|
533
|
+
return unless options[:customer_id]
|
534
|
+
|
535
|
+
xml.tag! 'customerID', options[:customer_id]
|
536
|
+
end
|
537
|
+
|
518
538
|
def add_merchant_description(xml, options)
|
519
539
|
return unless options[:merchant_descriptor_name] || options[:merchant_descriptor_address1] || options[:merchant_descriptor_locality]
|
520
540
|
|
@@ -585,7 +605,7 @@ module ActiveMerchant #:nodoc:
|
|
585
605
|
xml.tag! 'accountNumber', creditcard.number
|
586
606
|
xml.tag! 'expirationMonth', format(creditcard.month, :two_digits)
|
587
607
|
xml.tag! 'expirationYear', format(creditcard.year, :four_digits)
|
588
|
-
xml.tag!('cvNumber', creditcard.verification_value) unless @options[:ignore_cvv] || creditcard.verification_value.blank?
|
608
|
+
xml.tag!('cvNumber', creditcard.verification_value) unless @options[:ignore_cvv].to_s == 'true' || creditcard.verification_value.blank?
|
589
609
|
xml.tag! 'cardType', @@credit_card_codes[card_brand(creditcard).to_sym]
|
590
610
|
end
|
591
611
|
end
|
@@ -658,6 +678,13 @@ module ActiveMerchant #:nodoc:
|
|
658
678
|
end
|
659
679
|
end
|
660
680
|
|
681
|
+
def add_incremental_auth_service(xml, authorization, options)
|
682
|
+
xml.tag! 'ccIncrementalAuthService', { 'run' => 'true' } do
|
683
|
+
xml.tag! 'authRequestID', authorization
|
684
|
+
end
|
685
|
+
xml.tag! 'subsequentAuthReason', options[:auth_reason]
|
686
|
+
end
|
687
|
+
|
661
688
|
def add_normalized_threeds_2_data(xml, payment_method, options)
|
662
689
|
threeds_2_options = options[:three_d_secure]
|
663
690
|
cc_brand = card_brand(payment_method).to_sym
|
@@ -282,7 +282,13 @@ module ActiveMerchant #:nodoc:
|
|
282
282
|
if error = response.dig('status_details', 'error')
|
283
283
|
message = "#{error.dig('reason', 'description')} | #{error['type']}"
|
284
284
|
elsif response['error_type']
|
285
|
-
|
285
|
+
if response['validation_errors'].is_a?(Array)
|
286
|
+
message = response['validation_errors'].map { |errors| "#{errors['code']}: #{errors['param']}" }.join(', ')
|
287
|
+
elsif response['validation_errors'].is_a?(Hash)
|
288
|
+
errors = response['validation_errors'].map { |k, v| "#{k}: #{v}" }.join(', ')
|
289
|
+
message = "#{response['error_type']} - #{errors}"
|
290
|
+
end
|
291
|
+
|
286
292
|
message ||= response['error_type']
|
287
293
|
end
|
288
294
|
|
@@ -201,8 +201,8 @@ module ActiveMerchant #:nodoc:
|
|
201
201
|
private
|
202
202
|
|
203
203
|
def add_invoice(xml, options)
|
204
|
-
xml.ssl_invoice_number
|
205
|
-
xml.ssl_description
|
204
|
+
xml.ssl_invoice_number url_encode_truncate((options[:order_id] || options[:invoice]), 25)
|
205
|
+
xml.ssl_description url_encode_truncate(options[:description], 255)
|
206
206
|
end
|
207
207
|
|
208
208
|
def add_approval_code(xml, authorization)
|
@@ -219,8 +219,8 @@ module ActiveMerchant #:nodoc:
|
|
219
219
|
|
220
220
|
add_verification_value(xml, creditcard) if creditcard.verification_value?
|
221
221
|
|
222
|
-
xml.ssl_first_name
|
223
|
-
xml.ssl_last_name
|
222
|
+
xml.ssl_first_name url_encode_truncate(creditcard.first_name, 20)
|
223
|
+
xml.ssl_last_name url_encode_truncate(creditcard.last_name, 30)
|
224
224
|
end
|
225
225
|
|
226
226
|
def add_currency(xml, money, options)
|
@@ -240,7 +240,7 @@ module ActiveMerchant #:nodoc:
|
|
240
240
|
end
|
241
241
|
|
242
242
|
def add_customer_email(xml, options)
|
243
|
-
xml.ssl_email
|
243
|
+
xml.ssl_email url_encode_truncate(options[:email], 100) unless empty?(options[:email])
|
244
244
|
end
|
245
245
|
|
246
246
|
def add_salestax(xml, options)
|
@@ -253,27 +253,27 @@ module ActiveMerchant #:nodoc:
|
|
253
253
|
billing_address = options[:billing_address] || options[:address]
|
254
254
|
|
255
255
|
if billing_address
|
256
|
-
xml.ssl_avs_address
|
257
|
-
xml.ssl_address2
|
258
|
-
xml.ssl_avs_zip
|
259
|
-
xml.ssl_city
|
260
|
-
xml.ssl_state
|
261
|
-
xml.ssl_company
|
262
|
-
xml.ssl_phone
|
263
|
-
xml.ssl_country
|
256
|
+
xml.ssl_avs_address url_encode_truncate(billing_address[:address1], 30)
|
257
|
+
xml.ssl_address2 url_encode_truncate(billing_address[:address2], 30)
|
258
|
+
xml.ssl_avs_zip url_encode_truncate(billing_address[:zip].to_s.gsub(/[^a-zA-Z0-9]/, ''), 9)
|
259
|
+
xml.ssl_city url_encode_truncate(billing_address[:city], 30)
|
260
|
+
xml.ssl_state url_encode_truncate(billing_address[:state], 10)
|
261
|
+
xml.ssl_company url_encode_truncate(billing_address[:company], 50)
|
262
|
+
xml.ssl_phone url_encode_truncate(billing_address[:phone], 20)
|
263
|
+
xml.ssl_country url_encode_truncate(billing_address[:country], 50)
|
264
264
|
end
|
265
265
|
|
266
266
|
if shipping_address = options[:shipping_address]
|
267
|
-
xml.ssl_ship_to_address1
|
268
|
-
xml.ssl_ship_to_address2
|
269
|
-
xml.ssl_ship_to_city
|
270
|
-
xml.ssl_ship_to_company
|
271
|
-
xml.ssl_ship_to_country
|
272
|
-
xml.ssl_ship_to_first_name
|
273
|
-
xml.ssl_ship_to_last_name
|
274
|
-
xml.ssl_ship_to_phone
|
275
|
-
xml.ssl_ship_to_state
|
276
|
-
xml.ssl_ship_to_zip
|
267
|
+
xml.ssl_ship_to_address1 url_encode_truncate(shipping_address[:address1], 30)
|
268
|
+
xml.ssl_ship_to_address2 url_encode_truncate(shipping_address[:address2], 30)
|
269
|
+
xml.ssl_ship_to_city url_encode_truncate(shipping_address[:city], 30)
|
270
|
+
xml.ssl_ship_to_company url_encode_truncate(shipping_address[:company], 50)
|
271
|
+
xml.ssl_ship_to_country url_encode_truncate(shipping_address[:country], 50)
|
272
|
+
xml.ssl_ship_to_first_name url_encode_truncate(shipping_address[:first_name], 20)
|
273
|
+
xml.ssl_ship_to_last_name url_encode_truncate(shipping_address[:last_name], 30)
|
274
|
+
xml.ssl_ship_to_phone url_encode_truncate(shipping_address[:phone], 10)
|
275
|
+
xml.ssl_ship_to_state url_encode_truncate(shipping_address[:state], 2)
|
276
|
+
xml.ssl_ship_to_zip url_encode_truncate(shipping_address[:zip], 10)
|
277
277
|
end
|
278
278
|
end
|
279
279
|
|
@@ -293,9 +293,12 @@ module ActiveMerchant #:nodoc:
|
|
293
293
|
xml.ssl_cardholder_ip options[:ip] if options.has_key?(:ip)
|
294
294
|
end
|
295
295
|
|
296
|
+
# add_recurring_token is a field that can be sent in to obtain a token from Elavon for use with their tokenization program
|
296
297
|
def add_auth_purchase_params(xml, options)
|
297
298
|
xml.ssl_dynamic_dba options[:dba] if options.has_key?(:dba)
|
298
299
|
xml.ssl_merchant_initiated_unscheduled merchant_initiated_unscheduled(options) if merchant_initiated_unscheduled(options)
|
300
|
+
xml.ssl_add_token options[:add_recurring_token] if options.has_key?(:add_recurring_token)
|
301
|
+
xml.ssl_token options[:ssl_token] if options.has_key?(:ssl_token)
|
299
302
|
xml.ssl_customer_code options[:customer] if options.has_key?(:customer)
|
300
303
|
xml.ssl_customer_number options[:customer_number] if options.has_key?(:customer_number)
|
301
304
|
xml.ssl_entry_mode entry_mode(options) if entry_mode(options)
|
@@ -367,7 +370,7 @@ module ActiveMerchant #:nodoc:
|
|
367
370
|
|
368
371
|
def merchant_initiated_unscheduled(options)
|
369
372
|
return options[:merchant_initiated_unscheduled] if options[:merchant_initiated_unscheduled]
|
370
|
-
return 'Y' if options.dig(:stored_credential, :initiator) == 'merchant' && options.dig(:stored_credential, :reason_type) == 'unscheduled'
|
373
|
+
return 'Y' if options.dig(:stored_credential, :initiator) == 'merchant' && options.dig(:stored_credential, :reason_type) == 'unscheduled' || options.dig(:stored_credential, :reason_type) == 'recurring'
|
371
374
|
end
|
372
375
|
|
373
376
|
def entry_mode(options)
|
@@ -392,6 +395,7 @@ module ActiveMerchant #:nodoc:
|
|
392
395
|
request = "xmldata=#{request}".delete('&')
|
393
396
|
|
394
397
|
response = parse(ssl_post(test? ? self.test_url : self.live_url, request, headers))
|
398
|
+
response = hash_html_decode(response)
|
395
399
|
|
396
400
|
Response.new(
|
397
401
|
response[:result] == '0',
|
@@ -413,7 +417,7 @@ module ActiveMerchant #:nodoc:
|
|
413
417
|
def headers
|
414
418
|
{
|
415
419
|
'Accept' => 'application/xml',
|
416
|
-
'Content-type' => 'application/x-www-form-urlencoded'
|
420
|
+
'Content-type' => 'application/x-www-form-urlencoded;charset=utf8'
|
417
421
|
}
|
418
422
|
end
|
419
423
|
|
@@ -428,12 +432,40 @@ module ActiveMerchant #:nodoc:
|
|
428
432
|
[response[:approval_code], response[:txn_id]].join(';')
|
429
433
|
end
|
430
434
|
|
431
|
-
def
|
435
|
+
def url_encode_truncate(value, size)
|
432
436
|
return nil unless value
|
433
437
|
|
434
|
-
|
438
|
+
encoded = url_encode(value)
|
435
439
|
|
436
|
-
|
440
|
+
while encoded.length > size
|
441
|
+
value.chop!
|
442
|
+
encoded = url_encode(value)
|
443
|
+
end
|
444
|
+
encoded
|
445
|
+
end
|
446
|
+
|
447
|
+
def url_encode(value)
|
448
|
+
if value.is_a?(String)
|
449
|
+
encoded = CGI.escape(value)
|
450
|
+
encoded = encoded.tr('+', ' ') # don't encode spaces
|
451
|
+
encoded = encoded.gsub('%26', '%26amp;') # account for Elavon's weird '&' handling
|
452
|
+
encoded
|
453
|
+
else
|
454
|
+
value.to_s
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
def hash_html_decode(hash)
|
459
|
+
hash.each do |k, v|
|
460
|
+
if v.is_a?(String)
|
461
|
+
# decode all string params
|
462
|
+
v = v.gsub('&', '&') # account for Elavon's weird '&' handling
|
463
|
+
hash[k] = CGI.unescape_html(v)
|
464
|
+
elsif v.is_a?(Hash)
|
465
|
+
hash_html_decode(v)
|
466
|
+
end
|
467
|
+
end
|
468
|
+
hash
|
437
469
|
end
|
438
470
|
end
|
439
471
|
end
|
@@ -192,6 +192,8 @@ module ActiveMerchant #:nodoc:
|
|
192
192
|
xml.PaymentType options[:payment_type] if options[:payment_type]
|
193
193
|
xml.SubmissionType options[:submission_type] if options[:submission_type]
|
194
194
|
xml.DuplicateCheckDisableFlag options[:duplicate_check_disable_flag].to_s == 'true' ? 'True' : 'False' unless options[:duplicate_check_disable_flag].nil?
|
195
|
+
xml.DuplicateOverrideFlag options[:duplicate_override_flag].to_s == 'true' ? 'True' : 'False' unless options[:duplicate_override_flag].nil?
|
196
|
+
xml.MerchantDescriptor options[:merchant_descriptor] if options[:merchant_descriptor]
|
195
197
|
end
|
196
198
|
end
|
197
199
|
|
@@ -33,7 +33,7 @@ module ActiveMerchant #:nodoc:
|
|
33
33
|
add_creator_info(post, options)
|
34
34
|
add_fraud_fields(post, options)
|
35
35
|
add_external_cardholder_authentication_data(post, options)
|
36
|
-
commit(:authorize, post)
|
36
|
+
commit(:authorize, post, options: options)
|
37
37
|
end
|
38
38
|
|
39
39
|
def capture(money, authorization, options = {})
|
@@ -41,7 +41,7 @@ module ActiveMerchant #:nodoc:
|
|
41
41
|
add_order(post, money, options, capture: true)
|
42
42
|
add_customer_data(post, options)
|
43
43
|
add_creator_info(post, options)
|
44
|
-
commit(:capture, post, authorization)
|
44
|
+
commit(:capture, post, authorization: authorization)
|
45
45
|
end
|
46
46
|
|
47
47
|
def refund(money, authorization, options = {})
|
@@ -49,13 +49,13 @@ module ActiveMerchant #:nodoc:
|
|
49
49
|
add_amount(post, money, options)
|
50
50
|
add_refund_customer_data(post, options)
|
51
51
|
add_creator_info(post, options)
|
52
|
-
commit(:refund, post, authorization)
|
52
|
+
commit(:refund, post, authorization: authorization)
|
53
53
|
end
|
54
54
|
|
55
55
|
def void(authorization, options = {})
|
56
56
|
post = nestable_hash
|
57
57
|
add_creator_info(post, options)
|
58
|
-
commit(:void, post, authorization)
|
58
|
+
commit(:void, post, authorization: authorization)
|
59
59
|
end
|
60
60
|
|
61
61
|
def verify(payment, options = {})
|
@@ -277,9 +277,13 @@ module ActiveMerchant #:nodoc:
|
|
277
277
|
end
|
278
278
|
end
|
279
279
|
|
280
|
-
def
|
280
|
+
def idempotency_key_for_signature(options)
|
281
|
+
"x-gcs-idempotence-key:#{options[:idempotency_key]}" if options[:idempotency_key]
|
282
|
+
end
|
283
|
+
|
284
|
+
def commit(action, post, authorization: nil, options: {})
|
281
285
|
begin
|
282
|
-
raw_response = ssl_post(url(action, authorization), post.to_json, headers(action, post, authorization))
|
286
|
+
raw_response = ssl_post(url(action, authorization), post.to_json, headers(action, post, authorization, options))
|
283
287
|
response = parse(raw_response)
|
284
288
|
rescue ResponseError => e
|
285
289
|
response = parse(e.response.body) if e.response.code.to_i >= 400
|
@@ -306,21 +310,26 @@ module ActiveMerchant #:nodoc:
|
|
306
310
|
}
|
307
311
|
end
|
308
312
|
|
309
|
-
def headers(action, post, authorization = nil)
|
310
|
-
{
|
313
|
+
def headers(action, post, authorization = nil, options = {})
|
314
|
+
headers = {
|
311
315
|
'Content-Type' => content_type,
|
312
|
-
'Authorization' => auth_digest(action, post, authorization),
|
316
|
+
'Authorization' => auth_digest(action, post, authorization, options),
|
313
317
|
'Date' => date
|
314
318
|
}
|
319
|
+
|
320
|
+
headers['X-GCS-Idempotence-Key'] = options[:idempotency_key] if options[:idempotency_key]
|
321
|
+
headers
|
315
322
|
end
|
316
323
|
|
317
|
-
def auth_digest(action, post, authorization = nil)
|
324
|
+
def auth_digest(action, post, authorization = nil, options = {})
|
318
325
|
data = <<~REQUEST
|
319
326
|
POST
|
320
327
|
#{content_type}
|
321
328
|
#{date}
|
329
|
+
#{idempotency_key_for_signature(options)}
|
322
330
|
#{uri(action, authorization)}
|
323
331
|
REQUEST
|
332
|
+
data = data.each_line.reject { |line| line.strip == '' }.join
|
324
333
|
digest = OpenSSL::Digest.new('sha256')
|
325
334
|
key = @options[:secret_api_key]
|
326
335
|
"GCS v1HMAC:#{@options[:api_key_id]}:#{Base64.strict_encode64(OpenSSL::HMAC.digest(digest, key, data))}"
|
@@ -37,6 +37,7 @@ module ActiveMerchant #:nodoc:
|
|
37
37
|
post = {}
|
38
38
|
post[:ticketNumber] = authorization
|
39
39
|
add_invoice(action, post, amount, options)
|
40
|
+
add_full_response(post, options)
|
40
41
|
|
41
42
|
commit(action, post)
|
42
43
|
end
|
@@ -46,6 +47,7 @@ module ActiveMerchant #:nodoc:
|
|
46
47
|
|
47
48
|
post = {}
|
48
49
|
post[:ticketNumber] = authorization
|
50
|
+
add_full_response(post, options)
|
49
51
|
|
50
52
|
commit(action, post)
|
51
53
|
end
|
@@ -55,6 +57,7 @@ module ActiveMerchant #:nodoc:
|
|
55
57
|
|
56
58
|
post = {}
|
57
59
|
post[:ticketNumber] = authorization
|
60
|
+
add_full_response(post, options)
|
58
61
|
|
59
62
|
commit(action, post)
|
60
63
|
end
|
@@ -78,6 +81,7 @@ module ActiveMerchant #:nodoc:
|
|
78
81
|
post = {}
|
79
82
|
add_invoice(action, post, amount, options)
|
80
83
|
add_payment_method(post, payment_method, options)
|
84
|
+
add_full_response(post, options)
|
81
85
|
|
82
86
|
commit(action, post)
|
83
87
|
end
|
@@ -88,6 +92,8 @@ module ActiveMerchant #:nodoc:
|
|
88
92
|
post = {}
|
89
93
|
add_reference(post, authorization, options)
|
90
94
|
add_invoice(action, post, amount, options)
|
95
|
+
add_contact_details(post, options[:contact_details]) if options[:contact_details]
|
96
|
+
add_full_response(post, options)
|
91
97
|
|
92
98
|
commit(action, post)
|
93
99
|
end
|
@@ -98,6 +104,7 @@ module ActiveMerchant #:nodoc:
|
|
98
104
|
post = {}
|
99
105
|
add_reference(post, authorization, options)
|
100
106
|
add_invoice(action, post, amount, options)
|
107
|
+
add_full_response(post, options)
|
101
108
|
|
102
109
|
commit(action, post)
|
103
110
|
end
|
@@ -154,6 +161,22 @@ module ActiveMerchant #:nodoc:
|
|
154
161
|
post[:token] = authorization
|
155
162
|
end
|
156
163
|
|
164
|
+
def add_contact_details(post, contact_details_options)
|
165
|
+
contact_details = {}
|
166
|
+
contact_details[:documentType] = contact_details_options[:document_type] if contact_details_options[:document_type]
|
167
|
+
contact_details[:documentNumber] = contact_details_options[:document_number] if contact_details_options[:document_number]
|
168
|
+
contact_details[:email] = contact_details_options[:email] if contact_details_options[:email]
|
169
|
+
contact_details[:firstName] = contact_details_options[:first_name] if contact_details_options[:first_name]
|
170
|
+
contact_details[:lastName] = contact_details_options[:last_name] if contact_details_options[:last_name]
|
171
|
+
contact_details[:secondLastName] = contact_details_options[:second_last_name] if contact_details_options[:second_last_name]
|
172
|
+
contact_details[:phoneNumber] = contact_details_options[:phone_number] if contact_details_options[:phone_number]
|
173
|
+
post[:contactDetails] = contact_details
|
174
|
+
end
|
175
|
+
|
176
|
+
def add_full_response(post, options)
|
177
|
+
post[:fullResponse] = options[:full_response].to_s.casecmp('true').zero? if options[:full_response]
|
178
|
+
end
|
179
|
+
|
157
180
|
ENDPOINT = {
|
158
181
|
'tokenize' => 'tokens',
|
159
182
|
'charge' => 'charges',
|