activemerchant 1.79.2 → 1.129.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (279) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG +1391 -0
  3. data/README.md +29 -14
  4. data/lib/active_merchant/billing/avs_result.rb +25 -28
  5. data/lib/active_merchant/billing/base.rb +0 -13
  6. data/lib/active_merchant/billing/check.rb +55 -22
  7. data/lib/active_merchant/billing/compatibility.rb +10 -12
  8. data/lib/active_merchant/billing/credit_card.rb +82 -62
  9. data/lib/active_merchant/billing/credit_card_formatting.rb +4 -4
  10. data/lib/active_merchant/billing/credit_card_methods.rb +328 -58
  11. data/lib/active_merchant/billing/cvv_result.rb +0 -1
  12. data/lib/active_merchant/billing/gateway.rb +61 -56
  13. data/lib/active_merchant/billing/gateways/adyen.rb +562 -87
  14. data/lib/active_merchant/billing/gateways/airwallex.rb +370 -0
  15. data/lib/active_merchant/billing/gateways/alelo.rb +256 -0
  16. data/lib/active_merchant/billing/gateways/allied_wallet.rb +35 -36
  17. data/lib/active_merchant/billing/gateways/authorize_net.rb +297 -196
  18. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +31 -24
  19. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +94 -98
  20. data/lib/active_merchant/billing/gateways/axcessms.rb +64 -66
  21. data/lib/active_merchant/billing/gateways/balanced.rb +72 -65
  22. data/lib/active_merchant/billing/gateways/bambora_apac.rb +222 -0
  23. data/lib/active_merchant/billing/gateways/bank_frick.rb +16 -16
  24. data/lib/active_merchant/billing/gateways/banwire.rb +12 -12
  25. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +140 -69
  26. data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +7 -7
  27. data/lib/active_merchant/billing/gateways/be2bill.rb +7 -7
  28. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +115 -115
  29. data/lib/active_merchant/billing/gateways/beanstream.rb +39 -13
  30. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +1 -2
  31. data/lib/active_merchant/billing/gateways/blue_pay.rb +87 -58
  32. data/lib/active_merchant/billing/gateways/blue_snap.rb +405 -104
  33. data/lib/active_merchant/billing/gateways/bogus.rb +34 -30
  34. data/lib/active_merchant/billing/gateways/borgun.rb +97 -47
  35. data/lib/active_merchant/billing/gateways/bpoint.rb +20 -20
  36. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -3
  37. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +113 -0
  38. data/lib/active_merchant/billing/gateways/braintree.rb +1 -1
  39. data/lib/active_merchant/billing/gateways/braintree_blue.rb +561 -259
  40. data/lib/active_merchant/billing/gateways/braintree_orange.rb +1 -1
  41. data/lib/active_merchant/billing/gateways/bridge_pay.rb +53 -54
  42. data/lib/active_merchant/billing/gateways/cams.rb +31 -31
  43. data/lib/active_merchant/billing/gateways/card_connect.rb +85 -33
  44. data/lib/active_merchant/billing/gateways/card_save.rb +7 -9
  45. data/lib/active_merchant/billing/gateways/card_stream.rb +187 -169
  46. data/lib/active_merchant/billing/gateways/cardknox.rb +24 -25
  47. data/lib/active_merchant/billing/gateways/cardprocess.rb +9 -7
  48. data/lib/active_merchant/billing/gateways/cashnet.rb +43 -27
  49. data/lib/active_merchant/billing/gateways/cc5.rb +14 -17
  50. data/lib/active_merchant/billing/gateways/cecabank.rb +62 -52
  51. data/lib/active_merchant/billing/gateways/cenpos.rb +63 -62
  52. data/lib/active_merchant/billing/gateways/checkout.rb +21 -23
  53. data/lib/active_merchant/billing/gateways/checkout_v2.rb +391 -113
  54. data/lib/active_merchant/billing/gateways/citrus_pay.rb +1 -3
  55. data/lib/active_merchant/billing/gateways/clearhaus.rb +40 -41
  56. data/lib/active_merchant/billing/gateways/commerce_hub.rb +361 -0
  57. data/lib/active_merchant/billing/gateways/commercegate.rb +11 -12
  58. data/lib/active_merchant/billing/gateways/conekta.rb +35 -30
  59. data/lib/active_merchant/billing/gateways/creditcall.rb +59 -59
  60. data/lib/active_merchant/billing/gateways/credorax.rb +326 -145
  61. data/lib/active_merchant/billing/gateways/ct_payment.rb +269 -0
  62. data/lib/active_merchant/billing/gateways/culqi.rb +53 -53
  63. data/lib/active_merchant/billing/gateways/cyber_source/cyber_source_common.rb +36 -0
  64. data/lib/active_merchant/billing/gateways/cyber_source.rb +566 -208
  65. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +456 -0
  66. data/lib/active_merchant/billing/gateways/d_local.rb +342 -0
  67. data/lib/active_merchant/billing/gateways/data_cash.rb +40 -56
  68. data/lib/active_merchant/billing/gateways/decidir.rb +358 -0
  69. data/lib/active_merchant/billing/gateways/decidir_plus.rb +344 -0
  70. data/lib/active_merchant/billing/gateways/dibs.rb +34 -40
  71. data/lib/active_merchant/billing/gateways/digitzs.rb +48 -45
  72. data/lib/active_merchant/billing/gateways/ebanx.rb +110 -60
  73. data/lib/active_merchant/billing/gateways/efsnet.rb +46 -50
  74. data/lib/active_merchant/billing/gateways/elavon.rb +351 -189
  75. data/lib/active_merchant/billing/gateways/element.rb +106 -56
  76. data/lib/active_merchant/billing/gateways/epay.rb +74 -64
  77. data/lib/active_merchant/billing/gateways/evo_ca.rb +13 -14
  78. data/lib/active_merchant/billing/gateways/eway.rb +74 -73
  79. data/lib/active_merchant/billing/gateways/eway_managed.rb +85 -87
  80. data/lib/active_merchant/billing/gateways/eway_rapid.rb +105 -60
  81. data/lib/active_merchant/billing/gateways/exact.rb +29 -37
  82. data/lib/active_merchant/billing/gateways/ezic.rb +21 -22
  83. data/lib/active_merchant/billing/gateways/fat_zebra.rb +70 -48
  84. data/lib/active_merchant/billing/gateways/federated_canada.rb +11 -13
  85. data/lib/active_merchant/billing/gateways/finansbank.rb +3 -4
  86. data/lib/active_merchant/billing/gateways/first_giving.rb +23 -23
  87. data/lib/active_merchant/billing/gateways/first_pay.rb +33 -13
  88. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +106 -105
  89. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +505 -0
  90. data/lib/active_merchant/billing/gateways/flo2cash.rb +36 -36
  91. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +2 -2
  92. data/lib/active_merchant/billing/gateways/forte.rb +70 -40
  93. data/lib/active_merchant/billing/gateways/garanti.rb +24 -31
  94. data/lib/active_merchant/billing/gateways/global_collect.rb +378 -154
  95. data/lib/active_merchant/billing/gateways/global_transport.rb +12 -13
  96. data/lib/active_merchant/billing/gateways/hdfc.rb +55 -57
  97. data/lib/active_merchant/billing/gateways/hps.rb +236 -69
  98. data/lib/active_merchant/billing/gateways/iats_payments.rb +61 -39
  99. data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +1 -1
  100. data/lib/active_merchant/billing/gateways/inspire.rb +41 -47
  101. data/lib/active_merchant/billing/gateways/instapay.rb +10 -14
  102. data/lib/active_merchant/billing/gateways/ipg.rb +420 -0
  103. data/lib/active_merchant/billing/gateways/ipp.rb +25 -24
  104. data/lib/active_merchant/billing/gateways/iridium.rb +243 -244
  105. data/lib/active_merchant/billing/gateways/itransact.rb +14 -14
  106. data/lib/active_merchant/billing/gateways/iveri.rb +73 -34
  107. data/lib/active_merchant/billing/gateways/ixopay.rb +320 -0
  108. data/lib/active_merchant/billing/gateways/jetpay.rb +145 -152
  109. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +154 -159
  110. data/lib/active_merchant/billing/gateways/komoju.rb +16 -16
  111. data/lib/active_merchant/billing/gateways/kushki.rb +127 -57
  112. data/lib/active_merchant/billing/gateways/latitude19.rb +111 -115
  113. data/lib/active_merchant/billing/gateways/linkpoint.rb +82 -85
  114. data/lib/active_merchant/billing/gateways/litle.rb +247 -53
  115. data/lib/active_merchant/billing/gateways/mastercard.rb +41 -23
  116. data/lib/active_merchant/billing/gateways/maxipago.rb +5 -5
  117. data/lib/active_merchant/billing/gateways/mercado_pago.rb +135 -49
  118. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +62 -29
  119. data/lib/active_merchant/billing/gateways/merchant_one.rb +16 -20
  120. data/lib/active_merchant/billing/gateways/merchant_partners.rb +40 -40
  121. data/lib/active_merchant/billing/gateways/merchant_ware.rb +54 -60
  122. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +42 -44
  123. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +52 -14
  124. data/lib/active_merchant/billing/gateways/mercury.rb +47 -51
  125. data/lib/active_merchant/billing/gateways/metrics_global.rb +32 -42
  126. data/lib/active_merchant/billing/gateways/micropayment.rb +42 -45
  127. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +7 -7
  128. data/lib/active_merchant/billing/gateways/migs.rb +45 -40
  129. data/lib/active_merchant/billing/gateways/mit.rb +260 -0
  130. data/lib/active_merchant/billing/gateways/modern_payments.rb +2 -2
  131. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +29 -31
  132. data/lib/active_merchant/billing/gateways/moka.rb +290 -0
  133. data/lib/active_merchant/billing/gateways/monei.rb +255 -138
  134. data/lib/active_merchant/billing/gateways/moneris.rb +226 -88
  135. data/lib/active_merchant/billing/gateways/money_movers.rb +11 -13
  136. data/lib/active_merchant/billing/gateways/mundipagg.rb +117 -43
  137. data/lib/active_merchant/billing/gateways/nab_transact.rb +28 -31
  138. data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +13 -15
  139. data/lib/active_merchant/billing/gateways/net_registry.rb +12 -12
  140. data/lib/active_merchant/billing/gateways/netaxept.rb +33 -34
  141. data/lib/active_merchant/billing/gateways/netbanx.rb +167 -80
  142. data/lib/active_merchant/billing/gateways/netbilling.rb +27 -30
  143. data/lib/active_merchant/billing/gateways/netpay.rb +10 -10
  144. data/lib/active_merchant/billing/gateways/network_merchants.rb +7 -11
  145. data/lib/active_merchant/billing/gateways/nmi.rb +134 -48
  146. data/lib/active_merchant/billing/gateways/ogone.rb +88 -58
  147. data/lib/active_merchant/billing/gateways/omise.rb +30 -31
  148. data/lib/active_merchant/billing/gateways/openpay.rb +45 -26
  149. data/lib/active_merchant/billing/gateways/opp.rb +166 -144
  150. data/lib/active_merchant/billing/gateways/optimal_payment.rb +67 -64
  151. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +5 -7
  152. data/lib/active_merchant/billing/gateways/orbital.rb +726 -382
  153. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +26 -27
  154. data/lib/active_merchant/billing/gateways/pagarme.rb +47 -56
  155. data/lib/active_merchant/billing/gateways/pago_facil.rb +12 -14
  156. data/lib/active_merchant/billing/gateways/pay_arc.rb +392 -0
  157. data/lib/active_merchant/billing/gateways/pay_conex.rb +39 -40
  158. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +65 -65
  159. data/lib/active_merchant/billing/gateways/pay_hub.rb +39 -39
  160. data/lib/active_merchant/billing/gateways/pay_junction.rb +37 -37
  161. data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +70 -54
  162. data/lib/active_merchant/billing/gateways/pay_secure.rb +15 -17
  163. data/lib/active_merchant/billing/gateways/pay_trace.rb +450 -0
  164. data/lib/active_merchant/billing/gateways/paybox_direct.rb +71 -47
  165. data/lib/active_merchant/billing/gateways/payeezy.rb +159 -32
  166. data/lib/active_merchant/billing/gateways/payex.rb +39 -42
  167. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +41 -36
  168. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +11 -8
  169. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +3 -3
  170. data/lib/active_merchant/billing/gateways/payflow.rb +178 -54
  171. data/lib/active_merchant/billing/gateways/payflow_express.rb +61 -65
  172. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +0 -1
  173. data/lib/active_merchant/billing/gateways/payflow_uk.rb +1 -2
  174. data/lib/active_merchant/billing/gateways/payment_express.rb +66 -58
  175. data/lib/active_merchant/billing/gateways/paymentez.rb +114 -25
  176. data/lib/active_merchant/billing/gateways/paymill.rb +134 -133
  177. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +2 -1
  178. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +4 -0
  179. data/lib/active_merchant/billing/gateways/paypal.rb +27 -14
  180. data/lib/active_merchant/billing/gateways/paypal_ca.rb +1 -1
  181. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +2 -2
  182. data/lib/active_merchant/billing/gateways/paypal_express.rb +5 -2
  183. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +1 -1
  184. data/lib/active_merchant/billing/gateways/paysafe.rb +420 -0
  185. data/lib/active_merchant/billing/gateways/payscout.rb +10 -13
  186. data/lib/active_merchant/billing/gateways/paystation.rb +79 -82
  187. data/lib/active_merchant/billing/gateways/payu_in.rb +59 -58
  188. data/lib/active_merchant/billing/gateways/payu_latam.rb +139 -97
  189. data/lib/active_merchant/billing/gateways/payway.rb +27 -27
  190. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +253 -0
  191. data/lib/active_merchant/billing/gateways/pin.rb +87 -34
  192. data/lib/active_merchant/billing/gateways/plexo.rb +308 -0
  193. data/lib/active_merchant/billing/gateways/plugnpay.rb +82 -82
  194. data/lib/active_merchant/billing/gateways/priority.rb +392 -0
  195. data/lib/active_merchant/billing/gateways/pro_pay.rb +139 -140
  196. data/lib/active_merchant/billing/gateways/psigate.rb +44 -44
  197. data/lib/active_merchant/billing/gateways/psl_card.rb +29 -37
  198. data/lib/active_merchant/billing/gateways/qbms.rb +75 -76
  199. data/lib/active_merchant/billing/gateways/quantum.rb +21 -23
  200. data/lib/active_merchant/billing/gateways/quickbooks.rb +142 -55
  201. data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +103 -107
  202. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +156 -158
  203. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +7 -8
  204. data/lib/active_merchant/billing/gateways/quickpay.rb +1 -3
  205. data/lib/active_merchant/billing/gateways/qvalent.rb +137 -68
  206. data/lib/active_merchant/billing/gateways/rapyd.rb +319 -0
  207. data/lib/active_merchant/billing/gateways/reach.rb +277 -0
  208. data/lib/active_merchant/billing/gateways/realex.rb +132 -50
  209. data/lib/active_merchant/billing/gateways/redsys.rb +382 -186
  210. data/lib/active_merchant/billing/gateways/s5.rb +16 -16
  211. data/lib/active_merchant/billing/gateways/safe_charge.rb +83 -47
  212. data/lib/active_merchant/billing/gateways/sage.rb +49 -48
  213. data/lib/active_merchant/billing/gateways/sage_pay.rb +76 -83
  214. data/lib/active_merchant/billing/gateways/sallie_mae.rb +13 -15
  215. data/lib/active_merchant/billing/gateways/secure_net.rb +32 -40
  216. data/lib/active_merchant/billing/gateways/secure_pay.rb +30 -40
  217. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +23 -26
  218. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +14 -16
  219. data/lib/active_merchant/billing/gateways/securion_pay.rb +69 -31
  220. data/lib/active_merchant/billing/gateways/shift4.rb +342 -0
  221. data/lib/active_merchant/billing/gateways/simetrik.rb +368 -0
  222. data/lib/active_merchant/billing/gateways/skip_jack.rb +52 -53
  223. data/lib/active_merchant/billing/gateways/smart_ps.rb +51 -60
  224. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +29 -29
  225. data/lib/active_merchant/billing/gateways/spreedly_core.rb +66 -47
  226. data/lib/active_merchant/billing/gateways/stripe.rb +309 -148
  227. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +556 -0
  228. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +18 -23
  229. data/lib/active_merchant/billing/gateways/telr.rb +46 -48
  230. data/lib/active_merchant/billing/gateways/tns.rb +8 -7
  231. data/lib/active_merchant/billing/gateways/trans_first.rb +37 -37
  232. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +249 -245
  233. data/lib/active_merchant/billing/gateways/transact_pro.rb +25 -27
  234. data/lib/active_merchant/billing/gateways/transax.rb +6 -8
  235. data/lib/active_merchant/billing/gateways/transnational.rb +1 -2
  236. data/lib/active_merchant/billing/gateways/trexle.rb +22 -18
  237. data/lib/active_merchant/billing/gateways/trust_commerce.rb +161 -88
  238. data/lib/active_merchant/billing/gateways/usa_epay.rb +5 -6
  239. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +231 -238
  240. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +129 -55
  241. data/lib/active_merchant/billing/gateways/vanco.rb +42 -33
  242. data/lib/active_merchant/billing/gateways/verifi.rb +52 -53
  243. data/lib/active_merchant/billing/gateways/viaklix.rb +18 -22
  244. data/lib/active_merchant/billing/gateways/visanet_peru.rb +115 -74
  245. data/lib/active_merchant/billing/gateways/vpos.rb +223 -0
  246. data/lib/active_merchant/billing/gateways/webpay.rb +9 -9
  247. data/lib/active_merchant/billing/gateways/wepay.rb +38 -41
  248. data/lib/active_merchant/billing/gateways/wirecard.rb +36 -37
  249. data/lib/active_merchant/billing/gateways/wompi.rb +197 -0
  250. data/lib/active_merchant/billing/gateways/world_net.rb +39 -38
  251. data/lib/active_merchant/billing/gateways/worldpay.rb +756 -142
  252. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +73 -83
  253. data/lib/active_merchant/billing/gateways/worldpay_us.rb +31 -31
  254. data/lib/active_merchant/billing/model.rb +2 -2
  255. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +3 -3
  256. data/lib/active_merchant/billing/rails.rb +1 -1
  257. data/lib/active_merchant/billing/response.rb +32 -13
  258. data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
  259. data/lib/active_merchant/billing.rb +1 -0
  260. data/lib/active_merchant/connection.rb +24 -38
  261. data/lib/active_merchant/country.rb +9 -5
  262. data/lib/active_merchant/errors.rb +4 -1
  263. data/lib/active_merchant/net_http_ssl_connection.rb +2 -0
  264. data/lib/active_merchant/network_connection_retries.rb +28 -31
  265. data/lib/active_merchant/post_data.rb +5 -3
  266. data/lib/active_merchant/posts_data.rb +5 -7
  267. data/lib/active_merchant/version.rb +1 -1
  268. data/lib/active_merchant.rb +3 -3
  269. data/lib/activemerchant.rb +1 -1
  270. data/lib/certs/cacert.pem +1592 -2329
  271. data/lib/support/gateway_support.rb +8 -10
  272. data/lib/support/ssl_verify.rb +9 -14
  273. data/lib/support/ssl_version.rb +9 -10
  274. metadata +98 -37
  275. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +0 -246
  276. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +0 -13
  277. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +0 -29
  278. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +0 -66
  279. data/lib/active_merchant/billing/gateways/moneris_us.rb +0 -309
