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
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model'
4
+ require 'solidus_braintree/country_mapper'
5
+
6
+ module SolidusBraintree
7
+ class TransactionAddress
8
+ include ActiveModel::Model
9
+ include ActiveModel::Validations::Callbacks
10
+ include SolidusBraintree::CountryMapper
11
+
12
+ attr_accessor :country_code, :name, :city, :zip, :state_code,
13
+ :address_line_1, :address_line_2, :first_name, :last_name
14
+
15
+ validates :address_line_1, :city, :zip, :country_code, presence: true
16
+ validates :name, presence: true, unless: ->(address){ address.first_name.present? }
17
+
18
+ before_validation do
19
+ self.country_code = country_code.presence || "us"
20
+ end
21
+
22
+ validates :spree_country, presence: true
23
+ validates :state_code, :spree_state, presence: true, if: :should_match_state_model?
24
+
25
+ def initialize(attributes = {})
26
+ country_name = attributes.delete(:country_name) || ""
27
+ if attributes[:country_code].blank?
28
+ attributes[:country_code] = iso_from_name(country_name)
29
+ end
30
+
31
+ super(attributes)
32
+ end
33
+
34
+ def spree_country
35
+ country_code && (@country ||= ::Spree::Country.find_by(iso: country_code.upcase))
36
+ end
37
+
38
+ def spree_state
39
+ spree_country && state_code && ( @state ||= spree_country.states.find_by(
40
+ ::Spree::State.arel_table[:name].matches(state_code).or(
41
+ ::Spree::State.arel_table[:abbr].matches(state_code)
42
+ )
43
+ ))
44
+ end
45
+
46
+ def to_spree_address
47
+ address = ::Spree::Address.new(
48
+ city: city,
49
+ country: spree_country,
50
+ address1: address_line_1,
51
+ address2: address_line_2,
52
+ zipcode: zip
53
+ )
54
+
55
+ if SolidusSupport.combined_first_and_last_name_in_address?
56
+ address.name = begin
57
+ if first_name.nil?
58
+ name
59
+ else
60
+ [first_name, last_name].join(" ")
61
+ end
62
+ end
63
+ else
64
+ ::Spree::Deprecation.warn("first_name and last_name are deprecated. Use name instead.", caller)
65
+ if first_name.nil?
66
+ first, last = SolidusBraintree::Address.split_name(name)
67
+ address.firstname = first
68
+ address.lastname = last || "(left blank)"
69
+ else
70
+ address.firstname = first_name
71
+ address.lastname = last_name || "(left blank)"
72
+ end
73
+ end
74
+
75
+ if spree_state
76
+ address.state = spree_state
77
+ else
78
+ address.state_name = state_code
79
+ end
80
+ address
81
+ end
82
+
83
+ # Check to see if this address should match to a state model in the database
84
+ def should_match_state_model?
85
+ spree_country&.states_required?
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_model'
4
+
5
+ module SolidusBraintree
6
+ class TransactionImport
7
+ class InvalidImportError < StandardError; end
8
+
9
+ include ActiveModel::Model
10
+
11
+ validate do
12
+ errors.add("Address", "is invalid") if address&.invalid?
13
+
14
+ if transaction.invalid?
15
+ transaction.errors.each do |error|
16
+ errors.add(error.attribute, error.message)
17
+ end
18
+ end
19
+ errors.none?
20
+ end
21
+
22
+ attr_reader :transaction, :order
23
+
24
+ def initialize(order, transaction)
25
+ @order = order
26
+ @transaction = transaction
27
+ end
28
+
29
+ def source
30
+ SolidusBraintree::Source.new(
31
+ nonce: transaction.nonce,
32
+ payment_type: transaction.payment_type,
33
+ payment_method: transaction.payment_method,
34
+ paypal_funding_source: transaction.paypal_funding_source,
35
+ user: user
36
+ )
37
+ end
38
+
39
+ delegate :user, to: :order
40
+
41
+ def import!(end_state, restart_checkout: false)
42
+ if valid?
43
+ order.email = user&.email || transaction.email
44
+
45
+ if address
46
+ order.shipping_address = order.billing_address = address
47
+ # work around a bug in most solidus versions
48
+ # about tax zone cachine between address changes
49
+ order.instance_variable_set(:@tax_zone, nil)
50
+ end
51
+
52
+ payment = order.payments.new(
53
+ source: source,
54
+ payment_method: transaction.payment_method,
55
+ amount: order.total
56
+ )
57
+
58
+ order.save!
59
+ order.restart_checkout_flow if restart_checkout
60
+ advance_order(payment, end_state)
61
+ else
62
+ raise InvalidImportError,
63
+ "Validation failed: #{errors.full_messages.join(', ')}"
64
+ end
65
+ end
66
+
67
+ def address
68
+ transaction.address && transaction.address.to_spree_address.tap do |address|
69
+ address.phone = transaction.phone
70
+ end
71
+ end
72
+
73
+ def state_before_current?(state)
74
+ steps = order.checkout_steps
75
+ steps.index(state) < (steps.index(order.state) || 0)
76
+ end
77
+
78
+ protected
79
+
80
+ def advance_order(payment, end_state)
81
+ return if state_before_current?(end_state)
82
+
83
+ until order.state == end_state
84
+ order.next!
85
+ update_payment_total(payment) if order.payment?
86
+ end
87
+ end
88
+
89
+ def update_payment_total(payment)
90
+ payment_total = order.payments.where(state: %w[checkout pending]).sum(:amount)
91
+ payment_difference = order.outstanding_balance - payment_total
92
+
93
+ return unless payment_difference != 0
94
+
95
+ payment.update!(amount: payment.amount + payment_difference)
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ Deface::Override.new(
4
+ name: "payments/payment/add_paypal_funding_source_to_payment",
5
+ virtual_path: "spree/payments/_payment",
6
+ original: "0b5b5ae53626059cb3a202ef95d10827dd399925",
7
+ insert_after: "erb[loud]:contains('content_tag(:span, payment.payment_method.name)')",
8
+ partial: "solidus_braintree/payments/payment"
9
+ )
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- json.call(payment_source, :id, :created_at)
3
+ json.call(payment_source, :id, :token, :created_at)
@@ -0,0 +1,10 @@
1
+ <tr id="<%= dom_id(wallet_payment_source, 'spree')%>" class="<%= cycle('even', 'odd') %>">
2
+ <td>
3
+ <%= radio_button_tag "order[wallet_payment_source_id]",
4
+ wallet_payment_source.id,
5
+ default,
6
+ class: "existing-cc-radio" %>
7
+ </td>
8
+ <td><%= wallet_payment_source.payment_source.friendly_payment_type %></td>
9
+ <td><%= wallet_payment_source.payment_source.display_number %></td>
10
+ </tr>
@@ -0,0 +1,27 @@
1
+ <% address = current_order.ship_address %>
2
+
3
+ <button id="apple-pay-button" class="apple-pay-button"></button>
4
+
5
+ <script>
6
+ var applePayButtonElement = document.getElementById('apple-pay-button');
7
+ var applePayOptions = {
8
+ paymentMethodId: <%= id %>,
9
+ storeName: "<%= current_store.name %>",
10
+ orderEmail: "<%= current_order.email %>",
11
+ amount: "<%= current_order.total %>",
12
+ shippingContact: {
13
+ emailAddress: '<%= current_order.email %>',
14
+ givenName: '<%= address.firstname %>',
15
+ familyName: '<%= address.lastname %>',
16
+ phoneNumber: '<%= address.phone %>',
17
+ addressLines: ['<%= address.address1 %>','<%= address.address2 %>'],
18
+ locality: '<%= address.city %>',
19
+ administrativeArea: '<%= address.state.name %>',
20
+ postalCode: '<%= address.zipcode %>',
21
+ country: '<%= address.country.name %>',
22
+ countryCode: '<%= address.country.iso %>'
23
+ }
24
+ };
25
+ var button = new SolidusBraintree.createApplePayButton(applePayButtonElement, applePayOptions);
26
+ button.initialize();
27
+ </script>
@@ -0,0 +1,16 @@
1
+ <script type="text/javascript">
2
+ BraintreeError.DEFAULT = "<%= I18n.t('solidus_braintree.errors.default_error')%>"
3
+ BraintreeError.PAYPAL_POPUP_CLOSED = "<%= I18n.t('solidus_braintree.errors.paypal_popup_closed') %>"
4
+ BraintreeError.HOSTED_FIELDS_FIELDS_EMPTY = "<%= I18n.t('solidus_braintree.errors.empty_fields')%>"
5
+ BraintreeError.HOSTED_FIELDS_FIELDS_INVALID = "<%= I18n.t('solidus_braintree.errors.invalid_fields')%>"
6
+ BraintreeError.HOSTED_FIELDS_FAILED_TOKENIZATION = "<%= I18n.t('solidus_braintree.errors.invalid_card')%>"
7
+ BraintreeError.HOSTED_FIELDS_TOKENIZATION_NETWORK_ERROR = "<%= I18n.t('solidus_braintree.errors.network_error')%>"
8
+ BraintreeError.HOSTED_FIELDS_FIELD_DUPLICATE_IFRAME = "<%= I18n.t('solidus_braintree.errors.duplicate_iframe')%>"
9
+ BraintreeError.HOSTED_FIELDS_TOKENIZATION_FAIL_ON_DUPLICATE = "<%= I18n.t('solidus_braintree.errors.fail_on_duplicate')%>"
10
+ BraintreeError.HOSTED_FIELDS_TOKENIZATION_CVV_VERIFICATION_FAILED = "<%= I18n.t('solidus_braintree.errors.cvv_verification_failed')%>"
11
+ BraintreeError.THREEDS_AUTHENTICATION_FAILED = "<%= t('solidus_braintree.errors.threeds.authentication_failed') %>";
12
+ BraintreeError.THREEDS_CARDINAL_SDK_ERROR = "<%= t('solidus_braintree.errors.threeds.authentication_failed') %>";
13
+ BraintreeError.VENMO_CANCELED = "<%= t('solidus_braintree.errors.venmo.canceled') %>";
14
+ BraintreeError.VENMO_DESKTOP_CANCELED = "<%= t('solidus_braintree.errors.venmo.desktop_canceled') %>";
15
+ BraintreeError.VENMO_APP_CANCELED = "<%= t('solidus_braintree.errors.venmo.app_canceled') %>";
16
+ </script>
@@ -0,0 +1,26 @@
1
+ <% content_for :head do %>
2
+ <script src="https://js.braintreegateway.com/web/3.84.0/js/client.min.js"></script>
3
+ <script src="https://js.braintreegateway.com/web/3.84.0/js/data-collector.min.js"></script>
4
+
5
+ <% if current_store.braintree_configuration.paypal? %>
6
+ <script src="https://js.braintreegateway.com/web/3.84.0/js/paypal-checkout.min.js"></script>
7
+ <% end %>
8
+
9
+ <% if current_store.braintree_configuration.credit_card? %>
10
+ <script src="https://js.braintreegateway.com/web/3.84.0/js/hosted-fields.min.js"></script>
11
+
12
+ <% if current_store.braintree_configuration.three_d_secure? %>
13
+ <script src="https://js.braintreegateway.com/web/3.84.0/js/three-d-secure.min.js"></script>
14
+ <% end %>
15
+ <% end %>
16
+
17
+ <% if current_store.braintree_configuration.apple_pay? %>
18
+ <script src="https://js.braintreegateway.com/web/3.84.0/js/apple-pay.min.js"></script>
19
+ <% end %>
20
+
21
+ <% if current_store.braintree_configuration.venmo? %>
22
+ <script src="https://js.braintreegateway.com/web/3.84.0/js/venmo.min.js"></script>
23
+ <% end %>
24
+
25
+ <%= javascript_include_tag "solidus_braintree/checkout" %>
26
+ <% end %>
@@ -0,0 +1,43 @@
1
+ <% if defined?(id) && !defined?(payment_method) %>
2
+ <% payment_method = Spree::PaymentMethod.find(id) %>
3
+ <% Spree::Deprecation.warn(
4
+ "passing id to _braintree_hosted_fields.html.erb is deprecated. Please pass the payment_method directly.",
5
+ caller
6
+ ) %>
7
+ <% end %>
8
+
9
+ <% prefix = "payment_source[#{payment_method.id}]" %>
10
+
11
+ <div class="hosted-fields">
12
+ <div class="field" data-hook="card_number">
13
+ <%= label_tag "card_number#{payment_method.id}", Spree::CreditCard.human_attribute_name(:number), class: "required" %>
14
+ <div class="input" id="card_number<%= payment_method.id %>"></div>
15
+ </div>
16
+
17
+ <div class="field" data-hook="card_expiration">
18
+ <%= label_tag "card_expiry#{payment_method.id}", Spree::CreditCard.human_attribute_name(:expiration), class: "required" %>
19
+ <div class="input" id="card_expiry<%= payment_method.id %>"></div>
20
+ </div>
21
+
22
+ <div class="field" data-hook="card_code">
23
+ <%= label_tag "card_code#{payment_method.id}", Spree::CreditCard.human_attribute_name(:card_code), class: "required" %>
24
+ <div class="input" id="card_code<%= payment_method.id %>"></div>
25
+
26
+ <a href="/content/cvv" class="info cvvLink" target="_blank">
27
+ (<%= I18n.t("spree.what_is_this") %>)
28
+ </a>
29
+ </div>
30
+
31
+ <div class="clear"></div>
32
+ <input type="hidden" name="<%= prefix %>[payment_type]" value="<%= SolidusBraintree::Source::CREDIT_CARD %>">
33
+ <input type="hidden" id="payment_method_nonce" name="<%= prefix %>[nonce]">
34
+ </div>
35
+
36
+
37
+ <script>
38
+ <% if current_store.braintree_configuration.three_d_secure? %>
39
+ var threeDSecureOptions = <%= raw braintree_3ds_options_for(current_order).to_json %>;
40
+ <% end -%>
41
+ var credit_card_fields_style = <%= raw payment_method.preferred_credit_card_fields_style.to_json %>
42
+ var placeholder_text = <%= raw payment_method.preferred_placeholder_text.to_json %>
43
+ </script>
@@ -0,0 +1,38 @@
1
+ <%= render "spree/shared/braintree_head_scripts" %>
2
+
3
+ <div id="paypal-button"></div>
4
+ <div data-pp-message data-pp-placement="payment" data-pp-amount="<%= current_order.total %>"></div>
5
+
6
+ <script>
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
+ buyerCountry: '<%= SolidusBraintree::Gateway.first.preferred_force_buyer_country %>',
13
+ environment: '<%= Rails.env.production? ? "production" : "sandbox" %>',
14
+ locale: '<%= paypal_button_preference(:paypal_button_locale, store: current_store) %>',
15
+ useDataCollector: <%= SolidusBraintree::Gateway.first.preferred_use_data_collector %>,
16
+ style: {
17
+ color: '<%= paypal_button_preference(:paypal_button_color, store: current_store) %>',
18
+ shape: '<%= paypal_button_preference(:paypal_button_shape, store: current_store) %>',
19
+ label: '<%= paypal_button_preference(:paypal_button_label, store: current_store) %>',
20
+ layout: '<%= paypal_button_preference(:paypal_button_layout, store: current_store) %>',
21
+ <% if paypal_button_preference(:paypal_button_layout, store: current_store) == "horizontal" %>
22
+ tagline: '<%= paypal_button_preference(:paypal_button_tagline, store: current_store) %>',
23
+ <% end %>
24
+ messaging: '<%= paypal_button_preference(:paypal_button_messaging, store: current_store) %>'
25
+ }
26
+ }
27
+ var options = {
28
+ restart_checkout: true
29
+ }
30
+
31
+ var button = new SolidusBraintree.createPaypalButton(
32
+ document.querySelector("#paypal-button"),
33
+ paypalOptions,
34
+ options
35
+ )
36
+
37
+ button.initialize();
38
+ </script>
@@ -0,0 +1,13 @@
1
+ <%= render "spree/shared/braintree_head_scripts" %>
2
+
3
+ <div data-pp-message data-pp-placement="<%= options[:placement] %>" data-pp-amount="<%= options[:total] %>"></div>
4
+
5
+ <script>
6
+ var message = new SolidusBraintree.createPaypalMessaging(
7
+ {
8
+ currency: "<%= options[:currency] %>"
9
+ }
10
+ )
11
+
12
+ message.initialize();
13
+ </script>
@@ -0,0 +1,33 @@
1
+ <%= button_tag '', id: 'venmo-button', class: 'venmo-button', type: 'button' %>
2
+
3
+ <% store = Spree::Store.default %>
4
+ <% style = venmo_button_style(store) %>
5
+
6
+ <style>
7
+ .venmo-button {
8
+ width: <%= style[:width] %>px;
9
+ background-image: url('<%= venmo_button_asset_url(style)%>');
10
+ }
11
+ .venmo-button:active, .venmo-button:hover {
12
+ background-color: transparent !important;
13
+ background-image: url('<%= venmo_button_asset_url(style, active: true)%>') !important;
14
+ }
15
+ </style>
16
+
17
+ <% prefix = "payment_source[#{payment_method.id}]" %>
18
+
19
+ <div class="venmo-fields">
20
+ <div class="clear"></div>
21
+ <input disabled type="hidden" name="<%= prefix %>[payment_type]" value="<%= SolidusBraintree::Source::VENMO %>">
22
+ <input disabled type="hidden" id="venmo_payment_method_nonce" name="<%= prefix %>[nonce]">
23
+ </div>
24
+
25
+ <script>
26
+ var venmoButtonElement = document.getElementById('venmo-button');
27
+ var venmoOptions = {
28
+ newBrowserTabSupported: <%= SolidusBraintree::Gateway.first.preferred_venmo_new_tab_support %>,
29
+ flow: '<%= SolidusBraintree::Gateway.first.preferred_paypal_flow %>'
30
+ };
31
+ var button = new SolidusBraintree.createVenmoButton(venmoButtonElement, venmoOptions);
32
+ button.initialize();
33
+ </script>
data/bin/console CHANGED
@@ -1,14 +1,17 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ # frozen_string_literal: true
4
+
3
5
  require "bundler/setup"
