solidus_braintree 1.2.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (213) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +78 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github/stale.yml +1 -0
  5. data/.github_changelog_generator +2 -0
  6. data/.gitignore +21 -10
  7. data/.rspec +1 -1
  8. data/.rubocop.yml +86 -0
  9. data/CHANGELOG.md +186 -18
  10. data/Gemfile +35 -17
  11. data/LICENSE +26 -0
  12. data/README.md +389 -24
  13. data/Rakefile +6 -16
  14. data/app/assets/config/solidus_braintree_manifest.js +0 -0
  15. data/app/assets/javascripts/spree/backend/solidus_braintree/client.js +239 -0
  16. data/app/assets/javascripts/spree/backend/solidus_braintree/constants.js +89 -0
  17. data/app/assets/javascripts/spree/backend/solidus_braintree/hosted_form.js +46 -0
  18. data/app/assets/javascripts/spree/backend/solidus_braintree/promise.js +20 -0
  19. data/app/assets/javascripts/spree/backend/solidus_braintree.js +96 -0
  20. data/app/assets/stylesheets/spree/backend/solidus_braintree.scss +28 -0
  21. data/app/decorators/controllers/solidus_braintree/admin_payments_controller_decorator.rb +11 -0
  22. data/app/decorators/controllers/solidus_braintree/client_tokens_controller.rb +41 -0
  23. data/app/decorators/models/solidus_braintree/spree/store_decorator.rb +20 -0
  24. data/app/decorators/models/solidus_braintree/spree/user_decorator.rb +13 -0
  25. data/app/helpers/solidus_braintree/braintree_admin_helper.rb +23 -0
  26. data/app/models/application_record.rb +5 -0
  27. data/app/models/solidus_braintree/address.rb +64 -0
  28. data/app/models/solidus_braintree/avs_result.rb +69 -0
  29. data/app/models/solidus_braintree/configuration.rb +39 -0
  30. data/app/models/solidus_braintree/customer.rb +8 -0
  31. data/app/models/solidus_braintree/gateway.rb +437 -0
  32. data/app/models/solidus_braintree/response.rb +80 -0
  33. data/app/models/solidus_braintree/source.rb +140 -0
  34. data/app/models/solidus_braintree/transaction.rb +31 -0
  35. data/app/models/solidus_braintree/transaction_address.rb +88 -0
  36. data/app/models/solidus_braintree/transaction_import.rb +98 -0
  37. data/app/views/spree/api/payments/source_views/_braintree.json.jbuilder +3 -0
  38. data/bin/console +4 -1
  39. data/bin/dummy-app +37 -0
  40. data/bin/rails +5 -5
  41. data/bin/rails-dummy-app +17 -0
  42. data/bin/rails-engine +13 -0
  43. data/bin/rails-sandbox +16 -0
  44. data/bin/rake +7 -0
  45. data/bin/rspec +11 -0
  46. data/bin/sandbox +61 -0
  47. data/bin/setup +5 -4
  48. data/config/locales/en.yml +94 -2
  49. data/config/locales/it.yml +56 -0
  50. data/config/routes.rb +12 -3
  51. data/db/migrate/20160830061749_create_solidus_paypal_braintree_sources.rb +16 -0
  52. data/db/migrate/20160906201711_create_solidus_paypal_braintree_customers.rb +13 -0
  53. data/db/migrate/20161114231422_create_solidus_paypal_braintree_configurations.rb +11 -0
  54. data/db/migrate/20161125172005_add_braintree_configuration_to_stores.rb +7 -0
  55. data/db/migrate/20170203191030_add_credit_card_to_braintree_configuration.rb +6 -0
  56. data/db/migrate/20170505193712_add_null_constraint_to_sources.rb +38 -0
  57. data/db/migrate/20170508085402_add_not_null_constraint_to_sources_payment_type.rb +14 -0
  58. data/db/migrate/20190705115327_add_paypal_button_preferences_to_braintree_configurations.rb +5 -0
  59. data/db/migrate/20190911141712_add_3d_secure_to_braintree_configuration.rb +5 -0
  60. data/db/migrate/20211222170950_add_paypal_funding_source_to_solidus_paypal_braintree_sources.rb +5 -0
  61. data/db/migrate/20220104150301_add_venmo_to_braintree_configuration.rb +5 -0
  62. data/db/migrate/20230109080950_rename_solidus_paypal_braintree_source_type.rb +31 -0
  63. data/db/migrate/20230210104310_add_device_data_to_braintree_sources.rb +5 -0
  64. data/lib/controllers/backend/solidus_braintree/configurations_controller.rb +48 -0
  65. data/lib/generators/solidus_braintree/install/install_generator.rb +155 -19
  66. data/lib/generators/solidus_braintree/install/templates/app/assets/images/solidus_braintree/venmo/venmo_active_blue_button_280x48.svg +19 -0
  67. data/lib/generators/solidus_braintree/install/templates/app/assets/images/solidus_braintree/venmo/venmo_active_blue_button_320x48.svg +19 -0
  68. data/lib/generators/solidus_braintree/install/templates/app/assets/images/solidus_braintree/venmo/venmo_active_blue_button_375x48.svg +19 -0
  69. data/lib/generators/solidus_braintree/install/templates/app/assets/images/solidus_braintree/venmo/venmo_active_white_button_280x48.svg +19 -0
  70. data/lib/generators/solidus_braintree/install/templates/app/assets/images/solidus_braintree/venmo/venmo_active_white_button_320x48.svg +19 -0
  71. data/lib/generators/solidus_braintree/install/templates/app/assets/images/solidus_braintree/venmo/venmo_active_white_button_375x48.svg +19 -0
  72. data/lib/generators/solidus_braintree/install/templates/app/assets/images/solidus_braintree/venmo/venmo_blue_acceptance_mark.svg +15 -0
  73. data/lib/generators/solidus_braintree/install/templates/app/assets/images/solidus_braintree/venmo/venmo_blue_button_280x48.svg +19 -0
  74. data/lib/generators/solidus_braintree/install/templates/app/assets/images/solidus_braintree/venmo/venmo_blue_button_320x48.svg +19 -0
  75. data/lib/generators/solidus_braintree/install/templates/app/assets/images/solidus_braintree/venmo/venmo_blue_button_375x48.svg +19 -0
  76. data/lib/generators/solidus_braintree/install/templates/app/assets/images/solidus_braintree/venmo/venmo_blue_logo.svg +18 -0
  77. data/lib/generators/solidus_braintree/install/templates/app/assets/images/solidus_braintree/venmo/venmo_white_acceptance_mark.svg +20 -0
  78. data/lib/generators/solidus_braintree/install/templates/app/assets/images/solidus_braintree/venmo/venmo_white_button_280x48.svg +19 -0
  79. data/lib/generators/solidus_braintree/install/templates/app/assets/images/solidus_braintree/venmo/venmo_white_button_320x48.svg +19 -0
  80. data/lib/generators/solidus_braintree/install/templates/app/assets/images/solidus_braintree/venmo/venmo_white_button_375x48.svg +19 -0
  81. data/lib/generators/solidus_braintree/install/templates/app/assets/images/solidus_braintree/venmo/venmo_white_logo.svg +18 -0
  82. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/paypal_button.js +34 -0
  83. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/ajax.js +13 -0
  84. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/apple_pay_button.js +179 -0
  85. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/checkout.js +113 -0
  86. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/client.js +239 -0
  87. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/constants.js +89 -0
  88. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/frontend.js +15 -0
  89. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/hosted_form.js +48 -0
  90. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/paypal_button.js +178 -0
  91. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/paypal_messaging.js +22 -0
  92. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/promise.js +20 -0
  93. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree/venmo_button.js +86 -0
  94. data/lib/generators/solidus_braintree/install/templates/app/assets/javascripts/spree/frontend/solidus_braintree.js +1 -0
  95. data/lib/generators/solidus_braintree/install/templates/app/assets/stylesheets/spree/frontend/solidus_braintree.scss +62 -0
  96. data/lib/generators/solidus_braintree/install/templates/app/controllers/solidus_braintree/checkouts_controller.rb +31 -0
  97. data/lib/generators/solidus_braintree/install/templates/app/controllers/solidus_braintree/transactions_controller.rb +67 -0
  98. data/lib/generators/solidus_braintree/install/templates/app/helpers/solidus_braintree/braintree_checkout_helper.rb +60 -0
  99. data/lib/generators/solidus_braintree/install/templates/app/views/checkouts/existing_payment/_braintree.html.erb +2 -0
  100. data/lib/generators/solidus_braintree/install/templates/app/views/checkouts/payment/_braintree.html.erb +23 -0
  101. data/lib/generators/solidus_braintree/install/templates/app/views/payments/_braintree_payment_details.html.erb +9 -0
  102. data/lib/generators/solidus_braintree/install/templates/app/views/spree/shared/_apple_pay_button.html.erb +27 -0
  103. data/lib/generators/solidus_braintree/install/templates/app/views/spree/shared/_braintree_errors.html.erb +16 -0
  104. data/lib/generators/solidus_braintree/install/templates/app/views/spree/shared/_braintree_head_scripts.html.erb +26 -0
  105. data/lib/generators/solidus_braintree/install/templates/app/views/spree/shared/_braintree_hosted_fields.html.erb +40 -0
  106. data/lib/generators/solidus_braintree/install/templates/app/views/spree/shared/_paypal_cart_button.html.erb +38 -0
  107. data/lib/generators/solidus_braintree/install/templates/app/views/spree/shared/_paypal_checkout_button.html.erb +32 -0
  108. data/lib/generators/solidus_braintree/install/templates/app/views/spree/shared/_paypal_messaging.html.erb +13 -0
  109. data/lib/generators/solidus_braintree/install/templates/app/views/spree/shared/_venmo_button.html.erb +33 -0
  110. data/lib/generators/solidus_braintree/install/templates/config/initializers/solidus_braintree.rb +6 -0
  111. data/lib/solidus_braintree/country_mapper.rb +37 -0
  112. data/lib/solidus_braintree/engine.rb +61 -11
  113. data/lib/solidus_braintree/extension_configuration.rb +23 -0
  114. data/lib/solidus_braintree/request_protection.rb +21 -0
  115. data/lib/solidus_braintree/version.rb +3 -1
  116. data/lib/solidus_braintree.rb +14 -2
  117. data/lib/solidus_paypal_braintree.rb +6 -0
  118. data/lib/views/backend/solidus_braintree/configurations/list.html.erb +63 -0
  119. data/lib/views/backend/spree/admin/payments/source_forms/_braintree.html.erb +16 -0
  120. data/lib/views/backend/spree/admin/payments/source_views/_braintree.html.erb +39 -0
  121. data/lib/views/backend/spree/admin/shared/preference_fields/_preference_select.html.erb +13 -0
  122. data/lib/views/backend_v1.2/spree/admin/payments/source_forms/_braintree.html.erb +16 -0
  123. data/lib/views/backend_v2.4/spree/admin/shared/preference_fields/_hash.html.erb +12 -0
  124. data/solidus_braintree.gemspec +37 -38
  125. data/spec/controllers/solidus_braintree/checkouts_controller_spec.rb +99 -0
  126. data/spec/controllers/solidus_braintree/client_tokens_controller_spec.rb +55 -0
  127. data/spec/controllers/solidus_braintree/configurations_controller_spec.rb +73 -0
  128. data/spec/controllers/solidus_braintree/transactions_controller_spec.rb +183 -0
  129. data/spec/fixtures/cassettes/admin/invalid_credit_card.yml +63 -0
  130. data/spec/fixtures/cassettes/admin/resubmit_credit_card.yml +352 -0
  131. data/spec/fixtures/cassettes/admin/valid_credit_card.yml +412 -0
  132. data/spec/fixtures/cassettes/braintree/create_profile.yml +71 -0
  133. data/spec/fixtures/cassettes/braintree/generate_token.yml +63 -0
  134. data/spec/fixtures/cassettes/braintree/token.yml +63 -0
  135. data/spec/fixtures/cassettes/checkout/invalid_credit_card.yml +63 -0
  136. data/spec/fixtures/cassettes/checkout/resubmit_credit_card.yml +216 -0
  137. data/spec/fixtures/cassettes/checkout/update.yml +71 -0
  138. data/spec/fixtures/cassettes/checkout/valid_credit_card.yml +171 -0
  139. data/spec/fixtures/cassettes/checkout/valid_venmo_transaction.yml +599 -0
  140. data/spec/fixtures/cassettes/gateway/authorize/credit_card/address.yml +86 -0
  141. data/spec/fixtures/cassettes/gateway/authorize/merchant_account/EUR.yml +154 -0
  142. data/spec/fixtures/cassettes/gateway/authorize/paypal/EUR.yml +90 -0
  143. data/spec/fixtures/cassettes/gateway/authorize/paypal/address.yml +90 -0
  144. data/spec/fixtures/cassettes/gateway/authorize.yml +86 -0
  145. data/spec/fixtures/cassettes/gateway/authorized_transaction.yml +73 -0
  146. data/spec/fixtures/cassettes/gateway/cancel/missing.yml +63 -0
  147. data/spec/fixtures/cassettes/gateway/cancel/refunds.yml +272 -0
  148. data/spec/fixtures/cassettes/gateway/cancel/void.yml +201 -0
  149. data/spec/fixtures/cassettes/gateway/capture.yml +141 -0
  150. data/spec/fixtures/cassettes/gateway/complete.yml +157 -0
  151. data/spec/fixtures/cassettes/gateway/credit.yml +208 -0
  152. data/spec/fixtures/cassettes/gateway/customer.yml +79 -0
  153. data/spec/fixtures/cassettes/gateway/purchase.yml +87 -0
  154. data/spec/fixtures/cassettes/gateway/settled_transaction.yml +140 -0
  155. data/spec/fixtures/cassettes/gateway/void.yml +137 -0
  156. data/spec/fixtures/cassettes/source/bin.yml +295 -0
  157. data/spec/fixtures/cassettes/source/card_type.yml +267 -0
  158. data/spec/fixtures/cassettes/source/last4.yml +267 -0
  159. data/spec/fixtures/cassettes/transaction/import/valid/capture.yml +224 -0
  160. data/spec/fixtures/cassettes/transaction/import/valid.yml +71 -0
  161. data/spec/fixtures/views/carts/_cart_footer.html.erb +18 -0
  162. data/spec/helpers/solidus_braintree/braintree_admin_helper_spec.rb +17 -0
  163. data/spec/helpers/solidus_braintree/braintree_checkout_helper_spec.rb +70 -0
  164. data/spec/models/solidus_braintree/address_spec.rb +71 -0
  165. data/spec/models/solidus_braintree/avs_result_spec.rb +317 -0
  166. data/spec/models/solidus_braintree/gateway_spec.rb +774 -0
  167. data/spec/models/solidus_braintree/response_spec.rb +280 -0
  168. data/spec/models/solidus_braintree/source_spec.rb +555 -0
  169. data/spec/models/solidus_braintree/transaction_address_spec.rb +235 -0
  170. data/spec/models/solidus_braintree/transaction_import_spec.rb +302 -0
  171. data/spec/models/solidus_braintree/transaction_spec.rb +86 -0
  172. data/spec/models/spree/store_spec.rb +14 -0
  173. data/spec/requests/spree/api/orders_controller_spec.rb +36 -0
  174. data/spec/solidus_braintree_helper.rb +7 -0
  175. data/spec/support/solidus_braintree/capybara.rb +7 -0
  176. data/spec/support/solidus_braintree/factories.rb +55 -0
  177. data/spec/support/solidus_braintree/gateway_helpers.rb +29 -0
  178. data/spec/support/solidus_braintree/order_ready_for_payment.rb +44 -0
  179. data/spec/support/solidus_braintree/order_walkthrough.rb +87 -0
  180. data/spec/support/solidus_braintree/vcr.rb +42 -0
  181. data/spec/support/solidus_braintree/with_prepended_view_fixtures.rb +19 -0
  182. data/spec/system/backend/configuration_spec.rb +23 -0
  183. data/spec/system/backend/new_payment_spec.rb +136 -0
  184. data/spec/system/frontend/braintree_credit_card_checkout_spec.rb +199 -0
  185. data/spec/system/frontend/paypal_checkout_spec.rb +169 -0
  186. data/spec/system/frontend/venmo_checkout_spec.rb +193 -0
  187. metadata +289 -255
  188. data/.travis.yml +0 -41
  189. data/LICENSE.txt +0 -21
  190. data/app/controllers/spree/api/braintree_client_token_controller.rb +0 -13
  191. data/app/helpers/braintree_view_helpers.rb +0 -20
  192. data/app/models/concerns/solidus_braintree/add_name_validation_concern.rb +0 -8
  193. data/app/models/concerns/solidus_braintree/inject_device_data_concern.rb +0 -18
  194. data/app/models/concerns/solidus_braintree/payment_braintree_nonce_concern.rb +0 -8
  195. data/app/models/concerns/solidus_braintree/permitted_attributes_concern.rb +0 -11
  196. data/app/models/concerns/solidus_braintree/skip_require_card_numbers_concern.rb +0 -14
  197. data/app/models/concerns/solidus_braintree/use_data_field_concern.rb +0 -23
  198. data/app/models/credit_card_decorator.rb +0 -3
  199. data/app/models/payment_decorator.rb +0 -2
  200. data/app/models/permitted_attributes_decorator.rb +0 -1
  201. data/app/models/solidus/gateway/braintree_gateway.rb +0 -306
  202. data/app/overrides/spree/checkout/_confirm/braintree_security.html.erb.deface +0 -9
  203. data/app/views/spree/admin/payments/source_forms/_braintree.html.erb +0 -38
  204. data/app/views/spree/admin/payments/source_views/_braintree.html.erb +0 -30
  205. data/app/views/spree/checkout/payment/_braintree.html.erb +0 -55
  206. data/app/views/spree/checkout/payment/_braintree_initialization.html.erb +0 -12
  207. data/config/initializers/braintree.rb +0 -1
  208. data/db/migrate/20150910170527_add_data_to_credit_card.rb +0 -5
  209. data/db/migrate/20160426221931_add_braintree_device_data_to_order.rb +0 -5
  210. data/lib/assets/javascripts/spree/backend/braintree/solidus_braintree.js +0 -59
  211. data/lib/assets/javascripts/spree/frontend/braintree/solidus_braintree.js +0 -144
  212. data/lib/assets/javascripts/vendor/braintree.js +0 -8
  213. data/lib/assets/stylesheets/spree/frontend/solidus_braintree.scss +0 -26
