activemerchant 1.133.0 → 1.137.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 +240 -0
- data/lib/active_merchant/billing/check.rb +2 -2
- data/lib/active_merchant/billing/compatibility.rb +4 -4
- data/lib/active_merchant/billing/credit_card.rb +11 -8
- data/lib/active_merchant/billing/credit_card_formatting.rb +4 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +59 -6
- data/lib/active_merchant/billing/gateway.rb +9 -0
- data/lib/active_merchant/billing/gateways/adyen.rb +162 -43
- data/lib/active_merchant/billing/gateways/airwallex.rb +26 -12
- data/lib/active_merchant/billing/gateways/alelo.rb +23 -5
- data/lib/active_merchant/billing/gateways/authorize_net.rb +43 -35
- data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +10 -6
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +1 -3
- data/lib/active_merchant/billing/gateways/axcessms.rb +6 -2
- data/lib/active_merchant/billing/gateways/banwire.rb +4 -2
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +7 -3
- data/lib/active_merchant/billing/gateways/blue_pay.rb +13 -5
- data/lib/active_merchant/billing/gateways/blue_snap.rb +5 -5
- data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +65 -20
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +226 -73
- data/lib/active_merchant/billing/gateways/braintree_orange.rb +1 -1
- data/lib/active_merchant/billing/gateways/card_connect.rb +5 -2
- data/lib/active_merchant/billing/gateways/card_stream.rb +4 -6
- data/lib/active_merchant/billing/gateways/cashnet.rb +1 -1
- data/lib/active_merchant/billing/gateways/cecabank/cecabank_common.rb +36 -0
- data/lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb +316 -0
- data/lib/active_merchant/billing/gateways/cecabank/cecabank_xml.rb +220 -0
- data/lib/active_merchant/billing/gateways/cecabank.rb +7 -240
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +238 -34
- data/lib/active_merchant/billing/gateways/commerce_hub.rb +63 -6
- data/lib/active_merchant/billing/gateways/credorax.rb +3 -5
- data/lib/active_merchant/billing/gateways/cyber_source.rb +185 -47
- data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +102 -58
- data/lib/active_merchant/billing/gateways/d_local.rb +26 -15
- data/lib/active_merchant/billing/gateways/data_cash.rb +21 -17
- data/lib/active_merchant/billing/gateways/datatrans.rb +279 -0
- data/lib/active_merchant/billing/gateways/decidir.rb +53 -18
- data/lib/active_merchant/billing/gateways/decidir_plus.rb +4 -1
- data/lib/active_merchant/billing/gateways/deepstack.rb +382 -0
- data/lib/active_merchant/billing/gateways/ebanx.rb +40 -36
- data/lib/active_merchant/billing/gateways/efsnet.rb +6 -2
- data/lib/active_merchant/billing/gateways/elavon.rb +99 -33
- data/lib/active_merchant/billing/gateways/element.rb +36 -7
- data/lib/active_merchant/billing/gateways/epay.rb +6 -2
- data/lib/active_merchant/billing/gateways/evo_ca.rb +6 -2
- data/lib/active_merchant/billing/gateways/eway.rb +4 -2
- data/lib/active_merchant/billing/gateways/eway_managed.rb +6 -2
- data/lib/active_merchant/billing/gateways/exact.rb +6 -2
- data/lib/active_merchant/billing/gateways/fat_zebra.rb +31 -3
- data/lib/active_merchant/billing/gateways/federated_canada.rb +6 -2
- data/lib/active_merchant/billing/gateways/first_pay/first_pay_common.rb +15 -0
- data/lib/active_merchant/billing/gateways/first_pay/first_pay_json.rb +190 -0
- data/lib/active_merchant/billing/gateways/first_pay/first_pay_xml.rb +183 -0
- data/lib/active_merchant/billing/gateways/first_pay.rb +6 -172
- data/lib/active_merchant/billing/gateways/firstdata_e4.rb +6 -2
- data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +7 -3
- data/lib/active_merchant/billing/gateways/flex_charge.rb +347 -0
- data/lib/active_merchant/billing/gateways/garanti.rb +4 -2
- data/lib/active_merchant/billing/gateways/global_collect.rb +45 -37
- data/lib/active_merchant/billing/gateways/hi_pay.rb +286 -0
- data/lib/active_merchant/billing/gateways/hps.rb +1 -1
- data/lib/active_merchant/billing/gateways/iats_payments.rb +7 -2
- data/lib/active_merchant/billing/gateways/inspire.rb +6 -4
- data/lib/active_merchant/billing/gateways/instapay.rb +7 -4
- data/lib/active_merchant/billing/gateways/ipg.rb +9 -5
- data/lib/active_merchant/billing/gateways/iridium.rb +15 -5
- data/lib/active_merchant/billing/gateways/itransact.rb +6 -2
- data/lib/active_merchant/billing/gateways/iveri.rb +3 -3
- data/lib/active_merchant/billing/gateways/ixopay.rb +2 -2
- data/lib/active_merchant/billing/gateways/jetpay.rb +4 -2
- data/lib/active_merchant/billing/gateways/jetpay_v2.rb +4 -2
- data/lib/active_merchant/billing/gateways/kushki.rb +72 -12
- data/lib/active_merchant/billing/gateways/linkpoint.rb +6 -2
- data/lib/active_merchant/billing/gateways/litle.rb +33 -50
- data/lib/active_merchant/billing/gateways/mastercard.rb +4 -4
- data/lib/active_merchant/billing/gateways/maxipago.rb +2 -2
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +8 -5
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +11 -4
- data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +11 -4
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +19 -3
- data/lib/active_merchant/billing/gateways/mercury.rb +6 -2
- data/lib/active_merchant/billing/gateways/metrics_global.rb +8 -6
- data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +1 -0
- data/lib/active_merchant/billing/gateways/migs.rb +6 -2
- data/lib/active_merchant/billing/gateways/mit.rb +8 -3
- data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +18 -10
- data/lib/active_merchant/billing/gateways/monei.rb +1 -1
- data/lib/active_merchant/billing/gateways/moneris.rb +9 -3
- data/lib/active_merchant/billing/gateways/money_movers.rb +6 -2
- data/lib/active_merchant/billing/gateways/nab_transact.rb +12 -4
- data/lib/active_merchant/billing/gateways/net_registry.rb +6 -2
- data/lib/active_merchant/billing/gateways/netbanx.rb +1 -3
- data/lib/active_merchant/billing/gateways/netbilling.rb +6 -2
- data/lib/active_merchant/billing/gateways/network_merchants.rb +6 -2
- data/lib/active_merchant/billing/gateways/nmi.rb +18 -6
- data/lib/active_merchant/billing/gateways/ogone.rb +6 -2
- data/lib/active_merchant/billing/gateways/openpay.rb +4 -2
- data/lib/active_merchant/billing/gateways/opp.rb +1 -2
- data/lib/active_merchant/billing/gateways/optimal_payment.rb +6 -2
- data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +1 -3
- data/lib/active_merchant/billing/gateways/orbital.rb +83 -24
- data/lib/active_merchant/billing/gateways/pac_net_raven.rb +7 -4
- data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +6 -2
- data/lib/active_merchant/billing/gateways/pay_hub.rb +4 -2
- data/lib/active_merchant/billing/gateways/pay_junction.rb +6 -2
- data/lib/active_merchant/billing/gateways/pay_secure.rb +6 -2
- data/lib/active_merchant/billing/gateways/pay_trace.rb +31 -18
- data/lib/active_merchant/billing/gateways/payeezy.rb +19 -8
- data/lib/active_merchant/billing/gateways/payex.rb +4 -2
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
- data/lib/active_merchant/billing/gateways/payflow.rb +1 -3
- data/lib/active_merchant/billing/gateways/payment_express.rb +8 -4
- data/lib/active_merchant/billing/gateways/paymentez.rb +23 -11
- data/lib/active_merchant/billing/gateways/paysafe.rb +12 -11
- data/lib/active_merchant/billing/gateways/payscout.rb +7 -4
- data/lib/active_merchant/billing/gateways/paystation.rb +7 -3
- data/lib/active_merchant/billing/gateways/payway.rb +6 -2
- data/lib/active_merchant/billing/gateways/payway_dot_com.rb +2 -2
- data/lib/active_merchant/billing/gateways/pin.rb +22 -4
- data/lib/active_merchant/billing/gateways/plexo.rb +49 -10
- data/lib/active_merchant/billing/gateways/plugnpay.rb +6 -2
- data/lib/active_merchant/billing/gateways/priority.rb +6 -5
- data/lib/active_merchant/billing/gateways/psigate.rb +6 -2
- data/lib/active_merchant/billing/gateways/psl_card.rb +6 -2
- data/lib/active_merchant/billing/gateways/qbms.rb +6 -2
- data/lib/active_merchant/billing/gateways/quantum.rb +6 -2
- data/lib/active_merchant/billing/gateways/quickbooks.rb +6 -5
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +7 -4
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +6 -2
- data/lib/active_merchant/billing/gateways/rapyd.rb +148 -46
- data/lib/active_merchant/billing/gateways/reach.rb +11 -4
- data/lib/active_merchant/billing/gateways/redsys.rb +2 -10
- data/lib/active_merchant/billing/gateways/redsys_rest.rb +507 -0
- data/lib/active_merchant/billing/gateways/s5.rb +3 -3
- data/lib/active_merchant/billing/gateways/safe_charge.rb +36 -16
- data/lib/active_merchant/billing/gateways/sage.rb +12 -4
- data/lib/active_merchant/billing/gateways/sage_pay.rb +79 -5
- data/lib/active_merchant/billing/gateways/sallie_mae.rb +6 -2
- data/lib/active_merchant/billing/gateways/secure_net.rb +6 -2
- data/lib/active_merchant/billing/gateways/secure_pay.rb +8 -6
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +12 -4
- data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +6 -2
- data/lib/active_merchant/billing/gateways/securion_pay.rb +24 -10
- data/lib/active_merchant/billing/gateways/shift4.rb +17 -20
- data/lib/active_merchant/billing/gateways/shift4_v2.rb +117 -0
- data/lib/active_merchant/billing/gateways/simetrik.rb +17 -11
- data/lib/active_merchant/billing/gateways/skip_jack.rb +6 -2
- data/lib/active_merchant/billing/gateways/smart_ps.rb +7 -4
- data/lib/active_merchant/billing/gateways/so_easy_pay.rb +4 -2
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +2 -4
- data/lib/active_merchant/billing/gateways/stripe.rb +53 -21
- data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +199 -50
- data/lib/active_merchant/billing/gateways/sum_up.rb +223 -0
- data/lib/active_merchant/billing/gateways/swipe_checkout.rb +4 -2
- data/lib/active_merchant/billing/gateways/telr.rb +3 -4
- data/lib/active_merchant/billing/gateways/trans_first.rb +1 -2
- data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +8 -16
- data/lib/active_merchant/billing/gateways/transact_pro.rb +1 -1
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +6 -2
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +9 -8
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +6 -2
- data/lib/active_merchant/billing/gateways/vanco.rb +2 -4
- data/lib/active_merchant/billing/gateways/vantiv_express.rb +587 -0
- data/lib/active_merchant/billing/gateways/verifi.rb +6 -2
- data/lib/active_merchant/billing/gateways/viaklix.rb +6 -2
- data/lib/active_merchant/billing/gateways/visanet_peru.rb +2 -2
- data/lib/active_merchant/billing/gateways/vpos.rb +3 -3
- data/lib/active_merchant/billing/gateways/wirecard.rb +7 -3
- data/lib/active_merchant/billing/gateways/wompi.rb +5 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +140 -73
- data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +13 -10
- data/lib/active_merchant/billing/gateways/xpay.rb +242 -0
- data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
- data/lib/active_merchant/billing/response.rb +2 -2
- data/lib/active_merchant/connection.rb +3 -17
- data/lib/active_merchant/country.rb +1 -0
- data/lib/active_merchant/errors.rb +10 -0
- data/lib/active_merchant/version.rb +1 -1
- data/lib/support/gateway_support.rb +2 -2
- data/lib/support/ssl_verify.rb +4 -4
- data/lib/support/ssl_version.rb +6 -6
- metadata +30 -9
@@ -161,11 +161,13 @@ module ActiveMerchant #:nodoc:
|
|
161
161
|
'Content-Type' => 'text/xml; charset=utf-8' }
|
162
162
|
response_string = ssl_post(test? ? self.test_url : self.live_url, soap, headers)
|
163
163
|
response = parse(response_string, soap_action)
|
164
|
-
return Response.new(
|
164
|
+
return Response.new(
|
165
|
+
response['errorcode'] == '000',
|
165
166
|
response['errormessage'],
|
166
167
|
response,
|
167
168
|
test: test?,
|
168
|
-
authorization: response['transaction_id']
|
169
|
+
authorization: response['transaction_id']
|
170
|
+
)
|
169
171
|
end
|
170
172
|
|
171
173
|
def build_soap(request)
|
@@ -271,11 +271,9 @@ module ActiveMerchant #:nodoc:
|
|
271
271
|
end
|
272
272
|
end
|
273
273
|
|
274
|
-
def build_xml_request(root)
|
274
|
+
def build_xml_request(root, &block)
|
275
275
|
builder = Nokogiri::XML::Builder.new
|
276
|
-
builder.__send__(root)
|
277
|
-
yield(doc)
|
278
|
-
end
|
276
|
+
builder.__send__(root, &block)
|
279
277
|
builder.to_xml
|
280
278
|
end
|
281
279
|
|
@@ -7,14 +7,16 @@ module ActiveMerchant #:nodoc:
|
|
7
7
|
class StripeGateway < Gateway
|
8
8
|
self.live_url = 'https://api.stripe.com/v1/'
|
9
9
|
|
10
|
+
# Docs on AVS codes: https://en.wikipedia.org/w/index.php?title=Address_verification_service&_ga=2.97570079.1027215965.1655989706-2008268124.1655989706#AVS_response_codes
|
11
|
+
# possible response values: https://stripe.com/docs/api/payment_methods/object#payment_method_object-card-checks
|
10
12
|
AVS_CODE_TRANSLATOR = {
|
11
|
-
'line1: pass, zip: pass' => 'Y',
|
12
13
|
'line1: pass, zip: fail' => 'A',
|
13
14
|
'line1: pass, zip: unchecked' => 'B',
|
14
|
-
'line1:
|
15
|
+
'line1: unchecked, zip: unchecked' => 'I',
|
15
16
|
'line1: fail, zip: fail' => 'N',
|
16
17
|
'line1: unchecked, zip: pass' => 'P',
|
17
|
-
'line1:
|
18
|
+
'line1: pass, zip: pass' => 'Y',
|
19
|
+
'line1: fail, zip: pass' => 'Z'
|
18
20
|
}
|
19
21
|
|
20
22
|
CVC_CODE_TRANSLATOR = {
|
@@ -292,7 +294,9 @@ module ActiveMerchant #:nodoc:
|
|
292
294
|
gsub(%r(((\[card\]|card)\[number\]=)\d+), '\1[FILTERED]').
|
293
295
|
gsub(%r(((\[card\]|card)\[swipe_data\]=)[^&]+(&?)), '\1[FILTERED]\3').
|
294
296
|
gsub(%r(((\[bank_account\]|bank_account)\[account_number\]=)\d+), '\1[FILTERED]').
|
295
|
-
gsub(%r(((\[payment_method_data\]|payment_method_data)\[card\]\[token\]=)[^&]+(&?)), '\1[FILTERED]\3')
|
297
|
+
gsub(%r(((\[payment_method_data\]|payment_method_data)\[card\]\[token\]=)[^&]+(&?)), '\1[FILTERED]\3').
|
298
|
+
gsub(%r(((\[payment_method_data\]|payment_method_data)\[card\]\[network_token\]\[number\]=)\d+), '\1[FILTERED]').
|
299
|
+
gsub(%r(((\[payment_method_options\]|payment_method_options)\[card\]\[network_token\]\[cryptogram\]=)[^&]+(&?)), '\1[FILTERED]')
|
296
300
|
end
|
297
301
|
|
298
302
|
def supports_network_tokenization?
|
@@ -577,7 +581,7 @@ module ActiveMerchant #:nodoc:
|
|
577
581
|
|
578
582
|
def add_source_owner(post, creditcard, options)
|
579
583
|
post[:owner] = {}
|
580
|
-
post[:owner][:name] = creditcard.name if creditcard.name
|
584
|
+
post[:owner][:name] = creditcard.name if creditcard.respond_to?(:name) && creditcard.name
|
581
585
|
post[:owner][:email] = options[:email] if options[:email]
|
582
586
|
|
583
587
|
if address = options[:billing_address] || options[:address]
|
@@ -613,8 +617,21 @@ module ActiveMerchant #:nodoc:
|
|
613
617
|
post[:radar_options] = radar_options unless radar_options.empty?
|
614
618
|
end
|
615
619
|
|
620
|
+
def add_header_fields(response)
|
621
|
+
return unless @response_headers.present?
|
622
|
+
|
623
|
+
headers = {}
|
624
|
+
headers['response_headers'] = {}
|
625
|
+
headers['response_headers']['idempotent_replayed'] = @response_headers['idempotent-replayed'] if @response_headers['idempotent-replayed']
|
626
|
+
headers['response_headers']['stripe_should_retry'] = @response_headers['stripe-should-retry'] if @response_headers['stripe-should-retry']
|
627
|
+
|
628
|
+
response.merge!(headers)
|
629
|
+
end
|
630
|
+
|
616
631
|
def parse(body)
|
617
|
-
JSON.parse(body)
|
632
|
+
response = JSON.parse(body)
|
633
|
+
add_header_fields(response)
|
634
|
+
response
|
618
635
|
end
|
619
636
|
|
620
637
|
def post_data(params)
|
@@ -695,46 +712,46 @@ module ActiveMerchant #:nodoc:
|
|
695
712
|
|
696
713
|
def commit(method, url, parameters = nil, options = {})
|
697
714
|
add_expand_parameters(parameters, options) if parameters
|
698
|
-
|
699
715
|
return Response.new(false, 'Invalid API Key provided') unless key_valid?(options)
|
700
716
|
|
701
717
|
response = api_request(method, url, parameters, options)
|
702
718
|
response['webhook_id'] = options[:webhook_id] if options[:webhook_id]
|
703
719
|
success = success_from(response, options)
|
704
720
|
|
705
|
-
|
706
|
-
avs_code = AVS_CODE_TRANSLATOR["line1: #{
|
707
|
-
cvc_code = CVC_CODE_TRANSLATOR[
|
708
|
-
Response.new(
|
721
|
+
card_checks = card_from_response(response)
|
722
|
+
avs_code = AVS_CODE_TRANSLATOR["line1: #{card_checks['address_line1_check']}, zip: #{card_checks['address_zip_check'] || card_checks['address_postal_code_check']}"]
|
723
|
+
cvc_code = CVC_CODE_TRANSLATOR[card_checks['cvc_check']]
|
724
|
+
Response.new(
|
725
|
+
success,
|
709
726
|
message_from(success, response),
|
710
727
|
response,
|
711
728
|
test: response_is_test?(response),
|
712
|
-
authorization: authorization_from(success, url, method, response),
|
729
|
+
authorization: authorization_from(success, url, method, response, options),
|
713
730
|
avs_result: { code: avs_code },
|
714
731
|
cvv_result: cvc_code,
|
715
732
|
emv_authorization: emv_authorization_from_response(response),
|
716
|
-
error_code: success ? nil : error_code_from(response)
|
733
|
+
error_code: success ? nil : error_code_from(response)
|
734
|
+
)
|
717
735
|
end
|
718
736
|
|
719
737
|
def key_valid?(options)
|
720
738
|
return true unless test?
|
721
739
|
|
722
740
|
%w(sk rk).each do |k|
|
723
|
-
if key(options).start_with?(k)
|
724
|
-
return false unless key(options).start_with?("#{k}_test")
|
725
|
-
end
|
741
|
+
return false if key(options).start_with?(k) && !key(options).start_with?("#{k}_test")
|
726
742
|
end
|
727
743
|
|
728
744
|
true
|
729
745
|
end
|
730
746
|
|
731
|
-
def authorization_from(success, url, method, response)
|
732
|
-
return response.
|
747
|
+
def authorization_from(success, url, method, response, options)
|
748
|
+
return response.dig('error', 'charge') || response.dig('error', 'setup_intent', 'id') || response['id'] unless success
|
733
749
|
|
734
750
|
if url == 'customers'
|
735
751
|
[response['id'], response.dig('sources', 'data').first&.dig('id')].join('|')
|
736
|
-
elsif method == :post && (url.match(/customers\/.*\/cards/) || url.match(/payment_methods\/.*\/attach/))
|
737
|
-
[response['
|
752
|
+
elsif method == :post && (url.match(/customers\/.*\/cards/) || url.match(/payment_methods\/.*\/attach/) || options[:action] == :store)
|
753
|
+
response_id = options[:action] == :store ? response['payment_method'] : response['id']
|
754
|
+
[response['customer'], response_id].join('|')
|
738
755
|
else
|
739
756
|
response['id']
|
740
757
|
end
|
@@ -748,6 +765,18 @@ module ActiveMerchant #:nodoc:
|
|
748
765
|
!response.key?('error') && response['status'] != 'failed'
|
749
766
|
end
|
750
767
|
|
768
|
+
# Override the regular handle response so we can access the headers
|
769
|
+
# set header fields and values so we can add them to the response body
|
770
|
+
def handle_response(response)
|
771
|
+
@response_headers = response.each_header.to_h if response.respond_to?(:header)
|
772
|
+
case response.code.to_i
|
773
|
+
when 200...300
|
774
|
+
response.body
|
775
|
+
else
|
776
|
+
raise ResponseError.new(response)
|
777
|
+
end
|
778
|
+
end
|
779
|
+
|
751
780
|
def response_error(raw_response)
|
752
781
|
parse(raw_response)
|
753
782
|
rescue JSON::ParserError
|
@@ -783,7 +812,10 @@ module ActiveMerchant #:nodoc:
|
|
783
812
|
end
|
784
813
|
|
785
814
|
def card_from_response(response)
|
786
|
-
|
815
|
+
# StripePI puts the AVS and CVC check significantly deeper into the response object
|
816
|
+
response['card'] || response['active_card'] || response['source'] ||
|
817
|
+
response.dig('charges', 'data', 0, 'payment_method_details', 'card', 'checks') ||
|
818
|
+
response.dig('latest_attempt', 'payment_method_details', 'card', 'checks') || {}
|
787
819
|
end
|
788
820
|
|
789
821
|
def emv_authorization_from_response(response)
|
@@ -11,10 +11,15 @@ module ActiveMerchant #:nodoc:
|
|
11
11
|
CONFIRM_INTENT_ATTRIBUTES = %i[receipt_email return_url save_payment_method setup_future_usage off_session]
|
12
12
|
UPDATE_INTENT_ATTRIBUTES = %i[description statement_descriptor_suffix statement_descriptor receipt_email setup_future_usage]
|
13
13
|
DEFAULT_API_VERSION = '2020-08-27'
|
14
|
+
DIGITAL_WALLETS = {
|
15
|
+
apple_pay: 'apple_pay',
|
16
|
+
google_pay: 'google_pay_dpan',
|
17
|
+
untokenized_google_pay: 'google_pay_ecommerce_token'
|
18
|
+
}
|
14
19
|
|
15
20
|
def create_intent(money, payment_method, options = {})
|
16
21
|
MultiResponse.run do |r|
|
17
|
-
if payment_method.is_a?(NetworkTokenizationCreditCard)
|
22
|
+
if payment_method.is_a?(NetworkTokenizationCreditCard) && digital_wallet_payment_method?(payment_method) && options[:new_ap_gp_route] != true
|
18
23
|
r.process { tokenize_apple_google(payment_method, options) }
|
19
24
|
payment_method = (r.params['token']['id']) if r.success?
|
20
25
|
end
|
@@ -25,9 +30,15 @@ module ActiveMerchant #:nodoc:
|
|
25
30
|
add_confirmation_method(post, options)
|
26
31
|
add_customer(post, options)
|
27
32
|
|
28
|
-
|
29
|
-
|
33
|
+
if new_apple_google_pay_flow(payment_method, options)
|
34
|
+
add_digital_wallet(post, payment_method, options)
|
35
|
+
add_billing_address(post, payment_method, options)
|
36
|
+
else
|
37
|
+
result = add_payment_method_token(post, payment_method, options)
|
38
|
+
return result if result.is_a?(ActiveMerchant::Billing::Response)
|
39
|
+
end
|
30
40
|
|
41
|
+
add_network_token_cryptogram_and_eci(post, payment_method)
|
31
42
|
add_external_three_d_secure_auth_data(post, options)
|
32
43
|
add_metadata(post, options)
|
33
44
|
add_return_url(post, options)
|
@@ -43,6 +54,8 @@ module ActiveMerchant #:nodoc:
|
|
43
54
|
add_fulfillment_date(post, options)
|
44
55
|
request_three_d_secure(post, options)
|
45
56
|
add_level_three(post, options)
|
57
|
+
add_card_brand(post, options)
|
58
|
+
post[:expand] = ['charges.data.balance_transaction']
|
46
59
|
|
47
60
|
CREATE_INTENT_ATTRIBUTES.each do |attribute|
|
48
61
|
add_whitelisted_attribute(post, options, attribute)
|
@@ -63,8 +76,12 @@ module ActiveMerchant #:nodoc:
|
|
63
76
|
|
64
77
|
def confirm_intent(intent_id, payment_method, options = {})
|
65
78
|
post = {}
|
66
|
-
|
67
|
-
|
79
|
+
if new_apple_google_pay_flow(payment_method, options)
|
80
|
+
add_digital_wallet(post, payment_method, options)
|
81
|
+
else
|
82
|
+
result = add_payment_method_token(post, payment_method, options)
|
83
|
+
return result if result.is_a?(ActiveMerchant::Billing::Response)
|
84
|
+
end
|
68
85
|
|
69
86
|
add_payment_method_types(post, options)
|
70
87
|
CONFIRM_INTENT_ATTRIBUTES.each do |attribute|
|
@@ -80,22 +97,28 @@ module ActiveMerchant #:nodoc:
|
|
80
97
|
commit(:post, 'payment_methods', post_data, options)
|
81
98
|
end
|
82
99
|
|
100
|
+
def new_apple_google_pay_flow(payment_method, options)
|
101
|
+
return false unless options[:new_ap_gp_route]
|
102
|
+
|
103
|
+
payment_method.is_a?(NetworkTokenizationCreditCard) && digital_wallet_payment_method?(payment_method)
|
104
|
+
end
|
105
|
+
|
83
106
|
def add_payment_method_data(payment_method, options = {})
|
84
107
|
post = {
|
85
108
|
type: 'card',
|
86
109
|
card: {
|
87
|
-
number: payment_method.number,
|
88
110
|
exp_month: payment_method.month,
|
89
111
|
exp_year: payment_method.year
|
90
112
|
}
|
91
113
|
}
|
92
|
-
|
114
|
+
post[:card][:number] = payment_method.number unless adding_network_token_card_data?(payment_method)
|
93
115
|
post[:card][:cvc] = payment_method.verification_value if payment_method.verification_value
|
94
116
|
if billing = options[:billing_address] || options[:address]
|
95
117
|
post[:billing_details] = add_address(billing, options)
|
96
118
|
end
|
97
119
|
|
98
120
|
add_name_only(post, payment_method) if post[:billing_details].nil?
|
121
|
+
add_network_token_data(post, payment_method, options)
|
99
122
|
post
|
100
123
|
end
|
101
124
|
|
@@ -110,8 +133,12 @@ module ActiveMerchant #:nodoc:
|
|
110
133
|
post = {}
|
111
134
|
add_amount(post, money, options)
|
112
135
|
|
113
|
-
|
114
|
-
|
136
|
+
if new_apple_google_pay_flow(payment_method, options)
|
137
|
+
add_digital_wallet(post, payment_method, options)
|
138
|
+
else
|
139
|
+
result = add_payment_method_token(post, payment_method, options)
|
140
|
+
return result if result.is_a?(ActiveMerchant::Billing::Response)
|
141
|
+
end
|
115
142
|
|
116
143
|
add_payment_method_types(post, options)
|
117
144
|
add_customer(post, options)
|
@@ -131,16 +158,25 @@ module ActiveMerchant #:nodoc:
|
|
131
158
|
r.process do
|
132
159
|
post = {}
|
133
160
|
add_customer(post, options)
|
134
|
-
|
135
|
-
|
161
|
+
|
162
|
+
if new_apple_google_pay_flow(payment_method, options)
|
163
|
+
add_digital_wallet(post, payment_method, options)
|
164
|
+
add_billing_address(post, payment_method, options)
|
165
|
+
else
|
166
|
+
result = add_payment_method_token(post, payment_method, options, r)
|
167
|
+
return result if result.is_a?(ActiveMerchant::Billing::Response)
|
168
|
+
end
|
136
169
|
|
137
170
|
add_metadata(post, options)
|
138
171
|
add_return_url(post, options)
|
139
172
|
add_fulfillment_date(post, options)
|
140
173
|
request_three_d_secure(post, options)
|
174
|
+
add_card_brand(post, options)
|
175
|
+
add_exemption(post, options)
|
141
176
|
post[:on_behalf_of] = options[:on_behalf_of] if options[:on_behalf_of]
|
142
177
|
post[:usage] = options[:usage] if %w(on_session off_session).include?(options[:usage])
|
143
178
|
post[:description] = options[:description] if options[:description]
|
179
|
+
post[:expand] = ['latest_attempt']
|
144
180
|
|
145
181
|
commit(:post, 'setup_intents', post, options)
|
146
182
|
end
|
@@ -210,14 +246,16 @@ module ActiveMerchant #:nodoc:
|
|
210
246
|
# All other types will default to legacy Stripe store
|
211
247
|
def store(payment_method, options = {})
|
212
248
|
params = {}
|
213
|
-
post = {}
|
214
249
|
# If customer option is provided, create a payment method and attach to customer id
|
215
250
|
# Otherwise, create a customer, then attach
|
216
|
-
if payment_method
|
251
|
+
if new_apple_google_pay_flow(payment_method, options)
|
252
|
+
options[:customer] = customer(payment_method, options).params['id'] unless options[:customer]
|
253
|
+
verify(payment_method, options.merge!(action: :store))
|
254
|
+
elsif payment_method.is_a?(StripePaymentToken) || payment_method.is_a?(ActiveMerchant::Billing::CreditCard)
|
217
255
|
result = add_payment_method_token(params, payment_method, options)
|
218
256
|
return result if result.is_a?(ActiveMerchant::Billing::Response)
|
219
257
|
|
220
|
-
customer_id = options[:customer] || customer(
|
258
|
+
customer_id = options[:customer] || customer(payment_method, options).params['id']
|
221
259
|
options = format_idempotency_key(options, 'attach')
|
222
260
|
attach_parameters = { customer: customer_id }
|
223
261
|
attach_parameters[:validate] = options[:validate] unless options[:validate].nil?
|
@@ -227,7 +265,8 @@ module ActiveMerchant #:nodoc:
|
|
227
265
|
end
|
228
266
|
end
|
229
267
|
|
230
|
-
def customer(
|
268
|
+
def customer(payment, options)
|
269
|
+
post = {}
|
231
270
|
post[:description] = options[:description] if options[:description]
|
232
271
|
post[:expand] = [:sources]
|
233
272
|
post[:email] = options[:email]
|
@@ -267,8 +306,22 @@ module ActiveMerchant #:nodoc:
|
|
267
306
|
commit(:post, 'payment_intents', post, options)
|
268
307
|
end
|
269
308
|
|
309
|
+
def supports_network_tokenization?
|
310
|
+
true
|
311
|
+
end
|
312
|
+
|
270
313
|
private
|
271
314
|
|
315
|
+
def digital_wallet_payment_method?(payment_method)
|
316
|
+
payment_method.source == :google_pay || payment_method.source == :apple_pay
|
317
|
+
end
|
318
|
+
|
319
|
+
def adding_network_token_card_data?(payment_method)
|
320
|
+
return true if payment_method.is_a?(ActiveMerchant::Billing::NetworkTokenizationCreditCard) && payment_method.source == :network_token
|
321
|
+
|
322
|
+
false
|
323
|
+
end
|
324
|
+
|
272
325
|
def off_session_request?(options = {})
|
273
326
|
(options[:off_session] || options[:setup_future_usage]) && options[:confirm] == true
|
274
327
|
end
|
@@ -307,6 +360,14 @@ module ActiveMerchant #:nodoc:
|
|
307
360
|
post[:metadata][:event_type] = options[:event_type] if options[:event_type]
|
308
361
|
end
|
309
362
|
|
363
|
+
def add_card_brand(post, options)
|
364
|
+
return unless options[:card_brand]
|
365
|
+
|
366
|
+
post[:payment_method_options] ||= {}
|
367
|
+
post[:payment_method_options][:card] ||= {}
|
368
|
+
post[:payment_method_options][:card][:network] = options[:card_brand] if options[:card_brand]
|
369
|
+
end
|
370
|
+
|
310
371
|
def add_level_three(post, options = {})
|
311
372
|
level_three = {}
|
312
373
|
|
@@ -343,6 +404,72 @@ module ActiveMerchant #:nodoc:
|
|
343
404
|
return create_payment_method_and_extract_token(post, payment_method, options, responses) if options[:verify]
|
344
405
|
|
345
406
|
get_payment_method_data_from_card(post, payment_method, options, responses)
|
407
|
+
when ActiveMerchant::Billing::NetworkTokenizationCreditCard
|
408
|
+
get_payment_method_data_from_card(post, payment_method, options, responses)
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
def add_network_token_data(post_data, payment_method, options)
|
413
|
+
return unless adding_network_token_card_data?(payment_method)
|
414
|
+
|
415
|
+
post_data[:card] ||= {}
|
416
|
+
post_data[:card][:last4] = options[:last_4]
|
417
|
+
post_data[:card][:network_token] = {}
|
418
|
+
post_data[:card][:network_token][:number] = payment_method.number
|
419
|
+
post_data[:card][:network_token][:exp_month] = payment_method.month
|
420
|
+
post_data[:card][:network_token][:exp_year] = payment_method.year
|
421
|
+
post_data[:card][:network_token][:payment_account_reference] = options[:payment_account_reference] if options[:payment_account_reference]
|
422
|
+
|
423
|
+
post_data
|
424
|
+
end
|
425
|
+
|
426
|
+
def add_network_token_cryptogram_and_eci(post, payment_method)
|
427
|
+
return unless adding_network_token_card_data?(payment_method)
|
428
|
+
|
429
|
+
post[:payment_method_options] ||= {}
|
430
|
+
post[:payment_method_options][:card] ||= {}
|
431
|
+
post[:payment_method_options][:card][:network_token] ||= {}
|
432
|
+
post[:payment_method_options][:card][:network_token][:cryptogram] = payment_method.payment_cryptogram if payment_method.payment_cryptogram
|
433
|
+
post[:payment_method_options][:card][:network_token][:electronic_commerce_indicator] = payment_method.eci if payment_method.eci
|
434
|
+
end
|
435
|
+
|
436
|
+
def add_digital_wallet(post, payment_method, options)
|
437
|
+
post[:payment_method_data] = {
|
438
|
+
type: 'card',
|
439
|
+
card: {
|
440
|
+
last4: options[:last_4] || payment_method.number[-4..],
|
441
|
+
exp_month: payment_method.month,
|
442
|
+
exp_year: payment_method.year,
|
443
|
+
network_token: {
|
444
|
+
number: payment_method.number,
|
445
|
+
exp_month: payment_method.month,
|
446
|
+
exp_year: payment_method.year
|
447
|
+
}
|
448
|
+
}
|
449
|
+
}
|
450
|
+
|
451
|
+
add_cryptogram_and_eci(post, payment_method, options) unless options[:wallet_type]
|
452
|
+
source = payment_method.respond_to?(:source) ? payment_method.source : options[:wallet_type]
|
453
|
+
post[:payment_method_data][:card][:network_token][:tokenization_method] = DIGITAL_WALLETS[source]
|
454
|
+
end
|
455
|
+
|
456
|
+
def add_cryptogram_and_eci(post, payment_method, options)
|
457
|
+
post[:payment_method_options] ||= {}
|
458
|
+
post[:payment_method_options][:card] ||= {}
|
459
|
+
post[:payment_method_options][:card][:network_token] ||= {}
|
460
|
+
post[:payment_method_options][:card][:network_token] = {
|
461
|
+
cryptogram: payment_method.respond_to?(:payment_cryptogram) ? payment_method.payment_cryptogram : options[:cryptogram],
|
462
|
+
electronic_commerce_indicator: format_eci(payment_method, options)
|
463
|
+
}.compact
|
464
|
+
end
|
465
|
+
|
466
|
+
def format_eci(payment_method, options)
|
467
|
+
eci_value = payment_method.respond_to?(:eci) ? payment_method.eci : options[:eci]
|
468
|
+
|
469
|
+
if eci_value&.length == 1
|
470
|
+
"0#{eci_value}"
|
471
|
+
else
|
472
|
+
eci_value
|
346
473
|
end
|
347
474
|
end
|
348
475
|
|
@@ -384,7 +511,7 @@ module ActiveMerchant #:nodoc:
|
|
384
511
|
end
|
385
512
|
|
386
513
|
def get_payment_method_data_from_card(post, payment_method, options, responses)
|
387
|
-
return create_payment_method_and_extract_token(post, payment_method, options, responses) unless off_session_request?(options)
|
514
|
+
return create_payment_method_and_extract_token(post, payment_method, options, responses) unless off_session_request?(options) || adding_network_token_card_data?(payment_method)
|
388
515
|
|
389
516
|
post[:payment_method_data] = add_payment_method_data(payment_method, options)
|
390
517
|
end
|
@@ -405,7 +532,7 @@ module ActiveMerchant #:nodoc:
|
|
405
532
|
end
|
406
533
|
|
407
534
|
def add_exemption(post, options = {})
|
408
|
-
return unless options[:confirm]
|
535
|
+
return unless options[:confirm] && options[:moto]
|
409
536
|
|
410
537
|
post[:payment_method_options] ||= {}
|
411
538
|
post[:payment_method_options][:card] ||= {}
|
@@ -418,63 +545,71 @@ module ActiveMerchant #:nodoc:
|
|
418
545
|
# the existing logic by default. To be able to utilize this field, you must reach out to Stripe.
|
419
546
|
|
420
547
|
def add_stored_credentials(post, options = {})
|
421
|
-
|
548
|
+
stored_credential = options[:stored_credential]
|
549
|
+
return unless stored_credential && !stored_credential.values.all?(&:nil?)
|
422
550
|
|
423
551
|
post[:payment_method_options] ||= {}
|
424
552
|
post[:payment_method_options][:card] ||= {}
|
425
|
-
add_stored_credential_transaction_type(post, options) if options[:stored_credential_transaction_type]
|
426
553
|
|
427
|
-
|
428
|
-
|
554
|
+
card_options = post[:payment_method_options][:card]
|
555
|
+
card_options[:mit_exemption] = {}
|
429
556
|
|
430
557
|
# Stripe PI accepts network_transaction_id and ds_transaction_id via mit field under card.
|
431
558
|
# The network_transaction_id can be sent in nested under stored credentials OR as its own field (add_ntid handles when it is sent in on its own)
|
432
559
|
# If it is sent is as its own field AND under stored credentials, the value sent under its own field is what will send.
|
433
|
-
|
434
|
-
|
560
|
+
card_options[:mit_exemption][:ds_transaction_id] = stored_credential[:ds_transaction_id] if stored_credential[:ds_transaction_id]
|
561
|
+
card_options[:mit_exemption][:network_transaction_id] = stored_credential[:network_transaction_id] if !(options[:setup_future_usage] == 'off_session') && (stored_credential[:network_transaction_id])
|
562
|
+
|
563
|
+
add_stored_credential_transaction_type(post, options)
|
435
564
|
end
|
436
565
|
|
437
566
|
def add_stored_credential_transaction_type(post, options = {})
|
567
|
+
return unless options[:stored_credential_transaction_type]
|
568
|
+
|
438
569
|
stored_credential = options[:stored_credential]
|
439
570
|
# Do not add anything unless these are present.
|
440
571
|
return unless stored_credential[:reason_type] && stored_credential[:initiator]
|
441
572
|
|
442
573
|
# Not compatible with off_session parameter.
|
443
574
|
options.delete(:off_session)
|
444
|
-
if stored_credential[:initial_transaction]
|
445
|
-
# Initial transactions must by CIT
|
446
|
-
return unless stored_credential[:initiator] == 'cardholder'
|
447
575
|
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
576
|
+
stored_credential_type = if stored_credential[:initial_transaction]
|
577
|
+
return unless stored_credential[:initiator] == 'cardholder'
|
578
|
+
|
579
|
+
initial_transaction_stored_credential(post, stored_credential)
|
580
|
+
else
|
581
|
+
subsequent_transaction_stored_credential(post, stored_credential)
|
582
|
+
end
|
583
|
+
|
584
|
+
card_options = post[:payment_method_options][:card]
|
585
|
+
card_options[:stored_credential_transaction_type] = stored_credential_type
|
586
|
+
card_options[:mit_exemption].delete(:network_transaction_id) if stored_credential_type == 'setup_on_session'
|
453
587
|
end
|
454
588
|
|
455
|
-
def initial_transaction_stored_credential(post,
|
456
|
-
|
589
|
+
def initial_transaction_stored_credential(post, stored_credential)
|
590
|
+
case stored_credential[:reason_type]
|
591
|
+
when 'unscheduled'
|
457
592
|
# Charge on-session and store card for future one-off payment use
|
458
|
-
|
459
|
-
|
593
|
+
'setup_off_session_unscheduled'
|
594
|
+
when 'recurring'
|
460
595
|
# Charge on-session and store card for future recurring payment use
|
461
|
-
|
596
|
+
'setup_off_session_recurring'
|
462
597
|
else
|
463
598
|
# Charge on-session and store card for future on-session payment use.
|
464
|
-
|
599
|
+
'setup_on_session'
|
465
600
|
end
|
466
601
|
end
|
467
602
|
|
468
|
-
def subsequent_transaction_stored_credential(post,
|
469
|
-
if initiator == 'cardholder'
|
603
|
+
def subsequent_transaction_stored_credential(post, stored_credential)
|
604
|
+
if stored_credential[:initiator] == 'cardholder'
|
470
605
|
# Charge on-session customer using previously stored card.
|
471
|
-
|
472
|
-
elsif reason_type == 'recurring'
|
606
|
+
'stored_on_session'
|
607
|
+
elsif stored_credential[:reason_type] == 'recurring'
|
473
608
|
# Charge off-session customer using previously stored card for recurring transaction
|
474
|
-
|
609
|
+
'stored_off_session_recurring'
|
475
610
|
else
|
476
611
|
# Charge off-session customer using previously stored card for one-off transaction
|
477
|
-
|
612
|
+
'stored_off_session_unscheduled'
|
478
613
|
end
|
479
614
|
end
|
480
615
|
|
@@ -485,7 +620,7 @@ module ActiveMerchant #:nodoc:
|
|
485
620
|
post[:payment_method_options][:card] ||= {}
|
486
621
|
post[:payment_method_options][:card][:mit_exemption] = {}
|
487
622
|
|
488
|
-
post[:payment_method_options][:card][:mit_exemption][:network_transaction_id] = options[:network_transaction_id]
|
623
|
+
post[:payment_method_options][:card][:mit_exemption][:network_transaction_id] = options[:network_transaction_id]
|
489
624
|
end
|
490
625
|
|
491
626
|
def add_claim_without_transaction_id(post, options = {})
|
@@ -501,6 +636,16 @@ module ActiveMerchant #:nodoc:
|
|
501
636
|
post[:payment_method_options][:card][:mit_exemption][:claim_without_transaction_id] = options[:claim_without_transaction_id]
|
502
637
|
end
|
503
638
|
|
639
|
+
def add_billing_address_for_card_tokenization(post, options = {})
|
640
|
+
return unless (billing = options[:billing_address] || options[:address])
|
641
|
+
|
642
|
+
billing = add_address(billing, options)
|
643
|
+
billing[:address].transform_keys! { |k| k == :postal_code ? :address_zip : k.to_s.prepend('address_').to_sym }
|
644
|
+
|
645
|
+
post[:card][:name] = billing[:name]
|
646
|
+
post[:card].merge!(billing[:address])
|
647
|
+
end
|
648
|
+
|
504
649
|
def add_error_on_requires_action(post, options = {})
|
505
650
|
return unless options[:confirm]
|
506
651
|
|
@@ -534,14 +679,18 @@ module ActiveMerchant #:nodoc:
|
|
534
679
|
post
|
535
680
|
end
|
536
681
|
|
537
|
-
def
|
538
|
-
return
|
682
|
+
def add_billing_address(post, payment_method, options = {})
|
683
|
+
return if payment_method.nil? || payment_method.is_a?(StripePaymentToken) || payment_method.is_a?(String)
|
539
684
|
|
540
|
-
|
541
|
-
billing[:
|
685
|
+
post[:payment_method_data] ||= {}
|
686
|
+
if billing = options[:billing_address] || options[:address]
|
687
|
+
post[:payment_method_data][:billing_details] = add_address(billing, options)
|
688
|
+
end
|
542
689
|
|
543
|
-
post[:
|
544
|
-
|
690
|
+
unless post[:payment_method_data][:billing_details]
|
691
|
+
name = [payment_method.first_name, payment_method.last_name].compact.join(' ')
|
692
|
+
post[:payment_method_data][:billing_details] = { name: name }
|
693
|
+
end
|
545
694
|
end
|
546
695
|
|
547
696
|
def add_shipping_address(post, options = {})
|