mirror of
https://github.com/valitydev/hellgate.git
synced 2024-11-06 02:45:20 +00:00
OPS-442: Add shop limits (#121)
* OPS-442: Add shop limits * Fix tests and specs * Add tests * Format * Add regression test * Fix * Update PM image
This commit is contained in:
parent
55899c876c
commit
50480643a5
@ -29,7 +29,8 @@
|
||||
timings :: undefined | hg_timings:t(),
|
||||
allocation :: undefined | hg_allocation:allocation(),
|
||||
route_limits = #{} :: hg_routing:limits(),
|
||||
route_scores = #{} :: hg_routing:scores()
|
||||
route_scores = #{} :: hg_routing:scores(),
|
||||
shop_limit_status = undefined :: undefined | initialized | finalized
|
||||
}).
|
||||
|
||||
-record(refund_st, {
|
||||
|
@ -51,6 +51,20 @@
|
||||
}}
|
||||
).
|
||||
|
||||
-define(shop_limit_initiated(),
|
||||
{
|
||||
invoice_payment_shop_limit_initiated,
|
||||
#payproc_InvoicePaymentShopLimitInitiated{}
|
||||
}
|
||||
).
|
||||
|
||||
-define(shop_limit_applied(),
|
||||
{
|
||||
invoice_payment_shop_limit_applied,
|
||||
#payproc_InvoicePaymentShopLimitApplied{}
|
||||
}
|
||||
).
|
||||
|
||||
-define(cash_flow_changed(CashFlow),
|
||||
{invoice_payment_cash_flow_changed, #payproc_InvoicePaymentCashFlowChanged{
|
||||
cash_flow = CashFlow
|
||||
|
@ -148,6 +148,9 @@
|
||||
|
||||
-type payment_step() ::
|
||||
new
|
||||
| shop_limit_initializing
|
||||
| shop_limit_failure
|
||||
| shop_limit_finalizing
|
||||
| risk_scoring
|
||||
| routing
|
||||
| routing_failure
|
||||
@ -1813,6 +1816,12 @@ process_timeout(St) ->
|
||||
repair_process_timeout(get_activity(St), Action, St).
|
||||
|
||||
-spec process_timeout(activity(), action(), st()) -> machine_result().
|
||||
process_timeout({payment, shop_limit_initializing}, Action, St) ->
|
||||
process_shop_limit_initialization(Action, St);
|
||||
process_timeout({payment, shop_limit_failure}, Action, St) ->
|
||||
process_shop_limit_failure(Action, St);
|
||||
process_timeout({payment, shop_limit_finalizing}, Action, St) ->
|
||||
process_shop_limit_finalization(Action, St);
|
||||
process_timeout({payment, risk_scoring}, Action, St) ->
|
||||
process_risk_score(Action, St);
|
||||
process_timeout({payment, routing}, Action, St) ->
|
||||
@ -1924,6 +1933,39 @@ process_callback(_Tag, _Payload, undefined, _St) ->
|
||||
throw(invalid_callback).
|
||||
|
||||
%%
|
||||
|
||||
-spec process_shop_limit_initialization(action(), st()) -> machine_result().
|
||||
process_shop_limit_initialization(Action, St) ->
|
||||
Opts = get_opts(St),
|
||||
_ = hold_shop_limits(Opts, St),
|
||||
case check_shop_limits(Opts, St) of
|
||||
ok ->
|
||||
{next, {[?shop_limit_initiated()], hg_machine_action:set_timeout(0, Action)}};
|
||||
{error, {limit_overflow = Error, IDs}} ->
|
||||
Failure = construct_shop_limit_failure(Error, IDs),
|
||||
Events = [
|
||||
?shop_limit_initiated(),
|
||||
?payment_rollback_started(Failure)
|
||||
],
|
||||
{next, {Events, hg_machine_action:set_timeout(0, Action)}}
|
||||
end.
|
||||
|
||||
construct_shop_limit_failure(limit_overflow, IDs) ->
|
||||
Error = mk_static_error([authorization_failed, shop_limit_exceeded, unknown]),
|
||||
Reason = genlib:format("Limits with following IDs overflowed: ~p", [IDs]),
|
||||
{failure, payproc_errors:construct('PaymentFailure', Error, Reason)}.
|
||||
|
||||
process_shop_limit_failure(Action, St = #st{failure = Failure}) ->
|
||||
Opts = get_opts(St),
|
||||
_ = rollback_shop_limits(Opts, St, [ignore_business_error, ignore_not_found]),
|
||||
{done, {[?payment_status_changed(?failed(Failure))], hg_machine_action:set_timeout(0, Action)}}.
|
||||
|
||||
-spec process_shop_limit_finalization(action(), st()) -> machine_result().
|
||||
process_shop_limit_finalization(Action, St) ->
|
||||
Opts = get_opts(St),
|
||||
_ = commit_shop_limits(Opts, St),
|
||||
{next, {[?shop_limit_applied()], hg_machine_action:set_timeout(0, Action)}}.
|
||||
|
||||
-spec process_risk_score(action(), st()) -> machine_result().
|
||||
process_risk_score(Action, St) ->
|
||||
Opts = get_opts(St),
|
||||
@ -2551,6 +2593,52 @@ get_limit_overflow_routes(Routes, VS, St) ->
|
||||
Routes
|
||||
).
|
||||
|
||||
%% Shop limits
|
||||
|
||||
hold_shop_limits(Opts, St) ->
|
||||
Payment = get_payment(St),
|
||||
Invoice = get_invoice(Opts),
|
||||
Party = get_party(Opts),
|
||||
Shop = get_shop(Opts),
|
||||
TurnoverLimits = get_shop_turnover_limits(Shop),
|
||||
ok = hg_limiter:hold_shop_limits(TurnoverLimits, Party, Shop, Invoice, Payment).
|
||||
|
||||
commit_shop_limits(Opts, St) ->
|
||||
Payment = get_payment(St),
|
||||
Invoice = get_invoice(Opts),
|
||||
Party = get_party(Opts),
|
||||
Shop = get_shop(Opts),
|
||||
TurnoverLimits = get_shop_turnover_limits(Shop),
|
||||
ok = hg_limiter:commit_shop_limits(TurnoverLimits, Party, Shop, Invoice, Payment).
|
||||
|
||||
check_shop_limits(Opts, St) ->
|
||||
Payment = get_payment(St),
|
||||
Invoice = get_invoice(Opts),
|
||||
TurnoverLimits = get_shop_turnover_limits(get_shop(Opts)),
|
||||
hg_limiter:check_shop_limits(TurnoverLimits, Invoice, Payment).
|
||||
|
||||
rollback_shop_limits(Opts, St, Flags) ->
|
||||
Payment = get_payment(St),
|
||||
Invoice = get_invoice(Opts),
|
||||
Party = get_party(Opts),
|
||||
Shop = get_shop(Opts),
|
||||
TurnoverLimits = get_shop_turnover_limits(Shop),
|
||||
ok = hg_limiter:rollback_shop_limits(
|
||||
TurnoverLimits,
|
||||
Party,
|
||||
Shop,
|
||||
Invoice,
|
||||
Payment,
|
||||
Flags
|
||||
).
|
||||
|
||||
get_shop_turnover_limits(#domain_Shop{turnover_limits = undefined}) ->
|
||||
[];
|
||||
get_shop_turnover_limits(#domain_Shop{turnover_limits = T}) ->
|
||||
ordsets:to_list(T).
|
||||
|
||||
%%
|
||||
|
||||
-spec hold_limit_routes([hg_route:t()], hg_varset:varset(), pos_integer(), st()) ->
|
||||
{[hg_route:t()], [hg_route:rejected_route()]}.
|
||||
hold_limit_routes(Routes0, VS, Iter, St) ->
|
||||
@ -2979,11 +3067,35 @@ merge_change(Change = ?payment_started(Payment), #st{} = St, Opts) ->
|
||||
St#st{
|
||||
target = ?processed(),
|
||||
payment = Payment,
|
||||
activity = {payment, risk_scoring},
|
||||
activity = {payment, shop_limit_initializing},
|
||||
timings = hg_timings:mark(started, define_event_timestamp(Opts))
|
||||
};
|
||||
merge_change(Change = ?shop_limit_initiated(), #st{} = St, Opts) ->
|
||||
_ = validate_transition({payment, shop_limit_initializing}, Change, St, Opts),
|
||||
St#st{
|
||||
shop_limit_status = initialized,
|
||||
activity = {payment, shop_limit_finalizing}
|
||||
};
|
||||
merge_change(Change = ?shop_limit_applied(), #st{} = St, Opts) ->
|
||||
_ = validate_transition({payment, shop_limit_finalizing}, Change, St, Opts),
|
||||
St#st{
|
||||
shop_limit_status = finalized,
|
||||
activity = {payment, risk_scoring}
|
||||
};
|
||||
merge_change(Change = ?risk_score_changed(RiskScore), #st{} = St, Opts) ->
|
||||
_ = validate_transition({payment, risk_scoring}, Change, St, Opts),
|
||||
_ = validate_transition(
|
||||
[
|
||||
{payment, S}
|
||||
|| S <- [
|
||||
risk_scoring,
|
||||
%% Added for backward compatibility
|
||||
shop_limit_initializing
|
||||
]
|
||||
],
|
||||
Change,
|
||||
St,
|
||||
Opts
|
||||
),
|
||||
St#st{
|
||||
risk_score = RiskScore,
|
||||
activity = {payment, routing}
|
||||
@ -3061,14 +3173,20 @@ merge_change(Change = ?cash_changed(_OldCash, NewCash), #st{} = St, Opts) ->
|
||||
St#st{new_cash = NewCash, new_cash_provided = true, payment = Payment1};
|
||||
merge_change(Change = ?payment_rollback_started(Failure), St, Opts) ->
|
||||
_ = validate_transition(
|
||||
[{payment, cash_flow_building}, {payment, processing_session}],
|
||||
[
|
||||
{payment, shop_limit_finalizing},
|
||||
{payment, cash_flow_building},
|
||||
{payment, processing_session}
|
||||
],
|
||||
Change,
|
||||
St,
|
||||
Opts
|
||||
),
|
||||
Activity =
|
||||
case St#st.cash_flow of
|
||||
undefined ->
|
||||
case St of
|
||||
#st{shop_limit_status = initialized} ->
|
||||
{payment, shop_limit_failure};
|
||||
#st{cash_flow = undefined} ->
|
||||
{payment, routing_failure};
|
||||
_ ->
|
||||
{payment, processing_failure}
|
||||
@ -3086,6 +3204,7 @@ merge_change(Change = ?payment_status_changed({failed, _} = Status), #st{payment
|
||||
risk_scoring,
|
||||
routing,
|
||||
cash_flow_building,
|
||||
shop_limit_failure,
|
||||
routing_failure,
|
||||
processing_failure
|
||||
]
|
||||
@ -3834,6 +3953,7 @@ get_route_cascade_behaviour(Route, Revision) ->
|
||||
|
||||
-ifdef(TEST).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-include_lib("hellgate/test/hg_ct_domain.hrl").
|
||||
|
||||
-spec test() -> _.
|
||||
|
||||
@ -3925,4 +4045,50 @@ filter_attempted_routes_test_() ->
|
||||
)
|
||||
].
|
||||
|
||||
-spec shop_limits_regression_test() -> _.
|
||||
shop_limits_regression_test() ->
|
||||
DisposableResource = #domain_DisposablePaymentResource{
|
||||
payment_tool =
|
||||
{generic, #domain_GenericPaymentTool{
|
||||
payment_service = ?pmt_srv(<<"id">>)
|
||||
}}
|
||||
},
|
||||
ContactInfo = #domain_ContactInfo{},
|
||||
Payment = #domain_InvoicePayment{
|
||||
id = <<"PaymentID">>,
|
||||
created_at = <<"Timestamp">>,
|
||||
status = ?pending(),
|
||||
cost = ?cash(1000, <<"USD">>),
|
||||
domain_revision = 1,
|
||||
flow = ?invoice_payment_flow_instant(),
|
||||
payer = ?payment_resource_payer(DisposableResource, ContactInfo)
|
||||
},
|
||||
RiskScore = low,
|
||||
Route = #domain_PaymentRoute{
|
||||
provider = ?prv(1),
|
||||
terminal = ?trm(1)
|
||||
},
|
||||
FinalCashflow = [],
|
||||
TransactionInfo = #domain_TransactionInfo{
|
||||
id = <<"TransactionID">>,
|
||||
extra = #{}
|
||||
},
|
||||
Events = [
|
||||
?payment_started(Payment),
|
||||
?risk_score_changed(RiskScore),
|
||||
?route_changed(Route),
|
||||
?cash_flow_changed(FinalCashflow),
|
||||
hg_session:wrap_event(?processed(), hg_session:create()),
|
||||
hg_session:wrap_event(?processed(), ?trx_bound(TransactionInfo)),
|
||||
hg_session:wrap_event(?processed(), ?session_finished(?session_succeeded())),
|
||||
?payment_status_changed(?processed())
|
||||
],
|
||||
ChangeOpts = #{
|
||||
invoice_id => <<"InvoiceID">>
|
||||
},
|
||||
?assertMatch(
|
||||
#st{},
|
||||
collapse_changes(Events, undefined, ChangeOpts)
|
||||
).
|
||||
|
||||
-endif.
|
||||
|
@ -85,7 +85,9 @@ init_(PaymentID, Params, Opts = #{timestamp := CreatedAt0}) ->
|
||||
|
||||
Events =
|
||||
[
|
||||
?payment_started(Payment)
|
||||
?payment_started(Payment),
|
||||
?shop_limit_initiated(),
|
||||
?shop_limit_applied()
|
||||
] ++
|
||||
RiskScoreEventList ++
|
||||
[
|
||||
|
@ -16,6 +16,8 @@
|
||||
-type cash() :: dmsl_domain_thrift:'Cash'().
|
||||
-type handling_flag() :: ignore_business_error | ignore_not_found.
|
||||
-type turnover_limit_value() :: dmsl_payproc_thrift:'TurnoverLimitValue'().
|
||||
-type party() :: hg_party:party().
|
||||
-type shop() :: dmsl_domain_thrift:'Shop'().
|
||||
|
||||
-type change_queue() :: [hg_limiter_client:limit_change()].
|
||||
|
||||
@ -23,11 +25,15 @@
|
||||
|
||||
-export([get_turnover_limits/1]).
|
||||
-export([check_limits/4]).
|
||||
-export([check_shop_limits/3]).
|
||||
-export([hold_payment_limits/5]).
|
||||
-export([hold_shop_limits/5]).
|
||||
-export([hold_refund_limits/5]).
|
||||
-export([commit_payment_limits/6]).
|
||||
-export([commit_shop_limits/5]).
|
||||
-export([commit_refund_limits/5]).
|
||||
-export([rollback_payment_limits/6]).
|
||||
-export([rollback_shop_limits/6]).
|
||||
-export([rollback_refund_limits/5]).
|
||||
-export([get_limit_values/4]).
|
||||
|
||||
@ -36,6 +42,14 @@
|
||||
terminal = TerminalRef
|
||||
}).
|
||||
|
||||
-define(party(PartyID), #domain_Party{
|
||||
id = PartyID
|
||||
}).
|
||||
|
||||
-define(shop(ShopID), #domain_Shop{
|
||||
id = ShopID
|
||||
}).
|
||||
|
||||
-spec get_turnover_limits(turnover_selector() | undefined) -> [turnover_limit()].
|
||||
get_turnover_limits(undefined) ->
|
||||
[];
|
||||
@ -76,6 +90,21 @@ check_limits(TurnoverLimits, Invoice, Payment, Route) ->
|
||||
{error, {limit_overflow, IDs, Limits}}
|
||||
end.
|
||||
|
||||
-spec check_shop_limits([turnover_limit()], invoice(), payment()) ->
|
||||
ok
|
||||
| {error, {limit_overflow, [binary()]}}.
|
||||
check_shop_limits(TurnoverLimits, Invoice, Payment) ->
|
||||
Context = gen_limit_shop_context(Invoice, Payment),
|
||||
{ok, Limits} = gather_limits(TurnoverLimits, Context, []),
|
||||
try
|
||||
ok = check_limits_(Limits, Context),
|
||||
ok
|
||||
catch
|
||||
throw:limit_overflow ->
|
||||
IDs = [T#domain_TurnoverLimit.id || T <- TurnoverLimits],
|
||||
{error, {limit_overflow, IDs}}
|
||||
end.
|
||||
|
||||
check_limits_([], _) ->
|
||||
ok;
|
||||
check_limits_([TurnoverLimitValue | TLVs], Context) ->
|
||||
@ -114,6 +143,13 @@ hold_payment_limits(TurnoverLimits, Route, Iter, Invoice, Payment) ->
|
||||
Context = gen_limit_context(Invoice, Payment, Route),
|
||||
hold(LimitChanges, get_latest_clock(), Context).
|
||||
|
||||
-spec hold_shop_limits([turnover_limit()], party(), shop(), invoice(), payment()) -> ok.
|
||||
hold_shop_limits(TurnoverLimits, Party, Shop, Invoice, Payment) ->
|
||||
ChangeIDs = [construct_shop_change_id(Party, Shop, Invoice, Payment)],
|
||||
LimitChanges = gen_limit_changes(TurnoverLimits, ChangeIDs),
|
||||
Context = gen_limit_shop_context(Invoice, Payment),
|
||||
hold(LimitChanges, get_latest_clock(), Context).
|
||||
|
||||
-spec hold_refund_limits([turnover_limit()], invoice(), payment(), refund(), route()) -> ok.
|
||||
hold_refund_limits(TurnoverLimits, Invoice, Payment, Refund, Route) ->
|
||||
ChangeIDs = [construct_refund_change_id(Invoice, Payment, Refund)],
|
||||
@ -133,6 +169,16 @@ commit_payment_limits(TurnoverLimits, Route, Iter, Invoice, Payment, CapturedCas
|
||||
ok = commit(LimitChanges, Clock, Context),
|
||||
ok = log_limit_changes(TurnoverLimits, Clock, Context).
|
||||
|
||||
-spec commit_shop_limits([turnover_limit()], party(), shop(), invoice(), payment()) -> ok.
|
||||
commit_shop_limits(TurnoverLimits, Party, Shop, Invoice, Payment) ->
|
||||
ChangeIDs = [construct_shop_change_id(Party, Shop, Invoice, Payment)],
|
||||
LimitChanges = gen_limit_changes(TurnoverLimits, ChangeIDs),
|
||||
Context = gen_limit_shop_context(Invoice, Payment),
|
||||
Clock = get_latest_clock(),
|
||||
ok = commit(LimitChanges, Clock, Context),
|
||||
ok = log_limit_changes(TurnoverLimits, Clock, Context),
|
||||
ok.
|
||||
|
||||
-spec commit_refund_limits([turnover_limit()], invoice(), payment(), refund(), route()) -> ok.
|
||||
commit_refund_limits(TurnoverLimits, Invoice, Payment, Refund, Route) ->
|
||||
ChangeIDs = [construct_refund_change_id(Invoice, Payment, Refund)],
|
||||
@ -161,6 +207,14 @@ rollback_payment_limits(TurnoverLimits, Route, Iter, Invoice, Payment, Flags) ->
|
||||
Context = gen_limit_context(Invoice, Payment, Route),
|
||||
rollback(LimitChanges, get_latest_clock(), Context, Flags).
|
||||
|
||||
-spec rollback_shop_limits([turnover_limit()], party(), shop(), invoice(), payment(), [handling_flag()]) ->
|
||||
ok.
|
||||
rollback_shop_limits(TurnoverLimits, Party, Shop, Invoice, Payment, Flags) ->
|
||||
ChangeIDs = [construct_shop_change_id(Party, Shop, Invoice, Payment)],
|
||||
LimitChanges = gen_limit_changes(TurnoverLimits, ChangeIDs),
|
||||
Context = gen_limit_shop_context(Invoice, Payment),
|
||||
rollback(LimitChanges, get_latest_clock(), Context, Flags).
|
||||
|
||||
-spec rollback_refund_limits([turnover_limit()], invoice(), payment(), refund(), route()) -> ok.
|
||||
rollback_refund_limits(TurnoverLimits, Invoice, Payment, Refund, Route) ->
|
||||
ChangeIDs = [construct_refund_change_id(Invoice, Payment, Refund)],
|
||||
@ -238,6 +292,19 @@ gen_limit_context(Invoice, Payment, Route, CapturedCash) ->
|
||||
}
|
||||
}.
|
||||
|
||||
gen_limit_shop_context(Invoice, Payment) ->
|
||||
#limiter_LimitContext{
|
||||
payment_processing = #context_payproc_Context{
|
||||
op = {invoice_payment, #context_payproc_OperationInvoicePayment{}},
|
||||
invoice = #context_payproc_Invoice{
|
||||
invoice = Invoice,
|
||||
payment = #context_payproc_InvoicePayment{
|
||||
payment = Payment
|
||||
}
|
||||
}
|
||||
}
|
||||
}.
|
||||
|
||||
gen_limit_refund_context(Invoice, Payment, Refund, Route) ->
|
||||
PaymentCtx = #context_payproc_InvoicePayment{
|
||||
payment = Payment,
|
||||
@ -290,6 +357,14 @@ construct_payment_change_id(?route(ProviderRef, TerminalRef), Iter, Invoice, Pay
|
||||
integer_to_binary(Iter)
|
||||
]).
|
||||
|
||||
construct_shop_change_id(?party(PartyID), ?shop(ShopID), Invoice, Payment) ->
|
||||
hg_utils:construct_complex_id([
|
||||
PartyID,
|
||||
ShopID,
|
||||
get_invoice_id(Invoice),
|
||||
get_payment_id(Payment)
|
||||
]).
|
||||
|
||||
construct_refund_change_id(Invoice, Payment, Refund) ->
|
||||
hg_utils:construct_complex_id([
|
||||
get_invoice_id(Invoice),
|
||||
@ -341,7 +416,7 @@ mk_limit_log_attributes(#limiter_LimitContext{
|
||||
payment = #context_payproc_InvoicePayment{
|
||||
payment = Payment,
|
||||
refund = Refund,
|
||||
route = #base_Route{provider = Provider, terminal = Terminal}
|
||||
route = Route
|
||||
}
|
||||
} = CtxInvoice,
|
||||
#domain_Cash{amount = Amount, currency = Currency} =
|
||||
@ -357,10 +432,7 @@ mk_limit_log_attributes(#limiter_LimitContext{
|
||||
boundary => undefined,
|
||||
%% Current amount with accounted change
|
||||
amount => undefined,
|
||||
route => #{
|
||||
provider_id => Provider#domain_ProviderRef.id,
|
||||
terminal_id => Terminal#domain_TerminalRef.id
|
||||
},
|
||||
route => maybe_route_context(Route),
|
||||
party_id => PartyID,
|
||||
shop_id => ShopID,
|
||||
change => #{
|
||||
@ -368,3 +440,11 @@ mk_limit_log_attributes(#limiter_LimitContext{
|
||||
currency => Currency#domain_CurrencyRef.symbolic_code
|
||||
}
|
||||
}.
|
||||
|
||||
maybe_route_context(undefined) ->
|
||||
undefined;
|
||||
maybe_route_context(#base_Route{provider = Provider, terminal = Terminal}) ->
|
||||
#{
|
||||
provider_id => Provider#domain_ProviderRef.id,
|
||||
terminal_id => Terminal#domain_TerminalRef.id
|
||||
}.
|
||||
|
@ -12,6 +12,7 @@
|
||||
-export([create_party_and_shop/6]).
|
||||
-export([create_party/2]).
|
||||
-export([create_shop/6]).
|
||||
-export([create_shop/7]).
|
||||
-export([create_battle_ready_shop/6]).
|
||||
-export([adjust_contract/4]).
|
||||
|
||||
@ -350,6 +351,8 @@ create_client_w_context(RootUrl, WoodyCtx) ->
|
||||
-type party() :: dmsl_domain_thrift:'Party'().
|
||||
-type contract_id() :: dmsl_domain_thrift:'ContractID'().
|
||||
-type contract_tpl() :: dmsl_domain_thrift:'ContractTemplateRef'().
|
||||
-type turnover_limit() :: dmsl_domain_thrift:'TurnoverLimit'().
|
||||
-type turnover_limits() :: ordsets:ordset(turnover_limit()).
|
||||
-type shop_id() :: dmsl_domain_thrift:'ShopID'().
|
||||
-type category() :: dmsl_domain_thrift:'CategoryRef'().
|
||||
-type cash() :: dmsl_domain_thrift:'Cash'().
|
||||
@ -390,9 +393,34 @@ create_shop(PartyID, Category, Currency, TemplateRef, PaymentInstRef, PartyClien
|
||||
{ok, _Claim} = party_client_thrift:create_claim(PartyID, Changeset, Client, Context),
|
||||
ok
|
||||
end,
|
||||
create_shop_(PartyID, Category, Currency, TemplateRef, PaymentInstRef, PartyClient, Fun).
|
||||
create_shop_(PartyID, Category, Currency, TemplateRef, PaymentInstRef, undefined, PartyClient, Fun).
|
||||
|
||||
create_shop_(PartyID, Category, Currency, TemplateRef, PaymentInstRef, {Client, Context}, CreateShopFun) ->
|
||||
-spec create_shop(
|
||||
party_id(),
|
||||
category(),
|
||||
currency(),
|
||||
contract_tpl(),
|
||||
payment_inst_ref(),
|
||||
turnover_limits(),
|
||||
party_client()
|
||||
) -> shop_id().
|
||||
create_shop(PartyID, Category, Currency, TemplateRef, PaymentInstRef, TurnoverLimits, PartyClient) ->
|
||||
Fun = fun(_, Changeset, Client, Context) ->
|
||||
{ok, _Claim} = party_client_thrift:create_claim(PartyID, Changeset, Client, Context),
|
||||
ok
|
||||
end,
|
||||
create_shop_(PartyID, Category, Currency, TemplateRef, PaymentInstRef, TurnoverLimits, PartyClient, Fun).
|
||||
|
||||
create_shop_(
|
||||
PartyID,
|
||||
Category,
|
||||
Currency,
|
||||
TemplateRef,
|
||||
PaymentInstRef,
|
||||
TurnoverLimits0,
|
||||
{Client, Context},
|
||||
CreateShopFun
|
||||
) ->
|
||||
ShopID = hg_utils:unique_id(),
|
||||
ContractID = hg_utils:unique_id(),
|
||||
PayoutToolID = hg_utils:unique_id(),
|
||||
@ -403,6 +431,8 @@ create_shop_(PartyID, Category, Currency, TemplateRef, PaymentInstRef, {Client,
|
||||
ContractParams = make_contract_params(TemplateRef, PaymentInstRef),
|
||||
PayoutToolParams = make_payout_tool_params(),
|
||||
|
||||
TurnoverLimits1 = genlib:define(TurnoverLimits0, ordsets:new()),
|
||||
|
||||
Changeset = [
|
||||
{contract_modification, #payproc_ContractModificationUnit{
|
||||
id = ContractID,
|
||||
@ -417,7 +447,8 @@ create_shop_(PartyID, Category, Currency, TemplateRef, PaymentInstRef, {Client,
|
||||
}}
|
||||
}},
|
||||
?shop_modification(ShopID, {creation, ShopParams}),
|
||||
?shop_modification(ShopID, {shop_account_creation, ShopAccountParams})
|
||||
?shop_modification(ShopID, {shop_account_creation, ShopAccountParams}),
|
||||
?shop_modification(ShopID, {turnover_limits_modification, TurnoverLimits1})
|
||||
],
|
||||
|
||||
ok = CreateShopFun(PartyID, Changeset, Client, Context),
|
||||
@ -465,7 +496,7 @@ create_battle_ready_shop(PartyID, Category, Currency, TemplateRef, PaymentInstRe
|
||||
Fun = fun(_, Changeset, _, _) ->
|
||||
create_claim(PartyID, Changeset, PartyPair)
|
||||
end,
|
||||
create_shop_(PartyID, Category, Currency, TemplateRef, PaymentInstRef, PartyPair, Fun).
|
||||
create_shop_(PartyID, Category, Currency, TemplateRef, PaymentInstRef, undefined, PartyPair, Fun).
|
||||
|
||||
-spec adjust_contract(party_id(), contract_id(), contract_tpl(), party_client()) -> ok.
|
||||
adjust_contract(PartyID, ContractID, TemplateRef, Client) ->
|
||||
|
@ -26,7 +26,7 @@
|
||||
register_payment/4,
|
||||
start_payment/3,
|
||||
start_payment_ev/2,
|
||||
start_payment_ev_no_risk_scoring/2,
|
||||
register_payment_ev_no_risk_scoring/2,
|
||||
await_payment_session_started/4,
|
||||
await_payment_capture/3,
|
||||
await_payment_capture/4,
|
||||
@ -237,7 +237,7 @@ register_payment(InvoiceID, RegisterPaymentParams, WithRiskScoring, Client) ->
|
||||
true ->
|
||||
start_payment_ev(InvoiceID, Client);
|
||||
false ->
|
||||
start_payment_ev_no_risk_scoring(InvoiceID, Client)
|
||||
register_payment_ev_no_risk_scoring(InvoiceID, Client)
|
||||
end,
|
||||
?payment_ev(PaymentID, ?cash_flow_changed(_)) =
|
||||
next_change(InvoiceID, Client),
|
||||
@ -255,17 +255,21 @@ start_payment(InvoiceID, PaymentParams, Client) ->
|
||||
start_payment_ev(InvoiceID, Client) ->
|
||||
[
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_RiskScore)),
|
||||
?payment_ev(PaymentID, ?route_changed(Route))
|
||||
] = next_changes(InvoiceID, 3, Client),
|
||||
] = next_changes(InvoiceID, 5, Client),
|
||||
Route.
|
||||
|
||||
-spec start_payment_ev_no_risk_scoring(_, _) -> _.
|
||||
start_payment_ev_no_risk_scoring(InvoiceID, Client) ->
|
||||
-spec register_payment_ev_no_risk_scoring(_, _) -> _.
|
||||
register_payment_ev_no_risk_scoring(InvoiceID, Client) ->
|
||||
[
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?route_changed(Route))
|
||||
] = next_changes(InvoiceID, 2, Client),
|
||||
] = next_changes(InvoiceID, 4, Client),
|
||||
Route.
|
||||
|
||||
-spec await_payment_session_started(_, _, _, _) -> _.
|
||||
@ -322,10 +326,12 @@ await_payment_capture_finish(InvoiceID, PaymentID, Reason, Cost, Cart, Client) -
|
||||
-spec await_payment_cash_flow(_, _, _) -> _.
|
||||
await_payment_cash_flow(InvoiceID, PaymentID, Client) ->
|
||||
[
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_)),
|
||||
?payment_ev(PaymentID, ?route_changed(Route)),
|
||||
?payment_ev(PaymentID, ?cash_flow_changed(CashFlow))
|
||||
] = next_changes(InvoiceID, 3, Client),
|
||||
] = next_changes(InvoiceID, 5, Client),
|
||||
{CashFlow, Route}.
|
||||
|
||||
-spec construct_ta_context(_, _, _) -> _.
|
||||
|
@ -232,10 +232,12 @@ payment_w_all_blacklisted(C) ->
|
||||
?payment_state(?payment(PaymentID)) = hg_client_invoicing:start_payment(InvoiceID, PaymentParams, Client),
|
||||
[
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_RiskScore)),
|
||||
?payment_ev(PaymentID, ?route_changed(_Route)),
|
||||
?payment_ev(PaymentID, ?payment_rollback_started({failure, _Failure}))
|
||||
] = next_changes(InvoiceID, 4, Client),
|
||||
] = next_changes(InvoiceID, 6, Client),
|
||||
?invoice_state(
|
||||
?invoice_w_status(?invoice_unpaid()),
|
||||
[_PaymentSt]
|
||||
|
@ -37,6 +37,9 @@
|
||||
-export([invalid_payment_amount/1]).
|
||||
|
||||
-export([payment_limit_success/1]).
|
||||
-export([payment_shop_limit_success/1]).
|
||||
-export([payment_shop_limit_overflow/1]).
|
||||
-export([payment_shop_limit_more_overflow/1]).
|
||||
-export([payment_routes_limit_values/1]).
|
||||
-export([register_payment_limit_success/1]).
|
||||
-export([payment_limit_other_shop_success/1]).
|
||||
@ -220,11 +223,13 @@ init([]) ->
|
||||
|
||||
-define(PARTY_ID_WITH_LIMIT, <<"bIg merch limit">>).
|
||||
-define(PARTY_ID_WITH_SEVERAL_LIMITS, <<"bIg merch limit cascading">>).
|
||||
-define(PARTY_ID_WITH_SHOP_LIMITS, <<"small merch limit shop">>).
|
||||
-define(PARTYID_EXTERNAL, <<"DUBTV">>).
|
||||
-define(LIMIT_ID, <<"ID">>).
|
||||
-define(LIMIT_ID2, <<"ID2">>).
|
||||
-define(LIMIT_ID3, <<"ID3">>).
|
||||
-define(LIMIT_ID4, <<"ID4">>).
|
||||
-define(SHOPLIMIT_ID, <<"SHOPLIMITID">>).
|
||||
-define(LIMIT_UPPER_BOUNDARY, 100000).
|
||||
-define(BIG_LIMIT_UPPER_BOUNDARY, 1000000).
|
||||
-define(DEFAULT_NEXT_CHANGE_TIMEOUT, 12000).
|
||||
@ -378,6 +383,9 @@ groups() ->
|
||||
|
||||
{operation_limits, [], [
|
||||
payment_limit_success,
|
||||
payment_shop_limit_success,
|
||||
payment_shop_limit_overflow,
|
||||
payment_shop_limit_more_overflow,
|
||||
payment_routes_limit_values,
|
||||
register_payment_limit_success,
|
||||
payment_limit_other_shop_success,
|
||||
@ -1100,9 +1108,18 @@ register_invoice_payment(Route, ShopID, Client, C) ->
|
||||
init_operation_limits_group(C) ->
|
||||
PartyID1 = ?PARTY_ID_WITH_LIMIT,
|
||||
PartyID2 = ?PARTY_ID_WITH_SEVERAL_LIMITS,
|
||||
PartyID3 = ?PARTY_ID_WITH_SHOP_LIMITS,
|
||||
_ = hg_ct_helper:create_party(PartyID1, cfg(party_client, C)),
|
||||
_ = hg_ct_helper:create_party(PartyID2, cfg(party_client, C)),
|
||||
[{limits, #{party_id => PartyID1, party_id_w_several_limits => PartyID2}} | C].
|
||||
_ = hg_ct_helper:create_party(PartyID3, cfg(party_client, C)),
|
||||
[
|
||||
{limits, #{
|
||||
party_id => PartyID1,
|
||||
party_id_w_several_limits => PartyID2,
|
||||
party_id_w_shop_limits => PartyID3
|
||||
}}
|
||||
| C
|
||||
].
|
||||
|
||||
-spec payment_limit_success(config()) -> test_return().
|
||||
payment_limit_success(C) ->
|
||||
@ -1117,6 +1134,78 @@ payment_limit_success(C) ->
|
||||
[?payment_state(_Payment)]
|
||||
) = create_payment(PartyID, ShopID, 10000, Client, ?pmt_sys(<<"visa-ref">>)).
|
||||
|
||||
-spec payment_shop_limit_success(config()) -> test_return().
|
||||
payment_shop_limit_success(C) ->
|
||||
RootUrl = cfg(root_url, C),
|
||||
PartyClient = cfg(party_client, C),
|
||||
PartyID = cfg(party_id_big_merch, C),
|
||||
TurnoverLimits = [
|
||||
#domain_TurnoverLimit{
|
||||
id = ?SHOPLIMIT_ID,
|
||||
upper_boundary = ?LIMIT_UPPER_BOUNDARY,
|
||||
domain_revision = dmt_client:get_last_version()
|
||||
}
|
||||
],
|
||||
ShopID = hg_ct_helper:create_shop(PartyID, ?cat(1), <<"RUB">>, ?tmpl(1), ?pinst(1), TurnoverLimits, PartyClient),
|
||||
Client = hg_client_invoicing:start_link(hg_ct_helper:create_client(RootUrl)),
|
||||
|
||||
PaymentAmount = ?LIMIT_UPPER_BOUNDARY - 1,
|
||||
?invoice_state(
|
||||
?invoice_w_status(?invoice_paid()),
|
||||
[?payment_state(_Payment)]
|
||||
) = create_payment(PartyID, ShopID, PaymentAmount, Client, ?pmt_sys(<<"visa-ref">>)).
|
||||
|
||||
-spec payment_shop_limit_overflow(config()) -> test_return().
|
||||
payment_shop_limit_overflow(C) ->
|
||||
RootUrl = cfg(root_url, C),
|
||||
PartyClient = cfg(party_client, C),
|
||||
PartyID = cfg(party_id_big_merch, C),
|
||||
TurnoverLimits = ordsets:from_list([
|
||||
#domain_TurnoverLimit{
|
||||
id = ?SHOPLIMIT_ID,
|
||||
upper_boundary = ?LIMIT_UPPER_BOUNDARY,
|
||||
domain_revision = dmt_client:get_last_version()
|
||||
}
|
||||
]),
|
||||
ShopID = hg_ct_helper:create_shop(PartyID, ?cat(1), <<"RUB">>, ?tmpl(1), ?pinst(1), TurnoverLimits, PartyClient),
|
||||
Client = hg_client_invoicing:start_link(hg_ct_helper:create_client(RootUrl)),
|
||||
|
||||
PaymentAmount = ?LIMIT_UPPER_BOUNDARY + 1,
|
||||
Failure = create_payment_shop_limit_overflow(PartyID, ShopID, PaymentAmount, Client, ?pmt_sys(<<"visa-ref">>)),
|
||||
ok = payproc_errors:match('PaymentFailure', Failure, fun(
|
||||
{authorization_failed, {shop_limit_exceeded, {unknown, _}}}
|
||||
) ->
|
||||
ok
|
||||
end).
|
||||
|
||||
-spec payment_shop_limit_more_overflow(config()) -> test_return().
|
||||
payment_shop_limit_more_overflow(C) ->
|
||||
RootUrl = cfg(root_url, C),
|
||||
PartyClient = cfg(party_client, C),
|
||||
PartyID = cfg(party_id_big_merch, C),
|
||||
TurnoverLimits = ordsets:from_list([
|
||||
#domain_TurnoverLimit{
|
||||
id = ?SHOPLIMIT_ID,
|
||||
upper_boundary = ?LIMIT_UPPER_BOUNDARY,
|
||||
domain_revision = dmt_client:get_last_version()
|
||||
}
|
||||
]),
|
||||
ShopID = hg_ct_helper:create_shop(PartyID, ?cat(1), <<"RUB">>, ?tmpl(1), ?pinst(1), TurnoverLimits, PartyClient),
|
||||
Client = hg_client_invoicing:start_link(hg_ct_helper:create_client(RootUrl)),
|
||||
|
||||
PaymentAmount = ?LIMIT_UPPER_BOUNDARY - 1,
|
||||
?invoice_state(
|
||||
?invoice_w_status(?invoice_paid()),
|
||||
[?payment_state(_Payment)]
|
||||
) = create_payment(PartyID, ShopID, PaymentAmount, Client, ?pmt_sys(<<"visa-ref">>)),
|
||||
|
||||
Failure = create_payment_shop_limit_overflow(PartyID, ShopID, PaymentAmount, Client, ?pmt_sys(<<"visa-ref">>)),
|
||||
ok = payproc_errors:match('PaymentFailure', Failure, fun(
|
||||
{authorization_failed, {shop_limit_exceeded, {unknown, _}}}
|
||||
) ->
|
||||
ok
|
||||
end).
|
||||
|
||||
-spec payment_routes_limit_values(config()) -> test_return().
|
||||
payment_routes_limit_values(C) ->
|
||||
RootUrl = cfg(root_url, C),
|
||||
@ -1386,6 +1475,15 @@ create_payment_limit_overflow(PartyID, ShopID, Amount, Client, PmtSys) ->
|
||||
PaymentID = await_payment_started(InvoiceID, PaymentID, Client),
|
||||
await_payment_rollback(InvoiceID, PaymentID, Client).
|
||||
|
||||
create_payment_shop_limit_overflow(PartyID, ShopID, Amount, Client, PmtSys) ->
|
||||
InvoiceParams = make_invoice_params(PartyID, ShopID, <<"rubberduck">>, make_due_date(10), make_cash(Amount)),
|
||||
InvoiceID = create_invoice(InvoiceParams, Client),
|
||||
?invoice_created(?invoice_w_status(?invoice_unpaid())) = next_change(InvoiceID, Client),
|
||||
PaymentParams = make_payment_params(PmtSys),
|
||||
?payment_state(?payment(PaymentID)) = hg_client_invoicing:start_payment(InvoiceID, PaymentParams, Client),
|
||||
PaymentID = await_payment_started(InvoiceID, PaymentID, Client),
|
||||
await_payment_shop_limit_rollback(InvoiceID, PaymentID, Client).
|
||||
|
||||
%%----------------- operation_limits group end
|
||||
|
||||
-spec payment_success_ruleset(config()) -> test_return().
|
||||
@ -1435,9 +1533,11 @@ payment_w_misconfigured_routing_failed(C) ->
|
||||
?payment_state(?payment(PaymentID)) = hg_client_invoicing:start_payment(InvoiceID, PaymentParams, Client),
|
||||
[
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_)),
|
||||
?payment_ev(PaymentID, ?payment_status_changed(?failed({failure, Failure})))
|
||||
] = next_changes(InvoiceID, 3, Client),
|
||||
] = next_changes(InvoiceID, 5, Client),
|
||||
Reason = genlib:format({routing_decisions, {delegates, []}}),
|
||||
?assertRouteNotFound(Failure, {unknown, {{unknown_error, <<"misconfiguration">>}, _}}, Reason).
|
||||
|
||||
@ -2193,10 +2293,12 @@ payment_risk_score_check(C) ->
|
||||
?payment_state(?payment(PaymentID3)) = hg_client_invoicing:start_payment(InvoiceID3, PaymentParams, Client),
|
||||
[
|
||||
?payment_ev(PaymentID3, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
% fatal risk score is not going to be covered
|
||||
?payment_ev(PaymentID3, ?risk_score_changed(fatal)),
|
||||
?payment_ev(PaymentID3, ?payment_status_changed(?failed({failure, Failure})))
|
||||
] = next_changes(InvoiceID3, 3, Client),
|
||||
] = next_changes(InvoiceID3, 5, Client),
|
||||
ok = payproc_errors:match(
|
||||
'PaymentFailure',
|
||||
Failure,
|
||||
@ -2721,7 +2823,7 @@ registered_payment_adjustment_success(C) ->
|
||||
},
|
||||
?payment_state(?payment(PaymentID)) =
|
||||
hg_client_invoicing:register_payment(InvoiceID, PaymentParams, Client),
|
||||
_ = start_payment_ev_no_risk_scoring(InvoiceID, Client),
|
||||
_ = register_payment_ev_no_risk_scoring(InvoiceID, Client),
|
||||
?payment_ev(PaymentID, ?cash_flow_changed(CF1)) =
|
||||
next_change(InvoiceID, Client),
|
||||
PaymentID = await_payment_session_started(InvoiceID, PaymentID, Client, ?processed()),
|
||||
@ -5100,8 +5202,12 @@ repair_fail_routing_succeeded(C) ->
|
||||
%% Payment
|
||||
PaymentParams = make_payment_params(?pmt_sys(<<"visa-ref">>)),
|
||||
?payment_state(?payment(PaymentID)) = hg_client_invoicing:start_payment(InvoiceID, PaymentParams, Client),
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))) = next_change(InvoiceID, Client),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_RS)) = next_change(InvoiceID, Client),
|
||||
[
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_))
|
||||
] = next_changes(InvoiceID, 4, Client),
|
||||
%% routing broken
|
||||
timeout = next_change(InvoiceID, 2000, Client),
|
||||
|
||||
@ -5154,9 +5260,13 @@ repair_fail_cash_flow_building_succeeded(C) ->
|
||||
%% Payment
|
||||
PaymentParams = make_payment_params(?pmt_sys(<<"visa-ref">>)),
|
||||
?payment_state(?payment(PaymentID)) = hg_client_invoicing:start_payment(InvoiceID, PaymentParams, Client),
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))) = next_change(InvoiceID, Client),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_RS)) = next_change(InvoiceID, Client),
|
||||
?payment_ev(PaymentID, ?route_changed(Route)) = next_change(InvoiceID, Client),
|
||||
[
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_)),
|
||||
?payment_ev(PaymentID, ?route_changed(Route))
|
||||
] = next_changes(InvoiceID, 5, Client),
|
||||
%% cash_flow_building broken
|
||||
timeout = next_change(InvoiceID, 2000, Client),
|
||||
|
||||
@ -6075,10 +6185,12 @@ payment_cascade_success(C) ->
|
||||
?invoice_created(?invoice_w_status(?invoice_unpaid())) = next_change(InvoiceID, Client),
|
||||
{ok, Limit} = hg_limiter_helper:get_payment_limit_amount(?LIMIT_ID4, hg_domain:head(), Payment, Invoice),
|
||||
InitialAccountedAmount = hg_limiter_helper:get_amount(Limit),
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))) =
|
||||
next_change(InvoiceID, Client),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_)) =
|
||||
next_change(InvoiceID, Client),
|
||||
[
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_))
|
||||
] = next_changes(InvoiceID, 4, Client),
|
||||
{Route1, _CashFlow1, TrxID1, Failure1} =
|
||||
await_cascade_triggering(InvoiceID, PaymentID, Client),
|
||||
ok = payproc_errors:match('PaymentFailure', Failure1, fun({preauthorization_failed, {card_blocked, _}}) -> ok end),
|
||||
@ -6461,10 +6573,12 @@ payment_cascade_limit_overflow(C) ->
|
||||
?invoice_created(?invoice_w_status(?invoice_unpaid())) = next_change(InvoiceID, Client),
|
||||
{ok, Limit} = hg_limiter_helper:get_payment_limit_amount(?LIMIT_ID4, hg_domain:head(), Payment, Invoice),
|
||||
InitialAccountedAmount = hg_limiter_helper:get_amount(Limit),
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))) =
|
||||
next_change(InvoiceID, Client),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_)) =
|
||||
next_change(InvoiceID, Client),
|
||||
[
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_))
|
||||
] = next_changes(InvoiceID, 4, Client),
|
||||
{Route1, _CashFlow1, _TrxID1, Failure1} =
|
||||
await_cascade_triggering(InvoiceID, PaymentID, Client),
|
||||
ok = payproc_errors:match('PaymentFailure', Failure1, fun({authorization_failed, {unknown, _}}) -> ok end),
|
||||
@ -6515,10 +6629,12 @@ payment_big_cascade_success(C) ->
|
||||
?invoice_created(?invoice_w_status(?invoice_unpaid())) = next_change(InvoiceID, Client),
|
||||
{ok, Limit} = hg_limiter_helper:get_payment_limit_amount(?LIMIT_ID4, hg_domain:head(), Payment, Invoice),
|
||||
InitialAccountedAmount = hg_limiter_helper:get_amount(Limit),
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))) =
|
||||
next_change(InvoiceID, Client),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_)) =
|
||||
next_change(InvoiceID, Client),
|
||||
[
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_))
|
||||
] = next_changes(InvoiceID, 4, Client),
|
||||
[
|
||||
(fun() ->
|
||||
{_Route, _CashFlow, _TrxID, Failure} =
|
||||
@ -6672,10 +6788,12 @@ payment_cascade_fail_provider_error(C) ->
|
||||
{PaymentTool, Session} = hg_dummy_provider:make_payment_tool(no_preauth, ?pmt_sys(<<"visa-ref">>)),
|
||||
PaymentParams = make_payment_params(PaymentTool, Session, instant),
|
||||
hg_client_invoicing:start_payment(InvoiceID, PaymentParams, Client),
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))) =
|
||||
next_change(InvoiceID, Client),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_)) =
|
||||
next_change(InvoiceID, Client),
|
||||
[
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_))
|
||||
] = next_changes(InvoiceID, 4, Client),
|
||||
{_Route1, _CashFlow1, _TrxID1, Failure1} =
|
||||
await_cascade_triggering(InvoiceID, PaymentID, Client),
|
||||
%% And again
|
||||
@ -6774,10 +6892,12 @@ payment_cascade_fail_ui(C) ->
|
||||
{PaymentTool, Session} = hg_dummy_provider:make_payment_tool(preauth_3ds, ?pmt_sys(<<"visa-ref">>)),
|
||||
PaymentParams = make_payment_params(PaymentTool, Session, instant),
|
||||
hg_client_invoicing:start_payment(InvoiceID, PaymentParams, Client),
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))) =
|
||||
next_change(InvoiceID, Client),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_)) =
|
||||
next_change(InvoiceID, Client),
|
||||
[
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_))
|
||||
] = next_changes(InvoiceID, 4, Client),
|
||||
{_Route1, _CashFlow1, _TrxID1, Failure1} =
|
||||
await_cascade_triggering(InvoiceID, PaymentID, Client),
|
||||
ok = payproc_errors:match('PaymentFailure', Failure1, fun({authorization_failed, {unknown, _}}) -> ok end),
|
||||
@ -6983,10 +7103,12 @@ payment_cascade_fail_wo_available_attempt_limit(C) ->
|
||||
{PaymentTool, Session} = hg_dummy_provider:make_payment_tool(no_preauth, ?pmt_sys(<<"visa-ref">>)),
|
||||
PaymentParams = make_payment_params(PaymentTool, Session, instant),
|
||||
hg_client_invoicing:start_payment(InvoiceID, PaymentParams, Client),
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))) =
|
||||
next_change(InvoiceID, Client),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_)) =
|
||||
next_change(InvoiceID, Client),
|
||||
[
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_))
|
||||
] = next_changes(InvoiceID, 4, Client),
|
||||
{_Route, _CashFlow, _TrxID, Failure} =
|
||||
await_cascade_triggering(InvoiceID, PaymentID, Client),
|
||||
?payment_ev(PaymentID, ?payment_status_changed(?failed({failure, Failure}))) =
|
||||
@ -7071,10 +7193,12 @@ payment_cascade_failures(C) ->
|
||||
{PaymentTool, Session} = hg_dummy_provider:make_payment_tool(no_preauth, ?pmt_sys(<<"visa-ref">>)),
|
||||
PaymentParams = make_payment_params(PaymentTool, Session, instant),
|
||||
hg_client_invoicing:start_payment(InvoiceID, PaymentParams, Client),
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))) =
|
||||
next_change(InvoiceID, Client),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_)) =
|
||||
next_change(InvoiceID, Client),
|
||||
[
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_))
|
||||
] = next_changes(InvoiceID, 4, Client),
|
||||
{_Route1, _CashFlow1, _TrxID1, Failure1} =
|
||||
await_cascade_triggering(InvoiceID, PaymentID, Client),
|
||||
ok = payproc_errors:match('PaymentFailure', Failure1, fun({preauthorization_failed, {card_blocked, _}}) -> ok end),
|
||||
@ -7170,10 +7294,12 @@ payment_cascade_deadline_failures(C) ->
|
||||
processing_deadline = hg_datetime:add_time_span(#base_TimeSpan{seconds = 2}, hg_datetime:format_now())
|
||||
},
|
||||
hg_client_invoicing:start_payment(InvoiceID, PaymentParams, Client),
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))) =
|
||||
next_change(InvoiceID, Client),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_)) =
|
||||
next_change(InvoiceID, Client),
|
||||
[
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_))
|
||||
] = next_changes(InvoiceID, 4, Client),
|
||||
{_Route1, _CashFlow1, _TrxID1, Failure1} =
|
||||
await_cascade_triggering(InvoiceID, PaymentID, Client),
|
||||
ok = payproc_errors:match('PaymentFailure', Failure1, fun({preauthorization_failed, {card_blocked, _}}) -> ok end),
|
||||
@ -7481,8 +7607,8 @@ register_payment(InvoiceID, RegisterPaymentParams, WithRiskScoring, Client) ->
|
||||
start_payment_ev(InvoiceID, Client) ->
|
||||
hg_invoice_helper:start_payment_ev(InvoiceID, Client).
|
||||
|
||||
start_payment_ev_no_risk_scoring(InvoiceID, Client) ->
|
||||
hg_invoice_helper:start_payment_ev_no_risk_scoring(InvoiceID, Client).
|
||||
register_payment_ev_no_risk_scoring(InvoiceID, Client) ->
|
||||
hg_invoice_helper:register_payment_ev_no_risk_scoring(InvoiceID, Client).
|
||||
|
||||
process_payment(InvoiceID, PaymentParams, Client) ->
|
||||
hg_invoice_helper:process_payment(InvoiceID, PaymentParams, Client).
|
||||
@ -7497,18 +7623,29 @@ await_payment_cash_flow(InvoiceID, PaymentID, Client) ->
|
||||
|
||||
await_payment_cash_flow(RS, Route, InvoiceID, PaymentID, Client) ->
|
||||
[
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(RS)),
|
||||
?payment_ev(PaymentID, ?route_changed(Route)),
|
||||
?payment_ev(PaymentID, ?cash_flow_changed(CashFlow))
|
||||
] = next_changes(InvoiceID, 3, Client),
|
||||
] = next_changes(InvoiceID, 5, Client),
|
||||
CashFlow.
|
||||
|
||||
await_payment_rollback(InvoiceID, PaymentID, Client) ->
|
||||
[
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_)),
|
||||
?payment_ev(PaymentID, ?route_changed(_, _)),
|
||||
?payment_ev(PaymentID, ?payment_rollback_started({failure, Failure}))
|
||||
] = next_changes(InvoiceID, 3, Client),
|
||||
] = next_changes(InvoiceID, 5, Client),
|
||||
Failure.
|
||||
|
||||
await_payment_shop_limit_rollback(InvoiceID, PaymentID, Client) ->
|
||||
[
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?payment_rollback_started({failure, Failure}))
|
||||
] = next_changes(InvoiceID, 2, Client),
|
||||
Failure.
|
||||
|
||||
await_payment_session_started(InvoiceID, PaymentID, Client, Target) ->
|
||||
@ -7710,9 +7847,11 @@ execute_payment_w_cascade(InvoiceID, Params, Client, CascadeCount) when CascadeC
|
||||
#payproc_InvoicePayment{payment = _Payment} = hg_client_invoicing:start_payment(InvoiceID, Params, Client),
|
||||
[
|
||||
?payment_ev(PaymentID, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID, ?risk_score_changed(_))
|
||||
] =
|
||||
next_changes(InvoiceID, 2, Client),
|
||||
next_changes(InvoiceID, 4, Client),
|
||||
FailedRoutes = [
|
||||
begin
|
||||
{Route, _CashFlow, _TrxID, _Failure} =
|
||||
@ -7856,9 +7995,11 @@ payment_customer_risk_score_check(C) ->
|
||||
?payment_state(?payment(PaymentID1)) = hg_client_invoicing:start_payment(InvoiceID1, PaymentParams, Client),
|
||||
[
|
||||
?payment_ev(PaymentID1, ?payment_started(?payment_w_status(?pending()))),
|
||||
?payment_ev(PaymentID, ?shop_limit_initiated()),
|
||||
?payment_ev(PaymentID, ?shop_limit_applied()),
|
||||
?payment_ev(PaymentID1, ?risk_score_changed(fatal)),
|
||||
?payment_ev(PaymentID1, ?payment_status_changed(?failed(Failure)))
|
||||
] = next_changes(InvoiceID1, 3, Client),
|
||||
] = next_changes(InvoiceID1, 5, Client),
|
||||
{failure, #domain_Failure{
|
||||
code = <<"no_route_found">>,
|
||||
sub = #domain_SubFailure{code = <<"risk_score_is_too_high">>}
|
||||
|
@ -23,13 +23,15 @@
|
||||
-define(LIMIT_ID2, <<"ID2">>).
|
||||
-define(LIMIT_ID3, <<"ID3">>).
|
||||
-define(LIMIT_ID4, <<"ID4">>).
|
||||
-define(SHOPLIMIT_ID, <<"SHOPLIMITID">>).
|
||||
|
||||
-spec init_per_suite(config()) -> _.
|
||||
init_per_suite(_Config) ->
|
||||
_ = dmt_client:upsert({limit_config, mk_config_object(?LIMIT_ID)}),
|
||||
_ = dmt_client:upsert({limit_config, mk_config_object(?LIMIT_ID2)}),
|
||||
_ = dmt_client:upsert({limit_config, mk_config_object(?LIMIT_ID3)}),
|
||||
_ = dmt_client:upsert({limit_config, mk_config_object(?LIMIT_ID4)}).
|
||||
_ = dmt_client:upsert({limit_config, mk_config_object(?LIMIT_ID4)}),
|
||||
_ = dmt_client:upsert({limit_config, mk_config_object(?SHOPLIMIT_ID)}).
|
||||
|
||||
-spec get_amount(_) -> pos_integer().
|
||||
get_amount(#limiter_Limit{amount = Amount}) ->
|
||||
|
@ -97,7 +97,7 @@ services:
|
||||
disable: true
|
||||
|
||||
party-management:
|
||||
image: ghcr.io/valitydev/party-management:sha-28c1b38
|
||||
image: ghcr.io/valitydev/party-management:sha-7c202dc
|
||||
command: /opt/party-management/bin/party-management foreground
|
||||
depends_on:
|
||||
machinegun:
|
||||
|
@ -21,7 +21,7 @@
|
||||
{<<"ctx">>,{pkg,<<"ctx">>,<<"0.6.0">>},2},
|
||||
{<<"damsel">>,
|
||||
{git,"https://github.com/valitydev/damsel.git",
|
||||
{ref,"781e19277224071639719f9fdfcfd46f9f03a832"}},
|
||||
{ref,"b04aba83100a4d0adc19b5797372970fd632f911"}},
|
||||
0},
|
||||
{<<"dmt_client">>,
|
||||
{git,"https://github.com/valitydev/dmt-client.git",
|
||||
|
Loading…
Reference in New Issue
Block a user