solidus_bolt 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +41 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github/stale.yml +17 -0
  5. data/.github_changelog_generator +2 -0
  6. data/.gitignore +20 -0
  7. data/.rspec +2 -0
  8. data/.rubocop.yml +11 -0
  9. data/CHANGELOG.md +1 -0
  10. data/Gemfile +33 -0
  11. data/LICENSE +26 -0
  12. data/README.md +175 -0
  13. data/Rakefile +6 -0
  14. data/app/assets/images/bolt_logo_standard.png +0 -0
  15. data/app/assets/javascripts/authorize_account.js +74 -0
  16. data/app/assets/javascripts/solidus_bolt.js +91 -0
  17. data/app/assets/javascripts/spree/backend/solidus_bolt.js +4 -0
  18. data/app/assets/javascripts/spree/frontend/solidus_bolt.js +18 -0
  19. data/app/assets/stylesheets/spree/backend/solidus_bolt.css +4 -0
  20. data/app/assets/stylesheets/spree/frontend/solidus_bolt.css +4 -0
  21. data/app/controllers/solidus_bolt/accounts_controller.rb +17 -0
  22. data/app/controllers/solidus_bolt/base_controller.rb +21 -0
  23. data/app/controllers/solidus_bolt/webhooks_controller.rb +21 -0
  24. data/app/controllers/spree/admin/bolt_webhooks_controller.rb +34 -0
  25. data/app/controllers/spree/admin/bolts_controller.rb +43 -0
  26. data/app/decorators/controllers/solidus_bolt/spree_checkout_controller/add_addresses_to_bolt.rb +23 -0
  27. data/app/decorators/controllers/solidus_bolt/spree_checkout_controller/refresh_bolt_addresses.rb +17 -0
  28. data/app/decorators/controllers/solidus_bolt/spree_checkout_controller/refresh_bolt_payment_source.rb +17 -0
  29. data/app/decorators/models/solidus_bolt/address_decorator.rb +22 -0
  30. data/app/decorators/models/solidus_bolt/log_entry_decorator.rb +11 -0
  31. data/app/decorators/models/solidus_bolt/order_decorator.rb +44 -0
  32. data/app/decorators/models/solidus_bolt/payment_decorator.rb +11 -0
  33. data/app/decorators/omniauth/strategies/bolt_decorator.rb +16 -0
  34. data/app/jobs/solidus_bolt/add_address_job.rb +11 -0
  35. data/app/models/solidus_bolt/bolt_configuration.rb +74 -0
  36. data/app/models/solidus_bolt/gateway.rb +133 -0
  37. data/app/models/solidus_bolt/payment_method.rb +35 -0
  38. data/app/models/solidus_bolt/payment_source.rb +13 -0
  39. data/app/models/solidus_bolt.rb +7 -0
  40. data/app/overrides/spree/shared/_head/add_bolt_embed_script.html.erb.deface +6 -0
  41. data/app/services/solidus_bolt/accounts/add_address_service.rb +55 -0
  42. data/app/services/solidus_bolt/accounts/add_payment_method_service.rb +45 -0
  43. data/app/services/solidus_bolt/accounts/detail_service.rb +38 -0
  44. data/app/services/solidus_bolt/accounts/detect_account_service.rb +34 -0
  45. data/app/services/solidus_bolt/base_service.rb +55 -0
  46. data/app/services/solidus_bolt/oauth/token_service.rb +43 -0
  47. data/app/services/solidus_bolt/payments/capture_sync_service.rb +24 -0
  48. data/app/services/solidus_bolt/payments/credit_sync_service.rb +44 -0
  49. data/app/services/solidus_bolt/payments/void_sync_service.rb +18 -0
  50. data/app/services/solidus_bolt/server_error.rb +6 -0
  51. data/app/services/solidus_bolt/transactions/authorize_service.rb +72 -0
  52. data/app/services/solidus_bolt/transactions/base_service.rb +28 -0
  53. data/app/services/solidus_bolt/transactions/capture_service.rb +46 -0
  54. data/app/services/solidus_bolt/transactions/detail_service.rb +38 -0
  55. data/app/services/solidus_bolt/transactions/refund_service.rb +46 -0
  56. data/app/services/solidus_bolt/transactions/void_service.rb +44 -0
  57. data/app/services/solidus_bolt/users/refresh_access_token_service.rb +44 -0
  58. data/app/services/solidus_bolt/users/sync_addresses_service.rb +49 -0
  59. data/app/services/solidus_bolt/users/sync_payment_sources_service.rb +50 -0
  60. data/app/services/solidus_bolt/webhooks/create_service.rb +52 -0
  61. data/app/views/spree/admin/bolt_webhooks/new.html.erb +22 -0
  62. data/app/views/spree/admin/bolts/_configuration.html.erb +32 -0
  63. data/app/views/spree/admin/bolts/_form.html.erb +29 -0
  64. data/app/views/spree/admin/bolts/edit.html.erb +6 -0
  65. data/app/views/spree/admin/bolts/show.html.erb +21 -0
  66. data/app/views/spree/admin/payments/source_forms/_bolt.html.erb +1 -0
  67. data/app/views/spree/admin/payments/source_views/_bolt.html.erb +2 -0
  68. data/app/views/spree/api/payments/source_views/_bolt.json.jbuilder +4 -0
  69. data/app/views/spree/checkout/existing_payment/_bolt.html.erb +7 -0
  70. data/app/views/spree/checkout/payment/_bolt.html.erb +1 -0
  71. data/app/views/spree/shared/payment/_bolt.html.erb +19 -0
  72. data/app/webhooks/solidus_bolt/handlers/base_handler.rb +27 -0
  73. data/app/webhooks/solidus_bolt/handlers/capture_handler.rb +13 -0
  74. data/app/webhooks/solidus_bolt/handlers/credit_handler.rb +18 -0
  75. data/app/webhooks/solidus_bolt/handlers/void_handler.rb +11 -0
  76. data/app/webhooks/solidus_bolt/sorter.rb +33 -0
  77. data/bin/console +17 -0
  78. data/bin/rails +7 -0
  79. data/bin/rails-engine +13 -0
  80. data/bin/rails-sandbox +16 -0
  81. data/bin/rake +7 -0
  82. data/bin/sandbox +86 -0
  83. data/bin/setup +8 -0
  84. data/config/initializers/menu_items.rb +14 -0
  85. data/config/locales/en.yml +17 -0
  86. data/config/routes.rb +11 -0
  87. data/db/migrate/20220330094232_create_solidus_bolt_payment_sources.rb +16 -0
  88. data/db/migrate/20220413063328_create_solidus_bolt_bolt_configurations.rb +14 -0
  89. data/db/migrate/20220502005041_swap_url_for_env_boolean_in_bolt_configuration.rb +6 -0
  90. data/db/migrate/20220509102309_rework_solidus_bolt_payment_sources.rb +19 -0
  91. data/db/migrate/20220510075227_add_create_bolt_account_to_solidus_bolt_payment_source.rb +5 -0
  92. data/db/migrate/20220519233043_add_user_to_solidus_bolt_payment_source.rb +5 -0
  93. data/db/migrate/20220526005619_remove_user_id_from_solidus_bolt_payment_source.rb +5 -0
  94. data/db/migrate/20220530102107_rename_bolt_configuration_merchant_id_to_division_public_id.rb +5 -0
  95. data/db/migrate/20220531075527_update_bolt_configuration_environment_column_restrictions.rb +6 -0
  96. data/db/seeds.rb +30 -0
  97. data/lib/generators/solidus_bolt/install/install_generator.rb +78 -0
  98. data/lib/generators/solidus_bolt/install/templates/initializer.rb +8 -0
  99. data/lib/solidus_bolt/configuration.rb +19 -0
  100. data/lib/solidus_bolt/engine.rb +62 -0
  101. data/lib/solidus_bolt/testing_support/factories.rb +32 -0
  102. data/lib/solidus_bolt/version.rb +5 -0
  103. data/lib/solidus_bolt.rb +9 -0
  104. data/lib/tasks/db/seed/solidus_bolt.rake +14 -0
  105. data/lib/views/frontend/spree/shared/_login_bar_items.html.erb +18 -0
  106. data/solidus_bolt.gemspec +46 -0
  107. data/spec/decorators/models/solidus_bolt/address_decorator_spec.rb +24 -0
  108. data/spec/decorators/models/solidus_bolt/order_decorator_spec.rb +36 -0
  109. data/spec/decorators/models/solidus_bolt/payment_decorator_spec.rb +30 -0
  110. data/spec/fixtures/vcr_cassettes/SolidusBolt_Accounts_AddAddressService/_call/with_correct_access_token/receives_a_successful_response.yml +137 -0
  111. data/spec/fixtures/vcr_cassettes/SolidusBolt_Accounts_AddAddressService/_call/with_existing_address/skips_the_add_address_call.yml +82 -0
  112. data/spec/fixtures/vcr_cassettes/SolidusBolt_Accounts_AddAddressService/_call/with_wrong_access_token/gives_an_error.yml +55 -0
  113. data/spec/fixtures/vcr_cassettes/SolidusBolt_Accounts_AddPaymentMethodService/_call/with_correct_access_token/receives_a_successful_response.yml +186 -0
  114. data/spec/fixtures/vcr_cassettes/SolidusBolt_Accounts_AddPaymentMethodService/_call/with_wrong_access_token/gives_an_error.yml +179 -0
  115. data/spec/fixtures/vcr_cassettes/SolidusBolt_Accounts_DetailService/_call/with_correct_access_token/receives_a_successful_response.yml +55 -0
  116. data/spec/fixtures/vcr_cassettes/SolidusBolt_Accounts_DetailService/_call/with_wrong_access_token/gives_an_error.yml +55 -0
  117. data/spec/fixtures/vcr_cassettes/SolidusBolt_Accounts_DetectAccountService/_call/receives_the_correct_response.yml +50 -0
  118. data/spec/fixtures/vcr_cassettes/SolidusBolt_Accounts_DetectAccountService/_call/returns_status_200.yml +50 -0
  119. data/spec/fixtures/vcr_cassettes/SolidusBolt_Oauth_TokenService/_call/makes_the_API_call.yml +59 -0
  120. data/spec/fixtures/vcr_cassettes/SolidusBolt_Transactions_AuthorizeService/when_repeat_payment/_call/makes_the_API_call.yml +305 -0
  121. data/spec/fixtures/vcr_cassettes/SolidusBolt_Transactions_AuthorizeService/with_auto_capture/_call/makes_the_API_call.yml +307 -0
  122. data/spec/fixtures/vcr_cassettes/SolidusBolt_Transactions_AuthorizeService/without_auto_capture/_call/makes_the_API_call.yml +252 -0
  123. data/spec/fixtures/vcr_cassettes/SolidusBolt_Transactions_CaptureService/_call/makes_the_API_call.yml +242 -0
  124. data/spec/fixtures/vcr_cassettes/SolidusBolt_Transactions_DetailService/_call/makes_the_API_call.yml +244 -0
  125. data/spec/fixtures/vcr_cassettes/SolidusBolt_Transactions_RefundService/_call/makes_the_API_call.yml +296 -0
  126. data/spec/fixtures/vcr_cassettes/SolidusBolt_Transactions_VoidService/_call/makes_the_API_call.yml +242 -0
  127. data/spec/fixtures/vcr_cassettes/SolidusBolt_Transactions_VoidService/_call/when_transaction_id_is_missing/makes_the_API_call.yml +242 -0
  128. data/spec/fixtures/vcr_cassettes/SolidusBolt_Transactions_VoidService/_call/when_transaction_reference_is_missing/makes_the_API_call.yml +242 -0
  129. data/spec/fixtures/vcr_cassettes/SolidusBolt_Users_SyncAddressesService/_call/adds_the_bill_address_to_the_user.yml +165 -0
  130. data/spec/fixtures/vcr_cassettes/SolidusBolt_Users_SyncAddressesService/_call/adds_the_ship_address_to_the_user.yml +165 -0
  131. data/spec/fixtures/vcr_cassettes/SolidusBolt_Users_SyncPaymentSourcesService/_call/creates_a_new_payment_source_with_card_ID.yml +55 -0
  132. data/spec/fixtures/vcr_cassettes/SolidusBolt_Webhooks_CreateService/_call/with_all_event/returns_a_webhook_id.yml +54 -0
  133. data/spec/fixtures/vcr_cassettes/SolidusBolt_Webhooks_CreateService/_call/with_an_event/returns_a_webhook_id.yml +54 -0
  134. data/spec/fixtures/vcr_cassettes/SolidusBolt_Webhooks_CreateService/_call/with_empty_event/raises_a_server_error.yml +57 -0
  135. data/spec/jobs/solidus_bolt/add_address_job_spec.rb +18 -0
  136. data/spec/models/solidus_bolt/bolt_configuration_spec.rb +173 -0
  137. data/spec/models/solidus_bolt/gateway_spec.rb +130 -0
  138. data/spec/models/solidus_bolt/payment_method_spec.rb +21 -0
  139. data/spec/models/solidus_bolt/payment_source_spec.rb +22 -0
  140. data/spec/requests/solidus_bolt/accounts_controller_spec.rb +41 -0
  141. data/spec/requests/solidus_bolt/webhooks_controller_spec.rb +122 -0
  142. data/spec/requests/spree/admin/bolt_spec.rb +71 -0
  143. data/spec/requests/spree/admin/bolt_webhook_spec.rb +35 -0
  144. data/spec/requests/spree/checkout_controller_spec.rb +117 -0
  145. data/spec/services/solidus_bolt/accounts/add_address_service_spec.rb +45 -0
  146. data/spec/services/solidus_bolt/accounts/add_payment_method_service_spec.rb +47 -0
  147. data/spec/services/solidus_bolt/accounts/detail_service_spec.rb +32 -0
  148. data/spec/services/solidus_bolt/accounts/detect_account_service_spec.rb +15 -0
  149. data/spec/services/solidus_bolt/base_service_spec.rb +49 -0
  150. data/spec/services/solidus_bolt/oauth/token_service_spec.rb +15 -0
  151. data/spec/services/solidus_bolt/payments/capture_sync_service_spec.rb +27 -0
  152. data/spec/services/solidus_bolt/payments/credit_sync_service_spec.rb +38 -0
  153. data/spec/services/solidus_bolt/payments/void_sync_service_spec.rb +25 -0
  154. data/spec/services/solidus_bolt/transactions/authorize_service_spec.rb +117 -0
  155. data/spec/services/solidus_bolt/transactions/base_service_spec.rb +38 -0
  156. data/spec/services/solidus_bolt/transactions/capture_service_spec.rb +37 -0
  157. data/spec/services/solidus_bolt/transactions/detail_service_spec.rb +31 -0
  158. data/spec/services/solidus_bolt/transactions/refund_service_spec.rb +42 -0
  159. data/spec/services/solidus_bolt/transactions/void_service_spec.rb +70 -0
  160. data/spec/services/solidus_bolt/users/refresh_access_token_service_spec.rb +45 -0
  161. data/spec/services/solidus_bolt/users/sync_addresses_service_spec.rb +74 -0
  162. data/spec/services/solidus_bolt/users/sync_payment_sources_service_spec.rb +25 -0
  163. data/spec/services/solidus_bolt/webhooks/create_service_spec.rb +33 -0
  164. data/spec/spec_helper.rb +37 -0
  165. data/spec/support/bolt_configuration.rb +26 -0
  166. data/spec/support/bolt_helper.rb +66 -0
  167. data/spec/support/vcr.rb +29 -0
  168. data/spec/webhooks/solidus_bolt/handlers/base_handler_spec.rb +13 -0
  169. data/spec/webhooks/solidus_bolt/handlers/capture_handler_spec.rb +24 -0
  170. data/spec/webhooks/solidus_bolt/handlers/credit_handler_spec.rb +32 -0
  171. data/spec/webhooks/solidus_bolt/handlers/void_handler_spec.rb +19 -0
  172. data/spec/webhooks/solidus_bolt/sorter_spec.rb +39 -0
  173. metadata +492 -0
