activemerchant 1.79.2 → 1.129.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (279) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG +1391 -0
  3. data/README.md +29 -14
  4. data/lib/active_merchant/billing/avs_result.rb +25 -28
  5. data/lib/active_merchant/billing/base.rb +0 -13
  6. data/lib/active_merchant/billing/check.rb +55 -22
  7. data/lib/active_merchant/billing/compatibility.rb +10 -12
  8. data/lib/active_merchant/billing/credit_card.rb +82 -62
  9. data/lib/active_merchant/billing/credit_card_formatting.rb +4 -4
  10. data/lib/active_merchant/billing/credit_card_methods.rb +328 -58
  11. data/lib/active_merchant/billing/cvv_result.rb +0 -1
  12. data/lib/active_merchant/billing/gateway.rb +61 -56
  13. data/lib/active_merchant/billing/gateways/adyen.rb +562 -87
  14. data/lib/active_merchant/billing/gateways/airwallex.rb +370 -0
  15. data/lib/active_merchant/billing/gateways/alelo.rb +256 -0
  16. data/lib/active_merchant/billing/gateways/allied_wallet.rb +35 -36
  17. data/lib/active_merchant/billing/gateways/authorize_net.rb +297 -196
  18. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +31 -24
  19. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +94 -98
  20. data/lib/active_merchant/billing/gateways/axcessms.rb +64 -66
  21. data/lib/active_merchant/billing/gateways/balanced.rb +72 -65
  22. data/lib/active_merchant/billing/gateways/bambora_apac.rb +222 -0
  23. data/lib/active_merchant/billing/gateways/bank_frick.rb +16 -16
  24. data/lib/active_merchant/billing/gateways/banwire.rb +12 -12
  25. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +140 -69
  26. data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +7 -7
  27. data/lib/active_merchant/billing/gateways/be2bill.rb +7 -7
  28. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +115 -115
  29. data/lib/active_merchant/billing/gateways/beanstream.rb +39 -13
  30. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +1 -2
  31. data/lib/active_merchant/billing/gateways/blue_pay.rb +87 -58
  32. data/lib/active_merchant/billing/gateways/blue_snap.rb +405 -104
  33. data/lib/active_merchant/billing/gateways/bogus.rb +34 -30
  34. data/lib/active_merchant/billing/gateways/borgun.rb +97 -47
  35. data/lib/active_merchant/billing/gateways/bpoint.rb +20 -20
  36. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -3
  37. data/lib/active_merchant/billing/gateways/braintree/token_nonce.rb +113 -0
  38. data/lib/active_merchant/billing/gateways/braintree.rb +1 -1
  39. data/lib/active_merchant/billing/gateways/braintree_blue.rb +561 -259
  40. data/lib/active_merchant/billing/gateways/braintree_orange.rb +1 -1
  41. data/lib/active_merchant/billing/gateways/bridge_pay.rb +53 -54
  42. data/lib/active_merchant/billing/gateways/cams.rb +31 -31
  43. data/lib/active_merchant/billing/gateways/card_connect.rb +85 -33
  44. data/lib/active_merchant/billing/gateways/card_save.rb +7 -9
  45. data/lib/active_merchant/billing/gateways/card_stream.rb +187 -169
  46. data/lib/active_merchant/billing/gateways/cardknox.rb +24 -25
  47. data/lib/active_merchant/billing/gateways/cardprocess.rb +9 -7
  48. data/lib/active_merchant/billing/gateways/cashnet.rb +43 -27
  49. data/lib/active_merchant/billing/gateways/cc5.rb +14 -17
  50. data/lib/active_merchant/billing/gateways/cecabank.rb +62 -52
  51. data/lib/active_merchant/billing/gateways/cenpos.rb +63 -62
  52. data/lib/active_merchant/billing/gateways/checkout.rb +21 -23
  53. data/lib/active_merchant/billing/gateways/checkout_v2.rb +391 -113
  54. data/lib/active_merchant/billing/gateways/citrus_pay.rb +1 -3
  55. data/lib/active_merchant/billing/gateways/clearhaus.rb +40 -41
  56. data/lib/active_merchant/billing/gateways/commerce_hub.rb +361 -0
  57. data/lib/active_merchant/billing/gateways/commercegate.rb +11 -12
  58. data/lib/active_merchant/billing/gateways/conekta.rb +35 -30
  59. data/lib/active_merchant/billing/gateways/creditcall.rb +59 -59
  60. data/lib/active_merchant/billing/gateways/credorax.rb +326 -145
  61. data/lib/active_merchant/billing/gateways/ct_payment.rb +269 -0
  62. data/lib/active_merchant/billing/gateways/culqi.rb +53 -53
  63. data/lib/active_merchant/billing/gateways/cyber_source/cyber_source_common.rb +36 -0
  64. data/lib/active_merchant/billing/gateways/cyber_source.rb +566 -208
  65. data/lib/active_merchant/billing/gateways/cyber_source_rest.rb +456 -0
  66. data/lib/active_merchant/billing/gateways/d_local.rb +342 -0
  67. data/lib/active_merchant/billing/gateways/data_cash.rb +40 -56
  68. data/lib/active_merchant/billing/gateways/decidir.rb +358 -0
  69. data/lib/active_merchant/billing/gateways/decidir_plus.rb +344 -0
  70. data/lib/active_merchant/billing/gateways/dibs.rb +34 -40
  71. data/lib/active_merchant/billing/gateways/digitzs.rb +48 -45
  72. data/lib/active_merchant/billing/gateways/ebanx.rb +110 -60
  73. data/lib/active_merchant/billing/gateways/efsnet.rb +46 -50
  74. data/lib/active_merchant/billing/gateways/elavon.rb +351 -189
  75. data/lib/active_merchant/billing/gateways/element.rb +106 -56
  76. data/lib/active_merchant/billing/gateways/epay.rb +74 -64
  77. data/lib/active_merchant/billing/gateways/evo_ca.rb +13 -14
  78. data/lib/active_merchant/billing/gateways/eway.rb +74 -73
  79. data/lib/active_merchant/billing/gateways/eway_managed.rb +85 -87
  80. data/lib/active_merchant/billing/gateways/eway_rapid.rb +105 -60
  81. data/lib/active_merchant/billing/gateways/exact.rb +29 -37
  82. data/lib/active_merchant/billing/gateways/ezic.rb +21 -22
  83. data/lib/active_merchant/billing/gateways/fat_zebra.rb +70 -48
  84. data/lib/active_merchant/billing/gateways/federated_canada.rb +11 -13
  85. data/lib/active_merchant/billing/gateways/finansbank.rb +3 -4
  86. data/lib/active_merchant/billing/gateways/first_giving.rb +23 -23
  87. data/lib/active_merchant/billing/gateways/first_pay.rb +33 -13
  88. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +106 -105
  89. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +505 -0
  90. data/lib/active_merchant/billing/gateways/flo2cash.rb +36 -36
  91. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +2 -2
  92. data/lib/active_merchant/billing/gateways/forte.rb +70 -40
  93. data/lib/active_merchant/billing/gateways/garanti.rb +24 -31
  94. data/lib/active_merchant/billing/gateways/global_collect.rb +378 -154
  95. data/lib/active_merchant/billing/gateways/global_transport.rb +12 -13
  96. data/lib/active_merchant/billing/gateways/hdfc.rb +55 -57
  97. data/lib/active_merchant/billing/gateways/hps.rb +236 -69
  98. data/lib/active_merchant/billing/gateways/iats_payments.rb +61 -39
  99. data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +1 -1
  100. data/lib/active_merchant/billing/gateways/inspire.rb +41 -47
  101. data/lib/active_merchant/billing/gateways/instapay.rb +10 -14
  102. data/lib/active_merchant/billing/gateways/ipg.rb +420 -0
  103. data/lib/active_merchant/billing/gateways/ipp.rb +25 -24
  104. data/lib/active_merchant/billing/gateways/iridium.rb +243 -244
  105. data/lib/active_merchant/billing/gateways/itransact.rb +14 -14
  106. data/lib/active_merchant/billing/gateways/iveri.rb +73 -34
  107. data/lib/active_merchant/billing/gateways/ixopay.rb +320 -0
  108. data/lib/active_merchant/billing/gateways/jetpay.rb +145 -152
  109. data/lib/active_merchant/billing/gateways/jetpay_v2.rb +154 -159
  110. data/lib/active_merchant/billing/gateways/komoju.rb +16 -16
  111. data/lib/active_merchant/billing/gateways/kushki.rb +127 -57
  112. data/lib/active_merchant/billing/gateways/latitude19.rb +111 -115
  113. data/lib/active_merchant/billing/gateways/linkpoint.rb +82 -85
  114. data/lib/active_merchant/billing/gateways/litle.rb +247 -53
  115. data/lib/active_merchant/billing/gateways/mastercard.rb +41 -23
  116. data/lib/active_merchant/billing/gateways/maxipago.rb +5 -5
  117. data/lib/active_merchant/billing/gateways/mercado_pago.rb +135 -49
  118. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +62 -29
  119. data/lib/active_merchant/billing/gateways/merchant_one.rb +16 -20
  120. data/lib/active_merchant/billing/gateways/merchant_partners.rb +40 -40
  121. data/lib/active_merchant/billing/gateways/merchant_ware.rb +54 -60
  122. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +42 -44
  123. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +52 -14
  124. data/lib/active_merchant/billing/gateways/mercury.rb +47 -51
  125. data/lib/active_merchant/billing/gateways/metrics_global.rb +32 -42
  126. data/lib/active_merchant/billing/gateways/micropayment.rb +42 -45
  127. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +7 -7
  128. data/lib/active_merchant/billing/gateways/migs.rb +45 -40
  129. data/lib/active_merchant/billing/gateways/mit.rb +260 -0
  130. data/lib/active_merchant/billing/gateways/modern_payments.rb +2 -2
  131. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +29 -31
  132. data/lib/active_merchant/billing/gateways/moka.rb +290 -0
  133. data/lib/active_merchant/billing/gateways/monei.rb +255 -138
  134. data/lib/active_merchant/billing/gateways/moneris.rb +226 -88
  135. data/lib/active_merchant/billing/gateways/money_movers.rb +11 -13
  136. data/lib/active_merchant/billing/gateways/mundipagg.rb +117 -43
  137. data/lib/active_merchant/billing/gateways/nab_transact.rb +28 -31
  138. data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +13 -15
  139. data/lib/active_merchant/billing/gateways/net_registry.rb +12 -12
  140. data/lib/active_merchant/billing/gateways/netaxept.rb +33 -34
  141. data/lib/active_merchant/billing/gateways/netbanx.rb +167 -80
  142. data/lib/active_merchant/billing/gateways/netbilling.rb +27 -30
  143. data/lib/active_merchant/billing/gateways/netpay.rb +10 -10
  144. data/lib/active_merchant/billing/gateways/network_merchants.rb +7 -11
  145. data/lib/active_merchant/billing/gateways/nmi.rb +134 -48
  146. data/lib/active_merchant/billing/gateways/ogone.rb +88 -58
  147. data/lib/active_merchant/billing/gateways/omise.rb +30 -31
  148. data/lib/active_merchant/billing/gateways/openpay.rb +45 -26
  149. data/lib/active_merchant/billing/gateways/opp.rb +166 -144
  150. data/lib/active_merchant/billing/gateways/optimal_payment.rb +67 -64
  151. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +5 -7
  152. data/lib/active_merchant/billing/gateways/orbital.rb +726 -382
  153. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +26 -27
  154. data/lib/active_merchant/billing/gateways/pagarme.rb +47 -56
  155. data/lib/active_merchant/billing/gateways/pago_facil.rb +12 -14
  156. data/lib/active_merchant/billing/gateways/pay_arc.rb +392 -0
  157. data/lib/active_merchant/billing/gateways/pay_conex.rb +39 -40
  158. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +65 -65
  159. data/lib/active_merchant/billing/gateways/pay_hub.rb +39 -39
  160. data/lib/active_merchant/billing/gateways/pay_junction.rb +37 -37
  161. data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +70 -54
  162. data/lib/active_merchant/billing/gateways/pay_secure.rb +15 -17
  163. data/lib/active_merchant/billing/gateways/pay_trace.rb +450 -0
  164. data/lib/active_merchant/billing/gateways/paybox_direct.rb +71 -47
  165. data/lib/active_merchant/billing/gateways/payeezy.rb +159 -32
  166. data/lib/active_merchant/billing/gateways/payex.rb +39 -42
  167. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +41 -36
  168. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +11 -8
  169. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +3 -3
  170. data/lib/active_merchant/billing/gateways/payflow.rb +178 -54
  171. data/lib/active_merchant/billing/gateways/payflow_express.rb +61 -65
  172. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +0 -1
  173. data/lib/active_merchant/billing/gateways/payflow_uk.rb +1 -2
  174. data/lib/active_merchant/billing/gateways/payment_express.rb +66 -58
  175. data/lib/active_merchant/billing/gateways/paymentez.rb +114 -25
  176. data/lib/active_merchant/billing/gateways/paymill.rb +134 -133
  177. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +2 -1
  178. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +4 -0
  179. data/lib/active_merchant/billing/gateways/paypal.rb +27 -14
  180. data/lib/active_merchant/billing/gateways/paypal_ca.rb +1 -1
  181. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +2 -2
  182. data/lib/active_merchant/billing/gateways/paypal_express.rb +5 -2
  183. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +1 -1
  184. data/lib/active_merchant/billing/gateways/paysafe.rb +420 -0
  185. data/lib/active_merchant/billing/gateways/payscout.rb +10 -13
  186. data/lib/active_merchant/billing/gateways/paystation.rb +79 -82
  187. data/lib/active_merchant/billing/gateways/payu_in.rb +59 -58
  188. data/lib/active_merchant/billing/gateways/payu_latam.rb +139 -97
  189. data/lib/active_merchant/billing/gateways/payway.rb +27 -27
  190. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +253 -0
  191. data/lib/active_merchant/billing/gateways/pin.rb +87 -34
  192. data/lib/active_merchant/billing/gateways/plexo.rb +308 -0
  193. data/lib/active_merchant/billing/gateways/plugnpay.rb +82 -82
  194. data/lib/active_merchant/billing/gateways/priority.rb +392 -0
  195. data/lib/active_merchant/billing/gateways/pro_pay.rb +139 -140
  196. data/lib/active_merchant/billing/gateways/psigate.rb +44 -44
  197. data/lib/active_merchant/billing/gateways/psl_card.rb +29 -37
  198. data/lib/active_merchant/billing/gateways/qbms.rb +75 -76
  199. data/lib/active_merchant/billing/gateways/quantum.rb +21 -23
  200. data/lib/active_merchant/billing/gateways/quickbooks.rb +142 -55
  201. data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +103 -107
  202. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +156 -158
  203. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +7 -8
  204. data/lib/active_merchant/billing/gateways/quickpay.rb +1 -3
  205. data/lib/active_merchant/billing/gateways/qvalent.rb +137 -68
  206. data/lib/active_merchant/billing/gateways/rapyd.rb +319 -0
  207. data/lib/active_merchant/billing/gateways/reach.rb +277 -0
  208. data/lib/active_merchant/billing/gateways/realex.rb +132 -50
  209. data/lib/active_merchant/billing/gateways/redsys.rb +382 -186
  210. data/lib/active_merchant/billing/gateways/s5.rb +16 -16
  211. data/lib/active_merchant/billing/gateways/safe_charge.rb +83 -47
  212. data/lib/active_merchant/billing/gateways/sage.rb +49 -48
  213. data/lib/active_merchant/billing/gateways/sage_pay.rb +76 -83
  214. data/lib/active_merchant/billing/gateways/sallie_mae.rb +13 -15
  215. data/lib/active_merchant/billing/gateways/secure_net.rb +32 -40
  216. data/lib/active_merchant/billing/gateways/secure_pay.rb +30 -40
  217. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +23 -26
  218. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +14 -16
  219. data/lib/active_merchant/billing/gateways/securion_pay.rb +69 -31
  220. data/lib/active_merchant/billing/gateways/shift4.rb +342 -0
  221. data/lib/active_merchant/billing/gateways/simetrik.rb +368 -0
  222. data/lib/active_merchant/billing/gateways/skip_jack.rb +52 -53
  223. data/lib/active_merchant/billing/gateways/smart_ps.rb +51 -60
  224. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +29 -29
  225. data/lib/active_merchant/billing/gateways/spreedly_core.rb +66 -47
  226. data/lib/active_merchant/billing/gateways/stripe.rb +309 -148
  227. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +556 -0
  228. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +18 -23
  229. data/lib/active_merchant/billing/gateways/telr.rb +46 -48
  230. data/lib/active_merchant/billing/gateways/tns.rb +8 -7
  231. data/lib/active_merchant/billing/gateways/trans_first.rb +37 -37
  232. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +249 -245
  233. data/lib/active_merchant/billing/gateways/transact_pro.rb +25 -27
  234. data/lib/active_merchant/billing/gateways/transax.rb +6 -8
  235. data/lib/active_merchant/billing/gateways/transnational.rb +1 -2
  236. data/lib/active_merchant/billing/gateways/trexle.rb +22 -18
  237. data/lib/active_merchant/billing/gateways/trust_commerce.rb +161 -88
  238. data/lib/active_merchant/billing/gateways/usa_epay.rb +5 -6
  239. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +231 -238
  240. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +129 -55
  241. data/lib/active_merchant/billing/gateways/vanco.rb +42 -33
  242. data/lib/active_merchant/billing/gateways/verifi.rb +52 -53
  243. data/lib/active_merchant/billing/gateways/viaklix.rb +18 -22
  244. data/lib/active_merchant/billing/gateways/visanet_peru.rb +115 -74
  245. data/lib/active_merchant/billing/gateways/vpos.rb +223 -0
  246. data/lib/active_merchant/billing/gateways/webpay.rb +9 -9
  247. data/lib/active_merchant/billing/gateways/wepay.rb +38 -41
  248. data/lib/active_merchant/billing/gateways/wirecard.rb +36 -37
  249. data/lib/active_merchant/billing/gateways/wompi.rb +197 -0
  250. data/lib/active_merchant/billing/gateways/world_net.rb +39 -38
  251. data/lib/active_merchant/billing/gateways/worldpay.rb +756 -142
  252. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +73 -83
  253. data/lib/active_merchant/billing/gateways/worldpay_us.rb +31 -31
  254. data/lib/active_merchant/billing/model.rb +2 -2
  255. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +3 -3
  256. data/lib/active_merchant/billing/rails.rb +1 -1
  257. data/lib/active_merchant/billing/response.rb +32 -13
  258. data/lib/active_merchant/billing/three_d_secure_eci_mapper.rb +27 -0
  259. data/lib/active_merchant/billing.rb +1 -0
  260. data/lib/active_merchant/connection.rb +24 -38
  261. data/lib/active_merchant/country.rb +9 -5
  262. data/lib/active_merchant/errors.rb +4 -1
  263. data/lib/active_merchant/net_http_ssl_connection.rb +2 -0
  264. data/lib/active_merchant/network_connection_retries.rb +28 -31
  265. data/lib/active_merchant/post_data.rb +5 -3
  266. data/lib/active_merchant/posts_data.rb +5 -7
  267. data/lib/active_merchant/version.rb +1 -1
  268. data/lib/active_merchant.rb +3 -3
  269. data/lib/activemerchant.rb +1 -1
  270. data/lib/certs/cacert.pem +1592 -2329
  271. data/lib/support/gateway_support.rb +8 -10
  272. data/lib/support/ssl_verify.rb +9 -14
  273. data/lib/support/ssl_version.rb +9 -10
  274. metadata +98 -37
  275. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +0 -246
  276. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +0 -13
  277. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +0 -29
  278. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +0 -66
  279. data/lib/active_merchant/billing/gateways/moneris_us.rb +0 -309
