activemerchant 1.129.0 → 1.130.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 415c09ab9b38e3503d10b38cd42959b50c131f8b47237f39b36a8da7bc044d82
4
- data.tar.gz: 2b2cdd2955bd0ed6e2b808cad4fa31888749ee6cbe91b2a75c563f1cc09429d6
3
+ metadata.gz: 68d19e25c325eedb9f632b67713bd61ec67f09794560add0c22ba7b45c33cda6
4
+ data.tar.gz: 3c9405afcad2c9d066b76f1ad055d264e55569c14d9b9e322e2c6d3d83867b29
5
5
  SHA512:
6
- metadata.gz: 104444c88b66340a16502ae980ae4c2795f25cd8f9d3a78a05d636d55730a462d9ead8a565291774096dd3fa75149961f64ec472d2a74c7499ce6b472ec6de95
7
- data.tar.gz: bc738912b2788963721d232e43cf02675cc6a672c7aca913c6bd876fd73b72fd0cd0b7d43e734dca7f5494957e9092e8054d75b788b59ef3a2ca25a917d3d949
6
+ metadata.gz: e5c803983440bd24cbadd24fc5c689061ece449436010f3ad2f328dd3bdbaf2cc3c68c43dae86482f4fee84de454d2e626b89bacf54ad67468285410d8860610
7
+ data.tar.gz: 77458ab3d685b3ea7b7f3f1a26617d201eb071ef540414e6934677a1541166bbd68b132bc5f980dbf60656058d97877e70c907ab950b2314a2cfcf205e9e2de3
data/CHANGELOG CHANGED
@@ -3,7 +3,29 @@
3
3
 
4
4
  == HEAD
5
5
 
6
- == Version 1.129.0 (April 24th, 2023)
6
+ == Version 1.130.0 (June 13th, 2023)
7
+ * Payu Latam - Update error code method to surface network code [yunnydang] #4773
8
+ * CyberSource: Handling Canadian bank accounts [heavyblade] #4764
9
+ * CyberSource Rest: Fixing currency detection [heavyblade] #4777
10
+ * CyberSource: Allow business rules for requests with network tokens [aenand] #4764
11
+ * Adyen: Update Mastercard error messaging [kylene-spreedly] #4770
12
+ * Authorize.net: Update mapping for billing address phone number [jcreiff] #4778
13
+ * Braintree: Update mapping for billing address phone number [jcreiff] #4779
14
+ * CommerceHub: Enabling multi-use public key encryption [jherreraa] #4771
15
+ * Ogone: Enable 3ds Global for Ogone Gateway [javierpedrozaing] #4776
16
+ * Worldpay: Fix Google Pay [almalee24] #4774
17
+ * Borgun change default TrCurrencyExponent and MerchantReturnUrl [naashton] #4788
18
+ * Borgun: support for GBP currency [naashton] #4789
19
+ * CyberSource: Enable auto void on r230 [aenand] #4794
20
+ * Redsys: Set appropriate request fields for stored credentials with CITs and MITs [BritneyS] #4784
21
+ * Stripe & Stripe PI: Validate API Key [almalee24] #4801
22
+ * Add BIN for Maestro [jcreiff] #4799
23
+ * D_Local: Add save field on card object [yunnydang] #4805
24
+ * PayPal Express: Adds support for MsgSubID property on DoReferenceTransaction and DoExpressCheckoutPayment [wikiti] #4798
25
+ * Checkout_v2: use credit_card?, not case equality with CreditCard [bbraschi] #4803
26
+ * Shift4: Enable general credit feature [jherreraa] #4790
27
+
28
+ == Version 1.129.0 (May 3rd, 2023)
7
29
  * Adyen: Update selectedBrand mapping for Google Pay [jcreiff] #4763
8
30
  * Shift4: Add vendorReference field [jcreiff] #4762
9
31
  * Shift4: Add OAuth error [aenand] #4760
