start_activemerchant 1.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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