@@ -1,14 +1,14 @@
1
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'
2
4
 
3
5
  begin
4
- require "braintree"
6
+ require 'braintree'
5
7
  rescue LoadError
6
- raise "Could not load the braintree gem. Use `gem install braintree` to install it."
8
+ raise 'Could not load the braintree gem. Use `gem install braintree` to install it.'
7
9
  end
8
10
 
9
- unless Braintree::Version::Major == 2 && Braintree::Version::Minor >= 78
10
- raise "Need braintree gem >= 2.78.0. Run `gem install braintree --version '~>2.78'` to get the correct version."
11
- end
11
+ raise 'Need braintree gem >= 2.0.0.' unless Braintree::Version::Major >= 2 && Braintree::Version::Minor >= 0
12
12
 
13
13
  module ActiveMerchant #:nodoc:
14
14
  module Billing #:nodoc:
@@ -39,6 +39,7 @@ module ActiveMerchant #:nodoc:
39
39
  #
40
40
  class BraintreeBlueGateway < Gateway
41
41
  include BraintreeCommon
42
+ include Empty
42
43
 
43
44
  self.display_name = 'Braintree (Blue Platform)'
44
45
 
@@ -46,6 +47,8 @@ module ActiveMerchant #:nodoc:
46
47
  cannot_refund_if_unsettled: 91506
