activemerchant 1.130.0 → 1.137.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +268 -0
  3. data/lib/active_merchant/billing/check.rb +2 -2
  4. data/lib/active_merchant/billing/compatibility.rb +4 -4
  5. data/lib/active_merchant/billing/credit_card.rb +13 -8
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +4 -0
  7. data/lib/active_merchant/billing/credit_card_methods.rb +64 -7
  8. data/lib/active_merchant/billing/gateway.rb +9 -0
  9. data/lib/active_merchant/billing/gateways/adyen.rb +240 -41
  10. data/lib/active_merchant/billing/gateways/airwallex.rb +26 -12
  11. data/lib/active_merchant/billing/gateways/alelo.rb +23 -5
  12. data/lib/active_merchant/billing/gateways/authorize_net.rb +44 -36
  13. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +10 -6
  14. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +1 -3
  15. data/lib/active_merchant/billing/gateways/axcessms.rb +6 -2
  16. data/lib/active_merchant/billing/gateways/banwire.rb +4 -2
  17. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +7 -3
  18. data/lib/active_merchant/billing/gateways/blue_pay.rb +13 -5
  19. data/lib/active_merchant/billing/gateways/blue_snap.rb +5 -5
  20. data/lib/active_merchant/billing/gateways/borgun.rb +6 -4
  21. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +65 -20
  22. data/lib/active_merchant/billing/gateways/braintree_blue.rb +226 -73
  23. data/lib/active_merchant/billing/gateways/braintree_orange.rb +1 -1
  24. data/lib/active_merchant/billing/gateways/card_connect.rb +5 -2
  25. data/lib/active_merchant/billing/gateways/card_stream.rb +4 -6
  26. data/lib/active_merchant/billing/gateways/cashnet.rb +1 -1
  27. data/lib/active_merchant/billing/gateways/cecabank/cecabank_common.rb +36 -0
  28. data/lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb +316 -0
  29. data/lib/active_merchant/billing/gateways/cecabank/cecabank_xml.rb +220 -0
  30. data/lib/active_merchant/billing/gateways/cecabank.rb +7 -240
  31. data/lib/active_merchant/billing/gateways/checkout_v2.rb +252 -41
  32. data/lib/active_merchant/billing/gateways/commerce_hub.rb +69 -8
  33. data/lib/active_merchant/billing/gateways/credorax.rb +3 -5
  34. data/lib/active_merchant/billing/gateways/cyber_source.rb +192 -41
  35. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +102 -58
  36. data/lib/active_merchant/billing/gateways/d_local.rb +26 -15
  37. data/lib/active_merchant/billing/gateways/data_cash.rb +21 -17
  38. data/lib/active_merchant/billing/gateways/datatrans.rb +279 -0
  39. data/lib/active_merchant/billing/gateways/decidir.rb +53 -18
  40. data/lib/active_merchant/billing/gateways/decidir_plus.rb +4 -1
  41. data/lib/active_merchant/billing/gateways/deepstack.rb +382 -0
  42. data/lib/active_merchant/billing/gateways/ebanx.rb +40 -36
  43. data/lib/active_merchant/billing/gateways/efsnet.rb +6 -2
  44. data/lib/active_merchant/billing/gateways/elavon.rb +99 -33
  45. data/lib/active_merchant/billing/gateways/element.rb +36 -7
  46. data/lib/active_merchant/billing/gateways/epay.rb +6 -2
  47. data/lib/active_merchant/billing/gateways/evo_ca.rb +6 -2
  48. data/lib/active_merchant/billing/gateways/eway.rb +4 -2
  49. data/lib/active_merchant/billing/gateways/eway_managed.rb +6 -2
  50. data/lib/active_merchant/billing/gateways/exact.rb +6 -2
  51. data/lib/active_merchant/billing/gateways/fat_zebra.rb +31 -3
  52. data/lib/active_merchant/billing/gateways/federated_canada.rb +6 -2
  53. data/lib/active_merchant/billing/gateways/first_pay/first_pay_common.rb +15 -0
  54. data/lib/active_merchant/billing/gateways/first_pay/first_pay_json.rb +190 -0
  55. data/lib/active_merchant/billing/gateways/first_pay/first_pay_xml.rb +183 -0
  56. data/lib/active_merchant/billing/gateways/first_pay.rb +6 -172
  57. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +6 -2
  58. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +7 -3
  59. data/lib/active_merchant/billing/gateways/flex_charge.rb +347 -0
  60. data/lib/active_merchant/billing/gateways/garanti.rb +4 -2
  61. data/lib/active_merchant/billing/gateways/global_collect.rb +45 -37
  62. data/lib/active_merchant/billing/gateways/hi_pay.rb +286 -0
  63. data/lib/active_merchant/billing/gateways/hps.rb +1 -1
  64. data/lib/active_merchant/billing/gateways/iats_payments.rb +7 -2
  65. data/lib/active_merchant/billing/gateways/inspire.rb +6 -4
  66. data/lib/active_merchant/billing/gateways/instapay.rb +7 -4
  67. data/lib/active_merchant/billing/gateways/ipg.rb +10 -6
  68. data/lib/active_merchant/billing/gateways/iridium.rb +15 -5
  69. data/lib/active_merchant/billing/gateways/itransact.rb +6 -2
  70. data/lib/active_merchant/billing/gateways/iveri.rb +3 -3
  71. data/lib/active_merchant/billing/gateways/ixopay.rb +2 -2
  72. data/lib/active_merchant/billing/gateways/jetpay.rb +4 -2
  73. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +4 -2
  74. data/lib/active_merchant/billing/gateways/kushki.rb +73 -13
  75. data/lib/active_merchant/billing/gateways/linkpoint.rb +6 -2
  76. data/lib/active_merchant/billing/gateways/litle.rb +33 -50
  77. data/lib/active_merchant/billing/gateways/mastercard.rb +4 -4
  78. data/lib/active_merchant/billing/gateways/maxipago.rb +2 -2
  79. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +8 -5
  80. data/lib/active_merchant/billing/gateways/merchant_ware.rb +11 -4
  81. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +11 -4
  82. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +19 -3
  83. data/lib/active_merchant/billing/gateways/mercury.rb +6 -2
  84. data/lib/active_merchant/billing/gateways/metrics_global.rb +8 -6
  85. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +1 -0
  86. data/lib/active_merchant/billing/gateways/migs.rb +6 -2
  87. data/lib/active_merchant/billing/gateways/mit.rb +25 -20
  88. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +18 -10
  89. data/lib/active_merchant/billing/gateways/monei.rb +1 -1
  90. data/lib/active_merchant/billing/gateways/moneris.rb +9 -3
  91. data/lib/active_merchant/billing/gateways/money_movers.rb +6 -2
  92. data/lib/active_merchant/billing/gateways/nab_transact.rb +12 -4
  93. data/lib/active_merchant/billing/gateways/net_registry.rb +6 -2
  94. data/lib/active_merchant/billing/gateways/netbanx.rb +1 -3
  95. data/lib/active_merchant/billing/gateways/netbilling.rb +6 -2
  96. data/lib/active_merchant/billing/gateways/network_merchants.rb +6 -2
  97. data/lib/active_merchant/billing/gateways/nmi.rb +23 -6
  98. data/lib/active_merchant/billing/gateways/ogone.rb +6 -2
  99. data/lib/active_merchant/billing/gateways/openpay.rb +4 -2
  100. data/lib/active_merchant/billing/gateways/opp.rb +1 -2
  101. data/lib/active_merchant/billing/gateways/optimal_payment.rb +6 -2
  102. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +1 -3
  103. data/lib/active_merchant/billing/gateways/orbital.rb +83 -24
  104. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +7 -4
  105. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +6 -2
  106. data/lib/active_merchant/billing/gateways/pay_hub.rb +4 -2
  107. data/lib/active_merchant/billing/gateways/pay_junction.rb +6 -2
  108. data/lib/active_merchant/billing/gateways/pay_secure.rb +6 -2
  109. data/lib/active_merchant/billing/gateways/pay_trace.rb +31 -18
  110. data/lib/active_merchant/billing/gateways/payeezy.rb +19 -8
  111. data/lib/active_merchant/billing/gateways/payex.rb +4 -2
  112. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
  113. data/lib/active_merchant/billing/gateways/payflow.rb +1 -3
  114. data/lib/active_merchant/billing/gateways/payment_express.rb +8 -4
  115. data/lib/active_merchant/billing/gateways/paymentez.rb +23 -11
  116. data/lib/active_merchant/billing/gateways/paysafe.rb +12 -11
  117. data/lib/active_merchant/billing/gateways/payscout.rb +7 -4
  118. data/lib/active_merchant/billing/gateways/paystation.rb +7 -3
  119. data/lib/active_merchant/billing/gateways/payway.rb +6 -2
  120. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +3 -3
  121. data/lib/active_merchant/billing/gateways/pin.rb +22 -4
  122. data/lib/active_merchant/billing/gateways/plexo.rb +49 -10
  123. data/lib/active_merchant/billing/gateways/plugnpay.rb +6 -2
  124. data/lib/active_merchant/billing/gateways/priority.rb +6 -5
  125. data/lib/active_merchant/billing/gateways/psigate.rb +6 -2
  126. data/lib/active_merchant/billing/gateways/psl_card.rb +6 -2
  127. data/lib/active_merchant/billing/gateways/qbms.rb +6 -2
  128. data/lib/active_merchant/billing/gateways/quantum.rb +6 -2
  129. data/lib/active_merchant/billing/gateways/quickbooks.rb +6 -5
  130. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +7 -4
  131. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +6 -2
  132. data/lib/active_merchant/billing/gateways/rapyd.rb +148 -46
  133. data/lib/active_merchant/billing/gateways/reach.rb +11 -4
  134. data/lib/active_merchant/billing/gateways/redsys.rb +3 -11
  135. data/lib/active_merchant/billing/gateways/redsys_rest.rb +507 -0
  136. data/lib/active_merchant/billing/gateways/s5.rb +3 -3
  137. data/lib/active_merchant/billing/gateways/safe_charge.rb +38 -17
  138. data/lib/active_merchant/billing/gateways/sage.rb +12 -4
  139. data/lib/active_merchant/billing/gateways/sage_pay.rb +79 -5
  140. data/lib/active_merchant/billing/gateways/sallie_mae.rb +6 -2
  141. data/lib/active_merchant/billing/gateways/secure_net.rb +6 -2
  142. data/lib/active_merchant/billing/gateways/secure_pay.rb +8 -6
  143. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +12 -4
  144. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +6 -2
  145. data/lib/active_merchant/billing/gateways/securion_pay.rb +24 -10
  146. data/lib/active_merchant/billing/gateways/shift4.rb +17 -20
  147. data/lib/active_merchant/billing/gateways/shift4_v2.rb +117 -0
  148. data/lib/active_merchant/billing/gateways/simetrik.rb +17 -11
  149. data/lib/active_merchant/billing/gateways/skip_jack.rb +6 -2
  150. data/lib/active_merchant/billing/gateways/smart_ps.rb +7 -4
  151. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +4 -2
  152. data/lib/active_merchant/billing/gateways/spreedly_core.rb +2 -4
  153. data/lib/active_merchant/billing/gateways/stripe.rb +63 -19
  154. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +280 -88
  155. data/lib/active_merchant/billing/gateways/sum_up.rb +223 -0
  156. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +4 -2
  157. data/lib/active_merchant/billing/gateways/telr.rb +3 -4
  158. data/lib/active_merchant/billing/gateways/trans_first.rb +1 -2
  159. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +8 -16
  160. data/lib/active_merchant/billing/gateways/transact_pro.rb +1 -1
  161. data/lib/active_merchant/billing/gateways/trust_commerce.rb +6 -2
  162. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +9 -8
  163. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +6 -2
  164. data/lib/active_merchant/billing/gateways/vanco.rb +2 -4
  165. data/lib/active_merchant/billing/gateways/vantiv_express.rb +587 -0
  166. data/lib/active_merchant/billing/gateways/verifi.rb +6 -2
  167. data/lib/active_merchant/billing/gateways/viaklix.rb +6 -2
  168. data/lib/active_merchant/billing/gateways/visanet_peru.rb +2 -2
  169. data/lib/active_merchant/billing/gateways/vpos.rb +4 -4
  170. data/lib/active_merchant/billing/gateways/wirecard.rb +7 -3
  171. data/lib/active_merchant/billing/gateways/wompi.rb +5 -0
  172. data/lib/active_merchant/billing/gateways/worldpay.rb +147 -93
  173. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +13 -10
  174. data/lib/active_merchant/billing/gateways/xpay.rb +242 -0
  175. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
  176. data/lib/active_merchant/billing/response.rb +2 -2
  177. data/lib/active_merchant/connection.rb +3 -17
  178. data/lib/active_merchant/country.rb +1 -0
  179. data/lib/active_merchant/errors.rb +10 -0
  180. data/lib/active_merchant/version.rb +1 -1
  181. data/lib/support/gateway_support.rb +2 -2
  182. data/lib/support/ssl_verify.rb +4 -4
  183. data/lib/support/ssl_version.rb +6 -6
  184. metadata +30 -9
