solidus_braintree 1.4.0 → 2.0.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 (204) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +12 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github_changelog_generator +2 -0
  5. data/.gitignore +20 -11
  6. data/.rspec +1 -1
  7. data/.rubocop.yml +79 -0
  8. data/CHANGELOG.md +178 -18
  9. data/Gemfile +31 -23
  10. data/LICENSE +26 -0
  11. data/README.md +387 -26
  12. data/Rakefile +4 -19
  13. data/app/assets/config/solidus_braintree_manifest.js +1 -0
  14. data/app/assets/images/solidus_braintree/venmo/venmo_active_blue_button_280x48.svg +19 -0
  15. data/app/assets/images/solidus_braintree/venmo/venmo_active_blue_button_320x48.svg +19 -0
  16. data/app/assets/images/solidus_braintree/venmo/venmo_active_blue_button_375x48.svg +19 -0
  17. data/app/assets/images/solidus_braintree/venmo/venmo_active_white_button_280x48.svg +19 -0
  18. data/app/assets/images/solidus_braintree/venmo/venmo_active_white_button_320x48.svg +19 -0
  19. data/app/assets/images/solidus_braintree/venmo/venmo_active_white_button_375x48.svg +19 -0
  20. data/app/assets/images/solidus_braintree/venmo/venmo_blue_acceptance_mark.svg +15 -0
  21. data/app/assets/images/solidus_braintree/venmo/venmo_blue_button_280x48.svg +19 -0
  22. data/app/assets/images/solidus_braintree/venmo/venmo_blue_button_320x48.svg +19 -0
  23. data/app/assets/images/solidus_braintree/venmo/venmo_blue_button_375x48.svg +19 -0
  24. data/app/assets/images/solidus_braintree/venmo/venmo_blue_logo.svg +18 -0
  25. data/app/assets/images/solidus_braintree/venmo/venmo_white_acceptance_mark.svg +20 -0
  26. data/app/assets/images/solidus_braintree/venmo/venmo_white_button_280x48.svg +19 -0
  27. data/app/assets/images/solidus_braintree/venmo/venmo_white_button_320x48.svg +19 -0
  28. data/app/assets/images/solidus_braintree/venmo/venmo_white_button_375x48.svg +19 -0
  29. data/app/assets/images/solidus_braintree/venmo/venmo_white_logo.svg +18 -0
  30. data/app/assets/javascripts/solidus_braintree/apple_pay_button.js +179 -0
  31. data/app/assets/javascripts/solidus_braintree/checkout.js +108 -0
  32. data/app/assets/javascripts/solidus_braintree/client.js +239 -0
  33. data/app/assets/javascripts/solidus_braintree/constants.js +89 -0
  34. data/app/assets/javascripts/solidus_braintree/frontend.js +14 -0
  35. data/app/assets/javascripts/solidus_braintree/hosted_form.js +46 -0
  36. data/app/assets/javascripts/solidus_braintree/paypal_button.js +178 -0
  37. data/app/assets/javascripts/solidus_braintree/paypal_messaging.js +22 -0
  38. data/app/assets/javascripts/solidus_braintree/promise.js +20 -0
  39. data/app/assets/javascripts/solidus_braintree/venmo_button.js +86 -0
  40. data/app/assets/javascripts/spree/backend/solidus_braintree.js +96 -0
  41. data/app/assets/javascripts/spree/frontend/paypal_button.js +34 -0
  42. data/app/assets/javascripts/spree/frontend/solidus_braintree.js +1 -0
  43. data/app/assets/stylesheets/spree/backend/solidus_braintree.scss +28 -0
  44. data/app/assets/stylesheets/spree/frontend/solidus_braintree.scss +51 -0
  45. data/app/decorators/controllers/solidus_braintree/admin_payments_controller_decorator.rb +11 -0
  46. data/app/decorators/controllers/solidus_braintree/checkout_controller_decorator.rb +11 -0
  47. data/app/decorators/controllers/solidus_braintree/client_tokens_controller.rb +41 -0
  48. data/app/decorators/controllers/solidus_braintree/orders_controller_decorator.rb +11 -0
  49. data/app/decorators/models/solidus_braintree/spree/store_decorator.rb +20 -0
  50. data/app/decorators/models/solidus_braintree/spree/user_decorator.rb +13 -0
  51. data/app/helpers/solidus_braintree/braintree_admin_helper.rb +23 -0
  52. data/app/helpers/solidus_braintree/braintree_checkout_helper.rb +60 -0
  53. data/app/models/application_record.rb +5 -0
  54. data/app/models/solidus_braintree/address.rb +64 -0
  55. data/app/models/solidus_braintree/avs_result.rb +69 -0
  56. data/app/models/solidus_braintree/configuration.rb +39 -0
  57. data/app/models/solidus_braintree/customer.rb +8 -0
  58. data/app/models/solidus_braintree/gateway.rb +433 -0
  59. data/app/models/solidus_braintree/response.rb +80 -0
  60. data/app/models/solidus_braintree/source.rb +135 -0
  61. data/app/models/solidus_braintree/transaction.rb +31 -0
  62. data/app/models/solidus_braintree/transaction_address.rb +88 -0
  63. data/app/models/solidus_braintree/transaction_import.rb +98 -0
  64. data/app/overrides/spree/payments/payment/add_paypal_funding_source_to_payment.rb +9 -0
  65. data/app/views/spree/api/payments/source_views/_braintree.json.jbuilder +1 -1
  66. data/app/views/spree/checkout/existing_payment/_braintree.html.erb +10 -0
  67. data/app/views/spree/shared/_apple_pay_button.html.erb +27 -0
  68. data/app/views/spree/shared/_braintree_errors.html.erb +16 -0
  69. data/app/views/spree/shared/_braintree_head_scripts.html.erb +26 -0
  70. data/app/views/spree/shared/_braintree_hosted_fields.html.erb +43 -0
  71. data/app/views/spree/shared/_paypal_cart_button.html.erb +38 -0
  72. data/app/views/spree/shared/_paypal_messaging.html.erb +13 -0
  73. data/app/views/spree/shared/_venmo_button.html.erb +33 -0
  74. data/bin/console +4 -1
  75. data/bin/rails +5 -5
  76. data/bin/rails-engine +13 -0
  77. data/bin/rails-sandbox +16 -0
  78. data/bin/rake +7 -0
  79. data/bin/sandbox +103 -0
  80. data/bin/setup +5 -4
  81. data/config/locales/en.yml +94 -2
  82. data/config/locales/it.yml +56 -0
  83. data/config/routes.rb +12 -3
  84. data/db/migrate/20160830061749_create_solidus_paypal_braintree_sources.rb +16 -0
  85. data/db/migrate/20160906201711_create_solidus_paypal_braintree_customers.rb +13 -0
  86. data/db/migrate/20161114231422_create_solidus_paypal_braintree_configurations.rb +11 -0
  87. data/db/migrate/20161125172005_add_braintree_configuration_to_stores.rb +7 -0
  88. data/db/migrate/20170203191030_add_credit_card_to_braintree_configuration.rb +6 -0
  89. data/db/migrate/20170505193712_add_null_constraint_to_sources.rb +38 -0
  90. data/db/migrate/20170508085402_add_not_null_constraint_to_sources_payment_type.rb +14 -0
  91. data/db/migrate/20190705115327_add_paypal_button_preferences_to_braintree_configurations.rb +5 -0
  92. data/db/migrate/20190911141712_add_3d_secure_to_braintree_configuration.rb +5 -0
  93. data/db/migrate/20211222170950_add_paypal_funding_source_to_solidus_paypal_braintree_sources.rb +5 -0
  94. data/db/migrate/20220104150301_add_venmo_to_braintree_configuration.rb +5 -0
  95. data/db/migrate/20230109080950_rename_solidus_paypal_braintree_source_type.rb +31 -0
  96. data/lib/controllers/backend/solidus_braintree/configurations_controller.rb +48 -0
  97. data/lib/controllers/frontend/solidus_braintree/checkouts_controller.rb +31 -0
  98. data/lib/controllers/frontend/solidus_braintree/transactions_controller.rb +67 -0
  99. data/lib/generators/solidus_braintree/install/install_generator.rb +54 -18
  100. data/lib/generators/solidus_braintree/install/templates/initializer.rb +6 -0
  101. data/lib/solidus_braintree/country_mapper.rb +37 -0
  102. data/lib/solidus_braintree/engine.rb +55 -10
  103. data/lib/solidus_braintree/extension_configuration.rb +23 -0
  104. data/lib/solidus_braintree/request_protection.rb +21 -0
  105. data/lib/solidus_braintree/testing_support/factories.rb +53 -0
  106. data/lib/solidus_braintree/version.rb +3 -1
  107. data/lib/solidus_braintree.rb +14 -2
  108. data/lib/solidus_paypal_braintree.rb +6 -0
  109. data/lib/views/backend/solidus_braintree/configurations/list.html.erb +63 -0
  110. data/lib/views/backend/spree/admin/payments/source_forms/_braintree.html.erb +16 -0
  111. data/lib/views/backend/spree/admin/payments/source_views/_braintree.html.erb +39 -0
  112. data/lib/views/backend/spree/admin/shared/preference_fields/_preference_select.html.erb +13 -0
  113. data/lib/views/backend_v1.2/spree/admin/payments/source_forms/_braintree.html.erb +16 -0
  114. data/lib/views/backend_v2.4/spree/admin/shared/preference_fields/_hash.html.erb +12 -0
  115. data/lib/views/frontend/solidus_braintree/payments/_payment.html.erb +12 -0
  116. data/lib/views/frontend/spree/checkout/payment/_braintree.html.erb +23 -0
  117. data/lib/views/frontend/spree/shared/_paypal_checkout_button.html.erb +32 -0
  118. data/solidus_braintree.gemspec +39 -38
  119. data/spec/controllers/solidus_braintree/checkouts_controller_spec.rb +99 -0
  120. data/spec/controllers/solidus_braintree/client_tokens_controller_spec.rb +55 -0
  121. data/spec/controllers/solidus_braintree/configurations_controller_spec.rb +73 -0
  122. data/spec/controllers/solidus_braintree/transactions_controller_spec.rb +183 -0
  123. data/spec/features/backend/configuration_spec.rb +23 -0
  124. data/spec/features/backend/new_payment_spec.rb +137 -0
  125. data/spec/features/frontend/braintree_credit_card_checkout_spec.rb +191 -0
  126. data/spec/features/frontend/paypal_checkout_spec.rb +166 -0
  127. data/spec/features/frontend/venmo_checkout_spec.rb +194 -0
  128. data/spec/fixtures/cassettes/admin/invalid_credit_card.yml +63 -0
  129. data/spec/fixtures/cassettes/admin/resubmit_credit_card.yml +352 -0
  130. data/spec/fixtures/cassettes/admin/valid_credit_card.yml +412 -0
  131. data/spec/fixtures/cassettes/braintree/create_profile.yml +71 -0
  132. data/spec/fixtures/cassettes/braintree/generate_token.yml +63 -0
  133. data/spec/fixtures/cassettes/braintree/token.yml +63 -0
  134. data/spec/fixtures/cassettes/checkout/invalid_credit_card.yml +63 -0
  135. data/spec/fixtures/cassettes/checkout/resubmit_credit_card.yml +216 -0
  136. data/spec/fixtures/cassettes/checkout/update.yml +71 -0
  137. data/spec/fixtures/cassettes/checkout/valid_credit_card.yml +171 -0
  138. data/spec/fixtures/cassettes/checkout/valid_venmo_transaction.yml +599 -0
  139. data/spec/fixtures/cassettes/gateway/authorize/credit_card/address.yml +86 -0
  140. data/spec/fixtures/cassettes/gateway/authorize/merchant_account/EUR.yml +154 -0
  141. data/spec/fixtures/cassettes/gateway/authorize/paypal/EUR.yml +90 -0
  142. data/spec/fixtures/cassettes/gateway/authorize/paypal/address.yml +90 -0
  143. data/spec/fixtures/cassettes/gateway/authorize.yml +86 -0
  144. data/spec/fixtures/cassettes/gateway/authorized_transaction.yml +73 -0
  145. data/spec/fixtures/cassettes/gateway/cancel/missing.yml +63 -0
  146. data/spec/fixtures/cassettes/gateway/cancel/refunds.yml +272 -0
  147. data/spec/fixtures/cassettes/gateway/cancel/void.yml +201 -0
  148. data/spec/fixtures/cassettes/gateway/capture.yml +141 -0
  149. data/spec/fixtures/cassettes/gateway/complete.yml +157 -0
  150. data/spec/fixtures/cassettes/gateway/credit.yml +208 -0
  151. data/spec/fixtures/cassettes/gateway/customer.yml +79 -0
  152. data/spec/fixtures/cassettes/gateway/purchase.yml +87 -0
  153. data/spec/fixtures/cassettes/gateway/settled_transaction.yml +140 -0
  154. data/spec/fixtures/cassettes/gateway/void.yml +137 -0
  155. data/spec/fixtures/cassettes/source/bin.yml +295 -0
  156. data/spec/fixtures/cassettes/source/card_type.yml +267 -0
  157. data/spec/fixtures/cassettes/source/last4.yml +267 -0
  158. data/spec/fixtures/cassettes/transaction/import/valid/capture.yml +224 -0
  159. data/spec/fixtures/cassettes/transaction/import/valid.yml +71 -0
  160. data/spec/fixtures/views/spree/orders/edit.html.erb +50 -0
  161. data/spec/helpers/solidus_braintree/braintree_admin_helper_spec.rb +17 -0
  162. data/spec/helpers/solidus_braintree/braintree_checkout_helper_spec.rb +70 -0
  163. data/spec/models/solidus_braintree/address_spec.rb +71 -0
  164. data/spec/models/solidus_braintree/avs_result_spec.rb +317 -0
  165. data/spec/models/solidus_braintree/gateway_spec.rb +742 -0
  166. data/spec/models/solidus_braintree/response_spec.rb +280 -0
  167. data/spec/models/solidus_braintree/source_spec.rb +539 -0
  168. data/spec/models/solidus_braintree/transaction_address_spec.rb +235 -0
  169. data/spec/models/solidus_braintree/transaction_import_spec.rb +302 -0
  170. data/spec/models/solidus_braintree/transaction_spec.rb +86 -0
  171. data/spec/models/spree/store_spec.rb +14 -0
  172. data/spec/requests/spree/api/orders_controller_spec.rb +36 -0
  173. data/spec/spec_helper.rb +32 -0
  174. data/spec/support/capybara.rb +7 -0
  175. data/spec/support/gateway_helpers.rb +29 -0
  176. data/spec/support/order_ready_for_payment.rb +37 -0
  177. data/spec/support/vcr.rb +42 -0
  178. data/spec/support/views.rb +1 -0
  179. metadata +276 -224
  180. data/LICENSE.txt +0 -21
  181. data/app/controllers/spree/api/braintree_client_token_controller.rb +0 -13
  182. data/app/decorators/lib/solidus_braintree/spree/permitted_attributes_decorator.rb +0 -9
  183. data/app/decorators/models/solidus_braintree/spree/credit_card_decorator.rb +0 -11
  184. data/app/decorators/models/solidus_braintree/spree/payment_decorator.rb +0 -10
  185. data/app/helpers/braintree_view_helpers.rb +0 -20
  186. data/app/models/concerns/solidus_braintree/add_name_validation_concern.rb +0 -8
  187. data/app/models/concerns/solidus_braintree/inject_device_data_concern.rb +0 -18
  188. data/app/models/concerns/solidus_braintree/payment_braintree_nonce_concern.rb +0 -8
  189. data/app/models/concerns/solidus_braintree/permitted_attributes_concern.rb +0 -11
  190. data/app/models/concerns/solidus_braintree/skip_require_card_numbers_concern.rb +0 -14
  191. data/app/models/concerns/solidus_braintree/use_data_field_concern.rb +0 -23
  192. data/app/models/solidus/gateway/braintree_gateway.rb +0 -306
  193. data/app/overrides/spree/checkout/_confirm/braintree_security.html.erb.deface +0 -9
  194. data/app/views/spree/admin/payments/source_forms/_braintree.html.erb +0 -38
  195. data/app/views/spree/admin/payments/source_views/_braintree.html.erb +0 -30
  196. data/app/views/spree/checkout/payment/_braintree.html.erb +0 -55
  197. data/app/views/spree/checkout/payment/_braintree_initialization.html.erb +0 -12
  198. data/config/initializers/braintree.rb +0 -3
  199. data/db/migrate/20150910170527_add_data_to_credit_card.rb +0 -5
  200. data/db/migrate/20160426221931_add_braintree_device_data_to_order.rb +0 -5
  201. data/lib/assets/javascripts/spree/backend/braintree/solidus_braintree.js +0 -59
  202. data/lib/assets/javascripts/spree/frontend/braintree/solidus_braintree.js +0 -144
  203. data/lib/assets/javascripts/vendor/braintree.js +0 -8
  204. data/lib/assets/stylesheets/spree/frontend/solidus_braintree.scss +0 -26
