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
@@ -0,0 +1,347 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class FlexChargeGateway < Gateway
4
+ self.test_url = 'https://api-sandbox.flex-charge.com/v1/'
5
+ self.live_url = 'https://api.flex-charge.com/v1/'
6
+
7
+ self.supported_countries = ['US']
8
+ self.default_currency = 'USD'
9
+ self.supported_cardtypes = %i[visa master american_express discover]
10
+ self.money_format = :cents
11
+ self.homepage_url = 'https://www.flex-charge.com/'
12
+ self.display_name = 'FlexCharge'
13
+
14
+ ENDPOINTS_MAPPING = {
15
+ authenticate: 'oauth2/token',
16
+ purchase: 'evaluate',
17
+ sync: 'outcome',
18
+ refund: 'orders/%s/refund',
19
+ store: 'tokenize',
20
+ inquire: 'orders/%s',
21
+ capture: 'capture',
22
+ void: 'orders/%s/cancel'
23
+ }
24
+
25
+ SUCCESS_MESSAGES = %w(APPROVED CHALLENGE SUBMITTED SUCCESS PROCESSING CAPTUREREQUIRED).freeze
26
+
27
+ def initialize(options = {})
28
+ requires!(options, :app_key, :app_secret, :site_id, :mid)
29
+ super
30
+ end
31
+
32
+ def purchase(money, credit_card, options = {})
33
+ post = { transactionType: options.fetch(:transactionType, 'Purchase') }
34
+
35
+ add_merchant_data(post, options)
36
+ add_base_data(post, options)
37
+ add_invoice(post, money, credit_card, options)
38
+ add_mit_data(post, options)
39
+ add_payment_method(post, credit_card, address(options), options)
40
+ add_address(post, credit_card, address(options), :billingInformation)
41
+ add_address(post, credit_card, options[:shipping_address], :shippingInformation)
42
+ add_customer_data(post, options)
43
+ add_three_ds(post, options)
44
+ add_metadata(post, options)
45
+
46
+ commit(:purchase, post)
47
+ end
48
+
49
+ def authorize(money, credit_card, options = {})
50
+ options[:transactionType] = 'Authorization'
51
+ purchase(money, credit_card, options)
52
+ end
53
+
54
+ def capture(money, authorization, options = {})
55
+ order_id, currency = authorization.split('#')
56
+ post = {
57
+ idempotencyKey: options[:idempotency_key] || SecureRandom.uuid,
58
+ orderId: order_id,
59
+ amount: money,
60
+ currency: currency
61
+ }
62
+
63
+ commit(:capture, post, authorization)
64
+ end
65
+
66
+ def refund(money, authorization, options = {})
67
+ order_id, _currency = authorization.split('#')
68
+ self.money_format = :dollars
69
+ commit(:refund, { amountToRefund: localized_amount(money, 2).to_f }, order_id)
70
+ end
71
+
72
+ def void(authorization, options = {})
73
+ order_id, _currency = authorization.split('#')
74
+ commit(:void, {}, order_id)
75
+ end
76
+
77
+ def store(credit_card, options = {})
78
+ first_name, last_name = names_from_address(address(options), credit_card)
79
+
80
+ post = {
81
+ payment_method: {
82
+ credit_card: {
83
+ first_name: first_name,
84
+ last_name: last_name,
85
+ month: credit_card.month,
86
+ year: credit_card.year,
87
+ number: credit_card.number,
88
+ verification_value: credit_card.verification_value
89
+ }.compact
90
+ }
91
+ }
92
+ commit(:store, post)
93
+ end
94
+
95
+ def supports_scrubbing?
96
+ true
97
+ end
98
+
99
+ def scrub(transcript)
100
+ transcript.
101
+ gsub(%r((Authorization: Bearer )[a-zA-Z0-9._-]+)i, '\1[FILTERED]').
102
+ gsub(%r(("AppKey\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
103
+ gsub(%r(("AppSecret\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
104
+ gsub(%r(("accessToken\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
105
+ gsub(%r(("mid\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
106
+ gsub(%r(("siteId\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
107
+ gsub(%r(("environment\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
108
+ gsub(%r(("number\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
109
+ gsub(%r(("cardNumber\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
110
+ gsub(%r(("verification_value\\?":\\?")\d+), '\1[FILTERED]')
111
+ end
112
+
113
+ def inquire(authorization, options = {})
114
+ order_id, _currency = authorization.split('#')
115
+ commit(:inquire, {}, order_id, :get)
116
+ end
117
+
118
+ def add_metadata(post, options)
119
+ post[:Source] = 'Spreedly'
120
+ post[:ExtraData] = options[:extra_data] if options[:extra_data].present?
121
+ end
122
+
123
+ private
124
+
125
+ def address(options)
126
+ options[:billing_address] || options[:address] || {}
127
+ end
128
+
129
+ def add_three_ds(post, options)
130
+ return unless three_d_secure = options[:three_d_secure]
131
+
132
+ post[:threeDSecure] = {
133
+ threeDsVersion: three_d_secure[:version],
134
+ EcommerceIndicator: three_d_secure[:eci],
135
+ authenticationValue: three_d_secure[:cavv],
136
+ directoryServerTransactionId: three_d_secure[:ds_transaction_id],
137
+ xid: three_d_secure[:xid],
138
+ authenticationValueAlgorithm: three_d_secure[:cavv_algorithm],
139
+ directoryResponseStatus: three_d_secure[:directory_response_status],
140
+ authenticationResponseStatus: three_d_secure[:authentication_response_status],
141
+ enrolled: three_d_secure[:enrolled]
142
+ }
143
+ end
144
+
145
+ def add_merchant_data(post, options)
146
+ post[:siteId] = @options[:site_id]
147
+ post[:mid] = @options[:mid]
148
+ end
149
+
150
+ def add_base_data(post, options)
151
+ post[:isDeclined] = cast_bool(options[:is_declined])
152
+ post[:orderId] = options[:order_id]
153
+ post[:idempotencyKey] = options[:idempotency_key] || SecureRandom.uuid
154
+ post[:senseKey] = options[:sense_key]
155
+ end
156
+
157
+ def add_mit_data(post, options)
158
+ return if options[:is_mit].nil?
159
+
160
+ post[:isMIT] = cast_bool(options[:is_mit])
161
+ post[:isRecurring] = cast_bool(options[:is_recurring])
162
+ post[:expiryDateUtc] = options[:mit_expiry_date_utc]
163
+ end
164
+
165
+ def add_customer_data(post, options)
166
+ post[:payer] = { email: options[:email] || 'NA', phone: phone_from(options) }.compact
167
+ end
168
+
169
+ def add_address(post, payment, address, address_type)
170
+ return unless address.present?
171
+
172
+ first_name, last_name = names_from_address(address, payment)
173
+
174
+ post[address_type] = {
175
+ firstName: first_name,
176
+ lastName: last_name,
177
+ country: address[:country],
178
+ phone: address[:phone],
179
+ countryCode: address[:country],
180
+ addressLine1: address[:address1],
181
+ state: address[:state],
182
+ city: address[:city],
183
+ zipCode: address[:zip]
184
+ }.compact
185
+ end
186
+
187
+ def add_invoice(post, money, credit_card, options)
188
+ post[:transaction] = {
189
+ id: options[:order_id],
190
+ dynamicDescriptor: options[:description],
191
+ timestamp: Time.now.utc.iso8601,
192
+ timezoneUtcOffset: options[:timezone_utc_offset],
193
+ amount: money,
194
+ currency: (options[:currency] || currency(money)),
195
+ responseCode: options[:response_code],
196
+ responseCodeSource: options[:response_code_source] || '',
197
+ avsResultCode: options[:avs_result_code],
198
+ cvvResultCode: options[:cvv_result_code],
199
+ cavvResultCode: options[:cavv_result_code],
200
+ cardNotPresent: credit_card.is_a?(String) ? false : credit_card.verification_value.blank?
201
+ }.compact
202
+ end
203
+
204
+ def add_payment_method(post, credit_card, address, options)
205
+ payment_method = case credit_card
206
+ when String
207
+ { Token: true, cardNumber: credit_card }
208
+ when CreditCard
209
+ if credit_card.number
210
+ {
211
+ holderName: credit_card.name,
212
+ cardType: 'CREDIT',
213
+ cardBrand: credit_card.brand&.upcase,
214
+ cardCountry: address[:country],
215
+ expirationMonth: credit_card.month,
216
+ expirationYear: credit_card.year,
217
+ cardBinNumber: credit_card.number[0..5],
218
+ cardLast4Digits: credit_card.number[-4..-1],
219
+ cardNumber: credit_card.number,
220
+ Token: false
221
+ }
222
+ else
223
+ {}
224
+ end
225
+ end
226
+ post[:paymentMethod] = payment_method.compact
227
+ end
228
+
229
+ def names_from_address(address, payment_method)
230
+ split_names(address[:name]).tap do |names|
231
+ names[0] = payment_method&.first_name unless names[0].present? || payment_method.is_a?(String)
232
+ names[1] = payment_method&.last_name unless names[1].present? || payment_method.is_a?(String)
233
+ end
234
+ end
235
+
236
+ def phone_from(options)
237
+ options[:phone] || options.dig(:billing_address, :phone_number)
238
+ end
239
+
240
+ def access_token_valid?
241
+ @options[:access_token].present? && @options.fetch(:token_expires, 0) > DateTime.now.strftime('%Q').to_i
242
+ end
243
+
244
+ def fetch_access_token
245
+ params = { AppKey: @options[:app_key], AppSecret: @options[:app_secret] }
246
+ response = parse(ssl_post(url(:authenticate), params.to_json, headers))
247
+
248
+ @options[:access_token] = response[:accessToken]
249
+ @options[:token_expires] = response[:expires]
250
+ @options[:new_credentials] = true
251
+
252
+ Response.new(
253
+ response[:accessToken].present?,
254
+ message_from(response),
255
+ response,
256
+ test: test?,
257
+ error_code: response[:statusCode]
258
+ )
259
+ rescue ResponseError => e
260
+ raise OAuthResponseError.new(e)
261
+ end
262
+
263
+ def url(action, id = nil)
264
+ "#{test? ? test_url : live_url}#{ENDPOINTS_MAPPING[action] % id}"
265
+ end
266
+
267
+ def headers
268
+ { 'Content-Type' => 'application/json' }.tap do |headers|
269
+ headers['Authorization'] = "Bearer #{@options[:access_token]}" if @options[:access_token]
270
+ end
271
+ end
272
+
273
+ def parse(body)
274
+ body = '{}' if body.blank?
275
+
276
+ JSON.parse(body).with_indifferent_access
277
+ rescue JSON::ParserError
278
+ {
279
+ errors: body,
280
+ status: 'Unable to parse JSON response'
281
+ }.with_indifferent_access
282
+ end
283
+
284
+ def commit(action, post, authorization = nil, method = :post)
285
+ MultiResponse.run do |r|
286
+ r.process { fetch_access_token } unless access_token_valid?
287
+ r.process do
288
+ api_request(action, post, authorization, method).tap do |response|
289
+ response.params.merge!(@options.slice(:access_token, :token_expires)) if @options[:new_credentials]
290
+ end
291
+ end
292
+ end
293
+ end
294
+
295
+ def api_request(action, post, authorization = nil, method = :post)
296
+ response = parse ssl_request(method, url(action, authorization), post.to_json, headers)
297
+
298
+ Response.new(
299
+ success_from(action, response),
300
+ message_from(response),
301
+ response,
302
+ authorization: authorization_from(action, response, post),
303
+ test: test?,
304
+ error_code: error_code_from(action, response)
305
+ )
306
+ rescue ResponseError => e
307
+ response = parse(e.response.body)
308
+ # if current access_token is invalid then clean it
309
+ if e.response.code == '401'
310
+ @options[:access_token] = ''
311
+ @options[:new_credentials] = true
312
+ end
313
+ Response.new(false, message_from(response), response, test: test?)
314
+ end
315
+
316
+ def success_from(action, response)
317
+ case action
318
+ when :store then response.dig(:transaction, :payment_method, :token).present?
319
+ when :inquire then response[:id].present? && SUCCESS_MESSAGES.include?(response[:statusName])
320
+ when :void then response.empty?
321
+ else
322
+ response[:success] && SUCCESS_MESSAGES.include?(response[:status])
323
+ end
324
+ end
325
+
326
+ def message_from(response)
327
+ response[:title] || response[:responseMessage] || response[:statusName] || response[:status]
328
+ end
329
+
330
+ def authorization_from(action, response, options)
331
+ if action == :store
332
+ response.dig(:transaction, :payment_method, :token)
333
+ elsif success_from(action, response)
334
+ [response[:orderId], options[:currency] || default_currency].compact.join('#')
335
+ end
336
+ end
337
+
338
+ def error_code_from(action, response)
339
+ (response[:statusName] || response[:status]) unless success_from(action, response)
340
+ end
341
+
342
+ def cast_bool(value)
343
+ ![false, 0, '', '0', 'f', 'F', 'false', 'FALSE'].include?(value)
344
+ end
345
+ end
346
+ end
347
+ end
@@ -219,11 +219,13 @@ module ActiveMerchant #:nodoc:
219
219
 
220
220
  success = success?(response)
221
221
 
222
- Response.new(success,
222
+ Response.new(
223
+ success,
223
224
  success ? 'Approved' : "Declined (Reason: #{response[:reason_code]} - #{response[:error_msg]} - #{response[:sys_err_msg]})",
224
225
  response,
225
226
  test: test?,
226
- authorization: response[:order_id])
227
+ authorization: response[:order_id]
228
+ )
227
229
  end
228
230
 
229
231
  def parse(body)
@@ -5,19 +5,19 @@ module ActiveMerchant #:nodoc:
5
5
  class_attribute :ogone_direct_test
6
6
  class_attribute :ogone_direct_live
7
7
 
8
- self.display_name = 'GlobalCollect'
8
+ self.display_name = 'Worldline (formerly GlobalCollect)'
9
9
  self.homepage_url = 'http://www.globalcollect.com/'
10
10
 
11
11
  self.test_url = 'https://eu.sandbox.api-ingenico.com'
12
- self.preproduction_url = 'https://world.preprod.api-ingenico.com'
13
- self.live_url = 'https://world.api-ingenico.com'
12
+ self.preproduction_url = 'https://api.preprod.connect.worldline-solutions.com'
13
+ self.live_url = 'https://api.connect.worldline-solutions.com'
14
14
  self.ogone_direct_test = 'https://payment.preprod.direct.worldline-solutions.com'
15
15
  self.ogone_direct_live = 'https://payment.direct.worldline-solutions.com'
16
16
 
17
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]
18
18
  self.default_currency = 'USD'
19
19
  self.money_format = :cents
20
- self.supported_cardtypes = %i[visa master american_express discover naranja cabal]
20
+ self.supported_cardtypes = %i[visa master american_express discover naranja cabal tuya]
21
21
 
22
22
  def initialize(options = {})
23
23
  requires!(options, :merchant_id, :api_key_id, :secret_api_key)
@@ -40,6 +40,7 @@ module ActiveMerchant #:nodoc:
40
40
  add_creator_info(post, options)
41
41
  add_fraud_fields(post, options)
42
42
  add_external_cardholder_authentication_data(post, options)
43
+ add_threeds_exemption_data(post, options)
43
44
  commit(:post, :authorize, post, options: options)
44
45
  end
45
46
 
@@ -101,8 +102,8 @@ module ActiveMerchant #:nodoc:
101
102
  'diners_club' => '132',
102
103
  'cabal' => '135',
103
104
  'naranja' => '136',
104
- 'apple_pay': '302',
105
- 'google_pay': '320'
105
+ apple_pay: '302',
106
+ google_pay: '320'
106
107
  }
107
108
 
108
109
  def add_order(post, money, options, capture: false)
@@ -138,6 +139,7 @@ module ActiveMerchant #:nodoc:
138
139
  airline_data['isThirdParty'] = options[:airline_data][:is_third_party] if options[:airline_data][:is_third_party]
139
140
  airline_data['issueDate'] = options[:airline_data][:issue_date] if options[:airline_data][:issue_date]
140
141
  airline_data['merchantCustomerId'] = options[:airline_data][:merchant_customer_id] if options[:airline_data][:merchant_customer_id]
142
+ airline_data['agentNumericCode'] = options[:airline_data][:agent_numeric_code] if options[:airline_data][:agent_numeric_code]
141
143
  airline_data['flightLegs'] = add_flight_legs(airline_options)
142
144
  airline_data['passengers'] = add_passengers(airline_options)
143
145
 
@@ -275,7 +277,7 @@ module ActiveMerchant #:nodoc:
275
277
  if payment.is_a?(NetworkTokenizationCreditCard)
276
278
  add_mobile_credit_card(post, payment, options, specifics_inputs, expirydate)
277
279
  elsif payment.is_a?(CreditCard)
278
- options[:google_pay_pan_only] ? add_mobile_credit_card(post, payment, options, specifics_inputs, expirydate) : add_credit_card(post, payment, specifics_inputs, expirydate)
280
+ add_credit_card(post, payment, specifics_inputs, expirydate)
279
281
  end
280
282
  end
281
283
 
@@ -291,31 +293,32 @@ module ActiveMerchant #:nodoc:
291
293
  end
292
294
 
293
295
  def add_mobile_credit_card(post, payment, options, specifics_inputs, expirydate)
294
- specifics_inputs['paymentProductId'] = options[:google_pay_pan_only] ? BRAND_MAP[:google_pay] : BRAND_MAP[payment.source]
296
+ specifics_inputs['paymentProductId'] = BRAND_MAP[payment.source]
295
297
  post['mobilePaymentMethodSpecificInput'] = specifics_inputs
296
- add_decrypted_payment_data(post, payment, options, expirydate)
298
+
299
+ if options[:use_encrypted_payment_data]
300
+ post['mobilePaymentMethodSpecificInput']['encryptedPaymentData'] = payment.payment_data
301
+ else
302
+ add_decrypted_payment_data(post, payment, options, expirydate)
303
+ end
297
304
  end
298
305
 
299
306
  def add_decrypted_payment_data(post, payment, options, expirydate)
300
- if payment.is_a?(NetworkTokenizationCreditCard) && payment.payment_cryptogram
301
- data = {
302
- 'cardholderName' => payment.name,
303
- 'cryptogram' => payment.payment_cryptogram,
304
- 'eci' => payment.eci,
305
- 'expiryDate' => expirydate,
306
- 'dpan' => payment.number
307
- }
308
- data['paymentMethod'] = 'TOKENIZED_CARD' if payment.source == :google_pay
309
- # else case when google payment is an ONLY_PAN, doesn't have cryptogram or eci.
310
- elsif options[:google_pay_pan_only]
311
- data = {
312
- 'cardholderName' => payment.name,
313
- 'expiryDate' => expirydate,
314
- 'pan' => payment.number,
315
- 'paymentMethod' => 'CARD'
316
- }
317
- end
318
- post['mobilePaymentMethodSpecificInput']['decryptedPaymentData'] = data if data
307
+ data_type = payment.source == :apple_pay ? 'decrypted' : 'encrypted'
308
+ data = case payment.source
309
+ when :apple_pay
310
+ {
311
+ 'cardholderName' => payment.name,
312
+ 'cryptogram' => payment.payment_cryptogram,
313
+ 'eci' => payment.eci,
314
+ 'expiryDate' => expirydate,
315
+ 'dpan' => payment.number
316
+ }
317
+ when :google_pay
318
+ payment.payment_data
319
+ end
320
+
321
+ post['mobilePaymentMethodSpecificInput']["#{data_type}PaymentData"] = data if data
319
322
  end
320
323
 
321
324
  def add_customer_data(post, options, payment = nil)
@@ -326,8 +329,8 @@ module ActiveMerchant #:nodoc:
326
329
  post['order']['customer']['merchantCustomerId'] = options[:customer] if options[:customer]
327
330
  post['order']['customer']['companyInformation']['name'] = options[:company] if options[:company]
328
331
  post['order']['customer']['contactDetails']['emailAddress'] = options[:email] if options[:email]
329
- if address = options[:billing_address] || options[:address]
330
- post['order']['customer']['contactDetails']['phoneNumber'] = address[:phone] if address[:phone]
332
+ if address = options[:billing_address] || options[:address] && (address[:phone])
333
+ post['order']['customer']['contactDetails']['phoneNumber'] = address[:phone]
331
334
  end
332
335
  end
333
336
 
@@ -337,8 +340,8 @@ module ActiveMerchant #:nodoc:
337
340
  'countryCode' => address[:country]
338
341
  }
339
342
  post['customer']['contactDetails']['emailAddress'] = options[:email] if options[:email]
340
- if address = options[:billing_address] || options[:address]
341
- post['customer']['contactDetails']['phoneNumber'] = address[:phone] if address[:phone]
343
+ if address = options[:billing_address] || options[:address] && (address[:phone])
344
+ post['customer']['contactDetails']['phoneNumber'] = address[:phone]
342
345
  end
343
346
  end
344
347
  end
@@ -347,7 +350,8 @@ module ActiveMerchant #:nodoc:
347
350
  shipping_address = options[:shipping_address]
348
351
  if billing_address = options[:billing_address] || options[:address]
349
352
  post['order']['customer']['billingAddress'] = {
350
- 'street' => truncate(billing_address[:address1], 50),
353
+ 'street' => truncate(split_address(billing_address[:address1])[1], 50),
354
+ 'houseNumber' => split_address(billing_address[:address1])[0],
351
355
  'additionalInfo' => truncate(billing_address[:address2], 50),
352
356
  'zip' => billing_address[:zip],
353
357
  'city' => billing_address[:city],
@@ -357,7 +361,8 @@ module ActiveMerchant #:nodoc:
357
361
  end
358
362
  if shipping_address
359
363
  post['order']['customer']['shippingAddress'] = {
360
- 'street' => truncate(shipping_address[:address1], 50),
364
+ 'street' => truncate(split_address(shipping_address[:address1])[1], 50),
365
+ 'houseNumber' => split_address(shipping_address[:address1])[0],
361
366
  'additionalInfo' => truncate(shipping_address[:address2], 50),
362
367
  'zip' => shipping_address[:zip],
363
368
  'city' => shipping_address[:city],
@@ -374,7 +379,6 @@ module ActiveMerchant #:nodoc:
374
379
  def add_fraud_fields(post, options)
375
380
  fraud_fields = {}
376
381
  fraud_fields.merge!(options[:fraud_fields]) if options[:fraud_fields]
377
- fraud_fields[:customerIpAddress] = options[:ip] if options[:ip]
378
382
 
379
383
  post['fraudFields'] = fraud_fields unless fraud_fields.empty?
380
384
  end
@@ -403,6 +407,12 @@ module ActiveMerchant #:nodoc:
403
407
  post['cardPaymentMethodSpecificInput']['threeDSecure']['externalCardholderAuthenticationData'] = authentication_data unless authentication_data.empty?
404
408
  end
405
409
 
410
+ def add_threeds_exemption_data(post, options)
411
+ return unless options[:three_ds_exemption_type]
412
+
413
+ post['cardPaymentMethodSpecificInput']['transactionChannel'] = 'MOTO' if options[:three_ds_exemption_type] == 'moto'
414
+ end
415
+
406
416
  def add_number_of_installments(post, options)
407
417
  post['order']['additionalInput']['numberOfInstallments'] = options[:number_of_installments] if options[:number_of_installments]
408
418
  end
@@ -512,8 +522,6 @@ module ActiveMerchant #:nodoc:
512
522
  def success_from(action, response)
513
523
  return false if response['errorId'] || response['error_message']
514
524
 
515
- return %w(CAPTURED CAPTURE_REQUESTED).include?(response.dig('payment', 'status')) if response.dig('payment', 'paymentOutput', 'paymentMethod') == 'mobile'
516
-
517
525
  case action
518
526
  when :authorize
519
527
  response.dig('payment', 'statusOutput', 'isAuthorized')