@@ -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,24 +30,32 @@ module ActiveMerchant #:nodoc:
25
30
  add_confirmation_method(post, options)
26
31
  add_customer(post, options)
27
32
 
28
- result = add_payment_method_token(post, payment_method, options)
29
- return result if result.is_a?(ActiveMerchant::Billing::Response)
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)
34
45
  add_connected_account(post, options)
35
46
  add_radar_data(post, options)
36
47
  add_shipping_address(post, options)
48
+ add_stored_credentials(post, options)
37
49
  setup_future_usage(post, options)
38
50
  add_exemption(post, options)
39
- add_stored_credentials(post, options)
40
51
  add_ntid(post, options)
41
52
  add_claim_without_transaction_id(post, options)
42
53
  add_error_on_requires_action(post, options)
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
- result = add_payment_method_token(post, payment_method, options)
67
- return result if result.is_a?(ActiveMerchant::Billing::Response)
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|
@@ -76,22 +93,33 @@ module ActiveMerchant #:nodoc:
76
93
 
77
94
  def create_payment_method(payment_method, options = {})
78
95
  post_data = add_payment_method_data(payment_method, options)
79
-
80
96
  options = format_idempotency_key(options, 'pm')
81
97
  commit(:post, 'payment_methods', post_data, options)
82
98
  end