47
48
  }
48
49
 
50
+ DIRECT_BANK_ERROR = 'Direct bank account transactions are not supported. Bank accounts must be successfully stored before use.'.freeze
51
+
49
52
  def initialize(options = {})
50
53
  requires!(options, :merchant_id, :public_key, :private_key)
51
54
  @merchant_account_id = options[:merchant_account_id]
@@ -53,7 +56,7 @@ module ActiveMerchant #:nodoc:
53
56
  super
54
57
 
55
58
  if wiredump_device.present?
56
- logger = ((Logger === wiredump_device) ? wiredump_device : Logger.new(wiredump_device))
59
+ logger = (Logger === wiredump_device ? wiredump_device : Logger.new(wiredump_device))
57
60
  logger.level = Logger::DEBUG
58
61
  else
59
62
  logger = Braintree::Configuration.logger.clone
@@ -61,30 +64,45 @@ module ActiveMerchant #:nodoc:
61
64
  end
62
65
 
63
66
  @configuration = Braintree::Configuration.new(
64
- :merchant_id => options[:merchant_id],
65
- :public_key => options[:public_key],
66
- :private_key => options[:private_key],
67
- :environment => (options[:environment] || (test? ? :sandbox : :production)).to_sym,
68
- :custom_user_agent => "ActiveMerchant #{ActiveMerchant::VERSION}",
69
- :logger => options[:logger] || logger,
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
70
73
  )
71
74
 
72
- @braintree_gateway = Braintree::Gateway.new( @configuration )
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
73
82
  end
74
83
 
75
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
+
76
87
  create_transaction(:sale, money, credit_card_or_vault_id, options)
77
88
  end
78
89
 
79
90
  def capture(money, authorization, options = {})
80
- commit do
81
- result = @braintree_gateway.transaction.submit_for_settlement(authorization, localized_amount(money, options[:currency] || default_currency).to_s)
82
- response_from_result(result)
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
83
101
  end
84
102
  end
85
103
 
86
104
  def purchase(money, credit_card_or_vault_id, options = {})
87
- authorize(money, credit_card_or_vault_id, options.merge(:submit_for_settlement => true))
105
+ authorize(money, credit_card_or_vault_id, options.merge(submit_for_settlement: true))
88
106
  end
89
107
 
90
108
  def credit(money, credit_card_or_vault_id, options = {})
@@ -99,10 +117,13 @@ module ActiveMerchant #:nodoc:
99
117
 
100
118
  commit do
101
119
  response = response_from_result(@braintree_gateway.transaction.refund(transaction_id, money))
102
- return response if response.success?
103
- return response unless options[:force_full_refund_if_unsettled]
104
120
 
105
- void(transaction_id) if response.message =~ /#{ERROR_CODES[:cannot_refund_if_unsettled]}/
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
106
127
  end
107
128
  end
108
129
 
@@ -112,74 +133,90 @@ module ActiveMerchant #:nodoc:
112
133
  end
113
134
  end
114
135
 
115
- def verify(credit_card, options = {})
116
- MultiResponse.run(:use_first_response) do |r|
117
- r.process { authorize(100, credit_card, options) }
118
- r.process(:ignore_result) { void(r.authorization, options) }
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
119
166
  end
120
167
  end
121
168
 
122
- def store(creditcard, options = {})
123
- if options[:customer].present?
124
- MultiResponse.new.tap do |r|
125
- customer_exists_response = nil
126
- r.process{customer_exists_response = check_customer_exists(options[:customer])}
127
- r.process do
128
- if customer_exists_response.params["exists"]
129
- add_credit_card_to_customer(creditcard, options)
130
- else
131
- add_customer_with_credit_card(creditcard, options)
132
- end
133
- end
134
- end
135
- else
136
- add_customer_with_credit_card(creditcard, options)
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
137
176
  end
138
177
  end
139
178
 
140
179
  def update(vault_id, creditcard, options = {})
141
180
  braintree_credit_card = nil
142
181
  commit do
143
- braintree_credit_card = @braintree_gateway.customer.find(vault_id).credit_cards.detect { |cc| cc.default? }
182
+ braintree_credit_card = @braintree_gateway.customer.find(vault_id).credit_cards.detect(&:default?)
144
183
  return Response.new(false, 'Braintree::NotFoundError') if braintree_credit_card.nil?
145
184
 
146
- options.merge!(:update_existing_token => braintree_credit_card.token)
185
+ options[:update_existing_token] = braintree_credit_card.token
147
186
  credit_card_params = merge_credit_card_options({
148
- :credit_card => {
149
- :cardholder_name => creditcard.name,
150
- :number => creditcard.number,
151
- :cvv => creditcard.verification_value,
152
- :expiration_month => creditcard.month.to_s.rjust(2, "0"),
153
- :expiration_year => creditcard.year.to_s
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
154
193
  }
155
194
  }, options)[:credit_card]
