spree_vpago 0.1.0.pre.beta

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 (262) hide show
  1. checksums.yaml +7 -0
  2. data/.env.example +3 -0
  3. data/.github/workflows/test_and_publish_gem.yml +96 -0
  4. data/.gitignore +24 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +56 -0
  7. data/.ruby-version +1 -0
  8. data/.tool-versions +1 -0
  9. data/.travis.yml +45 -0
  10. data/Appraisals +20 -0
  11. data/Gemfile +27 -0
  12. data/Gemfile.lock +656 -0
  13. data/LICENSE +26 -0
  14. data/README.md +151 -0
  15. data/Rakefile +21 -0
  16. data/app/.gitkeep +0 -0
  17. data/app/assets/config/spree_vpago_manifest.js +3 -0
  18. data/app/assets/images/backend-process.svg +3 -0
  19. data/app/assets/images/vpago/payway/abapay.png +0 -0
  20. data/app/assets/images/vpago/payway/cards.png +0 -0
  21. data/app/assets/javascripts/vpago/vpago_payments/request_process_payment.js +44 -0
  22. data/app/assets/javascripts/vpago/vpago_payments/user_informers/firebase.js +15802 -0
  23. data/app/controllers/.gitkeep +0 -0
  24. data/app/controllers/spree/acleda_redirects_controller.rb +22 -0
  25. data/app/controllers/spree/admin/payment_methods_controller_decorator.rb +65 -0
  26. data/app/controllers/spree/admin/payment_payway_base_controller.rb +25 -0
  27. data/app/controllers/spree/admin/payment_payway_checkers_controller.rb +34 -0
  28. data/app/controllers/spree/admin/payment_payway_markers_controller.rb +44 -0
  29. data/app/controllers/spree/admin/payment_payway_queriers_controller.rb +39 -0
  30. data/app/controllers/spree/admin/payment_wing_sdk_base_controller.rb +21 -0
  31. data/app/controllers/spree/admin/payment_wing_sdk_checkers_controller.rb +26 -0
  32. data/app/controllers/spree/admin/payment_wing_sdk_markers_controller.rb +36 -0
  33. data/app/controllers/spree/admin/payment_wing_sdk_queriers_controller.rb +20 -0
  34. data/app/controllers/spree/admin/payments_controller_decorator.rb +19 -0
  35. data/app/controllers/spree/admin/payout_profile_products_controller.rb +21 -0
  36. data/app/controllers/spree/admin/payout_profile_shipping_methods_controller.rb +21 -0
  37. data/app/controllers/spree/admin/payout_profiles_controller.rb +91 -0
  38. data/app/controllers/spree/admin/payouts_controller.rb +16 -0
  39. data/app/controllers/spree/api/v2/storefront/checkout_controller_decorator.rb +84 -0
  40. data/app/controllers/spree/payway_card_popups_controller.rb +20 -0
  41. data/app/controllers/spree/payway_results_controller.rb +11 -0
  42. data/app/controllers/spree/payway_v2_card_popups_controller.rb +20 -0
  43. data/app/controllers/spree/vpago_payments_controller.rb +71 -0
  44. data/app/controllers/spree/webhook/acleda_mobiles_controller.rb +88 -0
  45. data/app/controllers/spree/webhook/acledas_controller.rb +80 -0
  46. data/app/controllers/spree/webhook/base_controller.rb +6 -0
  47. data/app/controllers/spree/webhook/payways_controller.rb +77 -0
  48. data/app/controllers/spree/webhook/wings_controller.rb +63 -0
  49. data/app/controllers/spree/wing/base_controller.rb +29 -0
  50. data/app/controllers/spree/wing/transactions_controller.rb +27 -0
  51. data/app/controllers/spree/wing_redirects_controller.rb +20 -0
  52. data/app/helpers/vpago/admin/base_helper_decorator.rb +40 -0
  53. data/app/helpers/vpago/vpago_payments_helper.rb +12 -0
  54. data/app/javascripts/vpago/vpago_payments/user_informers/firebase.js +62 -0
  55. data/app/jobs/application_unique_job.rb +1 -0
  56. data/app/jobs/vpago/payment_processor_job.rb +8 -0
  57. data/app/models/.gitkeep +0 -0
  58. data/app/models/concerns/vpago/payoutable.rb +11 -0
  59. data/app/models/spree/gateway/acleda.rb +63 -0
  60. data/app/models/spree/gateway/acleda_mobile.rb +46 -0
  61. data/app/models/spree/gateway/payway.rb +66 -0
  62. data/app/models/spree/gateway/payway_v2.rb +174 -0
  63. data/app/models/spree/gateway/wing_sdk.rb +51 -0
  64. data/app/models/spree/payout.rb +23 -0
  65. data/app/models/spree/payout_profile.rb +107 -0
  66. data/app/models/spree/payout_profile_product.rb +14 -0
  67. data/app/models/spree/payout_profile_shipping_method.rb +14 -0
  68. data/app/models/spree/payout_profiles/payway_v2.rb +40 -0
  69. data/app/models/spree/vpago_payment_source.rb +21 -0
  70. data/app/models/vpago/adjustment_decorator.rb +28 -0
  71. data/app/models/vpago/line_item_decorator.rb +75 -0
  72. data/app/models/vpago/order_decorator.rb +78 -0
  73. data/app/models/vpago/payment_decorator.rb +44 -0
  74. data/app/models/vpago/payment_method_decorator.rb +91 -0
  75. data/app/models/vpago/payouts_generator.rb +125 -0
  76. data/app/models/vpago/product_decorator.rb +30 -0
  77. data/app/models/vpago/promotion_action_decorator.rb +9 -0
  78. data/app/models/vpago/shipment_decorator.rb +23 -0
  79. data/app/models/vpago/shipping_method_decorator.rb +33 -0
  80. data/app/models/vpago/shipping_rate_decorator.rb +25 -0
  81. data/app/models/vpago/store_decorator.rb +17 -0
  82. data/app/models/vpago/tax_category_decorator.rb +9 -0
  83. data/app/models/vpago/variant_decorator.rb +22 -0
  84. data/app/models/vpago/vendor_decorator.rb +10 -0
  85. data/app/overrides/spree/admin/adjustments/_adjustment/handle_by_table_body.html.erb.deface +11 -0
  86. data/app/overrides/spree/admin/adjustments/_adjustments_table/handle_by_table_header.html.erb.deface +3 -0
  87. data/app/overrides/spree/admin/adjustments/_form/handle_by_field.html.erb.deface +10 -0
  88. data/app/overrides/spree/admin/orders/_shipment/edit_method.html.erb.deface +26 -0
  89. data/app/overrides/spree/admin/orders/_shipment/show_method.html.erb.deface +27 -0
  90. data/app/overrides/spree/admin/payment_methods/_form/enable_pre_auth_field.html.erb.deface +17 -0
  91. data/app/overrides/spree/admin/payment_methods/_form/vendor_field.html.erb.deface +6 -0
  92. data/app/overrides/spree/admin/payment_methods/index/list.html.erb.deface +45 -0
  93. data/app/overrides/spree/admin/payment_methods/index/payment_methods_tabs.html.erb.deface +9 -0
  94. data/app/overrides/spree/admin/payment_methods/index/vendor_body.html.erb.deface +5 -0
  95. data/app/overrides/spree/admin/payment_methods/index/vendor_header.html.erb.deface +5 -0
  96. data/app/overrides/spree/admin/payments/_list/actions.html.erb.deface +13 -0
  97. data/app/overrides/spree/admin/promotions/_promotion_action/run_by_field.html.erb.deface +13 -0
  98. data/app/overrides/spree/admin/shared/_order_tabs/payouts.html.erb.deface +8 -0
  99. data/app/overrides/spree/admin/shared/_product_tabs/payout_profile_products.html.erb.deface +8 -0
  100. data/app/overrides/spree/admin/shared/sub_menu/_integrations/payout_profiles.html.erb.deface +3 -0
  101. data/app/overrides/spree/admin/shipping_methods/_form/handle_by.html.erb.deface +12 -0
  102. data/app/overrides/spree/admin/shipping_methods/edit/shipping_method_tabs.html.erb.deface +3 -0
  103. data/app/overrides/spree/admin/tax_categories/_form/collect_by_field.html.erb.deface +10 -0
  104. data/app/overrides/spree/admin/tax_categories/index/collect_by_table_body.html.erb.deface +4 -0
  105. data/app/overrides/spree/admin/tax_categories/index/collect_by_table_header.html.erb.deface +4 -0
  106. data/app/serializers/spree/api/v2/platform/vpago_payment_source_serializer.rb +11 -0
  107. data/app/serializers/spree/v2/storefront/payment_method_serializer_decorator.rb +23 -0
  108. data/app/serializers/spree/v2/storefront/payment_redirect_serializer.rb +13 -0
  109. data/app/serializers/spree/v2/storefront/payment_serializer_decorator.rb +13 -0
  110. data/app/serializers/spree/v2/storefront/vpago_payment_source_serializer.rb +9 -0
  111. data/app/services/.gitkeep +0 -0
  112. data/app/services/vpago/payment_finder.rb +27 -0
  113. data/app/services/vpago/payment_processor.rb +72 -0
  114. data/app/services/vpago/payment_redirect_handler.rb +194 -0
  115. data/app/services/vpago/payment_url_constructor.rb +32 -0
  116. data/app/services/vpago/payments/find_or_create.rb +51 -0
  117. data/app/services/vpago/payout_profiles/payway/base_payout_profile_request.rb +38 -0
  118. data/app/services/vpago/payout_profiles/payway/open_ssl_encrypter.rb +31 -0
  119. data/app/services/vpago/payout_profiles/payway/payout_profile_request_creator.rb +50 -0
  120. data/app/services/vpago/payout_profiles/payway/payout_profile_request_params_builder.rb +58 -0
  121. data/app/services/vpago/payout_profiles/payway/payout_profile_request_updater.rb +28 -0
  122. data/app/services/vpago/payway_return_options_builder.rb +39 -0
  123. data/app/services/vpago/user_informers/firebase.rb +52 -0
  124. data/app/views/.gitkeep +0 -0
  125. data/app/views/layouts/acleda.html.erb +18 -0
  126. data/app/views/layouts/payway.html.erb +24 -0
  127. data/app/views/layouts/payway_v2.html.erb +18 -0
  128. data/app/views/layouts/vpago_payments.html.erb +18 -0
  129. data/app/views/layouts/wing.html.erb +18 -0
  130. data/app/views/spree/_payment_icon.html.erb +25 -0
  131. data/app/views/spree/acleda_redirects/show.html.erb +3 -0
  132. data/app/views/spree/admin/payments/source_forms/_payment_payway.html.erb +4 -0
  133. data/app/views/spree/admin/payments/source_forms/_payway_v2.html.erb +7 -0
  134. data/app/views/spree/admin/payments/source_views/_acleda.html.erb +1 -0
  135. data/app/views/spree/admin/payments/source_views/_acleda_mobile.html.erb +1 -0
  136. data/app/views/spree/admin/payments/source_views/_payment_payway.html.erb +98 -0
  137. data/app/views/spree/admin/payments/source_views/_payway_v2.html.erb +5 -0
  138. data/app/views/spree/admin/payments/source_views/_vpago_payment_tmpl.html.erb +113 -0
  139. data/app/views/spree/admin/payments/source_views/_wingsdk.html.erb +5 -0
  140. data/app/views/spree/admin/payout_profile_products/_form.html.erb +28 -0
  141. data/app/views/spree/admin/payout_profile_products/edit.html.erb +18 -0
  142. data/app/views/spree/admin/payout_profile_products/index.html.erb +58 -0
  143. data/app/views/spree/admin/payout_profile_products/new.html.erb +22 -0
  144. data/app/views/spree/admin/payout_profile_shipping_methods/_form.html.erb +28 -0
  145. data/app/views/spree/admin/payout_profile_shipping_methods/edit.html.erb +22 -0
  146. data/app/views/spree/admin/payout_profile_shipping_methods/index.html.erb +6 -0
  147. data/app/views/spree/admin/payout_profile_shipping_methods/new.html.erb +27 -0
  148. data/app/views/spree/admin/payout_profiles/_filter.html.erb +19 -0
  149. data/app/views/spree/admin/payout_profiles/_form.html.erb +72 -0
  150. data/app/views/spree/admin/payout_profiles/edit.html.erb +33 -0
  151. data/app/views/spree/admin/payout_profiles/index.html.erb +63 -0
  152. data/app/views/spree/admin/payout_profiles/new.html.erb +13 -0
  153. data/app/views/spree/admin/payouts/_line_item_info_with_popover.html.erb +43 -0
  154. data/app/views/spree/admin/payouts/index.html.erb +46 -0
  155. data/app/views/spree/admin/shared/_payment_methods_tabs.html.erb +15 -0
  156. data/app/views/spree/admin/shared/_shipping_method_tabs.html.erb +19 -0
  157. data/app/views/spree/admin/shared/payout_profile/_info_card.html.erb +24 -0
  158. data/app/views/spree/admin/shared/payout_profile/_status.html.erb +11 -0
  159. data/app/views/spree/checkout/payment/_acleda.html.erb +1 -0
  160. data/app/views/spree/checkout/payment/_acleda_checkout_form.html.erb +14 -0
  161. data/app/views/spree/checkout/payment/_acleda_mobile.html.erb +0 -0
  162. data/app/views/spree/checkout/payment/_payment_payway.html.erb +21 -0
  163. data/app/views/spree/checkout/payment/_payway_loader.html.erb +2 -0
  164. data/app/views/spree/checkout/payment/_payway_root.html.erb +9 -0
  165. data/app/views/spree/checkout/payment/_payway_script.html.erb +77 -0
  166. data/app/views/spree/checkout/payment/_payway_v2.html.erb +1 -0
  167. data/app/views/spree/checkout/payment/_payway_v2_loader.html.erb +2 -0
  168. data/app/views/spree/checkout/payment/_payway_v2_root.html.erb +9 -0
  169. data/app/views/spree/checkout/payment/_payway_v2_script.html.erb +79 -0
  170. data/app/views/spree/checkout/payment/_wing_checkout_form.html.erb +18 -0
  171. data/app/views/spree/checkout/payment/_wingsdk.html.erb +1 -0
  172. data/app/views/spree/checkout/payment/acleda_form.html.erb +3 -0
  173. data/app/views/spree/checkout/payment/payway_form.html.erb +10 -0
  174. data/app/views/spree/checkout/payment/payway_v2_form.html.erb +10 -0
  175. data/app/views/spree/checkout/payment/wingsdk_form.html.erb +3 -0
  176. data/app/views/spree/payway_card_popups/_form.html.erb +10 -0
  177. data/app/views/spree/payway_card_popups/show.html.erb +5 -0
  178. data/app/views/spree/payway_results/failed.html.erb +1 -0
  179. data/app/views/spree/payway_results/success.html.erb +1 -0
  180. data/app/views/spree/payway_v2_card_popups/_form.html.erb +15 -0
  181. data/app/views/spree/payway_v2_card_popups/show.html.erb +3 -0
  182. data/app/views/spree/vpago_payments/checkout.html.erb +3 -0
  183. data/app/views/spree/vpago_payments/forms/spree/gateway/_payway_v2.html.erb +13 -0
  184. data/app/views/spree/vpago_payments/processing.html.erb +49 -0
  185. data/app/views/spree/vpago_payments/success.html.erb +3 -0
  186. data/app/views/spree/wing_redirects/show.html.erb +3 -0
  187. data/bin/rails +8 -0
  188. data/build.js +9 -0
  189. data/config/initializers/assets.rb +1 -0
  190. data/config/initializers/spree_permitted_attributes.rb +5 -0
  191. data/config/locales/en.yml +28 -0
  192. data/config/locales/km.yml +24 -0
  193. data/config/routes.rb +92 -0
  194. data/db/migrate/20210128040625_create_spree_vpago_payment_sources.rb +14 -0
  195. data/db/migrate/20210430052432_add_fields_to_payment_sources.rb +7 -0
  196. data/db/migrate/20210824044737_add_preference_to_spree_vpago_payment_source.rb +5 -0
  197. data/db/migrate/20240506095140_create_spree_payout_profiles.rb +22 -0
  198. data/db/migrate/20240506095148_create_spree_payout_profile_products.rb +10 -0
  199. data/db/migrate/20240523070757_add_optional_spere_payout_profile_products.rb +5 -0
  200. data/db/migrate/20240715091228_create_spree_payouts.rb +25 -0
  201. data/db/migrate/20240718195510_create_spree_payout_profile_shipping_methods.rb +15 -0
  202. data/db/migrate/20240718201453_add_handle_by_to_spree_adjustments.rb +5 -0
  203. data/db/migrate/20240718201509_add_run_by_to_spree_promotion_actions.rb +5 -0
  204. data/db/migrate/20240718201523_add_collect_by_to_spree_tax_categories.rb +5 -0
  205. data/db/migrate/20240718201538_add_handle_by_to_spree_shipping_method.rb +5 -0
  206. data/db/migrate/20240718201554_add_handle_by_to_spree_shipping_rates.rb +5 -0
  207. data/db/migrate/20240808102853_add_vendor_reference_to_spree_payment_methods.rb +7 -0
  208. data/db/migrate/20240904030132_add_gateway_status_to_spree_payments.rb +5 -0
  209. data/db/migrate/20241029071959_add_pre_auth_response_to_spree_payment.rb +5 -0
  210. data/db/migrate/20241202104014_add_enable_pre_auth_to_spree_payment_method.rb +5 -0
  211. data/db/migrate/20250121044614_add_transaction_response_to_spree_payments.rb +5 -0
  212. data/docs/acleda.md +65 -0
  213. data/gemfiles/spree_3_7.gemfile +9 -0
  214. data/gemfiles/spree_4_0.gemfile +8 -0
  215. data/gemfiles/spree_4_1.gemfile +9 -0
  216. data/gemfiles/spree_master.gemfile +8 -0
  217. data/lib/generators/spree_vpago/install/install_generator.rb +26 -0
  218. data/lib/generators/spree_vpago/install/templates/app/assets/images/vpago/payway/acleda_merchant_logo_300x300.png +0 -0
  219. data/lib/spree_vpago/engine.rb +36 -0
  220. data/lib/spree_vpago/factories.rb +6 -0
  221. data/lib/spree_vpago/version.rb +9 -0
  222. data/lib/spree_vpago.rb +5 -0
  223. data/lib/vpago/acleda/base.rb +111 -0
  224. data/lib/vpago/acleda/checkout.rb +105 -0
  225. data/lib/vpago/acleda/deeplink_checkout.rb +74 -0
  226. data/lib/vpago/acleda/payment_request_updater.rb +38 -0
  227. data/lib/vpago/acleda/transaction_status.rb +71 -0
  228. data/lib/vpago/acleda_mobile/base.rb +28 -0
  229. data/lib/vpago/acleda_mobile/callback_validator.php +35 -0
  230. data/lib/vpago/acleda_mobile/callback_validator.rb +38 -0
  231. data/lib/vpago/acleda_mobile/checkout.rb +78 -0
  232. data/lib/vpago/acleda_mobile/payment_request_updater.rb +34 -0
  233. data/lib/vpago/acleda_mobile/payment_retriever.rb +24 -0
  234. data/lib/vpago/acleda_mobile/transaction_status.rb +35 -0
  235. data/lib/vpago/payment_amount_calculator.rb +23 -0
  236. data/lib/vpago/payment_request_updater.rb +19 -0
  237. data/lib/vpago/payment_status_marker.rb +109 -0
  238. data/lib/vpago/payway/base.rb +112 -0
  239. data/lib/vpago/payway/checkout.rb +24 -0
  240. data/lib/vpago/payway/payment_request_updater.rb +31 -0
  241. data/lib/vpago/payway/payment_status_marker.rb +84 -0
  242. data/lib/vpago/payway/transaction_status.rb +74 -0
  243. data/lib/vpago/payway.rb +13 -0
  244. data/lib/vpago/payway_v2/base.rb +153 -0
  245. data/lib/vpago/payway_v2/checkout.rb +35 -0
  246. data/lib/vpago/payway_v2/payment_request_updater.rb +65 -0
  247. data/lib/vpago/payway_v2/payouts_params_constructor.rb +47 -0
  248. data/lib/vpago/payway_v2/pre_auth_canceler.rb +43 -0
  249. data/lib/vpago/payway_v2/pre_auth_completer.rb +76 -0
  250. data/lib/vpago/payway_v2/transaction_status.rb +85 -0
  251. data/lib/vpago/wing_sdk/base.rb +58 -0
  252. data/lib/vpago/wing_sdk/checkout.rb +20 -0
  253. data/lib/vpago/wing_sdk/payment_request_updater.rb +46 -0
  254. data/lib/vpago/wing_sdk/payment_retriever.rb +34 -0
  255. data/lib/vpago/wing_sdk/transaction_status_checker.rb +64 -0
  256. data/lib/vpago/wing_sdk/transaction_status_response.rb +33 -0
  257. data/node_modules/.yarn-integrity +147 -0
  258. data/package-lock.json +1491 -0
  259. data/package.json +10 -0
  260. data/spree_vpago.gemspec +33 -0
  261. data/yarn.lock +921 -0
  262. metadata +403 -0