83
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
+
84
106
  def add_payment_method_data(payment_method, options = {})
85
- post_data = {}
86
- post_data[:type] = 'card'
87
- post_data[:card] = {}
88
- post_data[:card][:number] = payment_method.number
89
- post_data[:card][:exp_month] = payment_method.month
90
- post_data[:card][:exp_year] = payment_method.year
91
- post_data[:card][:cvc] = payment_method.verification_value if payment_method.verification_value
92
- add_billing_address(post_data, options)
93
- add_name_only(post_data, payment_method) if post_data[:billing_details].nil?
94
- post_data
107
+ post = {
108
+ type: 'card',
109
+ card: {
110
+ exp_month: payment_method.month,
111
+ exp_year: payment_method.year
112
+ }
113
+ }
114
+ post[:card][:number] = payment_method.number unless adding_network_token_card_data?(payment_method)
115
+ post[:card][:cvc] = payment_method.verification_value if payment_method.verification_value
116
+ if billing = options[:billing_address] || options[:address]
117
+ post[:billing_details] = add_address(billing, options)
118
+ end
119
+
120
+ add_name_only(post, payment_method) if post[:billing_details].nil?
121
+ add_network_token_data(post, payment_method, options)
122
+ post
95
123
  end
96
124
 
97
125
  def add_payment_method_card_data_token(post_data, payment_method)
