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,952 @@
1
+ require 'active_merchant/billing/gateways/braintree/braintree_common'
2
+ require 'active_merchant/billing/gateways/braintree/token_nonce'
3
+ require 'active_support/core_ext/array/extract_options'
4
+
5
+ begin
6
+ require 'braintree'
7
+ rescue LoadError
8
+ raise 'Could not load the braintree gem. Use `gem install braintree` to install it.'
9
+ end
10
+
11
+ raise 'Need braintree gem >= 2.0.0.' unless Braintree::Version::Major >= 2 && Braintree::Version::Minor >= 0
12
+
13
+ module ActiveMerchant #:nodoc:
14
+ module Billing #:nodoc:
15
+ # For more information on the Braintree Gateway please visit their
16
+ # {Developer Portal}[https://www.braintreepayments.com/developers]
17
+ #
18
+ # ==== About this implementation
19
+ #
20
+ # This implementation leverages the Braintree-authored ruby gem:
21
+ # https://github.com/braintree/braintree_ruby
22
+ #
23
+ # ==== Debugging Information
24
+ #
25
+ # Setting an ActiveMerchant +wiredump_device+ will automatically
26
+ # configure the Braintree logger (via the Braintree gem's
27
+ # configuration) when the BraintreeBlueGateway is instantiated.
28
+ # Additionally, the log level will be set to +DEBUG+. Therefore,
29
+ # all you have to do is set the +wiredump_device+ and you'll get
30
+ # your debug output from your HTTP interactions with the remote
31
+ # gateway. (Don't enable this in production.) The ActiveMerchant
32
+ # implementation doesn't mess with the Braintree::Configuration
33
+ # globals at all, so there won't be any side effects outside
34
+ # Active Merchant.
35
+ #
36
+ # If no +wiredump_device+ is set, the logger in
37
+ # +Braintree::Configuration.logger+ will be cloned and the log
38
+ # level set to +WARN+.
39
+ #
40
+ class BraintreeBlueGateway < Gateway
41
+ include BraintreeCommon
42
+ include Empty
43
+
44
+ self.display_name = 'Braintree (Blue Platform)'
45
+
46
+ ERROR_CODES = {
47
+ cannot_refund_if_unsettled: 91506
48
+ }
49
+
50
+ DIRECT_BANK_ERROR = 'Direct bank account transactions are not supported. Bank accounts must be successfully stored before use.'.freeze
51
+
52
+ def initialize(options = {})
53
+ requires!(options, :merchant_id, :public_key, :private_key)
54
+ @merchant_account_id = options[:merchant_account_id]
55
+
56
+ super
57
+
58
+ if wiredump_device.present?
59
+ logger = (Logger === wiredump_device ? wiredump_device : Logger.new(wiredump_device))
60
+ logger.level = Logger::DEBUG
61
+ else
62
+ logger = Braintree::Configuration.logger.clone
63
+ logger.level = Logger::WARN
64
+ end
65
+
66
+ @configuration = Braintree::Configuration.new(
67
+ merchant_id: options[:merchant_id],
68
+ public_key: options[:public_key],
69
+ private_key: options[:private_key],
70
+ environment: (options[:environment] || (test? ? :sandbox : :production)).to_sym,
71
+ custom_user_agent: "ActiveMerchant #{ActiveMerchant::VERSION}",
72
+ logger: options[:logger] || logger
73
+ )
74
+
75
+ @braintree_gateway = Braintree::Gateway.new(@configuration)
76
+ end
77
+
78
+ def setup_purchase
79
+ commit do
80
+ Response.new(true, 'Client token created', { client_token: @braintree_gateway.client_token.generate })
81
+ end
82
+ end
83
+
84
+ def authorize(money, credit_card_or_vault_id, options = {})
85
+ return Response.new(false, DIRECT_BANK_ERROR) if credit_card_or_vault_id.is_a? Check
86
+
87
+ create_transaction(:sale, money, credit_card_or_vault_id, options)
88
+ end
89
+
90
+ def capture(money, authorization, options = {})
91
+ if options[:partial_capture] == true
92
+ commit do
93
+ result = @braintree_gateway.transaction.submit_for_partial_settlement(authorization, localized_amount(money, options[:currency] || default_currency).to_s)
94
+ response_from_result(result)
95
+ end
96
+ else
97
+ commit do
98
+ result = @braintree_gateway.transaction.submit_for_settlement(authorization, localized_amount(money, options[:currency] || default_currency).to_s)
99
+ response_from_result(result)
100
+ end
101
+ end
102
+ end
103
+
104
+ def purchase(money, credit_card_or_vault_id, options = {})
105
+ authorize(money, credit_card_or_vault_id, options.merge(submit_for_settlement: true))
106
+ end
107
+
108
+ def credit(money, credit_card_or_vault_id, options = {})
109
+ create_transaction(:credit, money, credit_card_or_vault_id, options)
110
+ end
111
+
112
+ def refund(*args)
113
+ # legacy signature: #refund(transaction_id, options = {})
114
+ # new signature: #refund(money, transaction_id, options = {})
115
+ money, transaction_id, options = extract_refund_args(args)
116
+ money = localized_amount(money, options[:currency] || default_currency).to_s if money
117
+
118
+ commit do
119
+ response = response_from_result(@braintree_gateway.transaction.refund(transaction_id, money))
120
+
121
+ if !response.success? && options[:force_full_refund_if_unsettled] &&
122
+ response.message =~ /#{ERROR_CODES[:cannot_refund_if_unsettled]}/
123
+ void(transaction_id)
124
+ else
125
+ response
126
+ end
127
+ end
128
+ end
129
+
130
+ def void(authorization, options = {})
131
+ commit do
132
+ response_from_result(@braintree_gateway.transaction.void(authorization))
133
+ end
134
+ end
135
+
136
+ def verify(creditcard, options = {})
137
+ if options[:allow_card_verification] == true
138
+ options.delete(:allow_card_verification)
139
+ exp_month = creditcard.month.to_s
140
+ exp_year = creditcard.year.to_s
141
+ expiration = "#{exp_month}/#{exp_year}"
142
+ payload = {
143
+ credit_card: {
144
+ number: creditcard.number,
145
+ expiration_date: expiration,
146
+ cvv: creditcard.verification_value,
147
+ billing_address: {
148
+ postal_code: options[:billing_address][:zip]
149
+ }
150
+ }
151
+ }
152
+ commit do
153
+ result = @braintree_gateway.verification.create(payload)
154
+ response = Response.new(result.success?, message_from_transaction_result(result), response_options(result))
155
+ response.cvv_result['message'] = ''
156
+ response.cvv_result['code'] = response.params['cvv_result'] if response.params['cvv_result']
157
+ response.avs_result['code'] = response.params['avs_result'][:code] if response.params.dig('avs_result', :code)
158
+ response
159
+ end
160
+
161
+ else
162
+ MultiResponse.run(:use_first_response) do |r|
163
+ r.process { authorize(100, creditcard, options) }
164
+ r.process(:ignore_result) { void(r.authorization, options) }
165
+ end
166
+ end
167
+ end
168
+
169
+ def store(payment_method, options = {})
170
+ return Response.new(false, bank_account_errors(payment_method, options)) if payment_method.is_a?(Check) && bank_account_errors(payment_method, options).present?
171
+
172
+ MultiResponse.run do |r|
173
+ r.process { check_customer_exists(options[:customer]) }
174
+ process_by = payment_method.is_a?(Check) ? :store_bank_account : :store_credit_card
175
+ send process_by, payment_method, options, r
176
+ end
177
+ end
178
+
179
+ def update(vault_id, creditcard, options = {})
180
+ braintree_credit_card = nil
181
+ commit do
182
+ braintree_credit_card = @braintree_gateway.customer.find(vault_id).credit_cards.detect(&:default?)
183
+ return Response.new(false, 'Braintree::NotFoundError') if braintree_credit_card.nil?
184
+
185
+ options[:update_existing_token] = braintree_credit_card.token
186
+ credit_card_params = merge_credit_card_options({
187
+ credit_card: {
188
+ cardholder_name: creditcard.name,
189
+ number: creditcard.number,
190
+ cvv: creditcard.verification_value,
191
+ expiration_month: creditcard.month.to_s.rjust(2, '0'),
192
+ expiration_year: creditcard.year.to_s
193
+ }
194
+ }, options)[:credit_card]
195
+
196
+ result = @braintree_gateway.customer.update(vault_id,
197
+ first_name: creditcard.first_name,
198
+ last_name: creditcard.last_name,
199
+ email: scrub_email(options[:email]),
200
+ phone: phone_from(options),
201
+ credit_card: credit_card_params)
202
+ Response.new(result.success?, message_from_result(result),
203
+ braintree_customer: (customer_hash(@braintree_gateway.customer.find(vault_id), :include_credit_cards) if result.success?),
204
+ customer_vault_id: (result.customer.id if result.success?))
205
+ end
206
+ end
207
+
208
+ def unstore(customer_vault_id, options = {})
209
+ commit do
210
+ if !customer_vault_id && options[:credit_card_token]
211
+ @braintree_gateway.credit_card.delete(options[:credit_card_token])
212
+ else
213
+ @braintree_gateway.customer.delete(customer_vault_id)
214
+ end
215
+ Response.new(true, 'OK')
216
+ end
217
+ end
218
+ alias delete unstore
219
+
220
+ def supports_network_tokenization?
221
+ true
222
+ end
223
+
224
+ def verify_credentials
225
+ begin
226
+ @braintree_gateway.transaction.find('non_existent_token')
227
+ rescue Braintree::AuthenticationError
228
+ return false
229
+ rescue Braintree::NotFoundError
230
+ return true
231
+ end
232
+
233
+ true
234
+ end
235
+
236
+ private
237
+
238
+ def check_customer_exists(customer_vault_id)
239
+ return Response.new true, 'Customer not found', { exists: false } if customer_vault_id.blank?
240
+
241
+ commit do
242
+ @braintree_gateway.customer.find(customer_vault_id)
243
+ ActiveMerchant::Billing::Response.new(true, 'Customer found', { exists: true }, authorization: customer_vault_id)
244
+ rescue Braintree::NotFoundError
245
+ ActiveMerchant::Billing::Response.new(true, 'Customer not found', { exists: false })
246
+ end
247
+ end
248
+
249
+ def add_customer_with_credit_card(creditcard, options)
250
+ commit do
251
+ if options[:payment_method_nonce]
252
+ credit_card_params = { payment_method_nonce: options[:payment_method_nonce] }
253
+ else
254
+ credit_card_params = {
255
+ credit_card: {
256
+ cardholder_name: creditcard.name,
257
+ number: creditcard.number,
258
+ cvv: creditcard.verification_value,
259
+ expiration_month: creditcard.month.to_s.rjust(2, '0'),
260
+ expiration_year: creditcard.year.to_s,
261
+ token: options[:credit_card_token]
262
+ }
263
+ }
264
+ end
265
+ parameters = {
266
+ first_name: creditcard.first_name,
267
+ last_name: creditcard.last_name,
268
+ email: scrub_email(options[:email]),
269
+ phone: phone_from(options),
270
+ id: options[:customer],
271
+ device_data: options[:device_data]
272
+ }.merge credit_card_params
273
+ result = @braintree_gateway.customer.create(merge_credit_card_options(parameters, options))
274
+ Response.new(result.success?, message_from_result(result),
275
+ {
276
+ braintree_customer: (customer_hash(result.customer, :include_credit_cards) if result.success?),
277
+ customer_vault_id: (result.customer.id if result.success?),
278
+ credit_card_token: (result.customer.credit_cards[0].token if result.success?)
279
+ },
280
+ authorization: (result.customer.id if result.success?))
281
+ end
282
+ end
283
+
284
+ def add_credit_card_to_customer(credit_card, options)
285
+ commit do
286
+ parameters = {
287
+ customer_id: options[:customer],
288
+ token: options[:credit_card_token],
289
+ cardholder_name: credit_card.name,
290
+ number: credit_card.number,
291
+ cvv: credit_card.verification_value,
292
+ expiration_month: credit_card.month.to_s.rjust(2, '0'),
293
+ expiration_year: credit_card.year.to_s,
294
+ device_data: options[:device_data]
295
+ }
296
+ if options[:billing_address]
297
+ address = map_address(options[:billing_address])
298
+ parameters[:billing_address] = address unless address.all? { |_k, v| empty?(v) }
299
+ end
300
+
301
+ result = @braintree_gateway.credit_card.create(parameters)
302
+ ActiveMerchant::Billing::Response.new(
303
+ result.success?,
304
+ message_from_result(result),
305
+ {
306
+ customer_vault_id: (result.credit_card.customer_id if result.success?),
307
+ credit_card_token: (result.credit_card.token if result.success?)
308
+ },
309
+ authorization: (result.credit_card.customer_id if result.success?)
310
+ )
311
+ end
312
+ end
313
+
314
+ def scrub_email(email)
315
+ return nil unless email.present?
316
+ return nil if
317
+ email !~ /^.+@[^\.]+(\.[^\.]+)+[a-z]$/i ||
318
+ email =~ /\.(con|met)$/i
319
+
320
+ email
321
+ end
322
+
323
+ def scrub_zip(zip)
324
+ return nil unless zip.present?
325
+ return nil if
326
+ zip.gsub(/[^a-z0-9]/i, '').length > 9 ||
327
+ zip =~ /[^a-z0-9\- ]/i
328
+
329
+ zip
330
+ end
331
+
332
+ def merge_credit_card_options(parameters, options)
333
+ valid_options = {}
334
+ options.each do |key, value|
335
+ valid_options[key] = value if %i[update_existing_token verify_card verification_merchant_account_id].include?(key)
336
+ end
337
+
338
+ valid_options[:verification_merchant_account_id] ||= @merchant_account_id if valid_options.include?(:verify_card) && @merchant_account_id
339
+
340
+ parameters[:credit_card] ||= {}
341
+ parameters[:credit_card][:options] = valid_options
342
+ if options[:billing_address]
343
+ address = map_address(options[:billing_address])
344
+ parameters[:credit_card][:billing_address] = address unless address.all? { |_k, v| empty?(v) }
345
+ end
346
+ parameters
347
+ end
348
+
349
+ def phone_from(options)
350
+ options[:phone] || options.dig(:billing_address, :phone) || options.dig(:billing_address, :phone_number)
351
+ end
352
+
353
+ def map_address(address)
354
+ mapped = {
355
+ street_address: address[:address1],
356
+ extended_address: address[:address2],
357
+ company: address[:company],
358
+ locality: address[:city],
359
+ region: address[:state],
360
+ postal_code: scrub_zip(address[:zip])
361
+ }
362
+
363
+ mapped[:country_code_alpha2] = (address[:country] || address[:country_code_alpha2]) if address[:country] || address[:country_code_alpha2]
364
+ mapped[:country_name] = address[:country_name] if address[:country_name]
365
+ mapped[:country_code_alpha3] = address[:country_code_alpha3] if address[:country_code_alpha3]
366
+ mapped[:country_code_alpha3] ||= Country.find(address[:country]).code(:alpha3).value unless address[:country].blank?
367
+ mapped[:country_code_numeric] = address[:country_code_numeric] if address[:country_code_numeric]
368
+
369
+ mapped
370
+ end
371
+
372
+ def commit(&block)
373
+ yield
374
+ rescue Braintree::BraintreeError => ex
375
+ Response.new(false, ex.class.to_s)
376
+ end
377
+
378
+ def message_from_result(result)
379
+ if result.success?
380
+ 'OK'
381
+ elsif result.errors.any?
382
+ result.errors.map { |e| "#{e.message} (#{e.code})" }.join(' ')
383
+ elsif result.credit_card_verification
384
+ "Processor declined: #{result.credit_card_verification.processor_response_text} (#{result.credit_card_verification.processor_response_code})"
385
+ else
386
+ result.message.to_s
387
+ end
388
+ end
389
+
390
+ def response_from_result(result)
391
+ response_hash = { braintree_transaction: transaction_hash(result) }
392
+
393
+ Response.new(
394
+ result.success?,
395
+ message_from_result(result),
396
+ response_hash,
397
+ authorization: result.transaction&.id,
398
+ test: test?
399
+ )
400
+ end
401
+
402
+ def response_params(result)
403
+ params = {}
404
+ params[:customer_vault_id] = result.transaction.customer_details.id if result.success?
405
+ params[:braintree_transaction] = transaction_hash(result)
406
+ params
407
+ end
408
+
409
+ def response_options(result)
410
+ options = {}
411
+ if result.credit_card_verification
412
+ options[:authorization] = result.credit_card_verification.id
413
+ options[:avs_result] = { code: avs_code_from(result.credit_card_verification) }
414
+ options[:cvv_result] = result.credit_card_verification.cvv_response_code
415
+ elsif result.transaction
416
+ options[:authorization] = result.transaction.id
417
+ options[:avs_result] = { code: avs_code_from(result.transaction) }
418
+ options[:cvv_result] = result.transaction.cvv_response_code
419
+ end
420
+ options[:test] = test?
421
+ options
422
+ end
423
+
424
+ def avs_code_from(transaction)
425
+ transaction.avs_error_response_code ||
426
+ avs_mapping["street: #{transaction.avs_street_address_response_code}, zip: #{transaction.avs_postal_code_response_code}"]
427
+ end
428
+
429
+ def avs_mapping
430
+ {
431
+ 'street: M, zip: M' => 'M',
432
+ 'street: M, zip: N' => 'A',
433
+ 'street: M, zip: U' => 'B',
434
+ 'street: M, zip: I' => 'B',
435
+ 'street: M, zip: A' => 'B',
436
+
437
+ 'street: N, zip: M' => 'Z',
438
+ 'street: N, zip: N' => 'C',
439
+ 'street: N, zip: U' => 'C',
440
+ 'street: N, zip: I' => 'C',
441
+ 'street: N, zip: A' => 'C',
442
+
443
+ 'street: U, zip: M' => 'P',
444
+ 'street: U, zip: N' => 'N',
445
+ 'street: U, zip: U' => 'I',
446
+ 'street: U, zip: I' => 'I',
447
+ 'street: U, zip: A' => 'I',
448
+
449
+ 'street: I, zip: M' => 'P',
450
+ 'street: I, zip: N' => 'C',
451
+ 'street: I, zip: U' => 'I',
452
+ 'street: I, zip: I' => 'I',
453
+ 'street: I, zip: A' => 'I',
454
+
455
+ 'street: A, zip: M' => 'P',
456
+ 'street: A, zip: N' => 'C',
457
+ 'street: A, zip: U' => 'I',
458
+ 'street: A, zip: I' => 'I',
459
+ 'street: A, zip: A' => 'I',
460
+
461
+ 'street: B, zip: B' => 'B'
462
+ }
463
+ end
464
+
465
+ def message_from_transaction_result(result)
466
+ if result.transaction && result.transaction.status == 'gateway_rejected'
467
+ 'Transaction declined - gateway rejected'
468
+ elsif result.transaction
469
+ "#{result.transaction.processor_response_code} #{result.transaction.processor_response_text}"
470
+ else
471
+ message_from_result(result)
472
+ end
473
+ end
474
+
475
+ def response_code_from_result(result)
476
+ if result.transaction
477
+ result.transaction.processor_response_code
478
+ elsif result.errors.size == 0 && result.credit_card_verification
479
+ result.credit_card_verification.processor_response_code
480
+ elsif result.errors.size > 0
481
+ result.errors.first.code
482
+ end
483
+ end
484
+
485
+ def additional_processor_response_from_result(result)
486
+ result.transaction&.additional_processor_response
487
+ end
488
+
489
+ def create_transaction(transaction_type, money, credit_card_or_vault_id, options)
490
+ transaction_params = create_transaction_parameters(money, credit_card_or_vault_id, options)
491
+ commit do
492
+ result = @braintree_gateway.transaction.send(transaction_type, transaction_params)
493
+ make_default_payment_method_token(result) if options.dig(:paypal, :paypal_flow_type) == 'checkout_with_vault' && result.success?
494
+ response = Response.new(result.success?, message_from_transaction_result(result), response_params(result), response_options(result))
495
+ response.cvv_result['message'] = ''
496
+ response
497
+ end
498
+ end
499
+
500
+ def make_default_payment_method_token(result)
501
+ @braintree_gateway.customer.update(
502
+ result.transaction.customer_details.id,
503
+ default_payment_method_token: result.transaction.paypal_details.implicitly_vaulted_payment_method_token
504
+ )
505
+ end
506
+
507
+ def extract_refund_args(args)
508
+ options = args.extract_options!
509
+
510
+ # money, transaction_id, options
511
+ if args.length == 1 # legacy signature
512
+ return nil, args[0], options
513
+ elsif args.length == 2
514
+ return args[0], args[1], options
515
+ else
516
+ raise ArgumentError, "wrong number of arguments (#{args.length} for 2)"
517
+ end
518
+ end
519
+
520
+ def customer_hash(customer, include_credit_cards = false)
521
+ hash = {
522
+ 'email' => customer.email,
523
+ 'phone' => customer.phone,
524
+ 'first_name' => customer.first_name,
525
+ 'last_name' => customer.last_name,
526
+ 'id' => customer.id
527
+ }
528
+
529
+ if include_credit_cards
530
+ hash['credit_cards'] = customer.credit_cards.map do |cc|
531
+ {
532
+ 'bin' => cc.bin,
533
+ 'expiration_date' => cc.expiration_date,
534
+ 'token' => cc.token,
535
+ 'last_4' => cc.last_4,
536
+ 'card_type' => cc.card_type,
537
+ 'masked_number' => cc.masked_number
538
+ }
539
+ end
540
+ end
541
+
542
+ hash
543
+ end
544
+
545
+ def transaction_hash(result)
546
+ unless result.success?
547
+ return { 'processor_response_code' => response_code_from_result(result),
548
+ 'additional_processor_response' => additional_processor_response_from_result(result) }
549
+ end
550
+
551
+ transaction = result.transaction
552
+ if transaction.vault_customer
553
+ vault_customer = {
554
+ }
555
+ vault_customer['credit_cards'] = transaction.vault_customer.credit_cards.map do |cc|
556
+ {
557
+ 'bin' => cc.bin
558
+ }
559
+ end
560
+ else
561
+ vault_customer = nil
562
+ end
563
+
564
+ customer_details = {
565
+ 'id' => transaction.customer_details.id,
566
+ 'email' => transaction.customer_details.email,
567
+ 'phone' => transaction.customer_details.phone
568
+ }
569
+
570
+ billing_details = {
571
+ 'street_address' => transaction.billing_details.street_address,
572
+ 'extended_address' => transaction.billing_details.extended_address,
573
+ 'company' => transaction.billing_details.company,
574
+ 'locality' => transaction.billing_details.locality,
575
+ 'region' => transaction.billing_details.region,
576
+ 'postal_code' => transaction.billing_details.postal_code,
577
+ 'country_name' => transaction.billing_details.country_name
578
+ }
579
+
580
+ shipping_details = {
581
+ 'street_address' => transaction.shipping_details.street_address,
582
+ 'extended_address' => transaction.shipping_details.extended_address,
583
+ 'company' => transaction.shipping_details.company,
584
+ 'locality' => transaction.shipping_details.locality,
585
+ 'region' => transaction.shipping_details.region,
586
+ 'postal_code' => transaction.shipping_details.postal_code,
587
+ 'country_name' => transaction.shipping_details.country_name
588
+ }
589
+ credit_card_details = {
590
+ 'masked_number' => transaction.credit_card_details.masked_number,
591
+ 'bin' => transaction.credit_card_details.bin,
592
+ 'last_4' => transaction.credit_card_details.last_4,
593
+ 'card_type' => transaction.credit_card_details.card_type,
594
+ 'token' => transaction.credit_card_details.token
595
+ }
596
+
597
+ if transaction.risk_data
598
+ risk_data = {
599
+ 'id' => transaction.risk_data.id,
600
+ 'decision' => transaction.risk_data.decision,
601
+ 'device_data_captured' => transaction.risk_data.device_data_captured,
602
+ 'fraud_service_provider' => transaction.risk_data.fraud_service_provider
603
+ }
604
+ else
605
+ risk_data = nil
606
+ end
607
+
608
+ {
609
+ 'order_id' => transaction.order_id,
610
+ 'amount' => transaction.amount.to_s,
611
+ 'status' => transaction.status,
612
+ 'credit_card_details' => credit_card_details,
613
+ 'customer_details' => customer_details,
614
+ 'billing_details' => billing_details,
615
+ 'shipping_details' => shipping_details,
616
+ 'vault_customer' => vault_customer,
617
+ 'merchant_account_id' => transaction.merchant_account_id,
618
+ 'risk_data' => risk_data,
619
+ 'network_transaction_id' => transaction.network_transaction_id || nil,
620
+ 'processor_response_code' => response_code_from_result(result),
621
+ 'processor_authorization_code' => transaction.processor_authorization_code,
622
+ 'recurring' => transaction.recurring
623
+ }
624
+ end
625
+
626
+ def create_transaction_parameters(money, credit_card_or_vault_id, options)
627
+ parameters = {
628
+ amount: localized_amount(money, options[:currency] || default_currency).to_s,
629
+ order_id: options[:order_id],
630
+ customer: {
631
+ id: options[:store] == true ? '' : options[:store],
632
+ email: scrub_email(options[:email]),
633
+ phone: phone_from(options)
634
+ },
635
+ options: {
636
+ store_in_vault: options[:store] ? true : false,
637
+ submit_for_settlement: options[:submit_for_settlement],
638
+ hold_in_escrow: options[:hold_in_escrow]
639
+ }
640
+ }
641
+
642
+ parameters[:custom_fields] = options[:custom_fields]
643
+ parameters[:device_data] = options[:device_data] if options[:device_data]
644
+ parameters[:service_fee_amount] = options[:service_fee_amount] if options[:service_fee_amount]
645
+
646
+ add_account_type(parameters, options) if options[:account_type]
647
+ add_skip_options(parameters, options)
648
+ add_merchant_account_id(parameters, options)
649
+ add_profile_id(parameters, options)
650
+
651
+ add_payment_method(parameters, credit_card_or_vault_id, options)
652
+ add_stored_credential_data(parameters, credit_card_or_vault_id, options)
653
+ add_addresses(parameters, options)
654
+
655
+ add_descriptor(parameters, options)
656
+ add_risk_data(parameters, options)
657
+ add_paypal_options(parameters, options)
658
+ add_travel_data(parameters, options) if options[:travel_data]
659
+ add_lodging_data(parameters, options) if options[:lodging_data]
660
+ add_channel(parameters, options)
661
+ add_transaction_source(parameters, options)
662
+
663
+ add_level_2_data(parameters, options)
664
+ add_level_3_data(parameters, options)
665
+
666
+ add_3ds_info(parameters, options[:three_d_secure])
667
+
668
+ if options[:payment_method_nonce].is_a?(String)
669
+ parameters.delete(:customer)
670
+ parameters[:payment_method_nonce] = options[:payment_method_nonce]
671
+ end
672
+
673
+ parameters
674
+ end
675
+
676
+ def add_account_type(parameters, options)
677
+ parameters[:options][:credit_card] = {}
678
+ parameters[:options][:credit_card][:account_type] = options[:account_type]
679
+ end
680
+
681
+ def add_skip_options(parameters, options)
682
+ parameters[:options][:skip_advanced_fraud_checking] = options[:skip_advanced_fraud_checking] if options[:skip_advanced_fraud_checking]
683
+ parameters[:options][:skip_avs] = options[:skip_avs] if options[:skip_avs]
684
+ parameters[:options][:skip_cvv] = options[:skip_cvv] if options[:skip_cvv]
685
+ end
686
+
687
+ def add_merchant_account_id(parameters, options)
688
+ return unless merchant_account_id = (options[:merchant_account_id] || @merchant_account_id)
689
+
690
+ parameters[:merchant_account_id] = merchant_account_id
691
+ end
692
+
693
+ def add_profile_id(parameters, options)
694
+ return unless profile_id = options[:venmo_profile_id]
695
+
696
+ parameters[:options][:venmo] = {}
697
+ parameters[:options][:venmo][:profile_id] = profile_id
698
+ end
699
+
700
+ def add_transaction_source(parameters, options)
701
+ parameters[:transaction_source] = options[:transaction_source] if options[:transaction_source]
702
+ parameters[:transaction_source] = 'recurring' if options[:recurring]
703
+ end
704
+
705
+ def add_addresses(parameters, options)
706
+ parameters[:billing] = map_address(options[:billing_address]) if options[:billing_address]
707
+ parameters[:shipping] = map_address(options[:shipping_address]) if options[:shipping_address]
708
+ end
709
+
710
+ def add_channel(parameters, options)
711
+ channel = @options[:channel] || application_id
712
+ parameters[:channel] = channel if channel
713
+ end
714
+
715
+ def add_descriptor(parameters, options)
716
+ return unless options[:descriptor_name] || options[:descriptor_phone] || options[:descriptor_url]
717
+
718
+ parameters[:descriptor] = {
719
+ name: options[:descriptor_name],
720
+ phone: options[:descriptor_phone],
721
+ url: options[:descriptor_url]
722
+ }
723
+ end
724
+
725
+ def add_risk_data(parameters, options)
726
+ return unless options[:risk_data]
727
+
728
+ parameters[:risk_data] = {
729
+ customer_browser: options[:risk_data][:customer_browser],
730
+ customer_ip: options[:risk_data][:customer_ip]
731
+ }
732
+ end
733
+
734
+ def add_paypal_options(parameters, options)
735
+ return unless options[:paypal_custom_field] || options[:paypal_description]
736
+
737
+ parameters[:options][:paypal] = {
738
+ custom_field: options[:paypal_custom_field],
739
+ description: options[:paypal_description]
740
+ }
741
+ end
742
+
743
+ def add_level_2_data(parameters, options)
744
+ parameters[:tax_amount] = options[:tax_amount] if options[:tax_amount]
745
+ parameters[:tax_exempt] = options[:tax_exempt] if options[:tax_exempt]
746
+ parameters[:purchase_order_number] = options[:purchase_order_number] if options[:purchase_order_number]
747
+ end
748
+
749
+ def add_level_3_data(parameters, options)
750
+ parameters[:shipping_amount] = options[:shipping_amount] if options[:shipping_amount]
751
+ parameters[:discount_amount] = options[:discount_amount] if options[:discount_amount]
752
+ parameters[:ships_from_postal_code] = options[:ships_from_postal_code] if options[:ships_from_postal_code]
753
+
754
+ parameters[:line_items] = options[:line_items] if options[:line_items]
755
+ end
756
+
757
+ def add_travel_data(parameters, options)
758
+ parameters[:industry] = {
759
+ industry_type: Braintree::Transaction::IndustryType::TravelAndCruise,
760
+ data: {}
761
+ }
762
+
763
+ parameters[:industry][:data][:travel_package] = options[:travel_data][:travel_package] if options[:travel_data][:travel_package]
764
+ parameters[:industry][:data][:departure_date] = options[:travel_data][:departure_date] if options[:travel_data][:departure_date]
765
+ parameters[:industry][:data][:lodging_check_in_date] = options[:travel_data][:lodging_check_in_date] if options[:travel_data][:lodging_check_in_date]
766
+ parameters[:industry][:data][:lodging_check_out_date] = options[:travel_data][:lodging_check_out_date] if options[:travel_data][:lodging_check_out_date]
767
+ parameters[:industry][:data][:lodging_name] = options[:travel_data][:lodging_name] if options[:travel_data][:lodging_name]
768
+ end
769
+
770
+ def add_lodging_data(parameters, options)
771
+ parameters[:industry] = {
772
+ industry_type: Braintree::Transaction::IndustryType::Lodging,
773
+ data: {}
774
+ }
775
+
776
+ parameters[:industry][:data][:folio_number] = options[:lodging_data][:folio_number] if options[:lodging_data][:folio_number]
777
+ parameters[:industry][:data][:check_in_date] = options[:lodging_data][:check_in_date] if options[:lodging_data][:check_in_date]
778
+ parameters[:industry][:data][:check_out_date] = options[:lodging_data][:check_out_date] if options[:lodging_data][:check_out_date]
779
+ parameters[:industry][:data][:room_rate] = options[:lodging_data][:room_rate] if options[:lodging_data][:room_rate]
780
+ end
781
+
782
+ def add_3ds_info(parameters, three_d_secure_opts)
783
+ return if empty?(three_d_secure_opts)
784
+
785
+ pass_thru = {}
786
+
787
+ pass_thru[:three_d_secure_version] = three_d_secure_opts[:version] if three_d_secure_opts[:version]
788
+ pass_thru[:eci_flag] = three_d_secure_opts[:eci] if three_d_secure_opts[:eci]
789
+ pass_thru[:cavv_algorithm] = three_d_secure_opts[:cavv_algorithm] if three_d_secure_opts[:cavv_algorithm]
790
+ pass_thru[:cavv] = three_d_secure_opts[:cavv] if three_d_secure_opts[:cavv]
791
+ pass_thru[:directory_response] = three_d_secure_opts[:directory_response_status] if three_d_secure_opts[:directory_response_status]
792
+ pass_thru[:authentication_response] = three_d_secure_opts[:authentication_response_status] if three_d_secure_opts[:authentication_response_status]
793
+
794
+ parameters[:three_d_secure_pass_thru] = pass_thru.merge(xid_or_ds_trans_id(three_d_secure_opts))
795
+ end
796
+
797
+ def xid_or_ds_trans_id(three_d_secure_opts)
798
+ if three_d_secure_opts[:version].to_f >= 2
799
+ { ds_transaction_id: three_d_secure_opts[:ds_transaction_id] }
800
+ else
801
+ { xid: three_d_secure_opts[:xid] }
802
+ end
803
+ end
804
+
805
+ def add_stored_credential_data(parameters, credit_card_or_vault_id, options)
806
+ return unless (stored_credential = options[:stored_credential])
807
+
808
+ parameters[:external_vault] = {}
809
+ if stored_credential[:initial_transaction]
810
+ parameters[:external_vault][:status] = 'will_vault'
811
+ else
812
+ parameters[:external_vault][:status] = 'vaulted'
813
+ parameters[:external_vault][:previous_network_transaction_id] = stored_credential[:network_transaction_id]
814
+ end
815
+ if stored_credential[:initiator] == 'merchant'
816
+ if stored_credential[:reason_type] == 'installment'
817
+ parameters[:transaction_source] = 'recurring'
818
+ else
819
+ parameters[:transaction_source] = stored_credential[:reason_type]
820
+ end
821
+ elsif %w(recurring_first moto).include?(stored_credential[:reason_type])
822
+ parameters[:transaction_source] = stored_credential[:reason_type]
823
+ else
824
+ parameters[:transaction_source] = ''
825
+ end
826
+ end
827
+
828
+ def add_payment_method(parameters, credit_card_or_vault_id, options)
829
+ if credit_card_or_vault_id.is_a?(String) || credit_card_or_vault_id.is_a?(Integer)
830
+ if options[:payment_method_token]
831
+ parameters[:payment_method_token] = credit_card_or_vault_id
832
+ options.delete(:billing_address)
833
+ elsif options[:payment_method_nonce]
834
+ parameters[:payment_method_nonce] = credit_card_or_vault_id
835
+ else
836
+ parameters[:customer_id] = credit_card_or_vault_id
837
+ end
838
+ else
839
+ parameters[:customer].merge!(
840
+ first_name: credit_card_or_vault_id.first_name,
841
+ last_name: credit_card_or_vault_id.last_name
842
+ )
843
+ if credit_card_or_vault_id.is_a?(NetworkTokenizationCreditCard)
844
+ if credit_card_or_vault_id.source == :apple_pay
845
+ parameters[:apple_pay_card] = {
846
+ number: credit_card_or_vault_id.number,
847
+ expiration_month: credit_card_or_vault_id.month.to_s.rjust(2, '0'),
848
+ expiration_year: credit_card_or_vault_id.year.to_s,
849
+ cardholder_name: credit_card_or_vault_id.name,
850
+ cryptogram: credit_card_or_vault_id.payment_cryptogram,
851
+ eci_indicator: credit_card_or_vault_id.eci
852
+ }
853
+ elsif credit_card_or_vault_id.source == :android_pay || credit_card_or_vault_id.source == :google_pay
854
+ Braintree::Version::Major < 3 ? pay_card = :android_pay_card : pay_card = :google_pay_card
855
+ parameters[pay_card] = {
856
+ number: credit_card_or_vault_id.number,
857
+ cryptogram: credit_card_or_vault_id.payment_cryptogram,
858
+ expiration_month: credit_card_or_vault_id.month.to_s.rjust(2, '0'),
859
+ expiration_year: credit_card_or_vault_id.year.to_s,
860
+ google_transaction_id: credit_card_or_vault_id.transaction_id,
861
+ source_card_type: credit_card_or_vault_id.brand,
862
+ source_card_last_four: credit_card_or_vault_id.last_digits,
863
+ eci_indicator: credit_card_or_vault_id.eci
864
+ }
865
+ end
866
+ else
867
+ parameters[:credit_card] = {
868
+ number: credit_card_or_vault_id.number,
869
+ cvv: credit_card_or_vault_id.verification_value,
870
+ expiration_month: credit_card_or_vault_id.month.to_s.rjust(2, '0'),
871
+ expiration_year: credit_card_or_vault_id.year.to_s,
872
+ cardholder_name: credit_card_or_vault_id.name
873
+ }
874
+ end
875
+ end
876
+ end
877
+
878
+ def bank_account_errors(payment_method, options)
879
+ if payment_method.validate.present?
880
+ payment_method.validate
881
+ elsif options[:billing_address].blank?
882
+ 'billing_address is required parameter to store and verify Bank accounts.'
883
+ elsif options[:ach_mandate].blank?
884
+ 'ach_mandate is a required parameter to process bank acccount transactions see (https://developer.paypal.com/braintree/docs/guides/ach/client-side#show-required-authorization-language)'
885
+ end
886
+ end
887
+
888
+ def add_bank_account_to_customer(payment_method, options)
889
+ bank_account_nonce, error_message = TokenNonce.new(@braintree_gateway, options).create_token_nonce_for_payment_method payment_method
890
+ return Response.new(false, error_message) unless bank_account_nonce.present?
891
+
892
+ result = @braintree_gateway.payment_method.create(
893
+ customer_id: options[:customer],
894
+ payment_method_nonce: bank_account_nonce,
895
+ options: {
896
+ us_bank_account_verification_method: 'network_check'
897
+ }
898
+ )
899
+
900
+ verified = result.success? && result.payment_method&.verified
901
+ message = message_from_result(result)
902
+ message = not_verified_reason(result.payment_method) unless verified
903
+
904
+ Response.new(verified, message,
905
+ {
906
+ customer_vault_id: options[:customer],
907
+ bank_account_token: result.payment_method&.token,
908
+ verified: verified
909
+ },
910
+ authorization: result.payment_method&.token)
911
+ end
912
+
913
+ def not_verified_reason(bank_account)
914
+ return unless bank_account.verifications.present?
915
+
916
+ verification = bank_account.verifications.first
917
+ "verification_status: [#{verification.status}], processor_response: [#{verification.processor_response_code}-#{verification.processor_response_text}]"
918
+ end
919
+
920
+ def store_bank_account(payment_method, options, multi_response)
921
+ multi_response.process { create_customer_from_bank_account payment_method, options } unless multi_response.params['exists']
922
+ multi_response.process { add_bank_account_to_customer payment_method, options }
923
+ end
924
+
925
+ def store_credit_card(payment_method, options, multi_response)
926
+ process_by = multi_response.params['exists'] ? :add_credit_card_to_customer : :add_customer_with_credit_card
927
+ multi_response.process { send process_by, payment_method, options }
928
+ end
929
+
930
+ def create_customer_from_bank_account(payment_method, options)
931
+ parameters = {
932
+ id: options[:customer],
933
+ first_name: payment_method.first_name,
934
+ last_name: payment_method.last_name,
935
+ email: scrub_email(options[:email]),
936
+ phone: phone_from(options),
937
+ device_data: options[:device_data]
938
+ }.compact
939
+
940
+ result = @braintree_gateway.customer.create(parameters)
941
+ customer_id = result.customer.id if result.success?
942
+ options[:customer] = customer_id
943
+
944
+ Response.new(
945
+ result.success?,
946
+ message_from_result(result),
947
+ { customer_vault_id: customer_id, 'exists': true }
948
+ )
949
+ end
950
+ end
951
+ end
952
+ end