start_activemerchant 1.50.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (218) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +1769 -0
  3. data/CONTRIBUTORS +540 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +226 -0
  6. data/lib/active_merchant.rb +67 -0
  7. data/lib/active_merchant/billing.rb +15 -0
  8. data/lib/active_merchant/billing/apple_pay_payment_token.rb +22 -0
  9. data/lib/active_merchant/billing/avs_result.rb +98 -0
  10. data/lib/active_merchant/billing/base.rb +72 -0
  11. data/lib/active_merchant/billing/check.rb +76 -0
  12. data/lib/active_merchant/billing/compatibility.rb +120 -0
  13. data/lib/active_merchant/billing/credit_card.rb +404 -0
  14. data/lib/active_merchant/billing/credit_card_formatting.rb +24 -0
  15. data/lib/active_merchant/billing/credit_card_methods.rb +195 -0
  16. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  17. data/lib/active_merchant/billing/gateway.rb +291 -0
  18. data/lib/active_merchant/billing/gateways.rb +14 -0
  19. data/lib/active_merchant/billing/gateways/allied_wallet.rb +203 -0
  20. data/lib/active_merchant/billing/gateways/app55.rb +176 -0
  21. data/lib/active_merchant/billing/gateways/authorize_net.rb +510 -0
  22. data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +417 -0
  23. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +976 -0
  24. data/lib/active_merchant/billing/gateways/axcessms.rb +181 -0
  25. data/lib/active_merchant/billing/gateways/balanced.rb +256 -0
  26. data/lib/active_merchant/billing/gateways/bank_frick.rb +225 -0
  27. data/lib/active_merchant/billing/gateways/banwire.rb +105 -0
  28. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +314 -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.rb +192 -0
  32. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +389 -0
  33. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +58 -0
  34. data/lib/active_merchant/billing/gateways/blue_pay.rb +506 -0
  35. data/lib/active_merchant/billing/gateways/bogus.rb +140 -0
  36. data/lib/active_merchant/billing/gateways/borgun.rb +211 -0
  37. data/lib/active_merchant/billing/gateways/bpoint.rb +277 -0
  38. data/lib/active_merchant/billing/gateways/braintree.rb +19 -0
  39. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  40. data/lib/active_merchant/billing/gateways/braintree_blue.rb +574 -0
  41. data/lib/active_merchant/billing/gateways/braintree_orange.rb +20 -0
  42. data/lib/active_merchant/billing/gateways/bridge_pay.rb +189 -0
  43. data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
  44. data/lib/active_merchant/billing/gateways/card_stream.rb +238 -0
  45. data/lib/active_merchant/billing/gateways/cashnet.rb +202 -0
  46. data/lib/active_merchant/billing/gateways/cc5.rb +201 -0
  47. data/lib/active_merchant/billing/gateways/cecabank.rb +229 -0
  48. data/lib/active_merchant/billing/gateways/cenpos.rb +262 -0
  49. data/lib/active_merchant/billing/gateways/certo_direct.rb +278 -0
  50. data/lib/active_merchant/billing/gateways/checkout.rb +216 -0
  51. data/lib/active_merchant/billing/gateways/checkout_v2.rb +200 -0
  52. data/lib/active_merchant/billing/gateways/commercegate.rb +143 -0
  53. data/lib/active_merchant/billing/gateways/conekta.rb +210 -0
  54. data/lib/active_merchant/billing/gateways/cyber_source.rb +720 -0
  55. data/lib/active_merchant/billing/gateways/data_cash.rb +600 -0
  56. data/lib/active_merchant/billing/gateways/dibs.rb +206 -0
  57. data/lib/active_merchant/billing/gateways/efsnet.rb +219 -0
  58. data/lib/active_merchant/billing/gateways/elavon.rb +348 -0
  59. data/lib/active_merchant/billing/gateways/epay.rb +274 -0
  60. data/lib/active_merchant/billing/gateways/evo_ca.rb +308 -0
  61. data/lib/active_merchant/billing/gateways/eway.rb +214 -0
  62. data/lib/active_merchant/billing/gateways/eway_managed.rb +291 -0
  63. data/lib/active_merchant/billing/gateways/eway_rapid.rb +522 -0
  64. data/lib/active_merchant/billing/gateways/exact.rb +227 -0
  65. data/lib/active_merchant/billing/gateways/ezic.rb +206 -0
  66. data/lib/active_merchant/billing/gateways/fat_zebra.rb +213 -0
  67. data/lib/active_merchant/billing/gateways/federated_canada.rb +160 -0
  68. data/lib/active_merchant/billing/gateways/finansbank.rb +23 -0
  69. data/lib/active_merchant/billing/gateways/first_giving.rb +143 -0
  70. data/lib/active_merchant/billing/gateways/first_pay.rb +160 -0
  71. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +413 -0
  72. data/lib/active_merchant/billing/gateways/flo2cash.rb +215 -0
  73. data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +20 -0
  74. data/lib/active_merchant/billing/gateways/garanti.rb +261 -0
  75. data/lib/active_merchant/billing/gateways/global_transport.rb +179 -0
  76. data/lib/active_merchant/billing/gateways/hdfc.rb +207 -0
  77. data/lib/active_merchant/billing/gateways/hps.rb +287 -0
  78. data/lib/active_merchant/billing/gateways/iats_payments.rb +277 -0
  79. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +246 -0
  80. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  81. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  82. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +66 -0
  83. data/lib/active_merchant/billing/gateways/inspire.rb +219 -0
  84. data/lib/active_merchant/billing/gateways/instapay.rb +163 -0
  85. data/lib/active_merchant/billing/gateways/ipp.rb +175 -0
  86. data/lib/active_merchant/billing/gateways/iridium.rb +457 -0
  87. data/lib/active_merchant/billing/gateways/itransact.rb +448 -0
  88. data/lib/active_merchant/billing/gateways/jetpay.rb +275 -0
  89. data/lib/active_merchant/billing/gateways/linkpoint.rb +438 -0
  90. data/lib/active_merchant/billing/gateways/litle.rb +345 -0
  91. data/lib/active_merchant/billing/gateways/maxipago.rb +197 -0
  92. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +170 -0
  93. data/lib/active_merchant/billing/gateways/merchant_one.rb +114 -0
  94. data/lib/active_merchant/billing/gateways/merchant_partners.rb +245 -0
  95. data/lib/active_merchant/billing/gateways/merchant_ware.rb +319 -0
  96. data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +268 -0
  97. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +195 -0
  98. data/lib/active_merchant/billing/gateways/mercury.rb +326 -0
  99. data/lib/active_merchant/billing/gateways/metrics_global.rb +303 -0
  100. data/lib/active_merchant/billing/gateways/migs.rb +280 -0
  101. data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
  102. data/lib/active_merchant/billing/gateways/modern_payments.rb +37 -0
  103. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +219 -0
  104. data/lib/active_merchant/billing/gateways/monei.rb +307 -0
  105. data/lib/active_merchant/billing/gateways/moneris.rb +309 -0
  106. data/lib/active_merchant/billing/gateways/moneris_us.rb +298 -0
  107. data/lib/active_merchant/billing/gateways/money_movers.rb +152 -0
  108. data/lib/active_merchant/billing/gateways/nab_transact.rb +290 -0
  109. data/lib/active_merchant/billing/gateways/net_registry.rb +198 -0
  110. data/lib/active_merchant/billing/gateways/netaxept.rb +181 -0
  111. data/lib/active_merchant/billing/gateways/netbilling.rb +224 -0
  112. data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
  113. data/lib/active_merchant/billing/gateways/network_merchants.rb +242 -0
  114. data/lib/active_merchant/billing/gateways/nmi.rb +256 -0
  115. data/lib/active_merchant/billing/gateways/ogone.rb +435 -0
  116. data/lib/active_merchant/billing/gateways/omise.rb +319 -0
  117. data/lib/active_merchant/billing/gateways/openpay.rb +194 -0
  118. data/lib/active_merchant/billing/gateways/optimal_payment.rb +314 -0
  119. data/lib/active_merchant/billing/gateways/orbital.rb +834 -0
  120. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +47 -0
  121. data/lib/active_merchant/billing/gateways/pac_net_raven.rb +207 -0
  122. data/lib/active_merchant/billing/gateways/pago_facil.rb +122 -0
  123. data/lib/active_merchant/billing/gateways/pay_conex.rb +246 -0
  124. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +277 -0
  125. data/lib/active_merchant/billing/gateways/pay_hub.rb +213 -0
  126. data/lib/active_merchant/billing/gateways/pay_junction.rb +390 -0
  127. data/lib/active_merchant/billing/gateways/pay_secure.rb +112 -0
  128. data/lib/active_merchant/billing/gateways/paybox_direct.rb +188 -0
  129. data/lib/active_merchant/billing/gateways/payex.rb +412 -0
  130. data/lib/active_merchant/billing/gateways/payflow.rb +308 -0
  131. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +220 -0
  132. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  133. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  134. data/lib/active_merchant/billing/gateways/payflow_express.rb +224 -0
  135. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  136. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  137. data/lib/active_merchant/billing/gateways/payment_express.rb +353 -0
  138. data/lib/active_merchant/billing/gateways/paymill.rb +282 -0
  139. data/lib/active_merchant/billing/gateways/paypal.rb +129 -0
  140. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +679 -0
  141. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +65 -0
  142. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +262 -0
  143. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  144. data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +44 -0
  145. data/lib/active_merchant/billing/gateways/paypal_express.rb +264 -0
  146. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +30 -0
  147. data/lib/active_merchant/billing/gateways/payscout.rb +162 -0
  148. data/lib/active_merchant/billing/gateways/paystation.rb +199 -0
  149. data/lib/active_merchant/billing/gateways/payu_in.rb +247 -0
  150. data/lib/active_merchant/billing/gateways/payway.rb +207 -0
  151. data/lib/active_merchant/billing/gateways/pin.rb +207 -0
  152. data/lib/active_merchant/billing/gateways/plugnpay.rb +283 -0
  153. data/lib/active_merchant/billing/gateways/psigate.rb +216 -0
  154. data/lib/active_merchant/billing/gateways/psl_card.rb +303 -0
  155. data/lib/active_merchant/billing/gateways/qbms.rb +292 -0
  156. data/lib/active_merchant/billing/gateways/quantum.rb +276 -0
  157. data/lib/active_merchant/billing/gateways/quickbooks.rb +280 -0
  158. data/lib/active_merchant/billing/gateways/quickpay.rb +26 -0
  159. data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +188 -0
  160. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +240 -0
  161. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +227 -0
  162. data/lib/active_merchant/billing/gateways/qvalent.rb +179 -0
  163. data/lib/active_merchant/billing/gateways/realex.rb +298 -0
  164. data/lib/active_merchant/billing/gateways/redsys.rb +406 -0
  165. data/lib/active_merchant/billing/gateways/s5.rb +226 -0
  166. data/lib/active_merchant/billing/gateways/sage.rb +173 -0
  167. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +89 -0
  168. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +115 -0
  169. data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +149 -0
  170. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  171. data/lib/active_merchant/billing/gateways/sage_pay.rb +399 -0
  172. data/lib/active_merchant/billing/gateways/sallie_mae.rb +143 -0
  173. data/lib/active_merchant/billing/gateways/secure_net.rb +263 -0
  174. data/lib/active_merchant/billing/gateways/secure_pay.rb +201 -0
  175. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +281 -0
  176. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +105 -0
  177. data/lib/active_merchant/billing/gateways/skip_jack.rb +451 -0
  178. data/lib/active_merchant/billing/gateways/smart_ps.rb +283 -0
  179. data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
  180. data/lib/active_merchant/billing/gateways/spreedly_core.rb +247 -0
  181. data/lib/active_merchant/billing/gateways/stripe.rb +489 -0
  182. data/lib/active_merchant/billing/gateways/swipe_checkout.rb +157 -0
  183. data/lib/active_merchant/billing/gateways/tns.rb +227 -0
  184. data/lib/active_merchant/billing/gateways/trans_first.rb +126 -0
  185. data/lib/active_merchant/billing/gateways/transax.rb +23 -0
  186. data/lib/active_merchant/billing/gateways/transnational.rb +10 -0
  187. data/lib/active_merchant/billing/gateways/trust_commerce.rb +416 -0
  188. data/lib/active_merchant/billing/gateways/usa_epay.rb +25 -0
  189. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1516 -0
  190. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +259 -0
  191. data/lib/active_merchant/billing/gateways/vanco.rb +280 -0
  192. data/lib/active_merchant/billing/gateways/verifi.rb +225 -0
  193. data/lib/active_merchant/billing/gateways/viaklix.rb +183 -0
  194. data/lib/active_merchant/billing/gateways/webpay.rb +97 -0
  195. data/lib/active_merchant/billing/gateways/wepay.rb +205 -0
  196. data/lib/active_merchant/billing/gateways/wirecard.rb +420 -0
  197. data/lib/active_merchant/billing/gateways/worldpay.rb +331 -0
  198. data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +204 -0
  199. data/lib/active_merchant/billing/gateways/worldpay_us.rb +181 -0
  200. data/lib/active_merchant/billing/model.rb +30 -0
  201. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +24 -0
  202. data/lib/active_merchant/billing/payment_token.rb +21 -0
  203. data/lib/active_merchant/billing/rails.rb +3 -0
  204. data/lib/active_merchant/billing/response.rb +92 -0
  205. data/lib/active_merchant/connection.rb +172 -0
  206. data/lib/active_merchant/country.rb +332 -0
  207. data/lib/active_merchant/empty.rb +20 -0
  208. data/lib/active_merchant/errors.rb +35 -0
  209. data/lib/active_merchant/network_connection_retries.rb +79 -0
  210. data/lib/active_merchant/post_data.rb +24 -0
  211. data/lib/active_merchant/posts_data.rb +84 -0
  212. data/lib/active_merchant/version.rb +3 -0
  213. data/lib/activemerchant.rb +1 -0
  214. data/lib/certs/cacert.pem +3866 -0
  215. data/lib/support/gateway_support.rb +71 -0
  216. data/lib/support/outbound_hosts.rb +28 -0
  217. data/lib/support/ssl_verify.rb +93 -0
  218. metadata +387 -0