@@ -105,8 +133,12 @@ module ActiveMerchant #:nodoc:
105
133
  post = {}
106
134
  add_amount(post, money, options)
107
135
 
108
- result = add_payment_method_token(post, payment_method, options)
109
- return result if result.is_a?(ActiveMerchant::Billing::Response)
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
110
142
 
111
143
  add_payment_method_types(post, options)
112
144
  add_customer(post, options)
@@ -126,16 +158,25 @@ module ActiveMerchant #:nodoc:
126
158
  r.process do
127
159
  post = {}
128
160
  add_customer(post, options)
129
- result = add_payment_method_token(post, payment_method, options, r)
130
- return result if result.is_a?(ActiveMerchant::Billing::Response)
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
131
169
 
132
170
  add_metadata(post, options)
133
171
  add_return_url(post, options)
134
172
  add_fulfillment_date(post, options)
135
173
  request_three_d_secure(post, options)
174
+ add_card_brand(post, options)
175
+ add_exemption(post, options)
136
176
  post[:on_behalf_of] = options[:on_behalf_of] if options[:on_behalf_of]
137
177
  post[:usage] = options[:usage] if %w(on_session off_session).include?(options[:usage])
138
178
  post[:description] = options[:description] if options[:description]
179
+ post[:expand] = ['latest_attempt']
139
180
 
