activemerchant 1.133.0 → 1.138.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +450 -0
  3. data/CONTRIBUTORS +1 -0
  4. data/lib/active_merchant/billing/apple_pay_payment_token.rb +2 -2
  5. data/lib/active_merchant/billing/base.rb +2 -2
  6. data/lib/active_merchant/billing/check.rb +16 -4
  7. data/lib/active_merchant/billing/compatibility.rb +4 -4
  8. data/lib/active_merchant/billing/credit_card.rb +35 -16
  9. data/lib/active_merchant/billing/credit_card_formatting.rb +13 -2
  10. data/lib/active_merchant/billing/credit_card_methods.rb +74 -19
  11. data/lib/active_merchant/billing/gateway.rb +22 -2
  12. data/lib/active_merchant/billing/gateways/adyen.rb +282 -87
  13. data/lib/active_merchant/billing/gateways/airwallex.rb +46 -25
  14. data/lib/active_merchant/billing/gateways/alelo.rb +29 -11
  15. data/lib/active_merchant/billing/gateways/allied_wallet.rb +2 -2
  16. data/lib/active_merchant/billing/gateways/authorize_net.rb +49 -41
  17. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +14 -10
  18. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +3 -5
  19. data/lib/active_merchant/billing/gateways/axcessms.rb +9 -5
  20. data/lib/active_merchant/billing/gateways/balanced.rb +2 -2
  21. data/lib/active_merchant/billing/gateways/bambora_apac.rb +2 -2
  22. data/lib/active_merchant/billing/gateways/bank_frick.rb +2 -2
  23. data/lib/active_merchant/billing/gateways/banwire.rb +6 -4
  24. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +8 -8
  25. data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +2 -2
  26. data/lib/active_merchant/billing/gateways/be2bill.rb +2 -2
  27. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +12 -8
  28. data/lib/active_merchant/billing/gateways/beanstream.rb +2 -2
  29. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +2 -2
  30. data/lib/active_merchant/billing/gateways/blue_pay.rb +15 -7
  31. data/lib/active_merchant/billing/gateways/blue_snap.rb +5 -5
  32. data/lib/active_merchant/billing/gateways/bogus.rb +2 -2
  33. data/lib/active_merchant/billing/gateways/borgun.rb +2 -2
  34. data/lib/active_merchant/billing/gateways/bpoint.rb +2 -2
  35. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +3 -1
  36. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +68 -23
  37. data/lib/active_merchant/billing/gateways/braintree.rb +2 -2
  38. data/lib/active_merchant/billing/gateways/braintree_blue.rb +266 -89
  39. data/lib/active_merchant/billing/gateways/braintree_orange.rb +3 -3
  40. data/lib/active_merchant/billing/gateways/bridge_pay.rb +2 -2
  41. data/lib/active_merchant/billing/gateways/cams.rb +2 -2
  42. data/lib/active_merchant/billing/gateways/card_connect.rb +7 -4
  43. data/lib/active_merchant/billing/gateways/card_save.rb +2 -2
  44. data/lib/active_merchant/billing/gateways/card_stream.rb +12 -13
  45. data/lib/active_merchant/billing/gateways/cardknox.rb +2 -2
  46. data/lib/active_merchant/billing/gateways/cardprocess.rb +2 -2
  47. data/lib/active_merchant/billing/gateways/cashnet.rb +4 -4
  48. data/lib/active_merchant/billing/gateways/cc5.rb +2 -2
  49. data/lib/active_merchant/billing/gateways/cecabank/cecabank_common.rb +36 -0
  50. data/lib/active_merchant/billing/gateways/cecabank/cecabank_json.rb +331 -0
  51. data/lib/active_merchant/billing/gateways/cecabank/cecabank_xml.rb +220 -0
  52. data/lib/active_merchant/billing/gateways/cecabank.rb +9 -242
  53. data/lib/active_merchant/billing/gateways/cenpos.rb +9 -3
  54. data/lib/active_merchant/billing/gateways/checkout.rb +5 -5
  55. data/lib/active_merchant/billing/gateways/checkout_v2.rb +362 -50
  56. data/lib/active_merchant/billing/gateways/clearhaus.rb +2 -2
  57. data/lib/active_merchant/billing/gateways/commerce_hub.rb +117 -35
  58. data/lib/active_merchant/billing/gateways/commercegate.rb +4 -4
  59. data/lib/active_merchant/billing/gateways/conekta.rb +2 -2
  60. data/lib/active_merchant/billing/gateways/creditcall.rb +2 -2
  61. data/lib/active_merchant/billing/gateways/credorax.rb +109 -20
  62. data/lib/active_merchant/billing/gateways/ct_payment.rb +6 -6
  63. data/lib/active_merchant/billing/gateways/culqi.rb +2 -2
  64. data/lib/active_merchant/billing/gateways/cyber_source/cyber_source_common.rb +2 -2
  65. data/lib/active_merchant/billing/gateways/cyber_source.rb +379 -100
  66. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +147 -76
  67. data/lib/active_merchant/billing/gateways/d_local.rb +45 -22
  68. data/lib/active_merchant/billing/gateways/data_cash.rb +22 -18
  69. data/lib/active_merchant/billing/gateways/datatrans.rb +284 -0
  70. data/lib/active_merchant/billing/gateways/decidir.rb +82 -46
  71. data/lib/active_merchant/billing/gateways/decidir_plus.rb +31 -35
  72. data/lib/active_merchant/billing/gateways/deepstack.rb +382 -0
  73. data/lib/active_merchant/billing/gateways/dibs.rb +3 -3
  74. data/lib/active_merchant/billing/gateways/digitzs.rb +2 -2
  75. data/lib/active_merchant/billing/gateways/ebanx.rb +116 -68
  76. data/lib/active_merchant/billing/gateways/efsnet.rb +13 -8
  77. data/lib/active_merchant/billing/gateways/elavon.rb +80 -47
  78. data/lib/active_merchant/billing/gateways/element.rb +39 -10
  79. data/lib/active_merchant/billing/gateways/epay.rb +8 -4
  80. data/lib/active_merchant/billing/gateways/evo_ca.rb +8 -4
  81. data/lib/active_merchant/billing/gateways/eway.rb +6 -4
  82. data/lib/active_merchant/billing/gateways/eway_managed.rb +8 -4
  83. data/lib/active_merchant/billing/gateways/eway_rapid.rb +3 -3
  84. data/lib/active_merchant/billing/gateways/exact.rb +8 -4
  85. data/lib/active_merchant/billing/gateways/fat_zebra.rb +37 -7
  86. data/lib/active_merchant/billing/gateways/federated_canada.rb +8 -4
  87. data/lib/active_merchant/billing/gateways/finansbank.rb +2 -2
  88. data/lib/active_merchant/billing/gateways/first_giving.rb +2 -2
  89. data/lib/active_merchant/billing/gateways/first_pay/first_pay_common.rb +15 -0
  90. data/lib/active_merchant/billing/gateways/first_pay/first_pay_json.rb +190 -0
  91. data/lib/active_merchant/billing/gateways/first_pay/first_pay_xml.rb +183 -0
  92. data/lib/active_merchant/billing/gateways/first_pay.rb +8 -174
  93. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +8 -4
  94. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +9 -5
  95. data/lib/active_merchant/billing/gateways/flex_charge.rb +359 -0
  96. data/lib/active_merchant/billing/gateways/flo2cash.rb +4 -2
  97. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +2 -2
  98. data/lib/active_merchant/billing/gateways/forte.rb +6 -4
  99. data/lib/active_merchant/billing/gateways/fortis.rb +347 -0
  100. data/lib/active_merchant/billing/gateways/garanti.rb +6 -4
  101. data/lib/active_merchant/billing/gateways/global_collect.rb +69 -50
  102. data/lib/active_merchant/billing/gateways/global_transport.rb +2 -2
  103. data/lib/active_merchant/billing/gateways/hdfc.rb +2 -2
  104. data/lib/active_merchant/billing/gateways/hi_pay.rb +287 -0
  105. data/lib/active_merchant/billing/gateways/hps.rb +40 -47
  106. data/lib/active_merchant/billing/gateways/iats_payments.rb +9 -4
  107. data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +2 -2
  108. data/lib/active_merchant/billing/gateways/inspire.rb +8 -6
  109. data/lib/active_merchant/billing/gateways/instapay.rb +9 -6
  110. data/lib/active_merchant/billing/gateways/ipg.rb +14 -10
  111. data/lib/active_merchant/billing/gateways/ipp.rb +2 -2
  112. data/lib/active_merchant/billing/gateways/iridium.rb +18 -8
  113. data/lib/active_merchant/billing/gateways/itransact.rb +8 -4
  114. data/lib/active_merchant/billing/gateways/iveri.rb +12 -9
  115. data/lib/active_merchant/billing/gateways/ixopay.rb +4 -4
  116. data/lib/active_merchant/billing/gateways/jetpay.rb +6 -4
  117. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +9 -6
  118. data/lib/active_merchant/billing/gateways/komoju.rb +2 -2
  119. data/lib/active_merchant/billing/gateways/kushki.rb +79 -16
  120. data/lib/active_merchant/billing/gateways/latitude19.rb +2 -2
  121. data/lib/active_merchant/billing/gateways/linkpoint.rb +8 -4
  122. data/lib/active_merchant/billing/gateways/litle.rb +37 -54
  123. data/lib/active_merchant/billing/gateways/loan_payment_pro.rb +267 -0
  124. data/lib/active_merchant/billing/gateways/loan_payment_pro_ach.rb +93 -0
  125. data/lib/active_merchant/billing/gateways/mastercard.rb +4 -4
  126. data/lib/active_merchant/billing/gateways/maxipago.rb +4 -4
  127. data/lib/active_merchant/billing/gateways/mercado_pago.rb +32 -11
  128. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +10 -7
  129. data/lib/active_merchant/billing/gateways/merchant_one.rb +2 -2
  130. data/lib/active_merchant/billing/gateways/merchant_partners.rb +2 -2
  131. data/lib/active_merchant/billing/gateways/merchant_ware.rb +13 -6
  132. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +13 -6
  133. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +21 -5
  134. data/lib/active_merchant/billing/gateways/mercury.rb +11 -5
  135. data/lib/active_merchant/billing/gateways/metrics_global.rb +10 -8
  136. data/lib/active_merchant/billing/gateways/micropayment.rb +2 -2
  137. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +7 -6
  138. data/lib/active_merchant/billing/gateways/migs.rb +8 -4
  139. data/lib/active_merchant/billing/gateways/mit.rb +10 -5
  140. data/lib/active_merchant/billing/gateways/modern_payments.rb +2 -2
  141. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +21 -13
  142. data/lib/active_merchant/billing/gateways/moka.rb +2 -2
  143. data/lib/active_merchant/billing/gateways/monei.rb +3 -3
  144. data/lib/active_merchant/billing/gateways/moneris.rb +11 -5
  145. data/lib/active_merchant/billing/gateways/money_movers.rb +8 -4
  146. data/lib/active_merchant/billing/gateways/multi_pay.rb +267 -0
  147. data/lib/active_merchant/billing/gateways/mundipagg.rb +5 -3
  148. data/lib/active_merchant/billing/gateways/nab_transact.rb +18 -10
  149. data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +2 -2
  150. data/lib/active_merchant/billing/gateways/net_registry.rb +6 -2
  151. data/lib/active_merchant/billing/gateways/netaxept.rb +4 -4
  152. data/lib/active_merchant/billing/gateways/netbanx.rb +4 -6
  153. data/lib/active_merchant/billing/gateways/netbilling.rb +8 -4
  154. data/lib/active_merchant/billing/gateways/netpay.rb +2 -2
  155. data/lib/active_merchant/billing/gateways/network_merchants.rb +9 -5
  156. data/lib/active_merchant/billing/gateways/nmi.rb +29 -8
  157. data/lib/active_merchant/billing/gateways/nuvei.rb +573 -0
  158. data/lib/active_merchant/billing/gateways/ogone.rb +8 -4
  159. data/lib/active_merchant/billing/gateways/omise.rb +2 -2
  160. data/lib/active_merchant/billing/gateways/openpay.rb +6 -4
  161. data/lib/active_merchant/billing/gateways/opp.rb +3 -4
  162. data/lib/active_merchant/billing/gateways/optimal_payment.rb +12 -6
  163. data/lib/active_merchant/billing/gateways/orbital/orbital_codes.rb +273 -0
  164. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +3 -5
  165. data/lib/active_merchant/billing/gateways/orbital.rb +114 -94
  166. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +9 -6
  167. data/lib/active_merchant/billing/gateways/pagarme.rb +2 -2
  168. data/lib/active_merchant/billing/gateways/pago_facil.rb +2 -2
  169. data/lib/active_merchant/billing/gateways/pay_arc.rb +9 -7
  170. data/lib/active_merchant/billing/gateways/pay_conex.rb +6 -4
  171. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +8 -4
  172. data/lib/active_merchant/billing/gateways/pay_hub.rb +7 -5
  173. data/lib/active_merchant/billing/gateways/pay_junction.rb +8 -4
  174. data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +2 -2
  175. data/lib/active_merchant/billing/gateways/pay_secure.rb +8 -4
  176. data/lib/active_merchant/billing/gateways/pay_trace.rb +36 -22
  177. data/lib/active_merchant/billing/gateways/paybox_direct.rb +14 -14
  178. data/lib/active_merchant/billing/gateways/payeezy.rb +26 -13
  179. data/lib/active_merchant/billing/gateways/payex.rb +8 -6
  180. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +3 -3
  181. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +2 -2
  182. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +2 -2
  183. data/lib/active_merchant/billing/gateways/payflow.rb +12 -11
  184. data/lib/active_merchant/billing/gateways/payflow_express.rb +2 -2
  185. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +2 -2
  186. data/lib/active_merchant/billing/gateways/payflow_uk.rb +2 -2
  187. data/lib/active_merchant/billing/gateways/payment_express.rb +10 -6
  188. data/lib/active_merchant/billing/gateways/paymentez.rb +30 -16
  189. data/lib/active_merchant/billing/gateways/paymill.rb +6 -4
  190. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +17 -12
  191. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +2 -2
  192. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +2 -2
  193. data/lib/active_merchant/billing/gateways/paypal.rb +4 -2
  194. data/lib/active_merchant/billing/gateways/paypal_ca.rb +2 -2
  195. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +2 -2
  196. data/lib/active_merchant/billing/gateways/paypal_express.rb +4 -2
  197. data/lib/active_merchant/billing/gateways/paysafe.rb +48 -24
  198. data/lib/active_merchant/billing/gateways/payscout.rb +9 -6
  199. data/lib/active_merchant/billing/gateways/paystation.rb +9 -5
  200. data/lib/active_merchant/billing/gateways/payu_in.rb +2 -2
  201. data/lib/active_merchant/billing/gateways/payu_latam.rb +7 -5
  202. data/lib/active_merchant/billing/gateways/payway.rb +6 -2
  203. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +6 -6
  204. data/lib/active_merchant/billing/gateways/pin.rb +126 -41
  205. data/lib/active_merchant/billing/gateways/plexo.rb +71 -20
  206. data/lib/active_merchant/billing/gateways/plugnpay.rb +6 -2
  207. data/lib/active_merchant/billing/gateways/priority.rb +29 -24
  208. data/lib/active_merchant/billing/gateways/pro_pay.rb +2 -2
  209. data/lib/active_merchant/billing/gateways/psigate.rb +8 -4
  210. data/lib/active_merchant/billing/gateways/psl_card.rb +6 -2
  211. data/lib/active_merchant/billing/gateways/qbms.rb +9 -5
  212. data/lib/active_merchant/billing/gateways/quantum.rb +9 -5
  213. data/lib/active_merchant/billing/gateways/quickbooks.rb +27 -17
  214. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +7 -4
  215. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +8 -4
  216. data/lib/active_merchant/billing/gateways/quickpay.rb +2 -2
  217. data/lib/active_merchant/billing/gateways/qvalent.rb +2 -2
  218. data/lib/active_merchant/billing/gateways/rapyd.rb +172 -53
  219. data/lib/active_merchant/billing/gateways/reach.rb +16 -9
  220. data/lib/active_merchant/billing/gateways/redsys.rb +7 -15
  221. data/lib/active_merchant/billing/gateways/redsys_rest.rb +545 -0
  222. data/lib/active_merchant/billing/gateways/s5.rb +5 -5
  223. data/lib/active_merchant/billing/gateways/safe_charge.rb +47 -24
  224. data/lib/active_merchant/billing/gateways/sage.rb +14 -6
  225. data/lib/active_merchant/billing/gateways/sage_pay.rb +81 -7
  226. data/lib/active_merchant/billing/gateways/sallie_mae.rb +8 -4
  227. data/lib/active_merchant/billing/gateways/secure_net.rb +9 -5
  228. data/lib/active_merchant/billing/gateways/secure_pay.rb +10 -8
  229. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +25 -15
  230. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +8 -4
  231. data/lib/active_merchant/billing/gateways/securion_pay.rb +26 -12
  232. data/lib/active_merchant/billing/gateways/shift4.rb +34 -26
  233. data/lib/active_merchant/billing/gateways/shift4_v2.rb +117 -0
  234. data/lib/active_merchant/billing/gateways/simetrik.rb +26 -17
  235. data/lib/active_merchant/billing/gateways/skip_jack.rb +8 -4
  236. data/lib/active_merchant/billing/gateways/smart_ps.rb +10 -7
  237. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +6 -4
  238. data/lib/active_merchant/billing/gateways/spreedly_core.rb +4 -6
  239. data/lib/active_merchant/billing/gateways/stripe.rb +88 -84
  240. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +388 -77
  241. data/lib/active_merchant/billing/gateways/sum_up.rb +224 -0
  242. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +6 -4
  243. data/lib/active_merchant/billing/gateways/telr.rb +6 -7
  244. data/lib/active_merchant/billing/gateways/trans_first.rb +6 -4
  245. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +10 -18
  246. data/lib/active_merchant/billing/gateways/transact_pro.rb +3 -3
  247. data/lib/active_merchant/billing/gateways/transax.rb +2 -2
  248. data/lib/active_merchant/billing/gateways/transnational.rb +2 -2
  249. data/lib/active_merchant/billing/gateways/trexle.rb +2 -2
  250. data/lib/active_merchant/billing/gateways/trust_commerce.rb +9 -5
  251. data/lib/active_merchant/billing/gateways/usa_epay.rb +2 -2
  252. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +32 -31
  253. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +8 -4
  254. data/lib/active_merchant/billing/gateways/vanco.rb +2 -4
  255. data/lib/active_merchant/billing/gateways/vantiv_express.rb +668 -0
  256. data/lib/active_merchant/billing/gateways/verifi.rb +12 -8
  257. data/lib/active_merchant/billing/gateways/versa_pay.rb +307 -0
  258. data/lib/active_merchant/billing/gateways/viaklix.rb +8 -4
  259. data/lib/active_merchant/billing/gateways/visanet_peru.rb +5 -5
  260. data/lib/active_merchant/billing/gateways/vpos.rb +25 -13
  261. data/lib/active_merchant/billing/gateways/webpay.rb +3 -3
  262. data/lib/active_merchant/billing/gateways/wepay.rb +6 -4
  263. data/lib/active_merchant/billing/gateways/wirecard.rb +10 -6
  264. data/lib/active_merchant/billing/gateways/wompi.rb +14 -7
  265. data/lib/active_merchant/billing/gateways/world_net.rb +2 -2
  266. data/lib/active_merchant/billing/gateways/worldpay.rb +297 -113
  267. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +16 -13
  268. data/lib/active_merchant/billing/gateways/worldpay_us.rb +2 -2
  269. data/lib/active_merchant/billing/gateways/xpay.rb +244 -0
  270. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +15 -3
  271. data/lib/active_merchant/billing/payment_token.rb +2 -2
  272. data/lib/active_merchant/billing/response.rb +7 -6
  273. data/lib/active_merchant/billing.rb +1 -0
  274. data/lib/active_merchant/connection.rb +8 -20
  275. data/lib/active_merchant/country.rb +3 -1
  276. data/lib/active_merchant/errors.rb +12 -2
  277. data/lib/active_merchant/net_http_ssl_connection.rb +35 -0
  278. data/lib/active_merchant/posts_data.rb +19 -4
  279. data/lib/active_merchant/version.rb +1 -1
  280. data/lib/active_merchant/versionable.rb +29 -0
  281. data/lib/certs/cacert.pem +1326 -1491
  282. data/lib/support/gateway_support.rb +3 -3
  283. data/lib/support/ssl_verify.rb +6 -6
  284. data/lib/support/ssl_version.rb +8 -8
  285. metadata +35 -9
