TD-597: Updates invoice payments testcases to support provider failure results with transaction (#75)

This commit is contained in:
Aleksey Kashapov 2023-05-15 15:40:11 +03:00 committed by GitHub
parent 6a51744e9c
commit e87b1e2ccf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 101 additions and 62 deletions

View File

@ -17,6 +17,7 @@
-export([construct_silent_callback/1]).
-export([make_payment_tool/2]).
-export([mk_trx/1]).
%% cowboy http callbacks
-export([init/2]).
@ -261,14 +262,16 @@ token_respond(Response, CallbackResult) ->
process_payment(
?processed(),
undefined,
_PaymentInfo,
PaymentInfo,
#{<<"always_fail">> := FailureCode, <<"override">> := ProviderCode} = CtxOpts,
_
) ->
_ = maybe_sleep(CtxOpts),
Reason = <<"sub failure by ", ProviderCode/binary>>,
Failure = payproc_errors:from_notation(FailureCode, <<"sub failure by ", ProviderCode/binary>>),
result(?finish({failure, Failure}));
process_payment(?processed(), undefined, PaymentInfo, _CtxOpts, _) ->
TrxID = hg_utils:construct_complex_id([get_payment_id(PaymentInfo), get_ctx_opts_override(CtxOpts)]),
result(?finish({failure, Failure}), <<"state: ", Reason/binary>>, mk_trx(TrxID, PaymentInfo));
process_payment(?processed(), undefined, PaymentInfo, CtxOpts, _) ->
case get_payment_info_scenario(PaymentInfo) of
{preauth_3ds, Timeout} ->
Tag = generate_tag(<<"payment">>),
@ -316,7 +319,9 @@ process_payment(?processed(), undefined, PaymentInfo, _CtxOpts, _) ->
%% simple workflow without 3DS
result(?sleep(0), <<"sleeping">>);
unexpected_failure ->
sleep(1, <<"sleeping">>, undefined, get_payment_id(PaymentInfo));
TrxID = hg_utils:construct_complex_id([get_payment_id(PaymentInfo), get_ctx_opts_override(CtxOpts)]),
Trx = mk_trx(TrxID, PaymentInfo),
result(?sleep(1, undefined), <<"sleeping">>, Trx);
unexpected_failure_when_suspended ->
Intent = ?suspend(generate_tag(<<"payment">>), 0, undefined, {callback, <<"failure">>}),
result(Intent, <<"suspended">>);
@ -325,22 +330,25 @@ process_payment(?processed(), undefined, PaymentInfo, _CtxOpts, _) ->
{temporary_unavailability, _Scenario} ->
result(?sleep(0), <<"sleeping">>)
end;
process_payment(?processed(), <<"sleeping">>, PaymentInfo, _CtxOpts, _) ->
process_payment(?processed(), <<"sleeping">>, PaymentInfo, CtxOpts, _) ->
TrxID = hg_utils:construct_complex_id([get_payment_id(PaymentInfo), get_ctx_opts_override(CtxOpts)]),
case get_payment_info_scenario(PaymentInfo) of
unexpected_failure ->
error(unexpected_failure);
{temporary_unavailability, Scenario} ->
process_failure_scenario(PaymentInfo, Scenario, get_payment_id(PaymentInfo));
process_failure_scenario(PaymentInfo, Scenario, TrxID);
_ ->
finish(success(PaymentInfo), get_payment_id(PaymentInfo), mk_trx_extra(PaymentInfo))
finish(success(PaymentInfo), mk_trx(TrxID, PaymentInfo))
end;
process_payment(?processed(), <<"sleeping_with_user_interaction">>, PaymentInfo, _CtxOpts, _) ->
process_payment(?processed(), <<"sleeping_with_user_interaction">>, PaymentInfo, CtxOpts, _) ->
Key = {get_invoice_id(PaymentInfo), get_payment_id(PaymentInfo)},
TrxID = hg_utils:construct_complex_id([get_payment_id(PaymentInfo), get_ctx_opts_override(CtxOpts)]),
Trx = mk_trx(TrxID, PaymentInfo),
case get_transaction_state(Key) of
processed ->
finish(success(PaymentInfo), get_payment_id(PaymentInfo), mk_trx_extra(PaymentInfo));
finish(success(PaymentInfo), Trx);
{pending, Count} when Count > 2 ->
finish(failure(authorization_failed));
finish(failure(authorization_failed), undefined);
{pending, Count} ->
set_transaction_state(Key, {pending, Count + 1}),
result(?sleep(1), <<"sleeping_with_user_interaction">>);
@ -352,21 +360,23 @@ process_payment(
?captured(),
undefined,
PaymentInfo = #proxy_provider_PaymentInfo{capture = Capture},
_CtxOpts,
CtxOpts,
_Opts
) when Capture =/= undefined ->
TrxID = hg_utils:construct_complex_id([get_payment_id(PaymentInfo), get_ctx_opts_override(CtxOpts)]),
case get_payment_info_scenario(PaymentInfo) of
{temporary_unavailability, Scenario} ->
process_failure_scenario(PaymentInfo, Scenario, get_payment_id(PaymentInfo));
process_failure_scenario(PaymentInfo, Scenario, TrxID);
_ ->
finish(success(PaymentInfo))
finish(success(PaymentInfo), mk_trx(TrxID, PaymentInfo))
end;
process_payment(?cancelled(), _, PaymentInfo, _CtxOpts, _) ->
process_payment(?cancelled(), _, PaymentInfo, CtxOpts, _) ->
TrxID = hg_utils:construct_complex_id([get_payment_id(PaymentInfo), get_ctx_opts_override(CtxOpts)]),
case get_payment_info_scenario(PaymentInfo) of
{temporary_unavailability, Scenario} ->
process_failure_scenario(PaymentInfo, Scenario, get_payment_id(PaymentInfo));
process_failure_scenario(PaymentInfo, Scenario, TrxID);
_ ->
finish(success(PaymentInfo))
finish(success(PaymentInfo), mk_trx(TrxID, PaymentInfo))
end.
handle_payment_callback(?LAY_LOW_BUDDY, ?processed(), <<"suspended">>, _PaymentInfo, _Opts) ->
@ -467,33 +477,41 @@ get_failure_scenario_step(Scenario, Step) when Step > length(Scenario) ->
get_failure_scenario_step(Scenario, Step) ->
lists:nth(Step, Scenario).
process_refund(_State, _PaymentInfo, #{<<"always_fail">> := FailureCode, <<"override">> := ProviderCode}, _) ->
process_refund(_State, PaymentInfo, #{<<"always_fail">> := FailureCode, <<"override">> := ProviderCode} = CtxOpts, _) ->
Failure = payproc_errors:from_notation(FailureCode, <<"sub failure by ", ProviderCode/binary>>),
result(?finish({failure, Failure}));
process_refund(undefined, PaymentInfo, _CtxOpts, _) ->
TrxID = hg_utils:construct_complex_id([get_payment_id(PaymentInfo), get_ctx_opts_override(CtxOpts)]),
result(?finish({failure, Failure}), undefined, mk_trx(TrxID, PaymentInfo));
process_refund(undefined, PaymentInfo, CtxOpts, _) ->
case get_payment_info_scenario(PaymentInfo) of
{preauth_3ds, Timeout} ->
Tag = generate_tag(<<"refund">>),
Uri = get_callback_url(),
result(?suspend(Tag, Timeout, ?redirect(Uri, #{<<"tag">> => Tag})), <<"suspended">>);
{temporary_unavailability, Scenario} ->
PaymentId = hg_utils:construct_complex_id([get_payment_id(PaymentInfo), get_refund_id(PaymentInfo)]),
process_failure_scenario(PaymentInfo, Scenario, PaymentId);
TrxID = hg_utils:construct_complex_id([
get_payment_id(PaymentInfo),
get_refund_id(PaymentInfo),
get_ctx_opts_override(CtxOpts)
]),
process_failure_scenario(PaymentInfo, Scenario, TrxID);
_ ->
finish(success(PaymentInfo), get_payment_id(PaymentInfo))
TrxID = hg_utils:construct_complex_id([get_payment_id(PaymentInfo), get_ctx_opts_override(CtxOpts)]),
finish(success(PaymentInfo), mk_trx(TrxID, PaymentInfo))
end;
process_refund(<<"sleeping">>, PaymentInfo, _CtxOpts, _) ->
finish(success(PaymentInfo), get_payment_id(PaymentInfo)).
process_refund(<<"sleeping">>, PaymentInfo, CtxOpts, _) ->
TrxID = hg_utils:construct_complex_id([get_payment_id(PaymentInfo), get_ctx_opts_override(CtxOpts)]),
finish(success(PaymentInfo), mk_trx(TrxID, PaymentInfo)).
process_failure_scenario(PaymentInfo, Scenario, PaymentId) ->
process_failure_scenario(PaymentInfo, Scenario, TrxID) ->
Key = {get_invoice_id(PaymentInfo), get_payment_id(PaymentInfo)},
Trx = mk_trx(TrxID, PaymentInfo),
case do_failure_scenario_step(Scenario, Key) of
good ->
finish(success(PaymentInfo), PaymentId);
finish(success(PaymentInfo), Trx);
temp ->
finish(failure(authorization_failed, temporarily_unavailable));
finish(failure(authorization_failed, temporarily_unavailable), undefined);
fail ->
finish(failure(authorization_failed));
finish(failure(authorization_failed), Trx);
error ->
error(planned_scenario_error)
end.
@ -504,9 +522,6 @@ handle_refund_callback(_Tag, <<"suspended">>, _PaymentInfo, _Opts) ->
next_state = <<"sleeping">>
}).
result(Intent) ->
result(Intent, undefined).
result(Intent, NextState) ->
result(Intent, NextState, undefined).
@ -517,22 +532,21 @@ result(Intent, NextState, Trx) ->
trx = Trx
}.
finish(Status) ->
result(?finish(Status)).
-spec mk_trx(binary()) -> dmsl_domain_thrift:'TransactionInfo'().
mk_trx(TrxID) ->
mk_trx_w_extra(TrxID, #{}).
finish(Status, TrxID) ->
finish(Status, TrxID, #{}).
mk_trx(TrxID, PaymentInfo) ->
Extra = mk_trx_extra(PaymentInfo),
mk_trx_w_extra(TrxID, Extra).
finish(Status, TrxID, Extra) ->
mk_trx_w_extra(TrxID, Extra) ->
AdditionalInfo = hg_ct_fixture:construct_dummy_additional_info(),
Trx = #domain_TransactionInfo{id = TrxID, extra = Extra, additional_info = AdditionalInfo},
#domain_TransactionInfo{id = TrxID, extra = Extra, additional_info = AdditionalInfo}.
finish(Status, Trx) ->
result(?finish(Status), undefined, Trx).
sleep(Timeout, State, UserInteraction, TrxID) ->
AdditionalInfo = hg_ct_fixture:construct_dummy_additional_info(),
Trx = #domain_TransactionInfo{id = TrxID, extra = #{}, additional_info = AdditionalInfo},
result(?sleep(Timeout, UserInteraction), State, Trx).
respond(Response, CallbackResult) ->
#proxy_provider_PaymentCallbackResult{
response = Response,
@ -866,3 +880,6 @@ maybe_sleep(#{<<"sleep_ms">> := TimeMs}) when is_binary(TimeMs) ->
timer:sleep(binary_to_integer(TimeMs));
maybe_sleep(_Opts) ->
ok.
get_ctx_opts_override(CtxOpts) ->
maps:get(<<"override">>, CtxOpts, <<"">>).

View File

@ -4419,10 +4419,11 @@ payment_refund_failure(C) ->
PaymentID = await_refund_created(InvoiceID, PaymentID, RefundID, Client),
PaymentID = await_refund_session_started(InvoiceID, PaymentID, RefundID, Client),
[
?payment_ev(PaymentID, ?refund_ev(ID, ?session_ev(?refunded(), ?trx_bound(?trx_info(_TrxID))))),
?payment_ev(PaymentID, ?refund_ev(ID, ?session_ev(?refunded(), ?session_finished(?session_failed(Failure))))),
?payment_ev(PaymentID, ?refund_ev(ID, ?refund_rollback_started(Failure))),
?payment_ev(PaymentID, ?refund_ev(ID, ?refund_status_changed(?refund_failed(Failure))))
] = next_changes(InvoiceID, 3, Client),
] = next_changes(InvoiceID, 4, Client),
#domain_InvoicePaymentRefund{status = ?refund_failed(Failure)} =
hg_client_invoicing:get_payment_refund(InvoiceID, PaymentID, RefundID, Client).
@ -5241,9 +5242,10 @@ adhoc_repair_failed_succeeded(C) ->
{PaymentTool, Session} = hg_dummy_provider:make_payment_tool(unexpected_failure, ?pmt_sys(<<"visa-ref">>)),
PaymentParams = make_payment_params(PaymentTool, Session, instant),
PaymentID = start_payment(InvoiceID, PaymentParams, Client),
TrxID = hg_utils:construct_complex_id([PaymentID, <<"brovider">>]),
[
?payment_ev(PaymentID, ?session_ev(?processed(), ?session_started())),
?payment_ev(PaymentID, ?session_ev(?processed(), ?trx_bound(?trx_info(PaymentID))))
?payment_ev(PaymentID, ?session_ev(?processed(), ?trx_bound(?trx_info(TrxID))))
] = next_changes(InvoiceID, 2, Client),
% assume no more events here since machine is FUBAR already
timeout = next_change(InvoiceID, 2000, Client),
@ -5277,9 +5279,10 @@ adhoc_repair_invalid_changes_failed(C) ->
{PaymentTool, Session} = hg_dummy_provider:make_payment_tool(unexpected_failure, ?pmt_sys(<<"visa-ref">>)),
PaymentParams = make_payment_params(PaymentTool, Session, instant),
PaymentID = start_payment(InvoiceID, PaymentParams, Client),
TrxID = hg_utils:construct_complex_id([PaymentID, <<"brovider">>]),
[
?payment_ev(PaymentID, ?session_ev(?processed(), ?session_started())),
?payment_ev(PaymentID, ?session_ev(?processed(), ?trx_bound(?trx_info(PaymentID))))
?payment_ev(PaymentID, ?session_ev(?processed(), ?trx_bound(?trx_info(TrxID))))
] = next_changes(InvoiceID, 2, Client),
timeout = next_change(InvoiceID, 5000, Client),
InvalidChanges1 = [
@ -5460,9 +5463,10 @@ repair_fail_session_on_processed_succeeded(C) ->
{PaymentTool, Session} = hg_dummy_provider:make_payment_tool(unexpected_failure, ?pmt_sys(<<"visa-ref">>)),
PaymentParams = make_payment_params(PaymentTool, Session, instant),
PaymentID = start_payment(InvoiceID, PaymentParams, Client),
TrxID = hg_utils:construct_complex_id([PaymentID, <<"brovider">>]),
[
?payment_ev(PaymentID, ?session_ev(?processed(), ?session_started())),
?payment_ev(PaymentID, ?session_ev(?processed(), ?trx_bound(?trx_info(PaymentID))))
?payment_ev(PaymentID, ?session_ev(?processed(), ?trx_bound(?trx_info(TrxID))))
] = next_changes(InvoiceID, 2, Client),
timeout = next_change(InvoiceID, 2000, Client),
@ -5571,9 +5575,10 @@ repair_complex_second_scenario_succeeded(C) ->
{PaymentTool, Session} = hg_dummy_provider:make_payment_tool(unexpected_failure, ?pmt_sys(<<"visa-ref">>)),
PaymentParams = make_payment_params(PaymentTool, Session, instant),
PaymentID = start_payment(InvoiceID, PaymentParams, Client),
TrxID = hg_utils:construct_complex_id([PaymentID, <<"brovider">>]),
[
?payment_ev(PaymentID, ?session_ev(?processed(), ?session_started())),
?payment_ev(PaymentID, ?session_ev(?processed(), ?trx_bound(?trx_info(PaymentID))))
?payment_ev(PaymentID, ?session_ev(?processed(), ?trx_bound(?trx_info(TrxID))))
] = next_changes(InvoiceID, 2, Client),
timeout = next_change(InvoiceID, 2000, Client),
@ -5646,7 +5651,8 @@ repair_fulfill_session_on_processed_succeeded(C) ->
?payment_ev(PaymentID, ?session_ev(?processed(), ?session_finished(?session_succeeded()))),
?payment_ev(PaymentID, ?payment_status_changed(?processed()))
] = next_changes(InvoiceID, 2, Client),
PaymentID = await_payment_capture(InvoiceID, PaymentID, Client).
TrxID = <<PaymentID/binary, ".brovider">>,
PaymentID = await_payment_capture(InvoiceID, PaymentID, ?timeout_reason(), TrxID, Client).
-spec repair_fulfill_suspended_session_succeeded(config()) -> test_return().
repair_fulfill_suspended_session_succeeded(C) ->
@ -5668,7 +5674,8 @@ repair_fulfill_suspended_session_succeeded(C) ->
?payment_ev(PaymentID, ?session_ev(?processed(), ?session_finished(?session_succeeded()))),
?payment_ev(PaymentID, ?payment_status_changed(?processed()))
] = next_changes(InvoiceID, 2, Client),
PaymentID = await_payment_capture(InvoiceID, PaymentID, Client).
TrxID = <<PaymentID/binary, ".brovider">>,
PaymentID = await_payment_capture(InvoiceID, PaymentID, ?timeout_reason(), TrxID, Client).
-spec repair_fulfill_session_on_captured_succeeded(config()) -> test_return().
repair_fulfill_session_on_captured_succeeded(C) ->
@ -5725,10 +5732,12 @@ repair_fulfill_session_with_trx_succeeded(C) ->
next_change(InvoiceID, Client),
timeout = next_change(InvoiceID, 2000, Client),
ok = repair_invoice_with_scenario(InvoiceID, {fulfill_session, ?trx_info(PaymentID, #{})}, Client),
TrxID = <<PaymentID/binary, ".brovider">>,
Trx = hg_dummy_provider:mk_trx(TrxID),
ok = repair_invoice_with_scenario(InvoiceID, {fulfill_session, Trx}, Client),
[
?payment_ev(PaymentID, ?session_ev(?processed(), ?trx_bound(?trx_info(PaymentID)))),
?payment_ev(PaymentID, ?session_ev(?processed(), ?trx_bound(?trx_info(TrxID)))),
?payment_ev(PaymentID, ?session_ev(?processed(), ?session_finished(?session_succeeded()))),
?payment_ev(PaymentID, ?payment_status_changed(?processed()))
] = next_changes(InvoiceID, 3, Client),
@ -6151,7 +6160,7 @@ payment_cascade_success(C) ->
next_change(InvoiceID, Client),
?payment_ev(PaymentID, ?risk_score_changed(_)) =
next_change(InvoiceID, Client),
{_Route1, _CashFlow1, Failure1} =
{_Route1, _CashFlow1, TrxID1, Failure1} =
await_cascade_triggering(InvoiceID, PaymentID, Client),
ok = payproc_errors:match('PaymentFailure', Failure1, fun({preauthorization_failed, {card_blocked, _}}) -> ok end),
%% Assert payment status IS NOT failed
@ -6166,7 +6175,12 @@ payment_cascade_success(C) ->
next_changes(InvoiceID, 2, Client),
?assertMatch(#domain_PaymentRoute{provider = ?prv(1)}, Route2),
PaymentID = await_payment_session_started(InvoiceID, PaymentID, Client, ?processed()),
PaymentID = await_payment_process_finish(InvoiceID, PaymentID, Client),
[
?payment_ev(PaymentID, ?session_ev(?processed(), ?trx_bound(?trx_info(TrxID2)))),
?payment_ev(PaymentID, ?session_ev(?processed(), ?session_finished(?session_succeeded()))),
?payment_ev(PaymentID, ?payment_status_changed(?processed()))
] = next_changes(InvoiceID, 3, Client),
?assertNotEqual(TrxID1, TrxID2),
PaymentID = await_payment_capture(InvoiceID, PaymentID, Client),
?invoice_state(?invoice_w_status(?invoice_paid()), [PaymentSt = ?payment_state(PaymentFinal)]) =
hg_client_invoicing:get(InvoiceID, Client),
@ -6237,7 +6251,7 @@ payment_big_cascade_success(C) ->
next_change(InvoiceID, Client),
[
(fun() ->
{_Route, _CashFlow, Failure} =
{_Route, _CashFlow, _TrxID, Failure} =
await_cascade_triggering(InvoiceID, PaymentID, Client),
ok = payproc_errors:match(
'PaymentFailure',
@ -6295,7 +6309,7 @@ payment_cascade_fail_wo_available_attempt_limit(C) ->
next_change(InvoiceID, Client),
?payment_ev(PaymentID, ?risk_score_changed(_)) =
next_change(InvoiceID, Client),
{_Route, _CashFlow, Failure} =
{_Route, _CashFlow, _TrxID, Failure} =
await_cascade_triggering(InvoiceID, PaymentID, Client),
?payment_ev(PaymentID, ?payment_status_changed(?failed({failure, Failure}))) =
next_change(InvoiceID, Client),
@ -6318,11 +6332,11 @@ payment_cascade_failures(C) ->
next_change(InvoiceID, Client),
?payment_ev(PaymentID, ?risk_score_changed(_)) =
next_change(InvoiceID, Client),
{_Route1, _CashFlow1, Failure1} =
{_Route1, _CashFlow1, _TrxID1, Failure1} =
await_cascade_triggering(InvoiceID, PaymentID, Client),
ok = payproc_errors:match('PaymentFailure', Failure1, fun({preauthorization_failed, {card_blocked, _}}) -> ok end),
%% And again
{_Route2, _CashFlow2, Failure2} =
{_Route2, _CashFlow2, _TrxID2, Failure2} =
await_cascade_triggering(InvoiceID, PaymentID, Client),
?payment_ev(PaymentID, ?payment_status_changed(?failed({failure, Failure2}))) =
next_change(InvoiceID, Client),
@ -6347,7 +6361,7 @@ payment_cascade_deadline_failures(C) ->
next_change(InvoiceID, Client),
?payment_ev(PaymentID, ?risk_score_changed(_)) =
next_change(InvoiceID, Client),
{_Route1, _CashFlow1, Failure1} =
{_Route1, _CashFlow1, _TrxID1, Failure1} =
await_cascade_triggering(InvoiceID, PaymentID, Client),
ok = payproc_errors:match('PaymentFailure', Failure1, fun({preauthorization_failed, {card_blocked, _}}) -> ok end),
%% And again
@ -6381,7 +6395,7 @@ payment_cascade_no_route(C) ->
next_change(InvoiceID, Client),
?payment_ev(PaymentID, ?risk_score_changed(_)) =
next_change(InvoiceID, Client),
{_Route1, _CashFlow1, CardBlockedFailure} =
{_Route1, _CashFlow1, _TrxID1, CardBlockedFailure} =
await_cascade_triggering(InvoiceID, PaymentID, Client),
ok = payproc_errors:match(
'PaymentFailure',
@ -6406,14 +6420,15 @@ await_cascade_triggering(InvoiceID, PaymentID, Client) ->
?payment_ev(PaymentID, ?route_changed(Route)),
?payment_ev(PaymentID, ?cash_flow_changed(CashFlow)),
?payment_ev(PaymentID, ?session_ev(?processed(), ?session_started())),
?payment_ev(PaymentID, ?session_ev(?processed(), ?trx_bound(?trx_info(TrxID)))),
?payment_ev(
PaymentID,
?session_ev(?processed(), ?session_finished(?session_failed({failure, Failure})))
),
?payment_ev(PaymentID, ?payment_rollback_started({failure, Failure}))
] =
next_changes(InvoiceID, 5, Client),
{Route, CashFlow, Failure}.
next_changes(InvoiceID, 6, Client),
{Route, CashFlow, TrxID, Failure}.
next_changes(InvoiceID, Amount, Client) ->
next_changes(InvoiceID, Amount, ?DEFAULT_NEXT_CHANGE_TIMEOUT, Client).
@ -6887,11 +6902,17 @@ await_payment_capture(InvoiceID, PaymentID, Client) ->
await_payment_capture(InvoiceID, PaymentID, ?timeout_reason(), Client).
await_payment_capture(InvoiceID, PaymentID, Reason, Client) ->
await_payment_capture(InvoiceID, PaymentID, Reason, undefined, Client).
await_payment_capture(InvoiceID, PaymentID, Reason, TrxID, Client) ->
Cost = get_payment_cost(InvoiceID, PaymentID, Client),
[
?payment_ev(PaymentID, ?payment_capture_started(Reason, Cost, _, _)),
?payment_ev(PaymentID, ?session_ev(?captured(Reason, Cost), ?session_started()))
] = next_changes(InvoiceID, 2, Client),
TrxID =/= undefined andalso
(?payment_ev(PaymentID, ?session_ev(?captured(Reason, Cost, _Cart, _), ?trx_bound(?trx_info(TrxID)))) =
next_change(InvoiceID, Client)),
await_payment_capture_finish(InvoiceID, PaymentID, Reason, Client).
await_payment_partial_capture(InvoiceID, PaymentID, Reason, Cash, Client) ->
@ -7107,7 +7128,8 @@ execute_payment_w_cascade(InvoiceID, Params, Client, CascadeCount) when CascadeC
next_changes(InvoiceID, 2, Client),
FailedRoutes = [
begin
{Route, _CashFlow, _Failure} = await_cascade_triggering(InvoiceID, PaymentID, Client),
{Route, _CashFlow, _TrxID, _Failure} =
await_cascade_triggering(InvoiceID, PaymentID, Client),
Route
end
|| _I <- lists:seq(1, CascadeCount)