activemerchant 1.133.0 → 1.137.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 = {})
|