@@ -0,0 +1,45 @@
1
+ <!-- replace ".table-responsive" -->
2
+
3
+ <div class="table-responsive border rounded bg-white">
4
+ <table class="table sortable" id='listing_payment_methods' data-hook data-sortable-link="<%= update_positions_admin_payment_methods_url %>">
5
+ <thead class="text-muted">
6
+ <tr data-hook="admin_payment_methods_index_headers">
7
+ <th></th>
8
+ <th><%= Spree.t(:name) %></th>
9
+ <th><%= Spree.t(:provider) %></th>
10
+ <th class="text-center"><%= Spree.t(:transaction_type) %></th>
11
+ <th class="text-center"><%= Spree.t(:display) %></th>
12
+ <th class="text-center"><%= Spree.t(:active) %></th>
13
+ <th data-hook="admin_payment_methods_index_header_actions" class="actions"></th>
14
+ </tr>
15
+ </thead>
16
+ <tbody id="sortVert">
17
+ <% @payment_methods.each do |method| %>
18
+ <tr id="<%= spree_dom_id method %>" data-hook="admin_payment_methods_index_rows">
19
+ <td class="move-handle text-center">
20
+ <% if can?(:edit, method) %>
21
+ <%= svg_icon name: "grip-vertical.svg", width: '18', height: '18' %>
22
+ <% end %>
23
+ </td>
24
+ <td><%= method.name %></td>
25
+ <td><%= method.type.split('::', 3).last %></td>
26
+ <td class="text-center">
27
+ <% if method.enable_pre_auth? %>
28
+ <span class="badge badge-pill badge-info">Pre-Auth</span>
29
+ <% else %>
30
+ <span class="badge badge-pill badge-success">Purchase</span>
31
+ <% end %>
32
+ </td>
33
+ <td class="text-center"><%= Spree.t("admin.display_on.#{method.display_on}") %></td>
34
+ <td class="text-center"><%= active_badge(method.active) %></td>
35
+ <td data-hook="admin_payment_methods_index_row_actions" class="actions">
36
+ <span class="d-flex justify-content-end">
37
+ <%= link_to_edit(method, no_text: true) if can? :edit, method %>
38
+ <%= link_to_delete(method, no_text: true) if can? :delete, method %>
39
+ </span>
40
+ </td>
41
+ </tr>
42
+ <% end %>
43
+ </tbody>
44
+ </table>
45
+ </div>
@@ -0,0 +1,9 @@
1
+ <!-- insert_before "erb[silent]:contains('content_for :page_actions')" -->
2
+
3
+ <%= render partial: 'spree/admin/shared/payment_methods_tabs' %>
4
+
5
+ <% if params[:tab] == 'vendors' %>
6
+ <div class="alert alert-info mb-3">
7
+ <%= svg_icon name: "info-circle.svg", classes: 'mr-2', width: '16', height: '16' %> Payment methods for each vendor. Once set, only those payment methods will be displayed to user.
8
+ </div>
9
+ <% end %>
@@ -0,0 +1,5 @@
1
+ <!-- insert_before "[data-hook='admin_payment_methods_index_row_actions']" -->
2
+
3
+ <% if params[:tab] == 'vendors' %>
4
+ <td class="text-center"><%= method.vendor&.name || 'N/A' %></td>
5
+ <% end %>
@@ -0,0 +1,5 @@
1
+ <!-- insert_before "[data-hook='admin_payment_methods_index_header_actions']" -->
2
+
3
+ <% if params[:tab] == 'vendors' %>
4
+ <th class="text-center"><%= Spree.t(:vendor) %></th>
5
+ <% end %>
@@ -0,0 +1,13 @@
1
+ <!-- replace ".payment-action-buttons" -->
2
+
3
+ <span class="d-flex justify-content-center payment-action-buttons">
4
+ <% payment.actions.each do |action| %>
5
+ <% if action == 'credit' %>
6
+ <%= link_to_with_icon('exit.svg', Spree.t(:refund), new_admin_order_payment_refund_path(@order, payment), no_text: true, class: "btn btn-light btn-sm") if can?(:create, Spree::Refund) %>
7
+ <% elsif action == 'open_checkout' %>
8
+ <%= link_to_with_icon('qr-code.svg', Spree.t(action), payment.checkout_url, target: '_blank', no_text: true, class: "btn btn-light btn-sm") %>
9
+ <% else %>
10
+ <%= link_to_with_icon(action + '.svg', Spree.t(action), fire_admin_order_payment_path(@order, payment, e: action), method: :put, no_text: true, data: { action: action }, class: "btn btn-light btn-sm") if can?(action.to_sym, payment) %>
11
+ <% end %>
12
+ <% end %>
13
+ </span>
@@ -0,0 +1,13 @@
1
+ <!-- insert_after "erb[loud]:contains('hidden_field_tag')" -->
2
+
3
+ <div class="form-group card-body mb-0 pb-0">
4
+ <% field_name = "#{param_prefix}[run_by]" %>
5
+ <%= label_tag field_name do %>
6
+ <span class="mr-1" type="button" data-toggle="popover" data-trigger="hover" data-placement="left" data-content="This promotion is covered by <%= promotion_action.run_by %>. This information is crucial for the financial report.">
7
+ <%= svg_icon name: "info-circle-fill.svg", width: '12', height: '12' %>
8
+ </span>
9
+ <%= Spree.t(:run_by) %>
10
+ <% end %>
11
+ <%= select_tag field_name, options_from_collection_for_select(Spree::PromotionAction.run_bies.keys, :to_s, :capitalize, promotion_action.run_by),
12
+ class: 'type-select select2' %>
13
+ </div>
@@ -0,0 +1,8 @@
1
+ <!-- insert_after "[data-hook='admin_order_tabs_payments']" -->
2
+
3
+ <li class="nav-item" data-hook='admin_order_tabs_payouts'>
4
+ <%= link_to_with_icon 'wallet2.svg',
5
+ Spree.t(:payouts),
6
+ admin_order_payouts_url(@order),
7
+ class: "#{'active' if current == :payouts} nav-link" %>
8
+ </li>
@@ -0,0 +1,8 @@
1
+ <!-- insert_after "erb[silent]:contains('Spree::Price')" -->
2
+
3
+ <%= content_tag :li, class: 'nav-item' do %>
4
+ <%= link_to_with_icon 'wallet2.svg',
5
+ Spree.t(:payout),
6
+ admin_product_payout_profile_products_url(@product),
7
+ class: "nav-link #{'active' if current == :payout_profile_products}" %>
8
+ <% end if can?(:admin, Spree::PayoutProfileProduct) %>
@@ -0,0 +1,3 @@
1
+ <!-- insert_bottom "[data-hook='admin_integrations']" -->
2
+
3
+ <%= tab :payout_profiles, match_path: '/payout_profiles', label: 'Payout Profiles' if can? :manage, Spree::PayoutProfiles %>
@@ -0,0 +1,12 @@
1
+ <!-- insert_before "[data-hook='admin_shipping_method_form_display_field']" -->
2
+
3
+ <div data-hook="admin_shipping_method_form_handle_by_field" class="col-12 col-lg-6">
4
+ <%= f.field_container :handle_by do %>
5
+ <%= f.label :handle_by, raw(Spree.t(:handle_by) + required_span_tag) %>
6
+ <%= f.select :handle_by, Spree::ShippingMethod.handle_bies.keys.map {|item| [item.capitalize, item]}, {}, :class => "fullwidth select2" %>
7
+ <%= f.error_message_on :handle_by %>
8
+ <small class="form-text text-muted">
9
+ This information is crucial for the financial report.
10
+ </small>
11
+ <% end %>
12
+ </div>
@@ -0,0 +1,3 @@
1
+ <!-- insert_before "[data-hook='admin_shipping_method_edit_form_header']" -->
2
+
3
+ <%= render partial: 'spree/admin/shared/shipping_method_tabs', locals: { current: :edit } %>
@@ -0,0 +1,10 @@
1
+ <!-- insert_top "[data-hook='admin_tax_category_form_fields']" -->
2
+
3
+ <%= f.field_container :collect_by do %>
4
+ <%= f.label :collect_by, raw(Spree.t(:collect_by) + required_span_tag) %>
5
+ <%= f.select :collect_by, Spree::TaxCategory.collect_bies.keys.map {|item| [item.capitalize, item]}, {}, :class => "fullwidth select2" %>
6
+ <%= f.error_message_on :collect_by %>
7
+ <small class="form-text text-muted">
8
+ This information is crucial for the financial report.
9
+ </small>
10
+ <% end %>
@@ -0,0 +1,4 @@
1
+ <!-- insert_top "[data-hook='tax_row']" -->
2
+
3
+ <td><%= tax_category.id %></td>
4
+ <td class="text-center"><%= tax_category.collect_by.to_s.capitalize %></td>
@@ -0,0 +1,4 @@
1
+ <!-- insert_top "[data-hook='tax_header']" -->
2
+
3
+ <th><%= Spree.t(:id) %></th>
4
+ <th class="text-center"><%= Spree.t(:collect_by) %></th>
@@ -0,0 +1,11 @@
1
+ module Spree
2
+ module Api
3
+ module V2
4
+ module Platform
5
+ class VpagoPaymentSourceSerializer < BaseSerializer
6
+ set_type :vpago_payment_source
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ module Spree
2
+ module V2
3
+ module Storefront
4
+ module PaymentMethodSerializerDecorator
5
+ def self.prepended(base)
6
+ base.attribute :icon_name do |payment_method|
7
+ return nil if payment_method.preferences.blank?
8
+
9
+ payment_method.preferences[:icon_name]
10
+ end
11
+
12
+ base.attribute :payment_option do |payment_method|
13
+ pref = payment_method.preferences
14
+
15
+ pref.blank? || pref[:payment_option].blank? ? payment_method.method_type : pref[:payment_option]
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ Spree::V2::Storefront::PaymentMethodSerializer.prepend(Spree::V2::Storefront::PaymentMethodSerializerDecorator)
@@ -0,0 +1,13 @@
1
+ module Spree
2
+ module V2
3
+ module Storefront
4
+ class PaymentRedirectSerializer < BaseSerializer
5
+ set_type :payment_redirect
6
+
7
+ attributes :id, :amount, :response_code, :number, :state,
8
+ :payment_method_id, :payment_method_type, :payment_method_name,
9
+ :redirect_options, :gateway_params, :action_url
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Spree
2
+ module V2
3
+ module Storefront
4
+ module PaymentSerializerDecorator
5
+ def self.prepended(base)
6
+ base.attributes :pre_auth_status, :checkout_url
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
12
+
13
+ Spree::V2::Storefront::PaymentSerializer.prepend(Spree::V2::Storefront::PaymentSerializerDecorator)
@@ -0,0 +1,9 @@
1
+ module Spree
2
+ module V2
3
+ module Storefront
4
+ class VpagoPaymentSourceSerializer < BaseSerializer
5
+ set_type :vpago_payment_source
6
+ end
7
+ end
8
+ end
9
+ end
File without changes
@@ -0,0 +1,27 @@
1
+ module Vpago
2
+ class PaymentFinder
3
+ attr_reader :params_hash
4
+
5
+ def initialize(params_hash)
6
+ @params_hash = params_hash
7
+ end
8
+
9
+ def find_and_verify
10
+ find_and_verify!
11
+ rescue StandardError, ActiveRecord::RecordNotFound => e
12
+ Rails.logger.error("PaymentJwtVerifier#find_and_verify error: #{e.class} - #{e.message}")
13
+ nil
14
+ end
15
+
16
+ def find_and_verify!
17
+ order = Spree::Order.find_by!(number: params_hash[:order_number])
18
+ verify_jwt!(order)
19
+
20
+ Spree::Payment.find_by!(number: params_hash[:payment_number])
21
+ end
22
+
23
+ def verify_jwt!(order)
24
+ JWT.decode(params_hash[:order_jwt_token], order.token, 'HS256')
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,72 @@
1
+ module Vpago
2
+ class PaymentProcessor
3
+ attr_accessor :payment, :error
4
+
5
+ def initialize(payment:)
6
+ @payment = payment
7
+ @error = nil
8
+ end
9
+
10
+ def call
11
+ process_payment!
12
+ return process_order if payment.completed? || payment.pending?
13
+
14
+ mark_payment_process_failed
15
+ rescue Spree::Core::GatewayError, StateMachines::InvalidTransition => e
16
+ mark_payment_process_failed(e.message)
17
+ end
18
+
19
+ private
20
+
21
+ def process_payment!
22
+ user_informer.payment_is_processing(processing: true)
23
+ payment.process!
24
+ end
25
+
26
+ def process_order
27
+ user_informer.order_is_processing(processing: true)
28
+ completer = Spree::Checkout::Complete.new.call(order: payment.order)
29
+
30
+ if completer.success?
31
+ mark_order_process_completed
32
+ else
33
+ mark_order_process_failed(completer.error.to_s)
34
+ end
35
+ end
36
+
37
+ def mark_order_process_completed
38
+ payment.capture! if payment.pending?
39
+ user_informer.order_is_completed(processing: false)
40
+ end
41
+
42
+ def mark_order_process_failed(message)
43
+ user_informer.order_process_failed(processing: payment.pending?, log_message: message)
44
+
45
+ if payment.pending?
46
+ payment.void_transaction!
47
+ user_informer.payment_is_refunded(processing: false)
48
+ end
49
+
50
+ failure(message)
51
+ end
52
+
53
+ def mark_payment_process_failed(message = nil)
54
+ message ||= Spree.t(:payment_process_failed)
55
+
56
+ user_informer.payment_process_failed(processing: false, log_message: message)
57
+ failure(message)
58
+ end
59
+
60
+ def user_informer
61
+ @user_informer ||= ::Vpago::UserInformers::Firebase.new(payment.order)
62
+ end
63
+
64
+ def success?
65
+ @error.nil?
66
+ end
67
+
68
+ def failure(error)
69
+ @error = error
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,194 @@
1
+ require 'faraday'
2
+
3
+ module Vpago
4
+ class PaymentRedirectHandler
5
+ include ActiveModel::Serialization
6
+
7
+ attr_accessor :redirect_options, :error_message
8
+ attr_reader :payment, :gateway_params, :action_url, :vapgo_checkout_service,
9
+ :override_return_deeplink_url
10
+
11
+ delegate :id, :amount, :response_code, :number, :state,
12
+ :payment_method_id, :payment_method_name,
13
+ to: :payment
14
+
15
+ def initialize(payment:, override_return_deeplink_url: nil)
16
+ @payment = payment
17
+ @override_return_deeplink_url = override_return_deeplink_url
18
+
19
+ @vapgo_checkout_service = payment.payment_method.vapgo_checkout_service.presence&.new(
20
+ payment,
21
+ { override_return_deeplink_url: override_return_deeplink_url }
22
+ )
23
+
24
+ @gateway_params = vapgo_checkout_service&.gateway_params
25
+ @action_url = vapgo_checkout_service&.action_url
26
+ end
27
+
28
+ def process
29
+ validate_payment
30
+ check_and_process_payment
31
+
32
+ self
33
+ end
34
+
35
+ def check_and_process_payment
36
+ @payment.process!
37
+
38
+ if payment_method.type_payway_v2?
39
+ process_aba_v2_gateway
40
+ elsif payment_method.type_payway?
41
+ process_aba_gateway
42
+ elsif payment_method.type_wingsdk?
43
+ process_wing_gateway
44
+ elsif payment_method.type_acleda?
45
+ process_acleda_gateway
46
+ elsif payment_method.type_acleda_mobile?
47
+ process_acleda_mobile
48
+ end
49
+ end
50
+
51
+ def process_acleda_gateway
52
+ data = {
53
+ href: "#{ENV.fetch('DEFAULT_URL_HOST', nil)}/acleda_redirects?payment_number=#{@payment.number}"
54
+ }
55
+
56
+ @redirect_options = data
57
+ end
58
+
59
+ def process_acleda_mobile
60
+ service = Vpago::AcledaMobile::Checkout.new(@payment)
61
+ service.call
62
+
63
+ @redirect_options = service.results
64
+ end
65
+
66
+ def process_aba_v2_gateway
67
+ payment_option = @payment.payment_method.preferences[:payment_option]
68
+
69
+ if %w[abapay abapay_khqr_deeplink].include?(payment_option)
70
+ process_abapay_v2_deeplink
71
+ else
72
+ # construct web url for render web view.
73
+ # same implementation for alipay, wechat, cards, abapay_khqr.
74
+
75
+ # - for abapay_khqr: in web view, it renders QR then request to open intent://ababank.com?... for app to open ABA app.
76
+ # - for others: it only renders QR
77
+ process_payway_v2_card
78
+ end
79
+ end
80
+
81
+ def process_payway_v2_card
82
+ ## TO DO: generate redirect url
83
+ data = {
84
+ href: "#{ENV.fetch('DEFAULT_URL_HOST', nil)}/payway_v2_card_popups?payment_number=#{@payment.number}"
85
+ }
86
+
87
+ @redirect_options = data
88
+ end
89
+
90
+ def process_abapay_v2_deeplink
91
+ response = send_process_payway_v2_payment
92
+
93
+ return unless response.status == 200
94
+
95
+ json_response = JSON.parse(response.body)
96
+
97
+ if json_response['status']['code'] == '00'
98
+ @redirect_options = json_response
99
+ else
100
+ @error_message = json_response['description']
101
+ end
102
+ end
103
+
104
+ def send_process_payway_v2_payment
105
+ options = {
106
+ app_checkout: true,
107
+ override_return_deeplink_url:
108
+ }
109
+
110
+ abapay_payment = ::Vpago::PaywayV2::Checkout.new(@payment, options)
111
+ gateway_params = abapay_payment.gateway_params
112
+
113
+ conn = Faraday::Connection.new do |faraday|
114
+ faraday.request :url_encoded
115
+ end
116
+
117
+ conn.post(abapay_payment.checkout_url, gateway_params) do |request|
118
+ request.headers['Referer'] = ENV.fetch('DEFAULT_URL_HOST', nil)
119
+ end
120
+ end
121
+
122
+ def process_aba_gateway
123
+ payment_option = @payment.payment_method.preferences[:payment_option]
124
+ payment_option == 'abapay' ? process_abapay_deeplink : process_payway_card
125
+ end
126
+
127
+ def process_payway_card
128
+ ## TO DO: generate redirect url
129
+ data = {
130
+ href: "#{ENV.fetch('DEFAULT_URL_HOST', nil)}/payway_card_popups?payment_number=#{@payment.number}"
131
+ }
132
+
133
+ @redirect_options = data
134
+ end
135
+
136
+ def process_wing_gateway
137
+ data = {
138
+ href: "#{ENV.fetch('DEFAULT_URL_HOST', nil)}/wing_redirects?payment_number=#{@payment.number}"
139
+ }
140
+
141
+ @redirect_options = data
142
+ end
143
+
144
+ def process_abapay_deeplink
145
+ send_process_payment
146
+
147
+ return unless @response.status == 200
148
+
149
+ json_response = JSON.parse(@response.body)
150
+
151
+ if json_response['status'] == '0'
152
+ @redirect_options = json_response
153
+ else
154
+ @error_message = json_response['description']
155
+ end
156
+ end
157
+
158
+ def send_process_payment
159
+ options = {
160
+ app_checkout: true
161
+ }
162
+
163
+ abapay_payment = ::Vpago::Payway::Checkout.new(@payment, options)
164
+ gateway_params = abapay_payment.gateway_params
165
+ gateway_params[:payment_option] = 'abapay_deeplink'
166
+
167
+ conn = Faraday::Connection.new do |faraday|
168
+ faraday.request :url_encoded
169
+ end
170
+
171
+ @response = conn.post(abapay_payment.action_url, gateway_params) do |request|
172
+ request.headers['Referer'] = ENV.fetch('DEFAULT_URL_HOST', nil)
173
+ end
174
+ end
175
+
176
+ def validate_payment
177
+ raise ActiveRecord::RecordNotFound if !payment_valid || !payment_method.vpago_payment?
178
+
179
+ true
180
+ end
181
+
182
+ def payment_method
183
+ @payment.payment_method
184
+ end
185
+
186
+ def payment_method_type
187
+ payment_method.type
188
+ end
189
+
190
+ def payment_valid
191
+ !::Spree::Payment::INVALID_STATES.include?(@payment.state)
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,32 @@
1
+ require 'google/cloud/firestore'
2
+
3
+ module Vpago
4
+ class PaymentUrlConstructor
5
+ attr_accessor :payment, :order
6
+
7
+ def initialize(payment)
8
+ @payment = payment
9
+ @order = payment.order
10
+ end
11
+
12
+ def checkout_url = "#{base_url}/vpago_payments/checkout?#{query}"
13
+ def processing_url = "#{base_url}/vpago_payments/processing?#{query}"
14
+ def success_url = "#{base_url}/vpago_payments/success?#{query}"
15
+ def process_payment_url = "#{base_url}/vpago_payments/process_payment?#{query}"
16
+
17
+ def query
18
+ { payment_number: payment.number, order_number: order.number, order_jwt_token: order_jwt_token }.to_query
19
+ end
20
+
21
+ private
22
+
23
+ def base_url
24
+ ENV.fetch('DEFAULT_URL_HOST')
25
+ end
26
+
27
+ def order_jwt_token
28
+ payload = { order_number: order.number, order_id: order.id }
29
+ JWT.encode(payload, order.token, 'HS256')
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,51 @@
1
+ # Replacement for Spree::Payments::Create. To look for existing payment instead of always create new one.
2
+ module Vpago
3
+ module Payments
4
+ class FindOrCreate
5
+ prepend Spree::ServiceModule::Base
6
+
7
+ def call(order:, params: {}) # rubocop:disable Lint/UnusedMethodArgument
8
+ ApplicationRecord.transaction do
9
+ run :find_payment_method
10
+ run :find_or_create_payment
11
+ end
12
+ end
13
+
14
+ def find_payment_method(order:, params:)
15
+ payment_method = order.available_payment_methods.find { |pm| pm.id.to_s == params[:payment_method_id]&.to_s }
16
+ return failure(nil, :payment_method_not_found) if payment_method.blank?
17
+
18
+ success(order: order, params: params, payment_method: payment_method)
19
+ end
20
+
21
+ def find_or_create_payment(order:, params:, payment_method:)
22
+ payment = order.payments.find_or_initialize_by(
23
+ state: :checkout,
24
+ amount: order.order_total_after_store_credit,
25
+ payment_method: payment_method
26
+ )
27
+
28
+ if payment_method&.source_required? && payment.source.blank?
29
+ source_attributes = {
30
+ payment_option: params[:payment_option],
31
+ payment_method_id: payment_method.id,
32
+ user_id: order.user&.id,
33
+ gateway_payment_profile_id: params[:gateway_payment_profile_id],
34
+ gateway_customer_profile_id: params[:gateway_customer_profile_id],
35
+ last_digits: params[:last_digits],
36
+ month: params[:month],
37
+ year: params[:year],
38
+ name: params[:name]
39
+ }.compact
40
+
41
+ payment.source = payment_method.payment_source_class.new(source_attributes)
42
+ payment.save!
43
+ end
44
+
45
+ return failure(payment) if payment.errors.any?
46
+
47
+ success(order: order)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,38 @@
1
+ require 'faraday'
2
+
3
+ module Vpago
4
+ module PayoutProfiles
5
+ module Payway
6
+ class BasePayoutProfileRequest
7
+ attr_reader :profile, :base_url, :error_messages
8
+
9
+ # to be override
10
+ def request_path; end
11
+
12
+ def initialize(profile)
13
+ @base_url = profile.preferred_base_url
14
+ @profile = profile
15
+ @error_messages = []
16
+ end
17
+
18
+ def connection
19
+ Faraday::Connection.new(url: base_url)
20
+ end
21
+
22
+ def request_to_payway
23
+ response = connection.post(request_path) do |request|
24
+ request.headers['language'] = 'en'
25
+ request.headers['Content-Type'] = 'application/json'
26
+ request.body = PayoutProfileRequestParamsBuilder.new(Date.current, profile).request_params.to_json
27
+ end
28
+
29
+ json_response = JSON.parse(response.body)
30
+
31
+ @error_messages << response.body if json_response.nil? || json_response['status'].nil?
32
+
33
+ json_response
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end