@@ -1,24 +1,69 @@
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
7
16
 
8
- initializer "spree.gateway.payment_methods", after: "spree.register.payment_methods" do |app|
9
- app.config.spree.payment_methods << 'Solidus::Gateway::BraintreeGateway'
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!
21
+ ::Spree::PermittedAttributes.source_attributes.concat([:nonce, :payment_type, :paypal_funding_source]).uniq!
22
+ end
10
23
  end
11
24
 
12
- def self.activate
13
- Rails.application.config.assets.precompile += [
14
- 'lib/assets/javascripts/spree/backend/solidus_braintree.js',
25
+ if SolidusSupport.frontend_available?
26
+ config.assets.precompile += [
27
+ 'solidus_braintree/checkout.js',
28
+ 'solidus_braintree/frontend.js',
29
+ 'spree/frontend/apple_pay_button.js',
30
+ 'solidus_braintree_manifest.js'
15
31
  ]
32
+ paths["app/controllers"] << "lib/controllers/frontend"
33
+ paths["app/views"] << "lib/views/frontend"
34
+ end
16
35
 
17
- Dir.glob(File.join(File.dirname(__FILE__), "../../app/**/*_decorator*.rb")) do |c|
18
- Rails.configuration.cache_classes ? require(c) : load(c)
36
+ if SolidusSupport.backend_available?
37
+ config.assets.precompile += ["spree/backend/solidus_braintree.js"]
38
+ paths["app/controllers"] << "lib/controllers/backend"
39
+
40
+ # We support Solidus v1.2, which requires some different markup in the
41
+ # source form partial. This will take precedence over lib/views/backend.
42
+ paths["app/views"] << "lib/views/backend_v1.2" if Spree.solidus_gem_version < Gem::Version.new('1.3')
43
+
44
+ # Solidus v2.4 introduced preference field partials but does not ship a hash field type.
45
+ # This is solved in Solidus v2.5.
46
+ if Spree.solidus_gem_version <= Gem::Version.new('2.5.0')
47
+ paths["app/views"] << "lib/views/backend_v2.4"
48
+ end
49
+
50
+ paths["app/views"] << "lib/views/backend"
51
+
52
+ initializer "solidus_braintree_admin_menu_item", after: "register_solidus_braintree_gateway" do
53
+ Spree::Backend::Config.configure do |config|
54
+ config.menu_items << config.class::MenuItem.new(
55
+ [:braintree],
56
+ 'cc-paypal',
57
+ url: '/solidus_braintree/configurations/list',
58
+ condition: -> { can?(:list, SolidusBraintree::Configuration) }
59
+ )
60
+ end
19
61
  end
20
62
  end
21
63
 
22
- config.to_prepare &method(:activate).to_proc
64
+ # use rspec for tests
65
+ config.generators do |g|
66
+ g.test_framework :rspec
67
+ end
23
68
  end
24
69
  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
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ FactoryBot.define do
4
+ # Define your Spree extensions Factories within this file to enable applications,
5
+ # and other extensions to use and override them.
6
+ #
7
+ # Example adding this to your spec_helper will load these Factories for use:
8
+ # require 'solidus_braintree/factories'
9
+
10
+ factory :solidus_braintree_payment_method, class: SolidusBraintree::Gateway do
11
+ name { 'Solidus Braintree Gateway' }
12
+ active { true }
13
+ end
14
+
15
+ factory :solidus_braintree_source, class: SolidusBraintree::Source do
16
+ association(:payment_method, factory: :solidus_braintree_payment_method)
17
+ user
18
+
19
+ trait :credit_card do
20
+ payment_type { SolidusBraintree::Source::CREDIT_CARD }
21
+ end
22
+
23
+ trait :paypal do
24
+ payment_type { SolidusBraintree::Source::PAYPAL }
25
+ end
26
+
27
+ trait :apple_pay do
28
+ payment_type { SolidusBraintree::Source::APPLE_PAY }
29
+ end
30
+ end
31
+ end
32
+
33
+ FactoryBot.modify do
34
+ # The Solidus address factory randomizes the zipcode.
35
+ # The OrderWalkThrough we use in the credit card checkout spec uses this factory for the user addresses.
36
+ # For credit card payments we transmit the billing address to braintree, for paypal payments the shipping address.
37
+ # As we match the body in our VCR settings VCR can not match the request anymore and therefore cannot replay existing
38
+ # cassettes.
39
+ #
40
+
41
+ factory :address do
42
+ zipcode { '21088-0255' }
43
+
44
+ if SolidusSupport.combined_first_and_last_name_in_address?
45
+ transient do
46
+ firstname { "John" }
47
+ lastname { "Doe" }
48
+ end
49
+
50
+ name { "#{firstname} #{lastname}" }
51
+ end
52
+ end
53
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SolidusBraintree
2
- VERSION = "1.4.0"
4
+ VERSION = '2.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>
@@ -0,0 +1,12 @@
1
+ <br />
2
+ <%= payment.source.try(:display_payment_type) %>
3
+
4
+ <% if payment.source.try(:paypal?) %>
5
+ <% if payment.source.respond_to?(:paypal_funding_source) && payment.source.paypal_funding_source.present? %>
6
+ <br />
7
+ <%= t('spree.paypal_funding', funding: payment.source.display_paypal_funding_source) %>
8
+ <% end %>
9
+ <% elsif payment.source.try(:venmo?) %>
10
+ <br />
11
+ <%= payment.source.source_description %>
12
+ <% end %>
@@ -0,0 +1,23 @@
1
+ <% id = payment_method.id %>
2
+
3
+ <%= render "spree/shared/braintree_head_scripts" %>
4
+
5
+ <% if current_store.braintree_configuration.paypal? %>
6
+ <%= render "spree/shared/paypal_checkout_button" %>
7
+ <% end %>
8
+
9
+ <% if current_store.braintree_configuration.credit_card? %>
10
+ <fieldset class="braintree-hosted-fields" data-braintree-hosted-fields data-id="<%= id %>">
11
+ <%= render "spree/shared/braintree_hosted_fields", payment_method: payment_method %>
12
+ </fieldset>
13
+ <% end %>
14
+
15
+ <% if current_store.braintree_configuration.apple_pay? %>
16
+ <%= render "spree/shared/apple_pay_button", id: id %>
17
+ <% end %>
18
+
19
+ <% if current_store.braintree_configuration.venmo? %>
20
+ <%= render "spree/shared/venmo_button", payment_method: payment_method %>
21
+ <% end %>
22
+
23
+ <%= render "spree/shared/braintree_errors" %>
@@ -0,0 +1,32 @@
1
+ <div id="paypal-button"></div>
2
+ <div data-pp-message data-pp-placement="payment" data-pp-amount="<%= @order.total %>"></div>
3
+
4
+ <script>
5
+ var address = <%= sanitize SolidusBraintree::Address.new(current_order.ship_address).to_json %>
6
+
7
+ var paypalOptions = {
8
+ flow: '<%= SolidusBraintree::Gateway.first.preferred_paypal_flow %>',
9
+ amount: '<%= current_order.total %>',
10
+ currency: '<%= current_order.currency %>',
11
+ enableShippingAddress: true,
12
+ venmoFunding: <%= SolidusBraintree::Gateway.first.preferred_enable_venmo_funding %>,
13
+ buyerCountry: '<%= SolidusBraintree::Gateway.first.preferred_force_buyer_country %>',
14
+ shippingAddressOverride: address,
15
+ shippingAddressEditable: false,
16
+ environment: '<%= Rails.env.production? ? "production" : "sandbox" %>',
17
+ locale: '<%= paypal_button_preference(:paypal_button_locale, store: current_store) %>',
18
+ style: {
19
+ color: '<%= paypal_button_preference(:paypal_button_color, store: current_store) %>',
20
+ shape: '<%= paypal_button_preference(:paypal_button_shape, store: current_store) %>',
21
+ label: '<%= paypal_button_preference(:paypal_button_label, store: current_store) %>',
22
+ layout: '<%= paypal_button_preference(:paypal_button_layout, store: current_store) %>',
23
+ <% if paypal_button_preference(:paypal_button_layout, store: current_store) == "horizontal" %>
24
+ tagline: '<%= paypal_button_preference(:paypal_button_tagline, store: current_store) %>',
25
+ <% end %>
26
+ messaging: '<%= paypal_button_preference(:paypal_button_messaging, store: current_store) %>'
27
+ }
28
+ }
29
+
30
+ var button = new SolidusBraintree.createPaypalButton(document.querySelector("#paypal-button"), paypalOptions);
31
+ button.initialize();
32
+ </script>
@@ -1,43 +1,44 @@
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.5', '< 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", "< 4"]
23
- spec.add_dependency "solidus_core", [">= 1.0.0", "< 4"]
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 'webdrivers'
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', ['>= 2.4.0', '< 4']
35
+ spec.add_dependency 'solidus_core', ['>= 2.4.0', '< 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
+ spec.add_development_dependency 'vcr'
41
+ spec.add_development_dependency 'webmock'
42
+
43
+ spec.post_install_message = "If you're upgrading to v2.0.0, please see the README for upgrade instructions."
43
44
  end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+ require 'support/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