activemerchant 1.125.0 → 1.126.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +75 -0
  3. data/lib/active_merchant/billing/credit_card_methods.rb +12 -0
  4. data/lib/active_merchant/billing/gateway.rb +2 -1
  5. data/lib/active_merchant/billing/gateways/adyen.rb +7 -4
  6. data/lib/active_merchant/billing/gateways/airwallex.rb +341 -0
  7. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +2 -1
  8. data/lib/active_merchant/billing/gateways/blue_pay.rb +1 -1
  9. data/lib/active_merchant/billing/gateways/blue_snap.rb +31 -21
  10. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +6 -1
  11. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +113 -0
  12. data/lib/active_merchant/billing/gateways/braintree_blue.rb +87 -15
  13. data/lib/active_merchant/billing/gateways/card_connect.rb +1 -1
  14. data/lib/active_merchant/billing/gateways/checkout_v2.rb +1 -1
  15. data/lib/active_merchant/billing/gateways/credorax.rb +10 -0
  16. data/lib/active_merchant/billing/gateways/cyber_source.rb +13 -33
  17. data/lib/active_merchant/billing/gateways/d_local.rb +49 -0
  18. data/lib/active_merchant/billing/gateways/decidir.rb +17 -1
  19. data/lib/active_merchant/billing/gateways/decidir_plus.rb +185 -14
  20. data/lib/active_merchant/billing/gateways/ebanx.rb +3 -2
  21. data/lib/active_merchant/billing/gateways/global_collect.rb +26 -16
  22. data/lib/active_merchant/billing/gateways/ipg.rb +1 -2
  23. data/lib/active_merchant/billing/gateways/litle.rb +93 -1
  24. data/lib/active_merchant/billing/gateways/moneris.rb +35 -8
  25. data/lib/active_merchant/billing/gateways/nmi.rb +12 -7
  26. data/lib/active_merchant/billing/gateways/orbital.rb +349 -327
  27. data/lib/active_merchant/billing/gateways/payflow.rb +62 -0
  28. data/lib/active_merchant/billing/gateways/paymentez.rb +26 -7
  29. data/lib/active_merchant/billing/gateways/paysafe.rb +15 -15
  30. data/lib/active_merchant/billing/gateways/payu_latam.rb +25 -15
  31. data/lib/active_merchant/billing/gateways/priority.rb +158 -136
  32. data/lib/active_merchant/billing/gateways/rapyd.rb +258 -0
  33. data/lib/active_merchant/billing/gateways/safe_charge.rb +1 -4
  34. data/lib/active_merchant/billing/gateways/simetrik.rb +362 -0
  35. data/lib/active_merchant/billing/gateways/stripe.rb +4 -2
  36. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +93 -48
  37. data/lib/active_merchant/billing/gateways/visanet_peru.rb +6 -2
  38. data/lib/active_merchant/version.rb +1 -1
  39. metadata +6 -2