@@ -1,30 +1,33 @@
1
1
  module ActiveMerchant #:nodoc:
2
2
  module Billing #:nodoc:
3
3
  class GlobalCollectGateway < Gateway
4
- self.display_name = "GlobalCollect"
5
- self.homepage_url = "http://www.globalcollect.com/"
4
+ class_attribute :preproduction_url
6
5
 
7
- self.test_url = "https://api-sandbox.globalcollect.com/"
8
- self.live_url = "https://api.globalcollect.com/"
6
+ self.display_name = 'GlobalCollect'
7
+ self.homepage_url = 'http://www.globalcollect.com/'
9
8
 
10
- self.supported_countries = ["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"]
11
- self.default_currency = "USD"
9
+ self.test_url = 'https://eu.sandbox.api-ingenico.com'
10
+ self.preproduction_url = 'https://world.preprod.api-ingenico.com'
11
+ self.live_url = 'https://world.api-ingenico.com'
12
+
13
+ self.supported_countries = %w[AD AE AG AI AL AM AO AR AS AT AU AW AX AZ BA BB BD BE BF BG BH BI BJ BL BM BN BO BQ BR BS BT BW BY BZ CA CC CD CF CH CI CK CL CM CN CO CR CU CV CW CX CY CZ DE DJ DK DM DO DZ EC EE EG ER ES ET FI FJ FK FM FO FR GA GB GD GE GF GH GI GL GM GN GP GQ GR GS GT GU GW GY HK HN HR HT HU ID IE IL IM IN IS IT JM JO JP KE KG KH KI KM KN KR KW KY KZ LA LB LC LI LK LR LS LT LU LV MA MC MD ME MF MG MH MK MM MN MO MP MQ MR MS MT MU MV MW MX MY MZ NA NC NE NG NI NL NO NP NR NU NZ OM PA PE PF PG PH PL PN PS PT PW QA RE RO RS RU RW SA SB SC SE SG SH SI SJ SK SL SM SN SR ST SV SZ TC TD TG TH TJ TL TM TN TO TR TT TV TW TZ UA UG US UY UZ VC VE VG VI VN WF WS ZA ZM ZW]
14
+ self.default_currency = 'USD'
12
15
  self.money_format = :cents