@@ -1,24 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'solidus_core'
4
+ require 'solidus_support'
5
+
1
6
  module SolidusBraintree
2
7
  class Engine < Rails::Engine
8
+ include SolidusSupport::EngineExtensions
9
+
10
+ isolate_namespace SolidusBraintree
3
11
  engine_name 'solidus_braintree'
4
12
 
5
- config.autoload_paths += %W(#{config.root}/lib)
6
- config.assets.precompile += %w( spree/backend/braintree/solidus_braintree.js )
13
+ ActiveSupport::Inflector.inflections do |inflect|
14
+ inflect.acronym 'AVS'
15
+ end
16
+
17
+ initializer "register_solidus_braintree_gateway", after: "spree.register.payment_methods" do |app|
18
+ config.to_prepare do
19
+ app.config.spree.payment_methods << SolidusBraintree::Gateway
20
+ SolidusBraintree::Gateway.allowed_admin_form_preference_types.push(:preference_select).uniq!
7
21
 
8
- initializer "spree.gateway.payment_methods", after: "spree.register.payment_methods" do |app|
9
- app.config.spree.payment_methods << Solidus::Gateway::BraintreeGateway
22
+ ::Spree::PermittedAttributes.source_attributes.concat(
23
+ [:nonce, :payment_type, :paypal_funding_source, :device_data]
24
+ ).uniq!
25
+ end
10
26
  end
11
27
 
12
- def self.activate
13
- Rails.application.config.assets.precompile += [
14
- 'lib/assets/javascripts/spree/backend/solidus_braintree.js',
15
- ]
28
+ initializer 'add_solidus_braintree_response_to_log_entry_permitted_classes' do
29
+ Spree.config do |config|
30
+ config.log_entry_permitted_classes << 'SolidusBraintree::Response'
31
+ end
32
+ end
16
33
 
17
- Dir.glob(File.join(File.dirname(__FILE__), "../../app/**/*_decorator*.rb")) do |c|
18
- Rails.configuration.cache_classes ? require(c) : load(c)
34
+ config.assets.precompile += [
35
+ 'spree/frontend/solidus_braintree/checkout.js',
36
+ 'solidus_braintree_manifest.js'
37
+ ]
38
+ paths["app/controllers"] << "lib/controllers/frontend"
39
+ paths["app/views"] << "lib/views/frontend"
40
+
41
+ if SolidusSupport.backend_available?
42
+ config.assets.precompile += ["spree/backend/solidus_braintree.js"]
43
+ paths["app/controllers"] << "lib/controllers/backend"
44
+
45
+ # We support Solidus v1.2, which requires some different markup in the
46
+ # source form partial. This will take precedence over lib/views/backend.
47
+ paths["app/views"] << "lib/views/backend_v1.2" if Spree.solidus_gem_version < Gem::Version.new('1.3')
48
+
49
+ # Solidus v2.4 introduced preference field partials but does not ship a hash field type.
50
+ # This is solved in Solidus v2.5.
51
+ if Spree.solidus_gem_version <= Gem::Version.new('2.5.0')
52
+ paths["app/views"] << "lib/views/backend_v2.4"
53
+ end
54
+
55
+ paths["app/views"] << "lib/views/backend"
56
+
57
+ initializer "solidus_braintree_admin_menu_item", after: "register_solidus_braintree_gateway" do
58
+ Spree::Backend::Config.configure do |config|
59
+ config.menu_items << config.class::MenuItem.new(
60
+ [:braintree],
61
+ 'cc-paypal',
62
+ url: '/solidus_braintree/configurations/list',
63
+ condition: -> { can?(:list, SolidusBraintree::Configuration) }
64
+ )
65
+ end
19
66
  end
20
67
  end
21
68
 
22
- config.to_prepare &method(:activate).to_proc
69
+ # use rspec for tests
70
+ config.generators do |g|
71
+ g.test_framework :rspec
72
+ end
23
73
  end
24
74
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusBraintree
4
+ # Deviating from the usual `Configuration` name proposed by
5
+ # `solidus_dev_support` because it's already taken by a model.
6
+ class ExtensionConfiguration
7
+ # Define here the settings for this extension, e.g.:
8
+ #
9
+ # attr_accessor :my_setting
10
+ end
11
+
12
+ class << self
13
+ def configuration
14
+ @configuration ||= ExtensionConfiguration.new
15
+ end
16
+
17
+ alias config configuration
18
+
19
+ def configure
20
+ yield configuration
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_merchant/network_connection_retries'
4
+
5
+ module SolidusBraintree
6
+ module RequestProtection
7
+ include ActiveMerchant::NetworkConnectionRetries
8
+
9
+ def protected_request(&block)
10
+ raise ArgumentError unless block_given?
11
+
12
+ options = {
13
+ connection_exceptions: {
14
+ Braintree::BraintreeError => 'Error while connecting to Braintree gateway'
15
+ },
16
+ logger: Rails.logger
17
+ }
18
+ retry_exceptions(options, &block)
19
+ end
20
+ end
21
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SolidusBraintree
2
- VERSION = "1.2.0"
4
+ VERSION = '3.0.0'
3
5
  end
@@ -1,4 +1,16 @@
1
- require "solidus_core"
1
+ # frozen_string_literal: true
2
+
3
+ require 'solidus_core'
2
4
  require 'solidus_support'
3
- require "solidus_braintree/version"
5
+
6
+ require 'solidus_braintree/country_mapper'
7
+ require 'solidus_braintree/request_protection'
8
+ require 'solidus_braintree/extension_configuration'
9
+ require 'solidus_braintree/version'
4
10
  require 'solidus_braintree/engine'
11
+
12
+ module SolidusBraintree
13
+ def self.table_name_prefix
14
+ 'solidus_paypal_braintree_'
15
+ end
16
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'solidus_braintree'
4
+
5
+ SolidusPaypalBraintree =
6
+ ActiveSupport::Deprecation::DeprecatedConstantProxy.new('SolidusPaypalBraintree', 'SolidusBraintree')
@@ -0,0 +1,63 @@
1
+ <% content_for :page_title do %>
2
+ <%= t(:title, scope: 'solidus_braintree.configurations') %>
3
+ <% end %>
4
+
5
+ <%= form_for :configurations, url: solidus_braintree.configurations_path do |f| %>
6
+ <% @configurations.each do |config| %>
7
+ <div class="row">
8
+ <fieldset>
9
+ <legend><%= config.store.name %></legend>
10
+
11
+ <%= f.fields_for 'configuration_fields[]', config do |c| %>
12
+ <div class="field">
13
+ <%= c.check_box :paypal %>
14
+ <%= c.label :paypal do %>
15
+ <%= tag.i class: 'fa fa-paypal' %>
16
+ <%= c.object.class.human_attribute_name(:paypal) %>
17
+ <% end %>
18
+ </div>
19
+
20
+ <div class="field">
21
+ <%= c.check_box :apple_pay %>
22
+ <%= c.label :apple_pay do %>
23
+ <%= tag.i class: 'fa fa-apple' %>
24
+ <%= c.object.class.human_attribute_name(:apple_pay) %>
25
+ <% end %>
26
+ </div>
27
+
28
+ <div class="field">
29
+ <%= c.check_box :venmo %>
30
+ <%= c.label :venmo do %>
31
+ <%= tag.i class: 'fa fa-mobile' %>
32
+ <%= c.object.class.human_attribute_name(:venmo) %>
33
+ <% end %>
34
+ </div>
35
+
36
+ <div class="field">
37
+ <%= c.check_box :credit_card %>
38
+ <%= c.label :credit_card do %>
39
+ <%= tag.i class: 'fa fa-credit-card' %>
40
+ <%= c.object.class.human_attribute_name(:credit_card) %>
41
+ <% end %>
42
+ +
43
+ <%= c.check_box :three_d_secure %>
44
+ <%= c.label :three_d_secure do %>
45
+ <%= tag.i class: 'fa fa-shield' %>
46
+ <%= c.object.class.human_attribute_name(:three_d_secure) %>
47
+ <% end %>
48
+ </div>
49
+
50
+ <% config.admin_form_preference_names.each do |name| %>
51
+ <%= render "spree/admin/shared/preference_fields/#{config.preference_type(name)}",
52
+ form: c, attribute: "preferred_#{name}",
53
+ label: t(name, scope: 'spree', default: name.to_s.humanize) %>
54
+ <% end %>
55
+ <% end %>
56
+ </fieldset>
57
+ </div>
58
+ <% end %>
59
+
60
+ <div class="form-buttons filter-actions actions">
61
+ <%= submit_tag "Update", class: 'btn btn-primary' %>
62
+ </div>
63
+ <% end %>
@@ -0,0 +1,16 @@
1
+ <% id = payment_method.id %>
2
+
3
+ <fieldset class="no-border-bottom braintree-hosted-fields" data-braintree-hosted-fields data-id="<%= id %>" data-payment-method-id="<%= id %>">
4
+ <div class="field" data-hook="previous_cards">
5
+ <% if previous_cards.any? %>
6
+ <% previous_cards.each do |card| %>
7
+ <label><%= radio_button_tag :card, card.id, card == previous_cards.first %> <%= card.display_number %><br /></label>
8
+ <% end %>
9
+ <label><%= radio_button_tag :card, "new", false, { id: "card_new#{id}" } %> <%= I18n.t("spree.use_new_cc") %></label>
10
+ <% end %>
11
+ </div>
12
+
13
+ <div id="card_form<%= id %>" data-hook style="display: none;">
14
+ <%= render partial: "spree/shared/braintree_hosted_fields", locals: { payment_method: payment_method } %>
15
+ </div>
16
+ </fieldset>
@@ -0,0 +1,39 @@
1
+ <fieldset data-hook="credit_card">
2
+ <legend align="center"><%= SolidusBraintree::Gateway.model_name.human %></legend>
3
+
4
+ <div class="row">
5
+ <div class="alpha six columns">
6
+ <dl>
7
+ <dt><%= I18n.t("spree.identifier") %>:</dt>
8
+ <dd><%= payment.number %></dd>
9
+
10
+ <dt><%= I18n.t("spree.response_code") %>:</dt>
11
+ <dd><%= braintree_transaction_link(payment) %></dd>
12
+
13
+ <% if payment.source.token.present? %>
14
+ <dt><%= t('solidus_braintree.token') %>:</dt>
15
+ <dd><%= payment.source.token %></dd>
16
+ <% else %>
17
+ <dt><%= t('solidus_braintree.nonce') %>:</dt>
18
+ <dd><%= payment.source.nonce %></dd>
19
+ <% end %>
20
+
21
+ <dt><%= t('solidus_braintree.payment_type.label') %>:</dt>
22
+ <dd><%= payment.source.friendly_payment_type %></dd>
23
+
24
+ <% if payment.source.credit_card? %>
25
+ <dt><%= Spree::CreditCard.human_attribute_name(:card_type) %>:</dt>
26
+ <dd><%= payment.source.card_type %></dd>
27
+
28
+ <dt><%= Spree::CreditCard.human_attribute_name(:last_digits) %>:</dt>
29
+ <dd><%= payment.source.last_digits %></dd>
30
+ <% end %>
31
+
32
+ <% if payment.source.paypal? %>
33
+ <dt><%= I18n.t('spree.paypal_funding_source') %>:</dt>
34
+ <dd><%= payment.source.display_paypal_funding_source %></dd>
35
+ <% end %>
36
+ </dl>
37
+ </div>
38
+ </div>
39
+ </fieldset>
@@ -0,0 +1,13 @@
1
+ <% label = local_assigns[:label].presence %>
2
+ <% html_options = {class: 'custom-select fullwidth'}.update(local_assigns[:html_options] || {}) %>
3
+ <% options = form.object.send("#{attribute}_options") %>
4
+
5
+ <div class="field">
6
+ <% if local_assigns[:form] %>
7
+ <%= form.label attribute, label %>
8
+ <%= form.select attribute, options, {}, html_options %>
9
+ <% else %>
10
+ <%= label_tag name, label %>
11
+ <%= select_tag name, value, html_options %>
12
+ <% end %>
13
+ </div>
@@ -0,0 +1,16 @@
1
+ <% id = payment_method.id %>
2
+
3
+ <fieldset class="no-border-bottom braintree-hosted-fields" data-braintree-hosted-fields data-id="braintree" data-payment-method-id="<%= id %>">
4
+ <div class="field" data-hook="previous_cards">
5
+ <% if previous_cards.any? %>
6
+ <% previous_cards.each do |card| %>
7
+ <label><%= radio_button_tag :card, card.id, card == previous_cards.first %> <%= card.display_number %><br /></label>
8
+ <% end %>
9
+ <label><%= radio_button_tag :card, "new", false, { id: "card_new#{id}" } %> <%= I18n.t("spree.use_new_cc") %></label>
10
+ <% end %>
11
+ </div>
12
+
13
+ <div id="card_form<%= id %>" data-hook style="display: none;">
14
+ <%= render partial: "spree/shared/braintree_hosted_fields", locals: { payment_method: payment_method } %>
15
+ </div>
16
+ </fieldset>
@@ -0,0 +1,12 @@
1
+ <% label = local_assigns[:label].presence %>
2
+ <% html_options = {class: 'input_hash fullwidth'}.update(local_assigns[:html_options] || {}) %>
3
+
4
+ <div class="field">
5
+ <% if local_assigns[:form] %>
6
+ <%= form.label attribute, label %>
7
+ <%= form.text_area attribute, html_options %>
8
+ <% else %>
9
+ <%= label_tag name, label %>
10
+ <%= text_area_tag name, value, html_options %>
11
+ <% end %>
12
+ </div>
@@ -1,43 +1,42 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'solidus_braintree/version'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/solidus_braintree/version'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
- spec.name = "solidus_braintree"
8
- spec.version = SolidusBraintree::VERSION
9
- spec.authors = ["Solidus Team"]
10
- spec.email = ["contact@solidus.io"]
11
-
12
- spec.summary = %q{Adds Solidus support for Braintree v.zero Gateway.}
13
- spec.description = %q{Adds Solidus support for Braintree v.zero Gateway.}
14
- spec.homepage = "https://solidus.io"
15
- spec.license = "MIT"
16
-
17
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
- spec.bindir = "exe"
19
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
6
+ spec.name = 'solidus_braintree'
7
+ spec.version = SolidusBraintree::VERSION
8
+ spec.authors = ['Stembolt']
9
+ spec.email = 'braintree+gemfile@stembolt.com'
10
+
11
+ spec.summary = 'Officially supported Braintree extension'
12
+ spec.description = 'Uses the javascript API for seamless braintree payments'
13
+ spec.homepage = 'https://github.com/solidusio/solidus_braintree'
14
+ spec.license = 'BSD-3-Clause'
15
+
16
+ spec.metadata['homepage_uri'] = spec.homepage
17
+ spec.metadata['source_code_uri'] = 'https://github.com/solidusio/solidus_braintree'
18
+ spec.metadata['changelog_uri'] = 'https://github.com/solidusio/solidus_braintree/blob/master/CHANGELOG.md'
19
+
20
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.7', '< 4')
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ files = Dir.chdir(__dir__) { `git ls-files -z`.split("\x0") }
25
+
26
+ spec.files = files.grep_v(%r{^(test|spec|features)/})
27
+ spec.test_files = files.grep(%r{^(test|spec|features)/})
28
+ spec.bindir = "exe"
29
+ spec.executables = files.grep(%r{^exe/}) { |f| File.basename(f) }
20
30
  spec.require_paths = ["lib"]
21
31
 
22
- spec.add_dependency "solidus_api", [">= 1.0.0", "< 3"]
23
- spec.add_dependency "solidus_core", [">= 1.0.0", "< 3"]
24
- spec.add_dependency "solidus_support"
25
- spec.add_dependency "braintree", "~> 2.46"
26
-
27
- spec.add_development_dependency "bundler", "~> 1.10"
28
- spec.add_development_dependency "rake", "~> 10.0"
29
- spec.add_development_dependency 'factory_bot', '~> 4.4'
30
- spec.add_development_dependency 'rspec-rails'
31
- spec.add_development_dependency 'capybara', '~> 2.18'
32
- spec.add_development_dependency 'capybara-screenshot'
33
- spec.add_development_dependency 'poltergeist', '~> 1.9'
34
- spec.add_development_dependency 'ffaker'
35
- spec.add_development_dependency "rspec"
36
- spec.add_development_dependency "pry"
37
- spec.add_development_dependency "byebug"
38
- spec.add_development_dependency 'sqlite3'
39
- spec.add_development_dependency 'database_cleaner', '~> 1.2'
40
- spec.add_development_dependency "vcr", '~> 3.0'
41
- spec.add_development_dependency "webmock"
42
- spec.add_development_dependency 'simplecov'
32
+ spec.add_dependency 'activemerchant', '~> 1.48'
33
+ spec.add_dependency 'braintree', '~> 3.4'
34
+ spec.add_dependency 'solidus_api', ['>= 3.4.0.dev', '< 4']
35
+ spec.add_dependency 'solidus_core', ['>= 3.4.0.dev', '< 4']
36
+ spec.add_dependency 'solidus_support', ['>= 0.8.1', '< 1']
37
+
38
+ spec.add_development_dependency 'rails-controller-testing'
39
+ spec.add_development_dependency 'solidus_dev_support', '~> 2.5'
40
+
41
+ spec.post_install_message = "If you're upgrading to v2.0.0, please see the README for upgrade instructions."
43
42
  end
@@ -0,0 +1,99 @@
1
+ require 'solidus_braintree_helper'
2
+ require 'support/solidus_braintree/order_ready_for_payment'
3
+
4
+ RSpec.describe SolidusBraintree::CheckoutsController, type: :controller do
5
+ routes { SolidusBraintree::Engine.routes }
6
+
7
+ include_context 'when order is ready for payment'
8
+
9
+ describe 'PATCH update' do
10
+ subject(:patch_update) { patch :update, params: params }
11
+
12
+ let(:params) do
13
+ {
14
+ "state" => "payment",
15
+ "order" => {
16
+ "payments_attributes" => [
17
+ {
18
+ "payment_method_id" => payment_method.id,
19
+ "source_attributes" => {
20
+ "nonce" => "fake-paypal-billing-agreement-nonce",
21
+ "payment_type" => SolidusBraintree::Source::PAYPAL
22
+ }
23
+ }
24
+ ],
25
+ "use_billing" => "1",
26
+ "use_postmates_shipping" => "0"
27
+ },
28
+ "reuse_credit" => "1",
29
+ "order_bill_address" => "",
30
+ "reuse_bill_address" => "1"
31
+ }
32
+ end
33
+
34
+ let!(:payment_method) do
35
+ create_gateway
36
+ end
37
+
38
+ before do
39
+ allow(controller).to receive(:try_spree_current_user) { user }
40
+ allow(controller).to receive(:spree_current_user) { user }
41
+ allow(controller).to receive(:current_order) { order }
42
+ end
43
+
44
+ context "when a payment is created successfully", vcr: {
45
+ cassette_name: 'checkout/update',
46
+ match_requests_on: [:braintree_uri]
47
+ } do
48
+ it 'creates a payment' do
49
+ expect { patch_update }.
50
+ to change { order.payments.count }.
51
+ from(0).
52
+ to(1)
53
+ end
54
+
55
+ it 'creates a payment source' do
56
+ expect { patch_update }.
57
+ to change(SolidusBraintree::Source, :count).
58
+ from(0).
59
+ to(1)
60
+ end
61
+
62
+ it 'assigns @order' do
63
+ patch_update
64
+ expect(assigns(:order)).to eq order
65
+ end
66
+
67
+ it "is successful" do
68
+ expect(patch_update).to be_successful
69
+ end
70
+
71
+ it "renders 'ok'" do
72
+ expect(patch_update.body).to eql("ok")
73
+ end
74
+ end
75
+
76
+ context "when a payment is not created successfully" do
77
+ before do
78
+ allow_any_instance_of(::Spree::Payment).to receive(:save).and_return(false)
79
+ end
80
+
81
+ # No idea why this is the case, but I'm just adding the tests here
82
+ it "is successful" do
83
+ expect(patch_update).to be_successful
84
+ end
85
+
86
+ it "renders 'not-ok'" do
87
+ expect(patch_update.body).to eq('not-ok')
88
+ end
89
+
90
+ it "does not change the number of payments in the system" do
91
+ expect{ patch_update }.not_to(change(::Spree::Payment, :count))
92
+ end
93
+
94
+ it "does not change the number of sources in the system" do
95
+ expect{ patch_update }.not_to(change(SolidusBraintree::Source, :count))
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,55 @@
1
+ require 'solidus_braintree_helper'
2
+
3
+ RSpec.describe SolidusBraintree::ClientTokensController do
4
+ routes { SolidusBraintree::Engine.routes }
5
+
6
+ cassette_options = { cassette_name: "braintree/token" }
7
+ describe "POST create", vcr: cassette_options do
8
+ let!(:gateway) { create_gateway }
9
+ let(:user) { create(:user) }
10
+ let(:json) { JSON.parse(response.body) }
11
+
12
+ before { user.generate_spree_api_key! }
13
+
14
+ context 'without a payment method id' do
15
+ subject(:response) do
16
+ post :create, params: { token: user.spree_api_key }
17
+ end
18
+
19
+ it "returns a client token", aggregate_failures: true do
20
+ expect(response).to have_http_status(:success)
21
+ expect(response.content_type).to include 'application/json'
22
+ expect(json["client_token"]).to be_present
23
+ expect(json["client_token"]).to be_a String
24
+ expect(json["payment_method_id"]).to eq gateway.id
25
+ end
26
+
27
+ context "when there's two gateway's for different stores" do
28
+ let!(:store1) { create(:store, code: 'store_1') }
29
+ let!(:store2) { create(:store, code: 'store_2') }
30
+ let!(:gateway_for_store1) { create_gateway.tap{ |gw| store1.payment_methods << gw } }
31
+ let!(:gateway_for_store2) { create_gateway.tap{ |gw| store2.payment_methods << gw } }
32
+
33
+ it "returns the correct gateway for store1" do
34
+ allow_any_instance_of(described_class).to receive(:current_store).and_return store1
35
+ expect(json["payment_method_id"]).to eq gateway_for_store1.id
36
+ end
37
+
38
+ it "returns the correct gateway for store2" do
39
+ allow_any_instance_of(described_class).to receive(:current_store).and_return store2
40
+ expect(json["payment_method_id"]).to eq gateway_for_store2.id
41
+ end
42
+ end
43
+ end
44
+
45
+ context 'with a payment method id' do
46
+ subject(:response) do
47
+ post :create, params: { token: user.spree_api_key, payment_method_id: gateway.id }
48
+ end
49
+
50
+ it 'uses the selected gateway' do
51
+ expect(json["payment_method_id"]).to eq gateway.id
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,73 @@
1
+ require 'solidus_braintree_helper'
2
+
3
+ RSpec.describe SolidusBraintree::ConfigurationsController, type: :controller do
4
+ routes { SolidusBraintree::Engine.routes }
5
+
6
+ let!(:store_1) { create :store }
7
+ let!(:store_2) { create :store }
8
+
9
+ stub_authorization!
10
+
11
+ describe "GET #list" do
12
+ subject { get :list }
13
+
14
+ it "assigns all store's configurations as @configurations" do
15
+ subject
16
+ expect(assigns(:configurations)).
17
+ to eq [store_1.braintree_configuration, store_2.braintree_configuration]
18
+ end
19
+
20
+ it "renders the correct view" do
21
+ expect(subject).to render_template :list
22
+ end
23
+ end
24
+
25
+ describe "POST #update" do
26
+ subject { post :update, params: configurations_params }
27
+
28
+ let(:paypal_button_color) { 'blue' }
29
+ let(:configurations_params) do
30
+ {
31
+ configurations: {
32
+ configuration_fields: {
33
+ store_1.braintree_configuration.id.to_s => { paypal: true, apple_pay: true },
34
+ store_2.braintree_configuration.id.to_s => {
35
+ paypal: true,
36
+ apple_pay: false,
37
+ preferred_paypal_button_color: paypal_button_color
38
+ }
39
+ }
40
+ }
41
+ }
42
+ end
43
+
44
+ context "with valid parameters" do
45
+ it "updates the configuration" do
46
+ expect { subject }.to change { store_1.braintree_configuration.reload.paypal }.
47
+ from(false).to(true)
48
+ end
49
+
50
+ it "displays a success message to the user" do
51
+ subject
52
+ expect(flash[:success]).to eq "Successfully updated Braintree configurations."
53
+ end
54
+
55
+ it "displays all configurations" do
56
+ expect(subject).to redirect_to action: :list
57
+ end
58
+ end
59
+
60
+ context "with invalid parameters" do
61
+ let(:paypal_button_color) { 'invalid-color' }
62
+
63
+ it "displays an error message to the user" do
64
+ subject
65
+ expect(flash[:error]).to eq "An error occurred while updating Braintree configurations."
66
+ end
67
+
68
+ it "returns the user to the edit page" do
69
+ expect(subject).to redirect_to action: :list
70
+ end
71
+ end
72
+ end
73
+ end