mirror of
https://github.com/valitydev/capi-v2.git
synced 2024-11-06 01:55:20 +00:00
+bouncer_data as BouncerContext
This commit is contained in:
parent
c568a689d6
commit
82cd19cadf
@ -1,7 +1,6 @@
|
|||||||
-module(capi_bouncer_context).
|
-module(capi_bouncer_context).
|
||||||
|
|
||||||
-include_lib("bouncer_proto/include/bouncer_context_v1_thrift.hrl").
|
-include_lib("bouncer_proto/include/bouncer_context_v1_thrift.hrl").
|
||||||
|
|
||||||
-include_lib("damsel/include/dmsl_payment_processing_thrift.hrl").
|
-include_lib("damsel/include/dmsl_payment_processing_thrift.hrl").
|
||||||
-include_lib("damsel/include/dmsl_webhooker_thrift.hrl").
|
-include_lib("damsel/include/dmsl_webhooker_thrift.hrl").
|
||||||
-include_lib("reporter_proto/include/reporter_reports_thrift.hrl").
|
-include_lib("reporter_proto/include/reporter_reports_thrift.hrl").
|
||||||
@ -9,11 +8,12 @@
|
|||||||
|
|
||||||
-type fragment() :: bouncer_client:context_fragment().
|
-type fragment() :: bouncer_client:context_fragment().
|
||||||
-type acc() :: bouncer_context_helpers:context_fragment().
|
-type acc() :: bouncer_context_helpers:context_fragment().
|
||||||
|
-type payment_tool_context() :: bouncer_context_v1_thrift:'ContextPaymentTool'().
|
||||||
-type fragments() :: {acc(), _ExternalFragments :: #{_ID => fragment()}}.
|
-type fragments() :: {acc(), _ExternalFragments :: #{_ID => fragment()}}.
|
||||||
|
|
||||||
-export_type([fragment/0]).
|
-export_type([fragment/0]).
|
||||||
-export_type([acc/0]).
|
-export_type([acc/0]).
|
||||||
|
-export_type([payment_tool_context/0]).
|
||||||
-export_type([fragments/0]).
|
-export_type([fragments/0]).
|
||||||
|
|
||||||
-type prototypes() :: [
|
-type prototypes() :: [
|
||||||
@ -44,9 +44,7 @@
|
|||||||
}.
|
}.
|
||||||
|
|
||||||
-type prototype_payment_tool() :: #{
|
-type prototype_payment_tool() :: #{
|
||||||
invoice => entity_id(),
|
payment_tool_context => payment_tool_context()
|
||||||
customer => entity_id(),
|
|
||||||
expiration => timestamp()
|
|
||||||
}.
|
}.
|
||||||
|
|
||||||
-type prototype_payproc() :: #{
|
-type prototype_payproc() :: #{
|
||||||
@ -87,7 +85,6 @@
|
|||||||
-type payout() :: payouts_payout_manager_thrift:'Payout'().
|
-type payout() :: payouts_payout_manager_thrift:'Payout'().
|
||||||
|
|
||||||
-type entity_id() :: binary().
|
-type entity_id() :: binary().
|
||||||
-type timestamp() :: binary().
|
|
||||||
|
|
||||||
-export_type([prototypes/0]).
|
-export_type([prototypes/0]).
|
||||||
-export_type([prototype_operation/0]).
|
-export_type([prototype_operation/0]).
|
||||||
@ -141,13 +138,7 @@ build(operation, Params = #{id := OperationID}, Acc, _WoodyCtx) ->
|
|||||||
};
|
};
|
||||||
build(payment_tool, Params = #{}, Acc, _WoodyCtx) ->
|
build(payment_tool, Params = #{}, Acc, _WoodyCtx) ->
|
||||||
Acc#bctx_v1_ContextFragment{
|
Acc#bctx_v1_ContextFragment{
|
||||||
payment_tool = #bctx_v1_ContextPaymentTool{
|
payment_tool = maps:get(payment_tool_context, Params, undefined)
|
||||||
scope = #bctx_v1_AuthScope{
|
|
||||||
invoice = maybe_entity(invoice, Params),
|
|
||||||
customer = maybe_entity(customer, Params)
|
|
||||||
},
|
|
||||||
expiration = maps:get(expiration, Params, undefined)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
build(payproc, Params = #{}, Acc, WoodyCtx) ->
|
build(payproc, Params = #{}, Acc, WoodyCtx) ->
|
||||||
Acc#bctx_v1_ContextFragment{
|
Acc#bctx_v1_ContextFragment{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
-module(capi_crypto).
|
-module(capi_crypto).
|
||||||
|
|
||||||
-include_lib("damsel/include/dmsl_payment_tool_token_thrift.hrl").
|
-include_lib("damsel/include/dmsl_payment_tool_token_thrift.hrl").
|
||||||
|
-include_lib("bouncer_proto/include/bouncer_context_v1_thrift.hrl").
|
||||||
|
|
||||||
-type token() :: binary().
|
-type token() :: binary().
|
||||||
-type token_data() :: #{
|
-type token_data() :: #{
|
||||||
@ -8,8 +9,7 @@
|
|||||||
valid_until := deadline(),
|
valid_until := deadline(),
|
||||||
bouncer_data => bouncer_data()
|
bouncer_data => bouncer_data()
|
||||||
}.
|
}.
|
||||||
-type bouncer_data() :: term().
|
-type bouncer_data() :: capi_bouncer_context:payment_tool_context().
|
||||||
|
|
||||||
-type payment_tool() :: dmsl_domain_thrift:'PaymentTool'().
|
-type payment_tool() :: dmsl_domain_thrift:'PaymentTool'().
|
||||||
-type payment_tool_token() :: dmsl_payment_tool_token_thrift:'PaymentToolToken'().
|
-type payment_tool_token() :: dmsl_payment_tool_token_thrift:'PaymentToolToken'().
|
||||||
-type payment_tool_token_payload() :: dmsl_payment_tool_token_thrift:'PaymentToolTokenPayload'().
|
-type payment_tool_token_payload() :: dmsl_payment_tool_token_thrift:'PaymentToolTokenPayload'().
|
||||||
@ -22,11 +22,13 @@
|
|||||||
-export([encode_token/1]).
|
-export([encode_token/1]).
|
||||||
-export([decode_token/1]).
|
-export([decode_token/1]).
|
||||||
|
|
||||||
|
-define(THRIFT_TYPE, {struct, struct, {dmsl_payment_tool_token_thrift, 'PaymentToolToken'}}).
|
||||||
|
-define(BOUNCER_THRIFT_TYPE, {struct, struct, {bouncer_context_v1_thrift, 'ContextPaymentTool'}}).
|
||||||
|
|
||||||
-spec encode_token(token_data()) -> token().
|
-spec encode_token(token_data()) -> token().
|
||||||
encode_token(TokenData) ->
|
encode_token(TokenData) ->
|
||||||
PaymentToolToken = encode_payment_tool_token(TokenData),
|
PaymentToolToken = encode_payment_tool_token(TokenData),
|
||||||
ThriftType = {struct, struct, {dmsl_payment_tool_token_thrift, 'PaymentToolToken'}},
|
{ok, EncodedToken} = lechiffre:encode(?THRIFT_TYPE, PaymentToolToken),
|
||||||
{ok, EncodedToken} = lechiffre:encode(ThriftType, PaymentToolToken),
|
|
||||||
TokenVersion = token_version(),
|
TokenVersion = token_version(),
|
||||||
<<TokenVersion/binary, ".", EncodedToken/binary>>.
|
<<TokenVersion/binary, ".", EncodedToken/binary>>.
|
||||||
|
|
||||||
@ -47,8 +49,7 @@ token_version() ->
|
|||||||
<<"v2">>.
|
<<"v2">>.
|
||||||
|
|
||||||
decrypt_token(EncryptedPaymentToolToken) ->
|
decrypt_token(EncryptedPaymentToolToken) ->
|
||||||
ThriftType = {struct, struct, {dmsl_payment_tool_token_thrift, 'PaymentToolToken'}},
|
case lechiffre:decode(?THRIFT_TYPE, EncryptedPaymentToolToken) of
|
||||||
case lechiffre:decode(ThriftType, EncryptedPaymentToolToken) of
|
|
||||||
{ok, PaymentToolToken} ->
|
{ok, PaymentToolToken} ->
|
||||||
Payload = PaymentToolToken#ptt_PaymentToolToken.payload,
|
Payload = PaymentToolToken#ptt_PaymentToolToken.payload,
|
||||||
ValidUntil = PaymentToolToken#ptt_PaymentToolToken.valid_until,
|
ValidUntil = PaymentToolToken#ptt_PaymentToolToken.valid_until,
|
||||||
@ -73,11 +74,15 @@ encode_payment_tool_token(TokenData) ->
|
|||||||
bouncer_data = encode_bouncer_data(BouncerContext)
|
bouncer_data = encode_bouncer_data(BouncerContext)
|
||||||
}.
|
}.
|
||||||
|
|
||||||
-spec encode_bouncer_data(bouncer_data()) -> binary() | undefined.
|
-spec encode_bouncer_data(bouncer_data() | undefined) -> binary() | undefined.
|
||||||
encode_bouncer_data(undefined) ->
|
encode_bouncer_data(undefined) ->
|
||||||
undefined;
|
undefined;
|
||||||
encode_bouncer_data(BouncerData) ->
|
encode_bouncer_data(BouncerData) ->
|
||||||
base64:encode(erlang:term_to_binary(BouncerData)).
|
Codec = thrift_strict_binary_codec:new(),
|
||||||
|
case thrift_strict_binary_codec:write(Codec, ?BOUNCER_THRIFT_TYPE, BouncerData) of
|
||||||
|
{ok, Codec1} ->
|
||||||
|
thrift_strict_binary_codec:close(Codec1)
|
||||||
|
end.
|
||||||
|
|
||||||
-spec encode_deadline(deadline()) -> binary() | undefined.
|
-spec encode_deadline(deadline()) -> binary() | undefined.
|
||||||
encode_deadline(undefined) ->
|
encode_deadline(undefined) ->
|
||||||
@ -107,14 +112,16 @@ encode_payment_tool_token_payload({mobile_commerce, MobileCommerce}) ->
|
|||||||
mobile_commerce = MobileCommerce
|
mobile_commerce = MobileCommerce
|
||||||
}}.
|
}}.
|
||||||
|
|
||||||
-spec decode_bouncer_data(binary()) -> bouncer_data() | undefined | no_return().
|
-spec decode_bouncer_data(binary() | undefined) -> bouncer_data() | undefined | no_return().
|
||||||
decode_bouncer_data(undefined) ->
|
decode_bouncer_data(undefined) ->
|
||||||
undefined;
|
undefined;
|
||||||
decode_bouncer_data(Content) ->
|
decode_bouncer_data(Content) ->
|
||||||
try
|
Codec = thrift_strict_binary_codec:new(Content),
|
||||||
erlang:binary_to_term(base64:decode(Content))
|
case thrift_strict_binary_codec:read(Codec, ?BOUNCER_THRIFT_TYPE) of
|
||||||
catch
|
{ok, BouncerData, Codec1} ->
|
||||||
error:Error ->
|
_ = thrift_strict_binary_codec:close(Codec1),
|
||||||
|
BouncerData;
|
||||||
|
Error ->
|
||||||
erlang:error({malformed_token, Error}, [Content])
|
erlang:error({malformed_token, Error}, [Content])
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -115,28 +115,33 @@ prepare('CreateCustomerAccessToken' = OperationID, Req, Context) ->
|
|||||||
{ok, #{authorize => Authorize, process => Process}};
|
{ok, #{authorize => Authorize, process => Process}};
|
||||||
prepare('CreateBinding' = OperationID, Req, Context) ->
|
prepare('CreateBinding' = OperationID, Req, Context) ->
|
||||||
CustomerID = maps:get(customerID, Req),
|
CustomerID = maps:get(customerID, Req),
|
||||||
|
CustomerBindingParams = maps:get('CustomerBindingParams', Req),
|
||||||
|
PaymentToken = decode_payment_token(CustomerBindingParams),
|
||||||
Authorize = fun() ->
|
Authorize = fun() ->
|
||||||
Prototypes = [
|
Prototypes = [
|
||||||
{operation, #{id => OperationID, customer => CustomerID}},
|
{operation, #{id => OperationID, customer => CustomerID}},
|
||||||
{payproc, #{customer => CustomerID}}
|
{payproc, #{customer => CustomerID}},
|
||||||
|
{payment_tool, prepare_payment_tool_prototype(PaymentToken)}
|
||||||
],
|
],
|
||||||
{ok, capi_auth:authorize_operation(Prototypes, Context)}
|
{ok, capi_auth:authorize_operation(Prototypes, Context)}
|
||||||
end,
|
end,
|
||||||
Process = fun() ->
|
Process = fun() ->
|
||||||
Result =
|
Result =
|
||||||
try
|
try
|
||||||
CustomerBindingParams = maps:get('CustomerBindingParams', Req),
|
#{payment_tool := PaymentTool} = PaymentToken,
|
||||||
|
|
||||||
{CustomerBindingID, RecPaymentToolID} = generate_binding_ids(
|
{CustomerBindingID, RecPaymentToolID} = generate_binding_ids(
|
||||||
OperationID,
|
OperationID,
|
||||||
CustomerBindingParams,
|
CustomerBindingParams,
|
||||||
|
PaymentTool,
|
||||||
Context
|
Context
|
||||||
),
|
),
|
||||||
|
|
||||||
EncodedCustomerBindingParams = encode_customer_binding_params(
|
EncodedCustomerBindingParams = encode_customer_binding_params(
|
||||||
CustomerBindingID,
|
CustomerBindingID,
|
||||||
RecPaymentToolID,
|
RecPaymentToolID,
|
||||||
CustomerBindingParams
|
CustomerBindingParams,
|
||||||
|
PaymentTool
|
||||||
),
|
),
|
||||||
|
|
||||||
Call = {customer_management, 'StartBinding', {CustomerID, EncodedCustomerBindingParams}},
|
Call = {customer_management, 'StartBinding', {CustomerID, EncodedCustomerBindingParams}},
|
||||||
@ -285,6 +290,15 @@ prepare(_OperationID, _Req, _Context) ->
|
|||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
prepare_payment_tool_prototype(#{bouncer_data := BouncerData}) ->
|
||||||
|
#{
|
||||||
|
payment_tool_context => BouncerData
|
||||||
|
};
|
||||||
|
prepare_payment_tool_prototype(_Other) ->
|
||||||
|
#{}.
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
get_customer_by_id(CustomerID, Context) ->
|
get_customer_by_id(CustomerID, Context) ->
|
||||||
EventRange = #payproc_EventRange{},
|
EventRange = #payproc_EventRange{},
|
||||||
capi_handler_utils:service_call({customer_management, 'Get', {CustomerID, EventRange}}, Context).
|
capi_handler_utils:service_call({customer_management, 'Get', {CustomerID, EventRange}}, Context).
|
||||||
@ -316,23 +330,17 @@ encode_customer_params(CustomerID, PartyID, Params) ->
|
|||||||
encode_customer_metadata(Meta) ->
|
encode_customer_metadata(Meta) ->
|
||||||
capi_json_marshalling:marshal(Meta).
|
capi_json_marshalling:marshal(Meta).
|
||||||
|
|
||||||
generate_binding_ids(OperationID, CustomerBindingParams, Context = #{woody_context := WoodyContext}) ->
|
generate_binding_ids(OperationID, CustomerBindingParams, PaymentTool, Context = #{woody_context := WoodyContext}) ->
|
||||||
ExternalID = maps:get(<<"externalID">>, CustomerBindingParams, undefined),
|
ExternalID = maps:get(<<"externalID">>, CustomerBindingParams, undefined),
|
||||||
UserID = capi_handler_utils:get_user_id(Context),
|
UserID = capi_handler_utils:get_user_id(Context),
|
||||||
|
|
||||||
PaymentResource = maps:get(<<"paymentResource">>, CustomerBindingParams),
|
PaymentResource = maps:get(<<"paymentResource">>, CustomerBindingParams),
|
||||||
PaymentToolToken = maps:get(<<"paymentToolToken">>, PaymentResource),
|
PaymentResourceWoToken = maps:remove(<<"paymentToolToken">>, PaymentResource),
|
||||||
PaymentTool = capi_handler_decoder_party:decode_payment_tool(encode_payment_tool_token(PaymentToolToken)),
|
CustomerBindingParamsEncrypted = CustomerBindingParams#{
|
||||||
CustomerBindingParamsEncrypted =
|
<<"paymentResource">> => PaymentResourceWoToken#{
|
||||||
maps:put(
|
<<"paymentTool">> => capi_handler_decoder_party:decode_payment_tool(PaymentTool)
|
||||||
<<"paymentResource">>,
|
}
|
||||||
maps:put(
|
},
|
||||||
<<"paymentTool">>,
|
|
||||||
PaymentTool,
|
|
||||||
maps:remove(<<"paymentToolToken">>, PaymentResource)
|
|
||||||
),
|
|
||||||
CustomerBindingParams
|
|
||||||
),
|
|
||||||
|
|
||||||
Identity = capi_bender:make_identity(
|
Identity = capi_bender:make_identity(
|
||||||
{schema, capi_feature_schemas:customer_binding(), CustomerBindingParamsEncrypted}
|
{schema, capi_feature_schemas:customer_binding(), CustomerBindingParamsEncrypted}
|
||||||
@ -354,11 +362,9 @@ generate_binding_ids(OperationID, CustomerBindingParams, Context = #{woody_conte
|
|||||||
encode_customer_binding_params(
|
encode_customer_binding_params(
|
||||||
CustomerBindingID,
|
CustomerBindingID,
|
||||||
RecPaymentToolID,
|
RecPaymentToolID,
|
||||||
#{<<"paymentResource">> := PaymentResource}
|
#{<<"paymentResource">> := PaymentResource},
|
||||||
|
PaymentTool
|
||||||
) ->
|
) ->
|
||||||
PaymentToolToken = maps:get(<<"paymentToolToken">>, PaymentResource),
|
|
||||||
PaymentTool = encode_payment_tool_token(PaymentToolToken),
|
|
||||||
|
|
||||||
{ClientInfo, PaymentSession} =
|
{ClientInfo, PaymentSession} =
|
||||||
capi_handler_utils:unwrap_payment_session(maps:get(<<"paymentSession">>, PaymentResource)),
|
capi_handler_utils:unwrap_payment_session(maps:get(<<"paymentSession">>, PaymentResource)),
|
||||||
|
|
||||||
@ -372,27 +378,34 @@ encode_customer_binding_params(
|
|||||||
}
|
}
|
||||||
}.
|
}.
|
||||||
|
|
||||||
encode_payment_tool_token(Token) ->
|
decode_payment_token(#{<<"paymentResource">> := PaymentResource}) ->
|
||||||
|
decode_payment_token(PaymentResource);
|
||||||
|
decode_payment_token(#{<<"paymentToolToken">> := Token}) ->
|
||||||
case capi_crypto:decode_token(Token) of
|
case capi_crypto:decode_token(Token) of
|
||||||
{ok, TokenData} ->
|
% TODO #ED-162 Проверка времени жизни будет в bouncer, тут её следует убрать вместе с тестами
|
||||||
#{payment_tool := PaymentTool, valid_until := ValidUntil} = TokenData,
|
{ok, #{valid_until := ValidUntil} = TokenData} ->
|
||||||
case capi_utils:deadline_is_reached(ValidUntil) of
|
case capi_utils:deadline_is_reached(ValidUntil) of
|
||||||
true ->
|
true ->
|
||||||
logger:warning("Payment tool token expired: ~p", [capi_utils:deadline_to_binary(ValidUntil)]),
|
logger:warning("Payment tool token expired: ~p", [capi_utils:deadline_to_binary(ValidUntil)]),
|
||||||
capi_handler:respond(logic_error(invalidPaymentToolToken));
|
capi_handler:respond(logic_error(invalidPaymentToolToken));
|
||||||
_ ->
|
_ ->
|
||||||
PaymentTool
|
TokenData
|
||||||
end;
|
end;
|
||||||
unrecognized ->
|
unrecognized ->
|
||||||
encode_legacy_payment_tool_token(Token);
|
% TODO-162: удалить устаревшие токены, заменить их на актуальные и поправить тесты
|
||||||
|
decode_legacy_payment_token(Token);
|
||||||
{error, {decryption_failed, Error}} ->
|
{error, {decryption_failed, Error}} ->
|
||||||
logger:warning("Payment tool token decryption failed: ~p", [Error]),
|
logger:warning("Payment tool token decryption failed: ~p", [Error]),
|
||||||
capi_handler:respond(logic_error(invalidPaymentToolToken))
|
capi_handler:respond(logic_error(invalidPaymentToolToken))
|
||||||
end.
|
end;
|
||||||
|
decode_payment_token(_Other) ->
|
||||||
|
undefined.
|
||||||
|
|
||||||
encode_legacy_payment_tool_token(Token) ->
|
decode_legacy_payment_token(Token) ->
|
||||||
try
|
try
|
||||||
capi_handler_encoder:encode_payment_tool(capi_utils:base64url_to_map(Token))
|
#{
|
||||||
|
payment_tool => capi_handler_encoder:encode_payment_tool(capi_utils:base64url_to_map(Token))
|
||||||
|
}
|
||||||
catch
|
catch
|
||||||
error:badarg ->
|
error:badarg ->
|
||||||
capi_handler:respond(logic_error(invalidPaymentToolToken))
|
capi_handler:respond(logic_error(invalidPaymentToolToken))
|
||||||
|
@ -513,18 +513,11 @@ prepare(_OperationID, _Req, _Context) ->
|
|||||||
|
|
||||||
prepare_payment_tool_prototype(undefined) ->
|
prepare_payment_tool_prototype(undefined) ->
|
||||||
#{};
|
#{};
|
||||||
prepare_payment_tool_prototype(PaymentToken) ->
|
prepare_payment_tool_prototype(#{bouncer_data := BouncerData}) ->
|
||||||
#{
|
#{
|
||||||
expiration => prepare_payment_tool_expire(PaymentToken),
|
payment_tool_context => BouncerData
|
||||||
scope => prepare_payment_tool_scope(PaymentToken)
|
|
||||||
}.
|
}.
|
||||||
|
|
||||||
prepare_payment_tool_expire(#{valid_until := ValidUntil}) ->
|
|
||||||
capi_utils:deadline_to_binary(ValidUntil).
|
|
||||||
|
|
||||||
prepare_payment_tool_scope(#{bouncer_data := BouncerData}) ->
|
|
||||||
BouncerData.
|
|
||||||
|
|
||||||
%%
|
%%
|
||||||
validate_allocation(Allocation) ->
|
validate_allocation(Allocation) ->
|
||||||
case capi_allocation:validate(Allocation) of
|
case capi_allocation:validate(Allocation) of
|
||||||
|
@ -112,7 +112,9 @@
|
|||||||
]}
|
]}
|
||||||
]},
|
]},
|
||||||
{test, [
|
{test, [
|
||||||
{dialyzer, [{plt_extra_apps, [eunit, common_test, runtime_tools, bender_proto, payout_manager_proto]}]}
|
{dialyzer, [
|
||||||
|
{plt_extra_apps, [eunit, common_test, runtime_tools, bender_proto, payout_manager_proto]}
|
||||||
|
]}
|
||||||
]}
|
]}
|
||||||
]}.
|
]}.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user