13
- self.supported_cardtypes = [:visa, :master, :american_express, :discover]
16
+ self.supported_cardtypes = %i[visa master american_express discover naranja cabal]
14
17
 
15
- def initialize(options={})
18
+ def initialize(options = {})
16
19
  requires!(options, :merchant_id, :api_key_id, :secret_api_key)
17
20
  super
18
21
  end
19
22
 
20
- def purchase(money, payment, options={})
23
+ def purchase(money, payment, options = {})
21
24
  MultiResponse.run do |r|
22
25
  r.process { authorize(money, payment, options) }
23
- r.process { capture(money, r.authorization, options) } unless capture_requested?(r)
26
+ r.process { capture(money, r.authorization, options) } if should_request_capture?(r, options[:requires_approval])
24
27
  end
25
28
  end
26
29
 
27
- def authorize(money, payment, options={})
30
+ def authorize(money, payment, options = {})
28
31
  post = nestable_hash
29
32
  add_order(post, money, options)
30
33
  add_payment(post, payment, options)
@@ -32,39 +35,43 @@ module ActiveMerchant #:nodoc:
32
35
  add_address(post, payment, options)
33
36
  add_creator_info(post, options)
34
37
  add_fraud_fields(post, options)
35
-
36
- commit(:authorize, post)
38
+ add_external_cardholder_authentication_data(post, options)
39
+ commit(:post, :authorize, post, options: options)
37
40
  end