@@ -1,5 +1,5 @@
1
- module ActiveMerchant #:nodoc:
2
- module Billing #:nodoc:
1
+ module ActiveMerchant # :nodoc:
2
+ module Billing # :nodoc:
3
3
  class QbmsGateway < Gateway
4
4
  API_VERSION = '4.0'
5
5
 
@@ -142,12 +142,16 @@ module ActiveMerchant #:nodoc:
142
142
  response = parse(type, data)
143
143
  message = (response[:status_message] || '').strip
144
144
 
145
- Response.new(success?(response), message, response,
145
+ Response.new(
146
+ success?(response),
147
+ message,
148
+ response,
146
149
  test: test?,
147
150
  authorization: response[:credit_card_trans_id],
148
151
  fraud_review: fraud_review?(response),
149
152
  avs_result: { code: avs_result(response) },
150
- cvv_result: cvv_result(response))
153
+ cvv_result: cvv_result(response)
154
+ )
151
155
  end
152
156
 
153
157
  def success?(response)
@@ -166,7 +170,7 @@ module ActiveMerchant #:nodoc:
166
170
 
167
171
  if status_code != 0
168
172
  return {
169
- status_code: status_code,
173
+ status_code:,
170
174
  status_message: signon.attributes['statusMessage']
171
175
  }
