activemerchant 1.133.0 → 1.137.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +240 -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 +11 -8
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +4 -0
  7. data/lib/active_merchant/billing/credit_card_methods.rb +59 -6
  8. data/lib/active_merchant/billing/gateway.rb +9 -0
  9. data/lib/active_merchant/billing/gateways/adyen.rb +162 -43
  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 +43 -35
  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/braintree/token_nonce.rb +65 -20
  21. data/lib/active_merchant/billing/gateways/braintree_blue.rb +226 -73
  22. data/lib/active_merchant/billing/gateways/braintree_orange.rb +1 -1
  23. data/lib/active_merchant/billing/gateways/card_connect.rb +5 -2
  24. data/lib/active_merchant/billing/gateways/card_stream.rb +4 -6
  25. data/lib/active_merchant/billing/gateways/cashnet.rb +1 -1
  26. data/lib/active_merchant/billing/gateways/cecabank/cecabank_common.rb +36 -0
  27. data/lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb +316 -0
  28. data/lib/active_merchant/billing/gateways/cecabank/cecabank_xml.rb +220 -0
  29. data/lib/active_merchant/billing/gateways/cecabank.rb +7 -240
  30. data/lib/active_merchant/billing/gateways/checkout_v2.rb +238 -34
  31. data/lib/active_merchant/billing/gateways/commerce_hub.rb +63 -6
  32. data/lib/active_merchant/billing/gateways/credorax.rb +3 -5
  33. data/lib/active_merchant/billing/gateways/cyber_source.rb +185 -47
  34. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +102 -58
  35. data/lib/active_merchant/billing/gateways/d_local.rb +26 -15
  36. data/lib/active_merchant/billing/gateways/data_cash.rb +21 -17
  37. data/lib/active_merchant/billing/gateways/datatrans.rb +279 -0
  38. data/lib/active_merchant/billing/gateways/decidir.rb +53 -18
  39. data/lib/active_merchant/billing/gateways/decidir_plus.rb +4 -1
  40. data/lib/active_merchant/billing/gateways/deepstack.rb +382 -0
  41. data/lib/active_merchant/billing/gateways/ebanx.rb +40 -36
  42. data/lib/active_merchant/billing/gateways/efsnet.rb +6 -2
  43. data/lib/active_merchant/billing/gateways/elavon.rb +99 -33
  44. data/lib/active_merchant/billing/gateways/element.rb +36 -7
  45. data/lib/active_merchant/billing/gateways/epay.rb +6 -2
  46. data/lib/active_merchant/billing/gateways/evo_ca.rb +6 -2
  47. data/lib/active_merchant/billing/gateways/eway.rb +4 -2
  48. data/lib/active_merchant/billing/gateways/eway_managed.rb +6 -2
  49. data/lib/active_merchant/billing/gateways/exact.rb +6 -2
  50. data/lib/active_merchant/billing/gateways/fat_zebra.rb +31 -3
  51. data/lib/active_merchant/billing/gateways/federated_canada.rb +6 -2
  52. data/lib/active_merchant/billing/gateways/first_pay/first_pay_common.rb +15 -0
  53. data/lib/active_merchant/billing/gateways/first_pay/first_pay_json.rb +190 -0
  54. data/lib/active_merchant/billing/gateways/first_pay/first_pay_xml.rb +183 -0
  55. data/lib/active_merchant/billing/gateways/first_pay.rb +6 -172
  56. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +6 -2
  57. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +7 -3
  58. data/lib/active_merchant/billing/gateways/flex_charge.rb +347 -0
  59. data/lib/active_merchant/billing/gateways/garanti.rb +4 -2
  60. data/lib/active_merchant/billing/gateways/global_collect.rb +45 -37
  61. data/lib/active_merchant/billing/gateways/hi_pay.rb +286 -0
  62. data/lib/active_merchant/billing/gateways/hps.rb +1 -1
  63. data/lib/active_merchant/billing/gateways/iats_payments.rb +7 -2
  64. data/lib/active_merchant/billing/gateways/inspire.rb +6 -4
  65. data/lib/active_merchant/billing/gateways/instapay.rb +7 -4
  66. data/lib/active_merchant/billing/gateways/ipg.rb +9 -5
  67. data/lib/active_merchant/billing/gateways/iridium.rb +15 -5
  68. data/lib/active_merchant/billing/gateways/itransact.rb +6 -2
  69. data/lib/active_merchant/billing/gateways/iveri.rb +3 -3
  70. data/lib/active_merchant/billing/gateways/ixopay.rb +2 -2
  71. data/lib/active_merchant/billing/gateways/jetpay.rb +4 -2
  72. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +4 -2
  73. data/lib/active_merchant/billing/gateways/kushki.rb +72 -12
  74. data/lib/active_merchant/billing/gateways/linkpoint.rb +6 -2
  75. data/lib/active_merchant/billing/gateways/litle.rb +33 -50
  76. data/lib/active_merchant/billing/gateways/mastercard.rb +4 -4
  77. data/lib/active_merchant/billing/gateways/maxipago.rb +2 -2
  78. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +8 -5
  79. data/lib/active_merchant/billing/gateways/merchant_ware.rb +11 -4
  80. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +11 -4
  81. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +19 -3
  82. data/lib/active_merchant/billing/gateways/mercury.rb +6 -2
  83. data/lib/active_merchant/billing/gateways/metrics_global.rb +8 -6
  84. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +1 -0
  85. data/lib/active_merchant/billing/gateways/migs.rb +6 -2
  86. data/lib/active_merchant/billing/gateways/mit.rb +8 -3
  87. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +18 -10
  88. data/lib/active_merchant/billing/gateways/monei.rb +1 -1
  89. data/lib/active_merchant/billing/gateways/moneris.rb +9 -3
  90. data/lib/active_merchant/billing/gateways/money_movers.rb +6 -2
  91. data/lib/active_merchant/billing/gateways/nab_transact.rb +12 -4
  92. data/lib/active_merchant/billing/gateways/net_registry.rb +6 -2
  93. data/lib/active_merchant/billing/gateways/netbanx.rb +1 -3
  94. data/lib/active_merchant/billing/gateways/netbilling.rb +6 -2
  95. data/lib/active_merchant/billing/gateways/network_merchants.rb +6 -2
  96. data/lib/active_merchant/billing/gateways/nmi.rb +18 -6
  97. data/lib/active_merchant/billing/gateways/ogone.rb +6 -2
  98. data/lib/active_merchant/billing/gateways/openpay.rb +4 -2
  99. data/lib/active_merchant/billing/gateways/opp.rb +1 -2
  100. data/lib/active_merchant/billing/gateways/optimal_payment.rb +6 -2
  101. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +1 -3
  102. data/lib/active_merchant/billing/gateways/orbital.rb +83 -24
  103. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +7 -4
  104. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +6 -2
  105. data/lib/active_merchant/billing/gateways/pay_hub.rb +4 -2
  106. data/lib/active_merchant/billing/gateways/pay_junction.rb +6 -2
  107. data/lib/active_merchant/billing/gateways/pay_secure.rb +6 -2
  108. data/lib/active_merchant/billing/gateways/pay_trace.rb +31 -18
  109. data/lib/active_merchant/billing/gateways/payeezy.rb +19 -8
  110. data/lib/active_merchant/billing/gateways/payex.rb +4 -2
  111. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
  112. data/lib/active_merchant/billing/gateways/payflow.rb +1 -3
  113. data/lib/active_merchant/billing/gateways/payment_express.rb +8 -4
  114. data/lib/active_merchant/billing/gateways/paymentez.rb +23 -11
  115. data/lib/active_merchant/billing/gateways/paysafe.rb +12 -11
  116. data/lib/active_merchant/billing/gateways/payscout.rb +7 -4
  117. data/lib/active_merchant/billing/gateways/paystation.rb +7 -3
  118. data/lib/active_merchant/billing/gateways/payway.rb +6 -2
  119. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +2 -2
  120. data/lib/active_merchant/billing/gateways/pin.rb +22 -4
  121. data/lib/active_merchant/billing/gateways/plexo.rb +49 -10
  122. data/lib/active_merchant/billing/gateways/plugnpay.rb +6 -2
  123. data/lib/active_merchant/billing/gateways/priority.rb +6 -5
  124. data/lib/active_merchant/billing/gateways/psigate.rb +6 -2
  125. data/lib/active_merchant/billing/gateways/psl_card.rb +6 -2
  126. data/lib/active_merchant/billing/gateways/qbms.rb +6 -2
  127. data/lib/active_merchant/billing/gateways/quantum.rb +6 -2
  128. data/lib/active_merchant/billing/gateways/quickbooks.rb +6 -5
  129. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +7 -4
  130. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +6 -2
  131. data/lib/active_merchant/billing/gateways/rapyd.rb +148 -46
  132. data/lib/active_merchant/billing/gateways/reach.rb +11 -4
  133. data/lib/active_merchant/billing/gateways/redsys.rb +2 -10
  134. data/lib/active_merchant/billing/gateways/redsys_rest.rb +507 -0
  135. data/lib/active_merchant/billing/gateways/s5.rb +3 -3
  136. data/lib/active_merchant/billing/gateways/safe_charge.rb +36 -16
  137. data/lib/active_merchant/billing/gateways/sage.rb +12 -4
  138. data/lib/active_merchant/billing/gateways/sage_pay.rb +79 -5
  139. data/lib/active_merchant/billing/gateways/sallie_mae.rb +6 -2
  140. data/lib/active_merchant/billing/gateways/secure_net.rb +6 -2
  141. data/lib/active_merchant/billing/gateways/secure_pay.rb +8 -6
  142. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +12 -4
  143. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +6 -2
  144. data/lib/active_merchant/billing/gateways/securion_pay.rb +24 -10
  145. data/lib/active_merchant/billing/gateways/shift4.rb +17 -20
  146. data/lib/active_merchant/billing/gateways/shift4_v2.rb +117 -0
  147. data/lib/active_merchant/billing/gateways/simetrik.rb +17 -11
  148. data/lib/active_merchant/billing/gateways/skip_jack.rb +6 -2
  149. data/lib/active_merchant/billing/gateways/smart_ps.rb +7 -4
  150. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +4 -2
  151. data/lib/active_merchant/billing/gateways/spreedly_core.rb +2 -4
  152. data/lib/active_merchant/billing/gateways/stripe.rb +53 -21
  153. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +199 -50
  154. data/lib/active_merchant/billing/gateways/sum_up.rb +223 -0
  155. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +4 -2
  156. data/lib/active_merchant/billing/gateways/telr.rb +3 -4
  157. data/lib/active_merchant/billing/gateways/trans_first.rb +1 -2
  158. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +8 -16
  159. data/lib/active_merchant/billing/gateways/transact_pro.rb +1 -1
  160. data/lib/active_merchant/billing/gateways/trust_commerce.rb +6 -2
  161. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +9 -8
  162. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +6 -2
  163. data/lib/active_merchant/billing/gateways/vanco.rb +2 -4
  164. data/lib/active_merchant/billing/gateways/vantiv_express.rb +587 -0
  165. data/lib/active_merchant/billing/gateways/verifi.rb +6 -2
  166. data/lib/active_merchant/billing/gateways/viaklix.rb +6 -2
  167. data/lib/active_merchant/billing/gateways/visanet_peru.rb +2 -2
  168. data/lib/active_merchant/billing/gateways/vpos.rb +3 -3
  169. data/lib/active_merchant/billing/gateways/wirecard.rb +7 -3
  170. data/lib/active_merchant/billing/gateways/wompi.rb +5 -0
  171. data/lib/active_merchant/billing/gateways/worldpay.rb +140 -73
  172. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +13 -10
  173. data/lib/active_merchant/billing/gateways/xpay.rb +242 -0
  174. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
  175. data/lib/active_merchant/billing/response.rb +2 -2
  176. data/lib/active_merchant/connection.rb +3 -17
  177. data/lib/active_merchant/country.rb +1 -0
  178. data/lib/active_merchant/errors.rb +10 -0
  179. data/lib/active_merchant/version.rb +1 -1
  180. data/lib/support/gateway_support.rb +2 -2
  181. data/lib/support/ssl_verify.rb +4 -4
  182. data/lib/support/ssl_version.rb +6 -6
  183. metadata +30 -9