@@ -109,7 +109,7 @@ module ActiveMerchant #:nodoc:
109
109
  MAESTRO_BINS = Set.new(
110
110
  %w[ 500057
111
111
  501018 501043 501045 501047 501049 501051 501072 501075 501083 501087 501089 501095
112
- 501500
112
+ 501500 501623
113
113
  501879 502113 502120 502121 502301
114
114
  503175 503337 503645 503670
115
115
  504310 504338 504363 504533 504587 504620 504639 504656 504738 504781 504910
@@ -703,8 +703,8 @@ module ActiveMerchant #:nodoc:
703
703
  end
704
704
 
705
705
  def authorize_message_from(response)
706
- if response['refusalReason'] && response['additionalData'] && response['additionalData']['refusalReasonRaw']
707
- "#{response['refusalReason']} | #{response['additionalData']['refusalReasonRaw']}"
706
+ if response['refusalReason'] && response['additionalData'] && (response['additionalData']['merchantAdviceCode'] || response['additionalData']['refusalReasonRaw'])
707
+ "#{response['refusalReason']} | #{response['additionalData']['merchantAdviceCode'] || response['additionalData']['refusalReasonRaw']}"
708
708
  else
709
709
  response['refusalReason'] || response['resultCode'] || response['message'] || response['result']
710
710
  end
@@ -604,6 +604,7 @@ module ActiveMerchant
604
604
  first_name, last_name = names_from(payment_source, address, options)
605
605
  state = state_from(address, options)
606
606
  full_address = "#{address[:address1]} #{address[:address2]}".strip
607
+ phone = address[:phone] || address[:phone_number] || ''
607
608
 
608
609
  xml.firstName(truncate(first_name, 50)) unless empty?(first_name)
609
610
  xml.lastName(truncate(last_name, 50)) unless empty?(last_name)
@@ -613,7 +614,7 @@ module ActiveMerchant
613
614
  xml.state(truncate(state, 40))
614
615
  xml.zip(truncate((address[:zip] || options[:zip]), 20))
615
616
  xml.country(truncate(address[:country], 60))
616
- xml.phoneNumber(truncate(address[:phone], 25)) unless empty?(address[:phone])
617
+ xml.phoneNumber(truncate(phone, 25)) unless empty?(phone)
617
618
  xml.faxNumber(truncate(address[:fax], 25)) unless empty?(address[:fax])
618
619
  end
619
620
  end
@@ -96,6 +96,7 @@ module ActiveMerchant #:nodoc:
96
96
  CURRENCY_CODES['ISK'] = '352'
97
97
  CURRENCY_CODES['EUR'] = '978'
98
98
  CURRENCY_CODES['USD'] = '840'
99
+ CURRENCY_CODES['GBP'] = '826'
99
100
 
100
101
  def add_3ds_fields(post, options)
101
102
  post[:ThreeDSMessageId] = options[:three_ds_message_id] if options[:three_ds_message_id]
@@ -105,17 +106,17 @@ module ActiveMerchant #:nodoc:
105
106
 
106
107
  def add_3ds_preauth_fields(post, options)
107
108
  post[:SaleDescription] = options[:sale_description] || ''
108
- post[:MerchantReturnURL] = options[:merchant_return_url] if options[:merchant_return_url]
109
+ post[:MerchantReturnURL] = options[:redirect_url] if options[:redirect_url]
109
110
  end
110
111
 
111
112
  def add_invoice(post, money, options)
112
113
  post[:TrAmount] = amount(money)
113
114
  post[:TrCurrency] = CURRENCY_CODES[options[:currency] || currency(money)]
114
115
  # The ISK currency must have a currency exponent of 2 on the 3DS request but not on the auth request
115
- if post[:TrCurrency] == '352' && options[:apply_3d_secure] == '1'
116
- post[:TrCurrencyExponent] = 2
117
- else
116
+ if post[:TrCurrency] == '352' && options[:apply_3d_secure] != '1'
118
117
  post[:TrCurrencyExponent] = 0
118
+ else
119
+ post[:TrCurrencyExponent] = 2
119
120
  end
120
121
  post[:TerminalID] = options[:terminal_id] || '1'
121
122
  end
@@ -197,8 +197,7 @@ module ActiveMerchant #:nodoc:
197
197
  first_name: creditcard.first_name,
198
198
  last_name: creditcard.last_name,
199
199
  email: scrub_email(options[:email]),
200
- phone: options[:phone] || (options[:billing_address][:phone] if options[:billing_address] &&
201
- options[:billing_address][:phone]),
200
+ phone: phone_from(options),
202
201
  credit_card: credit_card_params)
203
202
  Response.new(result.success?, message_from_result(result),
204
203
  braintree_customer: (customer_hash(@braintree_gateway.customer.find(vault_id), :include_credit_cards) if result.success?),
@@ -267,8 +266,7 @@ module ActiveMerchant #:nodoc:
267
266
  first_name: creditcard.first_name,
268
267
  last_name: creditcard.last_name,
269
268
  email: scrub_email(options[:email]),
270
- phone: options[:phone] || (options[:billing_address][:phone] if options[:billing_address] &&
271
- options[:billing_address][:phone]),
269
+ phone: phone_from(options),
272
270
  id: options[:customer],
273
271
  device_data: options[:device_data]
274
272
  }.merge credit_card_params
@@ -348,6 +346,10 @@ module ActiveMerchant #:nodoc:
348
346
  parameters
349
347
  end
350
348
 
349
+ def phone_from(options)
350
+ options[:phone] || options.dig(:billing_address, :phone) || options.dig(:billing_address, :phone_number)
351
+ end
352
+
351
353
  def map_address(address)
352
354
  mapped = {
353
355
  street_address: address[:address1],
@@ -628,8 +630,7 @@ module ActiveMerchant #:nodoc:
628
630
  customer: {
629
631
  id: options[:store] == true ? '' : options[:store],
630
632
  email: scrub_email(options[:email]),
631
- phone: options[:phone] || (options[:billing_address][:phone] if options[:billing_address] &&
632
- options[:billing_address][:phone])
633
+ phone: phone_from(options)
633
634
  },
634
635
  options: {
635
636
  store_in_vault: options[:store] ? true : false,
@@ -932,7 +933,7 @@ module ActiveMerchant #:nodoc:
932
933
  first_name: payment_method.first_name,
933
934
  last_name: payment_method.last_name,
934
935
  email: scrub_email(options[:email]),
935
- phone: options[:phone] || options.dig(:billing_address, :phone),
936
+ phone: phone_from(options),
936
937
  device_data: options[:device_data]
937
938
  }.compact
938
939
 
@@ -185,7 +185,7 @@ module ActiveMerchant #:nodoc:
185
185
  post[key][:token_type] = token_type
186
186
  post[key][:cryptogram] = cryptogram if cryptogram
187
187
  post[key][:eci] = eci if eci
188
- when CreditCard
188
+ when ->(pm) { pm.try(:credit_card?) }
189
189
  post[key][:type] = 'card'
190
190
  post[key][:name] = payment_method.name
191
191
  post[key][:number] = payment_method.number
@@ -114,7 +114,7 @@ module ActiveMerchant #:nodoc:
114
114
  post[:transactionInteraction][:origin] = options[:origin] || 'ECOM'
115
115
  post[:transactionInteraction][:eciIndicator] = options[:eci_indicator] || 'CHANNEL_ENCRYPTED'
116
116
  post[:transactionInteraction][:posConditionCode] = options[:pos_condition_code] || 'CARD_NOT_PRESENT_ECOM'
117
- post[:transactionInteraction][:posEntryMode] = options[:pos_entry_mode] || 'MANUAL'
117
+ post[:transactionInteraction][:posEntryMode] = (options[:pos_entry_mode] || 'MANUAL') unless options[:encryption_data].present?
118
118
  post[:transactionInteraction][:additionalPosInformation] = {}
119
119
  post[:transactionInteraction][:additionalPosInformation][:dataEntrySource] = options[:data_entry_source] || 'UNSPECIFIED'
120
120
  end
@@ -256,7 +256,12 @@ module ActiveMerchant #:nodoc:
256
256
  when NetworkTokenizationCreditCard
257
257
  add_decrypted_wallet(source, payment, options)
258
258
  when CreditCard
259
- add_credit_card(source, payment, options)
259
+ if options[:encryption_data].present?
260
+ source[:sourceType] = 'PaymentCard'
261
+ source[:encryptionData] = options[:encryption_data]
262
+ else
263
+ add_credit_card(source, payment, options)
264
+ end
260
265
  when String
261
266
  add_payment_token(source, payment, options)
262
267
  end
@@ -519,11 +519,9 @@ module ActiveMerchant #:nodoc:
519
519
  def add_business_rules_data(xml, payment_method, options)
520
520
  prioritized_options = [options, @options]
521
521
 
522
- unless network_tokenization?(payment_method)
523
- xml.tag! 'businessRules' do
524
- xml.tag!('ignoreAVSResult', 'true') if extract_option(prioritized_options, :ignore_avs).to_s == 'true'
525
- xml.tag!('ignoreCVResult', 'true') if extract_option(prioritized_options, :ignore_cvv).to_s == 'true'
526
- end
522
+ xml.tag! 'businessRules' do
523
+ xml.tag!('ignoreAVSResult', 'true') if extract_option(prioritized_options, :ignore_avs).to_s == 'true'
524
+ xml.tag!('ignoreCVResult', 'true') if extract_option(prioritized_options, :ignore_cvv).to_s == 'true'
527
525
  end
528
526
  end
529
527
 
@@ -705,8 +703,8 @@ module ActiveMerchant #:nodoc:
705
703
  def add_check(xml, check, options)
706
704
  xml.tag! 'check' do
707
705
  xml.tag! 'accountNumber', check.account_number
708
- xml.tag! 'accountType', check.account_type[0]
709
- xml.tag! 'bankTransitNumber', check.routing_number
706
+ xml.tag! 'accountType', check.account_type == 'checking' ? 'C' : 'S'
707
+ xml.tag! 'bankTransitNumber', format_routing_number(check.routing_number, options)
710
708
  xml.tag! 'secCode', options[:sec_code] if options[:sec_code]
711
709
  end
712
710
  end
@@ -1055,6 +1053,8 @@ module ActiveMerchant #:nodoc:
1055
1053
  message = message_from(response)
1056
1054
  authorization = success || in_fraud_review?(response) ? authorization_from(response, action, amount, options) : nil
1057
1055
 
1056
+ message = auto_void?(authorization_from(response, action, amount, options), response, message, options)
1057
+
1058
1058
  Response.new(success, message, response,
1059
1059
  test: test?,
1060
1060
  authorization: authorization,
@@ -1063,6 +1063,14 @@ module ActiveMerchant #:nodoc:
1063
1063
  cvv_result: response[:cvCode])
1064
1064
  end
1065
1065
 
1066
+ def auto_void?(authorization, response, message, options = {})
1067
+ return message unless response[:reasonCode] == '230' && options[:auto_void_230]
1068
+
1069
+ response = void(authorization, options)
1070
+ response&.success? ? message += ' - transaction has been auto-voided.' : message += ' - transaction could not be auto-voided.'
1071
+ message
1072
+ end
1073
+
1066
1074
  # Parse the SOAP response
1067
1075
  # Technique inspired by the Paypal Gateway
1068
1076
  def parse(xml)
@@ -1131,6 +1139,10 @@ module ActiveMerchant #:nodoc:
1131
1139
  def eligible_for_zero_auth?(payment_method, options = {})
1132
1140
  payment_method.is_a?(CreditCard) && options[:zero_amount_auth]
1133
1141
  end
1142
+
1143
+ def format_routing_number(routing_number, options)
1144
+ options[:currency] == 'CAD' && routing_number.length > 8 ? routing_number[-8..-1] : routing_number
1145
+ end
1134
1146
  end
1135
1147
  end
1136
1148
  end
@@ -112,7 +112,7 @@ module ActiveMerchant #:nodoc:
112
112
  add_code(post, options)
113
113
  add_payment(post, payment, options)
114
114
  add_mdd_fields(post, options)
115
- add_amount(post, amount)
115
+ add_amount(post, amount, options)
116
116
  add_address(post, payment, options[:billing_address], options, :billTo)
117
117
  add_address(post, payment, options[:shipping_address], options, :shipTo)
118
118
  add_business_rules_data(post, payment, options)
@@ -125,7 +125,7 @@ module ActiveMerchant #:nodoc:
125
125
  { clientReferenceInformation: {}, orderInformation: {} }.tap do |post|
126
126
  add_code(post, options)
127
127
  add_mdd_fields(post, options)
128
- add_amount(post, amount)
128
+ add_amount(post, amount, options)
129
129
  add_partner_solution_id(post)
130
130
  end.compact
131
131
  end
@@ -135,7 +135,7 @@ module ActiveMerchant #:nodoc:
135
135
  add_code(post, options)
136
136
  add_credit_card(post, payment)
137
137
  add_mdd_fields(post, options)
138
- add_amount(post, amount)
138
+ add_amount(post, amount, options)
139
139
  add_address(post, payment, options[:billing_address], options, :billTo)
140
140
  add_merchant_description(post, options)
141
141
  end.compact
@@ -161,7 +161,7 @@ module ActiveMerchant #:nodoc:
161
161
  }
162
162
  end
163
163
 
164
- def add_amount(post, amount)
164
+ def add_amount(post, amount, options)
165
165
  currency = options[:currency] || currency(amount)
166
166
  post[:orderInformation][:amountDetails] = {
167
167
  totalAmount: localized_amount(amount, currency),
@@ -413,10 +413,8 @@ module ActiveMerchant #:nodoc:
413
413
 
414
414
  def add_business_rules_data(post, payment, options)
415
415
  post[:processingInformation][:authorizationOptions] = {}
416
- unless payment.is_a?(NetworkTokenizationCreditCard)
417
- post[:processingInformation][:authorizationOptions][:ignoreAvsResult] = 'true' if options[:ignore_avs].to_s == 'true'
418
- post[:processingInformation][:authorizationOptions][:ignoreCvResult] = 'true' if options[:ignore_cvv].to_s == 'true'
419
- end
416
+ post[:processingInformation][:authorizationOptions][:ignoreAvsResult] = 'true' if options[:ignore_avs].to_s == 'true'
417
+ post[:processingInformation][:authorizationOptions][:ignoreCvResult] = 'true' if options[:ignore_cvv].to_s == 'true'
420
418
  end
421
419
 
422
420
  def add_mdd_fields(post, options)
@@ -188,6 +188,7 @@ module ActiveMerchant #:nodoc:
188
188
  post[:card][:installments] = options[:installments] if options[:installments]
189
189
  post[:card][:installments_id] = options[:installments_id] if options[:installments_id]
190
190
  post[:card][:force_type] = options[:force_type].to_s.upcase if options[:force_type]
191
+ post[:card][:save] = options[:save] if options[:save]
191
192
  end
192
193
 
193
194
  def parse(body)
@@ -2,6 +2,8 @@ module ActiveMerchant #:nodoc:
2
2
  module Billing #:nodoc:
3
3
  class GlobalCollectGateway < Gateway
4
4
  class_attribute :preproduction_url
5
+ class_attribute :ogone_direct_test
6
+ class_attribute :ogone_direct_live
5
7
 
6
8
  self.display_name = 'GlobalCollect'
7
9
  self.homepage_url = 'http://www.globalcollect.com/'
@@ -9,6 +11,8 @@ module ActiveMerchant #:nodoc:
9
11
  self.test_url = 'https://eu.sandbox.api-ingenico.com'
10
12
  self.preproduction_url = 'https://world.preprod.api-ingenico.com'
11
13
  self.live_url = 'https://world.api-ingenico.com'
14
+ self.ogone_direct_test = 'https://payment.preprod.direct.worldline-solutions.com'
15
+ self.ogone_direct_live = 'https://payment.direct.worldline-solutions.com'
12
16
 
13
17
  self.supported_countries = %w[AD AE AG AI AL AM AO AR AS AT AU AW AX AZ BA BB BD BE BF BG BH BI BJ BL BM BN BO BQ BR BS BT BW BY BZ CA CC CD CF CH CI CK CL CM CN CO CR CU CV CW CX CY CZ DE DJ DK DM DO DZ EC EE EG ER ES ET FI FJ FK FM FO FR GA GB GD GE GF GH GI GL GM GN GP GQ GR GS GT GU GW GY HK HN HR HT HU ID IE IL IM IN IS IT JM JO JP KE KG KH KI KM KN KR KW KY KZ LA LB LC LI LK LR LS LT LU LV MA MC MD ME MF MG MH MK MM MN MO MP MQ MR MS MT MU MV MW MX MY MZ NA NC NE NG NI NL NO NP NR NU NZ OM PA PE PF PG PH PL PN PS PT PW QA RE RO RS RU RW SA SB SC SE SG SH SI SJ SK SL SM SN SR ST SV SZ TC TD TG TH TJ TL TM TN TO TR TT TV TW TZ UA UG US UY UZ VC VE VG VI VN WF WS ZA ZM ZW]
14
18
  self.default_currency = 'USD'
@@ -114,7 +118,7 @@ module ActiveMerchant #:nodoc:
114
118
  post['order']['references']['invoiceData'] = {
115
119
  'invoiceNumber' => options[:invoice]
116
120
  }
117
- add_airline_data(post, options)
121
+ add_airline_data(post, options) unless ogone_direct?
118
122
  add_lodging_data(post, options)
119
123
  add_number_of_installments(post, options) if options[:number_of_installments]
120
124
  end
@@ -248,9 +252,10 @@ module ActiveMerchant #:nodoc:
248
252
  end
249
253
 
250
254
  def add_amount(post, money, options = {})
255
+ currency_ogone = 'EUR' if ogone_direct?
251
256
  post['amountOfMoney'] = {
252
257
  'amount' => amount(money),
253
- 'currencyCode' => options[:currency] || currency(money)
258
+ 'currencyCode' => options[:currency] || currency_ogone || currency(money)
254
259
  }
255
260
  end
256
261
 
@@ -262,7 +267,7 @@ module ActiveMerchant #:nodoc:
262
267
  product_id = options[:payment_product_id] || BRAND_MAP[payment.brand]
263
268
  specifics_inputs = {
264
269
  'paymentProductId' => product_id,
265
- 'skipAuthentication' => 'true', # refers to 3DSecure
270
+ 'skipAuthentication' => options[:skip_authentication] || 'true', # refers to 3DSecure
266
271
  'skipFraudService' => 'true',
267
272
  'authorizationMode' => pre_authorization
268
273
  }
@@ -377,18 +382,24 @@ module ActiveMerchant #:nodoc:
377
382
  def add_external_cardholder_authentication_data(post, options)
378
383
  return unless threeds_2_options = options[:three_d_secure]
379
384
 
380
- authentication_data = {}
381
- authentication_data[:acsTransactionId] = threeds_2_options[:acs_transaction_id] if threeds_2_options[:acs_transaction_id]
382
- authentication_data[:cavv] = threeds_2_options[:cavv] if threeds_2_options[:cavv]
383
- authentication_data[:cavvAlgorithm] = threeds_2_options[:cavv_algorithm] if threeds_2_options[:cavv_algorithm]
384
- authentication_data[:directoryServerTransactionId] = threeds_2_options[:ds_transaction_id] if threeds_2_options[:ds_transaction_id]
385
- authentication_data[:eci] = threeds_2_options[:eci] if threeds_2_options[:eci]
386
- authentication_data[:threeDSecureVersion] = threeds_2_options[:version] if threeds_2_options[:version]
387
- authentication_data[:validationResult] = threeds_2_options[:authentication_response_status] if threeds_2_options[:authentication_response_status]
388
- authentication_data[:xid] = threeds_2_options[:xid] if threeds_2_options[:xid]
385
+ authentication_data = {
386
+ priorThreeDSecureData: { acsTransactionId: threeds_2_options[:acs_transaction_id] }.compact,
387
+ cavv: threeds_2_options[:cavv],
388
+ cavvAlgorithm: threeds_2_options[:cavv_algorithm],
389
+ directoryServerTransactionId: threeds_2_options[:ds_transaction_id],
390
+ eci: threeds_2_options[:eci],
391
+ threeDSecureVersion: threeds_2_options[:version] || options[:three_ds_version],
392
+ validationResult: threeds_2_options[:authentication_response_status],
393
+ xid: threeds_2_options[:xid],
394
+ acsTransactionId: threeds_2_options[:acs_transaction_id],
395
+ flow: threeds_2_options[:flow]
396
+ }.compact
389
397
 
390
398
  post['cardPaymentMethodSpecificInput'] ||= {}
391
399
  post['cardPaymentMethodSpecificInput']['threeDSecure'] ||= {}
400
+ post['cardPaymentMethodSpecificInput']['threeDSecure']['merchantFraudRate'] = threeds_2_options[:merchant_fraud_rate]
401
+ post['cardPaymentMethodSpecificInput']['threeDSecure']['exemptionRequest'] = threeds_2_options[:exemption_request]
402
+ post['cardPaymentMethodSpecificInput']['threeDSecure']['secureCorporatePayment'] = threeds_2_options[:secure_corporate_payment]
392
403
  post['cardPaymentMethodSpecificInput']['threeDSecure']['externalCardholderAuthenticationData'] = authentication_data unless authentication_data.empty?
393
404
  end
394
405
 
@@ -402,17 +413,28 @@ module ActiveMerchant #:nodoc:
402
413
 
403
414
  def url(action, authorization)
404
415
  return preproduction_url + uri(action, authorization) if @options[:url_override].to_s == 'preproduction'
416
+ return ogone_direct_url(action, authorization) if ogone_direct?
405
417
 
406
418
  (test? ? test_url : live_url) + uri(action, authorization)
407
419
  end
408
420
 
421
+ def ogone_direct_url(action, authorization)
422
+ (test? ? ogone_direct_test : ogone_direct_live) + uri(action, authorization)
423
+ end
424
+
425
+ def ogone_direct?
426
+ @options[:url_override].to_s == 'ogone_direct'
427
+ end
428
+
409
429
  def uri(action, authorization)
410
- uri = "/v1/#{@options[:merchant_id]}/"
430
+ version = ogone_direct? ? 'v2' : 'v1'
431
+ uri = "/#{version}/#{@options[:merchant_id]}/"
411
432
  case action
412
433
  when :authorize
413
434
  uri + 'payments'
414
435
  when :capture
415
- uri + "payments/#{authorization}/approve"
436
+ capture_name = ogone_direct? ? 'capture' : 'approve'
437
+ uri + "payments/#{authorization}/#{capture_name}"
416
438
  when :refund
417
439
  uri + "payments/#{authorization}/refund"
418
440
  when :void
@@ -423,7 +445,7 @@ module ActiveMerchant #:nodoc:
423
445
  end
424
446
 
425
447
  def idempotency_key_for_signature(options)
426
- "x-gcs-idempotence-key:#{options[:idempotency_key]}" if options[:idempotency_key]
448
+ "x-gcs-idempotence-key:#{options[:idempotency_key]}" if options[:idempotency_key] && !ogone_direct?
427
449
  end
428
450
 
429
451
  def commit(method, action, post, authorization: nil, options: {})
@@ -461,7 +483,7 @@ module ActiveMerchant #:nodoc:
461
483
  'Date' => date
462
484
  }
463
485
 
464
- headers['X-GCS-Idempotence-Key'] = options[:idempotency_key] if options[:idempotency_key]
486
+ headers['X-GCS-Idempotence-Key'] = options[:idempotency_key] if options[:idempotency_key] && !ogone_direct?
465
487
  headers
466
488
  end
467
489
 
@@ -474,13 +496,13 @@ module ActiveMerchant #:nodoc:
474
496
  #{uri(action, authorization)}
475
497
  REQUEST
476
498
  data = data.each_line.reject { |line| line.strip == '' }.join
477
- digest = OpenSSL::Digest.new('sha256')
499
+ digest = OpenSSL::Digest.new('SHA256')
478
500
  key = @options[:secret_api_key]
479
- "GCS v1HMAC:#{@options[:api_key_id]}:#{Base64.strict_encode64(OpenSSL::HMAC.digest(digest, key, data))}"
501
+ "GCS v1HMAC:#{@options[:api_key_id]}:#{Base64.strict_encode64(OpenSSL::HMAC.digest(digest, key, data)).strip}"
480
502
  end
481
503
 
482
504
  def date
483
- @date ||= Time.now.gmtime.strftime('%a, %d %b %Y %H:%M:%S %Z') # Must be same in digest and HTTP header
505
+ @date ||= Time.now.gmtime.strftime('%a, %d %b %Y %H:%M:%S GMT')
484
506
  end
485
507
 
486
508
  def content_type
@@ -108,6 +108,7 @@ module ActiveMerchant #:nodoc:
108
108
  xml.tag! 'n2:PaymentAction', action
109
109
  xml.tag! 'n2:Token', options[:token]
110
110
  xml.tag! 'n2:PayerID', options[:payer_id]
111
+ xml.tag! 'n2:MsgSubID', options[:idempotency_key] if options[:idempotency_key]
111
112
  add_payment_details(xml, money, currency_code, options)
112
113
  end
113
114
  end
@@ -251,6 +252,7 @@ module ActiveMerchant #:nodoc:
251
252
  add_payment_details(xml, money, currency_code, options)
252
253
  xml.tag! 'n2:IPAddress', options[:ip]
253
254
  xml.tag! 'n2:MerchantSessionId', options[:merchant_session_id] if options[:merchant_session_id].present?
255
+ xml.tag! 'n2:MsgSubID', options[:idempotency_key] if options[:idempotency_key]
254
256
  end
255
257
  end
256
258
  end
@@ -455,7 +455,7 @@ module ActiveMerchant #:nodoc:
455
455
  when 'verify_credentials'
456
456
  response['error'] || 'FAILED'
457
457
  else
458
- response['transactionResponse']['errorCode'] || response['transactionResponse']['responseCode'] if response['transactionResponse']
458
+ response['transactionResponse']['paymentNetworkResponseCode'] || response['transactionResponse']['errorCode'] if response['transactionResponse']
459
459
  end
460
460
  end
461
461
 
@@ -538,6 +538,7 @@ module ActiveMerchant #:nodoc:
538
538
  xml.DS_MERCHANT_COF_INI data[:DS_MERCHANT_COF_INI]
539
539
  xml.DS_MERCHANT_COF_TYPE data[:DS_MERCHANT_COF_TYPE]
540
540
  xml.DS_MERCHANT_COF_TXNID data[:DS_MERCHANT_COF_TXNID] if data[:DS_MERCHANT_COF_TXNID]
541
+ xml.DS_MERCHANT_DIRECTPAYMENT 'false' if options[:stored_credential][:initial_transaction]
541
542
  end
542
543
  end
543
544
  end
@@ -91,7 +91,7 @@ module ActiveMerchant #:nodoc:
91
91
  commit(action, post, options)
92
92
  end
93
93
 
94
- def refund(money, authorization, options = {})
94
+ def refund(money, payment_method, options = {})
95
95
  post = {}
96
96
  action = 'refund'
97
97
 
@@ -99,12 +99,15 @@ module ActiveMerchant #:nodoc:
99
99
  add_invoice(post, money, options)
100
100
  add_clerk(post, options)
101
101
  add_transaction(post, options)
102
- add_card(action, post, get_card_token(authorization), options)
102
+ card_token = payment_method.is_a?(CreditCard) ? get_card_token(payment_method) : payment_method
103
+ add_card(action, post, card_token, options)
103
104
  add_card_present(post, options)
104
105
 
105
106
  commit(action, post, options)
106
107
  end
107
108
 
109
+ alias credit refund
110
+
108
111
  def void(authorization, options = {})
109
112
  options[:invoice] = get_invoice(authorization)
110
113
  commit('invoice', {}, options)
@@ -652,18 +652,19 @@ module ActiveMerchant #:nodoc:
652
652
  end
653
653
  end
654
654
 
655
- def headers(options = {})
656
- key = options[:key] || @api_key
657
- idempotency_key = options[:idempotency_key]
655
+ def key(options = {})
656
+ options[:key] || @api_key
657
+ end
658
658
 
659
+ def headers(options = {})
659
660
  headers = {
660
- 'Authorization' => 'Basic ' + Base64.strict_encode64(key.to_s + ':').strip,
661
+ 'Authorization' => 'Basic ' + Base64.strict_encode64(key(options).to_s + ':').strip,
661
662
  'User-Agent' => "Stripe/v1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
662
663
  'Stripe-Version' => api_version(options),
663
664
  'X-Stripe-Client-User-Agent' => stripe_client_user_agent(options),
664
665
  'X-Stripe-Client-User-Metadata' => { ip: options[:ip] }.to_json
665
666
  }
666
- headers['Idempotency-Key'] = idempotency_key if idempotency_key
667
+ headers['Idempotency-Key'] = options[:idempotency_key] if options[:idempotency_key]
667
668
  headers['Stripe-Account'] = options[:stripe_account] if options[:stripe_account]
668
669
  headers
669
670
  end
@@ -694,6 +695,9 @@ module ActiveMerchant #:nodoc:
694
695
 
695
696
  def commit(method, url, parameters = nil, options = {})
696
697
  add_expand_parameters(parameters, options) if parameters
698
+
699
+ return Response.new(false, 'Invalid API Key provided') if test? && !key(options).start_with?('sk_test')
700
+
697
701
  response = api_request(method, url, parameters, options)
698
702
  response['webhook_id'] = options[:webhook_id] if options[:webhook_id]
699
703
  success = success_from(response, options)
@@ -683,7 +683,8 @@ module ActiveMerchant #:nodoc:
683
683
  'year' => format(payment_method.year, :four_digits_year)
684
684
  )