172
176
  end
@@ -1,5 +1,5 @@
1
- module ActiveMerchant #:nodoc:
2
- module Billing #:nodoc:
1
+ module ActiveMerchant # :nodoc:
2
+ module Billing # :nodoc:
3
3
  # ActiveMerchant Implementation for Quantum Gateway XML Requester Service
4
4
  # Based on API Doc from 8/6/2009
5
5
  #
@@ -215,11 +215,15 @@ module ActiveMerchant #:nodoc:
215
215
  authorization = success ? authorization_for(response) : nil
216
216
  end
217
217
 
218
- Response.new(success, message, response,
218
+ Response.new(
219
+ success,
220
+ message,
221
+ response,
219
222
  test: test?,
220
- authorization: authorization,
223
+ authorization:,
221
224
  avs_result: { code: response[:AVSResponseCode] },
222
- cvv_result: response[:CVV2ResponseCode])
225
+ cvv_result: response[:CVV2ResponseCode]
226
+ )
223
227
  end
224
228
 
225
229
  # Parse the SOAP response
@@ -1,6 +1,7 @@
1
- module ActiveMerchant #:nodoc:
2
- module Billing #:nodoc:
1
+ module ActiveMerchant # :nodoc:
2
+ module Billing # :nodoc:
3
3
  class QuickbooksGateway < Gateway