140
181
  commit(:post, 'setup_intents', post, options)
141
182
  end
@@ -205,23 +246,16 @@ module ActiveMerchant #:nodoc:
205
246
  # All other types will default to legacy Stripe store
206
247
  def store(payment_method, options = {})
207
248
  params = {}
208
- post = {}
209
249
  # If customer option is provided, create a payment method and attach to customer id
210
250
  # Otherwise, create a customer, then attach
211
- if payment_method.is_a?(StripePaymentToken) || payment_method.is_a?(ActiveMerchant::Billing::CreditCard)
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)
212
255
  result = add_payment_method_token(params, payment_method, options)
213
256
  return result if result.is_a?(ActiveMerchant::Billing::Response)
214
257
 
215
- if options[:customer]
216
- customer_id = options[:customer]
217
- else
218
- post[:description] = options[:description] if options[:description]
219
- post[:email] = options[:email] if options[:email]
220
- options = format_idempotency_key(options, 'customer')
221
- post[:expand] = [:sources]
222
- customer = commit(:post, 'customers', post, options)
223
- customer_id = customer.params['id']
224
- end
258
+ customer_id = options[:customer] || customer(payment_method, options).params['id']
225
259
  options = format_idempotency_key(options, 'attach')
226
260
  attach_parameters = { customer: customer_id }
227
261
  attach_parameters[:validate] = options[:validate] unless options[:validate].nil?
@@ -231,6 +265,24 @@ module ActiveMerchant #:nodoc:
231
265
  end
232
266
  end
233
267
 
268
+ def customer(payment, options)
269
+ post = {}
270
+ post[:description] = options[:description] if options[:description]
271
+ post[:expand] = [:sources]
272
+ post[:email] = options[:email]
273
+
274
+ if billing = options[:billing_address] || options[:address]
275
+ post.merge!(add_address(billing, options))
276
+ end
277
+
278
+ if shipping = options[:shipping_address]
279
+ post[:shipping] = add_address(shipping, options).except(:email)
280
+ end
281
+
282
+ options = format_idempotency_key(options, 'customer')
283
+ commit(:post, 'customers', post, options)
284
+ end
285
+
234
286
  def unstore(identification, options = {}, deprecated_options = {})
