activemerchant 1.133.0 → 1.138.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 (285) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +450 -0
  3. data/CONTRIBUTORS +1 -0
  4. data/lib/active_merchant/billing/apple_pay_payment_token.rb +2 -2
  5. data/lib/active_merchant/billing/base.rb +2 -2
  6. data/lib/active_merchant/billing/check.rb +16 -4
  7. data/lib/active_merchant/billing/compatibility.rb +4 -4
  8. data/lib/active_merchant/billing/credit_card.rb +35 -16
  9. data/lib/active_merchant/billing/credit_card_formatting.rb +13 -2
  10. data/lib/active_merchant/billing/credit_card_methods.rb +74 -19
  11. data/lib/active_merchant/billing/gateway.rb +22 -2
  12. data/lib/active_merchant/billing/gateways/adyen.rb +282 -87
  13. data/lib/active_merchant/billing/gateways/airwallex.rb +46 -25
  14. data/lib/active_merchant/billing/gateways/alelo.rb +29 -11
  15. data/lib/active_merchant/billing/gateways/allied_wallet.rb +2 -2
  16. data/lib/active_merchant/billing/gateways/authorize_net.rb +49 -41
  17. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +14 -10
  18. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +3 -5
  19. data/lib/active_merchant/billing/gateways/axcessms.rb +9 -5
  20. data/lib/active_merchant/billing/gateways/balanced.rb +2 -2
  21. data/lib/active_merchant/billing/gateways/bambora_apac.rb +2 -2
  22. data/lib/active_merchant/billing/gateways/bank_frick.rb +2 -2
  23. data/lib/active_merchant/billing/gateways/banwire.rb +6 -4
  24. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +8 -8
  25. data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +2 -2
  26. data/lib/active_merchant/billing/gateways/be2bill.rb +2 -2
  27. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +12 -8
  28. data/lib/active_merchant/billing/gateways/beanstream.rb +2 -2
  29. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +2 -2
  30. data/lib/active_merchant/billing/gateways/blue_pay.rb +15 -7
  31. data/lib/active_merchant/billing/gateways/blue_snap.rb +5 -5
  32. data/lib/active_merchant/billing/gateways/bogus.rb +2 -2
  33. data/lib/active_merchant/billing/gateways/borgun.rb +2 -2
  34. data/lib/active_merchant/billing/gateways/bpoint.rb +2 -2
  35. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +3 -1
  36. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +68 -23
  37. data/lib/active_merchant/billing/gateways/braintree.rb +2 -2
  38. data/lib/active_merchant/billing/gateways/braintree_blue.rb +266 -89
  39. data/lib/active_merchant/billing/gateways/braintree_orange.rb +3 -3
  40. data/lib/active_merchant/billing/gateways/bridge_pay.rb +2 -2
  41. data/lib/active_merchant/billing/gateways/cams.rb +2 -2
  42. data/lib/active_merchant/billing/gateways/card_connect.rb +7 -4
  43. data/lib/active_merchant/billing/gateways/card_save.rb +2 -2
  44. data/lib/active_merchant/billing/gateways/card_stream.rb +12 -13
  45. data/lib/active_merchant/billing/gateways/cardknox.rb +2 -2
  46. data/lib/active_merchant/billing/gateways/cardprocess.rb +2 -2
  47. data/lib/active_merchant/billing/gateways/cashnet.rb +4 -4
  48. data/lib/active_merchant/billing/gateways/cc5.rb +2 -2
  49. data/lib/active_merchant/billing/gateways/cecabank/cecabank_common.rb +36 -0
  50. data/lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb +331 -0
  51. data/lib/active_merchant/billing/gateways/cecabank/cecabank_xml.rb +220 -0
  52. data/lib/active_merchant/billing/gateways/cecabank.rb +9 -242
  53. data/lib/active_merchant/billing/gateways/cenpos.rb +9 -3
  54. data/lib/active_merchant/billing/gateways/checkout.rb +5 -5
  55. data/lib/active_merchant/billing/gateways/checkout_v2.rb +362 -50
  56. data/lib/active_merchant/billing/gateways/clearhaus.rb +2 -2
  57. data/lib/active_merchant/billing/gateways/commerce_hub.rb +117 -35
  58. data/lib/active_merchant/billing/gateways/commercegate.rb +4 -4
  59. data/lib/active_merchant/billing/gateways/conekta.rb +2 -2
  60. data/lib/active_merchant/billing/gateways/creditcall.rb +2 -2
  61. data/lib/active_merchant/billing/gateways/credorax.rb +109 -20
  62. data/lib/active_merchant/billing/gateways/ct_payment.rb +6 -6
  63. data/lib/active_merchant/billing/gateways/culqi.rb +2 -2
  64. data/lib/active_merchant/billing/gateways/cyber_source/cyber_source_common.rb +2 -2
  65. data/lib/active_merchant/billing/gateways/cyber_source.rb +379 -100
  66. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +147 -76
  67. data/lib/active_merchant/billing/gateways/d_local.rb +45 -22
  68. data/lib/active_merchant/billing/gateways/data_cash.rb +22 -18
  69. data/lib/active_merchant/billing/gateways/datatrans.rb +284 -0
  70. data/lib/active_merchant/billing/gateways/decidir.rb +82 -46
  71. data/lib/active_merchant/billing/gateways/decidir_plus.rb +31 -35
  72. data/lib/active_merchant/billing/gateways/deepstack.rb +382 -0
  73. data/lib/active_merchant/billing/gateways/dibs.rb +3 -3
  74. data/lib/active_merchant/billing/gateways/digitzs.rb +2 -2
  75. data/lib/active_merchant/billing/gateways/ebanx.rb +116 -68
  76. data/lib/active_merchant/billing/gateways/efsnet.rb +13 -8
  77. data/lib/active_merchant/billing/gateways/elavon.rb +80 -47
  78. data/lib/active_merchant/billing/gateways/element.rb +39 -10
  79. data/lib/active_merchant/billing/gateways/epay.rb +8 -4
  80. data/lib/active_merchant/billing/gateways/evo_ca.rb +8 -4
  81. data/lib/active_merchant/billing/gateways/eway.rb +6 -4
  82. data/lib/active_merchant/billing/gateways/eway_managed.rb +8 -4
  83. data/lib/active_merchant/billing/gateways/eway_rapid.rb +3 -3
  84. data/lib/active_merchant/billing/gateways/exact.rb +8 -4
  85. data/lib/active_merchant/billing/gateways/fat_zebra.rb +37 -7
  86. data/lib/active_merchant/billing/gateways/federated_canada.rb +8 -4
  87. data/lib/active_merchant/billing/gateways/finansbank.rb +2 -2
  88. data/lib/active_merchant/billing/gateways/first_giving.rb +2 -2
  89. data/lib/active_merchant/billing/gateways/first_pay/first_pay_common.rb +15 -0
  90. data/lib/active_merchant/billing/gateways/first_pay/first_pay_json.rb +190 -0
  91. data/lib/active_merchant/billing/gateways/first_pay/first_pay_xml.rb +183 -0
  92. data/lib/active_merchant/billing/gateways/first_pay.rb +8 -174
  93. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +8 -4
  94. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +9 -5
  95. data/lib/active_merchant/billing/gateways/flex_charge.rb +359 -0
  96. data/lib/active_merchant/billing/gateways/flo2cash.rb +4 -2
  97. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +2 -2
  98. data/lib/active_merchant/billing/gateways/forte.rb +6 -4
  99. data/lib/active_merchant/billing/gateways/fortis.rb +347 -0
  100. data/lib/active_merchant/billing/gateways/garanti.rb +6 -4
  101. data/lib/active_merchant/billing/gateways/global_collect.rb +69 -50
  102. data/lib/active_merchant/billing/gateways/global_transport.rb +2 -2
  103. data/lib/active_merchant/billing/gateways/hdfc.rb +2 -2
  104. data/lib/active_merchant/billing/gateways/hi_pay.rb +287 -0
  105. data/lib/active_merchant/billing/gateways/hps.rb +40 -47
  106. data/lib/active_merchant/billing/gateways/iats_payments.rb +9 -4
  107. data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +2 -2
  108. data/lib/active_merchant/billing/gateways/inspire.rb +8 -6
  109. data/lib/active_merchant/billing/gateways/instapay.rb +9 -6
  110. data/lib/active_merchant/billing/gateways/ipg.rb +14 -10
  111. data/lib/active_merchant/billing/gateways/ipp.rb +2 -2
  112. data/lib/active_merchant/billing/gateways/iridium.rb +18 -8
  113. data/lib/active_merchant/billing/gateways/itransact.rb +8 -4
  114. data/lib/active_merchant/billing/gateways/iveri.rb +12 -9
  115. data/lib/active_merchant/billing/gateways/ixopay.rb +4 -4
  116. data/lib/active_merchant/billing/gateways/jetpay.rb +6 -4
  117. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +9 -6
  118. data/lib/active_merchant/billing/gateways/komoju.rb +2 -2
  119. data/lib/active_merchant/billing/gateways/kushki.rb +79 -16
  120. data/lib/active_merchant/billing/gateways/latitude19.rb +2 -2
  121. data/lib/active_merchant/billing/gateways/linkpoint.rb +8 -4
  122. data/lib/active_merchant/billing/gateways/litle.rb +37 -54
  123. data/lib/active_merchant/billing/gateways/loan_payment_pro.rb +267 -0
  124. data/lib/active_merchant/billing/gateways/loan_payment_pro_ach.rb +93 -0
  125. data/lib/active_merchant/billing/gateways/mastercard.rb +4 -4
  126. data/lib/active_merchant/billing/gateways/maxipago.rb +4 -4
  127. data/lib/active_merchant/billing/gateways/mercado_pago.rb +32 -11
  128. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +10 -7
  129. data/lib/active_merchant/billing/gateways/merchant_one.rb +2 -2
  130. data/lib/active_merchant/billing/gateways/merchant_partners.rb +2 -2
  131. data/lib/active_merchant/billing/gateways/merchant_ware.rb +13 -6
  132. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +13 -6
  133. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +21 -5
  134. data/lib/active_merchant/billing/gateways/mercury.rb +11 -5
  135. data/lib/active_merchant/billing/gateways/metrics_global.rb +10 -8
  136. data/lib/active_merchant/billing/gateways/micropayment.rb +2 -2
  137. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +7 -6
  138. data/lib/active_merchant/billing/gateways/migs.rb +8 -4
  139. data/lib/active_merchant/billing/gateways/mit.rb +10 -5
  140. data/lib/active_merchant/billing/gateways/modern_payments.rb +2 -2
  141. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +21 -13
  142. data/lib/active_merchant/billing/gateways/moka.rb +2 -2
  143. data/lib/active_merchant/billing/gateways/monei.rb +3 -3
  144. data/lib/active_merchant/billing/gateways/moneris.rb +11 -5
  145. data/lib/active_merchant/billing/gateways/money_movers.rb +8 -4
  146. data/lib/active_merchant/billing/gateways/multi_pay.rb +267 -0
  147. data/lib/active_merchant/billing/gateways/mundipagg.rb +5 -3
  148. data/lib/active_merchant/billing/gateways/nab_transact.rb +18 -10
  149. data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +2 -2
  150. data/lib/active_merchant/billing/gateways/net_registry.rb +6 -2
  151. data/lib/active_merchant/billing/gateways/netaxept.rb +4 -4
  152. data/lib/active_merchant/billing/gateways/netbanx.rb +4 -6
  153. data/lib/active_merchant/billing/gateways/netbilling.rb +8 -4
  154. data/lib/active_merchant/billing/gateways/netpay.rb +2 -2
  155. data/lib/active_merchant/billing/gateways/network_merchants.rb +9 -5
  156. data/lib/active_merchant/billing/gateways/nmi.rb +29 -8
  157. data/lib/active_merchant/billing/gateways/nuvei.rb +573 -0
  158. data/lib/active_merchant/billing/gateways/ogone.rb +8 -4
  159. data/lib/active_merchant/billing/gateways/omise.rb +2 -2
  160. data/lib/active_merchant/billing/gateways/openpay.rb +6 -4
  161. data/lib/active_merchant/billing/gateways/opp.rb +3 -4
  162. data/lib/active_merchant/billing/gateways/optimal_payment.rb +12 -6
  163. data/lib/active_merchant/billing/gateways/orbital/orbital_codes.rb +273 -0
  164. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +3 -5
  165. data/lib/active_merchant/billing/gateways/orbital.rb +114 -94
  166. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +9 -6
  167. data/lib/active_merchant/billing/gateways/pagarme.rb +2 -2
  168. data/lib/active_merchant/billing/gateways/pago_facil.rb +2 -2
  169. data/lib/active_merchant/billing/gateways/pay_arc.rb +9 -7
  170. data/lib/active_merchant/billing/gateways/pay_conex.rb +6 -4
  171. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +8 -4
  172. data/lib/active_merchant/billing/gateways/pay_hub.rb +7 -5
  173. data/lib/active_merchant/billing/gateways/pay_junction.rb +8 -4
  174. data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +2 -2
  175. data/lib/active_merchant/billing/gateways/pay_secure.rb +8 -4
  176. data/lib/active_merchant/billing/gateways/pay_trace.rb +36 -22
  177. data/lib/active_merchant/billing/gateways/paybox_direct.rb +14 -14
  178. data/lib/active_merchant/billing/gateways/payeezy.rb +26 -13
  179. data/lib/active_merchant/billing/gateways/payex.rb +8 -6
  180. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +3 -3
  181. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +2 -2
  182. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +2 -2
  183. data/lib/active_merchant/billing/gateways/payflow.rb +12 -11
  184. data/lib/active_merchant/billing/gateways/payflow_express.rb +2 -2
  185. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +2 -2
  186. data/lib/active_merchant/billing/gateways/payflow_uk.rb +2 -2
  187. data/lib/active_merchant/billing/gateways/payment_express.rb +10 -6
  188. data/lib/active_merchant/billing/gateways/paymentez.rb +30 -16
  189. data/lib/active_merchant/billing/gateways/paymill.rb +6 -4
  190. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +17 -12
  191. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +2 -2
  192. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +2 -2
  193. data/lib/active_merchant/billing/gateways/paypal.rb +4 -2
  194. data/lib/active_merchant/billing/gateways/paypal_ca.rb +2 -2
  195. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +2 -2
  196. data/lib/active_merchant/billing/gateways/paypal_express.rb +4 -2
  197. data/lib/active_merchant/billing/gateways/paysafe.rb +48 -24
  198. data/lib/active_merchant/billing/gateways/payscout.rb +9 -6
  199. data/lib/active_merchant/billing/gateways/paystation.rb +9 -5
  200. data/lib/active_merchant/billing/gateways/payu_in.rb +2 -2
  201. data/lib/active_merchant/billing/gateways/payu_latam.rb +7 -5
  202. data/lib/active_merchant/billing/gateways/payway.rb +6 -2
  203. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +6 -6
  204. data/lib/active_merchant/billing/gateways/pin.rb +126 -41
  205. data/lib/active_merchant/billing/gateways/plexo.rb +71 -20
  206. data/lib/active_merchant/billing/gateways/plugnpay.rb +6 -2
  207. data/lib/active_merchant/billing/gateways/priority.rb +29 -24
  208. data/lib/active_merchant/billing/gateways/pro_pay.rb +2 -2
  209. data/lib/active_merchant/billing/gateways/psigate.rb +8 -4
  210. data/lib/active_merchant/billing/gateways/psl_card.rb +6 -2
  211. data/lib/active_merchant/billing/gateways/qbms.rb +9 -5
  212. data/lib/active_merchant/billing/gateways/quantum.rb +9 -5
  213. data/lib/active_merchant/billing/gateways/quickbooks.rb +27 -17
  214. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +7 -4
  215. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +8 -4
  216. data/lib/active_merchant/billing/gateways/quickpay.rb +2 -2
  217. data/lib/active_merchant/billing/gateways/qvalent.rb +2 -2
  218. data/lib/active_merchant/billing/gateways/rapyd.rb +172 -53
  219. data/lib/active_merchant/billing/gateways/reach.rb +16 -9
  220. data/lib/active_merchant/billing/gateways/redsys.rb +7 -15
  221. data/lib/active_merchant/billing/gateways/redsys_rest.rb +545 -0
  222. data/lib/active_merchant/billing/gateways/s5.rb +5 -5
  223. data/lib/active_merchant/billing/gateways/safe_charge.rb +47 -24
  224. data/lib/active_merchant/billing/gateways/sage.rb +14 -6
  225. data/lib/active_merchant/billing/gateways/sage_pay.rb +81 -7
  226. data/lib/active_merchant/billing/gateways/sallie_mae.rb +8 -4
  227. data/lib/active_merchant/billing/gateways/secure_net.rb +9 -5
  228. data/lib/active_merchant/billing/gateways/secure_pay.rb +10 -8
  229. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +25 -15
  230. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +8 -4
  231. data/lib/active_merchant/billing/gateways/securion_pay.rb +26 -12
  232. data/lib/active_merchant/billing/gateways/shift4.rb +34 -26
  233. data/lib/active_merchant/billing/gateways/shift4_v2.rb +117 -0
  234. data/lib/active_merchant/billing/gateways/simetrik.rb +26 -17
  235. data/lib/active_merchant/billing/gateways/skip_jack.rb +8 -4
  236. data/lib/active_merchant/billing/gateways/smart_ps.rb +10 -7
  237. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +6 -4
  238. data/lib/active_merchant/billing/gateways/spreedly_core.rb +4 -6
  239. data/lib/active_merchant/billing/gateways/stripe.rb +88 -84
  240. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +388 -77
  241. data/lib/active_merchant/billing/gateways/sum_up.rb +224 -0
  242. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +6 -4
  243. data/lib/active_merchant/billing/gateways/telr.rb +6 -7
  244. data/lib/active_merchant/billing/gateways/trans_first.rb +6 -4
  245. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +10 -18
  246. data/lib/active_merchant/billing/gateways/transact_pro.rb +3 -3
  247. data/lib/active_merchant/billing/gateways/transax.rb +2 -2
  248. data/lib/active_merchant/billing/gateways/transnational.rb +2 -2
  249. data/lib/active_merchant/billing/gateways/trexle.rb +2 -2
  250. data/lib/active_merchant/billing/gateways/trust_commerce.rb +9 -5
  251. data/lib/active_merchant/billing/gateways/usa_epay.rb +2 -2
  252. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +32 -31
  253. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +8 -4
  254. data/lib/active_merchant/billing/gateways/vanco.rb +2 -4
  255. data/lib/active_merchant/billing/gateways/vantiv_express.rb +668 -0
  256. data/lib/active_merchant/billing/gateways/verifi.rb +12 -8
  257. data/lib/active_merchant/billing/gateways/versa_pay.rb +307 -0
  258. data/lib/active_merchant/billing/gateways/viaklix.rb +8 -4
  259. data/lib/active_merchant/billing/gateways/visanet_peru.rb +5 -5
  260. data/lib/active_merchant/billing/gateways/vpos.rb +25 -13
  261. data/lib/active_merchant/billing/gateways/webpay.rb +3 -3
  262. data/lib/active_merchant/billing/gateways/wepay.rb +6 -4
  263. data/lib/active_merchant/billing/gateways/wirecard.rb +10 -6
  264. data/lib/active_merchant/billing/gateways/wompi.rb +14 -7
  265. data/lib/active_merchant/billing/gateways/world_net.rb +2 -2
  266. data/lib/active_merchant/billing/gateways/worldpay.rb +297 -113
  267. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +16 -13
  268. data/lib/active_merchant/billing/gateways/worldpay_us.rb +2 -2
  269. data/lib/active_merchant/billing/gateways/xpay.rb +244 -0
  270. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +15 -3
  271. data/lib/active_merchant/billing/payment_token.rb +2 -2
  272. data/lib/active_merchant/billing/response.rb +7 -6
  273. data/lib/active_merchant/billing.rb +1 -0
  274. data/lib/active_merchant/connection.rb +8 -20
  275. data/lib/active_merchant/country.rb +3 -1
  276. data/lib/active_merchant/errors.rb +12 -2
  277. data/lib/active_merchant/net_http_ssl_connection.rb +35 -0
  278. data/lib/active_merchant/posts_data.rb +19 -4
  279. data/lib/active_merchant/version.rb +1 -1
  280. data/lib/active_merchant/versionable.rb +29 -0
  281. data/lib/certs/cacert.pem +1326 -1491
  282. data/lib/support/gateway_support.rb +3 -3
  283. data/lib/support/ssl_verify.rb +6 -6
  284. data/lib/support/ssl_version.rb +8 -8
  285. metadata +35 -9