156
195
 
157
196
  result = @braintree_gateway.customer.update(vault_id,
158
- :first_name => creditcard.first_name,
159
- :last_name => creditcard.last_name,
160
- :email => scrub_email(options[:email]),
161
- :phone => options[:phone] || (options[:billing_address][:phone] if options[:billing_address] &&
162
- options[:billing_address][:phone]),
163
- :credit_card => credit_card_params
164
- )
197
+ first_name: creditcard.first_name,
198
+ last_name: creditcard.last_name,
199
+ email: scrub_email(options[:email]),
200
+ phone: options[:phone] || (options[:billing_address][:phone] if options[:billing_address] &&
201
+ options[:billing_address][:phone]),
202
+ credit_card: credit_card_params)
165
203
  Response.new(result.success?, message_from_result(result),
166
- :braintree_customer => (customer_hash(@braintree_gateway.customer.find(vault_id), :include_credit_cards) if result.success?),
167
- :customer_vault_id => (result.customer.id if result.success?)
168
- )
204
+ braintree_customer: (customer_hash(@braintree_gateway.customer.find(vault_id), :include_credit_cards) if result.success?),
205
+ customer_vault_id: (result.customer.id if result.success?))
169
206
  end
170
207
  end
171
208
 
172
209
  def unstore(customer_vault_id, options = {})
173
210
  commit do
174
- if(!customer_vault_id && options[:credit_card_token])
211
+ if !customer_vault_id && options[:credit_card_token]
175
212
  @braintree_gateway.credit_card.delete(options[:credit_card_token])
176
213
  else
177
214
  @braintree_gateway.customer.delete(customer_vault_id)
178
215
  end
179
- Response.new(true, "OK")
216
+ Response.new(true, 'OK')
180
217
  end
181
218
  end
182
- alias_method :delete, :unstore
219
+ alias delete unstore
183
220
 
184
221
  def supports_network_tokenization?
185
222
  true
@@ -187,7 +224,7 @@ module ActiveMerchant #:nodoc:
187
224
 
188
225
  def verify_credentials
189
226
  begin
190
- @braintree_gateway.transaction.find("non_existent_token")
227
+ @braintree_gateway.transaction.find('non_existent_token')
191
228
  rescue Braintree::AuthenticationError
192
229
  return false
193
230
  rescue Braintree::NotFoundError
@@ -200,13 +237,13 @@ module ActiveMerchant #:nodoc:
200
237
  private
201
238
 
202
239
  def check_customer_exists(customer_vault_id)
240
+ return Response.new true, 'Customer not found', { exists: false } if customer_vault_id.blank?
241
+
203
242
  commit do
204
- begin
205
- @braintree_gateway.customer.find(customer_vault_id)
206
- ActiveMerchant::Billing::Response.new(true, "Customer found", {exists: true}, authorization: customer_vault_id)
207
- rescue Braintree::NotFoundError
208
- ActiveMerchant::Billing::Response.new(true, "Customer not found", {exists: false})
209
- end
243
+ @braintree_gateway.customer.find(customer_vault_id)
244
+ ActiveMerchant::Billing::Response.new(true, 'Customer found', { exists: true }, authorization: customer_vault_id)
245
+ rescue Braintree::NotFoundError
246
+ ActiveMerchant::Billing::Response.new(true, 'Customer not found', { exists: false })
210
247
  end
211
248
  end
212
249
 
@@ -216,33 +253,33 @@ module ActiveMerchant #:nodoc:
216
253
  credit_card_params = { payment_method_nonce: options[:payment_method_nonce] }
217
254
  else
218
255
  credit_card_params = {
219
- :credit_card => {
220
- :cardholder_name => creditcard.name,
221
- :number => creditcard.number,
222
- :cvv => creditcard.verification_value,
223
- :expiration_month => creditcard.month.to_s.rjust(2, "0"),
224
- :expiration_year => creditcard.year.to_s,
225
- :token => options[:credit_card_token]
256
+ credit_card: {
257
+ cardholder_name: creditcard.name,
258
+ number: creditcard.number,
259
+ cvv: creditcard.verification_value,
260
+ expiration_month: creditcard.month.to_s.rjust(2, '0'),
261
+ expiration_year: creditcard.year.to_s,
262
+ token: options[:credit_card_token]
226
263
  }
227
264
  }
228
265
  end
229
266
  parameters = {
230
- :first_name => creditcard.first_name,
231
- :last_name => creditcard.last_name,
232
- :email => scrub_email(options[:email]),
233
- :phone => options[:phone] || (options[:billing_address][:phone] if options[:billing_address] &&
234
- options[:billing_address][:phone]),
235
- :id => options[:customer],
267
+ first_name: creditcard.first_name,
268
+ last_name: creditcard.last_name,
269
+ email: scrub_email(options[:email]),
270
+ phone: options[:phone] || (options[:billing_address][:phone] if options[:billing_address] &&
271
+ options[:billing_address][:phone]),
272
+ id: options[:customer],
273
+ device_data: options[:device_data]
236
274
  }.merge credit_card_params
237
275
  result = @braintree_gateway.customer.create(merge_credit_card_options(parameters, options))
238
276
  Response.new(result.success?, message_from_result(result),
239
277
  {
240
- :braintree_customer => (customer_hash(result.customer, :include_credit_cards) if result.success?),
241
- :customer_vault_id => (result.customer.id if result.success?),
242
- :credit_card_token => (result.customer.credit_cards[0].token if result.success?)
278
+ braintree_customer: (customer_hash(result.customer, :include_credit_cards) if result.success?),
279
+ customer_vault_id: (result.customer.id if result.success?),
280
+ credit_card_token: (result.customer.credit_cards[0].token if result.success?)
243
281
  },
244
- :authorization => (result.customer.id if result.success?)
245
- )
282
+ authorization: (result.customer.id if result.success?))
246
283
  end
247
284
  end
248
285
 
@@ -254,10 +291,14 @@ module ActiveMerchant #:nodoc:
254
291
  cardholder_name: credit_card.name,
255
292
  number: credit_card.number,
256
293
  cvv: credit_card.verification_value,
257
- expiration_month: credit_card.month.to_s.rjust(2, "0"),
294
+ expiration_month: credit_card.month.to_s.rjust(2, '0'),
258
295
  expiration_year: credit_card.year.to_s,
296
+ device_data: options[:device_data]
259
297
  }
260
- parameters[:billing_address] = map_address(options[:billing_address]) if options[:billing_address]
298
+ if options[:billing_address]
299
+ address = map_address(options[:billing_address])
300
+ parameters[:billing_address] = address unless address.all? { |_k, v| empty?(v) }
301
+ end
261
302
 
262
303
  result = @braintree_gateway.credit_card.create(parameters)
