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.
- checksums.yaml +7 -0
- data/.env.example +3 -0
- data/.github/workflows/test_and_publish_gem.yml +96 -0
- data/.gitignore +24 -0
- data/.rspec +3 -0
- data/.rubocop.yml +56 -0
- data/.ruby-version +1 -0
- data/.tool-versions +1 -0
- data/.travis.yml +45 -0
- data/Appraisals +20 -0
- data/Gemfile +27 -0
- data/Gemfile.lock +656 -0
- data/LICENSE +26 -0
- data/README.md +151 -0
- data/Rakefile +21 -0
- data/app/.gitkeep +0 -0
- data/app/assets/config/spree_vpago_manifest.js +3 -0
- data/app/assets/images/backend-process.svg +3 -0
- data/app/assets/images/vpago/payway/abapay.png +0 -0
- data/app/assets/images/vpago/payway/cards.png +0 -0
- data/app/assets/javascripts/vpago/vpago_payments/request_process_payment.js +44 -0
- data/app/assets/javascripts/vpago/vpago_payments/user_informers/firebase.js +15802 -0
- data/app/controllers/.gitkeep +0 -0
- data/app/controllers/spree/acleda_redirects_controller.rb +22 -0
- data/app/controllers/spree/admin/payment_methods_controller_decorator.rb +65 -0
- data/app/controllers/spree/admin/payment_payway_base_controller.rb +25 -0
- data/app/controllers/spree/admin/payment_payway_checkers_controller.rb +34 -0
- data/app/controllers/spree/admin/payment_payway_markers_controller.rb +44 -0
- data/app/controllers/spree/admin/payment_payway_queriers_controller.rb +39 -0
- data/app/controllers/spree/admin/payment_wing_sdk_base_controller.rb +21 -0
- data/app/controllers/spree/admin/payment_wing_sdk_checkers_controller.rb +26 -0
- data/app/controllers/spree/admin/payment_wing_sdk_markers_controller.rb +36 -0
- data/app/controllers/spree/admin/payment_wing_sdk_queriers_controller.rb +20 -0
- data/app/controllers/spree/admin/payments_controller_decorator.rb +19 -0
- data/app/controllers/spree/admin/payout_profile_products_controller.rb +21 -0
- data/app/controllers/spree/admin/payout_profile_shipping_methods_controller.rb +21 -0
- data/app/controllers/spree/admin/payout_profiles_controller.rb +91 -0
- data/app/controllers/spree/admin/payouts_controller.rb +16 -0
- data/app/controllers/spree/api/v2/storefront/checkout_controller_decorator.rb +84 -0
- data/app/controllers/spree/payway_card_popups_controller.rb +20 -0
- data/app/controllers/spree/payway_results_controller.rb +11 -0
- data/app/controllers/spree/payway_v2_card_popups_controller.rb +20 -0
- data/app/controllers/spree/vpago_payments_controller.rb +71 -0
- data/app/controllers/spree/webhook/acleda_mobiles_controller.rb +88 -0
- data/app/controllers/spree/webhook/acledas_controller.rb +80 -0
- data/app/controllers/spree/webhook/base_controller.rb +6 -0
- data/app/controllers/spree/webhook/payways_controller.rb +77 -0
- data/app/controllers/spree/webhook/wings_controller.rb +63 -0
- data/app/controllers/spree/wing/base_controller.rb +29 -0
- data/app/controllers/spree/wing/transactions_controller.rb +27 -0
- data/app/controllers/spree/wing_redirects_controller.rb +20 -0
- data/app/helpers/vpago/admin/base_helper_decorator.rb +40 -0
- data/app/helpers/vpago/vpago_payments_helper.rb +12 -0
- data/app/javascripts/vpago/vpago_payments/user_informers/firebase.js +62 -0
- data/app/jobs/application_unique_job.rb +1 -0
- data/app/jobs/vpago/payment_processor_job.rb +8 -0
- data/app/models/.gitkeep +0 -0
- data/app/models/concerns/vpago/payoutable.rb +11 -0
- data/app/models/spree/gateway/acleda.rb +63 -0
- data/app/models/spree/gateway/acleda_mobile.rb +46 -0
- data/app/models/spree/gateway/payway.rb +66 -0
- data/app/models/spree/gateway/payway_v2.rb +174 -0
- data/app/models/spree/gateway/wing_sdk.rb +51 -0
- data/app/models/spree/payout.rb +23 -0
- data/app/models/spree/payout_profile.rb +107 -0
- data/app/models/spree/payout_profile_product.rb +14 -0
- data/app/models/spree/payout_profile_shipping_method.rb +14 -0
- data/app/models/spree/payout_profiles/payway_v2.rb +40 -0
- data/app/models/spree/vpago_payment_source.rb +21 -0
- data/app/models/vpago/adjustment_decorator.rb +28 -0
- data/app/models/vpago/line_item_decorator.rb +75 -0
- data/app/models/vpago/order_decorator.rb +78 -0
- data/app/models/vpago/payment_decorator.rb +44 -0
- data/app/models/vpago/payment_method_decorator.rb +91 -0
- data/app/models/vpago/payouts_generator.rb +125 -0
- data/app/models/vpago/product_decorator.rb +30 -0
- data/app/models/vpago/promotion_action_decorator.rb +9 -0
- data/app/models/vpago/shipment_decorator.rb +23 -0
- data/app/models/vpago/shipping_method_decorator.rb +33 -0
- data/app/models/vpago/shipping_rate_decorator.rb +25 -0
- data/app/models/vpago/store_decorator.rb +17 -0
- data/app/models/vpago/tax_category_decorator.rb +9 -0
- data/app/models/vpago/variant_decorator.rb +22 -0
- data/app/models/vpago/vendor_decorator.rb +10 -0
- data/app/overrides/spree/admin/adjustments/_adjustment/handle_by_table_body.html.erb.deface +11 -0
- data/app/overrides/spree/admin/adjustments/_adjustments_table/handle_by_table_header.html.erb.deface +3 -0
- data/app/overrides/spree/admin/adjustments/_form/handle_by_field.html.erb.deface +10 -0
- data/app/overrides/spree/admin/orders/_shipment/edit_method.html.erb.deface +26 -0
- data/app/overrides/spree/admin/orders/_shipment/show_method.html.erb.deface +27 -0
- data/app/overrides/spree/admin/payment_methods/_form/enable_pre_auth_field.html.erb.deface +17 -0
- data/app/overrides/spree/admin/payment_methods/_form/vendor_field.html.erb.deface +6 -0
- data/app/overrides/spree/admin/payment_methods/index/list.html.erb.deface +45 -0
- data/app/overrides/spree/admin/payment_methods/index/payment_methods_tabs.html.erb.deface +9 -0
- data/app/overrides/spree/admin/payment_methods/index/vendor_body.html.erb.deface +5 -0
- data/app/overrides/spree/admin/payment_methods/index/vendor_header.html.erb.deface +5 -0
- data/app/overrides/spree/admin/payments/_list/actions.html.erb.deface +13 -0
- data/app/overrides/spree/admin/promotions/_promotion_action/run_by_field.html.erb.deface +13 -0
- data/app/overrides/spree/admin/shared/_order_tabs/payouts.html.erb.deface +8 -0
- data/app/overrides/spree/admin/shared/_product_tabs/payout_profile_products.html.erb.deface +8 -0
- data/app/overrides/spree/admin/shared/sub_menu/_integrations/payout_profiles.html.erb.deface +3 -0
- data/app/overrides/spree/admin/shipping_methods/_form/handle_by.html.erb.deface +12 -0
- data/app/overrides/spree/admin/shipping_methods/edit/shipping_method_tabs.html.erb.deface +3 -0
- data/app/overrides/spree/admin/tax_categories/_form/collect_by_field.html.erb.deface +10 -0
- data/app/overrides/spree/admin/tax_categories/index/collect_by_table_body.html.erb.deface +4 -0
- data/app/overrides/spree/admin/tax_categories/index/collect_by_table_header.html.erb.deface +4 -0
- data/app/serializers/spree/api/v2/platform/vpago_payment_source_serializer.rb +11 -0
- data/app/serializers/spree/v2/storefront/payment_method_serializer_decorator.rb +23 -0
- data/app/serializers/spree/v2/storefront/payment_redirect_serializer.rb +13 -0
- data/app/serializers/spree/v2/storefront/payment_serializer_decorator.rb +13 -0
- data/app/serializers/spree/v2/storefront/vpago_payment_source_serializer.rb +9 -0
- data/app/services/.gitkeep +0 -0
- data/app/services/vpago/payment_finder.rb +27 -0
- data/app/services/vpago/payment_processor.rb +72 -0
- data/app/services/vpago/payment_redirect_handler.rb +194 -0
- data/app/services/vpago/payment_url_constructor.rb +32 -0
- data/app/services/vpago/payments/find_or_create.rb +51 -0
- data/app/services/vpago/payout_profiles/payway/base_payout_profile_request.rb +38 -0
- data/app/services/vpago/payout_profiles/payway/open_ssl_encrypter.rb +31 -0
- data/app/services/vpago/payout_profiles/payway/payout_profile_request_creator.rb +50 -0
- data/app/services/vpago/payout_profiles/payway/payout_profile_request_params_builder.rb +58 -0
- data/app/services/vpago/payout_profiles/payway/payout_profile_request_updater.rb +28 -0
- data/app/services/vpago/payway_return_options_builder.rb +39 -0
- data/app/services/vpago/user_informers/firebase.rb +52 -0
- data/app/views/.gitkeep +0 -0
- data/app/views/layouts/acleda.html.erb +18 -0
- data/app/views/layouts/payway.html.erb +24 -0
- data/app/views/layouts/payway_v2.html.erb +18 -0
- data/app/views/layouts/vpago_payments.html.erb +18 -0
- data/app/views/layouts/wing.html.erb +18 -0
- data/app/views/spree/_payment_icon.html.erb +25 -0
- data/app/views/spree/acleda_redirects/show.html.erb +3 -0
- data/app/views/spree/admin/payments/source_forms/_payment_payway.html.erb +4 -0
- data/app/views/spree/admin/payments/source_forms/_payway_v2.html.erb +7 -0
- data/app/views/spree/admin/payments/source_views/_acleda.html.erb +1 -0
- data/app/views/spree/admin/payments/source_views/_acleda_mobile.html.erb +1 -0
- data/app/views/spree/admin/payments/source_views/_payment_payway.html.erb +98 -0
- data/app/views/spree/admin/payments/source_views/_payway_v2.html.erb +5 -0
- data/app/views/spree/admin/payments/source_views/_vpago_payment_tmpl.html.erb +113 -0
- data/app/views/spree/admin/payments/source_views/_wingsdk.html.erb +5 -0
- data/app/views/spree/admin/payout_profile_products/_form.html.erb +28 -0
- data/app/views/spree/admin/payout_profile_products/edit.html.erb +18 -0
- data/app/views/spree/admin/payout_profile_products/index.html.erb +58 -0
- data/app/views/spree/admin/payout_profile_products/new.html.erb +22 -0
- data/app/views/spree/admin/payout_profile_shipping_methods/_form.html.erb +28 -0
- data/app/views/spree/admin/payout_profile_shipping_methods/edit.html.erb +22 -0
- data/app/views/spree/admin/payout_profile_shipping_methods/index.html.erb +6 -0
- data/app/views/spree/admin/payout_profile_shipping_methods/new.html.erb +27 -0
- data/app/views/spree/admin/payout_profiles/_filter.html.erb +19 -0
- data/app/views/spree/admin/payout_profiles/_form.html.erb +72 -0
- data/app/views/spree/admin/payout_profiles/edit.html.erb +33 -0
- data/app/views/spree/admin/payout_profiles/index.html.erb +63 -0
- data/app/views/spree/admin/payout_profiles/new.html.erb +13 -0
- data/app/views/spree/admin/payouts/_line_item_info_with_popover.html.erb +43 -0
- data/app/views/spree/admin/payouts/index.html.erb +46 -0
- data/app/views/spree/admin/shared/_payment_methods_tabs.html.erb +15 -0
- data/app/views/spree/admin/shared/_shipping_method_tabs.html.erb +19 -0
- data/app/views/spree/admin/shared/payout_profile/_info_card.html.erb +24 -0
- data/app/views/spree/admin/shared/payout_profile/_status.html.erb +11 -0
- data/app/views/spree/checkout/payment/_acleda.html.erb +1 -0
- data/app/views/spree/checkout/payment/_acleda_checkout_form.html.erb +14 -0
- data/app/views/spree/checkout/payment/_acleda_mobile.html.erb +0 -0
- data/app/views/spree/checkout/payment/_payment_payway.html.erb +21 -0
- data/app/views/spree/checkout/payment/_payway_loader.html.erb +2 -0
- data/app/views/spree/checkout/payment/_payway_root.html.erb +9 -0
- data/app/views/spree/checkout/payment/_payway_script.html.erb +77 -0
- data/app/views/spree/checkout/payment/_payway_v2.html.erb +1 -0
- data/app/views/spree/checkout/payment/_payway_v2_loader.html.erb +2 -0
- data/app/views/spree/checkout/payment/_payway_v2_root.html.erb +9 -0
- data/app/views/spree/checkout/payment/_payway_v2_script.html.erb +79 -0
- data/app/views/spree/checkout/payment/_wing_checkout_form.html.erb +18 -0
- data/app/views/spree/checkout/payment/_wingsdk.html.erb +1 -0
- data/app/views/spree/checkout/payment/acleda_form.html.erb +3 -0
- data/app/views/spree/checkout/payment/payway_form.html.erb +10 -0
- data/app/views/spree/checkout/payment/payway_v2_form.html.erb +10 -0
- data/app/views/spree/checkout/payment/wingsdk_form.html.erb +3 -0
- data/app/views/spree/payway_card_popups/_form.html.erb +10 -0
- data/app/views/spree/payway_card_popups/show.html.erb +5 -0
- data/app/views/spree/payway_results/failed.html.erb +1 -0
- data/app/views/spree/payway_results/success.html.erb +1 -0
- data/app/views/spree/payway_v2_card_popups/_form.html.erb +15 -0
- data/app/views/spree/payway_v2_card_popups/show.html.erb +3 -0
- data/app/views/spree/vpago_payments/checkout.html.erb +3 -0
- data/app/views/spree/vpago_payments/forms/spree/gateway/_payway_v2.html.erb +13 -0
- data/app/views/spree/vpago_payments/processing.html.erb +49 -0
- data/app/views/spree/vpago_payments/success.html.erb +3 -0
- data/app/views/spree/wing_redirects/show.html.erb +3 -0
- data/bin/rails +8 -0
- data/build.js +9 -0
- data/config/initializers/assets.rb +1 -0
- data/config/initializers/spree_permitted_attributes.rb +5 -0
- data/config/locales/en.yml +28 -0
- data/config/locales/km.yml +24 -0
- data/config/routes.rb +92 -0
- data/db/migrate/20210128040625_create_spree_vpago_payment_sources.rb +14 -0
- data/db/migrate/20210430052432_add_fields_to_payment_sources.rb +7 -0
- data/db/migrate/20210824044737_add_preference_to_spree_vpago_payment_source.rb +5 -0
- data/db/migrate/20240506095140_create_spree_payout_profiles.rb +22 -0
- data/db/migrate/20240506095148_create_spree_payout_profile_products.rb +10 -0
- data/db/migrate/20240523070757_add_optional_spere_payout_profile_products.rb +5 -0
- data/db/migrate/20240715091228_create_spree_payouts.rb +25 -0
- data/db/migrate/20240718195510_create_spree_payout_profile_shipping_methods.rb +15 -0
- data/db/migrate/20240718201453_add_handle_by_to_spree_adjustments.rb +5 -0
- data/db/migrate/20240718201509_add_run_by_to_spree_promotion_actions.rb +5 -0
- data/db/migrate/20240718201523_add_collect_by_to_spree_tax_categories.rb +5 -0
- data/db/migrate/20240718201538_add_handle_by_to_spree_shipping_method.rb +5 -0
- data/db/migrate/20240718201554_add_handle_by_to_spree_shipping_rates.rb +5 -0
- data/db/migrate/20240808102853_add_vendor_reference_to_spree_payment_methods.rb +7 -0
- data/db/migrate/20240904030132_add_gateway_status_to_spree_payments.rb +5 -0
- data/db/migrate/20241029071959_add_pre_auth_response_to_spree_payment.rb +5 -0
- data/db/migrate/20241202104014_add_enable_pre_auth_to_spree_payment_method.rb +5 -0
- data/db/migrate/20250121044614_add_transaction_response_to_spree_payments.rb +5 -0
- data/docs/acleda.md +65 -0
- data/gemfiles/spree_3_7.gemfile +9 -0
- data/gemfiles/spree_4_0.gemfile +8 -0
- data/gemfiles/spree_4_1.gemfile +9 -0
- data/gemfiles/spree_master.gemfile +8 -0
- data/lib/generators/spree_vpago/install/install_generator.rb +26 -0
- data/lib/generators/spree_vpago/install/templates/app/assets/images/vpago/payway/acleda_merchant_logo_300x300.png +0 -0
- data/lib/spree_vpago/engine.rb +36 -0
- data/lib/spree_vpago/factories.rb +6 -0
- data/lib/spree_vpago/version.rb +9 -0
- data/lib/spree_vpago.rb +5 -0
- data/lib/vpago/acleda/base.rb +111 -0
- data/lib/vpago/acleda/checkout.rb +105 -0
- data/lib/vpago/acleda/deeplink_checkout.rb +74 -0
- data/lib/vpago/acleda/payment_request_updater.rb +38 -0
- data/lib/vpago/acleda/transaction_status.rb +71 -0
- data/lib/vpago/acleda_mobile/base.rb +28 -0
- data/lib/vpago/acleda_mobile/callback_validator.php +35 -0
- data/lib/vpago/acleda_mobile/callback_validator.rb +38 -0
- data/lib/vpago/acleda_mobile/checkout.rb +78 -0
- data/lib/vpago/acleda_mobile/payment_request_updater.rb +34 -0
- data/lib/vpago/acleda_mobile/payment_retriever.rb +24 -0
- data/lib/vpago/acleda_mobile/transaction_status.rb +35 -0
- data/lib/vpago/payment_amount_calculator.rb +23 -0
- data/lib/vpago/payment_request_updater.rb +19 -0
- data/lib/vpago/payment_status_marker.rb +109 -0
- data/lib/vpago/payway/base.rb +112 -0
- data/lib/vpago/payway/checkout.rb +24 -0
- data/lib/vpago/payway/payment_request_updater.rb +31 -0
- data/lib/vpago/payway/payment_status_marker.rb +84 -0
- data/lib/vpago/payway/transaction_status.rb +74 -0
- data/lib/vpago/payway.rb +13 -0
- data/lib/vpago/payway_v2/base.rb +153 -0
- data/lib/vpago/payway_v2/checkout.rb +35 -0
- data/lib/vpago/payway_v2/payment_request_updater.rb +65 -0
- data/lib/vpago/payway_v2/payouts_params_constructor.rb +47 -0
- data/lib/vpago/payway_v2/pre_auth_canceler.rb +43 -0
- data/lib/vpago/payway_v2/pre_auth_completer.rb +76 -0
- data/lib/vpago/payway_v2/transaction_status.rb +85 -0
- data/lib/vpago/wing_sdk/base.rb +58 -0
- data/lib/vpago/wing_sdk/checkout.rb +20 -0
- data/lib/vpago/wing_sdk/payment_request_updater.rb +46 -0
- data/lib/vpago/wing_sdk/payment_retriever.rb +34 -0
- data/lib/vpago/wing_sdk/transaction_status_checker.rb +64 -0
- data/lib/vpago/wing_sdk/transaction_status_response.rb +33 -0
- data/node_modules/.yarn-integrity +147 -0
- data/package-lock.json +1491 -0
- data/package.json +10 -0
- data/spree_vpago.gemspec +33 -0
- data/yarn.lock +921 -0
- metadata +403 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
module Vpago
|
4
|
+
module Acleda
|
5
|
+
class TransactionStatus < Base
|
6
|
+
attr_accessor :error_message, :result
|
7
|
+
|
8
|
+
def call
|
9
|
+
prepare
|
10
|
+
process
|
11
|
+
end
|
12
|
+
|
13
|
+
def prepare
|
14
|
+
@error_message = nil
|
15
|
+
@result = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def process
|
19
|
+
@response = check_acleda_payment_status
|
20
|
+
|
21
|
+
if @response.status == 200
|
22
|
+
if (json_response['result']['code']).zero?
|
23
|
+
@result = json_response
|
24
|
+
else
|
25
|
+
fail!(json_response['result']['errorDetails'])
|
26
|
+
end
|
27
|
+
else
|
28
|
+
fail!(@response.body)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def request_payload
|
33
|
+
payment_token_id = @payment.source.transaction_id
|
34
|
+
|
35
|
+
{
|
36
|
+
loginId: login_id,
|
37
|
+
password: password,
|
38
|
+
merchantName: merchant_name,
|
39
|
+
signature: signature,
|
40
|
+
merchantId: merchant_id,
|
41
|
+
paymentTokenid: payment_token_id
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
def check_acleda_payment_status
|
46
|
+
con = Faraday::Connection.new(url: host)
|
47
|
+
|
48
|
+
con.post(check_status_path) do |request|
|
49
|
+
request.headers['Content-Type'] = 'application/json'
|
50
|
+
request.body = request_payload.to_json
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def check_status_path
|
55
|
+
ENV.fetch('ACLEDA_CHECK_STATUS_PATH', nil)
|
56
|
+
end
|
57
|
+
|
58
|
+
def json_response
|
59
|
+
@json_response ||= JSON.parse(@response.body)
|
60
|
+
end
|
61
|
+
|
62
|
+
def fail!(message)
|
63
|
+
@error_message = message
|
64
|
+
end
|
65
|
+
|
66
|
+
def success?
|
67
|
+
@error_message.nil?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Vpago
|
2
|
+
module AcledaMobile
|
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 encryption_key
|
16
|
+
@payment.payment_method.preferences[:data_encryption_key]
|
17
|
+
end
|
18
|
+
|
19
|
+
def return_to_app_url
|
20
|
+
@payment.payment_method.preferences[:app_url]
|
21
|
+
end
|
22
|
+
|
23
|
+
def partner_id
|
24
|
+
@payment.payment_method.preferences[:partner_id]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<?php
|
2
|
+
$data = array(
|
3
|
+
"TransactionId" => "REF0361472663",
|
4
|
+
"PaymentTokenId" => "16de81d4-b5ef-ef59-16de-81d4b5efef59",
|
5
|
+
"TxnAmount" => "30",
|
6
|
+
"SenderName" => "Test User"
|
7
|
+
);
|
8
|
+
|
9
|
+
// will be provided
|
10
|
+
$secret_key = 'VTenhSecret';
|
11
|
+
|
12
|
+
// signed request fields
|
13
|
+
$hash_data = $data['TransactionId'] . ' ' . $data['PaymentTokenId'] . ' ' . $data['TxnAmount'];
|
14
|
+
$binary_output = false;
|
15
|
+
|
16
|
+
// calculate the signed input hash
|
17
|
+
echo "hash data: ${hash_data}";
|
18
|
+
$hash_value = hash_hmac('sha256', $hash_data, $secret_key, $binary_output);
|
19
|
+
|
20
|
+
|
21
|
+
$vtenh_request = $data;
|
22
|
+
|
23
|
+
// request payload with signed for vtenh callback
|
24
|
+
$vtenh_request["SignedHash"] = $hash_value;
|
25
|
+
|
26
|
+
print_r($vtenh_request);
|
27
|
+
// output
|
28
|
+
// Array
|
29
|
+
// (
|
30
|
+
// [TransactionId] => REF0361472663
|
31
|
+
// [PaymentTokenId] => 16de81d4-b5ef-ef59-16de-81d4b5efef59
|
32
|
+
// [TxnAmount] => 30
|
33
|
+
// [SenderName] => Test User
|
34
|
+
// [SignedHash] => c5b9be690bde7dc8a0abebb1a45c0850359540a4977aecd4cdf13e15a2edfe79
|
35
|
+
// )
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Vpago
|
2
|
+
module AcledaMobile
|
3
|
+
class CallbackValidator
|
4
|
+
# {
|
5
|
+
# "TransactionId": "REF0361472663",
|
6
|
+
# "PaymentTokenId": "16de81d4-b5ef-ef59-16de-81d4b5efef59",
|
7
|
+
# "TxnAmount": "30",
|
8
|
+
# "SenderName": "Test User",
|
9
|
+
# "SignedHash": "c5b9be690bde7dc8a0abebb1a45c0850359540a4977aecd4cdf13e15a2edfe79",
|
10
|
+
# }
|
11
|
+
def initialize(options)
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
valid?
|
17
|
+
end
|
18
|
+
|
19
|
+
def secret_key
|
20
|
+
ENV.fetch('ACLEDA_MOBILE_SECRET_HASH_KEY', nil)
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid?
|
24
|
+
return false if secret_key.blank?
|
25
|
+
|
26
|
+
hmac_hash == @options[:SignedHash]
|
27
|
+
end
|
28
|
+
|
29
|
+
def hmac_hash
|
30
|
+
key = secret_key
|
31
|
+
|
32
|
+
message = "#{@options[:TransactionId]} #{@options[:PaymentTokenId]} #{@options[:TxnAmount]}"
|
33
|
+
|
34
|
+
OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), key, message)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Vpago
|
2
|
+
module AcledaMobile
|
3
|
+
class Checkout < 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_payment_data
|
32
|
+
message = payment_data.to_json
|
33
|
+
key = encryption_key
|
34
|
+
|
35
|
+
hmac_hash(key, message)
|
36
|
+
end
|
37
|
+
|
38
|
+
def hmac_hash(key, message)
|
39
|
+
OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), key, message)
|
40
|
+
end
|
41
|
+
|
42
|
+
def aes_encrypted_payment_data
|
43
|
+
data = "#{payment_data.to_json}~#{hmac_payment_data}"
|
44
|
+
key = encryption_key
|
45
|
+
iv = [key].pack('H*') # #hex2bin
|
46
|
+
cipher = OpenSSL::Cipher.new('AES-256-CBC')
|
47
|
+
cipher.encrypt
|
48
|
+
|
49
|
+
cipher.key = pbkdf2_key
|
50
|
+
cipher.iv = iv
|
51
|
+
|
52
|
+
crypt = cipher.update(data) + cipher.final
|
53
|
+
encrypted_result = Base64.encode64(crypt).delete("\n")
|
54
|
+
encrypted_result.gsub('/', 'acledabankSecurityTC') # #follow acleda encrypting guide
|
55
|
+
end
|
56
|
+
|
57
|
+
def payment_data
|
58
|
+
{
|
59
|
+
app_name: 'VTENH',
|
60
|
+
payment_amount: amount_with_fee,
|
61
|
+
payment_amount_ccy: 'USD',
|
62
|
+
payment_purpose: 'VTENH Transaction',
|
63
|
+
txn_ref: payment_number,
|
64
|
+
app_url: return_to_app_url
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
def pbkdf2_key
|
69
|
+
pass = encryption_key
|
70
|
+
salt = pass
|
71
|
+
iter = 100
|
72
|
+
key_len = 32
|
73
|
+
|
74
|
+
OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter, length: key_len, hash: 'sha1')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Vpago
|
2
|
+
module AcledaMobile
|
3
|
+
class PaymentRequestUpdater < ::Vpago::PaymentRequestUpdater
|
4
|
+
def call
|
5
|
+
checker = payment_status_checker
|
6
|
+
|
7
|
+
if checker.success?
|
8
|
+
@error_message = nil
|
9
|
+
checker_result = {
|
10
|
+
status: true,
|
11
|
+
description: nil,
|
12
|
+
acleda_response: checker.result
|
13
|
+
}
|
14
|
+
marker_options = @options.merge(checker_result)
|
15
|
+
|
16
|
+
marker = ::Vpago::PaymentStatusMarker.new(@payment, marker_options)
|
17
|
+
marker.call
|
18
|
+
elsif !ignore_on_failed?
|
19
|
+
@error_message = checker.error_message
|
20
|
+
marker_options = @options.merge(status: false, description: @error_message)
|
21
|
+
|
22
|
+
marker = ::Vpago::PaymentStatusMarker.new(@payment, marker_options)
|
23
|
+
marker.call
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def payment_status_checker
|
28
|
+
trans_status = Vpago::AcledaMobile::TransactionStatus.new(@payment)
|
29
|
+
trans_status.call(@options[:payment_token_id]) # #TO DO: remove payment_token_id when check transaction status api ready
|
30
|
+
trans_status
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Vpago
|
2
|
+
module AcledaMobile
|
3
|
+
class PaymentRetriever
|
4
|
+
attr_accessor :payment
|
5
|
+
|
6
|
+
def initialize(options)
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
find_payment if data_valid?
|
12
|
+
end
|
13
|
+
|
14
|
+
def data_valid?
|
15
|
+
service = Vpago::AcledaMobile::CallbackValidator.new(@options)
|
16
|
+
service.valid?
|
17
|
+
end
|
18
|
+
|
19
|
+
def find_payment
|
20
|
+
@payment = Spree::Payment.find_by(number: @options[:PaymentTokenId])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
module Vpago
|
4
|
+
module AcledaMobile
|
5
|
+
class TransactionStatus < Base
|
6
|
+
attr_accessor :error_message, :result
|
7
|
+
|
8
|
+
# #TO DO: remove payment_token_id when check transaction status api ready
|
9
|
+
def call(payment_token_id = nil)
|
10
|
+
prepare
|
11
|
+
process(payment_token_id)
|
12
|
+
end
|
13
|
+
|
14
|
+
def prepare
|
15
|
+
@error_message = nil
|
16
|
+
@result = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def process(payment_token_id)
|
20
|
+
@result = {
|
21
|
+
ErrorCode: '200',
|
22
|
+
ErrorDescription: 'Success',
|
23
|
+
TransactionId: payment_number,
|
24
|
+
PaymentTokenId: payment_token_id,
|
25
|
+
Amount: '',
|
26
|
+
Currency: 'USD'
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def success?
|
31
|
+
@error_message.nil?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Vpago
|
2
|
+
module PaymentAmountCalculator
|
3
|
+
def amount
|
4
|
+
@payment.amount
|
5
|
+
end
|
6
|
+
|
7
|
+
def amount_with_fee
|
8
|
+
format('%.2f', (amount + transaction_fee))
|
9
|
+
end
|
10
|
+
|
11
|
+
def transaction_fee_fix
|
12
|
+
@payment.payment_method.preferences[:transaction_fee_fix].to_f
|
13
|
+
end
|
14
|
+
|
15
|
+
def transaction_fee_percentage
|
16
|
+
@payment.payment_method.preferences[:transaction_fee_percentage].to_f
|
17
|
+
end
|
18
|
+
|
19
|
+
def transaction_fee
|
20
|
+
transaction_fee_fix + ((amount * transaction_fee_percentage) / 100)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Vpago
|
2
|
+
class PaymentRequestUpdater
|
3
|
+
attr_accessor :payment, :error_message
|
4
|
+
|
5
|
+
def initialize(payment, options = {})
|
6
|
+
@options = options
|
7
|
+
@payment = payment
|
8
|
+
@error_message = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def ignore_on_failed?
|
12
|
+
@options[:ignore_on_failed] || false
|
13
|
+
end
|
14
|
+
|
15
|
+
def success?
|
16
|
+
@error_message.nil?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Vpago
|
2
|
+
class PaymentStatusMarker
|
3
|
+
attr_accessor :payment, :error_message
|
4
|
+
|
5
|
+
# :status, :description, :updated_by_user_id, updated_reason
|
6
|
+
def initialize(payment, options = {})
|
7
|
+
@payment = payment
|
8
|
+
@options = options
|
9
|
+
@options[:status] = @options[:status] || false
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
ActiveRecord::Base.transaction do
|
14
|
+
update_payment_source
|
15
|
+
update_payment_and_order
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def update_payment_source
|
22
|
+
source = @payment.source
|
23
|
+
|
24
|
+
payment_status = @options[:status] ? 'success' : 'failed'
|
25
|
+
source.payment_status = payment_status
|
26
|
+
source.payment_description = @options[:description]
|
27
|
+
## for acleda, we already update the transaction_id at when checkout
|
28
|
+
source.transaction_id = @options[:transaction_id] if @options[:transaction_id].present?
|
29
|
+
source.preferred_wing_response = @options[:wing_response]
|
30
|
+
source.preferred_acleda_response = @options[:acleda_response]
|
31
|
+
source.preferred_payway_v2_response = @options[:payway_v2_response]
|
32
|
+
|
33
|
+
if @options[:status]
|
34
|
+
source.updated_by_user_id = @options[:updated_by_user_id]
|
35
|
+
source.updated_reason = @options[:updated_reason]
|
36
|
+
source.updated_by_user_at = Time.zone.now
|
37
|
+
end
|
38
|
+
|
39
|
+
return if source.save
|
40
|
+
|
41
|
+
@error_message = source.errors.full_messages.join('\n')
|
42
|
+
end
|
43
|
+
|
44
|
+
def update_payment_and_order
|
45
|
+
if @options[:status]
|
46
|
+
transition_to_paid!
|
47
|
+
else
|
48
|
+
transition_to_failed!
|
49
|
+
end
|
50
|
+
|
51
|
+
order_updater
|
52
|
+
end
|
53
|
+
|
54
|
+
def transition_to_paid!
|
55
|
+
complete_payment!
|
56
|
+
complete_order!
|
57
|
+
confirm_payouts!
|
58
|
+
end
|
59
|
+
|
60
|
+
def transition_to_failed!
|
61
|
+
@payment.failure! unless @payment.failed?
|
62
|
+
@payment.order.update(state: 'payment')
|
63
|
+
|
64
|
+
notify_failed_payment
|
65
|
+
end
|
66
|
+
|
67
|
+
def order_updater
|
68
|
+
@payment.order.update_with_updater!
|
69
|
+
end
|
70
|
+
|
71
|
+
def complete_payment!
|
72
|
+
return if @payment.completed?
|
73
|
+
|
74
|
+
# not follow state machine rule when it manual
|
75
|
+
if @options[:updated_by_user_id].present?
|
76
|
+
ApplicationRecord.transaction do
|
77
|
+
@payment.state_changes.create!(previous_state: @payment.state, next_state: 'completed', name: 'payment')
|
78
|
+
@payment.update(state: 'completed')
|
79
|
+
end
|
80
|
+
else
|
81
|
+
@payment.complete!
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def complete_order!
|
86
|
+
return if @payment.order.completed?
|
87
|
+
|
88
|
+
order = @payment.order
|
89
|
+
order.finalize!
|
90
|
+
order.update(state: 'complete', completed_at: Time.zone.now)
|
91
|
+
end
|
92
|
+
|
93
|
+
def payout_confirmed?
|
94
|
+
@options[:payout_total] == @payment.payouts.sum(:amount)
|
95
|
+
end
|
96
|
+
|
97
|
+
def confirm_payouts!
|
98
|
+
return unless payout_confirmed?
|
99
|
+
|
100
|
+
@payment.payouts.find_each do |payout|
|
101
|
+
payout.update!(state: :confirmed)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def notify_failed_payment
|
106
|
+
Rails.logger.info("Gateway error check with: #{@options[:description]} and will be marked as failed")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module Vpago
|
2
|
+
module Payway
|
3
|
+
class Base
|
4
|
+
def initialize(payment, options = {})
|
5
|
+
@options = options
|
6
|
+
@payment = payment
|
7
|
+
end
|
8
|
+
|
9
|
+
def host
|
10
|
+
@payment.payment_method.preferences[:host]
|
11
|
+
end
|
12
|
+
|
13
|
+
def amount
|
14
|
+
format('%.2f', (@payment.amount + transaction_fee))
|
15
|
+
end
|
16
|
+
|
17
|
+
def transaction_fee_fix
|
18
|
+
@payment.payment_method.preferences[:transaction_fee_fix].to_f
|
19
|
+
end
|
20
|
+
|
21
|
+
def transaction_fee_percentage
|
22
|
+
@payment.payment_method.preferences[:transaction_fee_percentage].to_f
|
23
|
+
end
|
24
|
+
|
25
|
+
def transaction_fee
|
26
|
+
transaction_fee_fix + ((@payment.amount * transaction_fee_percentage) / 100)
|
27
|
+
end
|
28
|
+
|
29
|
+
def merchant_id
|
30
|
+
@payment.payment_method.preferences[:merchant_id]
|
31
|
+
end
|
32
|
+
|
33
|
+
def transaction_id
|
34
|
+
@payment.number
|
35
|
+
end
|
36
|
+
|
37
|
+
def email
|
38
|
+
@payment.order.email.presence || ENV.fetch('DEFAULT_EMAIL_FOR_PAYMENT', nil)
|
39
|
+
end
|
40
|
+
|
41
|
+
def first_name
|
42
|
+
@payment.order.billing_address.first_name
|
43
|
+
end
|
44
|
+
|
45
|
+
def last_name
|
46
|
+
@payment.order.billing_address.last_name
|
47
|
+
end
|
48
|
+
|
49
|
+
def return_url
|
50
|
+
preferred_return_url = @payment.payment_method.preferences[:return_url]
|
51
|
+
return nil if preferred_return_url.blank?
|
52
|
+
|
53
|
+
Base64.encode64(preferred_return_url)
|
54
|
+
end
|
55
|
+
|
56
|
+
def app_checkout
|
57
|
+
app_checkout? ? 'yes' : 'no'
|
58
|
+
end
|
59
|
+
|
60
|
+
def app_checkout?
|
61
|
+
return false if @options[:app_checkout].blank?
|
62
|
+
|
63
|
+
@options[:app_checkout]
|
64
|
+
end
|
65
|
+
|
66
|
+
def continue_success_url
|
67
|
+
preferred_continue_url = @payment.payment_method.preferences[:continue_success_url]
|
68
|
+
return nil if preferred_continue_url.blank?
|
69
|
+
|
70
|
+
query_string = "tran_id=#{transaction_id}&app_checkout=#{app_checkout}"
|
71
|
+
preferred_continue_url.index('?').nil? ? "#{preferred_continue_url}?#{query_string}" : "#{preferred_continue_url}&#{query_string}"
|
72
|
+
end
|
73
|
+
|
74
|
+
def payment_option
|
75
|
+
card_option = @payment.payment_method.preferences[:payment_option]
|
76
|
+
Vpago::Payway::CARD_TYPES.index(card_option).nil? ? Vpago::Payway::CARD_TYPE_ABAPAY : card_option
|
77
|
+
end
|
78
|
+
|
79
|
+
def phone_country_code
|
80
|
+
'+855'
|
81
|
+
end
|
82
|
+
|
83
|
+
def phone
|
84
|
+
@payment.order.billing_address.phone
|
85
|
+
end
|
86
|
+
|
87
|
+
def api_key
|
88
|
+
@payment.payment_method.preferences[:api_key]
|
89
|
+
end
|
90
|
+
|
91
|
+
def return_params
|
92
|
+
{ tran_id: transaction_id }.to_json
|
93
|
+
end
|
94
|
+
|
95
|
+
def hash_hmac
|
96
|
+
data = "#{merchant_id}#{transaction_id}#{amount}"
|
97
|
+
hash = Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha512'), api_key, data))
|
98
|
+
|
99
|
+
# somehow php counter part are not able to decode if the \n present.
|
100
|
+
hash.delete("\n")
|
101
|
+
end
|
102
|
+
|
103
|
+
def endpoint
|
104
|
+
@payment.payment_method.preferences[:endpoint]
|
105
|
+
end
|
106
|
+
|
107
|
+
def action_url
|
108
|
+
"#{host}#{endpoint}"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Vpago
|
2
|
+
module Payway
|
3
|
+
class Checkout < Base
|
4
|
+
def gateway_params
|
5
|
+
result = {
|
6
|
+
tran_id: transaction_id,
|
7
|
+
amount: amount,
|
8
|
+
hash: hash_hmac,
|
9
|
+
firstname: first_name,
|
10
|
+
lastname: last_name,
|
11
|
+
email: email,
|
12
|
+
payment_option: payment_option,
|
13
|
+
return_url: return_url,
|
14
|
+
continue_success_url: continue_success_url,
|
15
|
+
return_params: return_params
|
16
|
+
}
|
17
|
+
|
18
|
+
result[:phone_country_code] = phone_country_code
|
19
|
+
result[:phone] = phone
|
20
|
+
result
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Vpago
|
2
|
+
module Payway
|
3
|
+
class PaymentRequestUpdater < ::Vpago::PaymentRequestUpdater
|
4
|
+
def call
|
5
|
+
checker = check_payway_status
|
6
|
+
|
7
|
+
if checker.success?
|
8
|
+
@error_message = nil
|
9
|
+
|
10
|
+
marker_options = @options.merge(status: true, description: nil)
|
11
|
+
marker = ::Vpago::Payway::PaymentStatusMarker.new(@payment, marker_options)
|
12
|
+
marker.call
|
13
|
+
elsif !ignore_on_failed?
|
14
|
+
@error_message = checker.error_message[0...255]
|
15
|
+
marker_options = @options.merge(status: false, description: @error_message)
|
16
|
+
|
17
|
+
marker = ::Vpago::Payway::PaymentStatusMarker.new(@payment, marker_options)
|
18
|
+
marker.call
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def check_payway_status
|
25
|
+
trans_status = Vpago::Payway::TransactionStatus.new(@payment)
|
26
|
+
trans_status.call
|
27
|
+
trans_status
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|