@@ -1,5 +1,5 @@
1
- module ActiveMerchant #:nodoc:
2
- module Billing #:nodoc:
1
+ module ActiveMerchant # :nodoc:
2
+ module Billing # :nodoc:
3
3
  class WorldpayOnlinePaymentsGateway < Gateway
4
4
  self.live_url = 'https://api.worldpay.com/v1/'
5
5
 
@@ -34,14 +34,16 @@ module ActiveMerchant #:nodoc:
34
34
  if authorization
35
35
  commit(:post, "orders/#{CGI.escape(authorization)}/capture", { 'captureAmount' => money }, options, 'capture')
36
36
  else
37
- Response.new(false,
37
+ Response.new(
38
+ false,
38
39
  'FAILED',
39
40
  'FAILED',
40
41
  test: test?,
41
42
  authorization: false,
42
43
  avs_result: {},
43
44
  cvv_result: {},
44
- error_code: false)
45
+ error_code: false
46
+ )
45
47
  end
46
48
  end
47
49
 
@@ -84,8 +86,7 @@ module ActiveMerchant #:nodoc:
84
86
  },
85
87
  'clientKey' => @client_key
86
88
  }
87
- token_response = commit(:post, 'tokens', obj, { 'Authorization' => @service_key }, 'token')
88
- token_response
89
+ commit(:post, 'tokens', obj, { 'Authorization' => @service_key }, 'token')
89
90
  end
