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,358 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class DecidirGateway < Gateway
4
+ self.test_url = 'https://developers.decidir.com/api/v2'
5
+ self.live_url = 'https://live.decidir.com/api/v2'
6
+
7
+ self.supported_countries = ['AR']
8
+ self.money_format = :cents
9
+ self.default_currency = 'ARS'
10
+ self.supported_cardtypes = %i[visa master american_express diners_club naranja cabal]
11
+
12
+ self.homepage_url = 'http://www.decidir.com'
13
+ self.display_name = 'Decidir'
14
+
15
+ STANDARD_ERROR_CODE_MAPPING = {
16
+ 1 => STANDARD_ERROR_CODE[:call_issuer],
17
+ 2 => STANDARD_ERROR_CODE[:call_issuer],
18
+ 3 => STANDARD_ERROR_CODE[:config_error],
19
+ 4 => STANDARD_ERROR_CODE[:pickup_card],
20
+ 5 => STANDARD_ERROR_CODE[:card_declined],
21
+ 7 => STANDARD_ERROR_CODE[:pickup_card],
22
+ 12 => STANDARD_ERROR_CODE[:processing_error],
23
+ 14 => STANDARD_ERROR_CODE[:invalid_number],
24
+ 28 => STANDARD_ERROR_CODE[:processing_error],
25
+ 38 => STANDARD_ERROR_CODE[:incorrect_pin],
26
+ 39 => STANDARD_ERROR_CODE[:invalid_number],
27
+ 43 => STANDARD_ERROR_CODE[:pickup_card],
28
+ 45 => STANDARD_ERROR_CODE[:card_declined],
29
+ 46 => STANDARD_ERROR_CODE[:invalid_number],
30
+ 47 => STANDARD_ERROR_CODE[:card_declined],
31
+ 48 => STANDARD_ERROR_CODE[:card_declined],
32
+ 49 => STANDARD_ERROR_CODE[:invalid_expiry_date],
33
+ 51 => STANDARD_ERROR_CODE[:card_declined],
34
+ 53 => STANDARD_ERROR_CODE[:card_declined],
35
+ 54 => STANDARD_ERROR_CODE[:expired_card],
36
+ 55 => STANDARD_ERROR_CODE[:incorrect_pin],
37
+ 56 => STANDARD_ERROR_CODE[:card_declined],
38
+ 57 => STANDARD_ERROR_CODE[:card_declined],
39
+ 76 => STANDARD_ERROR_CODE[:call_issuer],
40
+ 91 => STANDARD_ERROR_CODE[:call_issuer],
41
+ 96 => STANDARD_ERROR_CODE[:processing_error],
42
+ 97 => STANDARD_ERROR_CODE[:processing_error]
43
+ }
44
+
45
+ def initialize(options = {})
46
+ requires!(options, :api_key)
47
+ super
48
+ @options[:preauth_mode] ||= false
49
+ end
50
+
51
+ def purchase(money, payment, options = {})
52
+ raise ArgumentError, 'Purchase is not supported on Decidir gateways configured with the preauth_mode option' if @options[:preauth_mode]
53
+
54
+ post = {}
55
+ add_auth_purchase_params(post, money, payment, options)
56
+ commit(:post, 'payments', post)
57
+ end
58
+
59
+ def authorize(money, payment, options = {})
60
+ raise ArgumentError, 'Authorize is not supported on Decidir gateways unless the preauth_mode option is enabled' unless @options[:preauth_mode]
61
+
62
+ post = {}
63
+ add_auth_purchase_params(post, money, payment, options)
64
+ commit(:post, 'payments', post)
65
+ end
66
+
67
+ def capture(money, authorization, options = {})
68
+ raise ArgumentError, 'Capture is not supported on Decidir gateways unless the preauth_mode option is enabled' unless @options[:preauth_mode]
69
+
70
+ post = {}
71
+ add_amount(post, money, options)
72
+ commit(:put, "payments/#{authorization}", post)
73
+ end
74
+
75
+ def refund(money, authorization, options = {})
76
+ post = {}
77
+ add_amount(post, money, options)
78
+ commit(:post, "payments/#{authorization}/refunds", post)
79
+ end
80
+
81
+ def void(authorization, options = {})
82
+ post = {}
83
+ commit(:post, "payments/#{authorization}/refunds", post)
84
+ end
85
+
86
+ def inquire(authorization, options = {})
87
+ options[:action] = 'inquire'
88
+ commit(:get, "payments/#{authorization}", nil, options)
89
+ end
90
+
91
+ def verify(credit_card, options = {})
92
+ raise ArgumentError, 'Verify is not supported on Decidir gateways unless the preauth_mode option is enabled' unless @options[:preauth_mode]
93
+
94
+ MultiResponse.run(:use_first_response) do |r|
95
+ r.process { authorize(100, credit_card, options) }
96
+ r.process(:ignore_result) { void(r.authorization, options) }
97
+ end
98
+ end
99
+
100
+ def supports_scrubbing?
101
+ true
102
+ end
103
+
104
+ def scrub(transcript)
105
+ transcript.
106
+ gsub(%r((apikey: )\w+)i, '\1[FILTERED]').
107
+ gsub(%r((\"card_number\\\":\\\")\d+), '\1[FILTERED]').
108
+ gsub(%r((\"security_code\\\":\\\")\d+), '\1[FILTERED]').
109
+ gsub(%r((\"emv_issuer_data\\\":\\\")\d+), '\1[FILTERED]')
110
+ end
111
+
112
+ private
113
+
114
+ def add_auth_purchase_params(post, money, credit_card, options)
115
+ post[:payment_method_id] = add_payment_method_id(credit_card, options)
116
+ post[:site_transaction_id] = options[:order_id]
117
+ post[:bin] = credit_card.number[0..5]
118
+ post[:payment_type] = options[:payment_type] || 'single'
119
+ post[:installments] = options[:installments] ? options[:installments].to_i : 1
120
+ post[:description] = options[:description] if options[:description]
121
+ post[:email] = options[:email] if options[:email]
122
+ post[:establishment_name] = options[:establishment_name] if options[:establishment_name]
123
+ post[:fraud_detection] = add_fraud_detection(options[:fraud_detection]) if options[:fraud_detection].present?
124
+ post[:site_id] = options[:site_id] if options[:site_id]
125
+
126
+ add_invoice(post, money, options)
127
+ add_payment(post, credit_card, options)
128
+ add_aggregate_data(post, options) if options[:aggregate_data]
129
+ add_sub_payments(post, options)
130
+ end
131
+
132
+ def add_payment_method_id(credit_card, options)
133
+ if options[:payment_method_id]
134
+ options[:payment_method_id].to_i
135
+ elsif options[:debit]
136
+ if CreditCard.brand?(credit_card.number) == 'visa'
137
+ 31
138
+ elsif CreditCard.brand?(credit_card.number) == 'master'
139
+ 105
140
+ elsif CreditCard.brand?(credit_card.number) == 'maestro'
141
+ 106
142
+ elsif CreditCard.brand?(credit_card.number) == 'cabal'
143
+ 108
144
+ end
145
+ elsif CreditCard.brand?(credit_card.number) == 'master'
146
+ 104
147
+ elsif CreditCard.brand?(credit_card.number) == 'american_express'
148
+ 65
149
+ elsif CreditCard.brand?(credit_card.number) == 'diners_club'
150
+ 8
151
+ elsif CreditCard.brand?(credit_card.number) == 'cabal'
152
+ 63
153
+ elsif CreditCard.brand?(credit_card.number) == 'naranja'
154
+ 24
155
+ else
156
+ 1
157
+ end
158
+ end
159
+
160
+ def add_invoice(post, money, options)
161
+ add_amount(post, money, options)
162
+ post[:currency] = (options[:currency] || currency(money))
163
+ end
164
+
165
+ def add_amount(post, money, options)
166
+ currency = (options[:currency] || currency(money))
167
+ post[:amount] = localized_amount(money, currency).to_i
168
+ end
169
+
170
+ def add_payment(post, credit_card, options)
171
+ card_data = {}
172
+ card_data[:card_number] = credit_card.number
173
+ card_data[:card_expiration_month] = format(credit_card.month, :two_digits)
174
+ card_data[:card_expiration_year] = format(credit_card.year, :two_digits)
175
+ card_data[:security_code] = credit_card.verification_value if credit_card.verification_value?
176
+ card_data[:card_holder_name] = credit_card.name if credit_card.name
177
+
178
+ # the device_unique_id has to be sent in via the card data (as device_unique_identifier) no other fraud detection fields require this
179
+ if options[:fraud_detection].present?
180
+ card_data[:fraud_detection] = {} if (options[:fraud_detection][:device_unique_id]).present?
181
+ card_data[:fraud_detection][:device_unique_identifier] = (options[:fraud_detection][:device_unique_id]) if (options[:fraud_detection][:device_unique_id]).present?
182
+ end
183
+
184
+ # additional data used for Visa transactions
185
+ card_data[:card_holder_door_number] = options[:card_holder_door_number].to_i if options[:card_holder_door_number]
186
+ card_data[:card_holder_birthday] = options[:card_holder_birthday] if options[:card_holder_birthday]
187
+
188
+ card_data[:card_holder_identification] = {}
189
+ card_data[:card_holder_identification][:type] = options[:card_holder_identification_type] if options[:card_holder_identification_type]
190
+ card_data[:card_holder_identification][:number] = options[:card_holder_identification_number] if options[:card_holder_identification_number]
191
+
192
+ post[:card_data] = card_data
193
+ end
194
+
195
+ def add_aggregate_data(post, options)
196
+ aggregate_data = {}
197
+ data = options[:aggregate_data]
198
+ aggregate_data[:indicator] = data[:indicator] if data[:indicator]
199
+ aggregate_data[:identification_number] = data[:identification_number] if data[:identification_number]
200
+ aggregate_data[:bill_to_pay] = data[:bill_to_pay] if data[:bill_to_pay]
201
+ aggregate_data[:bill_to_refund] = data[:bill_to_refund] if data[:bill_to_refund]
202
+ aggregate_data[:merchant_name] = data[:merchant_name] if data[:merchant_name]
203
+ aggregate_data[:street] = data[:street] if data[:street]
204
+ aggregate_data[:number] = data[:number] if data[:number]
205
+ aggregate_data[:postal_code] = data[:postal_code] if data[:postal_code]
206
+ aggregate_data[:category] = data[:category] if data[:category]
207
+ aggregate_data[:channel] = data[:channel] if data[:channel]
208
+ aggregate_data[:geographic_code] = data[:geographic_code] if data[:geographic_code]
209
+ aggregate_data[:city] = data[:city] if data[:city]
210
+ aggregate_data[:merchant_id] = data[:merchant_id] if data[:merchant_id]
211
+ aggregate_data[:province] = data[:province] if data[:province]
212
+ aggregate_data[:country] = data[:country] if data[:country]
213
+ aggregate_data[:merchant_email] = data[:merchant_email] if data[:merchant_email]
214
+ aggregate_data[:merchant_phone] = data[:merchant_phone] if data[:merchant_phone]
215
+ post[:aggregate_data] = aggregate_data
216
+ end
217
+
218
+ def add_sub_payments(post, options)
219
+ # sub_payments field is required for purchase transactions, even if empty
220
+ post[:sub_payments] = []
221
+
222
+ return unless sub_payments = options[:sub_payments]
223
+
224
+ sub_payments.each do |sub_payment|
225
+ sub_payment_hash = {
226
+ site_id: sub_payment[:site_id],
227
+ installments: sub_payment[:installments].to_i,
228
+ amount: sub_payment[:amount].to_i
229
+ }
230
+ post[:sub_payments] << sub_payment_hash
231
+ end
232
+ end
233
+
234
+ def add_fraud_detection(options = {})
235
+ {}.tap do |hsh|
236
+ hsh[:send_to_cs] = options[:send_to_cs] if valid_fraud_detection_option?(options[:send_to_cs]) # true/false
237
+ hsh[:channel] = options[:channel] if valid_fraud_detection_option?(options[:channel])
238
+ hsh[:dispatch_method] = options[:dispatch_method] if valid_fraud_detection_option?(options[:dispatch_method])
239
+ hsh[:csmdds] = options[:csmdds] if valid_fraud_detection_option?(options[:csmdds])
240
+ hsh[:device_unique_id] = options[:device_unique_id] if valid_fraud_detection_option?(options[:device_unique_id])
241
+ hsh[:bill_to] = options[:bill_to] if valid_fraud_detection_option?(options[:bill_to])
242
+ hsh[:purchase_totals] = options[:purchase_totals] if valid_fraud_detection_option?(options[:purchase_totals])
243
+ hsh[:customer_in_site] = options[:customer_in_site] if valid_fraud_detection_option?(options[:customer_in_site])
244
+ hsh[:retail_transaction_data] = options[:retail_transaction_data] if valid_fraud_detection_option?(options[:retail_transaction_data])
245
+ hsh[:ship_to] = options[:ship_to] if valid_fraud_detection_option?(options[:ship_to])
246
+ hsh[:tax_voucher_required] = options[:tax_voucher_required] if valid_fraud_detection_option?(options[:tax_voucher_required])
247
+ hsh[:copy_paste_card_data] = options[:copy_paste_card_data] if valid_fraud_detection_option?(options[:copy_paste_card_data])
248
+ end
249
+ end
250
+
251
+ # Avoid sending fields with empty or null when not populated.
252
+ def valid_fraud_detection_option?(val)
253
+ !val.nil? && val != ''
254
+ end
255
+
256
+ def headers(options = {})
257
+ {
258
+ 'apikey' => @options[:api_key],
259
+ 'Content-type' => 'application/json',
260
+ 'Cache-Control' => 'no-cache'
261
+ }
262
+ end
263
+
264
+ def commit(method, endpoint, parameters, options = {})
265
+ url = "#{(test? ? test_url : live_url)}/#{endpoint}"
266
+
267
+ begin
268
+ raw_response = ssl_request(method, url, post_data(parameters), headers(options))
269
+ response = parse(raw_response)
270
+ rescue ResponseError => e
271
+ raw_response = e.response.body
272
+ response = parse(raw_response)
273
+ end
274
+
275
+ success = success_from(response, options)
276
+ Response.new(
277
+ success,
278
+ message_from(success, response),
279
+ response,
280
+ authorization: authorization_from(response),
281
+ test: test?,
282
+ error_code: success ? nil : error_code_from(response)
283
+ )
284
+ end
285
+
286
+ def post_data(parameters = {})
287
+ parameters&.to_json
288
+ end
289
+
290
+ def parse(body)
291
+ JSON.parse(body)
292
+ rescue JSON::ParserError
293
+ {
294
+ 'message' => "A non-JSON response was received from Decidir where one was expected. The raw response was:\n\n#{body}"
295
+ }
296
+ end
297
+
298
+ def message_from(success, response)
299
+ return response['status'] if success
300
+ return response['message'] if response['message']
301
+
302
+ message = nil
303
+ if error = response.dig('status_details', 'error')
304
+ message = "#{error.dig('reason', 'description')} | #{error['type']}"
305
+ elsif response['error_type']
306
+ if response['validation_errors'].is_a?(Array)
307
+ message = response['validation_errors'].map { |errors| "#{errors['code']}: #{errors['param']}" }.join(', ')
308
+ elsif response['validation_errors'].is_a?(Hash)
309
+ errors = response['validation_errors'].map { |k, v| "#{k}: #{v}" }.join(', ')
310
+ message = "#{response['error_type']} - #{errors}"
311
+ end
312
+
313
+ message ||= response['error_type']
314
+ end
315
+
316
+ message
317
+ end
318
+
319
+ def success_from(response, options)
320
+ status = %w(approved pre_approved)
321
+
322
+ if options[:action] == 'inquire'
323
+ status.include?(response['status']) || response['status'] == 'rejected'
324
+ else
325
+ status.include?(response['status'])
326
+ end
327
+ end
328
+
329
+ def authorization_from(response)
330
+ response['id']
331
+ end
332
+
333
+ def error_code_from(response)
334
+ error_code = nil
335
+ if error = response.dig('status_details', 'error')
336
+ code = error.dig('reason', 'id')
337
+ standard_error_code = STANDARD_ERROR_CODE_MAPPING[code]
338
+ error_code = "#{code}, #{standard_error_code}"
339
+ error_code ||= error['type']
340
+ elsif response['error_type']
341
+ error_code = response['error_type'] if response['validation_errors']
342
+ elsif response.dig('error', 'validation_errors')
343
+ error = response.dig('error')
344
+ validation_errors = error.dig('validation_errors', 0)
345
+ code = validation_errors['code'] if validation_errors && validation_errors['code']
346
+ param = validation_errors['param'] if validation_errors && validation_errors['param']
347
+ error_code = "#{error['error_type']} | #{code} | #{param}" if error['error_type']
348
+ elsif error = response.dig('error')
349
+ code = error.dig('reason', 'id')
350
+ standard_error_code = STANDARD_ERROR_CODE_MAPPING[code]
351
+ error_code = "#{code}, #{standard_error_code}"
352
+ end
353
+
354
+ error_code || STANDARD_ERROR_CODE[:processing_error]
355
+ end
356
+ end
357
+ end
358
+ end
@@ -0,0 +1,344 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class DecidirPlusGateway < Gateway
4
+ self.test_url = 'https://developers.decidir.com/api/v2'
5
+ self.live_url = 'https://live.decidir.com/api/v2'
6
+
7
+ self.supported_countries = ['AR']
8
+ self.default_currency = 'ARS'
9
+ self.supported_cardtypes = %i[visa master american_express discover diners_club naranja cabal]
10
+
11
+ self.homepage_url = 'http://decidir.com.ar/home'
12
+ self.display_name = 'Decidir Plus'
13
+
14
+ def initialize(options = {})
15
+ requires!(options, :public_key, :private_key)
16
+ super
17
+ end
18
+
19
+ def purchase(money, payment, options = {})
20
+ post = {}
21
+ build_purchase_authorize_request(post, money, payment, options)
22
+
23
+ commit(:post, 'payments', post)
24
+ end
25
+
26
+ def authorize(money, payment, options = {})
27
+ post = {}
28
+ build_purchase_authorize_request(post, money, payment, options)
29
+
30
+ commit(:post, 'payments', post)
31
+ end
32
+
33
+ def capture(money, authorization, options = {})
34
+ post = {}
35
+ post[:amount] = money
36
+
37
+ commit(:put, "payments/#{add_reference(authorization)}", post)
38
+ end
39
+
40
+ def refund(money, authorization, options = {})
41
+ post = {}
42
+ post[:amount] = money
43
+
44
+ commit(:post, "payments/#{add_reference(authorization)}/refunds", post)
45
+ end
46
+
47
+ def void(authorization, options = {})
48
+ commit(:post, "payments/#{add_reference(authorization)}/refunds")
49
+ end
50
+
51
+ def verify(credit_card, options = {})
52
+ MultiResponse.run(:use_first_response) do |r|
53
+ r.process { store(credit_card, options) }
54
+ r.process { authorize(100, r.authorization, options) }
55
+ r.process(:ignore_result) { void(r.authorization, options) }
56
+ end
57
+ end
58
+
59
+ def store(payment, options = {})
60
+ post = {}
61
+ add_payment(post, payment, options)
62
+
63
+ commit(:post, 'tokens', post)
64
+ end
65
+
66
+ def unstore(customer_token)
67
+ commit(:delete, "cardtokens/#{customer_token}")
68
+ end
69
+
70
+ def supports_scrubbing?
71
+ true
72
+ end
73
+
74
+ def scrub(transcript)
75
+ transcript.
76
+ gsub(%r((Apikey: )\w+), '\1[FILTERED]').
77
+ gsub(%r(("card_number\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]').
78
+ gsub(%r(("security_code\\?"\s*:\s*\\?")[^"]*)i, '\1[FILTERED]')
79
+ end
80
+
81
+ private
82
+
83
+ def build_purchase_authorize_request(post, money, payment, options)
84
+ add_customer_data(post, options)
85
+ add_payment(post, payment, options)
86
+ add_purchase_data(post, money, payment, options)
87
+ add_fraud_detection(post, options)
88
+ end
89
+
90
+ def add_reference(authorization)
91
+ return unless authorization
92
+
93
+ authorization.split('|')[0]
94
+ end
95
+
96
+ def add_payment(post, payment, options = {})
97
+ if payment.is_a?(String)
98
+ token, bin = payment.split('|')
99
+ post[:token] = token
100
+ post[:bin] = bin
101
+ else
102
+ post[:card_number] = payment.number
103
+ post[:card_expiration_month] = format(payment.month, :two_digits)
104
+ post[:card_expiration_year] = format(payment.year, :two_digits)
105
+ post[:security_code] = payment.verification_value.to_s
106
+ post[:card_holder_name] = payment.name.empty? ? options[:name_override] : payment.name
107
+ post[:card_holder_identification] = {}
108
+ post[:card_holder_identification][:type] = options[:card_holder_identification_type] if options[:card_holder_identification_type]
109
+ post[:card_holder_identification][:number] = options[:card_holder_identification_number] if options[:card_holder_identification_number]
110
+
111
+ # additional data used for Visa transactions
112
+ post[:card_holder_door_number] = options[:card_holder_door_number].to_i if options[:card_holder_door_number]
113
+ post[:card_holder_birthday] = options[:card_holder_birthday] if options[:card_holder_birthday]
114
+ end
115
+ end
116
+
117
+ def add_customer_data(post, options = {})
118
+ return unless customer = options[:customer]
119
+
120
+ post[:customer] = {}
121
+ post[:customer][:id] = customer[:id] if customer[:id]
122
+ post[:customer][:email] = customer[:email] if customer[:email]
123
+ end
124
+
125
+ def add_purchase_data(post, money, payment, options = {})
126
+ post[:site_transaction_id] = options[:site_transaction_id] || SecureRandom.hex
127
+ post[:payment_method_id] = add_payment_method_id(options)
128
+ post[:amount] = money
129
+ post[:currency] = options[:currency] || self.default_currency
130
+ post[:installments] = options[:installments] || 1
131
+ post[:payment_type] = options[:payment_type] || 'single'
132
+ post[:establishment_name] = options[:establishment_name] if options[:establishment_name]
133
+
134
+ add_aggregate_data(post, options) if options[:aggregate_data]
135
+ add_sub_payments(post, options)
136
+ end
137
+
138
+ def add_aggregate_data(post, options)
139
+ aggregate_data = {}
140
+ data = options[:aggregate_data]
141
+ aggregate_data[:indicator] = data[:indicator] if data[:indicator]
142
+ aggregate_data[:identification_number] = data[:identification_number] if data[:identification_number]
143
+ aggregate_data[:bill_to_pay] = data[:bill_to_pay] if data[:bill_to_pay]
144
+ aggregate_data[:bill_to_refund] = data[:bill_to_refund] if data[:bill_to_refund]
145
+ aggregate_data[:merchant_name] = data[:merchant_name] if data[:merchant_name]
146
+ aggregate_data[:street] = data[:street] if data[:street]
147
+ aggregate_data[:number] = data[:number] if data[:number]
148
+ aggregate_data[:postal_code] = data[:postal_code] if data[:postal_code]
149
+ aggregate_data[:category] = data[:category] if data[:category]
150
+ aggregate_data[:channel] = data[:channel] if data[:channel]
151
+ aggregate_data[:geographic_code] = data[:geographic_code] if data[:geographic_code]
152
+ aggregate_data[:city] = data[:city] if data[:city]
153
+ aggregate_data[:merchant_id] = data[:merchant_id] if data[:merchant_id]
154
+ aggregate_data[:province] = data[:province] if data[:province]
155
+ aggregate_data[:country] = data[:country] if data[:country]
156
+ aggregate_data[:merchant_email] = data[:merchant_email] if data[:merchant_email]
157
+ aggregate_data[:merchant_phone] = data[:merchant_phone] if data[:merchant_phone]
158
+ post[:aggregate_data] = aggregate_data
159
+ end
160
+
161
+ def add_sub_payments(post, options)
162
+ # sub_payments field is required for purchase transactions, even if empty
163
+ post[:sub_payments] = []
164
+
165
+ return unless sub_payments = options[:sub_payments]
166
+
167
+ sub_payments.each do |sub_payment|
168
+ sub_payment_hash = {
169
+ site_id: sub_payment[:site_id],
170
+ installments: sub_payment[:installments].to_i,
171
+ amount: sub_payment[:amount].to_i
172
+ }
173
+ post[:sub_payments] << sub_payment_hash
174
+ end
175
+ end
176
+
177
+ def add_payment_method_id(options)
178
+ return options[:payment_method_id].to_i if options[:payment_method_id]
179
+
180
+ if options[:debit]
181
+ case options[:card_brand]
182
+ when 'visa'
183
+ 31
184
+ when 'master'
185
+ 105
186
+ when 'maestro'
187
+ 106
188
+ when 'cabal'
189
+ 108
190
+ else
191
+ 31
192
+ end
193
+ else
194
+ case options[:card_brand]
195
+ when 'visa'
196
+ 1
197
+ when 'master'
198
+ 104
199
+ when 'american_express'
200
+ 65
201
+ when 'american_express_prisma'
202
+ 111
203
+ when 'cabal'
204
+ 63
205
+ when 'diners_club'
206
+ 8
207
+ else
208
+ 1
209
+ end
210
+ end
211
+ end
212
+
213
+ def add_fraud_detection(post, options)
214
+ return unless fraud_detection = options[:fraud_detection]
215
+
216
+ {}.tap do |hsh|
217
+ hsh[:send_to_cs] = fraud_detection[:send_to_cs] == 'true' # true/false
218
+ hsh[:channel] = fraud_detection[:channel] if fraud_detection[:channel]
219
+ hsh[:dispatch_method] = fraud_detection[:dispatch_method] if fraud_detection[:dispatch_method]
220
+ add_csmdds(hsh, fraud_detection)
221
+
222
+ post[:fraud_detection] = hsh
223
+ end
224
+ end
225
+
226
+ def add_csmdds(hsh, fraud_detection)
227
+ return unless fraud_detection[:csmdds]
228
+
229
+ csmdds_arr = []
230
+ fraud_detection[:csmdds].each do |csmdds|
231
+ csmdds_hsh = {}
232
+ csmdds_hsh[:code] = csmdds[:code].to_i
233
+ csmdds_hsh[:description] = csmdds[:description]
234
+ csmdds_arr.append(csmdds_hsh)
235
+ end
236
+ hsh[:csmdds] = csmdds_arr unless csmdds_arr.empty?
237
+ end
238
+
239
+ def parse(body)
240
+ return {} if body.nil?
241
+
242
+ JSON.parse(body)
243
+ end
244
+
245
+ def commit(method, endpoint, parameters = {}, options = {})
246
+ begin
247
+ raw_response = ssl_request(method, url(endpoint), post_data(parameters), headers(endpoint))
248
+ response = parse(raw_response)
249
+ rescue ResponseError => e
250
+ raw_response = e.response.body
251
+ response = parse(raw_response)
252
+ end
253
+
254
+ Response.new(
255
+ success_from(response),
256
+ message_from(response),
257
+ response,
258
+ authorization: authorization_from(response),
259
+ avs_result: AVSResult.new(code: response['some_avs_response_key']),
260
+ cvv_result: CVVResult.new(response['some_cvv_response_key']),
261
+ test: test?,
262
+ error_code: error_code_from(response)
263
+ )
264
+ end
265
+
266
+ def headers(endpoint)
267
+ {
268
+ 'Content-Type' => 'application/json',
269
+ 'apikey' => endpoint == 'tokens' ? @options[:public_key] : @options[:private_key]
270
+ }
271
+ end
272
+
273
+ def url(action, options = {})
274
+ base_url = (test? ? test_url : live_url)
275
+
276
+ return "#{base_url}/#{action}"
277
+ end
278
+
279
+ def success_from(response)
280
+ response.dig('status') == 'approved' || response.dig('status') == 'active' || response.dig('status') == 'pre_approved' || response.empty?
281
+ end
282
+
283
+ def message_from(response)
284
+ return '' if response.empty?
285
+
286
+ rejected?(response) ? message_from_status_details(response) : response.dig('status') || error_message(response) || response.dig('message')
287
+ end
288
+
289
+ def authorization_from(response)
290
+ return nil unless response.dig('id') || response.dig('bin')
291
+
292
+ "#{response.dig('id')}|#{response.dig('bin')}"
293
+ end
294
+
295
+ def post_data(parameters = {})
296
+ parameters.to_json
297
+ end
298
+
299
+ def error_code_from(response)
300
+ return if success_from(response)
301
+
302
+ error_code = nil
303
+ if error = response.dig('status_details', 'error')
304
+ error_code = error.dig('reason', 'id') || error['type']
305
+ elsif response['error_type']
306
+ error_code = response['error_type']
307
+ elsif response.dig('error', 'validation_errors')
308
+ error = response.dig('error')
309
+ validation_errors = error.dig('validation_errors', 0)
310
+ code = validation_errors['code'] if validation_errors && validation_errors['code']
311
+ param = validation_errors['param'] if validation_errors && validation_errors['param']
312
+ error_code = "#{error['error_type']} | #{code} | #{param}" if error['error_type']
313
+ elsif error = response.dig('error')
314
+ error_code = error.dig('reason', 'id')
315
+ end
316
+
317
+ error_code
318
+ end
319
+
320
+ def error_message(response)
321
+ return error_code_from(response) unless validation_errors = response.dig('validation_errors')
322
+
323
+ validation_errors = validation_errors[0]
324
+
325
+ "#{validation_errors.dig('code')}: #{validation_errors.dig('param')}"
326
+ end
327
+
328
+ def rejected?(response)
329
+ return response.dig('status') == 'rejected'
330
+ end
331
+
332
+ def message_from_status_details(response)
333
+ return unless error = response.dig('status_details', 'error')
334
+ return message_from_fraud_detection(response) if error.dig('type') == 'cybersource_error'
335
+
336
+ "#{error.dig('type')}: #{error.dig('reason', 'description')}"
337
+ end
338
+
339
+ def message_from_fraud_detection(response)
340
+ return error_message(response.dig('fraud_detection', 'status', 'details'))
341
+ end
342
+ end
343
+ end
344
+ end