swiss-crm-activemerchant 1.0.12

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 (287) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +4033 -0
  3. data/CONTRIBUTORS +568 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +252 -0
  6. data/lib/active_merchant/billing/apple_pay_payment_token.rb +22 -0
  7. data/lib/active_merchant/billing/avs_result.rb +95 -0
  8. data/lib/active_merchant/billing/base.rb +48 -0
  9. data/lib/active_merchant/billing/check.rb +112 -0
  10. data/lib/active_merchant/billing/compatibility.rb +118 -0
  11. data/lib/active_merchant/billing/credit_card.rb +451 -0
  12. data/lib/active_merchant/billing/credit_card_formatting.rb +24 -0
  13. data/lib/active_merchant/billing/credit_card_methods.rb +512 -0
  14. data/lib/active_merchant/billing/cvv_result.rb +37 -0
  15. data/lib/active_merchant/billing/gateway.rb +332 -0
  16. data/lib/active_merchant/billing/gateways/adyen.rb +774 -0
  17. data/lib/active_merchant/billing/gateways/airwallex.rb +370 -0
  18. data/lib/active_merchant/billing/gateways/alelo.rb +256 -0
  19. data/lib/active_merchant/billing/gateways/allied_wallet.rb +205 -0
  20. data/lib/active_merchant/billing/gateways/authorize_net.rb +1125 -0
  21. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +424 -0
  22. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +977 -0
  23. data/lib/active_merchant/billing/gateways/axcessms.rb +242 -0
  24. data/lib/active_merchant/billing/gateways/balanced.rb +263 -0
  25. data/lib/active_merchant/billing/gateways/bambora_apac.rb +222 -0
  26. data/lib/active_merchant/billing/gateways/bank_frick.rb +225 -0
  27. data/lib/active_merchant/billing/gateways/banwire.rb +116 -0
  28. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +397 -0
  29. data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +15 -0
  30. data/lib/active_merchant/billing/gateways/be2bill.rb +131 -0
  31. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +474 -0
  32. data/lib/active_merchant/billing/gateways/beanstream.rb +238 -0
  33. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +57 -0
  34. data/lib/active_merchant/billing/gateways/blue_pay.rb +549 -0
  35. data/lib/active_merchant/billing/gateways/blue_snap.rb +644 -0
  36. data/lib/active_merchant/billing/gateways/bogus.rb +190 -0
  37. data/lib/active_merchant/billing/gateways/borgun.rb +272 -0
  38. data/lib/active_merchant/billing/gateways/bpoint.rb +277 -0
  39. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +28 -0
  40. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +113 -0
  41. data/lib/active_merchant/billing/gateways/braintree.rb +19 -0
  42. data/lib/active_merchant/billing/gateways/braintree_blue.rb +952 -0
  43. data/lib/active_merchant/billing/gateways/braintree_orange.rb +19 -0
  44. data/lib/active_merchant/billing/gateways/bridge_pay.rb +244 -0
  45. data/lib/active_merchant/billing/gateways/cams.rb +230 -0
  46. data/lib/active_merchant/billing/gateways/card_connect.rb +338 -0
  47. data/lib/active_merchant/billing/gateways/card_save.rb +21 -0
  48. data/lib/active_merchant/billing/gateways/card_stream.rb +394 -0
  49. data/lib/active_merchant/billing/gateways/cardknox.rb +327 -0
  50. data/lib/active_merchant/billing/gateways/cardprocess.rb +256 -0
  51. data/lib/active_merchant/billing/gateways/cashnet.rb +235 -0
  52. data/lib/active_merchant/billing/gateways/cc5.rb +198 -0
  53. data/lib/active_merchant/billing/gateways/cecabank.rb +249 -0
  54. data/lib/active_merchant/billing/gateways/cenpos.rb +328 -0
  55. data/lib/active_merchant/billing/gateways/checkout.rb +212 -0
  56. data/lib/active_merchant/billing/gateways/checkout_v2.rb +587 -0
  57. data/lib/active_merchant/billing/gateways/citrus_pay.rb +21 -0
  58. data/lib/active_merchant/billing/gateways/clearhaus.rb +219 -0
  59. data/lib/active_merchant/billing/gateways/commerce_hub.rb +366 -0
  60. data/lib/active_merchant/billing/gateways/commercegate.rb +142 -0
  61. data/lib/active_merchant/billing/gateways/conekta.rb +230 -0
  62. data/lib/active_merchant/billing/gateways/creditcall.rb +272 -0
  63. data/lib/active_merchant/billing/gateways/credorax.rb +526 -0
  64. data/lib/active_merchant/billing/gateways/ct_payment.rb +269 -0
  65. data/lib/active_merchant/billing/gateways/culqi.rb +279 -0
  66. data/lib/active_merchant/billing/gateways/cyber_source/cyber_source_common.rb +36 -0
  67. data/lib/active_merchant/billing/gateways/cyber_source.rb +1148 -0
  68. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +454 -0
  69. data/lib/active_merchant/billing/gateways/d_local.rb +343 -0
  70. data/lib/active_merchant/billing/gateways/data_cash.rb +302 -0
  71. data/lib/active_merchant/billing/gateways/decidir.rb +358 -0
  72. data/lib/active_merchant/billing/gateways/decidir_plus.rb +344 -0
  73. data/lib/active_merchant/billing/gateways/dibs.rb +199 -0
  74. data/lib/active_merchant/billing/gateways/digitzs.rb +295 -0
  75. data/lib/active_merchant/billing/gateways/ebanx.rb +346 -0
  76. data/lib/active_merchant/billing/gateways/efsnet.rb +215 -0
  77. data/lib/active_merchant/billing/gateways/elavon.rb +475 -0
  78. data/lib/active_merchant/billing/gateways/element.rb +406 -0
  79. data/lib/active_merchant/billing/gateways/epay.rb +296 -0
  80. data/lib/active_merchant/billing/gateways/evo_ca.rb +307 -0
  81. data/lib/active_merchant/billing/gateways/eway.rb +226 -0
  82. data/lib/active_merchant/billing/gateways/eway_managed.rb +289 -0
  83. data/lib/active_merchant/billing/gateways/eway_rapid.rb +578 -0
  84. data/lib/active_merchant/billing/gateways/exact.rb +219 -0
  85. data/lib/active_merchant/billing/gateways/ezic.rb +195 -0
  86. data/lib/active_merchant/billing/gateways/fat_zebra.rb +223 -0
  87. data/lib/active_merchant/billing/gateways/federated_canada.rb +158 -0
  88. data/lib/active_merchant/billing/gateways/finansbank.rb +22 -0
  89. data/lib/active_merchant/billing/gateways/first_giving.rb +143 -0
  90. data/lib/active_merchant/billing/gateways/first_pay.rb +182 -0
  91. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +452 -0
  92. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +505 -0
  93. data/lib/active_merchant/billing/gateways/flo2cash.rb +215 -0
  94. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +20 -0
  95. data/lib/active_merchant/billing/gateways/fluidpay.rb +275 -0
  96. data/lib/active_merchant/billing/gateways/forte.rb +286 -0
  97. data/lib/active_merchant/billing/gateways/garanti.rb +256 -0
  98. data/lib/active_merchant/billing/gateways/global_collect.rb +580 -0
  99. data/lib/active_merchant/billing/gateways/global_transport.rb +193 -0
  100. data/lib/active_merchant/billing/gateways/hdfc.rb +205 -0
  101. data/lib/active_merchant/billing/gateways/hps.rb +472 -0
  102. data/lib/active_merchant/billing/gateways/iats_payments.rb +312 -0
  103. data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +15 -0
  104. data/lib/active_merchant/billing/gateways/inspire.rb +213 -0
  105. data/lib/active_merchant/billing/gateways/instapay.rb +159 -0
  106. data/lib/active_merchant/billing/gateways/ipg.rb +420 -0
  107. data/lib/active_merchant/billing/gateways/ipp.rb +176 -0
  108. data/lib/active_merchant/billing/gateways/iridium.rb +467 -0
  109. data/lib/active_merchant/billing/gateways/itransact.rb +448 -0
  110. data/lib/active_merchant/billing/gateways/iveri.rb +290 -0
  111. data/lib/active_merchant/billing/gateways/ixopay.rb +320 -0
  112. data/lib/active_merchant/billing/gateways/jetpay.rb +395 -0
  113. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +432 -0
  114. data/lib/active_merchant/billing/gateways/klarna.rb +317 -0
  115. data/lib/active_merchant/billing/gateways/komoju.rb +115 -0
  116. data/lib/active_merchant/billing/gateways/kushki.rb +297 -0
  117. data/lib/active_merchant/billing/gateways/latitude19.rb +412 -0
  118. data/lib/active_merchant/billing/gateways/linkpoint.rb +448 -0
  119. data/lib/active_merchant/billing/gateways/litle.rb +643 -0
  120. data/lib/active_merchant/billing/gateways/mastercard.rb +286 -0
  121. data/lib/active_merchant/billing/gateways/maxipago.rb +220 -0
  122. data/lib/active_merchant/billing/gateways/mercado_pago.rb +348 -0
  123. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +228 -0
  124. data/lib/active_merchant/billing/gateways/merchant_one.rb +110 -0
  125. data/lib/active_merchant/billing/gateways/merchant_partners.rb +245 -0
  126. data/lib/active_merchant/billing/gateways/merchant_ware.rb +313 -0
  127. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +284 -0
  128. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +248 -0
  129. data/lib/active_merchant/billing/gateways/mercury.rb +352 -0
  130. data/lib/active_merchant/billing/gateways/metrics_global.rb +293 -0
  131. data/lib/active_merchant/billing/gateways/micropayment.rb +182 -0
  132. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
  133. data/lib/active_merchant/billing/gateways/migs.rb +329 -0
  134. data/lib/active_merchant/billing/gateways/mit.rb +260 -0
  135. data/lib/active_merchant/billing/gateways/modern_payments.rb +37 -0
  136. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +215 -0
  137. data/lib/active_merchant/billing/gateways/moka.rb +290 -0
  138. data/lib/active_merchant/billing/gateways/monei.rb +424 -0
  139. data/lib/active_merchant/billing/gateways/moneris.rb +488 -0
  140. data/lib/active_merchant/billing/gateways/money_movers.rb +150 -0
  141. data/lib/active_merchant/billing/gateways/mundipagg.rb +366 -0
  142. data/lib/active_merchant/billing/gateways/nab_transact.rb +299 -0
  143. data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +163 -0
  144. data/lib/active_merchant/billing/gateways/net_registry.rb +198 -0
  145. data/lib/active_merchant/billing/gateways/netaxept.rb +180 -0
  146. data/lib/active_merchant/billing/gateways/netbanx.rb +376 -0
  147. data/lib/active_merchant/billing/gateways/netbilling.rb +229 -0
  148. data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
  149. data/lib/active_merchant/billing/gateways/network_merchants.rb +238 -0
  150. data/lib/active_merchant/billing/gateways/nmi.rb +396 -0
  151. data/lib/active_merchant/billing/gateways/ogone.rb +509 -0
  152. data/lib/active_merchant/billing/gateways/omise.rb +323 -0
  153. data/lib/active_merchant/billing/gateways/openpay.rb +246 -0
  154. data/lib/active_merchant/billing/gateways/opp.rb +394 -0
  155. data/lib/active_merchant/billing/gateways/optimal_payment.rb +331 -0
  156. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +45 -0
  157. data/lib/active_merchant/billing/gateways/orbital.rb +1267 -0
  158. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +206 -0
  159. data/lib/active_merchant/billing/gateways/pagarme.rb +239 -0
  160. data/lib/active_merchant/billing/gateways/pago_facil.rb +120 -0
  161. data/lib/active_merchant/billing/gateways/pay_arc.rb +392 -0
  162. data/lib/active_merchant/billing/gateways/pay_conex.rb +245 -0
  163. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +277 -0
  164. data/lib/active_merchant/billing/gateways/pay_hub.rb +213 -0
  165. data/lib/active_merchant/billing/gateways/pay_junction.rb +390 -0
  166. data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +206 -0
  167. data/lib/active_merchant/billing/gateways/pay_secure.rb +110 -0
  168. data/lib/active_merchant/billing/gateways/pay_trace.rb +450 -0
  169. data/lib/active_merchant/billing/gateways/paybox_direct.rb +224 -0
  170. data/lib/active_merchant/billing/gateways/payeezy.rb +513 -0
  171. data/lib/active_merchant/billing/gateways/payex.rb +409 -0
  172. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +235 -0
  173. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +42 -0
  174. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  175. data/lib/active_merchant/billing/gateways/payflow.rb +473 -0
  176. data/lib/active_merchant/billing/gateways/payflow_express.rb +220 -0
  177. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +14 -0
  178. data/lib/active_merchant/billing/gateways/payflow_uk.rb +20 -0
  179. data/lib/active_merchant/billing/gateways/payment_express.rb +373 -0
  180. data/lib/active_merchant/billing/gateways/paymentez.rb +365 -0
  181. data/lib/active_merchant/billing/gateways/paymill.rb +369 -0
  182. data/lib/active_merchant/billing/gateways/paynetworx.rb +228 -0
  183. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +718 -0
  184. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +69 -0
  185. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +262 -0
  186. data/lib/active_merchant/billing/gateways/paypal.rb +136 -0
  187. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  188. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +44 -0
  189. data/lib/active_merchant/billing/gateways/paypal_express.rb +272 -0
  190. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +30 -0
  191. data/lib/active_merchant/billing/gateways/paypal_standard.rb +281 -0
  192. data/lib/active_merchant/billing/gateways/paysafe.rb +420 -0
  193. data/lib/active_merchant/billing/gateways/payscout.rb +159 -0
  194. data/lib/active_merchant/billing/gateways/paystation.rb +204 -0
  195. data/lib/active_merchant/billing/gateways/payu_in.rb +249 -0
  196. data/lib/active_merchant/billing/gateways/payu_latam.rb +482 -0
  197. data/lib/active_merchant/billing/gateways/payway.rb +207 -0
  198. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +253 -0
  199. data/lib/active_merchant/billing/gateways/pin.rb +273 -0
  200. data/lib/active_merchant/billing/gateways/pixxels.rb +263 -0
  201. data/lib/active_merchant/billing/gateways/plexo.rb +308 -0
  202. data/lib/active_merchant/billing/gateways/plugnpay.rb +283 -0
  203. data/lib/active_merchant/billing/gateways/priority.rb +392 -0
  204. data/lib/active_merchant/billing/gateways/pro_pay.rb +325 -0
  205. data/lib/active_merchant/billing/gateways/psigate.rb +227 -0
  206. data/lib/active_merchant/billing/gateways/psl_card.rb +295 -0
  207. data/lib/active_merchant/billing/gateways/qbms.rb +302 -0
  208. data/lib/active_merchant/billing/gateways/quantum.rb +274 -0
  209. data/lib/active_merchant/billing/gateways/quickbooks.rb +377 -0
  210. data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +184 -0
  211. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +297 -0
  212. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +226 -0
  213. data/lib/active_merchant/billing/gateways/quickpay.rb +24 -0
  214. data/lib/active_merchant/billing/gateways/qvalent.rb +305 -0
  215. data/lib/active_merchant/billing/gateways/rapyd.rb +319 -0
  216. data/lib/active_merchant/billing/gateways/reach.rb +277 -0
  217. data/lib/active_merchant/billing/gateways/realex.rb +400 -0
  218. data/lib/active_merchant/billing/gateways/redsys.rb +723 -0
  219. data/lib/active_merchant/billing/gateways/s5.rb +247 -0
  220. data/lib/active_merchant/billing/gateways/safe_charge.rb +298 -0
  221. data/lib/active_merchant/billing/gateways/sage.rb +446 -0
  222. data/lib/active_merchant/billing/gateways/sage_pay.rb +434 -0
  223. data/lib/active_merchant/billing/gateways/sallie_mae.rb +141 -0
  224. data/lib/active_merchant/billing/gateways/secure_net.rb +260 -0
  225. data/lib/active_merchant/billing/gateways/secure_pay.rb +191 -0
  226. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +290 -0
  227. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +103 -0
  228. data/lib/active_merchant/billing/gateways/securion_pay.rb +305 -0
  229. data/lib/active_merchant/billing/gateways/shift4.rb +345 -0
  230. data/lib/active_merchant/billing/gateways/simetrik.rb +368 -0
  231. data/lib/active_merchant/billing/gateways/skip_jack.rb +450 -0
  232. data/lib/active_merchant/billing/gateways/smart_ps.rb +274 -0
  233. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
  234. data/lib/active_merchant/billing/gateways/spreedly_core.rb +354 -0
  235. data/lib/active_merchant/billing/gateways/stripe.rb +866 -0
  236. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +602 -0
  237. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +151 -0
  238. data/lib/active_merchant/billing/gateways/telr.rb +273 -0
  239. data/lib/active_merchant/billing/gateways/tns.rb +23 -0
  240. data/lib/active_merchant/billing/gateways/trans_first.rb +240 -0
  241. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +612 -0
  242. data/lib/active_merchant/billing/gateways/transact_pro.rb +222 -0
  243. data/lib/active_merchant/billing/gateways/transax.rb +21 -0
  244. data/lib/active_merchant/billing/gateways/transnational.rb +9 -0
  245. data/lib/active_merchant/billing/gateways/trexle.rb +221 -0
  246. data/lib/active_merchant/billing/gateways/trust_commerce.rb +500 -0
  247. data/lib/active_merchant/billing/gateways/usa_epay.rb +24 -0
  248. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1612 -0
  249. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +367 -0
  250. data/lib/active_merchant/billing/gateways/vanco.rb +303 -0
  251. data/lib/active_merchant/billing/gateways/verifi.rb +224 -0
  252. data/lib/active_merchant/billing/gateways/viaklix.rb +171 -0
  253. data/lib/active_merchant/billing/gateways/visanet_peru.rb +250 -0
  254. data/lib/active_merchant/billing/gateways/vpos.rb +223 -0
  255. data/lib/active_merchant/billing/gateways/webpay.rb +97 -0
  256. data/lib/active_merchant/billing/gateways/wepay.rb +235 -0
  257. data/lib/active_merchant/billing/gateways/wirecard.rb +430 -0
  258. data/lib/active_merchant/billing/gateways/wompi.rb +197 -0
  259. data/lib/active_merchant/billing/gateways/world_net.rb +345 -0
  260. data/lib/active_merchant/billing/gateways/worldpay.rb +1050 -0
  261. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +208 -0
  262. data/lib/active_merchant/billing/gateways/worldpay_us.rb +221 -0
  263. data/lib/active_merchant/billing/gateways.rb +14 -0
  264. data/lib/active_merchant/billing/model.rb +30 -0
  265. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +39 -0
  266. data/lib/active_merchant/billing/payment_token.rb +21 -0
  267. data/lib/active_merchant/billing/rails.rb +3 -0
  268. data/lib/active_merchant/billing/response.rb +121 -0
  269. data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
  270. data/lib/active_merchant/billing.rb +16 -0
  271. data/lib/active_merchant/connection.rb +194 -0
  272. data/lib/active_merchant/country.rb +338 -0
  273. data/lib/active_merchant/empty.rb +20 -0
  274. data/lib/active_merchant/errors.rb +38 -0
  275. data/lib/active_merchant/net_http_ssl_connection.rb +11 -0
  276. data/lib/active_merchant/network_connection_retries.rb +78 -0
  277. data/lib/active_merchant/post_data.rb +26 -0
  278. data/lib/active_merchant/posts_data.rb +92 -0
  279. data/lib/active_merchant/version.rb +3 -0
  280. data/lib/active_merchant.rb +63 -0
  281. data/lib/activemerchant.rb +1 -0
  282. data/lib/certs/cacert.pem +3214 -0
  283. data/lib/support/gateway_support.rb +69 -0
  284. data/lib/support/outbound_hosts.rb +28 -0
  285. data/lib/support/ssl_verify.rb +88 -0
  286. data/lib/support/ssl_version.rb +86 -0
  287. metadata +506 -0