235
287
  if identification.include?('pm_')
236
288
  _, payment_method = identification.split('|')
@@ -254,8 +306,22 @@ module ActiveMerchant #:nodoc:
254
306
  commit(:post, 'payment_intents', post, options)
255
307
  end
256
308
 
309
+ def supports_network_tokenization?
310
+ true
311
+ end
312
+
257
313
  private
258
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
+
259
325
  def off_session_request?(options = {})
260
326
  (options[:off_session] || options[:setup_future_usage]) && options[:confirm] == true
261
327
  end
@@ -294,6 +360,14 @@ module ActiveMerchant #:nodoc:
294
360
  post[:metadata][:event_type] = options[:event_type] if options[:event_type]
295
361
  end
296
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
+
297
371
  def add_level_three(post, options = {})
298
372
  level_three = {}
299
373
 
@@ -329,10 +403,76 @@ module ActiveMerchant #:nodoc:
329
403
  when ActiveMerchant::Billing::CreditCard
330
404
  return create_payment_method_and_extract_token(post, payment_method, options, responses) if options[:verify]
331
405
 
406
+ get_payment_method_data_from_card(post, payment_method, options, responses)
407
+ when ActiveMerchant::Billing::NetworkTokenizationCreditCard
332
408
  get_payment_method_data_from_card(post, payment_method, options, responses)
333
409
  end
334
410
  end
335
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
473
+ end
474
+ end
475
+
336
476
  def extract_token_from_string_and_maybe_add_customer_id(post, payment_method)
337
477
  if payment_method.include?('|')
338
478
  customer_id, payment_method = payment_method.split('|')
@@ -371,7 +511,7 @@ module ActiveMerchant #:nodoc:
371
511
  end
372
512
 
373
513
  def get_payment_method_data_from_card(post, payment_method, options, responses)
374
- 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)
375
515
 
376
516
  post[:payment_method_data] = add_payment_method_data(payment_method, options)
377
517
  end
@@ -392,31 +532,85 @@ module ActiveMerchant #:nodoc:
392
532
  end
393
533
 
394
534
  def add_exemption(post, options = {})
395
- return unless options[:confirm]
535
+ return unless options[:confirm] && options[:moto]
396
536
 
397
537
  post[:payment_method_options] ||= {}
398
538
  post[:payment_method_options][:card] ||= {}
399
539
  post[:payment_method_options][:card][:moto] = true if options[:moto]
400
540
  end
401
541
 
402
- # Stripe Payment Intents does not pass any parameters for cardholder/merchant initiated
403
- # it also does not support installments for any country other than Mexico (reason for this is unknown)
404
- # The only thing that Stripe PI requires for stored credentials to work currently is the network_transaction_id
405
- # network_transaction_id is created when the card is authenticated using the field `setup_for_future_usage` with the value `off_session` see def setup_future_usage below
542
+ # Stripe Payment Intents now supports specifying on a transaction level basis stored credential information.
543
+ # The feature is currently gated but is listed as `stored_credential_transaction_type` inside the
544
+ # `post[:payment_method_options][:card]` hash. Since this is a beta field adding an extra check to use
545
+ # the existing logic by default. To be able to utilize this field, you must reach out to Stripe.
406
546
 
407
547
  def add_stored_credentials(post, options = {})
408
- return unless options[:stored_credential] && !options[:stored_credential].values.all?(&:nil?)
409
-
410
548
  stored_credential = options[:stored_credential]
549
+ return unless stored_credential && !stored_credential.values.all?(&:nil?)
550
+
411
551
  post[:payment_method_options] ||= {}