@@ -0,0 +1,362 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class SimetrikGateway < Gateway
4
+ self.test_url = 'https://payments.sta.simetrik.com/v1'
5
+ self.live_url = 'https://payments.simetrik.com/v1'
6
+
7
+ class_attribute :test_auth_url, :live_auth_url
8
+ self.test_auth_url = 'https://tenant-payments-dev.us.auth0.com/oauth/token'
9
+ self.live_auth_url = 'https://tenant-payments-prod.us.auth0.com/oauth/token'
10
+
11
+ self.supported_countries = %w(PE AR)
12
+ self.default_currency = 'USD'
13
+ self.supported_cardtypes = %i[visa master american_express discover]
14
+
15
+ self.homepage_url = 'https://www.simetrik.com'
16
+ self.display_name = 'Simetrik'
17
+
18
+ STANDARD_ERROR_CODE_MAPPING = {
19
+ 'R101' => STANDARD_ERROR_CODE[:incorrect_number],
20
+ 'R102' => STANDARD_ERROR_CODE[:invalid_number],
21
+ 'R103' => STANDARD_ERROR_CODE[:invalid_expiry_date],
22
+ 'R104' => STANDARD_ERROR_CODE[:invalid_cvc],
23
+ 'R105' => STANDARD_ERROR_CODE[:expired_card],
24
+ 'R106' => STANDARD_ERROR_CODE[:incorrect_cvc],
25
+ 'R107' => STANDARD_ERROR_CODE[:incorrect_pin],
26
+ 'R201' => STANDARD_ERROR_CODE[:incorrect_zip],
27
+ 'R202' => STANDARD_ERROR_CODE[:incorrect_address],
28
+ 'R301' => STANDARD_ERROR_CODE[:card_declined],
29
+ 'R302' => STANDARD_ERROR_CODE[:processing_error],
30
+ 'R303' => STANDARD_ERROR_CODE[:call_issuer],
31
+ 'R304' => STANDARD_ERROR_CODE[:pick_up_card],
32
+ 'R305' => STANDARD_ERROR_CODE[:processing_error],
33
+ 'R306' => STANDARD_ERROR_CODE[:processing_error],
34
+ 'R307' => STANDARD_ERROR_CODE[:processing_error],
35
+ 'R401' => STANDARD_ERROR_CODE[:config_error],
36
+ 'R402' => STANDARD_ERROR_CODE[:test_mode_live_card],
37
+ 'R403' => STANDARD_ERROR_CODE[:unsupported_feature]
38
+
39
+ }
40
+
41
+ def initialize(options = {})
42
+ requires!(options, :client_id, :client_secret, :audience)
43
+ super
44
+ @access_token = {}
45
+ sign_access_token()
46
+ end
47
+
48
+ def authorize(money, payment, options = {})
49
+ requires!(options, :token_acquirer)
50
+
51
+ post = {}
52
+ add_forward_route(post, options)
53
+ add_forward_payload(post, money, payment, options)
54
+ add_stored_credential(post, options)
55
+
56
+ commit('authorize', post, { token_acquirer: options[:token_acquirer] })
57
+ end
58
+
59
+ def capture(money, authorization, options = {})
60
+ requires!(options, :token_acquirer)
61
+ post = {
62
+ forward_payload: {
63
+ amount: {
64
+ total_amount: amount(money).to_f,
65
+ currency: (options[:currency] || currency(money))
66
+ },
67
+ transaction: {
68
+ id: authorization
69
+ },
70
+ acquire_extra_options: options[:acquire_extra_options] || {}
71
+ }
72
+ }
73
+ post[:forward_payload][:amount][:vat] = options[:vat] if options[:vat]
74
+
75
+ add_forward_route(post, options)
76
+ commit('capture', post, { token_acquirer: options[:token_acquirer] })
77
+ end
78
+
79
+ def refund(money, authorization, options = {})
80
+ requires!(options, :token_acquirer)
81
+ post = {
82
+ forward_payload: {
83
+ amount: {
84
+ total_amount: amount(money).to_f,
85
+ currency: (options[:currency] || currency(money))
86
+ },
87
+ transaction: {
88
+ id: authorization
89
+ },
90
+ acquire_extra_options: options[:acquire_extra_options] || {}
91
+ }
92
+ }
93
+ post[:forward_payload][:transaction][:comment] = options[:comment] if options[:comment]
94
+
95
+ add_forward_route(post, options)
96
+ commit('refund', post, { token_acquirer: options[:token_acquirer] })
97
+ end
98
+
99
+ def void(authorization, options = {})
100
+ requires!(options, :token_acquirer)
101
+ post = {
102
+ forward_payload: {
103
+ transaction: {
104
+ id: authorization
105
+ },
106
+ acquire_extra_options: options[:acquire_extra_options] || {}
107
+ }
108
+ }
109
+ add_forward_route(post, options)
110
+ commit('void', post, { token_acquirer: options[:token_acquirer] })
111
+ end
112
+
113
+ def purchase(money, payment, options = {})
114
+ requires!(options, :token_acquirer)
115
+
116
+ post = {}
117
+ add_forward_route(post, options)
118
+ add_forward_payload(post, money, payment, options)
119
+
120
+ add_stored_credential(post, options)
121
+ commit('charge', post, { token_acquirer: options[:token_acquirer] })
122
+ end
123
+
124
+ def supports_scrubbing?
125
+ true
126
+ end
127
+
128
+ def scrub(transcript)
129
+ transcript.
130
+ gsub(%r((\"number\\\":\\\")\d+), '\1[FILTERED]').
131
+ gsub(%r((\"security_code\\\":\\\")\d+), '\1[FILTERED]').
132
+ gsub(%r((\"exp_month\\\":\\\")\d+), '\1[FILTERED]').
133
+ gsub(%r((\"exp_year\\\":\\\")\d+), '\1[FILTERED]').
134
+ gsub(%r((\"holder_first_name\\\":\\\")"\w+"), '\1[FILTERED]').
135
+ gsub(%r((\"holder_last_name\\\":\\\")"\w+"), '\1[FILTERED]')
136
+ end
137
+
138
+ private
139
+
140
+ def add_forward_route(post, options)
141
+ forward_route = {}
142
+ forward_route[:trace_id] = options[:trace_id] if options[:trace_id]
143
+
144
+ forward_route[:psp_extra_fields] = options[:psp_extra_fields] || {}
145
+ post[:forward_route] = forward_route
146
+ end
147
+
148
+ def add_forward_payload(post, money, payment, options)
149
+ forward_payload = {}
150
+ add_user(forward_payload, options[:user]) if options[:user]
151
+ add_order(forward_payload, money, options[:order]) if options[:order] || money
152
+ add_payment_method(forward_payload, payment, options[:payment_method]) if options[:payment_method] || payment
153
+
154
+ forward_payload[:payment_method] = {} unless forward_payload[:payment_method]
155
+ forward_payload[:payment_method][:card] = {} unless forward_payload[:payment_method][:card]
156
+ add_address('billing_address', forward_payload[:payment_method][:card], options[:billing_address]) if options[:billing_address]
157
+
158
+ add_three_ds_fields(forward_payload[:authentication] = {}, options[:three_ds_fields]) if options[:three_ds_fields]
159
+ add_sub_merchant(forward_payload, options[:sub_merchant]) if options[:sub_merchant]
160
+ forward_payload[:acquire_extra_options] = options[:acquire_extra_options] || {}
161
+ post[:forward_payload] = forward_payload
162
+ end
163
+
164
+ def add_sub_merchant(post, sub_merchant_options)
165
+ sub_merchant = {}
166
+ sub_merchant[:merchant_id] = sub_merchant_options[:merchant_id] if sub_merchant_options[:merchant_id]
167
+ sub_merchant[:extra_params] = sub_merchant_options[:extra_params] if sub_merchant_options[:extra_params]
168
+ sub_merchant[:mcc] = sub_merchant_options[:mcc] if sub_merchant_options[:mcc]
169
+ sub_merchant[:name] = sub_merchant_options[:name] if sub_merchant_options[:name]
170
+ sub_merchant[:address] = sub_merchant_options[:address] if sub_merchant_options[:address]
171
+ sub_merchant[:postal_code] = sub_merchant_options[:postal_code] if sub_merchant_options[:postal_code]
172
+ sub_merchant[:url] = sub_merchant_options[:url] if sub_merchant_options[:url]
173
+ sub_merchant[:phone_number] = sub_merchant_options[:phone_number] if sub_merchant_options[:phone_number]
174
+
175
+ post[:sub_merchant] = sub_merchant
176
+ end
177
+
178
+ def add_payment_method(post, payment, payment_method_options)
179
+ payment_method = {}
180
+ opts = nil
181
+ opts = payment_method_options[:card] if payment_method_options
182
+ add_card(payment_method, payment, opts) if opts || payment
183
+
184
+ post[:payment_method] = payment_method
185
+ end
186
+
187
+ def add_three_ds_fields(post, three_ds_options)
188
+ three_ds = {}
189
+ three_ds[:version] = three_ds_options[:version] if three_ds_options[:version]
190
+ three_ds[:eci] = three_ds_options[:eci] if three_ds_options[:eci]
191
+ three_ds[:cavv] = three_ds_options[:cavv] if three_ds_options[:cavv]
192
+ three_ds[:ds_transaction_id] = three_ds_options[:ds_transaction_id] if three_ds_options[:ds_transaction_id]
193
+ three_ds[:acs_transaction_id] = three_ds_options[:acs_transaction_id] if three_ds_options[:acs_transaction_id]
194
+ three_ds[:xid] = three_ds_options[:xid] if three_ds_options[:xid]
195
+ three_ds[:enrolled] = three_ds_options[:enrolled] if three_ds_options[:enrolled]
196
+ three_ds[:cavv_algorithm] = three_ds_options[:cavv_algorithm] if three_ds_options[:cavv_algorithm]
197
+ three_ds[:directory_response_status] = three_ds_options[:directory_response_status] if three_ds_options[:directory_response_status]
198
+ three_ds[:authentication_response_status] = three_ds_options[:authentication_response_status] if three_ds_options[:authentication_response_status]
199
+ three_ds[:three_ds_server_trans_id] = three_ds_options[:three_ds_server_trans_id] if three_ds_options[:three_ds_server_trans_id]
200
+
201
+ post[:three_ds_fields] = three_ds
202
+ end
203
+
204
+ def add_card(post, card, card_options = {})
205
+ card_hash = {}
206
+ card_hash[:number] = card.number
207
+ card_hash[:exp_month] = card.month
208
+ card_hash[:exp_year] = card.year
209
+ card_hash[:security_code] = card.verification_value
210
+ card_hash[:type] = card.brand
211
+ card_hash[:holder_first_name] = card.first_name
212
+ card_hash[:holder_last_name] = card.last_name
213
+ post[:card] = card_hash
214
+ end
215
+
216
+ def add_user(post, user_options)
217
+ user = {}
218
+ user[:id] = user_options[:id] if user_options[:id]
219
+ user[:email] = user_options[:email] if user_options[:email]
220
+
221
+ post[:user] = user
222
+ end
223
+
224
+ def add_stored_credential(post, options)
225
+ return unless options[:stored_credential]
226
+
227
+ check_initiator = %w[merchant cardholder].any? { |item| item == options[:stored_credential][:initiator] }
228
+ check_reason_type = %w[recurring installment unscheduled].any? { |item| item == options[:stored_credential][:reason_type] }
229
+ post[:forward_payload][:authentication] = {} unless post[:forward_payload].key?(:authentication)
230
+ post[:forward_payload][:authentication][:stored_credential] = options[:stored_credential] if check_initiator && check_reason_type
231
+ end
232
+
233
+ def add_order(post, money, order_options)
234
+ order = {}
235
+ order[:id] = order_options[:id] if order_options[:id]
236
+ order[:description] = order_options[:description] if order_options[:description]
237
+ order[:installments] = order_options[:installments] if order_options[:installments]
238
+ order[:datetime_local_transaction] = order_options[:datetime_local_transaction] if order_options[:datetime_local_transaction]
239
+
240
+ add_amount(order, money, order_options[:amount]) if order_options[:amount]
241
+ add_address('shipping_address', order, order_options[:shipping_address]) if order_options[:shipping_address]
242
+
243
+ post[:order] = order
244
+ end
245
+
246
+ def add_amount(post, money, amount_options)
247
+ amount_obj = {}
248
+ amount_obj[:total_amount] = amount(money).to_f
249
+ amount_obj[:currency] = (amount_options[:currency] || currency(money))
250
+ amount_obj[:vat] = amount_options[:vat] if amount_options[:vat]
251
+
252
+ post[:amount] = amount_obj
253
+ end
254
+
255
+ def add_address(tag, post, address_options)
256
+ address = {}
257
+ address[:name] = address_options[:name] if address_options[:name]
258
+ address[:address1] = address_options[:address1] if address_options[:address1]
259
+ address[:address2] = address_options[:address2] if address_options[:address2]
260
+ address[:company] = address_options[:company] if address_options[:company]
261
+ address[:city] = address_options[:city] if address_options[:city]
262
+ address[:state] = address_options[:state] if address_options[:state]
263
+ address[:zip] = address_options[:zip] if address_options[:zip]
264
+ address[:country] = address_options[:country] if address_options[:country]
265
+ address[:phone] = address_options[:phone] if address_options[:phone]
266
+ address[:fax] = address_options[:fax] if address_options[:fax]
267
+
268
+ post[tag] = address
269
+ end
270
+
271
+ def parse(body)
272
+ JSON.parse(body)
273
+ end
274
+
275
+ def commit(action, parameters, url_params = {})
276
+ begin
277
+ response = JSON.parse ssl_post(url(action, url_params), post_data(parameters), authorized_headers())
278
+ rescue ResponseError => exception
279
+ case exception.response.code.to_i
280
+ when 400...499
281
+ response = JSON.parse exception.response.body
282
+ else
283
+ raise exception
284
+ end
285
+ end
286
+
287
+ Response.new(
288
+ success_from(response['code']),
289
+ message_from(response),
290
+ response,
291
+ authorization: authorization_from(response),
292
+ avs_result: AVSResult.new(code: avs_code_from(response)),
293
+ cvv_result: CVVResult.new(cvv_code_from(response)),
294
+ test: test?,
295
+ error_code: error_code_from(response)
296
+ )
297
+ end
298
+
299
+ def avs_code_from(response)
300
+ response['avs_result']
301
+ end
302
+
303
+ def cvv_code_from(response)
304
+ response['cvv_result']
305
+ end
306
+
307
+ def success_from(code)
308
+ code == 'S001'
309
+ end
310
+
311
+ def message_from(response)
312
+ response['message']
313
+ end
314
+
315
+ def url(action, url_params)
316
+ "#{(test? ? test_url : live_url)}/#{url_params[:token_acquirer]}/#{action}"
317
+ end
318
+
319
+ def post_data(data = {})
320
+ data.to_json
321
+ end
322
+
323
+ def authorization_from(response)
324
+ response['simetrik_authorization_id']
325
+ end
326
+
327
+ def error_code_from(response)
328
+ STANDARD_ERROR_CODE_MAPPING[response['code']] unless success_from(response['code'])
329
+ end
330
+
331
+ def authorized_headers
332
+ {
333
+ 'content-Type' => 'application/json',
334
+ 'Authorization' => "Bearer #{sign_access_token()}"
335
+ }
336
+ end
337
+
338
+ def sign_access_token
339
+ fetch_access_token() if Time.new.to_i > (@access_token[:expires_at] || 0) + 10
340
+ @access_token[:access_token]
341
+ end
342
+
343
+ def auth_url
344
+ (test? ? test_auth_url : live_auth_url)
345
+ end
346
+
347
+ def fetch_access_token
348
+ login_info = {}
349
+ login_info[:client_id] = @options[:client_id]
350
+ login_info[:client_secret] = @options[:client_secret]
351
+ login_info[:audience] = @options[:audience]
352
+ login_info[:grant_type] = 'client_credentials'
353
+ response = parse(ssl_post(auth_url(), login_info.to_json, {
354
+ 'content-Type' => 'application/json'
355
+ }))
356
+
357
+ @access_token[:access_token] = response['access_token']
358
+ @access_token[:expires_at] = Time.new.to_i + response['expires_in']
359
+ end
360
+ end
361
+ end
362
+ end
@@ -48,7 +48,8 @@ module ActiveMerchant #:nodoc:
48
48
  'processing_error' => STANDARD_ERROR_CODE[:processing_error],
49
49
  'incorrect_pin' => STANDARD_ERROR_CODE[:incorrect_pin],
50
50
  'test_mode_live_card' => STANDARD_ERROR_CODE[:test_mode_live_card],
51
- 'pickup_card' => STANDARD_ERROR_CODE[:pickup_card]
51
+ 'pickup_card' => STANDARD_ERROR_CODE[:pickup_card],
52
+ 'amount_too_small' => STANDARD_ERROR_CODE[:invalid_amount]
52
53
  }
53
54
 
54
55
  BANK_ACCOUNT_HOLDER_TYPE_MAPPING = {
@@ -288,7 +289,8 @@ module ActiveMerchant #:nodoc:
288
289
  gsub(%r(((\[card\]|card)\[encrypted_pin_key_id\]=)[\w=]+(&?)), '\1[FILTERED]\3').
289
290
  gsub(%r(((\[card\]|card)\[number\]=)\d+), '\1[FILTERED]').
290
291
  gsub(%r(((\[card\]|card)\[swipe_data\]=)[^&]+(&?)), '\1[FILTERED]\3').
291
- gsub(%r(((\[bank_account\]|bank_account)\[account_number\]=)\d+), '\1[FILTERED]')
292
+ gsub(%r(((\[bank_account\]|bank_account)\[account_number\]=)\d+), '\1[FILTERED]').
293
+ gsub(%r(((\[payment_method_data\]|payment_method_data)\[card\]\[token\]=)[^&]+(&?)), '\1[FILTERED]\3')
292
294
  end
293
295
 
294
296
  def supports_network_tokenization?
@@ -11,43 +11,44 @@ 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
- NO_WALLET_SUPPORT = %w(apple_pay google_pay android_pay)
15
14
 
16
15
  def create_intent(money, payment_method, options = {})
17
- card_source_pay = payment_method.source.to_s if defined?(payment_method.source)
18
- card_brand_pay = card_brand(payment_method) unless payment_method.is_a?(String) || payment_method.nil?
19
- if NO_WALLET_SUPPORT.include?(card_source_pay) || NO_WALLET_SUPPORT.include?(card_brand_pay)
20
- store_apple_or_google_pay_token = 'Direct Apple Pay and Google Pay transactions are not supported. Those payment methods must be stored before use.'
21
- return Response.new(false, store_apple_or_google_pay_token)
22
- end
23
- post = {}
24
- add_amount(post, money, options, true)
25
- add_capture_method(post, options)
26
- add_confirmation_method(post, options)
27
- add_customer(post, options)
28
- result = add_payment_method_token(post, payment_method, options)
29
- return result if result.is_a?(ActiveMerchant::Billing::Response)
30
-
31
- add_external_three_d_secure_auth_data(post, options)
32
- add_metadata(post, options)
33
- add_return_url(post, options)
34
- add_connected_account(post, options)
35
- add_radar_data(post, options)
36
- add_shipping_address(post, options)
37
- setup_future_usage(post, options)
38
- add_exemption(post, options)
39
- add_stored_credentials(post, options)
40
- add_ntid(post, options)
41
- add_claim_without_transaction_id(post, options)
42
- add_error_on_requires_action(post, options)
43
- add_fulfillment_date(post, options)
44
- request_three_d_secure(post, options)
45
-
46
- CREATE_INTENT_ATTRIBUTES.each do |attribute|
47
- add_whitelisted_attribute(post, options, attribute)
16
+ MultiResponse.run do |r|
17
+ if payment_method.is_a?(NetworkTokenizationCreditCard)
18
+ r.process { tokenize_apple_google(payment_method, options) }
19
+ payment_method = (r.params['token']['id']) if r.success?
20
+ end
21
+ r.process do
22
+ post = {}
23
+ add_amount(post, money, options, true)
24
+ add_capture_method(post, options)
25
+ add_confirmation_method(post, options)
26
+ add_customer(post, options)
27
+
28
+ result = add_payment_method_token(post, payment_method, options)
29
+ return result if result.is_a?(ActiveMerchant::Billing::Response)
30
+
31
+ add_external_three_d_secure_auth_data(post, options)
32
+ add_metadata(post, options)
33
+ add_return_url(post, options)
34
+ add_connected_account(post, options)
35
+ add_radar_data(post, options)
36
+ add_shipping_address(post, options)
37
+ setup_future_usage(post, options)
38
+ add_exemption(post, options)
39
+ add_stored_credentials(post, options)
40
+ add_ntid(post, options)
41
+ add_claim_without_transaction_id(post, options)
42
+ add_error_on_requires_action(post, options)
43
+ add_fulfillment_date(post, options)
44
+ request_three_d_secure(post, options)
45
+
46
+ CREATE_INTENT_ATTRIBUTES.each do |attribute|
47
+ add_whitelisted_attribute(post, options, attribute)
48
+ end
49
+ commit(:post, 'payment_intents', post, options)
50
+ end
48
51
  end
49
-
50
- commit(:post, 'payment_intents', post, options)
51
52
  end
52
53
 
53
54
  def show_intent(intent_id, options)
@@ -59,6 +60,7 @@ module ActiveMerchant #:nodoc:
59
60
  result = add_payment_method_token(post, payment_method, options)
60
61
  return result if result.is_a?(ActiveMerchant::Billing::Response)
61
62
 
63
+ add_payment_method_types(post, options)
62
64
  CONFIRM_INTENT_ATTRIBUTES.each do |attribute|
63
65
  add_whitelisted_attribute(post, options, attribute)
64
66
  end
@@ -86,6 +88,13 @@ module ActiveMerchant #:nodoc:
86
88
  post_data
87
89
  end
88
90
 
91
+ def add_payment_method_card_data_token(post_data, payment_method)
92
+ post_data.merge!({
93
+ payment_method_types: ['card'],
94
+ payment_method_data: { type: 'card', card: { token: payment_method } }
95
+ })
96
+ end
97
+
89
98
  def update_intent(money, intent_id, payment_method, options = {})
90
99
  post = {}
91
100
  add_amount(post, money, options)
@@ -115,6 +124,7 @@ module ActiveMerchant #:nodoc:
115
124
  add_metadata(post, options)
116
125
  add_return_url(post, options)
117
126
  add_fulfillment_date(post, options)
127
+ request_three_d_secure(post, options)
118
128
  post[:on_behalf_of] = options[:on_behalf_of] if options[:on_behalf_of]
119
129
  post[:usage] = options[:usage] if %w(on_session off_session).include?(options[:usage])
120
130
  post[:description] = options[:description] if options[:description]
@@ -186,7 +196,6 @@ module ActiveMerchant #:nodoc:
186
196
  def store(payment_method, options = {})
187
197
  params = {}
188
198
  post = {}
189
-
190
199
  # If customer option is provided, create a payment method and attach to customer id
191
200
  # Otherwise, create a customer, then attach
192
201
  if payment_method.is_a?(StripePaymentToken) || payment_method.is_a?(ActiveMerchant::Billing::CreditCard)
@@ -285,7 +294,13 @@ module ActiveMerchant #:nodoc:
285
294
  def add_payment_method_token(post, payment_method, options)
286
295
  case payment_method
287
296
  when StripePaymentToken
288
- post[:payment_method] = payment_method.payment_data['id']
297
+ post[:payment_method_data] = {
298
+ type: 'card',
299
+ card: {
300
+ token: payment_method.payment_data['id'] || payment_method.payment_data
301
+ }
302
+ }
303
+ post[:payment_method] = payment_method.payment_data['id'] || payment_method.payment_data
289
304
  when String
290
305
  extract_token_from_string_and_maybe_add_customer_id(post, payment_method)
291
306
  when ActiveMerchant::Billing::CreditCard
@@ -299,7 +314,34 @@ module ActiveMerchant #:nodoc:
299
314
  post[:customer] = customer_id
300
315
  end
301
316
 
302
- post[:payment_method] = payment_method
317
+ if payment_method.include?('tok_')
318
+ add_payment_method_card_data_token(post, payment_method)
319
+ else
320
+ post[:payment_method] = payment_method
321
+ end
322
+ end
323
+
324
+ def tokenize_apple_google(payment, options = {})
325
+ tokenization_method = payment.source == :google_pay ? :android_pay : payment.source
326
+ post = {
327
+ card: {
328
+ number: payment.number,
329
+ exp_month: payment.month,
330
+ exp_year: payment.year,
331
+ tokenization_method: tokenization_method,
332
+ eci: payment.eci,
333
+ cryptogram: payment.payment_cryptogram
334
+ }
335
+ }
336
+ token_response = api_request(:post, 'tokens', post, options)
337
+ success = token_response['error'].nil?
338
+ if success && token_response['id']
339
+ Response.new(success, nil, token: token_response)
340
+ elsif token_response['error']['message']
341
+ Response.new(false, "The tokenization process fails. #{token_response['error']['message']}")
342
+ else
343
+ Response.new(false, "The tokenization process fails. #{token_response}")
344
+ end
303
345
  end
304
346
 
305
347
  def get_payment_method_data_from_card(post, payment_method, options)
@@ -430,21 +472,24 @@ module ActiveMerchant #:nodoc:
430
472
  end
431
473
 
432
474
  def add_shipping_address(post, options = {})
433
- return unless shipping = options[:shipping]
475
+ return unless shipping = options[:shipping_address]
434
476
 
435
477
  post[:shipping] = {}
436
- post[:shipping][:address] = {}
437
- post[:shipping][:address][:line1] = shipping[:address][:line1]
438
- post[:shipping][:address][:city] = shipping[:address][:city] if shipping[:address][:city]
439
- post[:shipping][:address][:country] = shipping[:address][:country] if shipping[:address][:country]
440
- post[:shipping][:address][:line2] = shipping[:address][:line2] if shipping[:address][:line2]
441
- post[:shipping][:address][:postal_code] = shipping[:address][:postal_code] if shipping[:address][:postal_code]
442
- post[:shipping][:address][:state] = shipping[:address][:state] if shipping[:address][:state]
443
478
 
479
+ # fields required by Stripe PI
480
+ post[:shipping][:address] = {}
481
+ post[:shipping][:address][:line1] = shipping[:address1]
444
482
  post[:shipping][:name] = shipping[:name]
445
- post[:shipping][:carrier] = shipping[:carrier] if shipping[:carrier]
446
- post[:shipping][:phone] = shipping[:phone] if shipping[:phone]
447
- post[:shipping][:tracking_number] = shipping[:tracking_number] if shipping[:tracking_number]
483
+
484
+ # fields considered optional by Stripe PI
485
+ post[:shipping][:address][:city] = shipping[:city] if shipping[:city]
486
+ post[:shipping][:address][:country] = shipping[:country] if shipping[:country]
487
+ post[:shipping][:address][:line2] = shipping[:address2] if shipping[:address2]
488
+ post[:shipping][:address][:postal_code] = shipping[:zip] if shipping[:zip]
489
+ post[:shipping][:address][:state] = shipping[:state] if shipping[:state]
490
+ post[:shipping][:phone] = shipping[:phone_number] if shipping[:phone_number]
491
+ post[:shipping][:carrier] = (shipping[:carrier] || options[:shipping_carrier]) if shipping[:carrier] || options[:shipping_carrier]
492
+ post[:shipping][:tracking_number] = (shipping[:tracking_number] || options[:shipping_tracking_number]) if shipping[:tracking_number] || options[:shipping_tracking_number]
448
493
  end
449
494
 
450
495
  def format_idempotency_key(options, suffix)
@@ -90,8 +90,8 @@ module ActiveMerchant #:nodoc:
90
90
  CURRENCY_CODES['PEN'] = 604
91
91
 
92
92
  def add_invoice(params, money, options)
93
- # Visanet Peru expects a 9-digit numeric purchaseNumber
94
- params[:purchaseNumber] = (SecureRandom.random_number(900_000_000) + 100_000_000).to_s
93
+ # Visanet Peru expects a 12-digit alphanumeric purchaseNumber
94
+ params[:purchaseNumber] = generate_purchase_number_stamp
95
95
  params[:externalTransactionId] = options[:order_id]
96
96
  params[:amount] = amount(money)
97
97
  params[:currencyId] = CURRENCY_CODES[options[:currency] || currency(money)]
@@ -142,6 +142,10 @@ module ActiveMerchant #:nodoc:
142
142
  authorization.split('|')
143
143
  end
144
144
 
145
+ def generate_purchase_number_stamp
146
+ (Time.now.to_f.round(2) * 100).to_i.to_s
147
+ end
148
+
145
149
  def commit(action, params, options = {})
146
150
  raw_response = ssl_request(method(action), url(action, params, options), params.to_json, headers)
147
151
  response = parse(raw_response)
@@ -1,3 +1,3 @@
1
1
  module ActiveMerchant
2
- VERSION = '1.125.0'
2
+ VERSION = '1.126.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activemerchant
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.125.0
4
+ version: 1.126.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Luetke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-20 00:00:00.000000000 Z
11
+ date: 2022-04-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -184,6 +184,7 @@ files:
184
184
  - lib/active_merchant/billing/gateway.rb
185
185
  - lib/active_merchant/billing/gateways.rb
186
186
  - lib/active_merchant/billing/gateways/adyen.rb
187
+ - lib/active_merchant/billing/gateways/airwallex.rb
187
188
  - lib/active_merchant/billing/gateways/allied_wallet.rb
188
189
  - lib/active_merchant/billing/gateways/authorize_net.rb
189
190
  - lib/active_merchant/billing/gateways/authorize_net_arb.rb
@@ -206,6 +207,7 @@ files:
206
207
  - lib/active_merchant/billing/gateways/bpoint.rb
207
208
  - lib/active_merchant/billing/gateways/braintree.rb
208
209
  - lib/active_merchant/billing/gateways/braintree/braintree_common.rb
210
+ - lib/active_merchant/billing/gateways/braintree/token_nonce.rb
209
211
  - lib/active_merchant/billing/gateways/braintree_blue.rb
210
212
  - lib/active_merchant/billing/gateways/braintree_orange.rb
211
213
  - lib/active_merchant/billing/gateways/bridge_pay.rb
@@ -370,6 +372,7 @@ files:
370
372
  - lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb
371
373
  - lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb
372
374
  - lib/active_merchant/billing/gateways/qvalent.rb
375
+ - lib/active_merchant/billing/gateways/rapyd.rb
373
376
  - lib/active_merchant/billing/gateways/realex.rb
374
377
  - lib/active_merchant/billing/gateways/redsys.rb
375
378
  - lib/active_merchant/billing/gateways/s5.rb
@@ -382,6 +385,7 @@ files:
382
385
  - lib/active_merchant/billing/gateways/secure_pay_au.rb
383
386
  - lib/active_merchant/billing/gateways/secure_pay_tech.rb
384
387
  - lib/active_merchant/billing/gateways/securion_pay.rb
388
+ - lib/active_merchant/billing/gateways/simetrik.rb
385
389
  - lib/active_merchant/billing/gateways/skip_jack.rb
386
390
  - lib/active_merchant/billing/gateways/smart_ps.rb
387
391
  - lib/active_merchant/billing/gateways/so_easy_pay.rb