38
41
 
39
- def capture(money, authorization, options={})
42
+ def capture(money, authorization, options = {})
40
43
  post = nestable_hash
41
- add_order(post, money, options)
44
+ add_order(post, money, options, capture: true)
42
45
  add_customer_data(post, options)
43
46
  add_creator_info(post, options)
44
- commit(:capture, post, authorization)
47
+ commit(:post, :capture, post, authorization: authorization)
45
48
  end
46
49
 
47
- def refund(money, authorization, options={})
50
+ def refund(money, authorization, options = {})
48
51
  post = nestable_hash
49
52
  add_amount(post, money, options)
50
53
  add_refund_customer_data(post, options)
51
54
  add_creator_info(post, options)
52
- commit(:refund, post, authorization)
55
+ commit(:post, :refund, post, authorization: authorization)
53
56
  end
54
57
 
55
- def void(authorization, options={})
58
+ def void(authorization, options = {})
56
59
  post = nestable_hash
57
60
  add_creator_info(post, options)
58
- commit(:void, post, authorization)
61
+ commit(:post, :void, post, authorization: authorization)
59
62
  end
60
63
 
61
- def verify(payment, options={})
64
+ def verify(payment, options = {})
62
65
  MultiResponse.run(:use_first_response) do |r|
63
66
  r.process { authorize(100, payment, options) }
64
67
  r.process { void(r.authorization, options) }
65
68
  end
66
69
  end
67
70
 
71
+ def inquire(authorization, options = {})
72
+ commit(:get, :inquire, nil, authorization: authorization)
73
+ end
74
+
68
75
  def supports_scrubbing?
69
76
  true
70
77
  end
@@ -72,33 +79,161 @@ module ActiveMerchant #:nodoc:
72
79
  def scrub(transcript)
73
80
  transcript.
74
81
  gsub(%r((Authorization: )[^\\]*)i, '\1[FILTERED]').