685
685
  end
686
- xml.cardHolderName card_holder_name(payment_method, options)
686
+ name = card_holder_name(payment_method, options)
687
+ xml.cardHolderName name if name.present?
687
688
  xml.cvc payment_method.verification_value
688
689
 
689
690
  add_address(xml, (options[:billing_address] || options[:address]), options)
@@ -995,10 +996,10 @@ module ActiveMerchant #:nodoc:
995
996
  case payment_method
996
997
  when String
997
998
  token_type_and_details(payment_method)
998
- when NetworkTokenizationCreditCard
999
- { payment_type: :network_token }
1000
999
  else
1001
- { payment_type: :credit }
1000
+ type = payment_method.respond_to?(:source) ? :network_token : :credit
1001
+
1002
+ { payment_type: type }
1002
1003
  end
1003
1004
  end
1004
1005
 
@@ -1,3 +1,3 @@
1
1
  module ActiveMerchant
2
- VERSION = '1.129.0'
2
+ VERSION = '1.130.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.129.0
4
+ version: 1.130.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: 2023-05-03 00:00:00.000000000 Z
11
+ date: 2023-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -480,7 +480,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
480
480
  - !ruby/object:Gem::Version
481
481
  version: '0'
482
482
  requirements: []
483
- rubygems_version: 3.4.12
483
+ rubygems_version: 3.4.13
484
484
  signing_key:
485
485
  specification_version: 4
486
486
  summary: Framework and tools for dealing with credit card transactions.