@@ -0,0 +1,723 @@
1
+ # coding: utf-8
2
+
3
+ require 'nokogiri'
4
+
5
+ module ActiveMerchant #:nodoc:
6
+ module Billing #:nodoc:
7
+ # = Redsys Merchant Gateway
8
+ #
9
+ # Gateway support for the Spanish "Redsys" payment gateway system. This is
10
+ # used by many banks in Spain and is particularly well supported by
11
+ # Catalunya Caixa's ecommerce department.
12
+ #
13
+ # Redsys requires an order_id be provided with each transaction and it must
14
+ # follow a specific format. The rules are as follows:
15
+ #
16
+ # * First 4 digits must be numerical
17
+ # * Remaining 8 digits may be alphanumeric
18
+ # * Max length: 12
19
+ #
20
+ # If an invalid order_id is provided, we do our best to clean it up.
21
+ #
22
+ # Much of the code for this library is based on the active_merchant_sermepa
23
+ # integration gateway which uses essentially the same API but with the
24
+ # banks own payment screen.
25
+ #
26
+ # Written by Samuel Lown for Cabify. For implementation questions, or
27
+ # test access details please get in touch: sam@cabify.com.
28
+ #
29
+ # *** SHA256 Authentication Update ***
30
+ #
31
+ # Redsys is dropping support for the SHA1 authentication method. This
32
+ # adapter has been updated to work with the new SHA256 authentication
33
+ # method, however in your initialization options hash you will need to
34
+ # specify the key/value :signature_algorithm => "sha256" to use the
35
+ # SHA256 method. Otherwise it will default to using the SHA1.
36
+ #
37
+ #
38
+ class RedsysGateway < Gateway
39
+ self.live_url = 'https://sis.redsys.es/sis/operaciones'
40
+ self.test_url = 'https://sis-t.redsys.es:25443/sis/operaciones'
41
+
42
+ self.supported_countries = %w[ES FR GB IT PL PT]
43
+ self.default_currency = 'EUR'
44
+ self.money_format = :cents
45
+
46
+ # Not all card types may be activated by the bank!
47
+ self.supported_cardtypes = %i[visa master american_express jcb diners_club unionpay]
48
+ self.homepage_url = 'http://www.redsys.es/'
49
+ self.display_name = 'Redsys'
50
+
51
+ CURRENCY_CODES = {
52
+ 'AED' => '784',
53
+ 'ARS' => '32',
54
+ 'AUD' => '36',
55
+ 'BRL' => '986',
56
+ 'BOB' => '68',
57
+ 'CAD' => '124',
58
+ 'CHF' => '756',
59
+ 'CLP' => '152',
60
+ 'CNY' => '156',
61
+ 'COP' => '170',
62
+ 'CRC' => '188',
63
+ 'CZK' => '203',
64
+ 'DKK' => '208',
65
+ 'DOP' => '214',
66
+ 'EUR' => '978',
67
+ 'GBP' => '826',
68
+ 'GTQ' => '320',
69
+ 'HUF' => '348',
70
+ 'IDR' => '360',
71
+ 'INR' => '356',
72
+ 'JPY' => '392',
73
+ 'KRW' => '410',
74
+ 'MYR' => '458',
75
+ 'MXN' => '484',
76
+ 'NOK' => '578',
77
+ 'NZD' => '554',
78
+ 'PEN' => '604',
79
+ 'PLN' => '985',
80
+ 'RUB' => '643',
81
+ 'SAR' => '682',
82
+ 'SEK' => '752',
83
+ 'SGD' => '702',
84
+ 'THB' => '764',
85
+ 'TWD' => '901',
86
+ 'USD' => '840',
87
+ 'UYU' => '858'
88
+ }
89
+
90
+ # The set of supported transactions for this gateway.
91
+ # More operations are supported by the gateway itself, but
92
+ # are not supported in this library.
93
+ SUPPORTED_TRANSACTIONS = {
94
+ purchase: '0',
95
+ authorize: '1',
96
+ capture: '2',
97
+ refund: '3',
98
+ cancel: '9'
99
+ }
100
+
101
+ # These are the text meanings sent back by the acquirer when
102
+ # a card has been rejected. Syntax or general request errors
103
+ # are not covered here.
104
+ RESPONSE_TEXTS = {
105
+ 0 => 'Transaction Approved',
106
+ 400 => 'Cancellation Accepted',
107
+ 481 => 'Cancellation Accepted',
108
+ 500 => 'Reconciliation Accepted',
109
+ 900 => 'Refund / Confirmation approved',
110
+
111
+ 101 => 'Card expired',
112
+ 102 => 'Card blocked temporarily or under susciption of fraud',
113
+ 104 => 'Transaction not permitted',
114
+ 107 => 'Contact the card issuer',
115
+ 109 => 'Invalid identification by merchant or POS terminal',
116
+ 110 => 'Invalid amount',
117
+ 114 => 'Card cannot be used to the requested transaction',
118
+ 116 => 'Insufficient credit',
119
+ 118 => 'Non-registered card',
120
+ 125 => 'Card not effective',
121
+ 129 => 'CVV2/CVC2 Error',
122
+ 167 => 'Contact the card issuer: suspected fraud',
123
+ 180 => 'Card out of service',
124
+ 181 => 'Card with credit or debit restrictions',
125
+ 182 => 'Card with credit or debit restrictions',
126
+ 184 => 'Authentication error',
127
+ 190 => 'Refusal with no specific reason',
128
+ 191 => 'Expiry date incorrect',
129
+ 195 => 'Requires SCA authentication',
130
+
131
+ 201 => 'Card expired',
132
+ 202 => 'Card blocked temporarily or under suspicion of fraud',
133
+ 204 => 'Transaction not permitted',
134
+ 207 => 'Contact the card issuer',
135
+ 208 => 'Lost or stolen card',
136
+ 209 => 'Lost or stolen card',
137
+ 280 => 'CVV2/CVC2 Error',
138
+ 290 => 'Declined with no specific reason',
139
+
140
+ 480 => 'Original transaction not located, or time-out exceeded',
141
+ 501 => 'Original transaction not located, or time-out exceeded',
142
+ 502 => 'Original transaction not located, or time-out exceeded',
143
+ 503 => 'Original transaction not located, or time-out exceeded',
144
+
145
+ 904 => 'Merchant not registered at FUC',
146
+ 909 => 'System error',
147
+ 912 => 'Issuer not available',
148
+ 913 => 'Duplicate transmission',
149
+ 916 => 'Amount too low',
150
+ 928 => 'Time-out exceeded',
151
+ 940 => 'Transaction cancelled previously',
152
+ 941 => 'Authorization operation already cancelled',
153
+ 942 => 'Original authorization declined',
154
+ 943 => 'Different details from origin transaction',
155
+ 944 => 'Session error',
156
+ 945 => 'Duplicate transmission',
157
+ 946 => 'Cancellation of transaction while in progress',
158
+ 947 => 'Duplicate tranmission while in progress',
159
+ 949 => 'POS Inoperative',
160
+ 950 => 'Refund not possible',
161
+ 9064 => 'Card number incorrect',
162
+ 9078 => 'No payment method available',
163
+ 9093 => 'Non-existent card',
164
+ 9218 => 'Recursive transaction in bad gateway',
165
+ 9253 => 'Check-digit incorrect',
166
+ 9256 => 'Preauth not allowed for merchant',
167
+ 9257 => 'Preauth not allowed for card',
168
+ 9261 => 'Operating limit exceeded',
169
+ 9912 => 'Issuer not available',
170
+ 9913 => 'Confirmation error',
171
+ 9914 => 'KO Confirmation'
172
+ }
173
+
174
+ # Expected values as per documentation
175
+ THREE_DS_V1 = '1.0.2'
176
+ THREE_DS_V2 = '2.1.0'
177
+
178
+ # Creates a new instance
179
+ #
180
+ # Redsys requires a login and secret_key, and optionally also accepts a
181
+ # non-default terminal.
182
+ #
183
+ # ==== Options
184
+ #
185
+ # * <tt>:login</tt> -- The Redsys Merchant ID (REQUIRED)
186
+ # * <tt>:secret_key</tt> -- The Redsys Secret Key. (REQUIRED)
187
+ # * <tt>:terminal</tt> -- The Redsys Terminal. Defaults to 1. (OPTIONAL)
188
+ # * <tt>:test</tt> -- +true+ or +false+. Defaults to +false+. (OPTIONAL)
189
+ # * <tt>:signature_algorithm</tt> -- +"sha256"+ Defaults to +"sha1"+. (OPTIONAL)
190
+ def initialize(options = {})
191
+ requires!(options, :login, :secret_key)
192
+ options[:terminal] ||= 1
193
+ options[:signature_algorithm] ||= 'sha1'
194
+ super
195
+ end
196
+
197
+ def purchase(money, payment, options = {})
198
+ requires!(options, :order_id)
199
+
200
+ data = {}
201
+ add_action(data, :purchase, options)
202
+ add_amount(data, money, options)
203
+ add_order(data, options[:order_id])
204
+ add_payment(data, payment)
205
+ add_external_mpi_fields(data, options)
206
+ add_three_ds_data(data, options) if options[:execute_threed]
207
+ add_stored_credential_options(data, options)
208
+ data[:description] = options[:description]
209
+ data[:store_in_vault] = options[:store]
210
+ data[:sca_exemption] = options[:sca_exemption]
211
+ data[:sca_exemption_direct_payment_enabled] = options[:sca_exemption_direct_payment_enabled]
212
+
213
+ commit data, options
214
+ end
215
+
216
+ def authorize(money, payment, options = {})
217
+ requires!(options, :order_id)
218
+
219
+ data = {}
220
+ add_action(data, :authorize, options)
221
+ add_amount(data, money, options)
222
+ add_order(data, options[:order_id])
223
+ add_payment(data, payment)
224
+ add_external_mpi_fields(data, options)
225
+ add_three_ds_data(data, options) if options[:execute_threed]
226
+ add_stored_credential_options(data, options)
227
+ data[:description] = options[:description]
228
+ data[:store_in_vault] = options[:store]
229
+ data[:sca_exemption] = options[:sca_exemption]
230
+ data[:sca_exemption_direct_payment_enabled] = options[:sca_exemption_direct_payment_enabled]
231
+
232
+ commit data, options
233
+ end
234
+
235
+ def capture(money, authorization, options = {})
236
+ data = {}
237
+ add_action(data, :capture)
238
+ add_amount(data, money, options)
239
+ order_id, = split_authorization(authorization)
240
+ add_order(data, order_id)
241
+ data[:description] = options[:description]
242
+
243
+ commit data, options
244
+ end
245
+
246
+ def void(authorization, options = {})
247
+ data = {}
248
+ add_action(data, :cancel)
249
+ order_id, amount, currency = split_authorization(authorization)
250
+ add_amount(data, amount, currency: currency)
251
+ add_order(data, order_id)
252
+ data[:description] = options[:description]
253
+
254
+ commit data, options
255
+ end
256
+
257
+ def refund(money, authorization, options = {})
258
+ data = {}
259
+ add_action(data, :refund)
260
+ add_amount(data, money, options)
261
+ order_id, = split_authorization(authorization)
262
+ add_order(data, order_id)
263
+ data[:description] = options[:description]
264
+
265
+ commit data, options
266
+ end
267
+
268
+ def verify(creditcard, options = {})
269
+ if options[:sca_exemption_behavior_override] == 'endpoint_and_ntid'
270
+ purchase(0, creditcard, options)
271
+ else
272
+ MultiResponse.run(:use_first_response) do |r|
273
+ r.process { authorize(100, creditcard, options) }
274
+ r.process(:ignore_result) { void(r.authorization, options) }
275
+ end
276
+ end
277
+ end
278
+
279
+ def supports_scrubbing
280
+ true
281
+ end
282
+
283
+ def scrub(transcript)
284
+ transcript.
285
+ gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
286
+ gsub(%r((%3CDS_MERCHANT_PAN%3E)\d+(%3C%2FDS_MERCHANT_PAN%3E))i, '\1[FILTERED]\2').
287
+ gsub(%r((%3CDS_MERCHANT_CVV2%3E)\d+(%3C%2FDS_MERCHANT_CVV2%3E))i, '\1[FILTERED]\2').
288
+ gsub(%r((&lt;DS_MERCHANT_PAN&gt;)\d+(&lt;/DS_MERCHANT_PAN&gt;))i, '\1[FILTERED]\2').
289
+ gsub(%r((<DS_MERCHANT_PAN>)\d+(</DS_MERCHANT_PAN>))i, '\1[FILTERED]\2').
290
+ gsub(%r((<DS_MERCHANT_CVV2>)\d+(</DS_MERCHANT_CVV2>))i, '\1[FILTERED]\2').
291
+ gsub(%r((&lt;DS_MERCHANT_CVV2&gt;)\d+(&lt;/DS_MERCHANT_CVV2&gt;))i, '\1[FILTERED]\2').
292
+ gsub(%r((DS_MERCHANT_CVV2)%2F%3E%0A%3C%2F)i, '\1[BLANK]').
293
+ gsub(%r((DS_MERCHANT_CVV2)%2F%3E%3C)i, '\1[BLANK]').
294
+ gsub(%r((DS_MERCHANT_CVV2%3E)(%3C%2FDS_MERCHANT_CVV2))i, '\1[BLANK]\2').
295
+ gsub(%r((<DS_MERCHANT_CVV2>)(</DS_MERCHANT_CVV2>))i, '\1[BLANK]\2').
296
+ gsub(%r((DS_MERCHANT_CVV2%3E)\++(%3C%2FDS_MERCHANT_CVV2))i, '\1[BLANK]\2').
297
+ gsub(%r((<DS_MERCHANT_CVV2>)\s+(</DS_MERCHANT_CVV2>))i, '\1[BLANK]\2')
298
+ end
299
+
300
+ private
301
+
302
+ def add_action(data, action, options = {})
303
+ data[:action] = options[:execute_threed].present? ? '0' : transaction_code(action)
304
+ end
305
+
306
+ def add_amount(data, money, options)
307
+ data[:amount] = amount(money).to_s
308
+ data[:currency] = currency_code(options[:currency] || currency(money))
309
+ end
310
+
311
+ def add_order(data, order_id)
312
+ data[:order_id] = clean_order_id(order_id)
313
+ end
314
+
315
+ def url
316
+ test? ? test_url : live_url
317
+ end
318
+
319
+ def webservice_url
320
+ test? ? 'https://sis-t.redsys.es:25443/sis/services/SerClsWSEntradaV2' : 'https://sis.redsys.es/sis/services/SerClsWSEntradaV2'
321
+ end
322
+
323
+ def add_payment(data, card)
324
+ if card.is_a?(String)
325
+ data[:credit_card_token] = card
326
+ else
327
+ name = [card.first_name, card.last_name].join(' ').slice(0, 60)
328
+ year = sprintf('%.4i', card.year)
329
+ month = sprintf('%.2i', card.month)
330
+ data[:card] = {
331
+ name: name,
332
+ pan: card.number,
333
+ date: "#{year[2..3]}#{month}",
334
+ cvv: card.verification_value
335
+ }
336
+ end
337
+ end
338
+
339
+ def add_external_mpi_fields(data, options)
340
+ return unless options[:three_d_secure]
341
+
342
+ if options[:three_d_secure][:version] == THREE_DS_V2
343
+ data[:threeDSServerTransID] = options[:three_d_secure][:three_ds_server_trans_id] if options[:three_d_secure][:three_ds_server_trans_id]
344
+ data[:dsTransID] = options[:three_d_secure][:ds_transaction_id] if options[:three_d_secure][:ds_transaction_id]
345
+ data[:authenticacionValue] = options[:three_d_secure][:cavv] if options[:three_d_secure][:cavv]
346
+ data[:protocolVersion] = options[:three_d_secure][:version] if options[:three_d_secure][:version]
347
+ data[:authenticacionMethod] = options[:authentication_method] if options[:authentication_method]
348
+ data[:authenticacionType] = options[:authentication_type] if options[:authentication_type]
349
+ data[:authenticacionFlow] = options[:authentication_flow] if options[:authentication_flow]
350
+ data[:eci_v2] = options[:three_d_secure][:eci] if options[:three_d_secure][:eci]
351
+ elsif options[:three_d_secure][:version] == THREE_DS_V1
352
+ data[:txid] = options[:three_d_secure][:xid] if options[:three_d_secure][:xid]
353
+ data[:cavv] = options[:three_d_secure][:cavv] if options[:three_d_secure][:cavv]
354
+ data[:eci_v1] = options[:three_d_secure][:eci] if options[:three_d_secure][:eci]
355
+ end
356
+ end
357
+
358
+ def add_stored_credential_options(data, options)
359
+ return unless options[:stored_credential]
360
+
361
+ case options[:stored_credential][:initial_transaction]
362
+ when true
363
+ data[:DS_MERCHANT_COF_INI] = 'S'
364
+ when false
365
+ data[:DS_MERCHANT_COF_INI] = 'N'
366
+ data[:DS_MERCHANT_COF_TXNID] = options[:stored_credential][:network_transaction_id] if options[:stored_credential][:network_transaction_id]
367
+ end
368
+
369
+ case options[:stored_credential][:reason_type]
370
+ when 'recurring'
371
+ data[:DS_MERCHANT_COF_TYPE] = 'R'
372
+ when 'installment'
373
+ data[:DS_MERCHANT_COF_TYPE] = 'I'
374
+ when 'unscheduled'
375
+ return
376
+ end
377
+ end
378
+
379
+ def add_three_ds_data(data, options)
380
+ data[:three_ds_data] = { threeDSInfo: 'CardData' } if options[:execute_threed] == true
381
+ end
382
+
383
+ def determine_peticion_type(data)
384
+ three_ds_info = data.dig(:three_ds_data, :threeDSInfo)
385
+ return 'iniciaPeticion' if three_ds_info == 'CardData'
386
+ return 'trataPeticion' if three_ds_info == 'AuthenticationData' ||
387
+ three_ds_info == 'ChallengeResponse' ||
388
+ data[:sca_exemption] == 'MIT'
389
+ end
390
+
391
+ def use_webservice_endpoint?(data, options)
392
+ options[:use_webservice_endpoint].to_s == 'true' || data[:three_ds_data] || data[:sca_exemption] == 'MIT'
393
+ end
394
+
395
+ def commit(data, options = {})
396
+ xmlreq = xml_request_from(data, options)
397
+
398
+ if use_webservice_endpoint?(data, options)
399
+ peticion_type = determine_peticion_type(data)
400
+
401
+ request = <<-REQUEST
402
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://webservice.sis.sermepa.es" xmlns:intf="http://webservice.sis.sermepa.es" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
403
+ <soapenv:Header/>
404
+ <soapenv:Body>
405
+ <intf:#{peticion_type} xmlns:intf="http://webservice.sis.sermepa.es">
406
+ <intf:datoEntrada>
407
+ <![CDATA[#{xmlreq}]]>
408
+ </intf:datoEntrada>
409
+ </intf:#{peticion_type}>
410
+ </soapenv:Body>
411
+ </soapenv:Envelope>
412
+ REQUEST
413
+ parse(ssl_post(webservice_url, request, headers(peticion_type)), peticion_type)
414
+ else
415
+ parse(ssl_post(url, "entrada=#{CGI.escape(xmlreq)}", headers), peticion_type)
416
+ end
417
+ end
418
+
419
+ def headers(peticion_type = nil)
420
+ if peticion_type
421
+ {
422
+ 'Content-Type' => 'text/xml',
423
+ 'SOAPAction' => peticion_type
424
+ }
425
+ else
426
+ {
427
+ 'Content-Type' => 'application/x-www-form-urlencoded'
428
+ }
429
+ end
430
+ end
431
+
432
+ def xml_request_from(data, options = {})
433
+ if sha256_authentication?
434
+ build_sha256_xml_request(data, options)
435
+ else
436
+ build_sha1_xml_request(data, options)
437
+ end
438
+ end
439
+
440
+ def build_signature(data)
441
+ str = data[:amount] +
442
+ data[:order_id].to_s +
443
+ @options[:login].to_s +
444
+ data[:currency]
445
+
446
+ if card = data[:card]
447
+ str << card[:pan]
448
+ str << card[:cvv] if card[:cvv]
449
+ end
450
+
451
+ str << data[:action]
452
+ if data[:store_in_vault]
453
+ str << 'REQUIRED'
454
+ elsif data[:credit_card_token]
455
+ str << data[:credit_card_token]
456
+ end
457
+ str << @options[:secret_key]
458
+
459
+ Digest::SHA1.hexdigest(str)
460
+ end
461
+
462
+ def build_sha256_xml_request(data, options = {})
463
+ xml = Builder::XmlMarkup.new
464
+ xml.instruct!
465
+ xml.REQUEST do
466
+ build_merchant_data(xml, data, options)
467
+ xml.DS_SIGNATUREVERSION 'HMAC_SHA256_V1'
468
+ xml.DS_SIGNATURE sign_request(merchant_data_xml(data, options), data[:order_id])
469
+ end
470
+ xml.target!
471
+ end
472
+
473
+ def build_sha1_xml_request(data, options = {})
474
+ xml = Builder::XmlMarkup.new indent: 2
475
+ build_merchant_data(xml, data, options)
476
+ xml.target!
477
+ end
478
+
479
+ def merchant_data_xml(data, options = {})
480
+ xml = Builder::XmlMarkup.new
481
+ build_merchant_data(xml, data, options)
482
+ xml.target!
483
+ end
484
+
485
+ def build_merchant_data(xml, data, options = {})
486
+ # See https://sis-t.redsys.es:25443/sis/services/SerClsWSEntradaV2/wsdl/SerClsWSEntradaV2.wsdl
487
+ # (which results from calling #webservice_url + '?WSDL', https://sis-t.redsys.es:25443/sis/services/SerClsWSEntradaV2?WSDL)
488
+ xml.DATOSENTRADA do
489
+ # Basic elements
490
+ xml.DS_Version 0.1
491
+ xml.DS_MERCHANT_CURRENCY data[:currency]
492
+ xml.DS_MERCHANT_AMOUNT data[:amount]
493
+ xml.DS_MERCHANT_ORDER data[:order_id]
494
+ xml.DS_MERCHANT_TRANSACTIONTYPE data[:action]
495
+ if data[:description] && use_webservice_endpoint?(data, options)
496
+ xml.DS_MERCHANT_PRODUCTDESCRIPTION CGI.escape(data[:description])
497
+ else
498
+ xml.DS_MERCHANT_PRODUCTDESCRIPTION data[:description]
499
+ end
500
+ xml.DS_MERCHANT_TERMINAL options[:terminal] || @options[:terminal]
501
+ xml.DS_MERCHANT_MERCHANTCODE @options[:login]
502
+ xml.DS_MERCHANT_MERCHANTSIGNATURE build_signature(data) unless sha256_authentication?
503
+
504
+ peticion_type = determine_peticion_type(data) if data[:three_ds_data]
505
+ if peticion_type == 'iniciaPeticion' && data[:sca_exemption]
506
+ xml.DS_MERCHANT_EXCEP_SCA 'Y'
507
+ else
508
+ xml.DS_MERCHANT_EXCEP_SCA data[:sca_exemption] if data[:sca_exemption]
509
+ xml.DS_MERCHANT_DIRECTPAYMENT data[:sca_exemption_direct_payment_enabled] || 'true' if data[:sca_exemption] == 'MIT'
510
+ end
511
+
512
+ # Only when card is present
513
+ if data[:card]
514
+ if data[:card][:name] && use_webservice_endpoint?(data, options)
515
+ xml.DS_MERCHANT_TITULAR CGI.escape(data[:card][:name])
516
+ else
517
+ xml.DS_MERCHANT_TITULAR data[:card][:name]
518
+ end
519
+ xml.DS_MERCHANT_PAN data[:card][:pan]
520
+ xml.DS_MERCHANT_EXPIRYDATE data[:card][:date]
521
+ xml.DS_MERCHANT_CVV2 data[:card][:cvv]
522
+ xml.DS_MERCHANT_IDENTIFIER 'REQUIRED' if data[:store_in_vault]
523
+
524
+ build_merchant_mpi_external(xml, data)
525
+
526
+ elsif data[:credit_card_token]
527
+ xml.DS_MERCHANT_IDENTIFIER data[:credit_card_token]
528
+ xml.DS_MERCHANT_DIRECTPAYMENT 'true'
529
+ end
530
+
531
+ # Set moto flag only if explicitly requested via moto field
532
+ # Requires account configuration to be able to use
533
+ xml.DS_MERCHANT_DIRECTPAYMENT 'moto' if options.dig(:moto) && options.dig(:metadata, :manual_entry)
534
+
535
+ xml.DS_MERCHANT_EMV3DS data[:three_ds_data].to_json if data[:three_ds_data]
536
+
537
+ if options[:stored_credential]
538
+ xml.DS_MERCHANT_COF_INI data[:DS_MERCHANT_COF_INI]
539
+ xml.DS_MERCHANT_COF_TYPE data[:DS_MERCHANT_COF_TYPE]
540
+ xml.DS_MERCHANT_COF_TXNID data[:DS_MERCHANT_COF_TXNID] if data[:DS_MERCHANT_COF_TXNID]
541
+ xml.DS_MERCHANT_DIRECTPAYMENT 'false' if options[:stored_credential][:initial_transaction]
542
+ end
543
+ end
544
+ end
545
+
546
+ def build_merchant_mpi_external(xml, data)
547
+ return unless data[:txid] || data[:threeDSServerTransID]
548
+
549
+ ds_merchant_mpi_external = {}
550
+ ds_merchant_mpi_external[:TXID] = data[:txid] if data[:txid]
551
+ ds_merchant_mpi_external[:CAVV] = data[:cavv] if data[:cavv]
552
+ ds_merchant_mpi_external[:ECI] = data[:eci_v1] if data[:eci_v1]
553
+
554
+ ds_merchant_mpi_external[:threeDSServerTransID] = data[:threeDSServerTransID] if data[:threeDSServerTransID]
555
+ ds_merchant_mpi_external[:dsTransID] = data[:dsTransID] if data[:dsTransID]
556
+ ds_merchant_mpi_external[:authenticacionValue] = data[:authenticacionValue] if data[:authenticacionValue]
557
+ ds_merchant_mpi_external[:protocolVersion] = data[:protocolVersion] if data[:protocolVersion]
558
+ ds_merchant_mpi_external[:Eci] = data[:eci_v2] if data[:eci_v2]
559
+ ds_merchant_mpi_external[:authenticacionMethod] = data[:authenticacionMethod] if data[:authenticacionMethod]
560
+ ds_merchant_mpi_external[:authenticacionType] = data[:authenticacionType] if data[:authenticacionType]
561
+ ds_merchant_mpi_external[:authenticacionFlow] = data[:authenticacionFlow] if data[:authenticacionFlow]
562
+
563
+ xml.DS_MERCHANT_MPIEXTERNAL ds_merchant_mpi_external.to_json unless ds_merchant_mpi_external.empty?
564
+ xml.target!
565
+ end
566
+
567
+ def parse(data, action)
568
+ params = {}
569
+ success = false
570
+ message = ''
571
+ options = @options.merge(test: test?)
572
+ xml = Nokogiri::XML(data)
573
+ code = xml.xpath('//RETORNOXML/CODIGO').text
574
+
575
+ if code == '0' && xml.xpath('//RETORNOXML/OPERACION').present?
576
+ op = xml.xpath('//RETORNOXML/OPERACION')
577
+ op.children.each do |element|
578
+ params[element.name.downcase.to_sym] = element.text
579
+ end
580
+ if validate_signature(params)
581
+ message = response_text(params[:ds_response])
582
+ options[:authorization] = build_authorization(params)
583
+ success = success_response?(params[:ds_response])
584
+ else
585
+ message = 'Response failed validation check'
586
+ end
587
+ elsif %w[iniciaPeticion trataPeticion].include?(action)
588
+ vxml = Nokogiri::XML(data).remove_namespaces!.xpath("//Envelope/Body/#{action}Response/#{action}Return").inner_text
589
+ xml = Nokogiri::XML(vxml)
590
+ node = (action == 'iniciaPeticion' ? 'INFOTARJETA' : 'OPERACION')
591
+ op = xml.xpath("//RETORNOXML/#{node}")
592
+ op.children.each do |element|
593
+ params[element.name.downcase.to_sym] = element.text
594
+ end
595
+ message = response_text_3ds(xml, params)
596
+ options[:authorization] = build_authorization(params)
597
+ success = params.size > 0 && success_response?(params[:ds_response])
598
+ else
599
+ # Some kind of programmer error with the request!
600
+ message = "#{code} ERROR"
601
+ end
602
+
603
+ Response.new(success, message, params, options)
604
+ end
605
+
606
+ def validate_signature(data)
607
+ if sha256_authentication?
608
+ sig = Base64.strict_encode64(mac256(get_key(data[:ds_order].to_s), xml_signed_fields(data)))
609
+ sig.casecmp(data[:ds_signature].to_s).zero?
610
+ else
611
+ str = data[:ds_amount] +
612
+ data[:ds_order].to_s +
613
+ data[:ds_merchantcode] +
614
+ data[:ds_currency] +
615
+ data[:ds_response] +
616
+ data[:ds_cardnumber].to_s +
617
+ data[:ds_transactiontype].to_s +
618
+ data[:ds_securepayment].to_s +
619
+ @options[:secret_key]
620
+
621
+ sig = Digest::SHA1.hexdigest(str)
622
+ data[:ds_signature].to_s.downcase == sig
623
+ end
624
+ end
625
+
626
+ def build_authorization(params)
627
+ [params[:ds_order], params[:ds_amount], params[:ds_currency]].join('|')
628
+ end
629
+
630
+ def split_authorization(authorization)
631
+ order_id, amount, currency = authorization.split('|')
632
+ [order_id, amount.to_i, currency]
633
+ end
634
+
635
+ def currency_code(currency)
636
+ return currency if currency =~ /^\d+$/
637
+ raise ArgumentError, "Unknown currency #{currency}" unless CURRENCY_CODES[currency]
638
+
639
+ CURRENCY_CODES[currency]
640
+ end
641
+
642
+ def transaction_code(type)
643
+ SUPPORTED_TRANSACTIONS[type]
644
+ end
645
+
646
+ def response_text(code)
647
+ code = code.to_i
648
+ code = 0 if code < 100
649
+ RESPONSE_TEXTS[code] || 'Unknown code, please check in manual'
650
+ end
651
+
652
+ def response_text_3ds(xml, params)
653
+ code = xml.xpath('//RETORNOXML/CODIGO').text
654
+ message = ''
655
+ if code != '0'
656
+ message = "#{code} ERROR"
657
+ elsif params[:ds_emv3ds]
658
+ three_ds_data = JSON.parse(params[:ds_emv3ds])
659
+ message = three_ds_data['threeDSInfo']
660
+ elsif params[:ds_response]
661
+ message = response_text(params[:ds_response])
662
+ end
663
+ message
664
+ end
665
+
666
+ def success_response?(code)
667
+ (code.to_i < 100) || [400, 481, 500, 900].include?(code.to_i)
668
+ end
669
+
670
+ def clean_order_id(order_id)
671
+ cleansed = order_id.gsub(/[^\da-zA-Z]/, '')
672
+ if /^\d{4}/.match?(cleansed)
673
+ cleansed[0..11]
674
+ else
675
+ '%04d%s' % [rand(0..9999), cleansed[0...8]]
676
+ end
677
+ end
678
+
679
+ def sha256_authentication?
680
+ @options[:signature_algorithm] == 'sha256'
681
+ end
682
+
683
+ def sign_request(xml_request_string, order_id)
684
+ key = encrypt(@options[:secret_key], order_id)
685
+ Base64.strict_encode64(mac256(key, xml_request_string))
686
+ end
687
+
688
+ def encrypt(key, order_id)
689
+ block_length = 8
690
+ cipher = OpenSSL::Cipher.new('DES3')
691
+ cipher.encrypt
692
+
693
+ cipher.key = Base64.urlsafe_decode64(key)
694
+ # The OpenSSL default of an all-zeroes ("\\0") IV is used.
695
+ cipher.padding = 0
696
+
697
+ order_id += "\0" until order_id.bytesize % block_length == 0 # Pad with zeros
698
+
699
+ output = cipher.update(order_id) + cipher.final
700
+ output
701
+ end
702
+
703
+ def mac256(key, data)
704
+ OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), key, data)
705
+ end
706
+
707
+ def xml_signed_fields(data)
708
+ xml_signed_fields = data[:ds_amount] + data[:ds_order] + data[:ds_merchantcode] +
709
+ data[:ds_currency] + data[:ds_response]
710
+
711
+ xml_signed_fields += data[:ds_cardnumber] if data[:ds_cardnumber]
712
+
713
+ xml_signed_fields += data[:ds_emv3ds] if data[:ds_emv3ds]
714
+
715
+ xml_signed_fields + data[:ds_transactiontype] + data[:ds_securepayment]
716
+ end
717
+
718
+ def get_key(order_id)
719
+ encrypt(@options[:secret_key], order_id)
720
+ end
721
+ end
722
+ end
723
+ end