mirror of
https://github.com/valitydev/wapi-lib.git
synced 2024-11-07 02:35:18 +00:00
FF-33
добавил тест для большого deposit; код для проверки лимитов кошелька убрал в ff_party изменено: apps/ff_cth/src/ct_payment_system.erl новый файл: apps/ff_server/rebar.config изменено: apps/ff_server/src/ff_server.erl изменено: apps/ff_transfer/rebar.config изменено: apps/ff_transfer/src/ff_deposit.erl изменено: apps/ff_transfer/src/ff_withdrawal.erl изменено: apps/ff_transfer/test/ff_transfer_SUITE.erl изменено: apps/fistful/rebar.config изменено: apps/fistful/src/ff_party.erl
This commit is contained in:
parent
4bb7bec5e9
commit
21bb7e71e6
@ -64,7 +64,16 @@ start_processing_apps(Options) ->
|
|||||||
client => ff_woody_client:new(<<"http://machinegun:8022/v1/automaton">>)
|
client => ff_woody_client:new(<<"http://machinegun:8022/v1/automaton">>)
|
||||||
}},
|
}},
|
||||||
{StartedApps, _StartupCtx} = ct_helper:start_apps([
|
{StartedApps, _StartupCtx} = ct_helper:start_apps([
|
||||||
lager,
|
{lager, [
|
||||||
|
{error_logger_hwm, 600},
|
||||||
|
% {log_root, "/var/log/fistful-server"},
|
||||||
|
{crash_log, "crash.log"},
|
||||||
|
{handlers, [
|
||||||
|
{lager_console_backend, [
|
||||||
|
{level, warning}
|
||||||
|
]}
|
||||||
|
]}
|
||||||
|
]},
|
||||||
scoper,
|
scoper,
|
||||||
woody,
|
woody,
|
||||||
dmt_client,
|
dmt_client,
|
||||||
|
3
apps/ff_server/rebar.config
Normal file
3
apps/ff_server/rebar.config
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{erl_opts, [
|
||||||
|
{parse_transform, lager_transform}
|
||||||
|
]}.
|
@ -34,7 +34,7 @@ start() ->
|
|||||||
application:ensure_all_started(?MODULE).
|
application:ensure_all_started(?MODULE).
|
||||||
|
|
||||||
%% Application
|
%% Application
|
||||||
|
|
||||||
-spec start(normal, any()) ->
|
-spec start(normal, any()) ->
|
||||||
{ok, pid()} | {error, any()}.
|
{ok, pid()} | {error, any()}.
|
||||||
|
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
{erl_opts, [
|
||||||
|
{parse_transform, lager_transform}
|
||||||
|
]}.
|
@ -154,7 +154,7 @@ events(ID, Range) ->
|
|||||||
|
|
||||||
process_transfer(Deposit) ->
|
process_transfer(Deposit) ->
|
||||||
Activity = deduce_activity(Deposit),
|
Activity = deduce_activity(Deposit),
|
||||||
do_process_transfer(Activity, Deposit).
|
do_process_transfer(Activity, Deposit).
|
||||||
|
|
||||||
-spec process_failure(any(), deposit()) ->
|
-spec process_failure(any(), deposit()) ->
|
||||||
{ok, process_result()} |
|
{ok, process_result()} |
|
||||||
@ -220,8 +220,16 @@ create_p_transfer(Deposit) ->
|
|||||||
-spec finish_transfer(deposit()) ->
|
-spec finish_transfer(deposit()) ->
|
||||||
{ok, {ff_transfer_machine:action(), [ff_transfer_machine:event(ff_transfer:event())]}} |
|
{ok, {ff_transfer_machine:action(), [ff_transfer_machine:event(ff_transfer:event())]}} |
|
||||||
{error, _Reason}.
|
{error, _Reason}.
|
||||||
finish_transfer(_Deposit) ->
|
finish_transfer(Deposit) ->
|
||||||
{ok, {continue, [{status_changed, succeeded}]}}.
|
Body = body(Deposit),
|
||||||
|
#{
|
||||||
|
wallet_id := WalletID,
|
||||||
|
wallet_account := WalletAccount
|
||||||
|
} = params(Deposit),
|
||||||
|
do(fun () ->
|
||||||
|
valid = ff_party:validate_wallet_limits(WalletID, Body, WalletAccount),
|
||||||
|
{continue, [{status_changed, succeeded}]}
|
||||||
|
end).
|
||||||
|
|
||||||
-spec construct_p_transfer_id(id()) -> id().
|
-spec construct_p_transfer_id(id()) -> id().
|
||||||
construct_p_transfer_id(ID) ->
|
construct_p_transfer_id(ID) ->
|
||||||
|
@ -62,16 +62,13 @@
|
|||||||
|
|
||||||
-type id() :: ff_transfer_machine:id().
|
-type id() :: ff_transfer_machine:id().
|
||||||
-type body() :: ff_transfer:body().
|
-type body() :: ff_transfer:body().
|
||||||
-type wallet() :: ff_wallet:wallet().
|
|
||||||
-type account() :: ff_account:account().
|
-type account() :: ff_account:account().
|
||||||
-type provider() :: ff_withdrawal_provider:provider().
|
-type provider() :: ff_withdrawal_provider:provider().
|
||||||
-type wallet_id() :: ff_wallet:id().
|
-type wallet_id() :: ff_wallet:id().
|
||||||
-type timestamp() :: ff_time:timestamp_ms().
|
|
||||||
-type cash_flow_plan() :: ff_cash_flow:cash_flow_plan().
|
-type cash_flow_plan() :: ff_cash_flow:cash_flow_plan().
|
||||||
-type destination_id() :: ff_destination:id().
|
-type destination_id() :: ff_destination:id().
|
||||||
-type process_result() :: {ff_transfer_machine:action(), [event()]}.
|
-type process_result() :: {ff_transfer_machine:action(), [event()]}.
|
||||||
-type final_cash_flow() :: ff_cash_flow:final_cash_flow().
|
-type final_cash_flow() :: ff_cash_flow:final_cash_flow().
|
||||||
-type withdrawal_terms() :: dmsl_domain_thrift:'WithdrawalServiceTerms'().
|
|
||||||
|
|
||||||
%% Accessors
|
%% Accessors
|
||||||
|
|
||||||
@ -121,7 +118,7 @@ create(ID, #{wallet_id := WalletID, destination_id := DestinationID, body := Bod
|
|||||||
unwrap(destination, ff_destination:get_machine(DestinationID))
|
unwrap(destination, ff_destination:get_machine(DestinationID))
|
||||||
),
|
),
|
||||||
ok = unwrap(destination, valid(authorized, ff_destination:status(Destination))),
|
ok = unwrap(destination, valid(authorized, ff_destination:status(Destination))),
|
||||||
Terms = unwrap(contract, get_contract_terms(Wallet, Body, ff_time:now())),
|
Terms = unwrap(contract, ff_party:get_contract_terms(Wallet, Body, ff_time:now())),
|
||||||
valid = unwrap(terms, ff_party:validate_withdrawal_creation(Terms, Body, WalletAccount)),
|
valid = unwrap(terms, ff_party:validate_withdrawal_creation(Terms, Body, WalletAccount)),
|
||||||
CashFlowPlan = unwrap(cash_flow_plan, ff_party:get_withdrawal_cash_flow_plan(Terms)),
|
CashFlowPlan = unwrap(cash_flow_plan, ff_party:get_withdrawal_cash_flow_plan(Terms)),
|
||||||
|
|
||||||
@ -271,7 +268,7 @@ create_session(Withdrawal) ->
|
|||||||
destination_account := DestinationAccount
|
destination_account := DestinationAccount
|
||||||
} = params(Withdrawal),
|
} = params(Withdrawal),
|
||||||
do(fun () ->
|
do(fun () ->
|
||||||
valid = validate_wallet_limits(WalletID, Body, WalletAccount),
|
valid = ff_party:validate_wallet_limits(WalletID, Body, WalletAccount),
|
||||||
#{provider_id := ProviderID} = route(Withdrawal),
|
#{provider_id := ProviderID} = route(Withdrawal),
|
||||||
SenderSt = unwrap(ff_identity_machine:get(ff_account:identity(WalletAccount))),
|
SenderSt = unwrap(ff_identity_machine:get(ff_account:identity(WalletAccount))),
|
||||||
ReceiverSt = unwrap(ff_identity_machine:get(ff_account:identity(DestinationAccount))),
|
ReceiverSt = unwrap(ff_identity_machine:get(ff_account:identity(DestinationAccount))),
|
||||||
@ -316,29 +313,6 @@ poll_session_completion(Withdrawal) ->
|
|||||||
end
|
end
|
||||||
end).
|
end).
|
||||||
|
|
||||||
-spec get_contract_terms(wallet(), body(), timestamp()) -> Result when
|
|
||||||
Result :: {ok, withdrawal_terms()} | {error, Error},
|
|
||||||
Error ::
|
|
||||||
{party_not_found, id()} |
|
|
||||||
{party_not_exists_yet, id()} |
|
|
||||||
{exception, any()}.
|
|
||||||
get_contract_terms(Wallet, Body, Timestamp) ->
|
|
||||||
WalletID = ff_wallet:id(Wallet),
|
|
||||||
IdentityID = ff_wallet:identity(Wallet),
|
|
||||||
do(fun() ->
|
|
||||||
IdentityMachine = unwrap(ff_identity_machine:get(IdentityID)),
|
|
||||||
Identity = ff_identity_machine:identity(IdentityMachine),
|
|
||||||
ContractID = ff_identity:contract(Identity),
|
|
||||||
PartyID = ff_identity:party(Identity),
|
|
||||||
{_Amount, CurrencyID} = Body,
|
|
||||||
TermVarset = #{
|
|
||||||
amount => Body,
|
|
||||||
wallet_id => WalletID,
|
|
||||||
currency_id => CurrencyID
|
|
||||||
},
|
|
||||||
unwrap(ff_party:get_contract_terms(PartyID, ContractID, TermVarset, Timestamp))
|
|
||||||
end).
|
|
||||||
|
|
||||||
-spec get_route_provider(route()) -> {ok, provider()}.
|
-spec get_route_provider(route()) -> {ok, provider()}.
|
||||||
get_route_provider(#{provider_id := ProviderID}) ->
|
get_route_provider(#{provider_id := ProviderID}) ->
|
||||||
ff_withdrawal_provider:get(ProviderID).
|
ff_withdrawal_provider:get(ProviderID).
|
||||||
@ -364,11 +338,6 @@ finalize_cash_flow(CashFlowPlan, WalletAccount, DestinationAccount, SystemAccoun
|
|||||||
}),
|
}),
|
||||||
ff_cash_flow:finalize(CashFlowPlan, Accounts, Constants).
|
ff_cash_flow:finalize(CashFlowPlan, Accounts, Constants).
|
||||||
|
|
||||||
validate_wallet_limits(WalletID, Body, Account) ->
|
|
||||||
Wallet = ff_wallet_machine:wallet(unwrap(wallet, ff_wallet_machine:get(WalletID))),
|
|
||||||
Terms = unwrap(contract, get_contract_terms(Wallet, Body, ff_time:now())),
|
|
||||||
unwrap(wallet_limit, ff_party:validate_wallet_limits(Account, Terms)).
|
|
||||||
|
|
||||||
-spec maybe_migrate(ff_transfer:event() | ff_transfer:legacy_event()) ->
|
-spec maybe_migrate(ff_transfer:event() | ff_transfer:legacy_event()) ->
|
||||||
ff_transfer:event().
|
ff_transfer:event().
|
||||||
maybe_migrate(Ev) ->
|
maybe_migrate(Ev) ->
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
-export([get_missing_fails/1]).
|
-export([get_missing_fails/1]).
|
||||||
-export([deposit_via_admin_ok/1]).
|
-export([deposit_via_admin_ok/1]).
|
||||||
|
-export([deposit_via_admin_bad/1]).
|
||||||
-export([deposit_withdrawal_ok/1]).
|
-export([deposit_withdrawal_ok/1]).
|
||||||
|
|
||||||
-type config() :: ct_helper:config().
|
-type config() :: ct_helper:config().
|
||||||
@ -34,6 +35,7 @@ groups() ->
|
|||||||
{default, [parallel], [
|
{default, [parallel], [
|
||||||
get_missing_fails,
|
get_missing_fails,
|
||||||
deposit_via_admin_ok,
|
deposit_via_admin_ok,
|
||||||
|
deposit_via_admin_bad,
|
||||||
deposit_withdrawal_ok
|
deposit_withdrawal_ok
|
||||||
]}
|
]}
|
||||||
].
|
].
|
||||||
@ -80,6 +82,7 @@ end_per_testcase(_Name, _C) ->
|
|||||||
|
|
||||||
-spec get_missing_fails(config()) -> test_return().
|
-spec get_missing_fails(config()) -> test_return().
|
||||||
-spec deposit_via_admin_ok(config()) -> test_return().
|
-spec deposit_via_admin_ok(config()) -> test_return().
|
||||||
|
-spec deposit_via_admin_bad(config()) -> test_return().
|
||||||
-spec deposit_withdrawal_ok(config()) -> test_return().
|
-spec deposit_withdrawal_ok(config()) -> test_return().
|
||||||
|
|
||||||
get_missing_fails(_C) ->
|
get_missing_fails(_C) ->
|
||||||
@ -131,6 +134,55 @@ deposit_via_admin_ok(C) ->
|
|||||||
),
|
),
|
||||||
ok = await_wallet_balance({20000, <<"RUB">>}, WalID).
|
ok = await_wallet_balance({20000, <<"RUB">>}, WalID).
|
||||||
|
|
||||||
|
deposit_via_admin_bad(C) ->
|
||||||
|
Party = create_party(C),
|
||||||
|
IID = create_person_identity(Party, C),
|
||||||
|
WalID = create_wallet(IID, <<"HAHA NO">>, <<"RUB">>, C),
|
||||||
|
ok = await_wallet_balance({0, <<"RUB">>}, WalID),
|
||||||
|
|
||||||
|
% Create source
|
||||||
|
{ok, Src1} = admin_call('CreateSource', [#fistful_SourceParams{
|
||||||
|
name = <<"HAHA NO">>,
|
||||||
|
identity_id = IID,
|
||||||
|
currency = #'CurrencyRef'{symbolic_code = <<"RUB">>},
|
||||||
|
resource = #fistful_SourceResource{details = <<"Infinite source of cash">>}
|
||||||
|
}]),
|
||||||
|
unauthorized = Src1#fistful_Source.status,
|
||||||
|
SrcID = Src1#fistful_Source.id,
|
||||||
|
authorized = ct_helper:await(
|
||||||
|
authorized,
|
||||||
|
fun () ->
|
||||||
|
{ok, Src} = admin_call('GetSource', [SrcID]),
|
||||||
|
Src#fistful_Source.status
|
||||||
|
end
|
||||||
|
),
|
||||||
|
% Process deposit
|
||||||
|
% dbg:tracer(),
|
||||||
|
% dbg:tp(ff_transfer_machine, []),
|
||||||
|
% dbg:tp(ff_deposit, process_transfer, 1, []),
|
||||||
|
% dbg:p(all, c),
|
||||||
|
{ok, Dep1} = admin_call('CreateDeposit', [#fistful_DepositParams{
|
||||||
|
source = SrcID,
|
||||||
|
destination = WalID,
|
||||||
|
body = #'Cash'{
|
||||||
|
amount = 10000002,
|
||||||
|
currency = #'CurrencyRef'{symbolic_code = <<"RUB">>}
|
||||||
|
}
|
||||||
|
}]),
|
||||||
|
|
||||||
|
DepID = Dep1#fistful_Deposit.id,
|
||||||
|
{pending, _} = Dep1#fistful_Deposit.status,
|
||||||
|
failed = ct_helper:await(
|
||||||
|
failed,
|
||||||
|
fun () ->
|
||||||
|
{ok, Dep} = admin_call('GetDeposit', [DepID]),
|
||||||
|
{Status, _} = Dep#fistful_Deposit.status,
|
||||||
|
Status
|
||||||
|
end,
|
||||||
|
genlib_retry:linear(15, 1000)
|
||||||
|
),
|
||||||
|
ok = await_wallet_balance({0, <<"RUB">>}, WalID).
|
||||||
|
|
||||||
deposit_withdrawal_ok(C) ->
|
deposit_withdrawal_ok(C) ->
|
||||||
Party = create_party(C),
|
Party = create_party(C),
|
||||||
IID = create_person_identity(Party, C),
|
IID = create_person_identity(Party, C),
|
||||||
@ -145,7 +197,7 @@ deposit_withdrawal_ok(C) ->
|
|||||||
DestID = create_destination(IID, C),
|
DestID = create_destination(IID, C),
|
||||||
|
|
||||||
pass_identification(ICID, IID, C),
|
pass_identification(ICID, IID, C),
|
||||||
|
|
||||||
process_withdrawal(WalID, DestID).
|
process_withdrawal(WalID, DestID).
|
||||||
|
|
||||||
create_party(_C) ->
|
create_party(_C) ->
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
{erl_opts, [
|
||||||
|
{parse_transform, lager_transform}
|
||||||
|
]}.
|
@ -43,12 +43,13 @@
|
|||||||
-export([validate_account_creation/2]).
|
-export([validate_account_creation/2]).
|
||||||
-export([validate_withdrawal_creation/3]).
|
-export([validate_withdrawal_creation/3]).
|
||||||
-export([validate_wallet_limits/2]).
|
-export([validate_wallet_limits/2]).
|
||||||
|
-export([validate_wallet_limits/3]).
|
||||||
|
-export([get_contract_terms/3]).
|
||||||
-export([get_contract_terms/4]).
|
-export([get_contract_terms/4]).
|
||||||
-export([get_withdrawal_cash_flow_plan/1]).
|
-export([get_withdrawal_cash_flow_plan/1]).
|
||||||
|
|
||||||
%% Internal types
|
%% Internal types
|
||||||
|
-type body() :: ff_transfer:body().
|
||||||
-type cash() :: ff_transaction:body().
|
-type cash() :: ff_transaction:body().
|
||||||
-type terms() :: dmsl_domain_thrift:'TermSet'().
|
-type terms() :: dmsl_domain_thrift:'TermSet'().
|
||||||
-type wallet_terms() :: dmsl_domain_thrift:'WalletServiceTerms'() | undefined.
|
-type wallet_terms() :: dmsl_domain_thrift:'WalletServiceTerms'() | undefined.
|
||||||
@ -58,6 +59,7 @@
|
|||||||
-type domain_cash() :: dmsl_domain_thrift:'Cash'().
|
-type domain_cash() :: dmsl_domain_thrift:'Cash'().
|
||||||
-type cash_range() :: dmsl_domain_thrift:'CashRange'().
|
-type cash_range() :: dmsl_domain_thrift:'CashRange'().
|
||||||
-type timestamp() :: ff_time:timestamp_ms().
|
-type timestamp() :: ff_time:timestamp_ms().
|
||||||
|
-type wallet() :: ff_wallet:wallet().
|
||||||
|
|
||||||
-type currency_validation_error() :: {terms_violation, {not_allowed_currency, _Details}}.
|
-type currency_validation_error() :: {terms_violation, {not_allowed_currency, _Details}}.
|
||||||
-type withdrawal_currency_error() :: {invalid_withdrawal_currency, currency_id(), {wallet_currency, currency_id()}}.
|
-type withdrawal_currency_error() :: {invalid_withdrawal_currency, currency_id(), {wallet_currency, currency_id()}}.
|
||||||
@ -65,7 +67,7 @@
|
|||||||
|
|
||||||
%% Pipeline
|
%% Pipeline
|
||||||
|
|
||||||
-import(ff_pipeline, [do/1, unwrap/1]).
|
-import(ff_pipeline, [do/1, unwrap/1, unwrap/2]).
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
@ -133,7 +135,28 @@ change_contractor_level(ID, ContractID, ContractorLevel) ->
|
|||||||
ok
|
ok
|
||||||
end).
|
end).
|
||||||
|
|
||||||
%%
|
-spec get_contract_terms(wallet(), body(), timestamp()) -> Result when
|
||||||
|
Result :: {ok, wallet_terms()} | {error, Error},
|
||||||
|
Error ::
|
||||||
|
{party_not_found, id()} |
|
||||||
|
{party_not_exists_yet, id()} |
|
||||||
|
{exception, any()}.
|
||||||
|
get_contract_terms(Wallet, Body, Timestamp) ->
|
||||||
|
WalletID = ff_wallet:id(Wallet),
|
||||||
|
IdentityID = ff_wallet:identity(Wallet),
|
||||||
|
do(fun() ->
|
||||||
|
IdentityMachine = unwrap(ff_identity_machine:get(IdentityID)),
|
||||||
|
Identity = ff_identity_machine:identity(IdentityMachine),
|
||||||
|
ContractID = ff_identity:contract(Identity),
|
||||||
|
PartyID = ff_identity:party(Identity),
|
||||||
|
{_Amount, CurrencyID} = Body,
|
||||||
|
TermVarset = #{
|
||||||
|
amount => Body,
|
||||||
|
wallet_id => WalletID,
|
||||||
|
currency_id => CurrencyID
|
||||||
|
},
|
||||||
|
unwrap(get_contract_terms(PartyID, ContractID, TermVarset, Timestamp))
|
||||||
|
end).
|
||||||
|
|
||||||
-spec get_contract_terms(id(), contract_id(), term_varset(), timestamp()) -> Result when
|
-spec get_contract_terms(id(), contract_id(), term_varset(), timestamp()) -> Result when
|
||||||
Result :: {ok, terms()} | {error, Error},
|
Result :: {ok, terms()} | {error, Error},
|
||||||
@ -448,6 +471,13 @@ validate_wallet_limits(Account, #domain_TermSet{wallets = WalletTerms}) ->
|
|||||||
valid = unwrap(validate_cash_range(ExpMaxCash, CashRange))
|
valid = unwrap(validate_cash_range(ExpMaxCash, CashRange))
|
||||||
end).
|
end).
|
||||||
|
|
||||||
|
-spec validate_wallet_limits(machinery:id(), body(), ff_account:account()) ->
|
||||||
|
valid | {error, cash_range_validation_error()}.
|
||||||
|
validate_wallet_limits(WalletID, Body, Account) ->
|
||||||
|
Wallet = ff_wallet_machine:wallet(unwrap(wallet, ff_wallet_machine:get(WalletID))),
|
||||||
|
Terms = unwrap(contract, get_contract_terms(Wallet, Body, ff_time:now())),
|
||||||
|
unwrap(wallet_limit, validate_wallet_limits(Account, Terms)).
|
||||||
|
|
||||||
-spec validate_wallet_limits_terms_is_reduced(wallet_terms()) ->
|
-spec validate_wallet_limits_terms_is_reduced(wallet_terms()) ->
|
||||||
{ok, valid} | {error, {invalid_terms, _Details}}.
|
{ok, valid} | {error, {invalid_terms, _Details}}.
|
||||||
validate_wallet_limits_terms_is_reduced(Terms) ->
|
validate_wallet_limits_terms_is_reduced(Terms) ->
|
||||||
|
Loading…
Reference in New Issue
Block a user