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,15 @@
1
+ class CreateSpreePayoutProfileShippingMethods < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table :spree_payout_profile_shipping_methods, if_not_exists: true do |t|
4
+ t.references :payout_profile, foreign_key: { to_table: :spree_payout_profiles },
5
+ index: { name: 'index_payout_profile_shipping_methods_on_payout_profile_id' }
6
+
7
+ t.references :shipping_method, foreign_key: { to_table: :spree_shipping_methods },
8
+ index: { name: 'index_payout_profile_shipping_methods_on_shipping_method_id' }
9
+
10
+ t.boolean :optional, null: false, default: false
11
+
12
+ t.timestamps
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ class AddHandleByToSpreeAdjustments < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_column :spree_adjustments, :handle_by, :integer, null: false, default: 0, if_not_exists: true
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddRunByToSpreePromotionActions < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_column :spree_promotion_actions, :run_by, :integer, null: false, default: 0, if_not_exists: true
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddCollectByToSpreeTaxCategories < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_column :spree_tax_categories, :collect_by, :integer, null: false, default: 0, if_not_exists: true
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddHandleByToSpreeShippingMethod < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_column :spree_shipping_methods, :handle_by, :integer, null: false, default: 0, if_not_exists: true
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddHandleByToSpreeShippingRates < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_column :spree_shipping_rates, :handle_by, :integer, null: false, default: 0, if_not_exists: true
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ class AddVendorReferenceToSpreePaymentMethods < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_reference :spree_payment_methods, :vendor,
4
+ index: true, foreign_key: { to_table: :spree_vendors },
5
+ if_not_exists: true
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ class AddGatewayStatusToSpreePayments < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_column :spree_payments, :gateway_status, :boolean, default: false, if_not_exists: true
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddPreAuthResponseToSpreePayment < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_column :spree_payments, :pre_auth_response, :jsonb, default: {}, if_not_exists: true
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddEnablePreAuthToSpreePaymentMethod < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_column :spree_payment_methods, :enable_pre_auth, :boolean, default: false, if_not_exists: true
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddTransactionResponseToSpreePayments < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_column :spree_payments, :transaction_response, :jsonb, default: {}, if_not_exists: true
4
+ end
5
+ end
data/docs/acleda.md ADDED
@@ -0,0 +1,65 @@
1
+ # ACLEDA
2
+
3
+ From latest document of ACLEDA and [documents](https://drive.google.com/drive/folders/1BusMWt6ul8QbDb1R-2HBz-Gduc0zJk1D), there are 2 types of payments:
4
+ - XPAY (xpay or card)
5
+ - KHQR
6
+
7
+ Both can be created via `Spree::Gateway::Acleda`. Following are instructions to create these payment methods in admin dashboard:
8
+
9
+ ## Getting Start
10
+ To get start, request ACLEDA following:
11
+ - Request credentials (provide them email). They will send us following credentials via email:
12
+ ```
13
+ Merchant ID: AoGxxxxxxxxxxxEVY=
14
+ Merchant name: BOOKMEBUS
15
+ Remote User: remoteuser
16
+ Remote password: Bxxxxxxxxxx3
17
+ ```
18
+ Also note that they are not usually provide the signature key. Signature is a required credential to create acleda session, so you need request them if they are't provided yet.
19
+
20
+ - Request account/app to test:
21
+ - ACLEDA account, for test XPAY. eg. 00010221574410
22
+ - Cards like VISA, master, for XPAY card (pay with card)
23
+ - ACLEDA app & provide them your phone. For scan KHQR.
24
+
25
+ ## Setup Payment Methods
26
+ To setup ACLEDA payment method:
27
+ - Go to admin dashboard /admin/payment_methods/
28
+ - Click on "New Payment Method" and fill details with following instructions & example:
29
+ - Product Name in ACLEDA view. eg. BookMe+
30
+ - Host: https://epaymentuat.acledabank.com.kh:8443
31
+ - Signature: `"Signature" provided by ACLEDA`
32
+ - Payment Expiry Time In Mn: 10
33
+ - Merchant Name: `"Merchant name" provided by ACLEDA`
34
+ - Password: `"Remote password" provided by ACLEDA`
35
+ - Login: `"Remote User" provided by ACLEDA`
36
+ - Merchant: `"Merchant ID" provided by ACLEDA`
37
+ - Success Url: `whitelisted-url`/webhook/acledas/success
38
+ eg. https://example.com/webhook/acledas/success
39
+ - Error Url: `whitelisted-url`/webhook/acledas/error
40
+ - Other Url:`whitelisted-url`/webhook/acledas/return
41
+ - Icon Name: acleda
42
+
43
+ Above are details for overall payment type of ACLEDA, to support it for specific type, insert following details:
44
+
45
+ ### 1. for XPAY
46
+ - Payment Type: XPAY-MPGS
47
+ - Payment Card: 0 - XPAY
48
+
49
+ ### 2. for XPAY (card)
50
+ - Payment Type: XPAY-MPGS
51
+ - Payment Card: 1 - Visa, Master Card, etc.
52
+
53
+ ### 3. for KHQR
54
+ - Payment Type: KHQR
55
+ - Payment Card: (this field is ignored for KHQR, can put anything)
56
+
57
+ ## Merchant Logo
58
+ - To update merchant logo inside ACLEDA view, override following path:
59
+ [app/assets/images/vpago/payway/acleda_merchant_logo_300x300.png](../app/assets/images/vpago/payway/acleda_merchant_logo_300x300.png)
60
+
61
+ ## Expected Outcome
62
+
63
+ | XPAY | XPAY (card) | KHQR |
64
+ | - | - | - |
65
+ | ![xpay](https://github.com/bookmebus/spree_vpago/assets/29684683/c8d7d022-7b1c-4d5c-91e9-d9fe53ea8cec) | ![xpay_card](https://github.com/bookmebus/spree_vpago/assets/29684683/48712fd7-8e3d-4116-b2f6-c3e2adbbe791) | ![khqr](https://github.com/bookmebus/spree_vpago/assets/29684683/5c1290aa-624c-4e36-a879-2e94961346fa) |
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails-controller-testing"
6
+ gem "spree", "~> 3.7.0"
7
+ gem "sass-rails"
8
+
9
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails-controller-testing"
6
+ gem "spree", "~> 4.0.0"
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,9 @@
1
+
2
+ # This file was generated by Appraisal
3
+
4
+ source "https://rubygems.org"
5
+
6
+ gem "rails-controller-testing"
7
+ gem "spree", "~> 4.1.0"
8
+
9
+ gemspec path: "../"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails-controller-testing"
6
+ gem "spree", github: "spree/spree", branch: "master"
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,26 @@
1
+ module SpreeVpago
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ class_option :auto_run_migrations, type: :boolean, default: false
5
+ source_root File.expand_path('templates', __dir__)
6
+
7
+ def add_migrations
8
+ run 'bundle exec rake railties:install:migrations FROM=spree_multi_vendor'
9
+ run 'bundle exec rake railties:install:migrations FROM=spree_vpago'
10
+ end
11
+
12
+ def acleda_logo_template
13
+ template 'app/assets/images/vpago/payway/acleda_merchant_logo_300x300.png'
14
+ end
15
+
16
+ def run_migrations
17
+ run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask('Would you like to run the migrations now? [Y/n]'))
18
+ if run_migrations
19
+ run 'bundle exec rails db:migrate'
20
+ else
21
+ puts 'Skipping rails db:migrate, don\'t forget to run it!'
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,36 @@
1
+ module SpreeVpago
2
+ class Engine < Rails::Engine
3
+ require 'spree/core'
4
+ isolate_namespace Spree
5
+ engine_name 'spree_vpago'
6
+
7
+ config.autoload_paths += %W[#{config.root}/lib]
8
+
9
+ # use rspec for tests
10
+ config.generators do |g|
11
+ g.test_framework :rspec
12
+ end
13
+
14
+ initializer 'spree_vpago.environment', before: :load_config_initializers do |_app|
15
+ Config = Configuration.new # rubocop:disable Lint/ConstantDefinitionInBlock
16
+ end
17
+
18
+ config.after_initialize do
19
+ Rails.application.config.spree.payment_methods.push(
20
+ Spree::Gateway::Payway,
21
+ Spree::Gateway::PaywayV2,
22
+ Spree::Gateway::WingSdk,
23
+ Spree::Gateway::Acleda,
24
+ Spree::Gateway::AcledaMobile
25
+ )
26
+ end
27
+
28
+ def self.activate
29
+ Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c|
30
+ Rails.configuration.cache_classes ? require(c) : load(c)
31
+ end
32
+ end
33
+
34
+ config.to_prepare(&method(:activate).to_proc)
35
+ end
36
+ end
@@ -0,0 +1,6 @@
1
+ FactoryBot.define do
2
+ # Define your Spree extensions Factories within this file to enable applications, and other extensions to use and override them.
3
+ #
4
+ # Example adding this to your spec_helper will load these Factories for use:
5
+ # require 'spree_vpago/factories'
6
+ end
@@ -0,0 +1,9 @@
1
+ module SpreeVpago
2
+ module_function
3
+
4
+ VERSION = '0.1.0-beta'.freeze
5
+
6
+ def version
7
+ Gem::Version.new VERSION
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ require 'spree_core'
2
+ require 'spree_multi_vendor'
3
+ require 'spree_extension'
4
+ require 'spree_vpago/engine'
5
+ require 'spree_vpago/version'
@@ -0,0 +1,111 @@
1
+ module Vpago
2
+ module Acleda
3
+ class Base
4
+ include Vpago::PaymentAmountCalculator
5
+
6
+ def initialize(payment, options = {})
7
+ @options = options
8
+ @payment = payment
9
+ end
10
+
11
+ def payment_number
12
+ @payment.number
13
+ end
14
+
15
+ def app_checkout
16
+ app_checkout? ? '1' : '0'
17
+ end
18
+
19
+ def app_checkout?
20
+ return false if @options[:app_checkout].blank?
21
+
22
+ @options[:app_checkout]
23
+ end
24
+
25
+ def host
26
+ @payment.payment_method.preferences[:host]
27
+ end
28
+
29
+ def success_url
30
+ preferred_success_url = @payment.payment_method.preferred_success_url
31
+ return nil if preferred_success_url.blank?
32
+
33
+ query_string = {
34
+ app_checkout:,
35
+ order_number:,
36
+ order_channel: @payment.order.channel
37
+ }.to_query
38
+
39
+ "#{preferred_success_url}?#{query_string}"
40
+ end
41
+
42
+ def error_url
43
+ preferred_error_url = @payment.payment_method.preferred_error_url
44
+ return nil if preferred_error_url.blank?
45
+
46
+ query_string = {
47
+ app_checkout:,
48
+ order_number:
49
+ }.to_query
50
+
51
+ "#{preferred_error_url}?#{query_string}"
52
+ end
53
+
54
+ def other_url
55
+ preferred_other_url = @payment.payment_method.preferred_other_url
56
+ return nil if preferred_other_url.blank?
57
+
58
+ query_string = {
59
+ app_checkout:,
60
+ order_number:
61
+ }.to_query
62
+
63
+ "#{preferred_other_url}?#{query_string}"
64
+ end
65
+
66
+ def acleda_company_name
67
+ @payment.payment_method.preferences[:acleda_company_name]
68
+ end
69
+
70
+ def acleda_payment_card
71
+ @payment.payment_method.preferences[:acleda_payment_card]
72
+ end
73
+
74
+ def login_id
75
+ @payment.payment_method.preferences[:login_id]
76
+ end
77
+
78
+ def password
79
+ @payment.payment_method.preferences[:password]
80
+ end
81
+
82
+ def merchant_id
83
+ @payment.payment_method.preferences[:merchant_id]
84
+ end
85
+
86
+ def merchant_name
87
+ @payment.payment_method.preferences[:merchant_name]
88
+ end
89
+
90
+ def signature
91
+ @payment.payment_method.preferences[:signature]
92
+ end
93
+
94
+ def expiry_time
95
+ @payment.payment_method.preferences[:payment_expiry_time_in_mn]
96
+ end
97
+
98
+ def purchase_date
99
+ @payment.created_at.strftime('%d-%m-%Y')
100
+ end
101
+
102
+ def order_number
103
+ @payment.order.number
104
+ end
105
+
106
+ def action_url
107
+ "#{host}/#{merchant_name}/paymentPage.jsp"
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,105 @@
1
+ module Vpago
2
+ module Acleda
3
+ class Checkout < Base
4
+ attr_accessor :error_message
5
+
6
+ def initialize(payment, options = {})
7
+ super
8
+
9
+ @error_message = nil
10
+ start_connection
11
+ update_payment_source
12
+ end
13
+
14
+ def start_connection
15
+ @response = create_session
16
+
17
+ if @response.status != 500 && @response.status != 200
18
+ @error_message = 'Sever Error'
19
+ elsif @response.status == 500 ## mostly when passing wrong parameter name
20
+ @error_message = @response.body
21
+ elsif @response.status == 200 && json_response['result']['code'] != 0 ## mostly when passing invalid payload, wrong loginId, etc.
22
+ @error_message = json_response['result']['errorDetails']
23
+ end
24
+ end
25
+
26
+ def update_payment_source
27
+ return if failed?
28
+
29
+ @payment.source.update_column(:transaction_id, json_response['result']['xTran']['paymentTokenid'])
30
+ end
31
+
32
+ def json_response
33
+ @json_response ||= JSON.parse(@response.body)
34
+ end
35
+
36
+ def create_session
37
+ con = Faraday::Connection.new(url: host)
38
+
39
+ con.post(create_session_path) do |request|
40
+ request.headers['Content-Type'] = 'application/json'
41
+ request.body = create_session_request_body.to_json
42
+ end
43
+ end
44
+
45
+ def failed?
46
+ @error_message.present?
47
+ end
48
+
49
+ def create_session_request_body
50
+ request_body = {
51
+ loginId: login_id,
52
+ password:,
53
+ merchantID: merchant_id,
54
+ signature:,
55
+ xpayTransaction: {
56
+ txid: payment_number,
57
+ invoiceid: order_number,
58
+ purchaseAmount: amount_with_fee,
59
+ purchaseCurrency: 'USD',
60
+ purchaseDate: purchase_date,
61
+ purchaseDesc: 'items',
62
+ item: '1',
63
+ quantity: '1',
64
+ expiryTime: expiry_time,
65
+ otherUrl: other_url
66
+ }
67
+ }
68
+
69
+ if @payment.payment_method.xpay_mpgs?
70
+ request_body[:xpayTransaction][:paymentCard] = acleda_payment_card if acleda_payment_card.present?
71
+ elsif @payment.payment_method.khqr?
72
+ request_body[:xpayTransaction][:operationType] = '3'
73
+ end
74
+
75
+ request_body
76
+ end
77
+
78
+ def create_session_path
79
+ ENV.fetch('ACLEDA_CREATE_SESSION_PATH', nil)
80
+ end
81
+
82
+ def gateway_params
83
+ return {} if failed?
84
+
85
+ {
86
+ merchantID: merchant_id,
87
+ sessionid: json_response['result']['sessionid'],
88
+ paymenttokenid: json_response['result']['xTran']['paymentTokenid'],
89
+ description: 'items',
90
+ expirytime: expiry_time,
91
+ amount: amount_with_fee,
92
+ quantity: '1',
93
+ Item: '1',
94
+ invoiceid: order_number,
95
+ currencytype: 'USD',
96
+ transactionID: payment_number,
97
+ successUrlToReturn: success_url,
98
+ errorUrl: error_url,
99
+ companyName: acleda_company_name,
100
+ companyLogo: ActionController::Base.helpers.image_url('vpago/payway/acleda_merchant_logo_300x300.png')
101
+ }
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,74 @@
1
+ module Vpago
2
+ module Acleda
3
+ class DeeplinkCheckout < Base
4
+ attr_accessor :error_message, :results
5
+
6
+ def call
7
+ @results = {
8
+ play_store: acleda_play_store,
9
+ app_store: acleda_app_store,
10
+ acleda_ios_deeplink: acleda_ios_deeplink,
11
+ acleda_android_deeplink: acleda_android_deeplink
12
+ }
13
+ end
14
+
15
+ def acleda_app_store
16
+ 'https://apps.apple.com/us/app/acleda-unity-toanchet/id1196285236'
17
+ end
18
+
19
+ def acleda_play_store
20
+ 'market://details?id=com.domain.acledabankqr'
21
+ end
22
+
23
+ def acleda_ios_deeplink
24
+ "ACLEDAmobile://?partner_id=#{partner_id}&payment_data=#{aes_encrypted_payment_data}"
25
+ end
26
+
27
+ def acleda_android_deeplink
28
+ "market://com.domain.acledabankqr/app?partner_id=#{partner_id}&payment_data=#{aes_encrypted_payment_data}"
29
+ end
30
+
31
+ def hmac_encrypted_payment_data
32
+ json_data = payment_data.to_json
33
+ key = encryption_key
34
+
35
+ encrypted_result = Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), key, json_data))
36
+ encrypted_result.delete!("\n")
37
+ encrypted_result
38
+ end
39
+
40
+ def aes_encrypted_payment_data
41
+ data = "#{payment_data.to_json}~#{hmac_encrypted_payment_data}"
42
+ key = encryption_key
43
+ iv = [key].pack('H*') # #hex2bin
44
+ cipher = OpenSSL::Cipher.new('AES-256-CBC')
45
+ cipher.encrypt
46
+
47
+ cipher.key = pbkdf2_key
48
+ cipher.iv = iv
49
+
50
+ crypt = cipher.update(data) + cipher.final
51
+ encrypted_result = Base64.encode64(crypt).delete("\n")
52
+ encrypted_result.gsub('/', 'acledabankSecurityTC') # #follow acleda encrypting guide
53
+ end
54
+
55
+ def payment_data
56
+ {
57
+ app_name: 'VTENH',
58
+ payment_amount: amount_with_fee,
59
+ payment_amount_ccy: 'USD',
60
+ payment_purpose: 'VTENH Transaction',
61
+ txn_ref: payment_number
62
+ }
63
+ end
64
+
65
+ def pbkdf2_key
66
+ pass = encryption_key
67
+ salt = pass
68
+ iter = 100
69
+ key_len = 32
70
+ OpenSSL::KDF.pbkdf2_hmac(pass, salt:, iterations: iter, length: key_len, hash: 'sha1')
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,38 @@
1
+ module Vpago
2
+ module Acleda
3
+ class PaymentRequestUpdater < ::Vpago::PaymentRequestUpdater
4
+ def call
5
+ return if @payment.order.paid?
6
+
7
+ checker = payment_status_checker
8
+
9
+ if checker.success?
10
+ @error_message = nil
11
+ checker_result = {
12
+ status: true,
13
+ description: nil,
14
+ acleda_response: checker.result
15
+ }
16
+ marker_options = @options.merge(checker_result)
17
+
18
+ marker = ::Vpago::PaymentStatusMarker.new(@payment, marker_options)
19
+ marker.call
20
+ elsif !ignore_on_failed?
21
+ @error_message = checker.error_message
22
+ marker_options = @options.merge(status: false, description: @error_message)
23
+
24
+ marker = ::Vpago::PaymentStatusMarker.new(@payment, marker_options)
25
+ marker.call
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def payment_status_checker
32
+ trans_status = Vpago::Acleda::TransactionStatus.new(@payment)
33
+ trans_status.call
34
+ trans_status
35
+ end
36
+ end
37
+ end
38
+ end