@@ -0,0 +1,19 @@
1
+ require 'active_merchant/billing/gateways/braintree/braintree_common'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class BraintreeGateway < Gateway
6
+ include BraintreeCommon
7
+
8
+ self.abstract_class = true
9
+
10
+ def self.new(options={})
11
+ if options.has_key?(:login)
12
+ BraintreeOrangeGateway.new(options)
13
+ else
14
+ BraintreeBlueGateway.new(options)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,9 @@
1
+ module BraintreeCommon
2
+ def self.included(base)
3
+ base.supported_countries = %w(US CA AU AD AT BE BG CY CZ DK EE FI FR GI DE GR HU IS IM IE IT LV LI LT LU MT MC NL NO PL PT RO SM SK SI ES SE CH TR GB)
4
+ base.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club]
5
+ base.homepage_url = 'http://www.braintreepaymentsolutions.com'
6
+ base.display_name = 'Braintree'
7
+ base.default_currency = 'USD'
8
+ end
9
+ end
@@ -0,0 +1,574 @@
1
+ require 'active_merchant/billing/gateways/braintree/braintree_common'
2
+
3
+ begin
4
+ require "braintree"
5
+ rescue LoadError
6
+ raise "Could not load the braintree gem. Use `gem install braintree` to install it."
7
+ end
8
+
9
+ raise "Need braintree gem 2.x.y. Run `gem install braintree --version '~>2.0'` to get the correct version." unless Braintree::Version::Major == 2
10
+
11
+ module ActiveMerchant #:nodoc:
12
+ module Billing #:nodoc:
13
+ # For more information on the Braintree Gateway please visit their
14
+ # {Developer Portal}[https://www.braintreepayments.com/developers]
15
+ #
16
+ # ==== About this implementation
17
+ #
18
+ # This implementation leverages the Braintree-authored ruby gem:
19
+ # https://github.com/braintree/braintree_ruby
20
+ #
21
+ # ==== Debugging Information
22
+ #
23
+ # Setting an ActiveMerchant +wiredump_device+ will automatically
24
+ # configure the Braintree logger (via the Braintree gem's
25
+ # configuration) when the BraintreeBlueGateway is instantiated.
26
+ # Additionally, the log level will be set to +DEBUG+. Therefore,
27
+ # all you have to do is set the +wiredump_device+ and you'll get
28
+ # your debug output from your HTTP interactions with the remote
29
+ # gateway. (Don't enable this in production.) The ActiveMerchant
30
+ # implementation doesn't mess with the Braintree::Configuration
31
+ # globals at all, so there won't be any side effects outside
32
+ # Active Merchant.
33
+ #
34
+ # If no +wiredump_device+ is set, the logger in
35
+ # +Braintree::Configuration.logger+ will be cloned and the log
36
+ # level set to +WARN+.
37
+ #
38
+ class BraintreeBlueGateway < Gateway
39
+ include BraintreeCommon
40
+
41
+ self.display_name = 'Braintree (Blue Platform)'
42
+
43
+ def initialize(options = {})
44
+ requires!(options, :merchant_id, :public_key, :private_key)
45
+ @merchant_account_id = options[:merchant_account_id]
46
+
47
+ super
48
+
49
+ if wiredump_device
50
+ logger = ((Logger === wiredump_device) ? wiredump_device : Logger.new(wiredump_device))
51
+ logger.level = Logger::DEBUG
52
+ else
53
+ logger = Braintree::Configuration.logger.clone
54
+ logger.level = Logger::WARN
55
+ end
56
+
57
+ @configuration = Braintree::Configuration.new(
58
+ :merchant_id => options[:merchant_id],
59
+ :public_key => options[:public_key],
60
+ :private_key => options[:private_key],
61
+ :environment => (options[:environment] || (test? ? :sandbox : :production)).to_sym,
62
+ :custom_user_agent => "ActiveMerchant #{ActiveMerchant::VERSION}",
63
+ :logger => logger,
64
+ )
65
+
66
+ @braintree_gateway = Braintree::Gateway.new( @configuration )
67
+ end
68
+
69
+ def authorize(money, credit_card_or_vault_id, options = {})
70
+ create_transaction(:sale, money, credit_card_or_vault_id, options)
71
+ end
72
+
73
+ def capture(money, authorization, options = {})
74
+ commit do
75
+ result = @braintree_gateway.transaction.submit_for_settlement(authorization, amount(money).to_s)
76
+ response_from_result(result)
77
+ end
78
+ end
79
+
80
+ def purchase(money, credit_card_or_vault_id, options = {})
81
+ authorize(money, credit_card_or_vault_id, options.merge(:submit_for_settlement => true))
82
+ end
83
+
84
+ def credit(money, credit_card_or_vault_id, options = {})
85
+ create_transaction(:credit, money, credit_card_or_vault_id, options)
86
+ end
87
+
88
+ def refund(*args)
89
+ # legacy signature: #refund(transaction_id, options = {})
90
+ # new signature: #refund(money, transaction_id, options = {})
91
+ money, transaction_id, _ = extract_refund_args(args)
92
+ money = amount(money).to_s if money
93
+
94
+ commit do
95
+ response_from_result(@braintree_gateway.transaction.refund(transaction_id, money))
96
+ end
97
+ end
98
+
99
+ def void(authorization, options = {})
100
+ commit do
101
+ response_from_result(@braintree_gateway.transaction.void(authorization))
102
+ end
103
+ end
104
+
105
+ def verify(credit_card, options = {})
106
+ MultiResponse.run(:use_first_response) do |r|
107
+ r.process { authorize(100, credit_card, options) }
108
+ r.process(:ignore_result) { void(r.authorization, options) }
109
+ end
110
+ end
111
+
112
+ def store(creditcard, options = {})
113
+ if options[:customer].present?
114
+ MultiResponse.new.tap do |r|
115
+ customer_exists_response = nil
116
+ r.process{customer_exists_response = check_customer_exists(options[:customer])}
117
+ r.process do
118
+ if customer_exists_response.params["exists"]
119
+ add_credit_card_to_customer(creditcard, options)
120
+ else
121
+ add_customer_with_credit_card(creditcard, options)
122
+ end
123
+ end
124
+ end
125
+ else
126
+ add_customer_with_credit_card(creditcard, options)
127
+ end
128
+ end
129
+
130
+ def update(vault_id, creditcard, options = {})
131
+ braintree_credit_card = nil
132
+ commit do
133
+ braintree_credit_card = @braintree_gateway.customer.find(vault_id).credit_cards.detect { |cc| cc.default? }
134
+ return Response.new(false, 'Braintree::NotFoundError') if braintree_credit_card.nil?
135
+
136
+ options.merge!(:update_existing_token => braintree_credit_card.token)
137
+ credit_card_params = merge_credit_card_options({
138
+ :credit_card => {
139
+ :cardholder_name => creditcard.name,
140
+ :number => creditcard.number,
141
+ :cvv => creditcard.verification_value,
142
+ :expiration_month => creditcard.month.to_s.rjust(2, "0"),
143
+ :expiration_year => creditcard.year.to_s
144
+ }
145
+ }, options)[:credit_card]
146
+
147
+ result = @braintree_gateway.customer.update(vault_id,
148
+ :first_name => creditcard.first_name,
149
+ :last_name => creditcard.last_name,
150
+ :email => scrub_email(options[:email]),
151
+ :credit_card => credit_card_params
152
+ )
153
+ Response.new(result.success?, message_from_result(result),
154
+ :braintree_customer => (customer_hash(@braintree_gateway.customer.find(vault_id), :include_credit_cards) if result.success?),
155
+ :customer_vault_id => (result.customer.id if result.success?)
156
+ )
157
+ end
158
+ end
159
+
160
+ def unstore(customer_vault_id, options = {})
161
+ commit do
162
+ if(!customer_vault_id && options[:credit_card_token])
163
+ @braintree_gateway.credit_card.delete(options[:credit_card_token])
164
+ else
165
+ @braintree_gateway.customer.delete(customer_vault_id)
166
+ end
167
+ Response.new(true, "OK")
168
+ end
169
+ end
170
+ alias_method :delete, :unstore
171
+
172
+ private
173
+
174
+ def check_customer_exists(customer_vault_id)
175
+ commit do
176
+ begin
177
+ @braintree_gateway.customer.find(customer_vault_id)
178
+ ActiveMerchant::Billing::Response.new(true, "Customer found", {exists: true}, authorization: customer_vault_id)
179
+ rescue Braintree::NotFoundError
180
+ ActiveMerchant::Billing::Response.new(true, "Customer not found", {exists: false})
181
+ end
182
+ end
183
+ end
184
+
185
+ def add_customer_with_credit_card(creditcard, options)
186
+ commit do
187
+ parameters = {
188
+ :first_name => creditcard.first_name,
189
+ :last_name => creditcard.last_name,
190
+ :email => scrub_email(options[:email]),
191
+ :id => options[:customer],
192
+ :credit_card => {
193
+ :cardholder_name => creditcard.name,
194
+ :number => creditcard.number,
195
+ :cvv => creditcard.verification_value,
196
+ :expiration_month => creditcard.month.to_s.rjust(2, "0"),
197
+ :expiration_year => creditcard.year.to_s,
198
+ :token => options[:credit_card_token]
199
+ }
200
+ }
201
+ result = @braintree_gateway.customer.create(merge_credit_card_options(parameters, options))
202
+ Response.new(result.success?, message_from_result(result),
203
+ {
204
+ :braintree_customer => (customer_hash(result.customer, :include_credit_cards) if result.success?),
205
+ :customer_vault_id => (result.customer.id if result.success?),
206
+ :credit_card_token => (result.customer.credit_cards[0].token if result.success?)
207
+ },
208
+ :authorization => (result.customer.id if result.success?)
209
+ )
210
+ end
211
+ end
212
+
213
+ def add_credit_card_to_customer(credit_card, options)
214
+ commit do
215
+ parameters = {
216
+ customer_id: options[:customer],
217
+ token: options[:credit_card_token],
218
+ cardholder_name: credit_card.name,
219
+ number: credit_card.number,
220
+ cvv: credit_card.verification_value,
221
+ expiration_month: credit_card.month.to_s.rjust(2, "0"),
222
+ expiration_year: credit_card.year.to_s,
223
+ }
224
+ parameters[:billing_address] = map_address(options[:billing_address]) if options[:billing_address]
225
+
226
+ result = @braintree_gateway.credit_card.create(parameters)
227
+ ActiveMerchant::Billing::Response.new(
228
+ result.success?,
229
+ message_from_result(result),
230
+ {
231
+ customer_vault_id: (result.credit_card.customer_id if result.success?),
232
+ credit_card_token: (result.credit_card.token if result.success?)
233
+ },
234
+ authorization: (result.credit_card.customer_id if result.success?)
235
+ )
236
+ end
237
+ end
238
+
239
+ def scrub_email(email)
240
+ return nil unless email.present?
241
+ return nil if (
242
+ email !~ /^.+@[^\.]+(\.[^\.]+)+[a-z]$/i ||
243
+ email =~ /\.(con|met)$/i
244
+ )
245
+ email
246
+ end
247
+
248
+ def scrub_zip(zip)
249
+ return nil unless zip.present?
250
+ return nil if(
251
+ zip.gsub(/[^a-z0-9]/i, '').length > 9 ||
252
+ zip =~ /[^a-z0-9\- ]/i
253
+ )
254
+ zip
255
+ end
256
+
257
+ def merge_credit_card_options(parameters, options)
258
+ valid_options = {}
259
+ options.each do |key, value|
260
+ valid_options[key] = value if [:update_existing_token, :verify_card, :verification_merchant_account_id].include?(key)
261
+ end
262
+
263
+ if valid_options.include?(:verify_card) && @merchant_account_id
264
+ valid_options[:verification_merchant_account_id] ||= @merchant_account_id
265
+ end
266
+
267
+ parameters[:credit_card] ||= {}
268
+ parameters[:credit_card].merge!(:options => valid_options)
269
+ parameters[:credit_card][:billing_address] = map_address(options[:billing_address]) if options[:billing_address]
270
+ parameters
271
+ end
272
+
273
+ def map_address(address)
274
+ return {} if address.nil?
275
+ mapped = {
276
+ :street_address => address[:address1],
277
+ :extended_address => address[:address2],
278
+ :company => address[:company],
279
+ :locality => address[:city],
280
+ :region => address[:state],
281
+ :postal_code => scrub_zip(address[:zip]),
282
+ }
283
+ if(address[:country] || address[:country_code_alpha2])
284
+ mapped[:country_code_alpha2] = (address[:country] || address[:country_code_alpha2])
285
+ elsif address[:country_name]
286
+ mapped[:country_name] = address[:country_name]
287
+ elsif address[:country_code_alpha3]
288
+ mapped[:country_code_alpha3] = address[:country_code_alpha3]
289
+ elsif address[:country_code_numeric]
290
+ mapped[:country_code_numeric] = address[:country_code_numeric]
291
+ end
292
+ mapped
293
+ end
294
+
295
+ def commit(&block)
296
+ yield
297
+ rescue Braintree::BraintreeError => ex
298
+ Response.new(false, ex.class.to_s)
299
+ end
300
+
301
+ def message_from_result(result)
302
+ if result.success?
303
+ "OK"
304
+ elsif result.errors.size == 0 && result.credit_card_verification
305
+ "Processor declined: #{result.credit_card_verification.processor_response_text} (#{result.credit_card_verification.processor_response_code})"
306
+ else
307
+ result.errors.map { |e| "#{e.message} (#{e.code})" }.join(" ")
308
+ end
309
+ end
310
+
311
+ def response_from_result(result)
312
+ Response.new(result.success?, message_from_result(result),
313
+ { braintree_transaction: transaction_hash(result) },
314
+ { authorization: (result.transaction.id if result.success?) }
315
+ )
316
+ end
317
+
318
+ def response_params(result)
319
+ params = {}
320
+ params[:customer_vault_id] = result.transaction.customer_details.id if result.success?
321
+ params[:braintree_transaction] = transaction_hash(result)
322
+ params
323
+ end
324
+
325
+ def response_options(result)
326
+ options = {}
327
+ if result.success?
328
+ options[:authorization] = result.transaction.id
329
+ end
330
+ if result.transaction
331
+ options[:avs_result] = { code: avs_code_from(result.transaction) }
332
+ options[:cvv_result] = result.transaction.cvv_response_code
333
+ end
334
+ options
335
+ end
336
+
337
+ def avs_code_from(transaction)
338
+ transaction.avs_error_response_code ||
339
+ avs_mapping["street: #{transaction.avs_street_address_response_code}, zip: #{transaction.avs_postal_code_response_code}"]
340
+ end
341
+
342
+ def avs_mapping
343
+ {
344
+ "street: M, zip: M" => "M",
345
+ "street: M, zip: N" => "A",
346
+ "street: M, zip: U" => "B",
347
+ "street: M, zip: I" => "B",
348
+ "street: M, zip: A" => "B",
349
+
350
+ "street: N, zip: M" => "Z",
351
+ "street: N, zip: N" => "C",
352
+ "street: N, zip: U" => "C",
353
+ "street: N, zip: I" => "C",
354
+ "street: N, zip: A" => "C",
355
+
356
+ "street: U, zip: M" => "P",
357
+ "street: U, zip: N" => "N",
358
+ "street: U, zip: U" => "I",
359
+ "street: U, zip: I" => "I",
360
+ "street: U, zip: A" => "I",
361
+
362
+ "street: I, zip: M" => "P",
363
+ "street: I, zip: N" => "C",
364
+ "street: I, zip: U" => "I",
365
+ "street: I, zip: I" => "I",
366
+ "street: I, zip: A" => "I",
367
+
368
+ "street: A, zip: M" => "P",
369
+ "street: A, zip: N" => "C",
370
+ "street: A, zip: U" => "I",
371
+ "street: A, zip: I" => "I",
372
+ "street: A, zip: A" => "I"
373
+ }
374
+ end
375
+
376
+ def message_from_transaction_result(result)
377
+ if result.transaction && result.transaction.status == "gateway_rejected"
378
+ "Transaction declined - gateway rejected"
379
+ elsif result.transaction
380
+ "#{result.transaction.processor_response_code} #{result.transaction.processor_response_text}"
381
+ else
382
+ message_from_result(result)
383
+ end
384
+ end
385
+
386
+ def response_code_from_result(result)
387
+ if result.transaction
388
+ result.transaction.processor_response_code
389
+ elsif result.errors.size == 0 && result.credit_card_verification
390
+ result.credit_card_verification.processor_response_code
391
+ elsif result.errors.size > 0
392
+ result.errors.first.code
393
+ end
394
+ end
395
+
396
+ def create_transaction(transaction_type, money, credit_card_or_vault_id, options)
397
+ transaction_params = create_transaction_parameters(money, credit_card_or_vault_id, options)
398
+ commit do
399
+ result = @braintree_gateway.transaction.send(transaction_type, transaction_params)
400
+ response = Response.new(result.success?, message_from_transaction_result(result), response_params(result), response_options(result))
401
+ response.cvv_result['message'] = ''
402
+ response
403
+ end
404
+ end
405
+
406
+ def extract_refund_args(args)
407
+ options = args.extract_options!
408
+
409
+ # money, transaction_id, options
410
+ if args.length == 1 # legacy signature
411
+ return nil, args[0], options
412
+ elsif args.length == 2
413
+ return args[0], args[1], options
414
+ else
415
+ raise ArgumentError, "wrong number of arguments (#{args.length} for 2)"
416
+ end
417
+ end
418
+
419
+ def customer_hash(customer, include_credit_cards=false)
420
+ hash = {
421
+ "email" => customer.email,
422
+ "first_name" => customer.first_name,
423
+ "last_name" => customer.last_name,
424
+ "id" => customer.id
425
+ }
426
+
427
+ if include_credit_cards
428
+ hash["credit_cards"] = customer.credit_cards.map do |cc|
429
+ {
430
+ "bin" => cc.bin,
431
+ "expiration_date" => cc.expiration_date,
432
+ "token" => cc.token,
433
+ "last_4" => cc.last_4,
434
+ "card_type" => cc.card_type,
435
+ "masked_number" => cc.masked_number
436
+ }
437
+ end
438
+ end
439
+
440
+ hash
441
+ end
442
+
443
+ def transaction_hash(result)
444
+ unless result.success?
445
+ return { "processor_response_code" => response_code_from_result(result) }
446
+ end
447
+
448
+ transaction = result.transaction
449
+ if transaction.vault_customer
450
+ vault_customer = {
451
+ }
452
+ vault_customer["credit_cards"] = transaction.vault_customer.credit_cards.map do |cc|
453
+ {
454
+ "bin" => cc.bin
455
+ }
456
+ end
457
+ else
458
+ vault_customer = nil
459
+ end
460
+
461
+ customer_details = {
462
+ "id" => transaction.customer_details.id,
463
+ "email" => transaction.customer_details.email
464
+ }
465
+
466
+ billing_details = {
467
+ "street_address" => transaction.billing_details.street_address,
468
+ "extended_address" => transaction.billing_details.extended_address,
469
+ "company" => transaction.billing_details.company,
470
+ "locality" => transaction.billing_details.locality,
471
+ "region" => transaction.billing_details.region,
472
+ "postal_code" => transaction.billing_details.postal_code,
473
+ "country_name" => transaction.billing_details.country_name,
474
+ }
475
+
476
+ shipping_details = {
477
+ "street_address" => transaction.shipping_details.street_address,
478
+ "extended_address" => transaction.shipping_details.extended_address,
479
+ "company" => transaction.shipping_details.company,
480
+ "locality" => transaction.shipping_details.locality,
481
+ "region" => transaction.shipping_details.region,
482
+ "postal_code" => transaction.shipping_details.postal_code,
483
+ "country_name" => transaction.shipping_details.country_name,
484
+ }
485
+ credit_card_details = {
486
+ "masked_number" => transaction.credit_card_details.masked_number,
487
+ "bin" => transaction.credit_card_details.bin,
488
+ "last_4" => transaction.credit_card_details.last_4,
489
+ "card_type" => transaction.credit_card_details.card_type,
490
+ "token" => transaction.credit_card_details.token
491
+ }
492
+
493
+ {
494
+ "order_id" => transaction.order_id,
495
+ "status" => transaction.status,
496
+ "credit_card_details" => credit_card_details,
497
+ "customer_details" => customer_details,
498
+ "billing_details" => billing_details,
499
+ "shipping_details" => shipping_details,
500
+ "vault_customer" => vault_customer,
501
+ "merchant_account_id" => transaction.merchant_account_id,
502
+ "processor_response_code" => response_code_from_result(result)
503
+ }
504
+ end
505
+
506
+ def create_transaction_parameters(money, credit_card_or_vault_id, options)
507
+ parameters = {
508
+ :amount => amount(money).to_s,
509
+ :order_id => options[:order_id],
510
+ :customer => {
511
+ :id => options[:store] == true ? "" : options[:store],
512
+ :email => scrub_email(options[:email])
513
+ },
514
+ :options => {
515
+ :store_in_vault => options[:store] ? true : false,
516
+ :submit_for_settlement => options[:submit_for_settlement]
517
+ }
518
+ }
519
+
520
+ parameters[:custom_fields] = options[:custom_fields]
521
+ parameters[:device_data] = options[:device_data] if options[:device_data]
522
+ parameters[:service_fee_amount] = options[:service_fee_amount] if options[:service_fee_amount]
523
+ if merchant_account_id = (options[:merchant_account_id] || @merchant_account_id)
524
+ parameters[:merchant_account_id] = merchant_account_id
525
+ end
526
+
527
+ if options[:recurring]
528
+ parameters[:recurring] = true
529
+ end
530
+
531
+ if credit_card_or_vault_id.is_a?(String) || credit_card_or_vault_id.is_a?(Integer)
532
+ if options[:payment_method_token]
533
+ parameters[:payment_method_token] = credit_card_or_vault_id
534
+ else
535
+ parameters[:customer_id] = credit_card_or_vault_id
536
+ end
537
+ else
538
+ parameters[:customer].merge!(
539
+ :first_name => credit_card_or_vault_id.first_name,
540
+ :last_name => credit_card_or_vault_id.last_name
541
+ )
542
+ if credit_card_or_vault_id.is_a?(NetworkTokenizationCreditCard)
543
+ parameters[:apple_pay_card] = {
544
+ :number => credit_card_or_vault_id.number,
545
+ :expiration_month => credit_card_or_vault_id.month.to_s.rjust(2, "0"),
546
+ :expiration_year => credit_card_or_vault_id.year.to_s,
547
+ :cardholder_name => "#{credit_card_or_vault_id.first_name} #{credit_card_or_vault_id.last_name}",
548
+ :cryptogram => credit_card_or_vault_id.payment_cryptogram
549
+ }
550
+ else
551
+ parameters[:credit_card] = {
552
+ :number => credit_card_or_vault_id.number,
553
+ :cvv => credit_card_or_vault_id.verification_value,
554
+ :expiration_month => credit_card_or_vault_id.month.to_s.rjust(2, "0"),
555
+ :expiration_year => credit_card_or_vault_id.year.to_s
556
+ }
557
+ end
558
+ end
559
+ parameters[:billing] = map_address(options[:billing_address]) if options[:billing_address] && !options[:payment_method_token]
560
+ parameters[:shipping] = map_address(options[:shipping_address]) if options[:shipping_address]
561
+ parameters[:channel] = application_id if application_id.present? && application_id != "ActiveMerchant"
562
+
563
+ if options[:descriptor_name] || options[:descriptor_phone]
564
+ parameters[:descriptor] = {
565
+ name: options[:descriptor_name],
566
+ phone: options[:descriptor_phone]
567
+ }
568
+ end
569
+
570
+ parameters
571
+ end
572
+ end
573
+ end
574
+ end