4
6
  require "solidus_braintree"
5
7
 
6
8
  # You can add fixtures and/or initialization code here to make experimenting
7
9
  # with your gem easier. You can also use a different console, if you like.
10
+ $LOAD_PATH.unshift(*Dir["#{__dir__}/../app/*"])
8
11
 
9
12
  # (If you use this, don't forget to add pry to your Gemfile!)
10
13
  # require "pry"
11
14
  # Pry.start
12
15
 
13
16
  require "irb"
14
- IRB.start
17
+ IRB.start(__FILE__)
data/bin/rails CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- ENGINE_ROOT = File.expand_path('../..', __FILE__)
4
- ENGINE_PATH = File.expand_path('../../lib/solidus_braintree/engine', __FILE__)
5
-
6
- require 'rails/all'
7
- require 'rails/engine/commands'
3
+ if %w[g generate].include? ARGV.first
4
+ exec "#{__dir__}/rails-engine", *ARGV
5
+ else
6
+ exec "#{__dir__}/rails-sandbox", *ARGV
7
+ end
data/bin/rails-engine ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails gems
3
+ # installed from the root of your application.
4
+
5
+ ENGINE_ROOT = File.expand_path('..', __dir__)
6
+ ENGINE_PATH = File.expand_path('../lib/solidus_braintree/engine', __dir__)
7
+
8
+ # Set up gems listed in the Gemfile.
9
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
10
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
11
+
12
+ require 'rails/all'
13
+ require 'rails/engine/commands'
data/bin/rails-sandbox ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ app_root = 'sandbox'
4
+
5
+ unless File.exist? "#{app_root}/bin/rails"
6
+ warn 'Creating the sandbox app...'
7
+ Dir.chdir "#{__dir__}/.." do
8
+ system "#{__dir__}/sandbox" or begin
9
+ warn 'Automatic creation of the sandbox app failed'
10
+ exit 1
11
+ end
12
+ end
13
+ end
14
+
15
+ Dir.chdir app_root
16
+ exec 'bin/rails', *ARGV
data/bin/rake ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "rubygems"
5
+ require "bundler/setup"
6
+
7
+ load Gem.bin_path("rake", "rake")
data/bin/sandbox ADDED
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -e
4
+ if [ -n "$DEBUG" ]
5
+ then
6
+ set -x
7
+ fi
8
+
9
+ case "$DB" in
10
+ postgres|postgresql)
11
+ RAILSDB="postgresql"
12
+ ;;
13
+ mysql)
14
+ RAILSDB="mysql"
15
+ ;;
16
+ sqlite3|sqlite)
17
+ RAILSDB="sqlite3"
18
+ ;;
19
+ '')
20
+ echo "~~> Use 'export DB=[postgres|mysql|sqlite]' to control the DB adapter"
21
+ RAILSDB="sqlite3"
22
+ ;;
23
+ *)
24
+ echo "Invalid value specified for the Solidus sandbox: DB=\"$DB\"."
25
+ echo "Please use 'postgres', 'mysql', or 'sqlite' instead."
26
+ exit 1
27
+ ;;
28
+ esac
29
+ echo "~~> Using $RAILSDB as the database engine"
30
+
31
+ if [ -z "$SOLIDUS_BRANCH" ]
32
+ then
33
+ echo "~~> Use 'export SOLIDUS_BRANCH=[master|v3.2|...]' to control the Solidus branch"
34
+ SOLIDUS_BRANCH="master"
35
+ fi
36
+ echo "~~> Using branch $SOLIDUS_BRANCH of solidus"
37
+
38
+ if [ -z "$SOLIDUS_FRONTEND" ]
39
+ then
40
+ echo "~~> Use 'export SOLIDUS_FRONTEND=[solidus_frontend|solidus_starter_frontend]' to control the Solidus frontend"
41
+ SOLIDUS_FRONTEND="solidus_frontend"
42
+ fi
43
+ echo "~~> Using branch $SOLIDUS_FRONTEND as the solidus frontend"
44
+
45
+ extension_name="solidus_braintree"
46
+
47
+ # Stay away from the bundler env of the containing extension.
48
+ function unbundled {
49
+ ruby -rbundler -e'b = proc {system *ARGV}; Bundler.respond_to?(:with_unbundled_env) ? Bundler.with_unbundled_env(&b) : Bundler.with_clean_env(&b)' -- $@
50
+ }
51
+
52
+ rm -rf ./sandbox
53
+ unbundled bundle exec rails new sandbox --database="$RAILSDB" \
54
+ --skip-bundle \
55
+ --skip-git \
56
+ --skip-keeps \
57
+ --skip-rc \
58
+ --skip-spring \
59
+ --skip-test \
60
+ --skip-javascript
61
+
62
+ if [ ! -d "sandbox" ]; then
63
+ echo 'sandbox rails application failed'
64
+ exit 1
65
+ fi
66
+
67
+ cd ./sandbox
68
+ cat <<RUBY >> Gemfile
69
+ gem 'solidus', github: 'solidusio/solidus', branch: '$SOLIDUS_BRANCH'
70
+ gem 'rails-i18n'
71
+ gem 'solidus_i18n'
72
+
73
+ # This Braintree extension contains a user decorator, so the user class must be loaded first.
74
+ gem "solidus_auth_devise", "~> 2.5"
75
+ gem '$extension_name', path: '..'
76
+
77
+ group :test, :development do
78
+ platforms :mri do
79
+ gem 'pry-byebug'
80
+ end
81
+ end
82
+ RUBY
83
+
84
+ unbundled bundle install --gemfile Gemfile
85
+
86
+ unbundled bundle exec rake db:drop db:create
87
+
88
+ # Still request "devise". Solidus will skip installing it again but will include its seeds.
89
+ unbundled bundle exec rails generate solidus:install \
90
+ --auto-accept \
91
+ --user_class=Spree::User \
92
+ --enforce_available_locales=true \
93
+ --authentication="devise" \
94
+ --payment-method=none \
95
+ --frontend=${SOLIDUS_FRONTEND} \
96
+ $@
97
+
98
+ unbundled bundle exec rails generate solidus:auth:install --auto-run-migrations
99
+ unbundled bundle exec rails generate ${extension_name}:install --auto-run-migrations
100
+
101
+ echo
102
+ echo "๐Ÿš€ Sandbox app successfully created for $extension_name!"
103
+ echo "๐Ÿงช This app is intended for test purposes."
data/bin/setup CHANGED
@@ -1,7 +1,8 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
  set -euo pipefail
3
3
  IFS=$'\n\t'
4
+ set -vx
4
5
 
5
- bundle install
6
-
7
- # Do any other automated setup that you need to do here
6
+ gem install bundler --conservative
7
+ bundle update
8
+ bin/rake clobber