90
91
 
91
92
  def create_post_for_auth_or_purchase(token, money, options)
@@ -134,7 +135,10 @@ module ActiveMerchant #:nodoc:
134
135
 
135
136
  raw_response = ssl_request(method, self.live_url + url, json, headers(options))
136
137
 
137
- if raw_response != ''
138
+ if raw_response == ''
139
+ success = true
140
+ response = {}
141
+ else
138
142
  response = parse(raw_response)
139
143
  if type == 'token'
140
144
  success = response.key?('token')
@@ -151,9 +155,6 @@ module ActiveMerchant #:nodoc:
151
155
  end
152
156
  end
153
157
  end
154
- else
155
- success = true
156
- response = {}
157
158
  end
158
159
  rescue ResponseError => e
159
160
  raw_response = e.response.body
@@ -170,14 +171,16 @@ module ActiveMerchant #:nodoc:
170
171
  authorization = response['message']
171
172
  end
172
173
 
173
- Response.new(success,
174
+ Response.new(
175
+ success,
174
176
  success ? 'SUCCESS' : response['message'],
175
177
  response,
176
178
  test: test?,
177
- authorization: authorization,
179
+ authorization:,
178
180
  avs_result: {},
179
181
  cvv_result: {},
180
- error_code: success ? nil : response['customCode'])
182
+ error_code: success ? nil : response['customCode']
183
+ )
181
184
  end
