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,46 @@
1
+ module Spree
2
+ class Gateway::AcledaMobile < PaymentMethod
3
+ preference :partner_id, :string
4
+ preference :data_encryption_key, :string
5
+ preference :app_url, :string
6
+
7
+ # partial to render the gateway.
8
+ def method_type
9
+ 'acleda_mobile'
10
+ end
11
+
12
+ def payment_source_class
13
+ Spree::VpagoPaymentSource
14
+ end
15
+
16
+ def payment_profiles_supported?
17
+ false
18
+ end
19
+
20
+ # Custom PaymentMethod/Gateway can redefine this method to check method
21
+ # availability for concrete order.
22
+ def available_for_order?(_order)
23
+ true
24
+ end
25
+
26
+ # force to purchase instead of authorize
27
+ def auto_capture?
28
+ true
29
+ end
30
+
31
+ def process(_money, _source, gateway_options)
32
+ Rails.logger.debug { "About to create payment for order #{gateway_options[:order_id]}" }
33
+ # First of all, invalidate all previous tranx orders to prevent multiple paid orders
34
+ # source.save!
35
+ ActiveMerchant::Billing::Response.new(true, 'Order created')
36
+ end
37
+
38
+ def cancel(_response_code)
39
+ # we can use this to send request to payment gateway api to cancel the payment ( void )
40
+ # currently Payway does not support to cancel the gateway
41
+
42
+ # in our case don't do anything
43
+ ActiveMerchant::Billing::Response.new(true, 'Acleda Mobile order has been cancelled.')
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,66 @@
1
+ module Spree
2
+ class Gateway::Payway < PaymentMethod
3
+ # 'abapay', 'cards'
4
+ preference :endpoint, :string
5
+ preference :host, :string
6
+ preference :api_key, :string
7
+ preference :merchant_id, :string
8
+ preference :return_url, :string
9
+ preference :continue_success_url, :string
10
+ preference :payment_option, :string
11
+ preference :transaction_fee_fix, :string
12
+ preference :transaction_fee_percentage, :string
13
+
14
+ # Only enable one-click payments if spree_auth_devise is installed
15
+ # def self.allow_one_click_payments?
16
+ # Gem.loaded_specs.key?('spree_auth_devise')
17
+ # end
18
+
19
+ def payment_source_class
20
+ Spree::VpagoPaymentSource
21
+ end
22
+
23
+ def payment_profiles_supported?
24
+ false
25
+ end
26
+
27
+ def card_type
28
+ if Vpago::Payway::CARD_TYPES.index(preferences[:payment_option]).nil?
29
+ Vpago::Payway::CARD_TYPE_ABAPAY
30
+ else
31
+ preferences[:payment_option]
32
+ end
33
+ end
34
+
35
+ # partial to render the gateway.
36
+ def method_type
37
+ 'payment_payway'
38
+ end
39
+
40
+ # Custom PaymentMethod/Gateway can redefine this method to check method
41
+ # availability for concrete order.
42
+ def available_for_order?(_order)
43
+ true
44
+ end
45
+
46
+ # force to purchase instead of authorize
47
+ def auto_capture?
48
+ true
49
+ end
50
+
51
+ def process(_money, _source, gateway_options)
52
+ Rails.logger.debug { "About to create payment for order #{gateway_options[:order_id]}" }
53
+ # First of all, invalidate all previous tranx orders to prevent multiple paid orders
54
+ # source.save!
55
+ ActiveMerchant::Billing::Response.new(true, 'Order created')
56
+ end
57
+
58
+ def cancel(_response_code, _gateway_options)
59
+ # we can use this to send request to payment gateway api to cancel the payment ( void )
60
+ # currently Payway does not support to cancel the gateway
61
+
62
+ # in our case don't do anything
63
+ ActiveMerchant::Billing::Response.new(true, 'Payway order has been cancelled.')
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,174 @@
1
+ module Spree
2
+ class Gateway::PaywayV2 < PaymentMethod
3
+ preference :host, :string
4
+ preference :api_key, :string
5
+ preference :merchant_id, :string
6
+ preference :payment_option, :string # 'abapay', 'cards', 'abapay_deeplink'
7
+ preference :transaction_fee_fix, :string
8
+ preference :transaction_fee_percentage, :string
9
+ preference :public_key, :text
10
+
11
+ validates :preferred_public_key, presence: true, if: :enable_pre_auth?
12
+
13
+ # override: partial to render in admin
14
+ def method_type
15
+ 'payway_v2'
16
+ end
17
+
18
+ # override
19
+ def default_payout_profile
20
+ Spree::PayoutProfiles::PaywayV2.default
21
+ end
22
+
23
+ # override
24
+ def payment_source_class
25
+ Spree::VpagoPaymentSource
26
+ end
27
+
28
+ # override
29
+ def support_payout? = true
30
+
31
+ # override
32
+ def support_pre_auth? = true
33
+
34
+ # override
35
+ def enable_payout?
36
+ default_payout_profile.present? && default_payout_profile.receivable?
37
+ end
38
+
39
+ # override
40
+ def enable_pre_auth?
41
+ self[:enable_pre_auth]
42
+ end
43
+
44
+ # override
45
+ # authorize payment if pre-auth is enabled, otherwise purchase / complete immediately.
46
+ def auto_capture?
47
+ !enable_pre_auth?
48
+ end
49
+
50
+ # override
51
+ # authorize is used when pre auth enabled
52
+ def authorize(_amount, _source, gateway_options = {})
53
+ _, payment_number = gateway_options[:order_id].split('-')
54
+ payment = Spree::Payment.find_by(number: payment_number)
55
+
56
+ checker = check_transaction(payment)
57
+ payment.update(transaction_response: checker.json_response)
58
+
59
+ if checker.success?
60
+ ActiveMerchant::Billing::Response.new(true, 'Payway Gateway: Authorized')
61
+ else
62
+ ActiveMerchant::Billing::Response.new(false, 'Payway Gateway: Authorization Failed')
63
+ end
64
+ end
65
+
66
+ # override
67
+ # purchase is used when pre auth disabled
68
+ def purchase(_amount, _source, gateway_options = {})
69
+ _, payment_number = gateway_options[:order_id].split('-')
70
+ payment = Spree::Payment.find_by(number: payment_number)
71
+
72
+ checker = check_transaction(payment)
73
+ payment.update(transaction_response: checker.json_response)
74
+
75
+ success = checker.success?
76
+ params = {}
77
+
78
+ success, params[:payout] = confirm_payouts(payment) if success && payout_total_from_response(payment).present?
79
+
80
+ if success
81
+ ActiveMerchant::Billing::Response.new(true, 'Payway Gateway: Purchased', params)
82
+ else
83
+ ActiveMerchant::Billing::Response.new(false, 'Payway Gateway: Purchasing Failed', params)
84
+ end
85
+ end
86
+
87
+ # override
88
+ def capture(_amount, _response_code, gateway_options)
89
+ _, payment_number = gateway_options[:order_id].split('-')
90
+ payment = Spree::Payment.find_by(number: payment_number)
91
+
92
+ success = true
93
+ params = {}
94
+
95
+ success, params[:pre_auth] = complete_pre_auth(payment) if enable_pre_auth?
96
+ success, params[:payout] = confirm_payouts(payment) if success && payout_total_from_response(payment).present?
97
+
98
+ if success
99
+ ActiveMerchant::Billing::Response.new(true, 'Payway Gateway: Captured', params)
100
+ else
101
+ ActiveMerchant::Billing::Response.new(false, 'Payway Gateway: Capture Failed', params)
102
+ end
103
+ end
104
+
105
+ # override
106
+ def void(_response_code, gateway_options)
107
+ _, payment_number = gateway_options[:order_id].split('-')
108
+ payment = Spree::Payment.find_by(number: payment_number)
109
+
110
+ if enable_pre_auth?
111
+ params = {}
112
+ success, params[:pre_auth] = cancel_pre_auth(payment)
113
+
114
+ if success
115
+ ActiveMerchant::Billing::Response.new(true, 'Payway Gateway: Pre-authorization successfully canceled.', params)
116
+ else
117
+ ActiveMerchant::Billing::Response.new(false, 'Payway Gateway: Failed to cancel pre-authorization.', params)
118
+ end
119
+ else
120
+ ActiveMerchant::Billing::Response.new(true, 'Payway Gateway: Payment has been voided.')
121
+ end
122
+ end
123
+
124
+ # override
125
+ def cancel(_response_code, _payment)
126
+ ActiveMerchant::Billing::Response.new(true, 'Payway Gateway: Payment has been canceled.')
127
+ end
128
+
129
+ private
130
+
131
+ def check_transaction(payment)
132
+ checker = Vpago::PaywayV2::TransactionStatus.new(payment)
133
+ checker.call
134
+ checker
135
+ end
136
+
137
+ def cancel_pre_auth(payment)
138
+ canceler = Vpago::PaywayV2::PreAuthCanceler.new(payment)
139
+ canceler.call
140
+
141
+ [canceler.success?, canceler.request_data]
142
+ end
143
+
144
+ def complete_pre_auth(payment)
145
+ completer = Vpago::PaywayV2::PreAuthCompleter.new(payment)
146
+
147
+ completer.call
148
+ [completer.success?, completer.request_data]
149
+ end
150
+
151
+ def confirm_payouts(payment)
152
+ expect_payout_total = payment.payouts.sum(:amount)
153
+ payout_total = payout_total_from_response(payment)
154
+
155
+ confirmed = false
156
+
157
+ if payout_total == expect_payout_total
158
+ payment.payouts.find_each { |payout| payout.update!(state: :confirmed) }
159
+ confirmed = true
160
+ end
161
+
162
+ payout_params = { payout_total: payout_total, expect_payout_total: expect_payout_total }
163
+ [confirmed, payout_params]
164
+ end
165
+
166
+ def payout_total_from_response(payment)
167
+ payouts_response = payment.transaction_response&.dig('payout')
168
+
169
+ return nil if payouts_response.nil? || !payouts_response.is_a?(Array) || payouts_response.empty?
170
+
171
+ payouts_response.map { |payout| payout['amt'].to_f || 0 }.sum
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,51 @@
1
+ module Spree
2
+ class Gateway::WingSdk < PaymentMethod
3
+ preference :username, :string
4
+ preference :biller_code, :string
5
+ preference :rest_api_key, :string
6
+ preference :sandbox, :boolean
7
+ preference :host, :string
8
+ preference :return_url, :string
9
+ preference :transaction_fee_fix, :string
10
+ preference :transaction_fee_percentage, :string
11
+ preference :merchant_name, :string
12
+
13
+ ## for basic authentication on checking transaction on vtenh
14
+ preference :basic_auth_username, :string
15
+ preference :basic_auth_password, :string
16
+
17
+ def payment_source_class
18
+ Spree::VpagoPaymentSource
19
+ end
20
+
21
+ def payment_profiles_supported?
22
+ false
23
+ end
24
+
25
+ # Custom PaymentMethod/Gateway can redefine this method to check method
26
+ # availability for concrete order.
27
+ def available_for_order?(_order)
28
+ true
29
+ end
30
+
31
+ # force to purchase instead of authorize
32
+ def auto_capture?
33
+ true
34
+ end
35
+
36
+ def process(_money, _source, gateway_options)
37
+ Rails.logger.debug { "About to create payment for order #{gateway_options[:order_id]}" }
38
+ # First of all, invalidate all previous tranx orders to prevent multiple paid orders
39
+ # source.save!
40
+ ActiveMerchant::Billing::Response.new(true, 'Order created')
41
+ end
42
+
43
+ def cancel(_response_code)
44
+ # we can use this to send request to payment gateway api to cancel the payment ( void )
45
+ # currently Payway does not support to cancel the gateway
46
+
47
+ # in our case don't do anything
48
+ ActiveMerchant::Billing::Response.new(true, 'Wing Sdk order has been cancelled.')
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,23 @@
1
+ module Spree
2
+ class Payout < Base
3
+ include Metadata
4
+
5
+ belongs_to :payout_profile, class_name: 'Spree::PayoutProfile', required: true, inverse_of: :payouts
6
+ belongs_to :payoutable, required: false, inverse_of: :payouts, polymorphic: true
7
+ belongs_to :payment, class_name: 'Spree::Payment', required: true, inverse_of: :payouts
8
+
9
+ enum state: { created: 0, confirmed: 1 }
10
+
11
+ validates :payout_profile_id, uniqueness: { scope: %i[payoutable_type payoutable_id payment_id] }
12
+
13
+ delegate :currency, to: :payment
14
+
15
+ extend DisplayMoney
16
+ money_methods :amount, :outstanding_amount,
17
+ :amount_owed_to_vendor
18
+
19
+ def amount_owed_to_vendor
20
+ private_metadata&.dig('amount_owed_to_vendor')&.to_f
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,107 @@
1
+ module Spree
2
+ class PayoutProfile < Base
3
+ acts_as_paranoid
4
+
5
+ has_many :payouts, class_name: 'Spree::Payout', inverse_of: :payout_profile
6
+ has_many :payout_profile_products, class_name: 'Spree::PayoutProfileProduct', inverse_of: :payout_profile
7
+ has_many :products, class_name: 'Spree::Product', through: :payout_profile_products
8
+
9
+ has_many :payout_profile_shipping_methods,
10
+ class_name: 'Spree::PayoutProfileShippingMethod',
11
+ inverse_of: :payout_profile
12
+
13
+ has_many :shipping_methods, class_name: 'Spree::ShippingMethod', through: :payout_profile_shipping_methods
14
+
15
+ belongs_to :vendor, class_name: 'Spree::Vendor', optional: true, inverse_of: :payout_profiles
16
+
17
+ validates :type, presence: true
18
+ validates :name, presence: true
19
+ validates :bank_account_number, presence: true, uniqueness: { scope: %i[type vendor_id] }
20
+
21
+ scope :payway, -> { where(type: 'Spree::PayoutProfiles::PaywayV2') }
22
+ scope :verified, -> { where.not(verified_at: nil) }
23
+ scope :active, -> { where(active: true) }
24
+
25
+ before_save :ensure_default_exists_and_clear_vendor
26
+ before_destroy :confirm_destroyable
27
+
28
+ after_update :clear_default_cache, if: :default?
29
+
30
+ self.whitelisted_ransackable_attributes = %w[name vendor_id]
31
+
32
+ def self.default
33
+ Rails.cache.fetch("default_payout_account/#{name.underscore}") do
34
+ find_by(type: name, default: true)
35
+ end
36
+ end
37
+
38
+ def clear_default_cache
39
+ Rails.cache.delete("default_payout_account/#{self.class.name.underscore}")
40
+ end
41
+
42
+ def bank_name
43
+ 'None'
44
+ end
45
+
46
+ def display_name
47
+ display_name = name
48
+
49
+ bank_info = [bank_name, bank_account_number].compact.join(' - ')
50
+ display_name += " (#{bank_info})" unless bank_info.empty?
51
+
52
+ display_name
53
+ end
54
+
55
+ def verified?
56
+ verified_at.present?
57
+ end
58
+
59
+ def receivable?
60
+ verified? && active?
61
+ end
62
+
63
+ def registered_in_bank?
64
+ true
65
+ end
66
+
67
+ def allow_to_verify_with_bank?
68
+ true
69
+ end
70
+
71
+ def verify!(response_data)
72
+ update_columns(
73
+ verified_at: DateTime.current,
74
+ response_data: response_data
75
+ )
76
+ end
77
+
78
+ def reset_verification!
79
+ update_columns(
80
+ verified_at: nil
81
+ )
82
+ end
83
+
84
+ def can_be_deleted?
85
+ self.class.where.not(id: id, type: type).any?
86
+ end
87
+
88
+ private
89
+
90
+ def ensure_default_exists_and_clear_vendor
91
+ if default?
92
+ self.class.where.not(id: id, type: type).update_all(default: false)
93
+ self.vendor_id = nil
94
+ elsif self.class.where(default: true, type: type).count.zero?
95
+ self.default = true
96
+ self.vendor_id = nil
97
+ end
98
+ end
99
+
100
+ def confirm_destroyable
101
+ return if can_be_deleted?
102
+
103
+ errors.add(:base, :cannot_destroy_only_payout_profile)
104
+ throw(:abort)
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,14 @@
1
+ module Spree
2
+ class PayoutProfileProduct < Base
3
+ scope :required, -> { where(optional: false) }
4
+ scope :optional, -> { where(optional: true) }
5
+
6
+ belongs_to :payout_profile, class_name: 'Spree::PayoutProfile', inverse_of: :payout_profile_products
7
+ belongs_to :product, class_name: 'Spree::Product', inverse_of: :payout_profile_products
8
+
9
+ validates :payout_profile, presence: true
10
+ validates :product, presence: true
11
+
12
+ validates :payout_profile_id, uniqueness: { scope: :product_id }
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Spree
2
+ class PayoutProfileShippingMethod < Base
3
+ scope :required, -> { where(optional: false) }
4
+ scope :optional, -> { where(optional: true) }
5
+
6
+ belongs_to :payout_profile, class_name: 'Spree::PayoutProfile', inverse_of: :payout_profile_shipping_methods
7
+ belongs_to :shipping_method, class_name: 'Spree::ShippingMethod', inverse_of: :payout_profile_shipping_methods
8
+
9
+ validates :payout_profile, presence: true
10
+ validates :shipping_method, presence: true
11
+
12
+ validates :payout_profile_id, uniqueness: { scope: :shipping_method_id }
13
+ end
14
+ end
@@ -0,0 +1,40 @@
1
+ module Spree
2
+ module PayoutProfiles
3
+ class PaywayV2 < Spree::PayoutProfile
4
+ preference :base_url, :string
5
+ preference :payee, :string
6
+ preference :merchant_id, :string
7
+ preference :api_key, :string
8
+ preference :rsa_public_key, :text
9
+
10
+ before_validation -> { self.preferred_payee = bank_account_number }
11
+
12
+ # override
13
+ def set_default_preferences
14
+ self.preferred_base_url ||= self.class.default&.preferred_base_url
15
+ self.preferred_merchant_id ||= self.class.default&.preferred_merchant_id
16
+ self.preferred_api_key ||= self.class.default&.preferred_api_key
17
+ self.preferred_rsa_public_key ||= self.class.default&.preferred_rsa_public_key
18
+ end
19
+
20
+ # override
21
+ def registered_in_bank?
22
+ response_data['payee'].present?
23
+ end
24
+
25
+ # override
26
+ def allow_to_verify_with_bank?
27
+ preferred_base_url.present? &&
28
+ preferred_payee.present? &&
29
+ preferred_merchant_id.present? &&
30
+ preferred_api_key.present? &&
31
+ preferred_rsa_public_key.present?
32
+ end
33
+
34
+ # override
35
+ def bank_name
36
+ 'ABA'
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,21 @@
1
+ class Spree::VpagoPaymentSource < Spree::Base
2
+ preference :wing_response, :hash
3
+ preference :acleda_response, :hash
4
+ preference :payway_v2_response, :hash
5
+
6
+ belongs_to :payment_method
7
+ belongs_to :user, class_name: 'Spree::User'
8
+ belongs_to :updated_by_user, class_name: 'Spree::User'
9
+
10
+ has_one :payment, as: :source
11
+
12
+ # validates :updated_reason, presence: true, on: :update
13
+
14
+ def actions
15
+ actions = []
16
+ actions << 'open_checkout' if payment.checkout?
17
+ actions << 'process' if payment.processing? || payment.checkout? || payment.send(:has_invalid_state?)
18
+ actions << 'capture' if payment.pending?
19
+ actions
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ module Vpago
2
+ module AdjustmentDecorator
3
+ def self.prepended(base)
4
+ base.enum handle_by: { store: 0, vendor: 1 }, _prefix: true
5
+
6
+ base.scope :handle_by_vendor, -> { eligible.where(handle_by: :vendor) }
7
+ base.scope :handle_by_store, -> { eligible.where(handle_by: :store) }
8
+
9
+ base.before_save :set_handle_by
10
+
11
+ def base.total
12
+ sum(:amount) || 0
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def set_handle_by
19
+ if source.is_a?(::Spree::PromotionAction)
20
+ self.handle_by = source.run_by
21
+ elsif source.is_a?(::Spree::TaxRate)
22
+ self.handle_by = source.tax_category.collect_by
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ Spree::Adjustment.prepend(Vpago::AdjustmentDecorator) unless Spree::Adjustment.included_modules.include?(Vpago::AdjustmentDecorator)
@@ -0,0 +1,75 @@
1
+ module Vpago
2
+ module LineItemDecorator
3
+ def self.prepended(base)
4
+ base.include ::Vpago::Payoutable
5
+
6
+ base.has_many :payout_profiles, class_name: 'Spree::PayoutProfile', through: :product
7
+ base.has_many :active_payout_profiles, class_name: 'Spree::PayoutProfile', through: :product
8
+ base.has_many :active_payway_payout_profiles, class_name: 'Spree::PayoutProfile', through: :product
9
+
10
+ base.has_many :required_active_payout_profiles, class_name: 'Spree::PayoutProfile', through: :product
11
+
12
+ base.has_one :vendor, through: :variant
13
+ base.has_many :vendor_payment_methods, class_name: 'Spree::PaymentMethod', through: :variant
14
+ end
15
+
16
+ # considred required when there are any required profiles.
17
+ def required_payway_payout?
18
+ required_active_payout_profiles.payway.exists?
19
+ end
20
+
21
+ def commission_rate
22
+ product_commission_rate = product.respond_to?(:commission_rate) ? product.commission_rate : nil
23
+ product_commission_rate || vendor&.commission_rate || 0
24
+ end
25
+
26
+ def commission_amount
27
+ vendor_pre_tax_amount * commission_rate / 100.0
28
+ end
29
+
30
+ # amount expected to receive by vendor
31
+ def pre_commission_amount
32
+ vendor_pre_tax_amount - commission_amount + vendor_tax_total
33
+ end
34
+
35
+ def vendor_pre_tax_amount
36
+ subtotal + vendor_adjustments_total_excluding_tax
37
+ end
38
+
39
+ def vendor_tax_total
40
+ adjustments.tax.handle_by_vendor.total
41
+ end
42
+
43
+ def vendor_adjustments_total_excluding_tax
44
+ vendor_adjustment = adjustments.non_tax.handle_by_vendor.total
45
+ order_vendor_adjustment = if order.line_items_count.positive?
46
+ order.adjustments.non_tax.handle_by_vendor.total / order.line_items_count
47
+ else
48
+ 0
49
+ end
50
+
51
+ order_vendor_adjustment + vendor_adjustment
52
+ end
53
+
54
+ def latest_private_metadata
55
+ private_metadata ||= {}
56
+
57
+ private_metadata[:subtotal] = subtotal.to_f
58
+ private_metadata[:commission_rate] = commission_rate.to_f
59
+ private_metadata[:commission_amount] = commission_amount.to_f
60
+ private_metadata[:vendor_pre_tax_amount] = vendor_pre_tax_amount.to_f
61
+ private_metadata[:pre_commission_amount] = pre_commission_amount.to_f
62
+ private_metadata[:vendor_tax_total] = vendor_tax_total.to_f
63
+ private_metadata[:vendor_adjustments_total_excluding_tax] = vendor_adjustments_total_excluding_tax.to_f
64
+
65
+ private_metadata
66
+ end
67
+
68
+ # generate metadata for financial reports.
69
+ def update_total_metadata
70
+ update_column(:private_metadata, latest_private_metadata)
71
+ end
72
+ end
73
+ end
74
+
75
+ Spree::LineItem.prepend(Vpago::LineItemDecorator) if Spree::LineItem.included_modules.exclude?(Vpago::LineItemDecorator)