4
+ version 'v4'
4
5
  self.test_url = 'https://sandbox.api.intuit.com'
5
6
  self.live_url = 'https://api.intuit.com'
6
7
 
@@ -10,9 +11,17 @@ module ActiveMerchant #:nodoc:
10
11
 
11
12
  self.homepage_url = 'http://payments.intuit.com'
12
13
  self.display_name = 'QuickBooks Payments'
13
- BASE = '/quickbooks/v4/payments'
14
- ENDPOINT = "#{BASE}/charges"
15
- VOID_ENDPOINT = "#{BASE}/txn-requests"
14
+ def base_path
15
+ "/quickbooks/#{fetch_version}/payments"
16
+ end
17
+
18
+ def endpoint
19
+ "#{base_path}/charges"
20
+ end
21
+
22
+ def void_endpoint
23
+ "#{base_path}/txn-requests"
24
+ end
16
25
  REFRESH_URI = 'https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer'
17
26
 
18
27
  # https://developer.intuit.com/docs/0150_payments/0300_developer_guides/error_handling
@@ -42,10 +51,10 @@ module ActiveMerchant #:nodoc:
42
51
  'PMT-5001' => STANDARD_ERROR_CODE[:card_declined], # Merchant does not support given payment method
43
52
 
44
53
  # System Error
45
- 'PMT-6000' => STANDARD_ERROR_CODE[:processing_error], # A temporary Issue prevented this request from being processed.
54
+ 'PMT-6000' => STANDARD_ERROR_CODE[:processing_error] # A temporary Issue prevented this request from being processed.
46
55
  }
47
56
 
48
- FRAUD_WARNING_CODES = ['PMT-1000', 'PMT-1001', 'PMT-1002', 'PMT-1003']
57
+ FRAUD_WARNING_CODES = %w(PMT-1000 PMT-1001 PMT-1002 PMT-1003)
49
58
 
50
59
  def initialize(options = {})
51
60
  # Quickbooks is deprecating OAuth 1.0 on December 17, 2019.
@@ -67,8 +76,8 @@ module ActiveMerchant #:nodoc:
67
76
  add_charge_data(post, payment, options)
68
77
  post[:capture] = 'true'
69
78
 
70
- response = commit(ENDPOINT, post)
71
- check_token_response(response, ENDPOINT, post, options)
79
+ response = commit(endpoint, post)
80
+ check_token_response(response, endpoint, post, options)
72
81
  end
