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).
|
||||
|
||||
-include_lib("bouncer_proto/include/bouncer_context_v1_thrift.hrl").
|
||||
|
||||
-include_lib("damsel/include/dmsl_payment_processing_thrift.hrl").
|
||||
-include_lib("damsel/include/dmsl_webhooker_thrift.hrl").
|
||||
-include_lib("reporter_proto/include/reporter_reports_thrift.hrl").
|
||||
@ -9,11 +8,12 @@
|
||||
|
||||
-type fragment() :: bouncer_client:context_fragment().
|
||||
-type acc() :: bouncer_context_helpers:context_fragment().
|
||||
|
||||
-type payment_tool_context() :: bouncer_context_v1_thrift:'ContextPaymentTool'().
|
||||
-type fragments() :: {acc(), _ExternalFragments :: #{_ID => fragment()}}.
|
||||
|
||||
-export_type([fragment/0]).
|
||||
-export_type([acc/0]).
|
||||
-export_type([payment_tool_context/0]).
|
||||
-export_type([fragments/0]).
|
||||
|
||||
-type prototypes() :: [
|
||||
@ -44,9 +44,7 @@
|
||||
}.
|
||||
|
||||
-type prototype_payment_tool() :: #{
|
||||
invoice => entity_id(),
|
||||
customer => entity_id(),
|
||||
expiration => timestamp()
|
||||
payment_tool_context => payment_tool_context()
|
||||
}.
|
||||
|
||||
-type prototype_payproc() :: #{
|
||||
@ -87,7 +85,6 @@
|
||||
-type payout() :: payouts_payout_manager_thrift:'Payout'().
|
||||
|
||||
-type entity_id() :: binary().
|
||||
-type timestamp() :: binary().
|
||||
|
||||
-export_type([prototypes/0]).
|
||||
-export_type([prototype_operation/0]).
|
||||
@ -141,13 +138,7 @@ build(operation, Params = #{id := OperationID}, Acc, _WoodyCtx) ->
|
||||
};
|
||||
build(payment_tool, Params = #{}, Acc, _WoodyCtx) ->
|
||||
Acc#bctx_v1_ContextFragment{
|
||||
payment_tool = #bctx_v1_ContextPaymentTool{
|
||||
scope = #bctx_v1_AuthScope{
|
||||
invoice = maybe_entity(invoice, Params),
|
||||
customer = maybe_entity(customer, Params)
|
||||
},
|
||||
expiration = maps:get(expiration, Params, undefined)
|
||||
}
|
||||
payment_tool = maps:get(payment_tool_context, Params, undefined)
|
||||
};
|
||||
build(payproc, Params = #{}, Acc, WoodyCtx) ->
|
||||
Acc#bctx_v1_ContextFragment{
|
||||
|
@ -1,6 +1,7 @@
|
||||
-module(capi_crypto).
|
||||
|
||||
-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_data() :: #{
|
||||
@ -8,8 +9,7 @@
|
||||
valid_until := deadline(),
|
||||
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_token() :: dmsl_payment_tool_token_thrift:'PaymentToolToken'().
|
||||
-type payment_tool_token_payload() :: dmsl_payment_tool_token_thrift:'PaymentToolTokenPayload'().
|
||||
@ -22,11 +22,13 @@
|
||||
-export([encode_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().
|
||||
encode_token(TokenData) ->
|
||||
PaymentToolToken = encode_payment_tool_token(TokenData),
|
||||
ThriftType = {struct, struct, {dmsl_payment_tool_token_thrift, 'PaymentToolToken'}},
|
||||
{ok, EncodedToken} = lechiffre:encode(ThriftType, PaymentToolToken),
|
||||
{ok, EncodedToken} = lechiffre:encode(?THRIFT_TYPE, PaymentToolToken),
|
||||
TokenVersion = token_version(),
|
||||
<<TokenVersion/binary, ".", EncodedToken/binary>>.
|
||||
|
||||
@ -47,8 +49,7 @@ token_version() ->
|
||||
<<"v2">>.
|
||||
|
||||
decrypt_token(EncryptedPaymentToolToken) ->
|
||||
ThriftType = {struct, struct, {dmsl_payment_tool_token_thrift, 'PaymentToolToken'}},
|
||||
case lechiffre:decode(ThriftType, EncryptedPaymentToolToken) of
|
||||
case lechiffre:decode(?THRIFT_TYPE, EncryptedPaymentToolToken) of
|
||||
{ok, PaymentToolToken} ->
|
||||
Payload = PaymentToolToken#ptt_PaymentToolToken.payload,
|
||||
ValidUntil = PaymentToolToken#ptt_PaymentToolToken.valid_until,
|
||||
@ -73,11 +74,15 @@ encode_payment_tool_token(TokenData) ->
|
||||
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) ->
|
||||
undefined;
|
||||
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.
|
||||
encode_deadline(undefined) ->
|
||||
@ -107,14 +112,16 @@ encode_payment_tool_token_payload({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) ->
|
||||
undefined;
|
||||
decode_bouncer_data(Content) ->
|
||||
try
|
||||
erlang:binary_to_term(base64:decode(Content))
|
||||
catch
|
||||
error:Error ->
|
||||
Codec = thrift_strict_binary_codec:new(Content),
|
||||
case thrift_strict_binary_codec:read(Codec, ?BOUNCER_THRIFT_TYPE) of
|
||||
{ok, BouncerData, Codec1} ->
|
||||
_ = thrift_strict_binary_codec:close(Codec1),
|
||||
BouncerData;
|
||||
Error ->
|
||||
erlang:error({malformed_token, Error}, [Content])
|
||||
end.
|
||||
|
||||
|
@ -115,28 +115,33 @@ prepare('CreateCustomerAccessToken' = OperationID, Req, Context) ->
|
||||
{ok, #{authorize => Authorize, process => Process}};
|
||||
prepare('CreateBinding' = OperationID, Req, Context) ->
|
||||
CustomerID = maps:get(customerID, Req),
|
||||
CustomerBindingParams = maps:get('CustomerBindingParams', Req),
|
||||
PaymentToken = decode_payment_token(CustomerBindingParams),
|
||||
Authorize = fun() ->
|
||||
Prototypes = [
|
||||
{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)}
|
||||
end,
|
||||
Process = fun() ->
|
||||
Result =
|
||||
try
|
||||
CustomerBindingParams = maps:get('CustomerBindingParams', Req),
|
||||
#{payment_tool := PaymentTool} = PaymentToken,
|
||||
|
||||
{CustomerBindingID, RecPaymentToolID} = generate_binding_ids(
|
||||
OperationID,
|
||||
CustomerBindingParams,
|
||||
PaymentTool,
|
||||
Context
|
||||
),
|
||||
|
||||
EncodedCustomerBindingParams = encode_customer_binding_params(
|
||||
CustomerBindingID,
|
||||
RecPaymentToolID,
|
||||
CustomerBindingParams
|
||||
CustomerBindingParams,
|
||||
PaymentTool
|
||||
),
|
||||
|
||||
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) ->
|
||||
EventRange = #payproc_EventRange{},
|
||||
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) ->
|
||||
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),
|
||||
UserID = capi_handler_utils:get_user_id(Context),
|
||||
|
||||
PaymentResource = maps:get(<<"paymentResource">>, CustomerBindingParams),
|
||||
PaymentToolToken = maps:get(<<"paymentToolToken">>, PaymentResource),
|
||||
PaymentTool = capi_handler_decoder_party:decode_payment_tool(encode_payment_tool_token(PaymentToolToken)),
|
||||
CustomerBindingParamsEncrypted =
|
||||
maps:put(
|
||||
<<"paymentResource">>,
|
||||
maps:put(
|
||||
<<"paymentTool">>,
|
||||
PaymentTool,
|
||||
maps:remove(<<"paymentToolToken">>, PaymentResource)
|
||||
),
|
||||
CustomerBindingParams
|
||||
),
|
||||
PaymentResourceWoToken = maps:remove(<<"paymentToolToken">>, PaymentResource),
|
||||
CustomerBindingParamsEncrypted = CustomerBindingParams#{
|
||||
<<"paymentResource">> => PaymentResourceWoToken#{
|
||||
<<"paymentTool">> => capi_handler_decoder_party:decode_payment_tool(PaymentTool)
|
||||
}
|
||||
},
|
||||
|
||||
Identity = capi_bender:make_identity(
|
||||
{schema, capi_feature_schemas:customer_binding(), CustomerBindingParamsEncrypted}
|
||||
@ -354,11 +362,9 @@ generate_binding_ids(OperationID, CustomerBindingParams, Context = #{woody_conte
|
||||
encode_customer_binding_params(
|
||||
CustomerBindingID,
|
||||
RecPaymentToolID,
|
||||
#{<<"paymentResource">> := PaymentResource}
|
||||
#{<<"paymentResource">> := PaymentResource},
|
||||
PaymentTool
|
||||
) ->
|
||||
PaymentToolToken = maps:get(<<"paymentToolToken">>, PaymentResource),
|
||||
PaymentTool = encode_payment_tool_token(PaymentToolToken),
|
||||
|
||||
{ClientInfo, PaymentSession} =
|
||||
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
|
||||
{ok, TokenData} ->
|
||||
#{payment_tool := PaymentTool, valid_until := ValidUntil} = TokenData,
|
||||
% TODO #ED-162 Проверка времени жизни будет в bouncer, тут её следует убрать вместе с тестами
|
||||
{ok, #{valid_until := ValidUntil} = TokenData} ->
|
||||
case capi_utils:deadline_is_reached(ValidUntil) of
|
||||
true ->
|
||||
logger:warning("Payment tool token expired: ~p", [capi_utils:deadline_to_binary(ValidUntil)]),
|
||||
capi_handler:respond(logic_error(invalidPaymentToolToken));
|
||||
_ ->
|
||||
PaymentTool
|
||||
TokenData
|
||||
end;
|
||||
unrecognized ->
|
||||
encode_legacy_payment_tool_token(Token);
|
||||
% TODO-162: удалить устаревшие токены, заменить их на актуальные и поправить тесты
|
||||
decode_legacy_payment_token(Token);
|
||||
{error, {decryption_failed, Error}} ->
|
||||
logger:warning("Payment tool token decryption failed: ~p", [Error]),
|
||||
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
|
||||
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
|
||||
error:badarg ->
|
||||
capi_handler:respond(logic_error(invalidPaymentToolToken))
|
||||
|
@ -513,18 +513,11 @@ prepare(_OperationID, _Req, _Context) ->
|
||||
|
||||
prepare_payment_tool_prototype(undefined) ->
|
||||
#{};
|
||||
prepare_payment_tool_prototype(PaymentToken) ->
|
||||
prepare_payment_tool_prototype(#{bouncer_data := BouncerData}) ->
|
||||
#{
|
||||
expiration => prepare_payment_tool_expire(PaymentToken),
|
||||
scope => prepare_payment_tool_scope(PaymentToken)
|
||||
payment_tool_context => BouncerData
|
||||
}.
|
||||
|
||||
prepare_payment_tool_expire(#{valid_until := ValidUntil}) ->
|
||||
capi_utils:deadline_to_binary(ValidUntil).
|
||||
|
||||
prepare_payment_tool_scope(#{bouncer_data := BouncerData}) ->
|
||||
BouncerData.
|
||||
|
||||
%%
|
||||
validate_allocation(Allocation) ->
|
||||
case capi_allocation:validate(Allocation) of
|
||||
|
@ -112,7 +112,9 @@
|
||||
]}
|
||||
]},
|
||||
{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