75
- gsub(%r(("cardNumber\\":\\")\d+), '\1[FILTERED]').
76
- gsub(%r(("cvv\\":\\")\d+), '\1[FILTERED]')
82
+ gsub(%r(("cardNumber\\+":\\+")\d+), '\1[FILTERED]').
83
+ gsub(%r(("cvv\\+":\\+")\d+), '\1[FILTERED]').
84
+ gsub(%r(("dpan\\+":\\+")\d+), '\1[FILTERED]').
85
+ gsub(%r(("pan\\+":\\+")\d+), '\1[FILTERED]').
86
+ gsub(%r(("cryptogram\\+":\\+"|("cavv\\+" : \\+"))[^\\]*), '\1[FILTERED]')
77
87
  end
78
88
 
79
89
  private
80
90
 
81
91
  BRAND_MAP = {
82
- "visa" => "1",
83
- "american_express" => "2",
84
- "master" => "3",
85
- "discover" => "128",
86
- "jcb" => "125",
87
- "diners_club" => "132"
92
+ 'visa' => '1',
93
+ 'american_express' => '2',
94
+ 'master' => '3',
95
+ 'discover' => '128',
96
+ 'jcb' => '125',
97
+ 'diners_club' => '132',
98
+ 'cabal' => '135',
99
+ 'naranja' => '136',
100
+ 'apple_pay': '302',
101
+ 'google_pay': '320'
88
102
  }
89
103
 
90
- def add_order(post, money, options)
91
- post["order"]["amountOfMoney"] = {
92
- "amount" => amount(money),
93
- "currencyCode" => options[:currency] || currency(money)
94
- }
95
- post["order"]["references"] = {
96
- "merchantReference" => options[:order_id],
97
- "descriptor" => options[:description] # Max 256 chars
104
+ def add_order(post, money, options, capture: false)
105
+ if capture
106
+ post['amount'] = amount(money)
107
+ else
108
+ add_amount(post['order'], money, options)
109
+ end
110
+ post['order']['references'] = {
111
+ 'merchantReference' => options[:order_id],
112
+ 'descriptor' => options[:description] # Max 256 chars
98
113
  }
99
- post["order"]["references"]["invoiceData"] = {
100
- "invoiceNumber" => options[:invoice]
114
+ post['order']['references']['invoiceData'] = {
115
+ 'invoiceNumber' => options[:invoice]
101
116
  }
117
+ add_airline_data(post, options)
118
+ add_lodging_data(post, options)
119
+ add_number_of_installments(post, options) if options[:number_of_installments]
120
+ end
121
+
122
+ def add_airline_data(post, options)
123
+ return unless airline_options = options[:airline_data]
124
+
125
+ airline_data = {}
126
+
127
+ airline_data['flightDate'] = airline_options[:flight_date] if airline_options[:flight_date]
128
+ airline_data['passengerName'] = airline_options[:passenger_name] if airline_options[:passenger_name]
129
+ airline_data['code'] = airline_options[:code] if airline_options[:code]
130
+ airline_data['name'] = airline_options[:name] if airline_options[:name]
131
+ airline_data['invoiceNumber'] = options[:airline_data][:invoice_number] if options[:airline_data][:invoice_number]
132
+ airline_data['isETicket'] = options[:airline_data][:is_eticket] if options[:airline_data][:is_eticket]
133
+ airline_data['isRestrictedTicket'] = options[:airline_data][:is_restricted_ticket] if options[:airline_data][:is_restricted_ticket]
134
+ airline_data['isThirdParty'] = options[:airline_data][:is_third_party] if options[:airline_data][:is_third_party]
135
+ airline_data['issueDate'] = options[:airline_data][:issue_date] if options[:airline_data][:issue_date]
136
+ airline_data['merchantCustomerId'] = options[:airline_data][:merchant_customer_id] if options[:airline_data][:merchant_customer_id]
137
+ airline_data['flightLegs'] = add_flight_legs(airline_options)
138
+ airline_data['passengers'] = add_passengers(airline_options)
139
+
140
+ post['order']['additionalInput']['airlineData'] = airline_data
141
+ end
142
+
143
+ def add_flight_legs(airline_options)
144
+ flight_legs = []
145
+ airline_options[:flight_legs]&.each do |fl|
146
+ leg = {}
147
+ leg['airlineClass'] = fl[:airline_class] if fl[:airline_class]
148
+ leg['arrivalAirport'] = fl[:arrival_airport] if fl[:arrival_airport]
149
+ leg['arrivalTime'] = fl[:arrival_time] if fl[:arrival_time]
150
+ leg['carrierCode'] = fl[:carrier_code] if fl[:carrier_code]
151
+ leg['conjunctionTicket'] = fl[:conjunction_ticket] if fl[:conjunction_ticket]
152
+ leg['couponNumber'] = fl[:coupon_number] if fl[:coupon_number]
153
+ leg['date'] = fl[:date] if fl[:date]
154
+ leg['departureTime'] = fl[:departure_time] if fl[:departure_time]
155
+ leg['endorsementOrRestriction'] = fl[:endorsement_or_restriction] if fl[:endorsement_or_restriction]
156
+ leg['exchangeTicket'] = fl[:exchange_ticket] if fl[:exchange_ticket]
157
+ leg['fare'] = fl[:fare] if fl[:fare]
158
+ leg['fareBasis'] = fl[:fare_basis] if fl[:fare_basis]
159
+ leg['fee'] = fl[:fee] if fl[:fee]
160
+ leg['flightNumber'] = fl[:flight_number] if fl[:flight_number]
161
+ leg['number'] = fl[:number] if fl[:number]
162
+ leg['originAirport'] = fl[:origin_airport] if fl[:origin_airport]
163
+ leg['passengerClass'] = fl[:passenger_class] if fl[:passenger_class]
164
+ leg['stopoverCode'] = fl[:stopover_code] if fl[:stopover_code]
165
+ leg['taxes'] = fl[:taxes] if fl[:taxes]
166
+ flight_legs << leg
167
+ end
168
+ flight_legs
169
+ end
170
+
171
+ def add_passengers(airline_options)
172
+ passengers = []
173
+ airline_options[:passengers]&.each do |flyer|
174
+ passenger = {}
175
+ passenger['firstName'] = flyer[:first_name] if flyer[:first_name]
176
+ passenger['surname'] = flyer[:surname] if flyer[:surname]
177
+ passenger['surnamePrefix'] = flyer[:surname_prefix] if flyer[:surname_prefix]
178
+ passenger['title'] = flyer[:title] if flyer[:title]
179
+ passengers << passenger
180
+ end
181
+ passengers
182
+ end
183
+
184
+ def add_lodging_data(post, options)
185
+ return unless lodging_options = options[:lodging_data]
186
+
187
+ lodging_data = {}
188
+
189
+ lodging_data['charges'] = add_charges(lodging_options)
190
+ lodging_data['checkInDate'] = lodging_options[:check_in_date] if lodging_options[:check_in_date]
191
+ lodging_data['checkOutDate'] = lodging_options[:check_out_date] if lodging_options[:check_out_date]
192
+ lodging_data['folioNumber'] = lodging_options[:folio_number] if lodging_options[:folio_number]
193
+ lodging_data['isConfirmedReservation'] = lodging_options[:is_confirmed_reservation] if lodging_options[:is_confirmed_reservation]
194
+ lodging_data['isFacilityFireSafetyConform'] = lodging_options[:is_facility_fire_safety_conform] if lodging_options[:is_facility_fire_safety_conform]
195
+ lodging_data['isNoShow'] = lodging_options[:is_no_show] if lodging_options[:is_no_show]
196
+ lodging_data['isPreferenceSmokingRoom'] = lodging_options[:is_preference_smoking_room] if lodging_options[:is_preference_smoking_room]
197
+ lodging_data['numberOfAdults'] = lodging_options[:number_of_adults] if lodging_options[:number_of_adults]
198
+ lodging_data['numberOfNights'] = lodging_options[:number_of_nights] if lodging_options[:number_of_nights]
199
+ lodging_data['numberOfRooms'] = lodging_options[:number_of_rooms] if lodging_options[:number_of_rooms]
200
+ lodging_data['programCode'] = lodging_options[:program_code] if lodging_options[:program_code]
201
+ lodging_data['propertyCustomerServicePhoneNumber'] = lodging_options[:property_customer_service_phone_number] if lodging_options[:property_customer_service_phone_number]
202
+ lodging_data['propertyPhoneNumber'] = lodging_options[:property_phone_number] if lodging_options[:property_phone_number]
203
+ lodging_data['renterName'] = lodging_options[:renter_name] if lodging_options[:renter_name]
204
+ lodging_data['rooms'] = add_rooms(lodging_options)
205
+
206
+ post['order']['additionalInput']['lodgingData'] = lodging_data
207
+ end
208
+
209
+ def add_charges(lodging_options)
210
+ charges = []
211
+ lodging_options[:charges]&.each do |item|
212
+ charge = {}
213
+ charge['chargeAmount'] = item[:charge_amount] if item[:charge_amount]
214
+ charge['chargeAmountCurrencyCode'] = item[:charge_amount_currency_code] if item[:charge_amount_currency_code]
215
+ charge['chargeType'] = item[:charge_type] if item[:charge_type]
216
+ charges << charge
217
+ end
218
+ charges
219
+ end
220
+
221
+ def add_rooms(lodging_options)
222
+ rooms = []
223
+ lodging_options[:rooms]&.each do |item|
224
+ room = {}
225
+ room['dailyRoomRate'] = item[:daily_room_rate] if item[:daily_room_rate]
226
+ room['dailyRoomRateCurrencyCode'] = item[:daily_room_rate_currency_code] if item[:daily_room_rate_currency_code]
227
+ room['dailyRoomTaxAmount'] = item[:daily_room_tax_amount] if item[:daily_room_tax_amount]
228
+ room['dailyRoomTaxAmountCurrencyCode'] = item[:daily_room_tax_amount_currency_code] if item[:daily_room_tax_amount_currency_code]
229
+ room['numberOfNightsAtRoomRate'] = item[:number_of_nights_at_room_rate] if item[:number_of_nights_at_room_rate]
230
+ room['roomLocation'] = item[:room_location] if item[:room_location]
231
+ room['roomNumber'] = item[:room_number] if item[:room_number]
232
+ room['typeOfBed'] = item[:type_of_bed] if item[:type_of_bed]
233
+ room['typeOfRoom'] = item[:type_of_room] if item[:type_of_room]
234
+ rooms << room
235
+ end
236
+ rooms
102
237
  end
103
238
 
104
239
  def add_creator_info(post, options)
@@ -112,95 +247,121 @@ module ActiveMerchant #:nodoc:
112
247
  post['shoppingCartExtension']['extensionID'] = options[:extension_ID] if options[:extension_ID]
113
248
  end
114
249
 
115
- def add_amount(post, money, options={})
116
- post["amountOfMoney"] = {
117
- "amount" => amount(money),
118
- "currencyCode" => options[:currency] || currency(money)
250
+ def add_amount(post, money, options = {})
251
+ post['amountOfMoney'] = {
252
+ 'amount' => amount(money),
253
+ 'currencyCode' => options[:currency] || currency(money)
119
254
  }
120
255
  end
121
256
 
122
257
  def add_payment(post, payment, options)
123
258
  year = format(payment.year, :two_digits)
124
259
  month = format(payment.month, :two_digits)
125
- expirydate = "#{month}#{year}"
260
+ expirydate = "#{month}#{year}"
126
261
  pre_authorization = options[:pre_authorization] ? 'PRE_AUTHORIZATION' : 'FINAL_AUTHORIZATION'
127
-
128
- post["cardPaymentMethodSpecificInput"] = {
129
- "paymentProductId" => BRAND_MAP[payment.brand],
130
- "skipAuthentication" => "true", # refers to 3DSecure
131
- "skipFraudService" => "true",
132
- "authorizationMode" => pre_authorization
133
- }
134
- post["cardPaymentMethodSpecificInput"]["card"] = {
135
- "cvv" => payment.verification_value,
136
- "cardNumber" => payment.number,
137
- "expiryDate" => expirydate,
138
- "cardholderName" => payment.name
262
+ product_id = options[:payment_product_id] || BRAND_MAP[payment.brand]
263
+ specifics_inputs = {
264
+ 'paymentProductId' => product_id,
265
+ 'skipAuthentication' => 'true', # refers to 3DSecure
266
+ 'skipFraudService' => 'true',
267
+ 'authorizationMode' => pre_authorization
139
268
  }
269
+ specifics_inputs['requiresApproval'] = options[:requires_approval] unless options[:requires_approval].nil?
270
+ if payment.is_a?(NetworkTokenizationCreditCard)
271
+ add_mobile_credit_card(post, payment, options, specifics_inputs, expirydate)
272
+ elsif payment.is_a?(CreditCard)
273
+ options[:google_pay_pan_only] ? add_mobile_credit_card(post, payment, options, specifics_inputs, expirydate) : add_credit_card(post, payment, specifics_inputs, expirydate)
274
+ end
275
+ end
276
+
277
+ def add_credit_card(post, payment, specifics_inputs, expirydate)
278
+ post['cardPaymentMethodSpecificInput'] = specifics_inputs.merge({
279
+ 'card' => {
280
+ 'cvv' => payment.verification_value,
281
+ 'cardNumber' => payment.number,
282
+ 'expiryDate' => expirydate,
283
+ 'cardholderName' => payment.name
284
+ }
285
+ })
286
+ end
287
+
288
+ def add_mobile_credit_card(post, payment, options, specifics_inputs, expirydate)
289
+ specifics_inputs['paymentProductId'] = options[:google_pay_pan_only] ? BRAND_MAP[:google_pay] : BRAND_MAP[payment.source]
290
+ post['mobilePaymentMethodSpecificInput'] = specifics_inputs
291
+ add_decrypted_payment_data(post, payment, options, expirydate)
292
+ end
293
+
294
+ def add_decrypted_payment_data(post, payment, options, expirydate)
295
+ if payment.is_a?(NetworkTokenizationCreditCard) && payment.payment_cryptogram
296
+ data = {
297
+ 'cardholderName' => payment.name,
298
+ 'cryptogram' => payment.payment_cryptogram,
299
+ 'eci' => payment.eci,
300
+ 'expiryDate' => expirydate,
301
+ 'dpan' => payment.number
302
+ }
303
+ data['paymentMethod'] = 'TOKENIZED_CARD' if payment.source == :google_pay
304
+ # else case when google payment is an ONLY_PAN, doesn't have cryptogram or eci.
305
+ elsif options[:google_pay_pan_only]
306
+ data = {
307
+ 'cardholderName' => payment.name,
308
+ 'expiryDate' => expirydate,
309
+ 'pan' => payment.number,
310
+ 'paymentMethod' => 'CARD'
311
+ }
312
+ end
313
+ post['mobilePaymentMethodSpecificInput']['decryptedPaymentData'] = data if data
140
314
  end
141
315
 
142
316
  def add_customer_data(post, options, payment = nil)
143
- post["order"]["customer"] = {
144
- "merchantCustomerId" => options[:customer]
145
- }
146
317
  if payment
147
- post["order"]["customer"]["personalInformation"] = {
148
- "name" => {
149
- "firstName" => payment.first_name[0..14],
150
- "surname" => payment.last_name[0..69]
151
- }
152
- }
318
+ post['order']['customer']['personalInformation']['name']['firstName'] = payment.first_name[0..14] if payment.first_name
319
+ post['order']['customer']['personalInformation']['name']['surname'] = payment.last_name[0..69] if payment.last_name
153
320
  end
154
- post["order"]["companyInformation"] = {
155
- "name" => options[:company]
156
- }
157
- post["order"]["contactDetails"] = {
158
- "emailAddress" => options[:email]
159
- }
321
+ post['order']['customer']['merchantCustomerId'] = options[:customer] if options[:customer]
322
+ post['order']['customer']['companyInformation']['name'] = options[:company] if options[:company]
323
+ post['order']['customer']['contactDetails']['emailAddress'] = options[:email] if options[:email]
160
324
  if address = options[:billing_address] || options[:address]
161
- post["order"]["contactDetails"] = {
162
- "phoneNumber" => address[:phone]
163
- }
325
+ post['order']['customer']['contactDetails']['phoneNumber'] = address[:phone] if address[:phone]
164
326
  end
165
327
  end
166
328
 
167
329
  def add_refund_customer_data(post, options)
168
330
  if address = options[:billing_address] || options[:address]
169
- post["customer"]["address"] = {
170
- "countryCode" => address[:country]
171
- }
172
- post["customer"]["contactDetails"] = {
173
- "emailAddress" => options[:email],
174
- "phoneNumber" => address[:phone]
331
+ post['customer']['address'] = {
332
+ 'countryCode' => address[:country]
175
333
  }
334
+ post['customer']['contactDetails']['emailAddress'] = options[:email] if options[:email]
335
+ if address = options[:billing_address] || options[:address]
336
+ post['customer']['contactDetails']['phoneNumber'] = address[:phone] if address[:phone]
337
+ end
176
338
  end
177
339
  end
178
340
 
179
341
  def add_address(post, creditcard, options)
180
- billing_address = options[:billing_address] || options[:address]
181
342
  shipping_address = options[:shipping_address]
182
343
  if billing_address = options[:billing_address] || options[:address]
183
- post["order"]["customer"]["billingAddress"] = {
184
- "street" => billing_address[:address1],
185
- "additionalInfo" => billing_address[:address2],
186
- "zip" => billing_address[:zip],
187
- "city" => billing_address[:city],
188
- "state" => billing_address[:state],
189
- "countryCode" => billing_address[:country]
344
+ post['order']['customer']['billingAddress'] = {
345
+ 'street' => truncate(billing_address[:address1], 50),
346
+ 'additionalInfo' => truncate(billing_address[:address2], 50),
347
+ 'zip' => billing_address[:zip],
348
+ 'city' => billing_address[:city],
349
+ 'state' => truncate(billing_address[:state], 35),
350
+ 'countryCode' => billing_address[:country]
190
351
  }
191
352
  end
192
353
  if shipping_address
193
- post["order"]["customer"]["shippingAddress"] = {
194
- "street" => shipping_address[:address1],
195
- "additionalInfo" => shipping_address[:address2],
196
- "zip" => shipping_address[:zip],
197
- "city" => shipping_address[:city],
198
- "state" => shipping_address[:state],
199
- "countryCode" => shipping_address[:country]
354
+ post['order']['customer']['shippingAddress'] = {
355
+ 'street' => truncate(shipping_address[:address1], 50),
356
+ 'additionalInfo' => truncate(shipping_address[:address2], 50),
357
+ 'zip' => shipping_address[:zip],
358
+ 'city' => shipping_address[:city],
359
+ 'state' => truncate(shipping_address[:state], 35),
360
+ 'countryCode' => shipping_address[:country]
200
361
  }
201
- post["order"]["customer"]["shippingAddress"]["name"] = {
202
- "firstName" => shipping_address[:firstname],
203
- "surname" => shipping_address[:lastname]
362
+ post['order']['customer']['shippingAddress']['name'] = {
363
+ 'firstName' => shipping_address[:firstname],
364
+ 'surname' => shipping_address[:lastname]
204
365
  }
205
366
  end
206
367
  end
@@ -208,9 +369,31 @@ module ActiveMerchant #:nodoc:
208
369
  def add_fraud_fields(post, options)
209
370
  fraud_fields = {}
210
371
  fraud_fields.merge!(options[:fraud_fields]) if options[:fraud_fields]
211
- fraud_fields.merge!({customerIpAddress: options[:ip]}) if options[:ip]
372
+ fraud_fields[:customerIpAddress] = options[:ip] if options[:ip]
212
373
 
213
- post["fraudFields"] = fraud_fields unless fraud_fields.empty?
374
+ post['fraudFields'] = fraud_fields unless fraud_fields.empty?
375
+ end
376
+
377
+ def add_external_cardholder_authentication_data(post, options)
378
+ return unless threeds_2_options = options[:three_d_secure]
379
+
380
+ authentication_data = {}
381
+ authentication_data[:acsTransactionId] = threeds_2_options[:acs_transaction_id] if threeds_2_options[:acs_transaction_id]
382
+ authentication_data[:cavv] = threeds_2_options[:cavv] if threeds_2_options[:cavv]
383
+ authentication_data[:cavvAlgorithm] = threeds_2_options[:cavv_algorithm] if threeds_2_options[:cavv_algorithm]
384
+ authentication_data[:directoryServerTransactionId] = threeds_2_options[:ds_transaction_id] if threeds_2_options[:ds_transaction_id]
385
+ authentication_data[:eci] = threeds_2_options[:eci] if threeds_2_options[:eci]
386
+ authentication_data[:threeDSecureVersion] = threeds_2_options[:version] if threeds_2_options[:version]
387
+ authentication_data[:validationResult] = threeds_2_options[:authentication_response_status] if threeds_2_options[:authentication_response_status]
388
+ authentication_data[:xid] = threeds_2_options[:xid] if threeds_2_options[:xid]
389
+
390
+ post['cardPaymentMethodSpecificInput'] ||= {}
391
+ post['cardPaymentMethodSpecificInput']['threeDSecure'] ||= {}
392
+ post['cardPaymentMethodSpecificInput']['threeDSecure']['externalCardholderAuthenticationData'] = authentication_data unless authentication_data.empty?
393
+ end
394
+
395
+ def add_number_of_installments(post, options)
396
+ post['order']['additionalInput']['numberOfInstallments'] = options[:number_of_installments] if options[:number_of_installments]
214
397
  end
215
398
 
216
399
  def parse(body)
@@ -218,6 +401,8 @@ module ActiveMerchant #:nodoc:
218
401
  end
219
402
 
220
403
  def url(action, authorization)
404
+ return preproduction_url + uri(action, authorization) if @options[:url_override].to_s == 'preproduction'
405
+
221
406
  (test? ? test_url : live_url) + uri(action, authorization)
222
407
  end
223
408
 
@@ -225,109 +410,148 @@ module ActiveMerchant #:nodoc:
225
410
  uri = "/v1/#{@options[:merchant_id]}/"
226
411
  case action
227
412
  when :authorize
228
- uri + "payments"
413
+ uri + 'payments'
229
414
  when :capture
230
415
  uri + "payments/#{authorization}/approve"
231
416
  when :refund
232
417
  uri + "payments/#{authorization}/refund"
233
418
  when :void
234
419
  uri + "payments/#{authorization}/cancel"
420
+ when :inquire
421
+ uri + "payments/#{authorization}"
235
422
  end
236
423
  end
237
424
 
238
- def commit(action, post, authorization = nil)
425
+ def idempotency_key_for_signature(options)
426
+ "x-gcs-idempotence-key:#{options[:idempotency_key]}" if options[:idempotency_key]
427
+ end
428
+
429
+ def commit(method, action, post, authorization: nil, options: {})
239
430
  begin
240
- response = parse(ssl_post(url(action, authorization), post.to_json, headers(action, post, authorization)))
431
+ raw_response = ssl_request(method, url(action, authorization), post&.to_json, headers(method, action, post, authorization, options))
432
+ response = parse(raw_response)
241
433
  rescue ResponseError => e
242
- if e.response.code.to_i >= 400
243
- response = parse(e.response.body)
244
- end
434
+ response = parse(e.response.body) if e.response.code.to_i >= 400
435
+ rescue JSON::ParserError
436
+ response = json_error(raw_response)
245
437
  end
246
438
 
247
- succeeded = success_from(response)
439
+ succeeded = success_from(action, response)
248
440
  Response.new(
249
- succeeded,
250
- message_from(succeeded, response),
251
- response,
252
- authorization: authorization_from(succeeded, response),
253
- error_code: error_code_from(succeeded, response),
254
- test: test?
441
+ succeeded,
442
+ message_from(succeeded, response),
443
+ response,
444
+ authorization: authorization_from(response),
445
+ error_code: error_code_from(succeeded, response),
446
+ test: test?
255
447
  )
256
-
257
448
  end
258
449
 
259
- def headers(action, post, authorization = nil)
450
+ def json_error(raw_response)
260
451
  {
261
- "Content-Type" => content_type,
262
- "Authorization" => auth_digest(action, post, authorization),
263
- "Date" => date
452
+ 'error_message' => 'Invalid response received from the Ingenico ePayments (formerly GlobalCollect) API. Please contact Ingenico ePayments if you continue to receive this message.' \
453
+ " (The raw response returned by the API was #{raw_response.inspect})"
264
454
  }
265
455
  end
266
456
 
267
- def auth_digest(action, post, authorization = nil)
268
- data = <<-EOS
269
- POST
270
- #{content_type}
271
- #{date}
272
- #{uri(action, authorization)}
273
- EOS
457
+ def headers(method, action, post, authorization = nil, options = {})
458
+ headers = {
459
+ 'Content-Type' => content_type,
460
+ 'Authorization' => auth_digest(method, action, post, authorization, options),
461
+ 'Date' => date
462
+ }
463
+
464
+ headers['X-GCS-Idempotence-Key'] = options[:idempotency_key] if options[:idempotency_key]
465
+ headers
466
+ end
467
+
468
+ def auth_digest(method, action, post, authorization = nil, options = {})
469
+ data = <<~REQUEST
470
+ #{method.to_s.upcase}
471
+ #{content_type}
472
+ #{date}
473
+ #{idempotency_key_for_signature(options)}
474
+ #{uri(action, authorization)}
475
+ REQUEST
476
+ data = data.each_line.reject { |line| line.strip == '' }.join
274
477
  digest = OpenSSL::Digest.new('sha256')
275
478
  key = @options[:secret_api_key]
276
479
  "GCS v1HMAC:#{@options[:api_key_id]}:#{Base64.strict_encode64(OpenSSL::HMAC.digest(digest, key, data))}"
277
480
  end
278
481
 
279
482
  def date
280
- @date ||= Time.now.strftime("%a, %d %b %Y %H:%M:%S %Z") # Must be same in digest and HTTP header
483
+ @date ||= Time.now.gmtime.strftime('%a, %d %b %Y %H:%M:%S %Z') # Must be same in digest and HTTP header
281
484
  end
282
485
 
283
486
  def content_type
284
- "application/json"
487
+ 'application/json'
285
488
  end
286
489
 
287
- def success_from(response)
288
- !response["errorId"] && response["status"] != "REJECTED"
289
- end
490
+ def success_from(action, response)
491
+ return false if response['errorId'] || response['error_message']
290
492
 
291
- def message_from(succeeded, response)
292
- if succeeded
293
- "Succeeded"
493
+ return %w(CAPTURED CAPTURE_REQUESTED).include?(response.dig('payment', 'status')) if response.dig('payment', 'paymentOutput', 'paymentMethod') == 'mobile'
494
+
495
+ case action
496
+ when :authorize
497
+ response.dig('payment', 'statusOutput', 'isAuthorized')
498
+ when :capture
499
+ capture_status = response.dig('status') || response.dig('payment', 'status')
500
+ %w(CAPTURED CAPTURE_REQUESTED).include?(capture_status)
501
+ when :void
502
+ void_response_id = response.dig('cardPaymentMethodSpecificOutput', 'voidResponseId') || response.dig('mobilePaymentMethodSpecificOutput', 'voidResponseId')
503
+ %w(00 0 8 11).include?(void_response_id) || response.dig('payment', 'status') == 'CANCELLED'
504
+ when :refund
505
+ refund_status = response.dig('status') || response.dig('payment', 'status')
506
+ %w(REFUNDED REFUND_REQUESTED).include?(refund_status)
294
507
  else
295
- if errors = response["errors"]
296
- errors.first.try(:[], "message")
297
- elsif status = response["status"]
298
- "Status: " + status
299
- else
300
- "No message available"
301
- end
508
+ response['status'] != 'REJECTED'
302
509
  end
303
510
  end
304
511
 
305
- def authorization_from(succeeded, response)
306
- if succeeded
307
- response["id"] || response["payment"]["id"] || response["paymentResult"]["payment"]["id"]
512
+ def message_from(succeeded, response)
513
+ return 'Succeeded' if succeeded
514
+
515
+ if errors = response['errors']
516
+ errors.first.try(:[], 'message')
517
+ elsif response['error_message']
518
+ response['error_message']
519
+ elsif response['status']
520
+ 'Status: ' + response['status']
308
521
  else
309
- response["errorId"]
522
+ 'No message available'
310
523
  end
311
524
  end
312
525
 
526
+ def authorization_from(response)
527
+ response.dig('id') || response.dig('payment', 'id') || response.dig('paymentResult', 'payment', 'id')
528
+ end
529
+
313
530
  def error_code_from(succeeded, response)
314
- unless succeeded
315
- if errors = response["errors"]
316
- errors.first.try(:[], "code")
317
- elsif status = response.try(:[], "statusOutput").try(:[], "statusCode")
318
- status.to_s
319
- else
320
- "No error code available"
321
- end
531
+ return if succeeded
532
+
533
+ if errors = response['errors']
534
+ errors.first.try(:[], 'code')
535
+ elsif status = response.try(:[], 'statusOutput').try(:[], 'statusCode')
536
+ status.to_s
537
+ else
538
+ 'No error code available'
322
539
  end
323
540
  end
324
541
 
325
542
  def nestable_hash
326
- Hash.new {|h,k| h[k] = Hash.new(&h.default_proc) }
543
+ Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }
544
+ end
545
+
546
+ # Capture hasn't already been requested,
547
+ # and
548
+ # `requires_approval` is not false
549
+ def should_request_capture?(response, requires_approval)
550
+ !capture_requested?(response) && requires_approval != false
327
551
  end
328
552
 
329
553
  def capture_requested?(response)
330
- response.params.try(:[], "payment").try(:[], "status") == "CAPTURE_REQUESTED"
554
+ response.params.try(:[], 'payment').try(:[], 'status') == 'CAPTURE_REQUESTED'
331
555
  end
332
556
  end
333
557
  end