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,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module PermittedAttributesDecorator
4
- def self.prepended(base)
5
- base.singleton_class.prepend SolidusBraintree::PermittedAttributesConcern
6
- end
7
-
8
- Spree::PermittedAttributes.singleton_class.prepend(self)
9
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CreditCardDecorator
4
- def self.prepended(base)
5
- base.include SolidusBraintree::SkipRequireCardNumbersConcern
6
- base.include SolidusBraintree::AddNameValidationConcern
7
- base.include SolidusBraintree::UseDataFieldConcern
8
- end
9
-
10
- Spree::CreditCard.prepend(self)
11
- end
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module PaymentDecorator
4
- def self.prepended(base)
5
- base.include SolidusBraintree::PaymentBraintreeNonceConcern
6
- base.include SolidusBraintree::InjectDeviceDataConcern
7
- end
8
-
9
- Spree::Payment.prepend(self)
10
- end
@@ -1,20 +0,0 @@
1
- module BraintreeViewHelpers
2
- # Returns a link to the Braintree web UI for the given Braintree +payment_id+
3
- # (e.g. from Spree::Payment#response_code), or just the +payment_id+ if
4
- # Braintree's merchant ID is not configured or +payment_id+ is blank
5
- def braintree_transaction_link(payment_id)
6
- env = ENV['BRAINTREE_ENV'] == 'production' ? 'www' : 'sandbox'
7
- merchant = ENV['BRAINTREE_MERCHANT_ID']
8
-
9
- if payment_id.present? && merchant.present?
10
- link_to(
11
- payment_id,
12
- "https://#{env}.braintreegateway.com/merchants/#{merchant}/transactions/#{payment_id}",
13
- title: 'Show payment on Braintree',
14
- target: '_blank'
15
- )
16
- else
17
- payment_id
18
- end
19
- end
20
- end
@@ -1,8 +0,0 @@
1
- module SolidusBraintree
2
- module AddNameValidationConcern
3
- extend ActiveSupport::Concern
4
- included do
5
- validates :name, presence: true, on: :create
6
- end
7
- end
8
- end
@@ -1,18 +0,0 @@
1
- module SolidusBraintree
2
- module InjectDeviceDataConcern
3
- extend ActiveSupport::Concern
4
- included do
5
- prepend(InstanceMethods)
6
- end
7
-
8
- module InstanceMethods
9
- def gateway_options
10
- options = super
11
-
12
- options[:device_data] = order.braintree_device_data if order.braintree_device_data
13
-
14
- options
15
- end
16
- end
17
- end
18
- end
@@ -1,8 +0,0 @@
1
- module SolidusBraintree
2
- module PaymentBraintreeNonceConcern
3
- extend ActiveSupport::Concern
4
- included do
5
- attr_accessor :payment_method_nonce
6
- end
7
- end
8
- end
@@ -1,11 +0,0 @@
1
- module SolidusBraintree
2
- module PermittedAttributesConcern
3
- def payment_attributes
4
- super | [:payment_method_nonce]
5
- end
6
-
7
- def checkout_attributes
8
- super | [:braintree_device_data]
9
- end
10
- end
11
- end
@@ -1,14 +0,0 @@
1
- module SolidusBraintree
2
- module SkipRequireCardNumbersConcern
3
- extend ActiveSupport::Concern
4
- included do
5
- prepend(InstanceMethods)
6
- end
7
-
8
- module InstanceMethods
9
- def require_card_numbers?
10
- super && !self.payment_method.kind_of?(Solidus::Gateway::BraintreeGateway)
11
- end
12
- end
13
- end
14
- end
@@ -1,23 +0,0 @@
1
- module SolidusBraintree
2
- module UseDataFieldConcern
3
- extend ActiveSupport::Concern
4
- included do
5
- prepend(InstanceMethods)
6
- end
7
-
8
- module InstanceMethods
9
-
10
- def email
11
- data["email"]
12
- end
13
-
14
- def display_number
15
- cc_type == 'paypal' ? email : super
16
- end
17
-
18
- def data
19
- super.is_a?(String) ? JSON.parse(super) : super
20
- end
21
- end
22
- end
23
- end
@@ -1,306 +0,0 @@
1
- require "braintree"
2
-
3
- module Solidus
4
- gateway_superclass =
5
- if SolidusSupport.solidus_gem_version < Gem::Version.new('2.3.x')
6
- ::Spree::Gateway
7
- else
8
- ::Spree::PaymentMethod::CreditCard
9
- end
10
-
11
- class Gateway::BraintreeGateway < gateway_superclass
12
- preference :environment, :string
13
- preference :merchant_id, :string
14
- preference :public_key, :string
15
- preference :private_key, :string
16
- preference :always_send_bill_address, :boolean, default: false
17
- preference :transmit_shipping_address, :boolean, default: true
18
-
19
- CARD_TYPE_MAPPING = {
20
- 'American Express' => 'american_express',
21
- 'Diners Club' => 'diners_club',
22
- 'Discover' => 'discover',
23
- 'JCB' => 'jcb',
24
- 'Laser' => 'laser',
25
- 'Maestro' => 'maestro',
26
- 'MasterCard' => 'master',
27
- 'Solo' => 'solo',
28
- 'Switch' => 'switch',
29
- 'Visa' => 'visa',
30
- }
31
-
32
- if SolidusSupport.solidus_gem_version < Gem::Version.new('2.3.x')
33
- def method_type
34
- 'braintree'
35
- end
36
- else
37
- def partial_name
38
- 'braintree'
39
- end
40
- end
41
-
42
- def gateway_options
43
- {
44
- environment: preferred_environment.to_sym,
45
- merchant_id: preferred_merchant_id,
46
- public_key: preferred_public_key,
47
- private_key: preferred_private_key,
48
- logger: ::Braintree::Configuration.logger.clone,
49
- }
50
- end
51
-
52
- def braintree_gateway
53
- @braintree_gateway ||= ::Braintree::Gateway.new(gateway_options)
54
- end
55
-
56
- def payment_profiles_supported?
57
- true
58
- end
59
-
60
- def generate_client_token(options = {})
61
- braintree_gateway.client_token.generate(options)
62
- end
63
-
64
- def create_profile(payment)
65
- source = payment.source
66
-
67
- return if source.gateway_customer_profile_id.present? || payment.payment_method_nonce.nil?
68
-
69
- user = payment.order.user
70
- email = user ? user.email : payment.order.email
71
- address = (payment.source.address || payment.order.bill_address).try(:active_merchant_hash)
72
-
73
- params = {
74
- first_name: source.first_name,
75
- last_name: source.last_name,
76
- email: email,
77
- credit_card: {
78
- cardholder_name: source.name,
79
- billing_address: map_address(address),
80
- payment_method_nonce: payment.payment_method_nonce,
81
- options: {
82
- verify_card: true,
83
- },
84
- },
85
- device_data: payment.order.braintree_device_data
86
- }
87
-
88
- result = braintree_gateway.customer.create(params)
89
-
90
- if result.success?
91
- card = result.customer.payment_methods.last
92
- source.tap do |solidus_cc|
93
- if card.is_a?(::Braintree::PayPalAccount)
94
- solidus_cc.cc_type = 'paypal'
95
- data = {
96
- email: card.email
97
- }
98
- solidus_cc.data = data.to_json
99
- else
100
- solidus_cc.name = card.cardholder_name
101
- solidus_cc.cc_type = CARD_TYPE_MAPPING[card.card_type]
102
- solidus_cc.month = card.expiration_month
103
- solidus_cc.year = card.expiration_year
104
- solidus_cc.last_digits = card.last_4
105
- end
106
- solidus_cc.payment_method = self
107
- solidus_cc.gateway_customer_profile_id = result.customer.id
108
- solidus_cc.gateway_payment_profile_id = card.token
109
- end
110
- source.save!
111
- else
112
- raise ::Spree::Core::GatewayError, result.message
113
- end
114
- end
115
-
116
- def supports?(payment)
117
- true
118
- end
119
-
120
- def provider_class
121
- self
122
- end
123
-
124
- def authorize(cents, creditcard, options = {})
125
- result = braintree_gateway.transaction.sale(transaction_authorize_or_purchase_params(cents, creditcard, options))
126
- handle_result(result)
127
- end
128
-
129
- def purchase(cents, creditcard, options = {})
130
- params = transaction_authorize_or_purchase_params(cents, creditcard, options)
131
- params[:options][:submit_for_settlement] = true
132
- result = braintree_gateway.transaction.sale(params)
133
- handle_result(result)
134
- end
135
-
136
- def capture(money, authorization_code, options = {})
137
- result = braintree_gateway.transaction.submit_for_settlement(authorization_code, amount(money))
138
- handle_result(result)
139
- end
140
-
141
- def void(authorization_code, source = {}, options = {})
142
- # Allows voiding payments that are in a checkout state
143
- if authorization_code.nil?
144
- # Fake response since we don't need to void anything with Braintree
145
- ActiveMerchant::Billing::Response.new(
146
- true,
147
- "OK",
148
- {},
149
- {}
150
- )
151
- else
152
- result = braintree_gateway.transaction.void(authorization_code)
153
- handle_result(result)
154
- end
155
- end
156
-
157
- def credit(cents, source, authorization_code, options = {})
158
- result = braintree_gateway.transaction.refund(authorization_code, amount(cents))
159
- handle_result(result)
160
- end
161
-
162
- def voidable?(response_code)
163
- transaction = braintree_gateway.transaction.find(response_code)
164
- [
165
- ::Braintree::Transaction::Status::SubmittedForSettlement,
166
- ::Braintree::Transaction::Status::Authorized,
167
- ].include?(transaction.status)
168
- end
169
-
170
- def card_number_placeholder
171
- '4141 4141 4141 4141'
172
- end
173
-
174
- def expiration_date_placeholder
175
- '01/2020'
176
- end
177
-
178
- def card_code_placeholder
179
- '123'
180
- end
181
-
182
- def cancel(response)
183
- if voidable?(response)
184
- void(response)
185
- else
186
- handle_result(
187
- braintree_gateway.transaction.refund(response)
188
- )
189
- end
190
- end
191
-
192
- private
193
- def message_from_result(result)
194
- if result.success?
195
- "OK"
196
- elsif result.errors.count == 0 && result.credit_card_verification
197
- "Processor declined: #{result.credit_card_verification.processor_response_text} (#{result.credit_card_verification.processor_response_code})"
198
- elsif result.errors.count == 0 && result.transaction
199
- result.transaction.status
200
- else
201
- result.errors.map { |e| "#{e.message} (#{e.code})" }.join(" ")
202
- end
203
- end
204
-
205
- def build_results_hash(result)
206
- if result.success?
207
- {
208
- authorization: result.transaction.id,
209
- avs_result: {
210
- code: result.transaction.avs_street_address_response_code
211
- }
212
- }
213
- else
214
- {}
215
- end
216
- end
217
-
218
- def handle_result(result)
219
- ActiveMerchant::Billing::Response.new(
220
- result.success?,
221
- message_from_result(result),
222
- {},
223
- build_results_hash(result)
224
- )
225
- end
226
-
227
- def map_address(addr)
228
- full_name = addr.fetch(:name, "")
229
- *first_name_parts, last_name = full_name.split(" ")
230
- first_name = first_name_parts.join(" ")
231
- last_name ||= ""
232
-
233
- {
234
- first_name: first_name,
235
- last_name: last_name,
236
- street_address: addr[:address1],
237
- extended_address: addr[:address2],
238
- locality: addr[:city],
239
- region: addr[:state],
240
- country_code_alpha2: addr[:country],
241
- postal_code: addr[:zip],
242
- }
243
- end
244
-
245
- def amount(cents)
246
- sprintf("%.2f", cents.to_f / 100)
247
- end
248
-
249
- def transaction_authorize_or_purchase_params(cents, creditcard, options = {})
250
- params = options.select {|k| %i[
251
- billing_address_id
252
- channel
253
- custom_fields
254
- descriptor
255
- device_data
256
- device_session_id
257
- merchant_account_id
258
- options
259
- order_id
260
- purchase_order_number
261
- recurring
262
- service_fee_amount
263
- shipping_address_id
264
- tax_amount
265
- tax_exempt
266
- ].include?(k)}
267
-
268
- params[:options] ||= {}
269
- params[:amount] = amount(cents)
270
- params[:channel] ||= "Solidus"
271
- if (options[:shipping_address] && preferred_transmit_shipping_address)
272
- params[:shipping] = map_address(options[:shipping_address])
273
- end
274
-
275
- if options[:payment_method_nonce]
276
- params[:payment_method_nonce] = options[:payment_method_nonce]
277
- else
278
- params[:payment_method_token] = creditcard.gateway_payment_profile_id
279
- end
280
-
281
- # Send the bill address if we're using a nonce (i.e. doing a one-time
282
- # payment) or if we're configured to always send the bill address
283
- if (
284
- options[:payment_method_nonce] || preferred_always_send_bill_address
285
- ) && options[:billing_address]
286
- params[:billing] = map_address(options[:billing_address])
287
- end
288
-
289
- # if has profile, set the customer_id to the profile_id and delete the customer key
290
- if creditcard.try(:gateway_customer_profile_id)
291
- params[:customer_id] = creditcard.gateway_customer_profile_id
292
- # if no profile, define the customer key, delete the customer_id because they are
293
- # mutually exclusive
294
- else
295
- params[:customer] = {
296
- id: options[:customer_id],
297
- email: options[:customer],
298
- first_name: creditcard.first_name,
299
- last_name: creditcard.last_name,
300
- }
301
- end
302
-
303
- params
304
- end
305
- end
306
- end
@@ -1,9 +0,0 @@
1
- <!-- insert_before "erb[loud]:contains('place_order')" -->
2
-
3
- <%
4
- # Currently we assume we only have one braintree
5
- # payment method. In practice this should be true and it simplifies the code.
6
- braintree_payment = @order.unprocessed_payments.find {|p| p.payment_method.class == Solidus::Gateway::BraintreeGateway }
7
- if braintree_payment %>
8
- <%= render 'spree/checkout/payment/braintree_initialization', payment_method: braintree_payment.payment_method %>
9
- <% end %>
@@ -1,38 +0,0 @@
1
- <fieldset data-id='credit-card' class="no-border-bottom">
2
- <div class="field" data-hook="previous_cards">
3
- <% if previous_cards.any? %>
4
- <% previous_cards.each do |card| %>
5
- <label><%= radio_button_tag :card, card.id, card == previous_cards.first %> <%= card.display_number %><br /></label>
6
- <% end %>
7
- <% end %>
8
- <label><%= radio_button_tag :card, 'new', false, { id: "card_new#{payment_method.id}" } %> <%= t('spree.use_new_cc') %></label>
9
- </div>
10
-
11
- <div id="card_form<%= payment_method.id %>" data-hook>
12
- <% param_prefix = "payment_source[#{payment_method.id}]" %>
13
-
14
- <div class="clear"></div>
15
-
16
- <div class="alpha four columns">
17
- <div data-hook="card_name">
18
- <div class="field">
19
- <%= label_tag "card_name#{payment_method.id}", Spree::CreditCard.human_attribute_name(:name), class: 'required' %>
20
- <%= text_field_tag "#{param_prefix}[name]", '', id: "card_name#{payment_method.id}", class: 'required fullwidth', maxlength: 19 %>
21
- </div>
22
- </div>
23
- </div>
24
-
25
- <div id="braintree-dropin"></div>
26
- <input type="hidden" id="payment_method_nonce" name="payment[payment_method_nonce]">
27
-
28
- <div class="clear"></div>
29
-
30
- <%= label_tag "card_address#{payment_method.id}", t('spree.billing_address') %>
31
- <% address = @order.bill_address || @order.ship_address || Spree::Address.build_default %>
32
- <%= fields_for "#{param_prefix}[address_attributes]", address do |f| %>
33
- <%= render :partial => 'spree/admin/shared/address_form', :locals => { :f => f, :type => "billing" } %>
34
- <% end %>
35
-
36
- <div class="clear"></div>
37
- </div>
38
- </fieldset>
@@ -1,30 +0,0 @@
1
- <fieldset data-hook="credit_card">
2
- <legend align="center"><%= Spree::CreditCard.model_name.human %></legend>
3
-
4
- <div class="row">
5
- <div class="alpha six columns">
6
- <dl>
7
- <dt><%= t('spree.identifier') %>:</dt>
8
- <dd><%= payment.number %></dd>
9
-
10
- <dt><%= t('spree.response_code') %>:</dt>
11
- <dd><%= braintree_transaction_link(payment.response_code) %></dd>
12
-
13
- <dt><%= t('spree.name_on_card') %>:</dt>
14
- <dd><%= payment.source.name %></dd>
15
-
16
- <dt><%= Spree::CreditCard.human_attribute_name(:cc_type) %>:</dt>
17
- <dd><%= payment.source.cc_type %></dd>
18
-
19
- <dt><%= Spree::CreditCard.human_attribute_name(:number) %>:</dt>
20
- <dd><%= payment.source.display_number %></dd>
21
-
22
- <dt><%= Spree::CreditCard.human_attribute_name(:expiration) %>:</dt>
23
- <dd><%= payment.source.month %>/<%= payment.source.year %></dd>
24
- </dl>
25
- <% if payment.source.address %>
26
- <%= render partial: 'spree/admin/shared/address', locals: {address: payment.source.address} %>
27
- <% end %>
28
- </div>
29
- </div>
30
- </fieldset>
@@ -1,55 +0,0 @@
1
- <div class="braintree-payment">
2
- <%= render 'spree/checkout/payment/braintree_initialization', payment_method: payment_method %>
3
-
4
- <div class="braintree-paypal-input">
5
- <div class="braintree-paypal-header">
6
- <%= t('solidus_braintree.paypal_header_html') %>
7
- </div>
8
- <div id="#braintree_paypal_container"></div>
9
- </div>
10
-
11
- <div class="braintree-cc-input">
12
- <div class="braintree-cc-header">
13
- <%= t('solidus_braintree.creditcard_header_html') %>
14
- <%= image_tag 'credit_cards/credit_card.gif', :id => 'credit-card-image' %>
15
- </div>
16
- <% param_prefix = "payment_source[#{payment_method.id}]" %>
17
-
18
- <p class="field">
19
- <%= label_tag "name_on_card_#{payment_method.id}", t('spree.name_on_card') %><span class="required">*</span><br />
20
- <%= text_field_tag "#{param_prefix}[name]", "#{@order.billing_firstname} #{@order.billing_lastname}", { id: "name_on_card_#{payment_method.id}", :autocomplete => "cc-name" } %>
21
- </p>
22
-
23
- <p class="field" data-hook="card_number">
24
- <%= label_tag "braintree_card_number", t('spree.card_number') %><span class="required">*</span><br />
25
- <label for="braintree_card_number" id="braintree_card_number" class="braintree-hosted-field"></label>
26
- &nbsp;
27
- <span id="card_type" style="display:none;">
28
- ( <span id="looks_like" ><%= t('spree.card_type_is') %> <span id="type"></span></span>
29
- <span id="unrecognized"><%= t('spree.unrecognized_card_type') %></span>
30
- )
31
- </span>
32
- </p>
33
-
34
- <p class="field" data-hook="card_expiration">
35
- <%= label_tag "braintree_card_expiry", t('spree.expiration') %><span class="required">*</span><br />
36
- <label for="braintree_card_expiry" id="braintree_card_expiry" class="braintree-hosted-field"></label>
37
- </p>
38
-
39
- <p class="field" data-hook="card_code">
40
- <%= label_tag "braintree_card_code", t('spree.card_code') %><span class="required">*</span><br />
41
-
42
- <label for="braintree_card_code" id="braintree_card_code" class="braintree-hosted-field card-code"></label>
43
- <%= link_to "(#{t('spree.what_is_this')})", spree.cvv_path, :target => '_blank', "data-hook" => "cvv_link", :id => "cvv_link" %>
44
- </p>
45
- </div>
46
-
47
- <% if @order.bill_address %>
48
- <%= fields_for "#{param_prefix}[address_attributes]", @order.bill_address do |f| %>
49
- <%= render :partial => 'spree/address/form_hidden', :locals => { :form => f } %>
50
- <% end %>
51
- <% end %>
52
-
53
- <%= hidden_field_tag "#{param_prefix}[cc_type]", '', :id => "cc_type", :class => 'ccType' %>
54
- <%= hidden_field_tag "order[payments_attributes][][payment_method_nonce]", '', :id => "payment_method_nonce" %>
55
- </div>
@@ -1,12 +0,0 @@
1
- <% content_for :head do %>
2
- <%= javascript_tag do %>
3
- braintree.environment = "<%= payment_method.preferred_environment %>"
4
- braintree.placeholders = {
5
- "number": "<%= payment_method.card_number_placeholder %>",
6
- "expirationDate": "<%= payment_method.expiration_date_placeholder %>",
7
- "cvv": "<%= payment_method.card_code_placeholder %>"
8
- }
9
- <% end %>
10
- <% end %>
11
-
12
- <%= hidden_field_tag "order[braintree_device_data]", '', :id => "device_data" %>
@@ -1,3 +0,0 @@
1
- Rails.application.config.to_prepare do
2
- ActionView::Base.include(BraintreeViewHelpers)
3
- end
@@ -1,5 +0,0 @@
1
- class AddDataToCreditCard < SolidusSupport::Migration[4.2]
2
- def change
3
- add_column :spree_credit_cards, :data, :text
4
- end
5
- end
@@ -1,5 +0,0 @@
1
- class AddBraintreeDeviceDataToOrder < SolidusSupport::Migration[4.2]
2
- def change
3
- add_column :spree_orders, :braintree_device_data, :text
4
- end
5
- end
@@ -1,59 +0,0 @@
1
- //= require "vendor/braintree"
2
-
3
- Spree.pathFor.payment_client_token_api = Spree.pathFor("api/payment_client_token")
4
-
5
- var braintreeDropinIntegration;
6
- var paymentForm = "#new_payment";
7
- var cardSelector = "#new_payment [name=card]";
8
-
9
- var getClientToken = function(onSuccess) {
10
- return Spree.ajax({
11
- url: Spree.pathFor.payment_client_token_api,
12
- type: "POST",
13
- data: {
14
- payment_method_id: $('form input[type=radio]:checked').val()
15
- },
16
- error: function(xhr, status) {
17
- show_flash("error", xhr.responseJSON.message);
18
- },
19
- success: function(data) {
20
- onSuccess(data);
21
- }
22
- });
23
- };
24
-
25
- var attachDropIn = function(data) {
26
- braintree.setup(data.client_token, "dropin", {
27
- container: "braintree-dropin",
28
- form: "new_payment",
29
- onReady: function (integration) {
30
- braintreeDropinIntegration = integration;
31
- },
32
- onError: function(type, message) {
33
- show_flash("error", message);
34
- },
35
- onPaymentMethodReceived: function(obj) {
36
- $("#payment_method_nonce").val(obj.nonce);
37
- $("#new_payment").submit();
38
- return;
39
- }
40
- });
41
- };
42
-
43
- $(document).ready(function() {
44
- if ($(paymentForm).length) {
45
- if ($(cardSelector).length) {
46
- $(cardSelector).on("change", function() {
47
- if ($(cardSelector + ":checked").val() === "new") {
48
- getClientToken(attachDropIn);
49
- } else {
50
- if (braintreeDropinIntegration) {
51
- braintreeDropinIntegration.teardown();
52
- }
53
- }
54
- });
55
- } else {
56
- getClientToken(attachDropIn);
57
- }
58
- }
59
- });