@@ -28,14 +28,20 @@ module ActiveMerchant #:nodoc:
28
28
  maestro: '042',
29
29
  master: '002',
30
30
  unionpay: '062',
31
- visa: '001'
31
+ visa: '001',
32
+ carnet: '058'
32
33
  }
33
34
 
34
- PAYMENT_SOLUTION = {
35
+ WALLET_PAYMENT_SOLUTION = {
35
36
  apple_pay: '001',
36
37
  google_pay: '012'
37
38
  }
38
39
 
40
+ NT_PAYMENT_SOLUTION = {
41
+ 'master' => '014',
42
+ 'visa' => '015'
43
+ }
44
+
39
45
  def initialize(options = {})
40
46
  requires!(options, :merchant_id, :public_key, :private_key)
41
47
  super
@@ -93,6 +99,7 @@ module ActiveMerchant #:nodoc:
93
99
  gsub(/(\\?"number\\?":\\?")\d+/, '\1[FILTERED]').
94
100
  gsub(/(\\?"routingNumber\\?":\\?")\d+/, '\1[FILTERED]').
95
101
  gsub(/(\\?"securityCode\\?":\\?")\d+/, '\1[FILTERED]').
102
+ gsub(/(\\?"cryptogram\\?":\\?")[^<]+/, '\1[FILTERED]').
96
103
  gsub(/(signature=")[^"]*/, '\1[FILTERED]').
97
104
  gsub(/(keyid=")[^"]*/, '\1[FILTERED]').
98
105
  gsub(/(Digest: SHA-256=)[\w\/\+=]*/, '\1[FILTERED]')
@@ -100,6 +107,47 @@ module ActiveMerchant #:nodoc:
100
107
 
101
108
  private
102
109
 
110
+ def add_level_2_data(post, options)
111
+ return unless options[:purchase_order_number]
112
+
113
+ post[:orderInformation][:invoiceDetails] ||= {}
114
+ post[:orderInformation][:invoiceDetails][:purchaseOrderNumber] = options[:purchase_order_number]
115
+ end
116
+
117
+ def add_level_3_data(post, options)
118
+ return unless options[:line_items]
119
+
120
+ post[:orderInformation][:lineItems] = options[:line_items]
121
+ post[:processingInformation][:purchaseLevel] = '3'
122
+ post[:orderInformation][:shipping_details] = { shipFromPostalCode: options[:ships_from_postal_code] }
123
+ post[:orderInformation][:amountDetails] ||= {}
124
+ post[:orderInformation][:amountDetails][:discountAmount] = options[:discount_amount]
125
+ end
126
+
127
+ def add_three_ds(post, payment_method, options)
128
+ return unless three_d_secure = options[:three_d_secure]
129
+
130
+ post[:consumerAuthenticationInformation] ||= {}
131
+ if payment_method.brand == 'master'
132
+ post[:consumerAuthenticationInformation][:ucafAuthenticationData] = three_d_secure[:cavv]
133
+ post[:consumerAuthenticationInformation][:ucafCollectionIndicator] = '2'
134
+ else
135
+ post[:consumerAuthenticationInformation][:cavv] = three_d_secure[:cavv]
136
+ end
137
+ post[:consumerAuthenticationInformation][:cavvAlgorithm] = three_d_secure[:cavv_algorithm] if three_d_secure[:cavv_algorithm]
138
+ post[:consumerAuthenticationInformation][:paSpecificationVersion] = three_d_secure[:version] if three_d_secure[:version]
139
+ post[:consumerAuthenticationInformation][:directoryServerTransactionID] = three_d_secure[:ds_transaction_id] if three_d_secure[:ds_transaction_id]
140
+ post[:consumerAuthenticationInformation][:eciRaw] = three_d_secure[:eci] if three_d_secure[:eci]
141
+ if three_d_secure[:xid].present?
142
+ post[:consumerAuthenticationInformation][:xid] = three_d_secure[:xid]
143
+ else
144
+ post[:consumerAuthenticationInformation][:xid] = three_d_secure[:cavv]
145
+ end
146
+ post[:consumerAuthenticationInformation][:veresEnrolled] = three_d_secure[:enrolled] if three_d_secure[:enrolled]
147
+ post[:consumerAuthenticationInformation][:paresStatus] = three_d_secure[:authentication_response_status] if three_d_secure[:authentication_response_status]
148
+ post
149
+ end
150
+
103
151
  def build_void_request(amount = nil)
104
152
  { reversalInformation: { amountDetails: { totalAmount: nil } } }.tap do |post|
105
153
  add_reversal_amount(post, amount.to_i) if amount.present?
@@ -118,6 +166,9 @@ module ActiveMerchant #:nodoc:
118
166
  add_business_rules_data(post, payment, options)
119
167
  add_partner_solution_id(post)
120
168
  add_stored_credentials(post, payment, options)
169
+ add_three_ds(post, payment, options)
170
+ add_level_2_data(post, options)
171
+ add_level_3_data(post, options)
121
172
  end.compact
122
173
  end
123
174
 
@@ -191,25 +242,30 @@ module ActiveMerchant #:nodoc:
191
242
  end
192
243
 
193
244
  def add_network_tokenization_card(post, payment, options)
194
- post[:processingInformation][:paymentSolution] = PAYMENT_SOLUTION[payment.source]
195
- post[:processingInformation][:commerceIndicator] = 'internet' unless card_brand(payment) == 'jcb'
245
+ post[:processingInformation][:commerceIndicator] = 'internet' unless options[:stored_credential] || card_brand(payment) == 'jcb'
196
246
 
197
247
  post[:paymentInformation][:tokenizedCard] = {
198
248
  number: payment.number,
199
249
  expirationMonth: payment.month,
200
250
  expirationYear: payment.year,
201
251
  cryptogram: payment.payment_cryptogram,
202
- transactionType: '1',
203
- type: CREDIT_CARD_CODES[card_brand(payment).to_sym]
252
+ type: CREDIT_CARD_CODES[card_brand(payment).to_sym],
253
+ transactionType: payment.source == :network_token ? '3' : '1'
204
254
  }
205
255
 
206
- if card_brand(payment) == 'master'
207
- post[:consumerAuthenticationInformation] = {
208
- ucafAuthenticationData: payment.payment_cryptogram,
209
- ucafCollectionIndicator: '2'
210
- }
256
+ if payment.source == :network_token && NT_PAYMENT_SOLUTION[payment.brand]
257
+ post[:processingInformation][:paymentSolution] = NT_PAYMENT_SOLUTION[payment.brand]
211
258
  else
212
- post[:consumerAuthenticationInformation] = { cavv: payment.payment_cryptogram }
259
+ # Apple Pay / Google Pay
260
+ post[:processingInformation][:paymentSolution] = WALLET_PAYMENT_SOLUTION[payment.source]
261
+ if card_brand(payment) == 'master'
262
+ post[:consumerAuthenticationInformation] = {
263
+ ucafAuthenticationData: payment.payment_cryptogram,
264
+ ucafCollectionIndicator: '2'
265
+ }
266
+ else
267
+ post[:consumerAuthenticationInformation] = { cavv: payment.payment_cryptogram }
268
+ end
213
269
  end
214
270
  end
215
271
 
@@ -258,56 +314,43 @@ module ActiveMerchant #:nodoc:
258
314
  end
259
315
 
260
316
  def add_stored_credentials(post, payment, options)
261
- return unless stored_credential = options[:stored_credential]
317
+ return unless options[:stored_credential]
262
318
 
263
- options = stored_credential_options(stored_credential, options.fetch(:reason_code, ''))
264
- post[:processingInformation][:commerceIndicator] = options.fetch(:transaction_type, 'internet')
265
- stored_credential[:initial_transaction] ? initial_transaction(post, options) : subsequent_transaction(post, options)
319
+ post[:processingInformation][:commerceIndicator] = commerce_indicator(options.dig(:stored_credential, :reason_type))
320
+ add_authorization_options(post, payment, options)
266
321
  end
267
322
 
268
- def stored_credential_options(options, reason_code)
269
- transaction_type = options[:reason_type]
270
- transaction_type = 'install' if transaction_type == 'installment'
271
- initiator = options[:initiator] if options[:initiator]
272
- initiator = 'customer' if initiator == 'cardholder'
273
- stored_on_file = options[:reason_type] == 'recurring'
274
- options.merge({
275
- transaction_type: transaction_type,
276
- initiator: initiator,
277
- reason_code: reason_code,
278
- stored_on_file: stored_on_file
279
- })
323
+ def commerce_indicator(reason_type)
324
+ case reason_type
325
+ when 'recurring'
326
+ 'recurring'
327
+ when 'installment'
328
+ 'install'
329
+ else
330
+ 'internet'
331
+ end
280
332
  end
281
333
 
282
- def add_processing_information(initiator, merchant_initiated_transaction_hash = {})
283
- {
334
+ def add_authorization_options(post, payment, options)
335
+ initiator = options.dig(:stored_credential, :initiator) == 'cardholder' ? 'customer' : 'merchant'
336
+ authorization_options = {
284
337
  authorizationOptions: {
285
338
  initiator: {
286
- type: initiator,
287
- merchantInitiatedTransaction: merchant_initiated_transaction_hash,
288
- storedCredentialUsed: true
339
+ type: initiator
289
340
  }
290
341
  }
291
342
  }.compact
292
- end
293
-
294
- def initial_transaction(post, options)
295
- processing_information = add_processing_information(options[:initiator], {
296
- reason: options[:reason_code]
297
- })
298
343
 
299
- post[:processingInformation].merge!(processing_information)
300
- end
301
-
302
- def subsequent_transaction(post, options)
303
- network_transaction_id = options[:network_transaction_id] || options.dig(:stored_credential, :network_transaction_id) || ''
304
- processing_information = add_processing_information(options[:initiator], {
305
- originalAuthorizedAmount: post.dig(:orderInformation, :amountDetails, :totalAmount),
306
- previousTransactionID: network_transaction_id,
307
- reason: options[:reason_code],
308
- storedCredentialUsed: options[:stored_on_file]
309
- })
310
- post[:processingInformation].merge!(processing_information)
344
+ authorization_options[:authorizationOptions][:initiator][:storedCredentialUsed] = true if initiator == 'merchant'
345
+ authorization_options[:authorizationOptions][:initiator][:credentialStoredOnFile] = true if options.dig(:stored_credential, :initial_transaction)
346
+ authorization_options[:authorizationOptions][:initiator][:merchantInitiatedTransaction] ||= {}
347
+ unless options.dig(:stored_credential, :initial_transaction)
348
+ network_transaction_id = options[:network_transaction_id] || options.dig(:stored_credential, :network_transaction_id) || ''
349
+ authorization_options[:authorizationOptions][:initiator][:merchantInitiatedTransaction][:previousTransactionID] = network_transaction_id
350
+ authorization_options[:authorizationOptions][:initiator][:merchantInitiatedTransaction][:originalAuthorizedAmount] = post.dig(:orderInformation, :amountDetails, :totalAmount) if card_brand(payment) == 'discover'
351
+ end
352
+ authorization_options[:authorizationOptions][:initiator][:merchantInitiatedTransaction][:reason] = options[:reason_code] if options[:reason_code]
353
+ post[:processingInformation].merge!(authorization_options)
311
354
  end
312
355
 
313
356
  def network_transaction_id_from(response)
@@ -315,7 +358,7 @@ module ActiveMerchant #:nodoc:
315
358
  end
316
359
 
317
360
  def url(action)
318
- "#{(test? ? test_url : live_url)}/pts/v2/#{action}"
361
+ "#{test? ? test_url : live_url}/pts/v2/#{action}"
319
362
  end
320
363
 
321
364
  def host
@@ -330,7 +373,7 @@ module ActiveMerchant #:nodoc:
330
373
  add_reconciliation_id(post, options)
331
374
  add_sec_code(post, options)
332
375
  add_invoice_number(post, options)
333
- response = parse(ssl_post(url(action), post.to_json, auth_headers(action, post)))
376
+ response = parse(ssl_post(url(action), post.to_json, auth_headers(action, options, post)))
334
377
  Response.new(
335
378
  success_from(response),
336
379
  message_from(response),
@@ -378,7 +421,7 @@ module ActiveMerchant #:nodoc:
378
421
  string_to_sign = {
379
422
  host: host,
380
423
  date: gmtdatetime,
381
- "(request-target)": "#{http_method} /pts/v2/#{resource}",
424
+ "request-target": "#{http_method} /pts/v2/#{resource}",
382
425
  digest: digest,
383
426
  "v-c-merchant-id": @options[:merchant_id]
384
427
  }.map { |k, v| "#{k}: #{v}" }.join("\n").force_encoding(Encoding::UTF_8)
@@ -386,7 +429,7 @@ module ActiveMerchant #:nodoc:
386
429
  {
387
430
  keyid: @options[:public_key],
388
431
  algorithm: 'HmacSHA256',
389
- headers: "host date (request-target)#{digest.present? ? ' digest' : ''} v-c-merchant-id",
432
+ headers: "host date request-target#{digest.present? ? ' digest' : ''} v-c-merchant-id",
390
433
  signature: sign_payload(string_to_sign)
391
434
  }.map { |k, v| %{#{k}="#{v}"} }.join(', ')
392
435
  end
@@ -396,14 +439,14 @@ module ActiveMerchant #:nodoc:
396
439
  Base64.strict_encode64(OpenSSL::HMAC.digest('sha256', decoded_key, payload))
397
440
  end
398
441
 
399
- def auth_headers(action, post, http_method = 'post')
442
+ def auth_headers(action, options, post, http_method = 'post')
400
443
  digest = "SHA-256=#{Digest::SHA256.base64digest(post.to_json)}" if post.present?
401
444
  date = Time.now.httpdate
402
445
 
403
446
  {
404
447
  'Accept' => 'application/hal+json;charset=utf-8',
405
448
  'Content-Type' => 'application/json;charset=utf-8',
406
- 'V-C-Merchant-Id' => @options[:merchant_id],
449
+ 'V-C-Merchant-Id' => options[:merchant_id] || @options[:merchant_id],
407
450
  'Date' => date,
408
451
  'Host' => host,
409
452
  'Signature' => get_http_signature(action, digest, http_method, date),
@@ -441,7 +484,8 @@ module ActiveMerchant #:nodoc:
441
484
  def add_invoice_number(post, options)
442
485
  return unless options[:invoice_number].present?
443
486
 
444
- post[:orderInformation][:invoiceDetails] = { invoiceNumber: options[:invoice_number] }
487
+ post[:orderInformation][:invoiceDetails] ||= {}
488
+ post[:orderInformation][:invoiceDetails][:invoiceNumber] = options[:invoice_number]
445
489
  end
446
490
 
447
491
  def add_partner_solution_id(post)
@@ -118,16 +118,18 @@ module ActiveMerchant #:nodoc:
118
118
 
119
119
  def add_payer(post, card, options)
120
120
  address = options[:billing_address] || options[:address]
121
+ phone_number = address[:phone] || address[:phone_number] if address
122
+
121
123
  post[:payer] = {}
122
124
  post[:payer][:name] = card.name
123
125
  post[:payer][:email] = options[:email] if options[:email]
124
126
  post[:payer][:birth_date] = options[:birth_date] if options[:birth_date]
125
- post[:payer][:phone] = address[:phone] if address && address[:phone]
127
+ post[:payer][:phone] = phone_number if phone_number
126
128
  post[:payer][:document] = options[:document] if options[:document]
127
129
  post[:payer][:document2] = options[:document2] if options[:document2]
128
130
  post[:payer][:user_reference] = options[:user_reference] if options[:user_reference]
129
131
  post[:payer][:event_uuid] = options[:device_id] if options[:device_id]
130
- post[:payer][:onboarding_ip_address] = options[:ip] if options[:ip]
132
+ post[:payer][:ip] = options[:ip] if options[:ip]
131
133
  post[:payer][:address] = add_address(post, card, options)
132
134
  end
133
135
 
@@ -163,23 +165,19 @@ module ActiveMerchant #:nodoc:
163
165
  post[:card][:network_token] = card.number
164
166
  post[:card][:cryptogram] = card.payment_cryptogram
165
167
  post[:card][:eci] = card.eci
166
- # used case of Network Token: 'CARD_ON_FILE', 'SUBSCRIPTION', 'UNSCHEDULED_CARD_ON_FILE'
167
- if options.dig(:stored_credential, :reason_type) == 'unscheduled'
168
- if options.dig(:stored_credential, :initiator) == 'merchant'
169
- post[:card][:stored_credential_type] = 'UNSCHEDULED_CARD_ON_FILE'
170
- else
171
- post[:card][:stored_credential_type] = 'CARD_ON_FILE'
172
- end
173
- else
174
- post[:card][:stored_credential_type] = 'SUBSCRIPTION'
175
- end
176
- # required for MC debit recurrent in BR 'USED'(subsecuence Payments) . 'FIRST' an inital payment
177
- post[:card][:stored_credential_usage] = (options[:stored_credential][:initial_transaction] ? 'FIRST' : 'USED') if options[:stored_credential]
178
168
  else
179
169
  post[:card][:number] = card.number
180
170
  post[:card][:cvv] = card.verification_value
181
171
  end
182
172
 
173
+ if options[:stored_credential]
174
+ # required for MC debit recurrent in BR 'USED'(subsecuence Payments) . 'FIRST' an inital payment
175
+ post[:card][:stored_credential_usage] = (options[:stored_credential][:initial_transaction] ? 'FIRST' : 'USED')
176
+ post[:card][:network_payment_reference] = options[:stored_credential][:network_transaction_id] if options[:stored_credential][:network_transaction_id]
177
+ # used case of Network Token: 'CARD_ON_FILE', 'SUBSCRIPTION', 'UNSCHEDULED_CARD_ON_FILE'
178
+ post[:card][:stored_credential_type] = fetch_stored_credential_type(options[:stored_credential])
179
+ end
180
+
183
181
  post[:card][:holder_name] = card.name
184
182
  post[:card][:expiration_month] = card.month
185
183
  post[:card][:expiration_year] = card.year
@@ -191,6 +189,14 @@ module ActiveMerchant #:nodoc:
191
189
  post[:card][:save] = options[:save] if options[:save]
192
190
  end
193
191
 
192
+ def fetch_stored_credential_type(stored_credential)
193
+ if stored_credential[:reason_type] == 'unscheduled'
194
+ stored_credential[:initiator] == 'merchant' ? 'UNSCHEDULED_CARD_ON_FILE' : 'CARD_ON_FILE'
195
+ else
196
+ 'SUBSCRIPTION'
197
+ end
198
+ end
199
+
194
200
  def parse(body)
195
201
  JSON.parse(body)
196
202
  end
@@ -218,6 +224,7 @@ module ActiveMerchant #:nodoc:
218
224
  message_from(action, response),
219
225
  response,
220
226
  authorization: authorization_from(response),
227
+ network_transaction_id: network_transaction_id_from(response),
221
228
  avs_result: AVSResult.new(code: response['some_avs_response_key']),
222
229
  cvv_result: CVVResult.new(response['some_cvv_response_key']),
223
230
  test: test?,
@@ -242,6 +249,10 @@ module ActiveMerchant #:nodoc:
242
249
  response['id']
243
250
  end
244
251
 
252
+ def network_transaction_id_from(response)
253
+ response.dig('card', 'network_tx_reference')
254
+ end
255
+
245
256
  def error_code_from(action, response)
246
257
  return if success_from(action, response)
247
258
 
@@ -250,7 +261,7 @@ module ActiveMerchant #:nodoc:
250
261
  end
251
262
 
252
263
  def url(action, parameters, options = {})
253
- "#{(test? ? test_url : live_url)}/#{endpoint(action, parameters, options)}/"
264
+ "#{test? ? test_url : live_url}/#{endpoint(action, parameters, options)}/"
254
265
  end
255
266
 
256
267
  def endpoint(action, parameters, options)
@@ -235,23 +235,23 @@ module ActiveMerchant
235
235
  # a predefined one
236
236
  xml.tag! :ExtendedPolicy do
237
237
  xml.tag! :cv2_policy,
238
- notprovided: POLICY_REJECT,
239
- notchecked: POLICY_REJECT,
240
- matched: POLICY_ACCEPT,
241
- notmatched: POLICY_REJECT,
242
- partialmatch: POLICY_REJECT
238
+ notprovided: POLICY_REJECT,
239
+ notchecked: POLICY_REJECT,
240
+ matched: POLICY_ACCEPT,
241
+ notmatched: POLICY_REJECT,
242
+ partialmatch: POLICY_REJECT
243
243
  xml.tag! :postcode_policy,
244
- notprovided: POLICY_ACCEPT,
245
- notchecked: POLICY_ACCEPT,
246
- matched: POLICY_ACCEPT,
247
- notmatched: POLICY_REJECT,
248
- partialmatch: POLICY_ACCEPT
244
+ notprovided: POLICY_ACCEPT,
245
+ notchecked: POLICY_ACCEPT,
246
+ matched: POLICY_ACCEPT,
247
+ notmatched: POLICY_REJECT,
248
+ partialmatch: POLICY_ACCEPT
249
249
  xml.tag! :address_policy,
250
- notprovided: POLICY_ACCEPT,
251
- notchecked: POLICY_ACCEPT,
252
- matched: POLICY_ACCEPT,
253
- notmatched: POLICY_REJECT,
254
- partialmatch: POLICY_ACCEPT
250
+ notprovided: POLICY_ACCEPT,
251
+ notchecked: POLICY_ACCEPT,
252
+ matched: POLICY_ACCEPT,
253
+ notmatched: POLICY_REJECT,
254
+ partialmatch: POLICY_ACCEPT
255
255
  end
256
256
  end
257
257
  end
@@ -260,9 +260,13 @@ module ActiveMerchant
260
260
  def commit(request)
261
261
  response = parse(ssl_post(test? ? self.test_url : self.live_url, request))
262
262
 
263
- Response.new(response[:status] == '1', response[:reason], response,
263
+ Response.new(
264
+ response[:status] == '1',
265
+ response[:reason],
266
+ response,
264
267
  test: test?,
265
- authorization: "#{response[:datacash_reference]};#{response[:authcode]};#{response[:ca_reference]}")
268
+ authorization: "#{response[:datacash_reference]};#{response[:authcode]};#{response[:ca_reference]}"
269
+ )
266
270
  end
267
271
 
268
272
  def format_date(month, year)