activemerchant 1.130.0 → 1.137.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +268 -0
  3. data/lib/active_merchant/billing/check.rb +2 -2
  4. data/lib/active_merchant/billing/compatibility.rb +4 -4
  5. data/lib/active_merchant/billing/credit_card.rb +13 -8
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +4 -0
  7. data/lib/active_merchant/billing/credit_card_methods.rb +64 -7
  8. data/lib/active_merchant/billing/gateway.rb +9 -0
  9. data/lib/active_merchant/billing/gateways/adyen.rb +240 -41
  10. data/lib/active_merchant/billing/gateways/airwallex.rb +26 -12
  11. data/lib/active_merchant/billing/gateways/alelo.rb +23 -5
  12. data/lib/active_merchant/billing/gateways/authorize_net.rb +44 -36
  13. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +10 -6
  14. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +1 -3
  15. data/lib/active_merchant/billing/gateways/axcessms.rb +6 -2
  16. data/lib/active_merchant/billing/gateways/banwire.rb +4 -2
  17. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +7 -3
  18. data/lib/active_merchant/billing/gateways/blue_pay.rb +13 -5
  19. data/lib/active_merchant/billing/gateways/blue_snap.rb +5 -5
  20. data/lib/active_merchant/billing/gateways/borgun.rb +6 -4
  21. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +65 -20
  22. data/lib/active_merchant/billing/gateways/braintree_blue.rb +226 -73
  23. data/lib/active_merchant/billing/gateways/braintree_orange.rb +1 -1
  24. data/lib/active_merchant/billing/gateways/card_connect.rb +5 -2
  25. data/lib/active_merchant/billing/gateways/card_stream.rb +4 -6
  26. data/lib/active_merchant/billing/gateways/cashnet.rb +1 -1
  27. data/lib/active_merchant/billing/gateways/cecabank/cecabank_common.rb +36 -0
  28. data/lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb +316 -0
  29. data/lib/active_merchant/billing/gateways/cecabank/cecabank_xml.rb +220 -0
  30. data/lib/active_merchant/billing/gateways/cecabank.rb +7 -240
  31. data/lib/active_merchant/billing/gateways/checkout_v2.rb +252 -41
  32. data/lib/active_merchant/billing/gateways/commerce_hub.rb +69 -8
  33. data/lib/active_merchant/billing/gateways/credorax.rb +3 -5
  34. data/lib/active_merchant/billing/gateways/cyber_source.rb +192 -41
  35. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +102 -58
  36. data/lib/active_merchant/billing/gateways/d_local.rb +26 -15
  37. data/lib/active_merchant/billing/gateways/data_cash.rb +21 -17
  38. data/lib/active_merchant/billing/gateways/datatrans.rb +279 -0
  39. data/lib/active_merchant/billing/gateways/decidir.rb +53 -18
  40. data/lib/active_merchant/billing/gateways/decidir_plus.rb +4 -1
  41. data/lib/active_merchant/billing/gateways/deepstack.rb +382 -0
  42. data/lib/active_merchant/billing/gateways/ebanx.rb +40 -36
  43. data/lib/active_merchant/billing/gateways/efsnet.rb +6 -2
  44. data/lib/active_merchant/billing/gateways/elavon.rb +99 -33
  45. data/lib/active_merchant/billing/gateways/element.rb +36 -7
  46. data/lib/active_merchant/billing/gateways/epay.rb +6 -2
  47. data/lib/active_merchant/billing/gateways/evo_ca.rb +6 -2
  48. data/lib/active_merchant/billing/gateways/eway.rb +4 -2
  49. data/lib/active_merchant/billing/gateways/eway_managed.rb +6 -2
  50. data/lib/active_merchant/billing/gateways/exact.rb +6 -2
  51. data/lib/active_merchant/billing/gateways/fat_zebra.rb +31 -3
  52. data/lib/active_merchant/billing/gateways/federated_canada.rb +6 -2
  53. data/lib/active_merchant/billing/gateways/first_pay/first_pay_common.rb +15 -0
  54. data/lib/active_merchant/billing/gateways/first_pay/first_pay_json.rb +190 -0
  55. data/lib/active_merchant/billing/gateways/first_pay/first_pay_xml.rb +183 -0
  56. data/lib/active_merchant/billing/gateways/first_pay.rb +6 -172
  57. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +6 -2
  58. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +7 -3
  59. data/lib/active_merchant/billing/gateways/flex_charge.rb +347 -0
  60. data/lib/active_merchant/billing/gateways/garanti.rb +4 -2
  61. data/lib/active_merchant/billing/gateways/global_collect.rb +45 -37
  62. data/lib/active_merchant/billing/gateways/hi_pay.rb +286 -0
  63. data/lib/active_merchant/billing/gateways/hps.rb +1 -1
  64. data/lib/active_merchant/billing/gateways/iats_payments.rb +7 -2
  65. data/lib/active_merchant/billing/gateways/inspire.rb +6 -4
  66. data/lib/active_merchant/billing/gateways/instapay.rb +7 -4
  67. data/lib/active_merchant/billing/gateways/ipg.rb +10 -6
  68. data/lib/active_merchant/billing/gateways/iridium.rb +15 -5
  69. data/lib/active_merchant/billing/gateways/itransact.rb +6 -2
  70. data/lib/active_merchant/billing/gateways/iveri.rb +3 -3
  71. data/lib/active_merchant/billing/gateways/ixopay.rb +2 -2
  72. data/lib/active_merchant/billing/gateways/jetpay.rb +4 -2
  73. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +4 -2
  74. data/lib/active_merchant/billing/gateways/kushki.rb +73 -13
  75. data/lib/active_merchant/billing/gateways/linkpoint.rb +6 -2
  76. data/lib/active_merchant/billing/gateways/litle.rb +33 -50
  77. data/lib/active_merchant/billing/gateways/mastercard.rb +4 -4
  78. data/lib/active_merchant/billing/gateways/maxipago.rb +2 -2
  79. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +8 -5
  80. data/lib/active_merchant/billing/gateways/merchant_ware.rb +11 -4
  81. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +11 -4
  82. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +19 -3
  83. data/lib/active_merchant/billing/gateways/mercury.rb +6 -2
  84. data/lib/active_merchant/billing/gateways/metrics_global.rb +8 -6
  85. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +1 -0
  86. data/lib/active_merchant/billing/gateways/migs.rb +6 -2
  87. data/lib/active_merchant/billing/gateways/mit.rb +25 -20
  88. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +18 -10
  89. data/lib/active_merchant/billing/gateways/monei.rb +1 -1
  90. data/lib/active_merchant/billing/gateways/moneris.rb +9 -3
  91. data/lib/active_merchant/billing/gateways/money_movers.rb +6 -2
  92. data/lib/active_merchant/billing/gateways/nab_transact.rb +12 -4
  93. data/lib/active_merchant/billing/gateways/net_registry.rb +6 -2
  94. data/lib/active_merchant/billing/gateways/netbanx.rb +1 -3
  95. data/lib/active_merchant/billing/gateways/netbilling.rb +6 -2
  96. data/lib/active_merchant/billing/gateways/network_merchants.rb +6 -2
  97. data/lib/active_merchant/billing/gateways/nmi.rb +23 -6
  98. data/lib/active_merchant/billing/gateways/ogone.rb +6 -2
  99. data/lib/active_merchant/billing/gateways/openpay.rb +4 -2
  100. data/lib/active_merchant/billing/gateways/opp.rb +1 -2
  101. data/lib/active_merchant/billing/gateways/optimal_payment.rb +6 -2
  102. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +1 -3
  103. data/lib/active_merchant/billing/gateways/orbital.rb +83 -24
  104. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +7 -4
  105. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +6 -2
  106. data/lib/active_merchant/billing/gateways/pay_hub.rb +4 -2
  107. data/lib/active_merchant/billing/gateways/pay_junction.rb +6 -2
  108. data/lib/active_merchant/billing/gateways/pay_secure.rb +6 -2
  109. data/lib/active_merchant/billing/gateways/pay_trace.rb +31 -18
  110. data/lib/active_merchant/billing/gateways/payeezy.rb +19 -8
  111. data/lib/active_merchant/billing/gateways/payex.rb +4 -2
  112. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
  113. data/lib/active_merchant/billing/gateways/payflow.rb +1 -3
  114. data/lib/active_merchant/billing/gateways/payment_express.rb +8 -4
  115. data/lib/active_merchant/billing/gateways/paymentez.rb +23 -11
  116. data/lib/active_merchant/billing/gateways/paysafe.rb +12 -11
  117. data/lib/active_merchant/billing/gateways/payscout.rb +7 -4
  118. data/lib/active_merchant/billing/gateways/paystation.rb +7 -3
  119. data/lib/active_merchant/billing/gateways/payway.rb +6 -2
  120. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +3 -3
  121. data/lib/active_merchant/billing/gateways/pin.rb +22 -4
  122. data/lib/active_merchant/billing/gateways/plexo.rb +49 -10
  123. data/lib/active_merchant/billing/gateways/plugnpay.rb +6 -2
  124. data/lib/active_merchant/billing/gateways/priority.rb +6 -5
  125. data/lib/active_merchant/billing/gateways/psigate.rb +6 -2
  126. data/lib/active_merchant/billing/gateways/psl_card.rb +6 -2
  127. data/lib/active_merchant/billing/gateways/qbms.rb +6 -2
  128. data/lib/active_merchant/billing/gateways/quantum.rb +6 -2
  129. data/lib/active_merchant/billing/gateways/quickbooks.rb +6 -5
  130. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +7 -4
  131. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +6 -2
  132. data/lib/active_merchant/billing/gateways/rapyd.rb +148 -46
  133. data/lib/active_merchant/billing/gateways/reach.rb +11 -4
  134. data/lib/active_merchant/billing/gateways/redsys.rb +3 -11
  135. data/lib/active_merchant/billing/gateways/redsys_rest.rb +507 -0
  136. data/lib/active_merchant/billing/gateways/s5.rb +3 -3
  137. data/lib/active_merchant/billing/gateways/safe_charge.rb +38 -17
  138. data/lib/active_merchant/billing/gateways/sage.rb +12 -4
  139. data/lib/active_merchant/billing/gateways/sage_pay.rb +79 -5
  140. data/lib/active_merchant/billing/gateways/sallie_mae.rb +6 -2
  141. data/lib/active_merchant/billing/gateways/secure_net.rb +6 -2
  142. data/lib/active_merchant/billing/gateways/secure_pay.rb +8 -6
  143. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +12 -4
  144. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +6 -2
  145. data/lib/active_merchant/billing/gateways/securion_pay.rb +24 -10
  146. data/lib/active_merchant/billing/gateways/shift4.rb +17 -20
  147. data/lib/active_merchant/billing/gateways/shift4_v2.rb +117 -0
  148. data/lib/active_merchant/billing/gateways/simetrik.rb +17 -11
  149. data/lib/active_merchant/billing/gateways/skip_jack.rb +6 -2
  150. data/lib/active_merchant/billing/gateways/smart_ps.rb +7 -4
  151. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +4 -2
  152. data/lib/active_merchant/billing/gateways/spreedly_core.rb +2 -4
  153. data/lib/active_merchant/billing/gateways/stripe.rb +63 -19
  154. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +280 -88
  155. data/lib/active_merchant/billing/gateways/sum_up.rb +223 -0
  156. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +4 -2
  157. data/lib/active_merchant/billing/gateways/telr.rb +3 -4
  158. data/lib/active_merchant/billing/gateways/trans_first.rb +1 -2
  159. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +8 -16
  160. data/lib/active_merchant/billing/gateways/transact_pro.rb +1 -1
  161. data/lib/active_merchant/billing/gateways/trust_commerce.rb +6 -2
  162. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +9 -8
  163. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +6 -2
  164. data/lib/active_merchant/billing/gateways/vanco.rb +2 -4
  165. data/lib/active_merchant/billing/gateways/vantiv_express.rb +587 -0
  166. data/lib/active_merchant/billing/gateways/verifi.rb +6 -2
  167. data/lib/active_merchant/billing/gateways/viaklix.rb +6 -2
  168. data/lib/active_merchant/billing/gateways/visanet_peru.rb +2 -2
  169. data/lib/active_merchant/billing/gateways/vpos.rb +4 -4
  170. data/lib/active_merchant/billing/gateways/wirecard.rb +7 -3
  171. data/lib/active_merchant/billing/gateways/wompi.rb +5 -0
  172. data/lib/active_merchant/billing/gateways/worldpay.rb +147 -93
  173. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +13 -10
  174. data/lib/active_merchant/billing/gateways/xpay.rb +242 -0
  175. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
  176. data/lib/active_merchant/billing/response.rb +2 -2
  177. data/lib/active_merchant/connection.rb +3 -17
  178. data/lib/active_merchant/country.rb +1 -0
  179. data/lib/active_merchant/errors.rb +10 -0
  180. data/lib/active_merchant/version.rb +1 -1
  181. data/lib/support/gateway_support.rb +2 -2
  182. data/lib/support/ssl_verify.rb +4 -4
  183. data/lib/support/ssl_version.rb +6 -6
  184. metadata +30 -9
@@ -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')