412
552
  post[:payment_method_options][:card] ||= {}
413
- post[:payment_method_options][:card][:mit_exemption] = {}
553
+
554
+ card_options = post[:payment_method_options][:card]
555
+ card_options[:mit_exemption] = {}
414
556
 
415
557
  # Stripe PI accepts network_transaction_id and ds_transaction_id via mit field under card.
416
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)
417
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.
418
- post[:payment_method_options][:card][:mit_exemption][:ds_transaction_id] = stored_credential[:ds_transaction_id] if stored_credential[:ds_transaction_id]
419
- post[:payment_method_options][:card][:mit_exemption][:network_transaction_id] = stored_credential[:network_transaction_id] if stored_credential[:network_transaction_id]
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)
564
+ end
565
+
566
+ def add_stored_credential_transaction_type(post, options = {})
567
+ return unless options[:stored_credential_transaction_type]
568
+
569
+ stored_credential = options[:stored_credential]
570
+ # Do not add anything unless these are present.
571
+ return unless stored_credential[:reason_type] && stored_credential[:initiator]
572
+
573
+ # Not compatible with off_session parameter.
574
+ options.delete(:off_session)
575
+
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'
587
+ end
588
+
589
+ def initial_transaction_stored_credential(post, stored_credential)
590
+ case stored_credential[:reason_type]
591
+ when 'unscheduled'
592
+ # Charge on-session and store card for future one-off payment use
593
+ 'setup_off_session_unscheduled'
594
+ when 'recurring'
595
+ # Charge on-session and store card for future recurring payment use
596
+ 'setup_off_session_recurring'
597
+ else
598
+ # Charge on-session and store card for future on-session payment use.
599
+ 'setup_on_session'
600
+ end
601
+ end
602
+
603
+ def subsequent_transaction_stored_credential(post, stored_credential)
604
+ if stored_credential[:initiator] == 'cardholder'
605
+ # Charge on-session customer using previously stored card.
606
+ 'stored_on_session'
607
+ elsif stored_credential[:reason_type] == 'recurring'
608
+ # Charge off-session customer using previously stored card for recurring transaction
609
+ 'stored_off_session_recurring'
610
+ else
611
+ # Charge off-session customer using previously stored card for one-off transaction
612
+ 'stored_off_session_unscheduled'
613
+ end
420
614
  end
421
615
 
422
616
  def add_ntid(post, options = {})
@@ -426,7 +620,7 @@ module ActiveMerchant #:nodoc:
426
620
  post[:payment_method_options][:card] ||= {}
427
621
  post[:payment_method_options][:card][:mit_exemption] = {}
428
622
 
429
- post[:payment_method_options][:card][:mit_exemption][:network_transaction_id] = options[:network_transaction_id] if options[:network_transaction_id]
623
+ post[:payment_method_options][:card][:mit_exemption][:network_transaction_id] = options[:network_transaction_id]
430
624
  end
431
625
 
432
626
  def add_claim_without_transaction_id(post, options = {})
@@ -442,6 +636,16 @@ module ActiveMerchant #:nodoc:
442
636
  post[:payment_method_options][:card][:mit_exemption][:claim_without_transaction_id] = options[:claim_without_transaction_id]
443
637
  end
444
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
+
445
649
  def add_error_on_requires_action(post, options = {})
446
650
  return unless options[:confirm]
447
651
 
@@ -475,33 +679,42 @@ module ActiveMerchant #:nodoc:
475
679
  post
476
680
  end
477
681
 
478
- def add_billing_address_for_card_tokenization(post, options = {})
479
- return unless (billing = options[:billing_address] || options[:address])
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)
684
+
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
480
689
 
481
- post[:card][:address_city] = billing[:city] if billing[:city]
482
- post[:card][:address_country] = billing[:country] if billing[:country]
483
- post[:card][:address_line1] = billing[:address1] if billing[:address1]
484
- post[:card][:address_line2] = billing[:address2] if billing[:address2]
485
- post[:card][:address_zip] = billing[:zip] if billing[:zip]
486
- post[:card][:address_state] = billing[:state] if billing[:state]
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
487
694
  end