73
82
 
74
83
  def authorize(money, payment, options = {})
@@ -77,8 +86,8 @@ module ActiveMerchant #:nodoc:
77
86
  add_charge_data(post, payment, options)
78
87
  post[:capture] = 'false'
79
88
 
80
- response = commit(ENDPOINT, post)
81
- check_token_response(response, ENDPOINT, post, options)
89
+ response = commit(endpoint, post)
90
+ check_token_response(response, endpoint, post, options)
82
91
  end
83
92
 
84
93
  def capture(money, authorization, options = {})
@@ -128,8 +137,8 @@ module ActiveMerchant #:nodoc:
128
137
  gsub(%r((oauth_nonce=\")\w+), '\1[FILTERED]').
129
138
  gsub(%r((oauth_signature=\")[a-zA-Z%0-9]+), '\1[FILTERED]').
130
139
  gsub(%r((oauth_token=\")\w+), '\1[FILTERED]').
131
- gsub(%r((number\D+)\d{16}), '\1[FILTERED]').
132
- gsub(%r((cvc\D+)\d{3}), '\1[FILTERED]').
140
+ gsub(%r((number\\\":\\\")\d+), '\1[FILTERED]').
141
+ gsub(%r((cvc\\\":\\\")\d+), '\1[FILTERED]').
133
142
  gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
134
143
  gsub(%r((access_token\\?":\\?")[\w\-\.]+)i, '\1[FILTERED]').
135
144
  gsub(%r((refresh_token\\?":\\?")\w+), '\1[FILTERED]').
@@ -263,7 +272,7 @@ module ActiveMerchant #:nodoc:
263
272
  oauth_parameters[:oauth_signature] = CGI.escape(Base64.encode64(hmac_signature).chomp.delete("\n"))
264
273
 
265
274
  # prepare Authorization header string
266
- oauth_parameters = Hash[oauth_parameters.sort_by { |k, _| k }]
275
+ oauth_parameters = oauth_parameters.sort_by { |k, _| k }.to_h
267
276
  oauth_headers = ["OAuth realm=\"#{@options[:realm]}\""]
268
277
  oauth_headers += oauth_parameters.map { |k, v| "#{k}=\"#{v}\"" }
269
278
 
@@ -358,19 +367,20 @@ module ActiveMerchant #:nodoc:
358
367
  rescue JSON::ParserError
359
368
  raise response_error
360
369
  end
370
+
361
371
  response_error.response.body
362
372
  end
363
373
 
364
374
  def refund_uri(authorization)
365
- "#{ENDPOINT}/#{CGI.escape(authorization.to_s)}/refunds"
375
+ "#{endpoint}/#{CGI.escape(authorization.to_s)}/refunds"
366
376
  end
367
377
 
368
378
  def capture_uri(authorization)
369
- "#{ENDPOINT}/#{CGI.escape(authorization.to_s)}/capture"
379
+ "#{endpoint}/#{CGI.escape(authorization.to_s)}/capture"
370
380
  end
371
381
 
372
382
  def void_uri(request_id)
373
- "#{VOID_ENDPOINT}/#{CGI.escape(request_id.to_s)}/void"
383
+ "#{void_endpoint}/#{CGI.escape(request_id.to_s)}/void"
374
384
  end
375
385
  end
376
386
  end
@@ -153,9 +153,13 @@ module ActiveMerchant
153
153
  response = json_error(response)
154
154
  end
155
155
 
156
- Response.new(success, message_from(success, response), response,
156
+ Response.new(
157
+ success,
158
+ message_from(success, response),
159
+ response,
157
160
  test: test?,
158
- authorization: authorization_from(response))
161
+ authorization: authorization_from(response)
162
+ )
159
163
  end
160
164
 
161
165
  def authorization_from(response)
@@ -251,7 +255,7 @@ module ActiveMerchant
251
255
 
252
256
  requires!(address, :name, :address1, :city, :zip, :country)
253
257
  country = Country.find(address[:country])
254
- mapped = {
258
+ {
255
259
  name: address[:name],
256
260
  street: address[:address1],
257
261
  city: address[:city],
@@ -259,7 +263,6 @@ module ActiveMerchant
259
263
  zip_code: address[:zip],
260
264
  country_code: country.code(:alpha3).value
261
265
  }
262
- mapped
263
266
  end
264
267
 
265
268
  def format_order_id(order_id)
@@ -2,8 +2,8 @@ require 'rexml/document'
2
2
  require 'digest/md5'
3
3
  require 'active_merchant/billing/gateways/quickpay/quickpay_common'
4
4
 
5
- module ActiveMerchant #:nodoc:
6
- module Billing #:nodoc:
5
+ module ActiveMerchant # :nodoc:
6
+ module Billing # :nodoc:
7
7
  class QuickpayV4to7Gateway < Gateway
8
8
  include QuickpayCommon
9
9
  self.live_url = self.test_url = 'https://secure.quickpay.dk/api'
@@ -164,9 +164,13 @@ module ActiveMerchant #:nodoc:
164
164
  def commit(action, params)
165
165
  response = parse(ssl_post(self.live_url, post_data(action, params)))
166
166
 
167
- Response.new(successful?(response), message_from(response), response,
167
+ Response.new(
168
+ successful?(response),
169
+ message_from(response),
170
+ response,
168
171
  test: test?,
169
- authorization: response[:transaction])
172
+ authorization: response[:transaction]
173
+ )
170
174
  end
171
175
 
172
176
  def successful?(response)
@@ -4,8 +4,8 @@ require 'digest/md5'
4
4
  require 'active_merchant/billing/gateways/quickpay/quickpay_v10'
5
5
  require 'active_merchant/billing/gateways/quickpay/quickpay_v4to7'
6
6
 
7
- module ActiveMerchant #:nodoc:
8
- module Billing #:nodoc:
7
+ module ActiveMerchant # :nodoc:
8
+ module Billing # :nodoc:
9
9
  class QuickpayGateway < Gateway
10
10
  self.abstract_class = true
11
11
 
@@ -1,5 +1,5 @@
1
- module ActiveMerchant #:nodoc:
2
- module Billing #:nodoc:
1
+ module ActiveMerchant # :nodoc:
2
+ module Billing # :nodoc:
3
3
  class QvalentGateway < Gateway
4
4
  self.display_name = 'Qvalent'
5
5
  self.homepage_url = 'https://www.qvalent.com/'
@@ -1,12 +1,19 @@
1
- module ActiveMerchant #:nodoc:
2
- module Billing #:nodoc:
1
+ module ActiveMerchant # :nodoc:
2
+ module Billing # :nodoc:
3
3
  class RapydGateway < Gateway
4
- self.test_url = 'https://sandboxapi.rapyd.net/v1/'
5
- self.live_url = 'https://api.rapyd.net/v1/'
4
+ class_attribute :payment_redirect_test, :payment_redirect_live
5
+
6
+ version 'v1'
7
+
8
+ self.test_url = "https://sandboxapi.rapyd.net/#{fetch_version}/"
9
+ self.live_url = "https://api.rapyd.net/#{fetch_version}/"
10
+
11
+ self.payment_redirect_test = "https://sandboxpayment-redirect.rapyd.net/#{fetch_version}/"
12
+ self.payment_redirect_live = "https://payment-redirect.rapyd.net/#{fetch_version}/"
6
13
 
7
14
  self.supported_countries = %w(CA CL CO DO SV PE PT VI AU HK IN ID JP MY NZ PH SG KR TW TH VN AD AT BE BA BG HR CY CZ DK EE FI FR GE DE GI GR GL HU IS IE IL IT LV LI LT LU MK MT MD MC ME NL GB NO PL RO RU SM SK SI ZA ES SE CH TR VA)
8
15
  self.default_currency = 'USD'
9
- self.supported_cardtypes = %i[visa master american_express discover]
16
+ self.supported_cardtypes = %i[visa master american_express discover verve]
10
17
 
11
18
  self.homepage_url = 'https://www.rapyd.net/'
12
19
  self.display_name = 'Rapyd Gateway'
@@ -38,6 +45,7 @@ module ActiveMerchant #:nodoc:
38
45
 
39
46
  def capture(money, authorization, options = {})
40
47
  post = {}
48
+ add_idempotency(options)
41
49
  commit(:post, "payments/#{add_reference(authorization)}/capture", post)
42
50
  end
43
51
 
@@ -47,12 +55,14 @@ module ActiveMerchant #:nodoc:
47
55
  add_invoice(post, money, options)
48
56
  add_metadata(post, options)
49
57
  add_ewallet(post, options)
58
+ add_idempotency(options)
50
59
 
51
60
  commit(:post, 'refunds', post)
52
61
  end
53
62
 
54
63
  def void(authorization, options = {})
55
64
  post = {}
65
+ add_idempotency(options)
56
66
  commit(:delete, "payments/#{add_reference(authorization)}", post)
57
67
  end
58
68
 
@@ -63,12 +73,13 @@ module ActiveMerchant #:nodoc:
63
73
  def store(payment, options = {})
64
74
  post = {}
65
75
  add_payment(post, payment, options)
66
- add_customer_object(post, payment, options)
76
+ add_customer_data(post, payment, options, 'store')
67
77
  add_metadata(post, options)
68
78
  add_ewallet(post, options)
69
79
  add_payment_fields(post, options)
70
- add_payment_urls(post, options)
80
+ add_payment_urls(post, options, 'store')
71
81
  add_address(post, payment, options)
82
+ add_idempotency(options)
72
83
  commit(:post, 'customers', post)
73
84
  end
74
85
 
@@ -100,18 +111,23 @@ module ActiveMerchant #:nodoc:
100
111
  def add_auth_purchase(post, money, payment, options)
101
112
  add_invoice(post, money, options)
102
113
  add_payment(post, payment, options)
103
- add_customer_object(post, payment, options)
114
+ add_customer_data(post, payment, options)
104
115
  add_3ds(post, payment, options)
105
116
  add_address(post, payment, options)
106
117
  add_metadata(post, options)
107
118
  add_ewallet(post, options)
108
119
  add_payment_fields(post, options)
109
120
  add_payment_urls(post, options)
110
- add_customer_id(post, options)
121
+ add_idempotency(options)
122
+ end
123
+
124
+ def add_idempotency(options)
125
+ @options[:idempotency] = options[:idempotency_key] if options[:idempotency_key]
111
126
  end
112
127
 
113
128
  def add_address(post, creditcard, options)
114
- return unless address = options[:billing_address]
129
+ address = options[:billing_address]
130
+ return unless valid_address?(address)
115
131
 
116
132
  post[:address] = {}
117
133
  # name and line_1 are required at the gateway
@@ -125,9 +141,21 @@ module ActiveMerchant #:nodoc:
125
141
  post[:address][:phone_number] = address[:phone].gsub(/\D/, '') if address[:phone]
126
142
  end
127
143
 
144
+ def valid_address?(address)
145
+ return false unless address
146
+
147
+ required_fields = %i[name address1 city state country zip]
148
+ missing_fields = required_fields.select { |field| address[field].to_s.strip.empty? }
149
+ missing_fields.empty?
150
+ end
151
+
128
152
  def add_invoice(post, money, options)
129
153
  post[:amount] = money.zero? ? 0 : amount(money).to_f.to_s
130
154
  post[:currency] = (options[:currency] || currency(money))
155
+ post[:merchant_reference_id] = options[:merchant_reference_id] || options[:order_id]
156
+ post[:requested_currency] = options[:requested_currency] if options[:requested_currency].present?
157
+ post[:fixed_side] = options[:fixed_side] if options[:fixed_side].present?
158
+ post[:expiration] = (options[:expiration_days] || 7).to_i.days.from_now.to_i if options[:fixed_side].present?
131
159
  end
132
160
 
133
161
  def add_payment(post, payment, options)
@@ -136,15 +164,27 @@ module ActiveMerchant #:nodoc:
136
164
  elsif payment.is_a?(Check)
137
165
  add_ach(post, payment, options)
138
166
  else
139
- add_token(post, payment, options)
167
+ add_tokens(post, payment, options)
140
168
  end
141
169
  end
142
170
 
143
171
  def add_stored_credential(post, options)
144
- return unless stored_credential = options[:stored_credential]
172
+ add_network_reference_id(post, options)
173
+ add_initiation_type(post, options)
174
+ end
175
+
176
+ def add_network_reference_id(post, options)
177
+ return unless (options[:stored_credential] && options[:stored_credential][:reason_type] == 'recurring') || options[:network_transaction_id]
145
178
 
146
- post[:payment_method][:fields][:network_reference_id] = stored_credential[:network_transaction_id] if stored_credential[:network_transaction_id]
147
- post[:initiation_type] = stored_credential[:reason_type] if stored_credential[:reason_type]
179
+ network_transaction_id = options[:network_transaction_id] || options[:stored_credential][:network_transaction_id]
180
+ post[:payment_method][:fields][:network_reference_id] = network_transaction_id unless network_transaction_id&.empty?
181
+ end
182
+
183
+ def add_initiation_type(post, options)
184
+ return unless options[:stored_credential] || options[:initiation_type]
185
+
186
+ initiation_type = options[:initiation_type] || options[:stored_credential][:reason_type]
187
+ post[:initiation_type] = initiation_type if initiation_type
148
188
  end
149
189
 
150
190
  def add_creditcard(post, payment, options)
@@ -154,14 +194,23 @@ module ActiveMerchant #:nodoc:
154
194
 
155
195
  post[:payment_method][:type] = options[:pm_type]
156
196
  pm_fields[:number] = payment.number
157
- pm_fields[:expiration_month] = payment.month.to_s
158
- pm_fields[:expiration_year] = payment.year.to_s
197
+ pm_fields[:expiration_month] = format(payment.month, :two_digits).to_s
198
+ pm_fields[:expiration_year] = format(payment.year, :two_digits).to_s
159
199
  pm_fields[:name] = "#{payment.first_name} #{payment.last_name}"
160
- pm_fields[:cvv] = payment.verification_value.to_s
161
-
200
+ pm_fields[:cvv] = payment.verification_value.to_s unless valid_network_transaction_id?(options) || payment.verification_value.blank?
201
+ pm_fields[:recurrence_type] = options[:recurrence_type] if options[:recurrence_type]
162
202
  add_stored_credential(post, options)
163
203
  end
164
204
 
205
+ def send_customer_object?(options)
206
+ options[:stored_credential] && options[:stored_credential][:reason_type] == 'recurring'
207
+ end
208
+
209
+ def valid_network_transaction_id?(options)
210
+ network_transaction_id = options[:network_tansaction_id] || options.dig(:stored_credential_options, :network_transaction_id) || options.dig(:stored_credential, :network_transaction_id)
211
+ return network_transaction_id.present?
212
+ end
213
+
165
214
  def add_ach(post, payment, options)
166
215
  post[:payment_method] = {}
167
216
  post[:payment_method][:fields] = {}
@@ -175,22 +224,27 @@ module ActiveMerchant #:nodoc:
175
224
  post[:payment_method][:fields][:payment_purpose] = options[:payment_purpose] if options[:payment_purpose]
176
225
  end
177
226
 
178
- def add_token(post, payment, options)
179
- return unless token = payment.split('|')[1]
227
+ def add_tokens(post, payment, options)
228
+ return unless payment.respond_to?(:split)
180
229
 
181
- post[:payment_method] = token
230
+ customer_id, card_id = payment.split('|')
231
+
232
+ post[:customer] = customer_id unless send_customer_object?(options)
233
+ post[:payment_method] = card_id
182
234
  end
183
235
 
184
236
  def add_3ds(post, payment, options)
185
- return unless three_d_secure = options[:three_d_secure]
186
-
187
- post[:payment_method_options] = {}
188
- post[:payment_method_options]['3d_required'] = three_d_secure[:required]
189
- post[:payment_method_options]['3d_version'] = three_d_secure[:version]
190
- post[:payment_method_options][:cavv] = three_d_secure[:cavv]
191
- post[:payment_method_options][:eci] = three_d_secure[:eci]
192
- post[:payment_method_options][:xid] = three_d_secure[:xid]
193
- post[:payment_method_options][:ds_trans_id] = three_d_secure[:ds_transaction_id]
237
+ if options[:execute_threed] == true
238
+ post[:payment_method_options] = { '3d_required' => true } if options[:force_3d_secure].to_s == 'true'
239
+ elsif three_d_secure = options[:three_d_secure]
240
+ post[:payment_method_options] = {}
241
+ post[:payment_method_options]['3d_required'] = three_d_secure[:required]
242
+ post[:payment_method_options]['3d_version'] = three_d_secure[:version]
243
+ post[:payment_method_options][:cavv] = three_d_secure[:cavv]
244
+ post[:payment_method_options][:eci] = three_d_secure[:eci]
245
+ post[:payment_method_options][:xid] = three_d_secure[:xid]
246
+ post[:payment_method_options][:ds_trans_id] = three_d_secure[:ds_transaction_id]
247
+ end
194
248
  end
195
249
 
196
250
  def add_metadata(post, options)
@@ -198,27 +252,69 @@ module ActiveMerchant #:nodoc:
198
252
  end
199
253
 
200
254
  def add_ewallet(post, options)
201
- post[:ewallet_id] = options[:ewallet_id] if options[:ewallet_id]
255
+ post[:ewallet] = options[:ewallet_id] if options[:ewallet_id]
202
256
  end
203
257
 
204
258
  def add_payment_fields(post, options)
205
- post[:payment] = {}
259
+ post[:description] = options[:description] if options[:description]
260
+ post[:statement_descriptor] = options[:statement_descriptor] if options[:statement_descriptor]
261
+ post[:save_payment_method] = options[:save_payment_method] if options[:save_payment_method]
262
+ end
263
+
264
+ def add_payment_urls(post, options, action = '')
265
+ if action == 'store'
266
+ url_location = post[:payment_method]
267
+ else
268
+ url_location = post
269
+ end
206
270
 
207
- post[:payment][:description] = options[:description] if options[:description]
208
- post[:payment][:statement_descriptor] = options[:statement_descriptor] if options[:statement_descriptor]
271
+ url_location[:complete_payment_url] = options[:complete_payment_url] if options[:complete_payment_url]
272
+ url_location[:error_payment_url] = options[:error_payment_url] if options[:error_payment_url]
209
273
  end
210
274
 
211
- def add_payment_urls(post, options)
212
- post[:complete_payment_url] = options[:complete_payment_url] if options[:complete_payment_url]
213
- post[:error_payment_url] = options[:error_payment_url] if options[:error_payment_url]
275
+ def add_customer_data(post, payment, options, action = '')
276
+ phone_number = options.dig(:billing_address, :phone) || options.dig(:billing_address, :phone_number)
277
+ post[:phone_number] = phone_number.gsub(/\D/, '') unless phone_number.nil?
278
+ post[:receipt_email] = options[:email] if payment.is_a?(String) && options[:customer_id].present? && !send_customer_object?(options)
279
+ return if payment.is_a?(String)
280
+ return add_customer_id(post, options) if options[:customer_id]
281
+
282
+ if action == 'store'
283
+ post.merge!(customer_fields(payment, options))
284
+ else
285
+ post[:customer] = customer_fields(payment, options) unless send_customer_object?(options)
286
+ end
214
287
  end
215
288
 
216
- def add_customer_object(post, payment, options)
217
- post[:name] = "#{payment.first_name} #{payment.last_name}" unless payment.is_a?(String)
218
- phone = options.dig(:billing_address, :phone) .gsub(/\D/, '') unless options[:billing_address].nil?
219
- post[:phone_number] = phone || options.dig(:customer, :phone_number)
220
- post[:email] = options[:email] || options.dig(:customer, :email)
221
- post[:addresses] = options.dig(:customer, :addresses) if USA_PAYMENT_METHODS.include?(options[:pm_type])
289
+ def customer_fields(payment, options)
290
+ return if options[:customer_id]
291
+
292
+ customer_address = address(options)
293
+ customer_data = {}
294
+ customer_data[:name] = "#{payment.first_name} #{payment.last_name}" unless payment.is_a?(String)
295
+ customer_data[:email] = options[:email] unless payment.is_a?(String) && options[:customer_id].blank?
296
+ customer_data[:phone_number] = options.dig(:billing_address, :phone) || options.dig(:billing_address, :phone_number)
297
+ customer_data[:phone_number] = customer_data[:phone_number].gsub(/\D/, '') if customer_data[:phone_number]
298
+ customer_data[:addresses] = [customer_address] if customer_address
299
+ customer_data
300
+ end
301
+
302
+ def address(options)
303
+ address = options[:billing_address]
304
+ return unless valid_address?(address)
305
+
306
+ formatted_address = {}
307
+
308
+ formatted_address[:name] = address[:name] if address[:name]
309
+ formatted_address[:line_1] = address[:address1] if address[:address1]
310
+ formatted_address[:line_2] = address[:address2] if address[:address2]
311
+ formatted_address[:city] = address[:city] if address[:city]
312
+ formatted_address[:state] = address[:state] if address[:state]
313
+ formatted_address[:country] = address[:country] if address[:country]
314
+ formatted_address[:zip] = address[:zip] if address[:zip]
315
+ formatted_address[:phone_number] = address[:phone].gsub(/\D/, '') if address[:phone]
316
+
317
+ formatted_address
222
318
  end
223
319
 
224
320
  def add_customer_id(post, options)
@@ -228,13 +324,21 @@ module ActiveMerchant #:nodoc:
228
324
  def parse(body)
229
325
  return {} if body.empty? || body.nil?
230
326
 
231
- JSON.parse(body)
327
+ parsed = JSON.parse(body)
328
+ parsed.is_a?(Hash) ? parsed : { 'status' => { 'status' => parsed } }
329
+ end
330
+
331
+ def url(action, url_override = nil)
332
+ if url_override.to_s == 'payment_redirect' && action == 'payments'
333
+ (self.test? ? self.payment_redirect_test : self.payment_redirect_live) + action.to_s
334
+ else
335
+ (self.test? ? self.test_url : self.live_url) + action.to_s
336
+ end
232
337
  end
233
338
 
234
339
  def commit(method, action, parameters)
235
- url = (test? ? test_url : live_url) + action.to_s
236
- rel_path = "#{method}/v1/#{action}"
237
- response = api_request(method, url, rel_path, parameters)
340
+ rel_path = "#{method}/#{fetch_version}/#{action}"
341
+ response = api_request(method, url(action, @options[:url_override]), rel_path, parameters)
238
342
 
239
343
  Response.new(
240
344
  success_from(response),
@@ -246,10 +350,25 @@ module ActiveMerchant #:nodoc:
246
350
  test: test?,
247
351
  error_code: error_code_from(response)
248
352
  )
353
+ rescue ActiveMerchant::ResponseError => e
354
+ response = e.response.body.present? ? parse(e.response.body) : { 'status' => { 'response_code' => e.response.msg } }
355
+ message = response['status'].slice('message', 'response_code').values.select(&:present?).first || ''
356
+ Response.new(false, message, response, test: test?, error_code: error_code_from(response))
357
+ end
358
+
359
+ # We need to revert the work of ActiveSupport JSON encoder to prevent discrepancies
360
+ # Between the signature and the actual request body
361
+ def revert_json_html_encoding!(string)
362
+ {
363
+ '\\u003e' => '>',
364
+ '\\u003c' => '<',
365
+ '\\u0026' => '&'
366
+ }.each { |k, v| string.gsub! k, v }
249
367
  end
250
368
 
251
369
  def api_request(method, url, rel_path, params)
252
370
  params == {} ? body = '' : body = params.to_json
371
+ revert_json_html_encoding!(body) if defined?(ActiveSupport::JSON::Encoding) && ActiveSupport::JSON::Encoding.escape_html_entities_in_json
253
372
  parse(ssl_request(method, url, body, headers(rel_path, body)))
254
373
  end
255
374
 
@@ -261,20 +380,20 @@ module ActiveMerchant #:nodoc:
261
380
  'access_key' => @options[:access_key],
262
381
  'salt' => salt,
263
382
  'timestamp' => timestamp,
264
- 'signature' => generate_hmac(rel_path, salt, timestamp, payload)
265
- }
383
+ 'signature' => generate_hmac(rel_path, salt, timestamp, payload),
384
+ 'idempotency' => @options[:idempotency]
385
+ }.delete_if { |_, value| value.nil? }
266
386
  end
267
387
 
268
388
  def generate_hmac(rel_path, salt, timestamp, payload)
269
389
  signature = "#{rel_path}#{salt}#{timestamp}#{@options[:access_key]}#{@options[:secret_key]}#{payload}"
270
- hash = Base64.urlsafe_encode64(OpenSSL::HMAC.hexdigest('sha256', @options[:secret_key], signature))
271
- hash
390
+ Base64.urlsafe_encode64(OpenSSL::HMAC.hexdigest('sha256', @options[:secret_key], signature))
272
391
  end
273
392
 
274
393
  def avs_result(response)
275
394
  return nil unless (code = response.dig('data', 'payment_method_data', 'acs_check'))
276
395
 
277
- AVSResult.new(code: code)
396
+ AVSResult.new(code:)
278
397
  end
279
398
 
280
399
  def cvv_result(response)
@@ -303,7 +422,7 @@ module ActiveMerchant #:nodoc:
303
422
  end
304
423
 
305
424
  def error_code_from(response)
306
- response.dig('status', 'error_code') unless success_from(response)
425
+ response.dig('status', 'error_code') || response.dig('status', 'response_code') || ''
307
426
  end
308
427
 
309
428
  def handle_response(response)