@@ -0,0 +1,32 @@
1
+ <% if @bolt_configuration.present? %>
2
+ <table class="index">
3
+ <thead>
4
+ <tr>
5
+ <th><%= SolidusBolt::BoltConfiguration.human_attribute_name(:merchant_public_id) %></th>
6
+ <th><%= SolidusBolt::BoltConfiguration.human_attribute_name(:environment) %></th>
7
+ <th><%= SolidusBolt::BoltConfiguration.human_attribute_name(:created_at) %></th>
8
+ <th><%= SolidusBolt::BoltConfiguration.human_attribute_name(:updated_at) %></th>
9
+ <th class="actions"></th>
10
+ </tr>
11
+ </thead>
12
+ <tbody>
13
+ <tr>
14
+ <td><%= @bolt_configuration.merchant_public_id %></td>
15
+ <td><%= @bolt_configuration.environment %></td>
16
+ <td>
17
+ <%= @bolt_configuration.created_at.to_s(:long) %>
18
+ </td>
19
+ <td>
20
+ <%= @bolt_configuration.updated_at.to_s(:long) %>
21
+ </td>
22
+ <td class="actions">
23
+ <% if can?(:edit, @bolt_configuration) %>
24
+ <%= link_to edit_btn, edit_admin_bolt_path, class: 'btn btn-primary' %>
25
+ <% end %>
26
+ </td>
27
+ </tr>
28
+ </tbody>
29
+ </table>
30
+ <% else %>
31
+ <p> <%= t('spree.admin.bolt.configuration_not_found') %> </p>
32
+ <% end %>
@@ -0,0 +1,29 @@
1
+ <%= render partial: 'spree/shared/error_messages', locals: { target: @bolt_configuration } %>
2
+ <fieldset class="form-group no-border-bottom no-border-top">
3
+ <div class="row">
4
+ <div id="general_fields" class="col-9">
5
+ <div class="row">
6
+ <div class="col-12">
7
+ <%= f.label :environment %>
8
+ <%= f.select :environment, %w[production sandbox staging] %><br />
9
+ <%= f.label :bearer_token %>
10
+ <%= f.text_field :bearer_token, class: 'fullwidth'%>
11
+ <%= f.label 'Merchant Public Id' %><br />
12
+ <%= f.text_field :merchant_public_id, class: 'fullwidth' %>
13
+ <%= f.label 'Division Public Id' %><br />
14
+ <%= f.text_field :division_public_id, class: 'fullwidth' %>
15
+ <%= f.label :api_key %><br />
16
+ <%= f.text_field :api_key, class: 'fullwidth' %>
17
+ <%= f.label :signing_secret %><br />
18
+ <%= f.text_field :signing_secret, class: 'fullwidth' %>
19
+ <%= f.label :publishable_key %><br />
20
+ <%= f.text_field :publishable_key, class: 'fullwidth' %>
21
+ </div>
22
+ </div>
23
+ <div class="row p-2 justify-content-center">
24
+ <%= f.submit submit_name, class: 'btn btn-primary', data: { disable_with: 'Save' } %>
25
+ <%= link_to 'Cancel', admin_bolt_path, class: 'button' %>
26
+ </div>
27
+ </div>
28
+ </div>
29
+ </fieldset>
@@ -0,0 +1,6 @@
1
+ <fieldset class="no-border-bottom">
2
+ <legend align="center"><%= t('spree.admin.bolt.edit_configuration') %></legend>
3
+ <%= form_for @bolt_configuration, url: admin_bolt_path, method: :put do |f| %>
4
+ <%= render partial: 'form', locals: { f: f, submit_name: 'Update' } %>
5
+ <% end %>
6
+ </fieldset>
@@ -0,0 +1,21 @@
1
+ <% admin_breadcrumb(plural_resource_name(SolidusBolt::BoltConfiguration)) %>
2
+
3
+ <% content_for :page_actions do %>
4
+ <% if SolidusBolt::BoltConfiguration.config_empty? %>
5
+ <li>
6
+ <p>Don't have a <%= image_tag "bolt_logo_standard.png", alt: "Bolt", width: "40" %> Merchant account yet?</p>
7
+ </li>
8
+ <li>
9
+ <%= link_to t('spree.admin.bolt.create_merchant_account'), SolidusBolt::BoltConfiguration::REGISTER_URL, class: 'btn btn-primary', target: '_blank' %>
10
+ </li>
11
+ <% else %>
12
+ <li>
13
+ <%= link_to 'Configure Webhooks', new_admin_bolt_webhook_path, class: 'btn btn-primary' %>
14
+ </li>
15
+ <% end %>
16
+ <% end %>
17
+
18
+ <fieldset class="no-border-bottom">
19
+ <legend align="center"><%= t('spree.admin.bolt.configuration') %></legend>
20
+ <%= render partial: 'configuration', locals: { edit_btn: 'Edit' } %>
21
+ </fieldset>
@@ -0,0 +1 @@
1
+ <%= render 'spree/shared/payment/bolt', frontend: false, payment_method: payment_method %>
@@ -0,0 +1,2 @@
1
+ <p>Card Number: <b>XXXX-XXXX-XXXX-<%= @payment.source.card_last4 %></b></p>
2
+ <p>Expiration:<b> <%= @payment.source.card_expiration %></b></p>
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ json.call(payment_source, :id, :created_at, :card_token, :card_last4, :card_bin, :card_number, :card_expiration,
4
+ :card_postal_code, :card_id, :create_bolt_account)
@@ -0,0 +1,7 @@
1
+ <tr id="<%= dom_id(wallet_payment_source, 'spree')%>" class="<%= cycle('even', 'odd') %>">
2
+ <td><%= wallet_payment_source.payment_source.card_last4 %></td>
3
+ <td><%= wallet_payment_source.payment_source.card_expiration %></td>
4
+ <td>
5
+ <%= radio_button_tag "order[wallet_payment_source_id]", wallet_payment_source.id, default, class: "existing-cc-radio" %>
6
+ </td>
7
+ </tr>
@@ -0,0 +1 @@
1
+ <%= render 'spree/shared/payment/bolt', frontend: true, payment_method: payment_method %>
@@ -0,0 +1,19 @@
1
+ <div id="bolt-container"
2
+ data-publishable-key="<%= payment_method.preferred_bolt_publishable_key %>"
3
+ data-payment-method-id="<%= payment_method.id %>"
4
+ data-frontend="<%= frontend %>"
5
+ data-bolt-user-signed-in="<%= spree_current_user&.user_authentications&.where(provider: 'bolt')&.exists? == true %>"
6
+ ></div>
7
+ <div id="payment-status-container" style="display: none;">
8
+ <div id="account-checkbox"></div>
9
+ <br>
10
+ <button id="bolt-submit-button" type="button">Submit</button>
11
+ <br>
12
+ </div>
13
+ <button id="bolt-card-button" type="button">Pay</button>
14
+
15
+ <% unless frontend %>
16
+ <% content_for :head do %>
17
+ <script id="bolt-embedded" type="text/javascript" src="<%= payment_method.preferred_bolt_base_url %>"></script>
18
+ <% end %>
19
+ <% end %>
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusBolt
4
+ module Handlers
5
+ class BaseHandler
6
+ attr_reader :params
7
+
8
+ def initialize(params)
9
+ @params = params
10
+ end
11
+
12
+ def self.call(params)
13
+ new(params).call
14
+ end
15
+
16
+ def call
17
+ raise NotImplementedError, 'Missing #call method on class'
18
+ end
19
+
20
+ private
21
+
22
+ def payment
23
+ Spree::Payment.find_by(response_code: params[:data][:reference])
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusBolt
4
+ module Handlers
5
+ class CaptureHandler < BaseHandler
6
+ def call
7
+ capture_amount = params[:data][:captures].last[:amount][:amount].to_i
8
+
9
+ SolidusBolt::Payments::CaptureSyncService.call(payment: payment, capture_amount: capture_amount)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusBolt
4
+ module Handlers
5
+ class CreditHandler < BaseHandler
6
+ def call
7
+ payment_response_code = params[:data][:source_transaction][:reference]
8
+ source_payment = Spree::Payment.find_by(response_code: payment_response_code)
9
+ amount = params[:data][:requested_refund_amount][:amount].to_i
10
+ refund_transaction_id = params[:data][:reference]
11
+
12
+ SolidusBolt::Payments::CreditSyncService.call(
13
+ payment: source_payment, amount: amount, transaction_id: refund_transaction_id
14
+ )
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusBolt
4
+ module Handlers
5
+ class VoidHandler < BaseHandler
6
+ def call
7
+ SolidusBolt::Payments::VoidSyncService.call(payment: payment)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidusBolt
4
+ class Sorter
5
+ attr_reader :params
6
+
7
+ def self.call(params)
8
+ new(params).call
9
+ end
10
+
11
+ def initialize(params)
12
+ @params = params
13
+ end
14
+
15
+ def call
16
+ handler&.call(params)
17
+ end
18
+
19
+ private
20
+
21
+ def handler
22
+ class_name = "#{event_type.split('.').map(&:capitalize).join}Handler"
23
+
24
+ return unless SolidusBolt::Handlers.const_defined?(class_name)
25
+
26
+ SolidusBolt::Handlers.const_get(class_name)
27
+ end
28
+
29
+ def event_type
30
+ params[:type]
31
+ end
32
+ end
33
+ end
data/bin/console ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require "bundler/setup"
6
+ require "solidus_bolt"
7
+
8
+ # You can add fixtures and/or initialization code here to make experimenting
9
+ # with your gem easier. You can also use a different console, if you like.
10
+ $LOAD_PATH.unshift(*Dir["#{__dir__}/../app/*"])
11
+
12
+ # (If you use this, don't forget to add pry to your Gemfile!)
13
+ # require "pry"
14
+ # Pry.start
15
+
16
+ require "irb"
17
+ IRB.start(__FILE__)
data/bin/rails ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
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_bolt/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,86 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -e
4
+
5
+ case "$DB" in
6
+ postgres|postgresql)
7
+ RAILSDB="postgresql"
8
+ ;;
9
+ mysql)
10
+ RAILSDB="mysql"
11
+ ;;
12
+ sqlite|'')
13
+ RAILSDB="sqlite3"
14
+ ;;
15
+ *)
16
+ echo "Invalid DB specified: $DB"
17
+ exit 1
18
+ ;;
19
+ esac
20
+
21
+ if [ ! -z $SOLIDUS_BRANCH ]
22
+ then
23
+ BRANCH=$SOLIDUS_BRANCH
24
+ else
25
+ BRANCH="master"
26
+ fi
27
+
28
+ extension_name="solidus_bolt"
29
+
30
+ # Stay away from the bundler env of the containing extension.
31
+ function unbundled {
32
+ ruby -rbundler -e'b = proc {system *ARGV}; Bundler.respond_to?(:with_unbundled_env) ? Bundler.with_unbundled_env(&b) : Bundler.with_clean_env(&b)' -- $@
33
+ }
34
+
35
+ rm -rf ./sandbox
36
+ unbundled bundle exec rails new sandbox --database="$RAILSDB" \
37
+ --skip-bundle \
38
+ --skip-git \
39
+ --skip-keeps \
40
+ --skip-rc \
41
+ --skip-spring \
42
+ --skip-test \
43
+ --skip-javascript
44
+
45
+ if [ ! -d "sandbox" ]; then
46
+ echo 'sandbox rails application failed'
47
+ exit 1
48
+ fi
49
+
50
+ cd ./sandbox
51
+ cat <<RUBY >> Gemfile
52
+ gem 'solidus', github: 'solidusio/solidus', branch: '$BRANCH'
53
+ gem 'solidus_auth_devise', '>= 2.1.0'
54
+ gem 'rails-i18n'
55
+ gem 'solidus_i18n'
56
+
57
+ gem '$extension_name', path: '..'
58
+
59
+ group :test, :development do
60
+ platforms :mri do
61
+ gem 'pry-byebug'
62
+ end
63
+ end
64
+ RUBY
65
+
66
+ unbundled bundle install --gemfile Gemfile
67
+
68
+ unbundled bundle exec rake db:drop db:create
69
+
70
+ unbundled bundle exec rails generate solidus:install \
71
+ --auto-accept \
72
+ --user_class=Spree::User \
73
+ --enforce_available_locales=true \
74
+ --with-authentication=false \
75
+ --payment-method=none \
76
+ $@
77
+
78
+ unbundled bundle exec rails generate solidus:auth:install
79
+ unbundled bundle exec rails generate ${extension_name}:install
80
+
81
+ echo
82
+ echo "🚀 Sandbox app successfully created for $extension_name!"
83
+ echo "🚀 Using $RAILSDB and Solidus $BRANCH"
84
+ echo "🚀 Use 'export DB=[postgres|mysql|sqlite]' to control the DB adapter"
85
+ echo "🚀 Use 'export SOLIDUS_BRANCH=<BRANCH-NAME>' to control the Solidus version"
86
+ echo "🚀 This app is intended for test purposes."
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ gem install bundler --conservative
7
+ bundle update
8
+ bin/rake clobber
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ Spree::Backend::Config.configure do |config|
4
+ config.locale = 'en'
5
+
6
+ config.menu_items << config.class::MenuItem.new(
7
+ [:bolt],
8
+ 'bolt',
9
+ condition: -> { can?(:admin, :bolt) },
10
+ url: :admin_bolt_path,
11
+ position: 6,
12
+ match_path: %r{/admin/bolt/}
13
+ )
14
+ end
@@ -0,0 +1,17 @@
1
+ # Sample localization file for English. Add more files in this directory for other locales.
2
+ # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3
+
4
+ en:
5
+ activerecord:
6
+ models:
7
+ solidus_bolt/payment_method: Bolt
8
+ spree:
9
+ admin:
10
+ bolt:
11
+ configuration: 'Bolt Configuration'
12
+ configuration_not_found: 'No Bolt Configuration found'
13
+ edit_configuration: 'Edit Bolt Configuration'
14
+ updated_successfully: 'Bolt Configuration Updated Successfully'
15
+ create_merchant_account: 'Create Merchant Account'
16
+ tab:
17
+ bolt: 'Bolt'
data/config/routes.rb ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ Spree::Core::Engine.routes.draw do
4
+ namespace :admin do
5
+ resource :bolt, only: [:show, :edit, :update]
6
+ resource :bolt_webhook, only: [:new, :create]
7
+ end
8
+
9
+ post '/webhooks/bolt', to: '/solidus_bolt/webhooks#update'
10
+ post '/api/accounts/bolt', to: '/solidus_bolt/accounts#create'
11
+ end
@@ -0,0 +1,16 @@
1
+ class CreateSolidusBoltPaymentSources < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :solidus_bolt_payment_sources do |t|
4
+ t.integer :payment_method_id, index: true
5
+ t.string :transaction_id
6
+ t.string :transaction_reference, null: false
7
+ t.string :transaction_type
8
+ t.string :processor
9
+ t.date :date
10
+ t.string :transaction_status
11
+ t.decimal :amount, precision: 10, scale: 2
12
+ t.string :currency
13
+ t.timestamps
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ class CreateSolidusBoltBoltConfigurations < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :solidus_bolt_bolt_configurations do |t|
4
+ t.string :bearer_token
5
+ t.string :environment_url
6
+ t.string :merchant_public_id
7
+ t.string :merchant_id
8
+ t.string :api_key
9
+ t.string :signing_secret
10
+ t.string :publishable_key
11
+ t.timestamps
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,6 @@
1
+ class SwapUrlForEnvBooleanInBoltConfiguration < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_column :solidus_bolt_bolt_configurations, :environment, :integer
4
+ remove_column :solidus_bolt_bolt_configurations, :environment_url, :string
5
+ end
6
+ end
@@ -0,0 +1,19 @@
1
+ class ReworkSolidusBoltPaymentSources < ActiveRecord::Migration[6.1]
2
+ def change
3
+ remove_column :solidus_bolt_payment_sources, :transaction_id, :string
4
+ remove_column :solidus_bolt_payment_sources, :transaction_reference, :string
5
+ remove_column :solidus_bolt_payment_sources, :transaction_type, :string
6
+ remove_column :solidus_bolt_payment_sources, :processor, :string
7
+ remove_column :solidus_bolt_payment_sources, :date, :date
8
+ remove_column :solidus_bolt_payment_sources, :transaction_status, :string
9
+ remove_column :solidus_bolt_payment_sources, :amount, :decimal
10
+ remove_column :solidus_bolt_payment_sources, :currency, :string
11
+ add_column :solidus_bolt_payment_sources, :card_token, :string
12
+ add_column :solidus_bolt_payment_sources, :card_last4, :string
13
+ add_column :solidus_bolt_payment_sources, :card_bin, :string
14
+ add_column :solidus_bolt_payment_sources, :card_number, :string
15
+ add_column :solidus_bolt_payment_sources, :card_expiration, :string
16
+ add_column :solidus_bolt_payment_sources, :card_postal_code, :string
17
+ add_column :solidus_bolt_payment_sources, :card_id, :string
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ class AddCreateBoltAccountToSolidusBoltPaymentSource < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_column :solidus_bolt_payment_sources, :create_bolt_account, :boolean, default: false
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddUserToSolidusBoltPaymentSource < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_column :solidus_bolt_payment_sources, :user_id, :integer
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class RemoveUserIdFromSolidusBoltPaymentSource < ActiveRecord::Migration[6.1]
2
+ def change
3
+ remove_column :solidus_bolt_payment_sources, :user_id, :integer
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class RenameBoltConfigurationMerchantIdToDivisionPublicId < ActiveRecord::Migration[6.1]
2
+ def change
3
+ rename_column :solidus_bolt_bolt_configurations, :merchant_id, :division_public_id
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class UpdateBoltConfigurationEnvironmentColumnRestrictions < ActiveRecord::Migration[6.1]
2
+ def change
3
+ remove_column :solidus_bolt_bolt_configurations, :environment, :integer
4
+ add_column :solidus_bolt_bolt_configurations, :environment, :integer, null: false, default: 1
5
+ end
6
+ end
data/db/seeds.rb ADDED
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ solidus_bolt_configuration = SolidusBolt::BoltConfiguration.fetch
4
+
5
+ solidus_bolt_configuration.bearer_token = ENV['BOLT_BEARER_TOKEN']
6
+ solidus_bolt_configuration.environment = ENV['BOLT_ENVIRONMENT']
7
+ solidus_bolt_configuration.merchant_public_id = ENV['BOLT_MERCHANT_PUBLIC_ID']
8
+ solidus_bolt_configuration.division_public_id = ENV['BOLT_DIVISION_PUBLIC_ID']
9
+ solidus_bolt_configuration.api_key = ENV['BOLT_API_KEY']
10
+ solidus_bolt_configuration.signing_secret = ENV['BOLT_SIGNING_SECRET']
11
+ solidus_bolt_configuration.publishable_key = ENV['BOLT_PUBLISHABLE_KEY']
12
+
13
+ solidus_bolt_configuration.save
14
+
15
+ Spree::AuthenticationMethod.find_or_create_by(provider: :bolt) do |authentication_method|
16
+ authentication_method.environment = "development"
17
+ authentication_method.provider = "bolt"
18
+ authentication_method.api_key = SolidusBolt::BoltConfiguration.fetch.publishable_key
19
+ authentication_method.api_secret = SolidusBolt::BoltConfiguration.fetch.api_key
20
+ authentication_method.active = true
21
+ end
22
+
23
+ if ENV['BOLT_API_KEY'] && ENV['BOLT_SIGNING_SECRET'] && ENV['BOLT_PUBLISHABLE_KEY']
24
+ SolidusBolt::PaymentMethod.create!(
25
+ type: 'SolidusBolt::PaymentMethod',
26
+ name: 'Bolt',
27
+ preference_source: 'bolt_credentials',
28
+ active: true
29
+ )
30
+ end