182
185
 
183
186
  def test?
@@ -1,7 +1,7 @@
1
1
  require 'nokogiri'
2
2
 
3
- module ActiveMerchant #:nodoc:
4
- module Billing #:nodoc:
3
+ module ActiveMerchant # :nodoc:
4
+ module Billing # :nodoc:
5
5
  class WorldpayUsGateway < Gateway
6
6
  class_attribute :backup_url
7
7
 
@@ -0,0 +1,244 @@
1
+ module ActiveMerchant # :nodoc:
2
+ module Billing # :nodoc:
3
+ class XpayGateway < Gateway
4
+ self.display_name = 'XPay Gateway'
5
+ self.homepage_url = 'https://developer.nexi.it/en'
6
+
7
+ version 'v1'
8
+
9
+ self.test_url = "https://xpaysandbox.nexigroup.com/api/phoenix-0.0/psp/api/#{fetch_version}/"
10
+ self.live_url = "https://xpay.nexigroup.com/api/phoenix-0.0/psp/api/#{fetch_version}/"
11
+
12
+ self.supported_countries = %w(AT BE CY EE FI FR DE GR IE IT LV LT LU MT PT SK SI ES BG HR DK NO PL RO RO SE CH HU)
13
+ self.default_currency = 'EUR'
14
+ self.currencies_without_fractions = %w(BGN HRK DKK NOK GBP PLN CZK RON SEK CHF HUF)
15
+ self.money_format = :cents
16
+ self.supported_cardtypes = %i[visa master maestro american_express jcb]
17
+
18
+ ENDPOINTS_MAPPING = {
19
+ validation: 'orders/3steps/validation',
20
+ purchase: 'orders/3steps/payment',
21
+ authorize: 'orders/3steps/payment',
22
+ preauth: 'orders/3steps/init',
23
+ capture: 'operations/%s/captures',
24
+ verify: 'orders/card_verification',
25
+ refund: 'operations/%s/refunds'
26
+ }
27
+
28
+ SUCCESS_MESSAGES = %w(PENDING AUTHORIZED THREEDS_VALIDATED EXECUTED).freeze
29
+
30
+ def initialize(options = {})
31
+ requires!(options, :api_key)
32
+ @api_key = options[:api_key]
33
+ super
34
+ end
35
+
36
+ def preauth(amount, credit_card, options = {})
37
+ order_request(:preauth, amount, {}, credit_card, options)
38
+ end
39
+
40
+ def purchase(amount, credit_card, options = {})
41
+ complete_order_request(:purchase, amount, credit_card, options)
42
+ end
43
+
44
+ def authorize(amount, credit_card, options = {})
45
+ complete_order_request(:authorize, amount, credit_card, options)
46
+ end
47
+
48
+ def capture(amount, authorization, options = {})
49
+ operation_request(:capture, amount, authorization, options)
50
+ end
51
+
52
+ def refund(amount, authorization, options = {})
53
+ operation_request(:refund, amount, authorization, options)
54
+ end
55
+
56
+ def verify(credit_card, options = {})
57
+ post = {}
58
+ add_invoice(post, 0, options)
59
+ add_customer_data(post, credit_card, options)
60
+ add_credit_card(post, credit_card)
61
+ commit(:verify, post, options)
62
+ end
63
+
64
+ def supports_scrubbing?
65
+ true
66
+ end
67
+
68
+ def scrub(transcript)
69
+ transcript.
70
+ gsub(%r((X-Api-Key: )(\w|-)+), '\1[FILTERED]').
71
+ gsub(%r(("pan\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
72
+ gsub(%r(("cvv\\?":\\?")\d+), '\1[FILTERED]')
73
+ end
74
+
75
+ private
76
+
77
+ def validation(options = {})
78
+ post = {}
79
+ add_3ds_validation_params(post, options)
80
+ commit(:validation, post, options)
81
+ end
82
+
83
+ def complete_order_request(action, amount, credit_card, options = {})
84
+ MultiResponse.run do |r|
85
+ r.process { validation(options) }
86
+ r.process { order_request(action, amount, { captureType: (action == :authorize ? 'EXPLICIT' : 'IMPLICIT') }, credit_card, options.merge!(validation: r.params)) }
87
+ end
88
+ end
89
+
90
+ def order_request(action, amount, post, credit_card, options = {})
91
+ add_invoice(post, amount, options)
92
+ add_credit_card(post, credit_card)
93
+ add_customer_data(post, credit_card, options)
94
+ add_address(post, options)
95
+ add_recurrence(post, options) unless options[:operation_id]
96
+ add_exemptions(post, options)
97
+ add_3ds_params(post, options[:validation]) if options[:validation]
98
+
99
+ commit(action, post, options)
100
+ end
101
+
102
+ def operation_request(action, amount, authorization, options)
103
+ options[:correlation_id], options[:reference] = authorization.split('#')
104
+ commit(action, { amount:, currency: options[:currency] }, options)
105
+ end
106
+
107
+ def add_invoice(post, amount, options)
108
+ currency = options[:currency] || currency(amount)
109
+ post[:order] = {
110
+ orderId: options[:order_id],
111
+ amount: localized_amount(amount, currency),
112
+ currency:
113
+ }.compact
114
+ end
115
+
116
+ def add_credit_card(post, credit_card)
117
+ post[:card] = {
118
+ pan: credit_card.number,
119
+ expiryDate: expdate(credit_card),
120
+ cvv: credit_card.verification_value
121
+ }
122
+ end
123
+
124
+ def add_customer_data(post, credit_card, options)
125
+ post[:order][:customerInfo] = {
126
+ cardHolderName: credit_card.name,
127
+ cardHolderEmail: options[:email]
128
+ }.compact
129
+ end
130
+
131
+ def add_address(post, options)
132
+ if address = options[:billing_address] || options[:address]
133
+ post[:order][:customerInfo][:billingAddress] = {
134
+ name: address[:name],
135
+ street: address[:address1],
136
+ additionalInfo: address[:address2],
137
+ city: address[:city],
138
+ postCode: address[:zip],
139
+ country: address[:country]
140
+ }.compact
141
+ end
142
+
143
+ if address = options[:shipping_address]
144
+ post[:order][:customerInfo][:shippingAddress] = {
145
+ name: address[:name],
146
+ street: address[:address1],
147
+ additionalInfo: address[:address2],
148
+ city: address[:city],
149
+ postCode: address[:zip],
150
+ country: address[:country]
151
+ }.compact
152
+ end
153
+ end
154
+
155
+ def add_recurrence(post, options)
156
+ post[:recurrence] = { action: options[:recurrence] || 'NO_RECURRING' }
157
+ end
158
+
159
+ def add_exemptions(post, options)
160
+ post[:exemptions] = options[:exemptions] || 'NO_PREFERENCE'
161
+ end
162
+
163
+ def add_3ds_params(post, validation)
164
+ post[:threeDSAuthData] = {
165
+ authenticationValue: validation['threeDSAuthResult']['authenticationValue'],
166
+ eci: validation['threeDSAuthResult']['eci'],
167
+ xid: validation['threeDSAuthResult']['xid']
168
+ }
169
+ post[:operationId] = validation['operation']['operationId']
170
+ end
171
+
172
+ def add_3ds_validation_params(post, options)
173
+ post[:operationId] = options[:operation_id]
174
+ post[:threeDSAuthResponse] = options[:three_ds_auth_response]
175
+ end
176
+
177
+ def parse(body)
178
+ JSON.parse(body)
179
+ end
180
+
181
+ def commit(action, params, options)
182
+ options[:correlation_id] ||= SecureRandom.uuid
183
+ transaction_id = transaction_id_from(params, options, action)
184
+ raw_response =
185
+ begin
186
+ url = build_request_url(action, transaction_id)
187
+ ssl_post(url, params.to_json, request_headers(options, action))
188
+ rescue ResponseError => e
189
+ { errors: [code: e.response.code, description: e.response.body] }.to_json
190
+ end
191
+ response = parse(raw_response)
192
+
193
+ Response.new(
194
+ success_from(action, response),
195
+ message_from(response),
196
+ response,
197
+ authorization: authorization_from(options[:correlation_id], response),
198
+ test: test?,
199
+ error_code: error_code_from(response)
200
+ )
201
+ end
202
+
203
+ def request_headers(options, action = nil)
204
+ headers = { 'X-Api-Key' => @api_key, 'Content-Type' => 'application/json', 'Correlation-Id' => options[:correlation_id] }
205
+ headers.merge!('Idempotency-Key' => options[:idempotency_key] || SecureRandom.uuid) if %i[capture refund].include?(action)
206
+ headers
207
+ end
208
+
209
+ def transaction_id_from(params, options, action = nil)
210
+ case action
211
+ when :refund, :capture
212
+ return options[:reference]
213
+ else
214
+ return params[:operation_id]
215
+ end
216
+ end
217
+
218
+ def build_request_url(action, id = nil)
219
+ "#{test? ? test_url : live_url}#{ENDPOINTS_MAPPING[action.to_sym] % id}"
220
+ end
221
+
222
+ def success_from(action, response)
223
+ case action
224
+ when :capture, :refund
225
+ response.include?('operationId') && response.include?('operationTime')
226
+ else
227
+ SUCCESS_MESSAGES.include?(response.dig('operation', 'operationResult'))
228
+ end
229
+ end
230
+
231
+ def message_from(response)
232
+ response['operationId'] || response.dig('operation', 'operationResult') || response.dig('errors', 0, 'description')
233
+ end
234
+
235
+ def authorization_from(correlation_id, response = {})
236
+ [correlation_id, (response['operationId'] || response.dig('operation', 'operationId'))].join('#')
237
+ end
238
+
239
+ def error_code_from(response)
240
+ response.dig('errors', 0, 'code')
241
+ end
242
+ end
243
+ end
244
+ end
@@ -1,5 +1,5 @@
1
- module ActiveMerchant #:nodoc:
2
- module Billing #:nodoc:
1
+ module ActiveMerchant # :nodoc:
2
+ module Billing # :nodoc:
3
3
  class NetworkTokenizationCreditCard < CreditCard
4
4
  # A +NetworkTokenizationCreditCard+ object represents a tokenized credit card
5
5
  # using the EMV Network Tokenization specification, http://www.emvco.com/specifications.aspx?id=263.
@@ -14,7 +14,7 @@ module ActiveMerchant #:nodoc:
14
14
  self.require_verification_value = false
15
15
  self.require_name = false
16
16
 
17
- attr_accessor :payment_cryptogram, :eci, :transaction_id, :metadata
17
+ attr_accessor :payment_cryptogram, :eci, :transaction_id, :metadata, :payment_data
18
18
  attr_writer :source
19
19
 
20
20
  SOURCES = %i(apple_pay android_pay google_pay network_token)
@@ -31,6 +31,18 @@ module ActiveMerchant #:nodoc:
31
31
  true
32
32
  end
33
33
 
34
+ def network_token?
35
+ source == :network_token
36
+ end
37
+
38
+ def mobile_wallet?
39
+ %i[apple_pay android_pay google_pay].include?(source)
40
+ end
41
+
42
+ def encrypted_wallet?
43
+ payment_data.present?
44
+ end
45
+
34
46
  def type
35
47
  'network_tokenization'
36
48
  end
@@ -1,5 +1,5 @@
1
- module ActiveMerchant #:nodoc:
2
- module Billing #:nodoc:
1
+ module ActiveMerchant # :nodoc:
2
+ module Billing # :nodoc:
3
3
  # Base class representation of cryptographic payment data tokens that may be used for EMV-style transactions
4
4
  # like Apple Pay. Payment data may be transmitted via any data type, and may also be padded
5
5
  # with metadata specific to the cryptographer. This metadata should be parsed and interpreted in concrete
@@ -1,10 +1,10 @@
1
- module ActiveMerchant #:nodoc:
2
- module Billing #:nodoc:
3
- class Error < ActiveMerchantError #:nodoc:
1
+ module ActiveMerchant # :nodoc:
2
+ module Billing # :nodoc:
3
+ class Error < ActiveMerchantError # :nodoc:
4
4
  end
5
5
 
6
6
  class Response
7
- attr_reader :params, :message, :test, :authorization, :avs_result, :cvv_result, :error_code, :emv_authorization, :network_transaction_id
7
+ attr_reader :params, :message, :test, :authorization, :avs_result, :cvv_result, :error_code, :emv_authorization, :network_transaction_id, :pending
8
8
 
9
9
  def success?
10
10
  @success
@@ -30,6 +30,7 @@ module ActiveMerchant #:nodoc:
30
30
  @error_code = options[:error_code]
31
31
  @emv_authorization = options[:emv_authorization]
32
32
  @network_transaction_id = options[:network_transaction_id]
33
+ @pending = options[:pending] || false
33
34
 
34
35
  @avs_result = if options[:avs_result].kind_of?(AVSResult)
35
36
  options[:avs_result].to_hash
@@ -100,11 +101,11 @@ module ActiveMerchant #:nodoc:
100
101
  end
101
102
 
102
103
  %w(params message test authorization error_code emv_authorization test? fraud_review?).each do |m|
103
- class_eval %(
104
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
104
105
  def #{m}
105
106
  (@responses.empty? ? nil : primary_response.#{m})
106
107
  end
107
- )
108
+ RUBY
108
109
  end
109
110
  end
110
111
  end
@@ -1,4 +1,5 @@
1
1
  require 'active_merchant/errors'
2
+ require 'active_merchant/versionable'
2
3
 
3
4
  require 'active_merchant/billing/avs_result'
4
5
  require 'active_merchant/billing/cvv_result'
@@ -18,27 +18,13 @@ module ActiveMerchant
18
18
  RETRY_SAFE = false
19
19
  RUBY_184_POST_HEADERS = { 'Content-Type' => 'application/x-www-form-urlencoded' }
20
20
 
21
- attr_accessor :endpoint
22
- attr_accessor :open_timeout
23
- attr_accessor :read_timeout
24
- attr_accessor :verify_peer
25
- attr_accessor :ssl_version
21
+ attr_accessor :endpoint, :open_timeout, :read_timeout, :verify_peer, :ssl_version, :ca_file, :ca_path, :pem, :pem_password, :logger, :tag, :ignore_http_status, :max_retries, :proxy_address, :proxy_port, :proxy_user, :proxy_password
22
+
26
23
  if Net::HTTP.instance_methods.include?(:min_version=)
27
24
  attr_accessor :min_version
28
25
  attr_accessor :max_version
29
26
  end
30
- attr_reader :ssl_connection
31
- attr_accessor :ca_file
32
- attr_accessor :ca_path
33
- attr_accessor :pem
34
- attr_accessor :pem_password
35
- attr_reader :wiredump_device
36
- attr_accessor :logger
37
- attr_accessor :tag
38
- attr_accessor :ignore_http_status
39
- attr_accessor :max_retries
40
- attr_accessor :proxy_address
41
- attr_accessor :proxy_port
27
+ attr_reader :ssl_connection, :wiredump_device
42
28
 
43
29
  def initialize(endpoint)
44
30
  @endpoint = endpoint.is_a?(URI) ? endpoint : URI.parse(endpoint)
@@ -58,6 +44,8 @@ module ActiveMerchant
58
44
  @ssl_connection = {}
59
45
  @proxy_address = :ENV
60
46
  @proxy_port = nil
47
+ @proxy_user = nil
48
+ @proxy_password = nil
61
49
  end
62
50
 
63
51
  def wiredump_device=(device)
@@ -72,7 +60,7 @@ module ActiveMerchant
72
60
  headers = headers.dup
73
61
  headers['connection'] ||= 'close'
74
62
 
75
- retry_exceptions(max_retries: max_retries, logger: logger, tag: tag) do
63
+ retry_exceptions(max_retries:, logger:, tag:) do
76
64
  info "connection_http_method=#{method.to_s.upcase} connection_uri=#{endpoint}", tag
77
65
 
78
66
  result = nil
@@ -88,7 +76,7 @@ module ActiveMerchant
88
76
  http.get(endpoint.request_uri, headers)
89
77
  when :post
90
78
  debug body
91
- http.post(endpoint.request_uri, body, RUBY_184_POST_HEADERS.merge(headers))
79
+ http.post(endpoint.request_uri, body, headers.reverse_merge!(RUBY_184_POST_HEADERS))
92
80
  when :put
93
81
  debug body
94
82
  http.put(endpoint.request_uri, body, headers)
@@ -125,7 +113,7 @@ module ActiveMerchant
125
113
 
126
114
  def http
127
115
  @http ||= begin
128
- http = Net::HTTP.new(endpoint.host, endpoint.port, proxy_address, proxy_port)
116
+ http = Net::HTTP.new(endpoint.host, endpoint.port, proxy_address, proxy_port, proxy_user, proxy_password)
129
117
  configure_debugging(http)
130
118
  configure_timeouts(http)
131
119
  configure_ssl(http)
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- module ActiveMerchant #:nodoc:
3
+ module ActiveMerchant # :nodoc:
4
4
  class InvalidCountryCodeError < StandardError
5
5
  end
6
6
 
@@ -9,6 +9,7 @@ module ActiveMerchant #:nodoc:
9
9
 
10
10
  class CountryCode
11
11
  attr_reader :value, :format
12
+
12
13
  def initialize(value)
13
14
  @value = value.to_s.upcase
14
15
  detect_format
@@ -309,6 +310,7 @@ module ActiveMerchant #:nodoc:
309
310
  { alpha2: 'VU', name: 'Vanuatu', alpha3: 'VUT', numeric: '548' },
310
311
  { alpha2: 'VE', name: 'Venezuela', alpha3: 'VEN', numeric: '862' },
311
312
  { alpha2: 'VN', name: 'Viet Nam', alpha3: 'VNM', numeric: '704' },
313
+ { alpha2: 'VN', name: 'Vietnam', alpha3: 'VNM', numeric: '704' },
312
314
  { alpha2: 'VG', name: 'Virgin Islands, British', alpha3: 'VGB', numeric: '092' },
313
315
  { alpha2: 'VI', name: 'Virgin Islands, U.S.', alpha3: 'VIR', numeric: '850' },
314
316
  { alpha2: 'WF', name: 'Wallis and Futuna', alpha3: 'WLF', numeric: '876' },
@@ -1,5 +1,5 @@
1
- module ActiveMerchant #:nodoc:
2
- class ActiveMerchantError < StandardError #:nodoc:
1
+ module ActiveMerchant # :nodoc:
2
+ class ActiveMerchantError < StandardError # :nodoc:
3
3
  end
4
4
 
5
5
  class ConnectionError < ActiveMerchantError # :nodoc:
@@ -23,6 +23,16 @@ module ActiveMerchant #:nodoc:
23
23
  end
24
24
 
25
25
  def to_s
26
+ if response.kind_of?(String)
27
+ if response.start_with?('Failed')
28
+ return response
29
+ else
30
+ return "Failed with #{response}"
31
+ end
32
+ end
33
+
34
+ return response.message if response.respond_to?(:message) && response.message.start_with?('Failed')
35
+
26
36
  "Failed with #{response.code if response.respond_to?(:code)} #{response.message if response.respond_to?(:message)}"
27
37
  end
28
38
  end
@@ -1,11 +1,46 @@
1
1
  require 'net/http'
2
2
 
3
3
  module NetHttpSslConnection
4
+ module InnocuousCapitalize
5
+ def capitalize(name) = name
6
+ private :capitalize
7
+ end
8
+
9
+ class CaseSensitivePost < Net::HTTP::Post; prepend InnocuousCapitalize; end
10
+
11
+ class CaseSensitivePatch < Net::HTTP::Patch; prepend InnocuousCapitalize; end
12
+
13
+ class CaseSensitivePut < Net::HTTP::Put; prepend InnocuousCapitalize; end
14
+
15
+ class CaseSensitiveDelete < Net::HTTP::Delete; prepend InnocuousCapitalize; end
16
+
4
17
  refine Net::HTTP do
5
18
  def ssl_connection
6
19
  return {} unless use_ssl? && @socket.present?
7
20
 
8
21
  { version: @socket.io.ssl_version, cipher: @socket.io.cipher[0] }
9
22
  end
23
+
24
+ unless ENV['RUNNING_UNIT_TESTS']
25
+ def post(path, data, initheader = nil, dest = nil, &block)
26
+ send_entity(path, data, initheader, dest, request_type(CaseSensitivePost, Net::HTTP::Post, initheader), &block)
27
+ end
28
+
29
+ def patch(path, data, initheader = nil, dest = nil, &block)
30
+ send_entity(path, data, initheader, dest, request_type(CaseSensitivePatch, Net::HTTP::Patch, initheader), &block)
31
+ end
32
+
33
+ def put(path, data, initheader = nil)
34
+ request(request_type(CaseSensitivePut, Net::HTTP::Put, initheader).new(path, initheader), data)
35
+ end
36
+
37
+ def delete(path, initheader = { 'Depth' => 'Infinity' })
38
+ request(request_type(CaseSensitiveDelete, Net::HTTP::Delete, initheader).new(path, initheader))
39
+ end
40
+
41
+ def request_type(replace, default, initheader)
42
+ initheader.is_a?(ActiveMerchant::PostsData::CaseSensitiveHeaders) ? replace : default
43
+ end
44
+ end
10
45
  end
11
46
  end
@@ -1,5 +1,5 @@
1
- module ActiveMerchant #:nodoc:
2
- module PostsData #:nodoc:
1
+ module ActiveMerchant # :nodoc:
2
+ module PostsData # :nodoc:
3
3
  def self.included(base)
4
4
  base.class_attribute :ssl_strict
5
5
  base.ssl_strict = true
@@ -30,6 +30,8 @@ module ActiveMerchant #:nodoc:
30
30
 
31
31
  base.class_attribute :proxy_address
32
32
  base.class_attribute :proxy_port
33
+ base.class_attribute :proxy_user
34
+ base.class_attribute :proxy_password
33
35
  end
34
36
 
35
37
  def ssl_get(endpoint, headers = {})
@@ -68,8 +70,10 @@ module ActiveMerchant #:nodoc:
68
70
 
69
71
  connection.ignore_http_status = @options[:ignore_http_status] if @options
70
72
 
71
- connection.proxy_address = proxy_address
72
- connection.proxy_port = proxy_port
73
+ connection.proxy_address = proxy_address
74
+ connection.proxy_port = proxy_port
75
+ connection.proxy_user = proxy_user
76
+ connection.proxy_password = proxy_password
73
77
 
74
78
  connection.request(method, data, headers)
75
79
  end
@@ -88,5 +92,16 @@ module ActiveMerchant #:nodoc:
88
92
  raise ResponseError.new(response)
89
93
  end
90
94
  end
95
+
96
+ # This class is needed to play along with the Refinement done for Net::HTTP
97
+ # class so it can have a way to detect if the hash that represent the headers
98
+ # should use the case sensitive version of the headers or not.
99
+ class CaseSensitiveHeaders < Hash
100
+ def dup
101
+ case_sensitive_dup = self.class.new
102
+ each { |key, value| case_sensitive_dup[key] = value }
103
+ case_sensitive_dup
104
+ end
105
+ end
91
106
  end
92
107
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveMerchant
2
- VERSION = '1.133.0'
2
+ VERSION = '1.138.0'
3
3
  end
@@ -0,0 +1,29 @@
1
+ module ActiveMerchant
2
+ module Versionable
3
+ def self.included(base)
4
+ if base.respond_to?(:class_attribute)
5
+ base.class_attribute :versions, default: {}
6
+ base.extend(ClassMethods)
7
+ end
8
+ end
9
+
10
+ module ClassMethods
11
+ def inherited(subclass)
12
+ super
13
+ subclass.versions = {}
14
+ end
15
+
16
+ def version(version, feature = :default_api)
17
+ versions[feature] = version
18
+ end
19
+
20
+ def fetch_version(feature = :default_api)
21
+ versions[feature]
22
+ end
23
+ end
24
+
25
+ def fetch_version(feature = :default_api)
26
+ versions[feature]
27
+ end
28
+ end
29
+ end