488
695
 
489
- def add_billing_address(post, options = {})
490
- return unless billing = options[:billing_address] || options[:address]
696
+ def add_shipping_address(post, options = {})
697
+ return unless shipping = options[:shipping_address]
491
698
 
492
- email = billing[:email] || options[:email]
699
+ post[:shipping] = add_address(shipping, options).except(:email)
700
+ post[:shipping][:carrier] = (shipping[:carrier] || options[:shipping_carrier]) if shipping[:carrier] || options[:shipping_carrier]
701
+ post[:shipping][:tracking_number] = (shipping[:tracking_number] || options[:shipping_tracking_number]) if shipping[:tracking_number] || options[:shipping_tracking_number]
702
+ end
493
703
 
494
- post[:billing_details] = {}
495
- post[:billing_details][:address] = {}
496
- post[:billing_details][:address][:city] = billing[:city] if billing[:city]
497
- post[:billing_details][:address][:country] = billing[:country] if billing[:country]
498
- post[:billing_details][:address][:line1] = billing[:address1] if billing[:address1]
499
- post[:billing_details][:address][:line2] = billing[:address2] if billing[:address2]
500
- post[:billing_details][:address][:postal_code] = billing[:zip] if billing[:zip]
501
- post[:billing_details][:address][:state] = billing[:state] if billing[:state]
502
- post[:billing_details][:email] = email if email
503
- post[:billing_details][:name] = billing[:name] if billing[:name]
504
- post[:billing_details][:phone] = billing[:phone] if billing[:phone]
704
+ def add_address(address, options)
705
+ {
706
+ address: {
707
+ city: address[:city],
708
+ country: address[:country],
709
+ line1: address[:address1],
710
+ line2: address[:address2],
711
+ postal_code: address[:zip],
712
+ state: address[:state]
713
+ }.compact,
714
+ email: address[:email] || options[:email],
715
+ phone: address[:phone] || address[:phone_number],
716
+ name: address[:name]
717
+ }.compact
505
718
  end
506
719
 
507
720
  def add_name_only(post, payment_method)
@@ -511,27 +724,6 @@ module ActiveMerchant #:nodoc:
511
724
  post[:billing_details][:name] = name
512
725
  end
513
726
 
514
- def add_shipping_address(post, options = {})
515
- return unless shipping = options[:shipping_address]
516
-
517
- post[:shipping] = {}
518
-
519
- # fields required by Stripe PI
520
- post[:shipping][:address] = {}
521
- post[:shipping][:address][:line1] = shipping[:address1]
522
- post[:shipping][:name] = shipping[:name]
523
-
524
- # fields considered optional by Stripe PI
525
- post[:shipping][:address][:city] = shipping[:city] if shipping[:city]
526
- post[:shipping][:address][:country] = shipping[:country] if shipping[:country]
527
- post[:shipping][:address][:line2] = shipping[:address2] if shipping[:address2]
528
- post[:shipping][:address][:postal_code] = shipping[:zip] if shipping[:zip]
529
- post[:shipping][:address][:state] = shipping[:state] if shipping[:state]
530
- post[:shipping][:phone] = shipping[:phone_number] if shipping[:phone_number]
531
- post[:shipping][:carrier] = (shipping[:carrier] || options[:shipping_carrier]) if shipping[:carrier] || options[:shipping_carrier]
532
- post[:shipping][:tracking_number] = (shipping[:tracking_number] || options[:shipping_tracking_number]) if shipping[:tracking_number] || options[:shipping_tracking_number]
533
- end
534
-
535
727
  def format_idempotency_key(options, suffix)
536
728
  return options unless options[:idempotency_key]
537
729