263
304
  ActiveMerchant::Billing::Response.new(
@@ -274,57 +315,55 @@ module ActiveMerchant #:nodoc:
274
315
 
275
316
  def scrub_email(email)
276
317
  return nil unless email.present?
277
- return nil if (
318
+ return nil if
278
319
  email !~ /^.+@[^\.]+(\.[^\.]+)+[a-z]$/i ||
279
320
  email =~ /\.(con|met)$/i
280
- )
321
+
281
322
  email
282
323
  end
283
324
 
284
325
  def scrub_zip(zip)
285
326
  return nil unless zip.present?
286
- return nil if(
327
+ return nil if
287
328
  zip.gsub(/[^a-z0-9]/i, '').length > 9 ||
288
329
  zip =~ /[^a-z0-9\- ]/i
289
- )
330
+
290
331
  zip
291
332
  end
292
333
 
293
334
  def merge_credit_card_options(parameters, options)
294
335
  valid_options = {}
295
336
  options.each do |key, value|
296
- valid_options[key] = value if [:update_existing_token, :verify_card, :verification_merchant_account_id].include?(key)
337
+ valid_options[key] = value if %i[update_existing_token verify_card verification_merchant_account_id].include?(key)
297
338
  end
298
339
 
299
- if valid_options.include?(:verify_card) && @merchant_account_id
300
- valid_options[:verification_merchant_account_id] ||= @merchant_account_id
301
- end
340
+ valid_options[:verification_merchant_account_id] ||= @merchant_account_id if valid_options.include?(:verify_card) && @merchant_account_id
302
341
 
303
342
  parameters[:credit_card] ||= {}
304
- parameters[:credit_card].merge!(:options => valid_options)
305
- parameters[:credit_card][:billing_address] = map_address(options[:billing_address]) if options[:billing_address]
343
+ parameters[:credit_card][:options] = valid_options
344
+ if options[:billing_address]
345
+ address = map_address(options[:billing_address])
346
+ parameters[:credit_card][:billing_address] = address unless address.all? { |_k, v| empty?(v) }
347
+ end
306
348
  parameters
307
349
  end
308
350
 
309
351
  def map_address(address)
310
- return {} if address.nil?
311
352
  mapped = {
312
- :street_address => address[:address1],
313
- :extended_address => address[:address2],
314
- :company => address[:company],
315
- :locality => address[:city],
316
- :region => address[:state],
317
- :postal_code => scrub_zip(address[:zip]),
353
+ street_address: address[:address1],
354
+ extended_address: address[:address2],
355
+ company: address[:company],
356
+ locality: address[:city],
357
+ region: address[:state],
358
+ postal_code: scrub_zip(address[:zip])
318
359
  }
319
- if (address[:country] || address[:country_code_alpha2])
320
- mapped[:country_code_alpha2] = (address[:country] || address[:country_code_alpha2])
321
- elsif address[:country_name]
322
- mapped[:country_name] = address[:country_name]
323
- elsif address[:country_code_alpha3]
324
- mapped[:country_code_alpha3] = address[:country_code_alpha3]
325
- elsif address[:country_code_numeric]
326
- mapped[:country_code_numeric] = address[:country_code_numeric]
327
- end
360
+
361
+ mapped[:country_code_alpha2] = (address[:country] || address[:country_code_alpha2]) if address[:country] || address[:country_code_alpha2]
362
+ mapped[:country_name] = address[:country_name] if address[:country_name]
363
+ mapped[:country_code_alpha3] = address[:country_code_alpha3] if address[:country_code_alpha3]
364
+ mapped[:country_code_alpha3] ||= Country.find(address[:country]).code(:alpha3).value unless address[:country].blank?
365
+ mapped[:country_code_numeric] = address[:country_code_numeric] if address[:country_code_numeric]
366
+
328
367
  mapped
329
368
  end
330
369
 
@@ -336,9 +375,9 @@ module ActiveMerchant #:nodoc:
336
375
 
337
376
  def message_from_result(result)
338
377
  if result.success?
339
- "OK"
378
+ 'OK'
340
379
  elsif result.errors.any?
341
- result.errors.map { |e| "#{e.message} (#{e.code})" }.join(" ")
380
+ result.errors.map { |e| "#{e.message} (#{e.code})" }.join(' ')
342
381
  elsif result.credit_card_verification
343
382
  "Processor declined: #{result.credit_card_verification.processor_response_text} (#{result.credit_card_verification.processor_response_code})"
344
383
  else
@@ -347,10 +386,15 @@ module ActiveMerchant #:nodoc:
347
386
  end
348
387
 
349
388
  def response_from_result(result)
350
- Response.new(result.success?, message_from_result(result),
351
- { braintree_transaction: transaction_hash(result) },
352
- { authorization: (result.transaction.id if result.transaction) }
353
- )
389
+ response_hash = { braintree_transaction: transaction_hash(result) }
390
+
391
+ Response.new(
392
+ result.success?,
393
+ message_from_result(result),
394
+ response_hash,
395
+ authorization: result.transaction&.id,
396
+ test: test?
397
+ )
354
398
  end
355
399
 
356
400
  def response_params(result)
@@ -362,11 +406,16 @@ module ActiveMerchant #:nodoc:
362
406
 
363
407
  def response_options(result)
364
408
  options = {}
365
- if result.transaction
409
+ if result.credit_card_verification
410
+ options[:authorization] = result.credit_card_verification.id
411
+ options[:avs_result] = { code: avs_code_from(result.credit_card_verification) }
412
+ options[:cvv_result] = result.credit_card_verification.cvv_response_code
413
+ elsif result.transaction
366
414
  options[:authorization] = result.transaction.id
367
415
  options[:avs_result] = { code: avs_code_from(result.transaction) }
368
416
  options[:cvv_result] = result.transaction.cvv_response_code
369
417
  end
418
+ options[:test] = test?
370
419
  options
371
420
  end
372
421
 
@@ -377,41 +426,43 @@ module ActiveMerchant #:nodoc:
377
426
 
378
427
  def avs_mapping
379
428
  {
380
- "street: M, zip: M" => "M",
381
- "street: M, zip: N" => "A",
382
- "street: M, zip: U" => "B",
383
- "street: M, zip: I" => "B",
384
- "street: M, zip: A" => "B",
385
-
386
- "street: N, zip: M" => "Z",
387
- "street: N, zip: N" => "C",
388
- "street: N, zip: U" => "C",
389
- "street: N, zip: I" => "C",
390
- "street: N, zip: A" => "C",
391
-
392
- "street: U, zip: M" => "P",
393
- "street: U, zip: N" => "N",
394
- "street: U, zip: U" => "I",
395
- "street: U, zip: I" => "I",
396
- "street: U, zip: A" => "I",
397
-
398
- "street: I, zip: M" => "P",
399
- "street: I, zip: N" => "C",
400
- "street: I, zip: U" => "I",
401
- "street: I, zip: I" => "I",
402
- "street: I, zip: A" => "I",
403
-
404
- "street: A, zip: M" => "P",
405
- "street: A, zip: N" => "C",
406
- "street: A, zip: U" => "I",
407
- "street: A, zip: I" => "I",
408
- "street: A, zip: A" => "I"
429
+ 'street: M, zip: M' => 'M',
430
+ 'street: M, zip: N' => 'A',
431
+ 'street: M, zip: U' => 'B',
432
+ 'street: M, zip: I' => 'B',
433
+ 'street: M, zip: A' => 'B',
434
+
435
+ 'street: N, zip: M' => 'Z',
436
+ 'street: N, zip: N' => 'C',
437
+ 'street: N, zip: U' => 'C',
438
+ 'street: N, zip: I' => 'C',
439
+ 'street: N, zip: A' => 'C',
440
+
441
+ 'street: U, zip: M' => 'P',
442
+ 'street: U, zip: N' => 'N',
443
+ 'street: U, zip: U' => 'I',
444
+ 'street: U, zip: I' => 'I',
445
+ 'street: U, zip: A' => 'I',
446
+
447
+ 'street: I, zip: M' => 'P',
448
+ 'street: I, zip: N' => 'C',
449
+ 'street: I, zip: U' => 'I',
450
+ 'street: I, zip: I' => 'I',
451
+ 'street: I, zip: A' => 'I',
452
+
453
+ 'street: A, zip: M' => 'P',
454
+ 'street: A, zip: N' => 'C',
455
+ 'street: A, zip: U' => 'I',
456
+ 'street: A, zip: I' => 'I',
457
+ 'street: A, zip: A' => 'I',
458
+
459
+ 'street: B, zip: B' => 'B'
409
460
  }
410
461
  end
411
462
 
412
463
  def message_from_transaction_result(result)
413
- if result.transaction && result.transaction.status == "gateway_rejected"
414
- "Transaction declined - gateway rejected"
464
+ if result.transaction && result.transaction.status == 'gateway_rejected'
465
+ 'Transaction declined - gateway rejected'
415
466
  elsif result.transaction
416
467
  "#{result.transaction.processor_response_code} #{result.transaction.processor_response_text}"
417
468
  else
@@ -429,16 +480,28 @@ module ActiveMerchant #:nodoc:
429
480
  end
430
481
  end
431
482
 
483
+ def additional_processor_response_from_result(result)
484
+ result.transaction&.additional_processor_response
485
+ end
486
+
432
487
  def create_transaction(transaction_type, money, credit_card_or_vault_id, options)
433
488
  transaction_params = create_transaction_parameters(money, credit_card_or_vault_id, options)
434
489
  commit do
435
490
  result = @braintree_gateway.transaction.send(transaction_type, transaction_params)
491
+ make_default_payment_method_token(result) if options.dig(:paypal, :paypal_flow_type) == 'checkout_with_vault' && result.success?
436
492
  response = Response.new(result.success?, message_from_transaction_result(result), response_params(result), response_options(result))
437
493
  response.cvv_result['message'] = ''
438
494
  response
439
495
  end
440
496
  end
441
497
 
498
+ def make_default_payment_method_token(result)
499
+ @braintree_gateway.customer.update(
500
+ result.transaction.customer_details.id,
501
+ default_payment_method_token: result.transaction.paypal_details.implicitly_vaulted_payment_method_token
502
+ )
503
+ end
504
+
442
505
  def extract_refund_args(args)
443
506
  options = args.extract_options!
444
507
 
@@ -452,24 +515,24 @@ module ActiveMerchant #:nodoc:
452
515
  end
453
516
  end
454
517
 
455
- def customer_hash(customer, include_credit_cards=false)
518
+ def customer_hash(customer, include_credit_cards = false)
456
519
  hash = {
457
- "email" => customer.email,
458
- "phone" => customer.phone,
459
- "first_name" => customer.first_name,
460
- "last_name" => customer.last_name,
461
- "id" => customer.id
520
+ 'email' => customer.email,
521
+ 'phone' => customer.phone,
522
+ 'first_name' => customer.first_name,
523
+ 'last_name' => customer.last_name,
524
+ 'id' => customer.id
462
525
  }
463
526
 
464
527
  if include_credit_cards
465
- hash["credit_cards"] = customer.credit_cards.map do |cc|
528
+ hash['credit_cards'] = customer.credit_cards.map do |cc|
466
529
  {
467
- "bin" => cc.bin,
468
- "expiration_date" => cc.expiration_date,
469
- "token" => cc.token,
470
- "last_4" => cc.last_4,
471
- "card_type" => cc.card_type,
472
- "masked_number" => cc.masked_number
530
+ 'bin' => cc.bin,
531
+ 'expiration_date' => cc.expiration_date,
532
+ 'token' => cc.token,
533
+ 'last_4' => cc.last_4,
534
+ 'card_type' => cc.card_type,
535
+ 'masked_number' => cc.masked_number
473
536
  }
474
537
  end
475
538
  end
@@ -479,16 +542,17 @@ module ActiveMerchant #:nodoc:
479
542
 
480
543
  def transaction_hash(result)
481
544
  unless result.success?
482
- return { "processor_response_code" => response_code_from_result(result) }
545
+ return { 'processor_response_code' => response_code_from_result(result),
546
+ 'additional_processor_response' => additional_processor_response_from_result(result) }
483
547
  end
484
548
 
485
549
  transaction = result.transaction
486
550
  if transaction.vault_customer
487
551
  vault_customer = {
488
552
  }
489
- vault_customer["credit_cards"] = transaction.vault_customer.credit_cards.map do |cc|
553
+ vault_customer['credit_cards'] = transaction.vault_customer.credit_cards.map do |cc|
490
554
  {
491
- "bin" => cc.bin
555
+ 'bin' => cc.bin
492
556
  }
493
557
  end
494
558
  else
@@ -496,84 +560,271 @@ module ActiveMerchant #:nodoc:
496
560
  end
497
561
 
498
562
  customer_details = {
499
- "id" => transaction.customer_details.id,
500
- "email" => transaction.customer_details.email,
501
- "phone" => transaction.customer_details.phone,
563
+ 'id' => transaction.customer_details.id,
564
+ 'email' => transaction.customer_details.email,
565
+ 'phone' => transaction.customer_details.phone
502
566
  }
503
567
 
504
568
  billing_details = {
505
- "street_address" => transaction.billing_details.street_address,
506
- "extended_address" => transaction.billing_details.extended_address,
507
- "company" => transaction.billing_details.company,
508
- "locality" => transaction.billing_details.locality,
509
- "region" => transaction.billing_details.region,
510
- "postal_code" => transaction.billing_details.postal_code,
511
- "country_name" => transaction.billing_details.country_name,
569
+ 'street_address' => transaction.billing_details.street_address,
570
+ 'extended_address' => transaction.billing_details.extended_address,
571
+ 'company' => transaction.billing_details.company,
572
+ 'locality' => transaction.billing_details.locality,
573
+ 'region' => transaction.billing_details.region,
574
+ 'postal_code' => transaction.billing_details.postal_code,
575
+ 'country_name' => transaction.billing_details.country_name
512
576
  }
513
577
 
514
578
  shipping_details = {
515
- "street_address" => transaction.shipping_details.street_address,
516
- "extended_address" => transaction.shipping_details.extended_address,
517
- "company" => transaction.shipping_details.company,
518
- "locality" => transaction.shipping_details.locality,
519
- "region" => transaction.shipping_details.region,
520
- "postal_code" => transaction.shipping_details.postal_code,
521
- "country_name" => transaction.shipping_details.country_name,
579
+ 'street_address' => transaction.shipping_details.street_address,
580
+ 'extended_address' => transaction.shipping_details.extended_address,
581
+ 'company' => transaction.shipping_details.company,
582
+ 'locality' => transaction.shipping_details.locality,
583
+ 'region' => transaction.shipping_details.region,
584
+ 'postal_code' => transaction.shipping_details.postal_code,
585
+ 'country_name' => transaction.shipping_details.country_name
522
586
  }
523
587
  credit_card_details = {
524
- "masked_number" => transaction.credit_card_details.masked_number,
525
- "bin" => transaction.credit_card_details.bin,
526
- "last_4" => transaction.credit_card_details.last_4,
527
- "card_type" => transaction.credit_card_details.card_type,
528
- "token" => transaction.credit_card_details.token
588
+ 'masked_number' => transaction.credit_card_details.masked_number,
589
+ 'bin' => transaction.credit_card_details.bin,
590
+ 'last_4' => transaction.credit_card_details.last_4,
591
+ 'card_type' => transaction.credit_card_details.card_type,
592
+ 'token' => transaction.credit_card_details.token
529
593
  }
530
594
 
595
+ if transaction.risk_data
596
+ risk_data = {
597
+ 'id' => transaction.risk_data.id,
598
+ 'decision' => transaction.risk_data.decision,
599
+ 'device_data_captured' => transaction.risk_data.device_data_captured,
600
+ 'fraud_service_provider' => transaction.risk_data.fraud_service_provider
601
+ }
602
+ else
603
+ risk_data = nil
604
+ end
605
+
531
606
  {
532
- "order_id" => transaction.order_id,
533
- "amount" => transaction.amount.to_s,
534
- "status" => transaction.status,
535
- "credit_card_details" => credit_card_details,
536
- "customer_details" => customer_details,
537
- "billing_details" => billing_details,
538
- "shipping_details" => shipping_details,
539
- "vault_customer" => vault_customer,
540
- "merchant_account_id" => transaction.merchant_account_id,
541
- "processor_response_code" => response_code_from_result(result)
607
+ 'order_id' => transaction.order_id,
608
+ 'amount' => transaction.amount.to_s,
609
+ 'status' => transaction.status,
610
+ 'credit_card_details' => credit_card_details,
611
+ 'customer_details' => customer_details,
612
+ 'billing_details' => billing_details,
613
+ 'shipping_details' => shipping_details,
614
+ 'vault_customer' => vault_customer,
615
+ 'merchant_account_id' => transaction.merchant_account_id,
616
+ 'risk_data' => risk_data,
617
+ 'network_transaction_id' => transaction.network_transaction_id || nil,
618
+ 'processor_response_code' => response_code_from_result(result),
619
+ 'processor_authorization_code' => transaction.processor_authorization_code,
620
+ 'recurring' => transaction.recurring
542
621
  }
543
622
  end
544
623
 
545
624
  def create_transaction_parameters(money, credit_card_or_vault_id, options)
546
625
  parameters = {
547
- :amount => localized_amount(money, options[:currency] || default_currency).to_s,
548
- :order_id => options[:order_id],
549
- :customer => {
550
- :id => options[:store] == true ? "" : options[:store],
551
- :email => scrub_email(options[:email]),
552
- :phone => options[:phone] || (options[:billing_address][:phone] if options[:billing_address] &&
553
- options[:billing_address][:phone])
626
+ amount: localized_amount(money, options[:currency] || default_currency).to_s,
627
+ order_id: options[:order_id],
628
+ customer: {
629
+ id: options[:store] == true ? '' : options[:store],
630
+ email: scrub_email(options[:email]),
631
+ phone: options[:phone] || (options[:billing_address][:phone] if options[:billing_address] &&
632
+ options[:billing_address][:phone])
554
633
  },
555
- :options => {
556
- :store_in_vault => options[:store] ? true : false,
557
- :submit_for_settlement => options[:submit_for_settlement],
558
- :hold_in_escrow => options[:hold_in_escrow],
634
+ options: {
635
+ store_in_vault: options[:store] ? true : false,
636
+ submit_for_settlement: options[:submit_for_settlement],
637
+ hold_in_escrow: options[:hold_in_escrow]
559
638
  }
560
639
  }
561
640
 
562
- if options[:skip_advanced_fraud_checking]
563
- parameters[:options].merge!({ :skip_advanced_fraud_checking => options[:skip_advanced_fraud_checking] })
564
- end
565
-
566
641
  parameters[:custom_fields] = options[:custom_fields]
567
642
  parameters[:device_data] = options[:device_data] if options[:device_data]
568
643
  parameters[:service_fee_amount] = options[:service_fee_amount] if options[:service_fee_amount]
569
- if merchant_account_id = (options[:merchant_account_id] || @merchant_account_id)
570
- parameters[:merchant_account_id] = merchant_account_id
644
+
645
+ add_account_type(parameters, options) if options[:account_type]
646
+ add_skip_options(parameters, options)
647
+ add_merchant_account_id(parameters, options)
648
+ add_profile_id(parameters, options)
649
+
650
+ add_payment_method(parameters, credit_card_or_vault_id, options)
651
+ add_stored_credential_data(parameters, credit_card_or_vault_id, options)
652
+ add_addresses(parameters, options)
653
+
654
+ add_descriptor(parameters, options)
655
+ add_risk_data(parameters, options)
656
+ add_paypal_options(parameters, options)
657
+ add_travel_data(parameters, options) if options[:travel_data]
658
+ add_lodging_data(parameters, options) if options[:lodging_data]
659
+ add_channel(parameters, options)
660
+ add_transaction_source(parameters, options)
661
+
662
+ add_level_2_data(parameters, options)
663
+ add_level_3_data(parameters, options)
664
+
665
+ add_3ds_info(parameters, options[:three_d_secure])
666
+
667
+ if options[:payment_method_nonce].is_a?(String)
668
+ parameters.delete(:customer)
669
+ parameters[:payment_method_nonce] = options[:payment_method_nonce]
571
670
  end
572
671
 
573
- if options[:recurring]
574
- parameters[:recurring] = true
672
+ parameters
673
+ end
674
+
675
+ def add_account_type(parameters, options)
676
+ parameters[:options][:credit_card] = {}
677
+ parameters[:options][:credit_card][:account_type] = options[:account_type]
678
+ end
679
+
680
+ def add_skip_options(parameters, options)
681
+ parameters[:options][:skip_advanced_fraud_checking] = options[:skip_advanced_fraud_checking] if options[:skip_advanced_fraud_checking]
682
+ parameters[:options][:skip_avs] = options[:skip_avs] if options[:skip_avs]
683
+ parameters[:options][:skip_cvv] = options[:skip_cvv] if options[:skip_cvv]
684
+ end
685
+
686
+ def add_merchant_account_id(parameters, options)
687
+ return unless merchant_account_id = (options[:merchant_account_id] || @merchant_account_id)
688
+
689
+ parameters[:merchant_account_id] = merchant_account_id
690
+ end
691
+
692
+ def add_profile_id(parameters, options)
693
+ return unless profile_id = options[:venmo_profile_id]
694
+
695
+ parameters[:options][:venmo] = {}
696
+ parameters[:options][:venmo][:profile_id] = profile_id
697
+ end
698
+
699
+ def add_transaction_source(parameters, options)
700
+ parameters[:transaction_source] = options[:transaction_source] if options[:transaction_source]
701
+ parameters[:transaction_source] = 'recurring' if options[:recurring]
702
+ end
703
+
704
+ def add_addresses(parameters, options)
705
+ parameters[:billing] = map_address(options[:billing_address]) if options[:billing_address]
706
+ parameters[:shipping] = map_address(options[:shipping_address]) if options[:shipping_address]
707
+ end
708
+
709
+ def add_channel(parameters, options)
710
+ channel = @options[:channel] || application_id
711
+ parameters[:channel] = channel if channel
712
+ end
713
+
714
+ def add_descriptor(parameters, options)
715
+ return unless options[:descriptor_name] || options[:descriptor_phone] || options[:descriptor_url]
716
+
717
+ parameters[:descriptor] = {
718
+ name: options[:descriptor_name],
719
+ phone: options[:descriptor_phone],
720
+ url: options[:descriptor_url]
721
+ }
722
+ end
723
+
724
+ def add_risk_data(parameters, options)
725
+ return unless options[:risk_data]
726
+
727
+ parameters[:risk_data] = {
728
+ customer_browser: options[:risk_data][:customer_browser],
729
+ customer_ip: options[:risk_data][:customer_ip]
730
+ }
731
+ end
732
+
733
+ def add_paypal_options(parameters, options)
734
+ return unless options[:paypal_custom_field] || options[:paypal_description]
735
+
736
+ parameters[:options][:paypal] = {
737
+ custom_field: options[:paypal_custom_field],
738
+ description: options[:paypal_description]
739
+ }
740
+ end
741
+
742
+ def add_level_2_data(parameters, options)
743
+ parameters[:tax_amount] = options[:tax_amount] if options[:tax_amount]
744
+ parameters[:tax_exempt] = options[:tax_exempt] if options[:tax_exempt]
745
+ parameters[:purchase_order_number] = options[:purchase_order_number] if options[:purchase_order_number]
746
+ end
747
+
748
+ def add_level_3_data(parameters, options)
749
+ parameters[:shipping_amount] = options[:shipping_amount] if options[:shipping_amount]
750
+ parameters[:discount_amount] = options[:discount_amount] if options[:discount_amount]
751
+ parameters[:ships_from_postal_code] = options[:ships_from_postal_code] if options[:ships_from_postal_code]
752
+
753
+ parameters[:line_items] = options[:line_items] if options[:line_items]
754
+ end
755
+
756
+ def add_travel_data(parameters, options)
757
+ parameters[:industry] = {
758
+ industry_type: Braintree::Transaction::IndustryType::TravelAndCruise,
759
+ data: {}
760
+ }
761
+
762
+ parameters[:industry][:data][:travel_package] = options[:travel_data][:travel_package] if options[:travel_data][:travel_package]
763
+ parameters[:industry][:data][:departure_date] = options[:travel_data][:departure_date] if options[:travel_data][:departure_date]
764
+ parameters[:industry][:data][:lodging_check_in_date] = options[:travel_data][:lodging_check_in_date] if options[:travel_data][:lodging_check_in_date]
765
+ parameters[:industry][:data][:lodging_check_out_date] = options[:travel_data][:lodging_check_out_date] if options[:travel_data][:lodging_check_out_date]
766
+ parameters[:industry][:data][:lodging_name] = options[:travel_data][:lodging_name] if options[:travel_data][:lodging_name]
767
+ end
768
+
769
+ def add_lodging_data(parameters, options)
770
+ parameters[:industry] = {
771
+ industry_type: Braintree::Transaction::IndustryType::Lodging,
772
+ data: {}
773
+ }
774
+
775
+ parameters[:industry][:data][:folio_number] = options[:lodging_data][:folio_number] if options[:lodging_data][:folio_number]
776
+ parameters[:industry][:data][:check_in_date] = options[:lodging_data][:check_in_date] if options[:lodging_data][:check_in_date]
777
+ parameters[:industry][:data][:check_out_date] = options[:lodging_data][:check_out_date] if options[:lodging_data][:check_out_date]
778
+ parameters[:industry][:data][:room_rate] = options[:lodging_data][:room_rate] if options[:lodging_data][:room_rate]
779
+ end
780
+
781
+ def add_3ds_info(parameters, three_d_secure_opts)
782
+ return if empty?(three_d_secure_opts)
783
+
784
+ pass_thru = {}
785
+
786
+ pass_thru[:three_d_secure_version] = three_d_secure_opts[:version] if three_d_secure_opts[:version]
787
+ pass_thru[:eci_flag] = three_d_secure_opts[:eci] if three_d_secure_opts[:eci]
788
+ pass_thru[:cavv_algorithm] = three_d_secure_opts[:cavv_algorithm] if three_d_secure_opts[:cavv_algorithm]
789
+ pass_thru[:cavv] = three_d_secure_opts[:cavv] if three_d_secure_opts[:cavv]
790
+ pass_thru[:directory_response] = three_d_secure_opts[:directory_response_status] if three_d_secure_opts[:directory_response_status]
791
+ pass_thru[:authentication_response] = three_d_secure_opts[:authentication_response_status] if three_d_secure_opts[:authentication_response_status]
792
+
793
+ parameters[:three_d_secure_pass_thru] = pass_thru.merge(xid_or_ds_trans_id(three_d_secure_opts))
794
+ end
795
+
796
+ def xid_or_ds_trans_id(three_d_secure_opts)
797
+ if three_d_secure_opts[:version].to_f >= 2
798
+ { ds_transaction_id: three_d_secure_opts[:ds_transaction_id] }
799
+ else
800
+ { xid: three_d_secure_opts[:xid] }
575
801
  end
802
+ end
576
803
 
804
+ def add_stored_credential_data(parameters, credit_card_or_vault_id, options)
805
+ return unless (stored_credential = options[:stored_credential])
806
+
807
+ parameters[:external_vault] = {}
808
+ if stored_credential[:initial_transaction]
809
+ parameters[:external_vault][:status] = 'will_vault'
810
+ else
811
+ parameters[:external_vault][:status] = 'vaulted'
812
+ parameters[:external_vault][:previous_network_transaction_id] = stored_credential[:network_transaction_id]
813
+ end
814
+ if stored_credential[:initiator] == 'merchant'
815
+ if stored_credential[:reason_type] == 'installment'
816
+ parameters[:transaction_source] = 'recurring'
817
+ else
818
+ parameters[:transaction_source] = stored_credential[:reason_type]
819
+ end
820
+ elsif %w(recurring_first moto).include?(stored_credential[:reason_type])
821
+ parameters[:transaction_source] = stored_credential[:reason_type]
822
+ else
823
+ parameters[:transaction_source] = ''
824
+ end
825
+ end
826
+
827
+ def add_payment_method(parameters, credit_card_or_vault_id, options)
577
828
  if credit_card_or_vault_id.is_a?(String) || credit_card_or_vault_id.is_a?(Integer)
578
829
  if options[:payment_method_token]
579
830
  parameters[:payment_method_token] = credit_card_or_vault_id
@@ -585,64 +836,115 @@ module ActiveMerchant #:nodoc:
585
836
  end
586
837
  else
587
838
  parameters[:customer].merge!(
588
- :first_name => credit_card_or_vault_id.first_name,
589
- :last_name => credit_card_or_vault_id.last_name
839
+ first_name: credit_card_or_vault_id.first_name,
840
+ last_name: credit_card_or_vault_id.last_name
590
841
  )
591
842
  if credit_card_or_vault_id.is_a?(NetworkTokenizationCreditCard)
592
843
  if credit_card_or_vault_id.source == :apple_pay
593
844
  parameters[:apple_pay_card] = {
594
- :number => credit_card_or_vault_id.number,
595
- :expiration_month => credit_card_or_vault_id.month.to_s.rjust(2, "0"),
596
- :expiration_year => credit_card_or_vault_id.year.to_s,
597
- :cardholder_name => credit_card_or_vault_id.name,
598
- :cryptogram => credit_card_or_vault_id.payment_cryptogram,
599
- :eci_indicator => credit_card_or_vault_id.eci
845
+ number: credit_card_or_vault_id.number,
846
+ expiration_month: credit_card_or_vault_id.month.to_s.rjust(2, '0'),
847
+ expiration_year: credit_card_or_vault_id.year.to_s,
848
+ cardholder_name: credit_card_or_vault_id.name,
849
+ cryptogram: credit_card_or_vault_id.payment_cryptogram,
850
+ eci_indicator: credit_card_or_vault_id.eci
600
851
  }
601
- elsif credit_card_or_vault_id.source == :android_pay
602
- parameters[:android_pay_card] = {
603
- :number => credit_card_or_vault_id.number,
604
- :cryptogram => credit_card_or_vault_id.payment_cryptogram,
605
- :expiration_month => credit_card_or_vault_id.month.to_s.rjust(2, "0"),
606
- :expiration_year => credit_card_or_vault_id.year.to_s,
607
- :google_transaction_id => credit_card_or_vault_id.transaction_id,
608
- :source_card_type => credit_card_or_vault_id.brand,
609
- :source_card_last_four => credit_card_or_vault_id.last_digits,
610
- :eci_indicator => credit_card_or_vault_id.eci
852
+ elsif credit_card_or_vault_id.source == :android_pay || credit_card_or_vault_id.source == :google_pay
853
+ Braintree::Version::Major < 3 ? pay_card = :android_pay_card : pay_card = :google_pay_card
854
+ parameters[pay_card] = {
855
+ number: credit_card_or_vault_id.number,
856
+ cryptogram: credit_card_or_vault_id.payment_cryptogram,
857
+ expiration_month: credit_card_or_vault_id.month.to_s.rjust(2, '0'),
858
+ expiration_year: credit_card_or_vault_id.year.to_s,
859
+ google_transaction_id: credit_card_or_vault_id.transaction_id,
860
+ source_card_type: credit_card_or_vault_id.brand,
861
+ source_card_last_four: credit_card_or_vault_id.last_digits,
862
+ eci_indicator: credit_card_or_vault_id.eci
611
863
  }
612
864
  end
613
865
  else
614
866
  parameters[:credit_card] = {
615
- :number => credit_card_or_vault_id.number,
616
- :cvv => credit_card_or_vault_id.verification_value,
617
- :expiration_month => credit_card_or_vault_id.month.to_s.rjust(2, "0"),
618
- :expiration_year => credit_card_or_vault_id.year.to_s,
619
- :cardholder_name => credit_card_or_vault_id.name
867
+ number: credit_card_or_vault_id.number,
868
+ cvv: credit_card_or_vault_id.verification_value,
869
+ expiration_month: credit_card_or_vault_id.month.to_s.rjust(2, '0'),
870
+ expiration_year: credit_card_or_vault_id.year.to_s,
871
+ cardholder_name: credit_card_or_vault_id.name
620
872
  }
621
873
  end
622
874
  end
623
- parameters[:billing] = map_address(options[:billing_address]) if options[:billing_address]
624
- parameters[:shipping] = map_address(options[:shipping_address]) if options[:shipping_address]
625
-
626
- channel = @options[:channel] || application_id
627
- parameters[:channel] = channel if channel
875
+ end
628
876
 
629
- if options[:descriptor_name] || options[:descriptor_phone] || options[:descriptor_url]
630
- parameters[:descriptor] = {
631
- name: options[:descriptor_name],
632
- phone: options[:descriptor_phone],
633
- url: options[:descriptor_url]
634
- }
877
+ def bank_account_errors(payment_method, options)
878
+ if payment_method.validate.present?
879
+ payment_method.validate
880
+ elsif options[:billing_address].blank?
881
+ 'billing_address is required parameter to store and verify Bank accounts.'
882
+ elsif options[:ach_mandate].blank?
883
+ '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)'
635
884
  end
885
+ end
886
+
887
+ def add_bank_account_to_customer(payment_method, options)
888
+ bank_account_nonce, error_message = TokenNonce.new(@braintree_gateway, options).create_token_nonce_for_payment_method payment_method
889
+ return Response.new(false, error_message) unless bank_account_nonce.present?
636
890
 
637
- if options[:three_d_secure]
638
- parameters[:three_d_secure_pass_thru] = {
639
- cavv: options[:three_d_secure][:cavv],
640
- eci_flag: options[:three_d_secure][:eci],
641
- xid: options[:three_d_secure][:xid],
891
+ result = @braintree_gateway.payment_method.create(
892
+ customer_id: options[:customer],
893
+ payment_method_nonce: bank_account_nonce,
894
+ options: {
895
+ us_bank_account_verification_method: 'network_check'
642
896
  }
643
- end
897
+ )
644
898
 
645
- parameters
899
+ verified = result.success? && result.payment_method&.verified
900
+ message = message_from_result(result)
901
+ message = not_verified_reason(result.payment_method) unless verified
902
+
903
+ Response.new(verified, message,
904
+ {
905
+ customer_vault_id: options[:customer],
906
+ bank_account_token: result.payment_method&.token,
907
+ verified: verified
908
+ },
909
+ authorization: result.payment_method&.token)
910
+ end
911
+
912
+ def not_verified_reason(bank_account)
913
+ return unless bank_account.verifications.present?
914
+
915
+ verification = bank_account.verifications.first
916
+ "verification_status: [#{verification.status}], processor_response: [#{verification.processor_response_code}-#{verification.processor_response_text}]"
917
+ end
918
+
919
+ def store_bank_account(payment_method, options, multi_response)
920
+ multi_response.process { create_customer_from_bank_account payment_method, options } unless multi_response.params['exists']
921
+ multi_response.process { add_bank_account_to_customer payment_method, options }
922
+ end
923
+
924
+ def store_credit_card(payment_method, options, multi_response)
925
+ process_by = multi_response.params['exists'] ? :add_credit_card_to_customer : :add_customer_with_credit_card
926
+ multi_response.process { send process_by, payment_method, options }
927
+ end
928
+
929
+ def create_customer_from_bank_account(payment_method, options)
930
+ parameters = {
931
+ id: options[:customer],
932
+ first_name: payment_method.first_name,
933
+ last_name: payment_method.last_name,
934
+ email: scrub_email(options[:email]),
935
+ phone: options[:phone] || options.dig(:billing_address, :phone),
936
+ device_data: options[:device_data]
937
+ }.compact
938
+
939
+ result = @braintree_gateway.customer.create(parameters)
940
+ customer_id = result.customer.id if result.success?
941
+ options[:customer] = customer_id
942
+
943
+ Response.new(
944
+ result.success?,
945
+ message_from_result(result),
946
+ { customer_vault_id: customer_id, 'exists': true }
947
+ )
646
948
  end
647
949
  end
648
950
  end