TD-195: Remove old payment methods (#9)

* removed legacy

* fixed format

* fixed

* added some tests, refactored for more coverage

* added requested changes

* fixed dep

* fixed

* fixed

* fixed
This commit is contained in:
Артем 2022-04-20 15:07:35 +03:00 committed by GitHub
parent b0b9ece994
commit d4fe7e16bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 251 additions and 488 deletions

13
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,13 @@
# Чеклист по изменениям
В этом документе будут перечислены архитектурные особенности сервиса,
которые следует учитывать при добавлении новых программных модулей.
- **Проверить не влияет ли публикуемое изменение на идемпотентность операций,
выполняемых во время перехода между версиями сервиса**.
При изменении внешнего или внутреннего формата данных нужно учитывать их
использование для формирования запросов к API, так как во время публикации
новой версии сервиса могут возникнуть конфликты в запросах, которые должны
работать идемпотентно. [Подробнее](README.md).
- **При добавлении новых методов в API необходимо доработать [политики авторизации](https://github.com/valitydev/bouncer-policies)**.

View File

@ -2,13 +2,12 @@ ARG OTP_VERSION
# Build the release
FROM docker.io/library/erlang:${OTP_VERSION} AS builder
ARG BUILDARCH
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Install thrift compiler
ARG THRIFT_VERSION
RUN wget -q -O- "https://github.com/valitydev/thrift/releases/download/${THRIFT_VERSION}/thrift-${THRIFT_VERSION}-linux-${BUILDARCH}.tar.gz" \
ARG TARGETARCH
RUN wget -q -O- "https://github.com/valitydev/thrift/releases/download/${THRIFT_VERSION}/thrift-${THRIFT_VERSION}-linux-${TARGETARCH}.tar.gz" \
| tar -xvz -C /usr/local/bin/
# Copy sources
@ -17,8 +16,8 @@ COPY . /build/
# Build the release
WORKDIR /build
RUN rebar3 compile
RUN rebar3 as prod release
RUN rebar3 compile && \
rebar3 as prod release
# Make a runner image
FROM docker.io/library/erlang:${OTP_VERSION}-slim
@ -37,7 +36,10 @@ WORKDIR /opt/${SERVICE_NAME}
COPY --from=builder /build/_build/prod/rel/${SERVICE_NAME} /opt/${SERVICE_NAME}
RUN echo "#!/bin/sh" >> /entrypoint.sh && \
echo "exec /opt/${SERVICE_NAME}/bin/${SERVICE_NAME} foreground" >> /entrypoint.sh && \
chmod +x /entrypoint.sh
ENTRYPOINT []
CMD /opt/${SERVICE_NAME}/bin/${SERVICE_NAME} foreground
CMD ["/entrypoint.sh"]
EXPOSE 8022

View File

@ -1,13 +1,12 @@
ARG OTP_VERSION
FROM docker.io/library/erlang:${OTP_VERSION}
ARG BUILDARCH
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Install thrift compiler
ARG THRIFT_VERSION
RUN wget -q -O- "https://github.com/valitydev/thrift/releases/download/${THRIFT_VERSION}/thrift-${THRIFT_VERSION}-linux-${BUILDARCH}.tar.gz" \
ARG TARGETARCH
RUN wget -q -O- "https://github.com/valitydev/thrift/releases/download/${THRIFT_VERSION}/thrift-${THRIFT_VERSION}-linux-${TARGETARCH}.tar.gz" \
| tar -xvz -C /usr/local/bin/
# Set env
@ -15,4 +14,4 @@ ENV CHARSET=UTF-8
ENV LANG=C.UTF-8
# Set runtime
CMD /bin/bash
CMD ["/bin/bash"]

View File

@ -25,7 +25,7 @@ dev-image: .image.dev
.image.dev: Dockerfile.dev .env
$(DOCKER) build $(DOTENV:%=--build-arg %) -f Dockerfile.dev -t $(DEV_IMAGE_TAG) .
$(DOCKER) image ls -q -f "reference=$(DEV_IMAGE_ID)" | head -n1 > $@
$(DOCKER) image ls -q -f "reference=$(DEV_IMAGE_TAG)" | head -n1 > $@
clean-dev-image:
ifneq ($(DEV_IMAGE_ID),)

View File

@ -21,6 +21,21 @@
[1]: http://erlang.org/doc/man/shell.html
[2]: https://github.com/erlware/relx
[3]: https://docs.docker.com/machine/install-machine/
[4]: https://github.com/valitydev/feat
## Реализация идемпотентности запросов
Идемпотентность запросов создания/изменения сущностей обеспечивается специальной [подсистемой][4],
которая оперирует несколькими понятиями:
- ExternalId - внешний идентификатор сущности.
- Features - значимая часть данных запроса, изменение которых может появлиять на результат выполнения запроса.
- Schema - рецепт как из полной структуры данных запроса получить Features.
В случае, когда в запросе фигурирует ExternalId, сервис будет обрабатывать запрос идемпотентно.
Для структуры данных запроса существует Schema, по которой извлекается Features. Features ассоциируется с
переданным ExternalId. При повторе запроса с таким же ExternalId код извлечет Features из новых данных и
сравнит их с Features оригинального запроса, в случае совпадения сервис ответит идемпотентно, в противном случае
сервис ответит ошибкой с кодом 409.
## TODO

View File

@ -84,9 +84,9 @@ encode_payment_tool_token_payload({digital_wallet, DigitalWallet}) ->
{digital_wallet_payload, #ptt_DigitalWalletPayload{
digital_wallet = DigitalWallet
}};
encode_payment_tool_token_payload({crypto_currency_deprecated, CryptoCurrency}) ->
encode_payment_tool_token_payload({crypto_currency, CryptoCurrency}) ->
{crypto_currency_payload, #ptt_CryptoCurrencyPayload{
crypto_currency_deprecated = CryptoCurrency
crypto_currency = CryptoCurrency
}};
encode_payment_tool_token_payload({mobile_commerce, MobileCommerce}) ->
{mobile_commerce_payload, #ptt_MobileCommercePayload{
@ -109,7 +109,7 @@ decode_payment_tool_token_payload(PaymentToolToken) ->
{digital_wallet_payload, Payload} ->
{digital_wallet, Payload#ptt_DigitalWalletPayload.digital_wallet};
{crypto_currency_payload, Payload} ->
{crypto_currency_deprecated, Payload#ptt_CryptoCurrencyPayload.crypto_currency_deprecated};
{crypto_currency, Payload#ptt_CryptoCurrencyPayload.crypto_currency};
{mobile_commerce_payload, Payload} ->
{mobile_commerce, Payload#ptt_MobileCommercePayload.mobile_commerce}
end.

View File

@ -7,12 +7,8 @@
-export([get_payment_institutions/1]).
-export([get/2]).
-export([get_objects_by_type/2]).
-export([map_to_dictionary_id/2]).
-export([map_to_dictionary_id/3]).
-export([encode_enum/2]).
-export([encode_enum/3]).
-export([fetch_type_info/1]).
-export([fetch_type_info/2]).
-export([extract_type/1]).
-type processing_context() :: capi_handler:processing_context().
@ -80,57 +76,6 @@ get(Ref, Context) ->
{error, not_found}
end.
-spec map_to_dictionary_id(dmt_client:object_type(), ID :: undefined | term()) -> NewRef :: undefined | term().
map_to_dictionary_id(ObjectName, LegacyID) ->
map_to_dictionary_id(ObjectName, LegacyID, undefined).
-spec map_to_dictionary_id(dmt_client:object_type(), ID :: undefined | term(), NewRef) -> NewRef when
NewRef :: term() | no_return().
map_to_dictionary_id(ObjectName, LegacyID, NewRef) ->
DictionaryID =
case LegacyID of
undefined ->
NewRef;
_ ->
case fetch_dictionary_id(ObjectName, LegacyID) of
{ok, Ref} when Ref =:= NewRef; NewRef =:= undefined ->
Ref;
{ok, OtherRef} ->
logger:warning(
"Mismatch in mapped to dictionary value and passed ~p: ~p->~p and ~p."
"Using dictionary value (the latter)",
[ObjectName, LegacyID, OtherRef, NewRef]
),
OtherRef;
{error, _} = Error ->
logger:warning(
"Failed to find mapping ~w with id ~w: "
"chance of domain misconifuration (Error: ~w). Using passed new ref",
[ObjectName, LegacyID, Error]
),
NewRef
end
end,
case DictionaryID of
undefined ->
error({no_mapping, {ObjectName, LegacyID, DictionaryID}});
DictionaryID ->
DictionaryID
end.
fetch_dictionary_id(ObjectName, LegacyID) ->
{dmsl_domain_thrift, RefRecordShortName} =
extract_type(fetch_type_info([{variant, ObjectName}, {field, ref}])),
RefRecordName = dmsl_domain_thrift:record_name(RefRecordShortName),
case get({ObjectName, {RefRecordName, LegacyID}}, undefined) of
{ok, Data} ->
{DataFieldID, _Kind, _Info, data, _Default} =
fetch_type_info([{variant, ObjectName}, {field, data}]),
{ok, element(1 + DataFieldID, Data)};
{error, _} = Error ->
Error
end.
-spec encode_enum(Type :: atom(), binary()) -> {ok, atom()} | {error, unknown_atom | unknown_variant}.
encode_enum(Type, Binary) ->
encode_enum(dmsl_domain_thrift, Type, Binary).
@ -148,25 +93,6 @@ encode_enum(Module, Type, Binary) ->
{error, unknown_atom}
end.
-spec fetch_type_info([{variant, atom()} | {field, atom()}]) -> term().
fetch_type_info(Path) ->
fetch_type_info('DomainObject', Path).
-spec fetch_type_info(TypeInfo :: term(), [{variant, atom()} | {field, atom()}]) -> term().
fetch_type_info(TypeInfo, []) ->
TypeInfo;
fetch_type_info(TypeInfo, [{variant, Variant} | Rest]) ->
fetch_type_info(fetch_struct_field(TypeInfo, union, Variant), Rest);
fetch_type_info(TypeInfo, [{field, Field} | Rest]) ->
fetch_type_info(fetch_struct_field(TypeInfo, struct, Field), Rest);
fetch_type_info(_, _) ->
error(badarg).
fetch_struct_field(TypeInfo, Kind, Field) ->
{Module, Type} = extract_type(TypeInfo),
{struct, Kind, Fields} = Module:struct_info(Type),
lists:keyfind(Field, 4, Fields).
-type type() :: atom().
-type type_info() ::
type() | {module(), type()} | dmsl_domain_thrift:struct_info().

View File

@ -634,7 +634,7 @@ compare_customer_features_test() ->
-spec read_customer_binding_features_test() -> _.
read_customer_binding_features_test() ->
Session = ?TEST_PAYMENT_SESSION(<<"Session">>),
Tool = ?TEST_PAYMENT_TOOL(visa, <<"TOKEN">>),
Tool = ?TEST_PAYMENT_TOOL(<<"visa">>, <<"TOKEN">>),
Request = payment_resource(Session, Tool),
Features = #{
?payment_resource => #{
@ -657,11 +657,11 @@ read_customer_binding_features_test() ->
-spec compare_customer_binding_features_test() -> _.
compare_customer_binding_features_test() ->
Session1 = ?TEST_PAYMENT_SESSION(<<"Session1">>),
Tool1 = ?TEST_PAYMENT_TOOL(visa),
Tool1 = ?TEST_PAYMENT_TOOL(<<"visa">>),
Request1 = payment_resource(Session1, Tool1),
Session2 = ?TEST_PAYMENT_SESSION(<<"Session2">>),
Tool2 = ?TEST_PAYMENT_TOOL(mastercard)#{<<"exp_date">> => <<"01/2020">>},
Tool2 = ?TEST_PAYMENT_TOOL(<<"mastercard">>)#{<<"exp_date">> => <<"01/2020">>},
Request2 = payment_resource(Session2, Tool2),
common_compare_tests(customer_binding(), Request1, Request2, [

View File

@ -660,7 +660,7 @@ compare_customer_features_test() ->
-spec read_customer_binding_features_test() -> _.
read_customer_binding_features_test() ->
Session = ?TEST_PAYMENT_SESSION(<<"Session">>),
Tool = ?TEST_PAYMENT_TOOL(visa, <<"TOKEN">>),
Tool = ?TEST_PAYMENT_TOOL(<<"visa">>, <<"TOKEN">>),
Request = payment_resource(Session, Tool),
Features = #{
?payment_resource => #{
@ -699,11 +699,11 @@ read_customer_binding_features_test() ->
-spec compare_customer_binding_features_test() -> _.
compare_customer_binding_features_test() ->
Session1 = ?TEST_PAYMENT_SESSION(<<"Session1">>),
Tool1 = ?TEST_PAYMENT_TOOL(visa),
Tool1 = ?TEST_PAYMENT_TOOL(<<"visa">>),
Request1 = payment_resource(Session1, Tool1),
Session2 = ?TEST_PAYMENT_SESSION(<<"Session2">>),
Tool2 = ?TEST_PAYMENT_TOOL(mastercard)#{<<"exp_date">> => <<"01/2020">>},
Tool2 = ?TEST_PAYMENT_TOOL(<<"mastercard">>)#{<<"exp_date">> => <<"01/2020">>},
Request2 = payment_resource(Session2, Tool2),
common_compare_tests(customer_binding(), Request1, Request2, [

View File

@ -365,23 +365,15 @@ encode_payment_tool_token(Token) ->
#{payment_tool := PaymentTool, 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)]),
logger:info("Payment tool token expired: ~p", [capi_utils:deadline_to_binary(ValidUntil)]),
capi_handler:respond(logic_error('invalidPaymentToolToken'));
_ ->
PaymentTool
end;
unrecognized ->
encode_legacy_payment_tool_token(Token);
capi_handler:respond(logic_error('invalidPaymentToolToken'));
{error, {decryption_failed, Error}} ->
logger:warning("Payment tool token decryption failed: ~p", [Error]),
capi_handler:respond(logic_error('invalidPaymentToolToken'))
end.
encode_legacy_payment_tool_token(Token) ->
try
capi_handler_encoder:encode_payment_tool(capi_utils:base64url_to_map(Token))
catch
error:badarg ->
logger:info("Payment tool token decryption failed: ~p", [Error]),
capi_handler:respond(logic_error('invalidPaymentToolToken'))
end.

View File

@ -476,7 +476,7 @@ decode_payment_methods(PaymentMethodRefs) ->
decode_payment_method(bank_card, Cards) ->
{Regular, Tokenized} =
lists:partition(
fun(#domain_BankCardPaymentMethod{token_provider_deprecated = TP}) -> TP =:= undefined end,
fun(#domain_BankCardPaymentMethod{payment_token = TP}) -> TP =:= undefined end,
Cards
),
[
@ -487,64 +487,50 @@ decode_payment_method(payment_terminal, Providers) ->
[
#{
<<"method">> => <<"PaymentTerminal">>,
<<"providers">> => [Id || #domain_PaymentServiceRef{id = Id} <- Providers]
<<"providers">> => [
capi_handler_decoder_utils:decode_payment_service_ref(Provider)
|| Provider <- Providers
]
}
];
decode_payment_method(digital_wallet, Providers) ->
[
#{
<<"method">> => <<"DigitalWallet">>,
<<"providers">> => [Id || #domain_PaymentServiceRef{id = Id} <- Providers]
<<"providers">> => [
capi_handler_decoder_utils:decode_payment_service_ref(Provider)
|| Provider <- Providers
]
}
];
decode_payment_method(crypto_currency, CryptoCurrencies) ->
[
#{
<<"method">> => <<"CryptoWallet">>,
<<"cryptoCurrencies">> => [Id || #domain_CryptoCurrencyRef{id = Id} <- CryptoCurrencies]
<<"cryptoCurrencies">> => [
capi_handler_decoder_utils:decode_crypto_currency_ref(Currency)
|| Currency <- CryptoCurrencies
]
}
];
decode_payment_method(mobile, MobileOperators) ->
[
#{
<<"method">> => <<"MobileCommerce">>,
<<"operators">> => [Id || #domain_MobileOperatorRef{id = Id} <- MobileOperators]
<<"operators">> => [
capi_handler_decoder_utils:decode_mobile_operator_ref(Operator)
|| Operator <- MobileOperators
]
}
];
decode_payment_method(empty_cvv_bank_card_deprecated, PaymentSystems) ->
[#{<<"method">> => <<"BankCard">>, <<"paymentSystems">> => lists:map(fun genlib:to_binary/1, PaymentSystems)}];
decode_payment_method(bank_card_deprecated, PaymentSystems) ->
[#{<<"method">> => <<"BankCard">>, <<"paymentSystems">> => lists:map(fun genlib:to_binary/1, PaymentSystems)}];
decode_payment_method(tokenized_bank_card_deprecated, TokenizedBankCards) ->
decode_tokenized_bank_cards(TokenizedBankCards);
decode_payment_method(payment_terminal_deprecated, Providers) ->
[#{<<"method">> => <<"PaymentTerminal">>, <<"providers">> => lists:map(fun genlib:to_binary/1, Providers)}];
decode_payment_method(digital_wallet_deprecated, Providers) ->
[#{<<"method">> => <<"DigitalWallet">>, <<"providers">> => lists:map(fun genlib:to_binary/1, Providers)}];
decode_payment_method(crypto_currency_deprecated, CryptoCurrencies) ->
Decoder = fun capi_handler_decoder_utils:convert_crypto_currency_to_swag/1,
[
#{
<<"method">> => <<"CryptoWallet">>,
<<"cryptoCurrencies">> => lists:map(Decoder, CryptoCurrencies)
}
];
decode_payment_method(mobile_deprecated, MobileOperators) ->
[#{<<"method">> => <<"MobileCommerce">>, <<"operators">> => lists:map(fun genlib:to_binary/1, MobileOperators)}].
].
decode_bank_card(#domain_BankCardPaymentMethod{payment_system_deprecated = PS}) -> genlib:to_binary(PS).
decode_bank_card(#domain_BankCardPaymentMethod{payment_system = PS}) ->
capi_handler_decoder_utils:decode_payment_system_ref(PS).
decode_tokenized_bank_cards([#domain_BankCardPaymentMethod{} | _] = TokenizedBankCards) ->
PropTokenizedBankCards = [
{TP, PS}
|| #domain_BankCardPaymentMethod{payment_system_deprecated = PS, token_provider_deprecated = TP} <-
TokenizedBankCards
],
do_decode_tokenized_bank_cards(PropTokenizedBankCards);
decode_tokenized_bank_cards([#domain_TokenizedBankCard{} | _] = TokenizedBankCards) ->
PropTokenizedBankCards = [
{TP, PS}
|| #domain_TokenizedBankCard{payment_system_deprecated = PS, token_provider_deprecated = TP} <-
|| #domain_BankCardPaymentMethod{payment_system = PS, payment_token = TP} <-
TokenizedBankCards
],
do_decode_tokenized_bank_cards(PropTokenizedBankCards);
@ -563,8 +549,10 @@ do_decode_tokenized_bank_cards(PropTokenizedBankCards) ->
decode_tokenized_bank_card(TokenProvider, PaymentSystems) ->
#{
<<"method">> => <<"BankCard">>,
<<"paymentSystems">> => lists:map(fun genlib:to_binary/1, PaymentSystems),
<<"tokenProviders">> => [genlib:to_binary(TokenProvider)]
<<"paymentSystems">> =>
lists:map(fun capi_handler_decoder_utils:decode_payment_system_ref/1, PaymentSystems),
<<"tokenProviders">> =>
[capi_handler_decoder_utils:decode_bank_card_token_service_ref(TokenProvider)]
}.
-spec make_invoice_and_token(capi_handler_encoder:encode_data(), processing_context()) ->

View File

@ -175,9 +175,7 @@ decode_payment_tool({digital_wallet, DigitalWallet}) ->
decode_payment_tool({mobile_commerce, MobileCommerce}) ->
decode_mobile_commerce(MobileCommerce);
decode_payment_tool({crypto_currency, CryptoCurrency}) ->
decode_crypto_wallet(CryptoCurrency);
decode_payment_tool({crypto_currency_deprecated, LegacyCryptoCurrency}) ->
decode_legacy_crypto_wallet(LegacyCryptoCurrency).
decode_crypto_wallet(CryptoCurrency).
-spec wrap_payment_tool_token(capi_handler_decoder_utils:decode_data()) -> binary().
wrap_payment_tool_token(#{<<"type">> := <<"bank_card">>} = BankCard) ->
@ -205,29 +203,28 @@ wrap_payment_tool_token(#{<<"type">> := <<"mobile_commerce">>} = MobileCommerce)
decode_bank_card(#domain_BankCard{
'token' = Token,
'payment_system' = NewPaymentSystem,
'payment_system_deprecated' = LegacyPaymentSystem,
'payment_system' = PaymentSystem,
'bin' = Bin,
'last_digits' = LastDigits,
'token_provider_deprecated' = TokenProvider,
'payment_token' = BankCardTokenServiceRef,
'issuer_country' = IssuerCountry,
'bank_name' = BankName,
'metadata' = Metadata,
'is_cvv_empty' = IsCVVEmpty,
'exp_date' = ExpDate,
'cardholder_name' = CardHolder
%% 'tokenization_method' = TokenizationMethod,
%% 'payment_token' = BankCardTokenServiceRef,
%% 'token_provider_deprecated' = LegacyTokenProvider
% 'tokenization_method' = TokenizationMethod
}) ->
PaymentSystem = map_to_dictionary_id(payment_system_legacy, LegacyPaymentSystem, NewPaymentSystem),
genlib_map:compact(#{
<<"type">> => <<"bank_card">>,
<<"token">> => Token,
<<"payment_system">> => PaymentSystem,
<<"payment_system">> => capi_handler_decoder_utils:decode_payment_system_ref(PaymentSystem),
<<"bin">> => Bin,
<<"masked_pan">> => LastDigits,
<<"token_provider">> => TokenProvider,
<<"token_provider">> => capi_utils:maybe(
BankCardTokenServiceRef,
fun capi_handler_decoder_utils:decode_bank_card_token_service_ref/1
),
<<"issuer_country">> => IssuerCountry,
<<"bank_name">> => BankName,
<<"metadata">> => decode_bank_card_metadata(Metadata),
@ -248,26 +245,20 @@ decode_bank_card_metadata(undefined) ->
decode_bank_card_metadata(Meta) ->
maps:map(fun(_, Data) -> capi_msgp_marshalling:unmarshal(Data) end, Meta).
decode_payment_terminal(#domain_PaymentTerminal{
payment_service = PaymentService,
terminal_type_deprecated = LegacyTerminalType
}) ->
Type = map_to_dictionary_id(terminal_provider_legacy, LegacyTerminalType, PaymentService),
decode_payment_terminal(#domain_PaymentTerminal{payment_service = PaymentService}) ->
#{
<<"type">> => <<"payment_terminal">>,
<<"terminal_type">> => Type
<<"terminal_type">> => capi_handler_decoder_utils:decode_payment_service_ref(PaymentService)
}.
decode_digital_wallet(#domain_DigitalWallet{
payment_service = PaymentService,
provider_deprecated = LegacyProvider,
id = ID,
token = Token
}) ->
Provider = map_to_dictionary_id(payment_service_legacy, LegacyProvider, PaymentService),
genlib_map:compact(#{
<<"type">> => <<"digital_wallet">>,
<<"provider">> => Provider,
<<"provider">> => capi_handler_decoder_utils:decode_payment_service_ref(PaymentService),
<<"id">> => ID,
<<"token">> => Token
}).
@ -275,30 +266,22 @@ decode_digital_wallet(#domain_DigitalWallet{
decode_crypto_wallet(CryptoCurrency) ->
#{
<<"type">> => <<"crypto_wallet">>,
<<"crypto_currency">> => CryptoCurrency
}.
decode_legacy_crypto_wallet(LegacyCryptoCurrency) ->
CryptoCurrency = map_to_dictionary_id(crypto_currency_legacy, LegacyCryptoCurrency),
#{
<<"type">> => <<"crypto_wallet">>,
<<"crypto_currency">> => CryptoCurrency
<<"crypto_currency">> => capi_handler_decoder_utils:decode_crypto_currency_ref(CryptoCurrency)
}.
decode_mobile_commerce(MobileCommerce) ->
#domain_MobileCommerce{
operator = NewMobileOperator,
operator_deprecated = LegacyOperator,
operator = MobileOperator,
phone = #domain_MobilePhone{
cc = Cc,
ctn = Ctn
}
} = MobileCommerce,
MobileOperator = map_to_dictionary_id(mobile_operator_legacy, LegacyOperator, NewMobileOperator),
Phone = #{<<"cc">> => Cc, <<"ctn">> => Ctn},
#{
<<"type">> => <<"mobile_commerce">>,
<<"phone">> => Phone,
<<"operator">> => MobileOperator
<<"operator">> => capi_handler_decoder_utils:decode_mobile_operator_ref(MobileOperator)
}.
-spec decode_payment_tool_details(capi_handler_encoder:encode_data()) -> capi_handler_decoder_utils:decode_data().
@ -313,12 +296,6 @@ decode_payment_tool_details({crypto_currency, #domain_CryptoCurrencyRef{id = Cry
<<"detailsType">> => <<"PaymentToolDetailsCryptoWallet">>,
<<"cryptoCurrency">> => CryptoCurrency
};
decode_payment_tool_details({crypto_currency_deprecated, LegacyCryptoCurrency}) ->
CryptoCurrency = map_to_dictionary_id(crypto_currency_legacy, LegacyCryptoCurrency),
#{
<<"detailsType">> => <<"PaymentToolDetailsCryptoWallet">>,
<<"cryptoCurrency">> => CryptoCurrency
};
decode_payment_tool_details({mobile_commerce, MobileCommerce}) ->
#domain_MobileCommerce{
phone = Phone
@ -335,40 +312,30 @@ mask_phone_number(PhoneNumber) ->
decode_bank_card_details(BankCard, V) ->
LastDigits = capi_handler_decoder_utils:decode_last_digits(BankCard#domain_BankCard.last_digits),
Bin = capi_handler_decoder_utils:decode_bank_card_bin(BankCard#domain_BankCard.bin),
PaymentSystem =
map_to_dictionary_id(
payment_system_legacy,
BankCard#domain_BankCard.payment_system_deprecated,
BankCard#domain_BankCard.payment_system
),
TokenProvider =
map_to_dictionary_id(
payment_token_legacy,
BankCard#domain_BankCard.token_provider_deprecated,
BankCard#domain_BankCard.payment_token
),
PaymentSystem = BankCard#domain_BankCard.payment_system,
TokenProvider = BankCard#domain_BankCard.payment_token,
capi_handler_utils:merge_and_compact(V, #{
<<"last4">> => LastDigits,
<<"first6">> => Bin,
<<"cardNumberMask">> => capi_handler_decoder_utils:decode_masked_pan(Bin, LastDigits),
<<"paymentSystem">> => PaymentSystem,
<<"tokenProvider">> => TokenProvider
<<"paymentSystem">> => capi_handler_decoder_utils:decode_payment_system_ref(PaymentSystem),
<<"tokenProvider">> => capi_utils:maybe(
TokenProvider,
fun capi_handler_decoder_utils:decode_bank_card_token_service_ref/1
)
% TODO: Uncomment or delete this when we negotiate deploying non-breaking changes
% <<"tokenizationMethod">> => genlib:to_binary(BankCard#domain_BankCard.tokenization_method)
% <<"tokenization_method">> => TokenizationMethod
}).
decode_payment_terminal_details(
#domain_PaymentTerminal{
payment_service = PaymentService,
terminal_type_deprecated = LegacyTerminalType
payment_service = PaymentService
},
V
) ->
Type = map_to_dictionary_id(terminal_provider_legacy, LegacyTerminalType, PaymentService),
V#{
<<"provider">> => Type
<<"provider">> => capi_handler_decoder_utils:decode_payment_service_ref(PaymentService)
}.
decode_digital_wallet_details(#domain_DigitalWallet{payment_service = Provider}, V) ->
@ -452,16 +419,6 @@ decode_mobile_phone(#domain_MobilePhone{cc = Cc, ctn = Ctn}) ->
gen_phone_number(#{<<"cc">> := Cc, <<"ctn">> := Ctn}) ->
<<"+", Cc/binary, Ctn/binary>>.
map_to_dictionary_id(_ObjectName, undefined) -> undefined;
map_to_dictionary_id(ObjectName, LegacyID) -> unwrap_ref(capi_domain:map_to_dictionary_id(ObjectName, LegacyID)).
map_to_dictionary_id(_ObjectName, undefined, undefined) ->
undefined;
map_to_dictionary_id(ObjectName, LegacyID, NewRef) ->
unwrap_ref(capi_domain:map_to_dictionary_id(ObjectName, LegacyID, NewRef)).
unwrap_ref({Type, ID}) when is_atom(Type) ->
ID.
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").

View File

@ -4,6 +4,11 @@
-export([decode_map/2]).
-export([decode_currency/1]).
-export([decode_payment_system_ref/1]).
-export([decode_payment_service_ref/1]).
-export([decode_crypto_currency_ref/1]).
-export([decode_bank_card_token_service_ref/1]).
-export([decode_mobile_operator_ref/1]).
-export([decode_business_schedule_ref/1]).
-export([decode_bank_card_bin/1]).
-export([decode_last_digits/1]).
@ -21,6 +26,11 @@
-type decode_data() :: #{binary() => term()}.
-type encoded_currency() :: dmsl_domain_thrift:'Currency'() | dmsl_domain_thrift:'CurrencyRef'().
-type encoded_payment_system_ref() :: dmsl_domain_thrift:'PaymentSystemRef'().
-type encoded_payment_service_ref() :: dmsl_domain_thrift:'PaymentServiceRef'().
-type encoded_crypto_currency_ref() :: dmsl_domain_thrift:'CryptoCurrencyRef'().
-type encoded_bank_card_token_service_ref() :: dmsl_domain_thrift:'BankCardTokenServiceRef'().
-type encoded_mobile_operator_ref() :: dmsl_domain_thrift:'MobileOperatorRef'().
-spec decode_map(map(), fun((_) -> any())) -> [any()].
decode_map(Items, Fun) ->
@ -30,6 +40,21 @@ decode_map(Items, Fun) ->
decode_currency(#domain_Currency{symbolic_code = SymbolicCode}) -> SymbolicCode;
decode_currency(#domain_CurrencyRef{symbolic_code = SymbolicCode}) -> SymbolicCode.
-spec decode_payment_system_ref(encoded_payment_system_ref()) -> binary().
decode_payment_system_ref(#domain_PaymentSystemRef{id = ID}) -> ID.
-spec decode_payment_service_ref(encoded_payment_service_ref()) -> binary().
decode_payment_service_ref(#domain_PaymentServiceRef{id = ID}) -> ID.
-spec decode_crypto_currency_ref(encoded_crypto_currency_ref()) -> binary().
decode_crypto_currency_ref(#domain_CryptoCurrencyRef{id = ID}) -> ID.
-spec decode_bank_card_token_service_ref(encoded_bank_card_token_service_ref()) -> binary().
decode_bank_card_token_service_ref(#domain_BankCardTokenServiceRef{id = ID}) -> ID.
-spec decode_mobile_operator_ref(encoded_mobile_operator_ref()) -> binary().
decode_mobile_operator_ref(#domain_MobileOperatorRef{id = ID}) -> ID.
-spec decode_business_schedule_ref(capi_handler_encoder:encode_data()) -> binary() | undefined.
decode_business_schedule_ref(#domain_BusinessScheduleRef{id = ID}) when ID /= undefined ->
ID;

View File

@ -5,7 +5,6 @@
-export([encode_contact_info/1]).
-export([encode_client_info/1]).
-export([encode_payment_tool/1]).
-export([encode_cash/1]).
-export([encode_cash/2]).
-export([encode_currency/1]).
@ -39,59 +38,6 @@ encode_client_info(ClientInfo) ->
ip_address = maps:get(<<"ip">>, ClientInfo)
}.
-spec encode_payment_tool(request_data()) -> encode_data().
encode_payment_tool(PaymentTool) ->
case PaymentTool of
#{<<"type">> := <<"bank_card">>} = Encoded ->
encode_bank_card(Encoded);
#{<<"type">> := <<"payment_terminal">>} = Encoded ->
encode_payment_terminal(Encoded);
#{<<"type">> := <<"digital_wallet">>} = Encoded ->
encode_digital_wallet(Encoded);
#{<<"type">> := <<"crypto_wallet">>} = Encoded ->
encode_crypto_wallet(Encoded);
#{<<"type">> := <<"mobile_commerce">>} = Encoded ->
encode_mobile_commerce(Encoded)
end.
encode_bank_card(BankCard) ->
{PaymentSystemDeprecated, PaymentSystem} =
infer_legacy_and_dictionary_ids(
payment_system_legacy,
maps:get(<<"payment_system">>, BankCard)
),
{PaymentTokenProvider, LegacyTokenProvider} =
infer_legacy_and_dictionary_ids(
payment_token_legacy,
genlib_map:get(<<"token_provider">>, BankCard)
),
{bank_card, #domain_BankCard{
token = maps:get(<<"token">>, BankCard),
payment_system = PaymentSystem,
payment_system_deprecated = PaymentSystemDeprecated,
bin = maps:get(<<"bin">>, BankCard, <<>>),
last_digits = maps:get(<<"masked_pan">>, BankCard),
payment_token = PaymentTokenProvider,
token_provider_deprecated = LegacyTokenProvider,
issuer_country = encode_residence(genlib_map:get(<<"issuer_country">>, BankCard)),
bank_name = genlib_map:get(<<"bank_name">>, BankCard),
metadata = encode_bank_card_metadata(genlib_map:get(<<"metadata">>, BankCard)),
is_cvv_empty = encode_bank_card_cvv_flag(genlib_map:get(<<"is_cvv_empty">>, BankCard)),
tokenization_method = genlib_map:get(<<"tokenization_method">>, BankCard)
}}.
encode_bank_card_cvv_flag(undefined) ->
undefined;
encode_bank_card_cvv_flag(Flag) when is_binary(Flag) ->
erlang:binary_to_existing_atom(Flag, utf8).
encode_bank_card_metadata(undefined) ->
undefined;
encode_bank_card_metadata(Meta) ->
maps:map(fun(_, Data) -> capi_msgp_marshalling:marshal(Data) end, Meta).
-spec encode_residence(binary() | undefined) -> atom().
encode_residence(undefined) ->
undefined;
@ -101,52 +47,6 @@ encode_residence(Residence) when is_binary(Residence) ->
{error, _} -> throw({encode_residence, invalid_residence})
end.
encode_payment_terminal(#{<<"terminal_type">> := Type}) ->
{LegacyTerminalProvider, PaymentService} =
infer_legacy_and_dictionary_ids(terminal_provider_legacy, Type),
{payment_terminal, #domain_PaymentTerminal{
payment_service = PaymentService,
terminal_type_deprecated = LegacyTerminalProvider
}}.
encode_digital_wallet(#{<<"provider">> := Provider, <<"id">> := ID} = Wallet) ->
{LegacyDigitalWalletProvider, PaymentService} =
infer_legacy_and_dictionary_ids(payment_service_legacy, Provider),
{digital_wallet, #domain_DigitalWallet{
payment_service = PaymentService,
provider_deprecated = LegacyDigitalWalletProvider,
id = ID,
token = maps:get(<<"token">>, Wallet, undefined)
}}.
encode_crypto_wallet(#{<<"crypto_currency">> := CryptoCurrency0}) ->
CryptoCurrency =
convert_crypto_currency_from_swag(CryptoCurrency0),
case infer_legacy_and_dictionary_ids(payment_service_legacy, CryptoCurrency) of
{LegacyCryptoCurrency, undefined} ->
{crypto_currency_deprecated, LegacyCryptoCurrency};
{_, CryptoCurrencyRef} ->
{crypto_currency, CryptoCurrencyRef}
end.
convert_crypto_currency_from_swag(<<"bitcoinCash">>) ->
<<"bitcoin_cash">>;
convert_crypto_currency_from_swag(CryptoCurrency) when is_binary(CryptoCurrency) ->
CryptoCurrency.
encode_mobile_commerce(#{<<"phoneNumber">> := PhoneNumber, <<"operator">> := Operator}) ->
#{<<"cc">> := Cc, <<"ctn">> := Ctn} = PhoneNumber,
{LegacyOperator, OperatorRef} = infer_legacy_and_dictionary_ids(mobile_operator_legacy, Operator),
{mobile_commerce, #domain_MobileCommerce{
operator = OperatorRef,
operator_deprecated = LegacyOperator,
phone = #domain_MobilePhone{
cc = Cc,
ctn = Ctn
}
}}.
-spec encode_cash(request_data()) -> encode_data().
encode_cash(Params) ->
Amount = genlib_map:get(<<"amount">>, Params),
@ -253,32 +153,3 @@ encode_stat_request(Dsl, ContinuationToken) when is_binary(Dsl) ->
dsl = Dsl,
continuation_token = ContinuationToken
}.
infer_legacy_and_dictionary_ids(ObjectVariant, ID) ->
{dmsl_domain_thrift, LegacyIDType} =
capi_domain:extract_type(
capi_domain:fetch_type_info(
'DomainObject',
[
{variant, ObjectVariant},
{field, ref},
{field, id}
]
)
),
case capi_domain:encode_enum(LegacyIDType, ID) of
{ok, LegacyID} ->
DictionaryID = map_to_dictionary_id(ObjectVariant, LegacyID),
{LegacyID, DictionaryID};
{error, _} ->
DictionaryID = ID,
{undefined, DictionaryID}
end.
map_to_dictionary_id(ObjectVariant, LegacyID) ->
try
capi_domain:map_to_dictionary_id(ObjectVariant, LegacyID)
catch
error:{no_mapping, _} -> undefined
end.

View File

@ -309,19 +309,22 @@ decode_stat_payment_tool_token({mobile_commerce, MobileCommerce}) ->
decode_bank_card(#merchstat_BankCard{
'token' = Token,
'payment_system_deprecated' = PaymentSystem,
'payment_system' = PaymentSystem,
'bin' = Bin,
'masked_pan' = MaskedPan,
'token_provider_deprecated' = TokenProvider
'payment_token' = BankCardTokenServiceRef
}) ->
capi_utils:map_to_base64url(
genlib_map:compact(#{
<<"type">> => <<"bank_card">>,
<<"token">> => Token,
<<"payment_system">> => PaymentSystem,
<<"payment_system">> => capi_handler_decoder_utils:decode_payment_system_ref(PaymentSystem),
<<"bin">> => Bin,
<<"masked_pan">> => MaskedPan,
<<"token_provider">> => TokenProvider,
<<"token_provider">> => capi_utils:maybe(
BankCardTokenServiceRef,
fun capi_handler_decoder_utils:decode_bank_card_token_service_ref/1
),
<<"issuer_country">> => undefined,
<<"bank_name">> => undefined,
<<"metadata">> => undefined
@ -391,19 +394,19 @@ decode_stat_payment_tool_details({mobile_commerce, MobileCommerce}) ->
decode_bank_card_details(BankCard, V) ->
LastDigits = capi_handler_decoder_utils:decode_last_digits(BankCard#merchstat_BankCard.masked_pan),
Bin = capi_handler_decoder_utils:decode_bank_card_bin(BankCard#merchstat_BankCard.bin),
PaymentSystem = capi_handler_decoder_utils:decode_payment_system_ref(BankCard#merchstat_BankCard.payment_system),
BankCardTokenServiceRef = capi_utils:maybe(
BankCard#merchstat_BankCard.payment_token,
fun capi_handler_decoder_utils:decode_bank_card_token_service_ref/1
),
capi_handler_utils:merge_and_compact(V, #{
<<"last4">> => LastDigits,
<<"first6">> => Bin,
<<"cardNumberMask">> => capi_handler_decoder_utils:decode_masked_pan(Bin, LastDigits),
<<"paymentSystem">> => genlib:to_binary(BankCard#merchstat_BankCard.payment_system_deprecated),
<<"tokenProvider">> => decode_token_provider(BankCard#merchstat_BankCard.token_provider_deprecated)
<<"paymentSystem">> => PaymentSystem,
<<"tokenProvider">> => BankCardTokenServiceRef
}).
decode_token_provider(Provider) when Provider /= undefined ->
genlib:to_binary(Provider);
decode_token_provider(undefined) ->
undefined.
decode_payment_terminal_details(#merchstat_PaymentTerminal{terminal_type = Type}, V) ->
V#{
<<"provider">> => genlib:to_binary(Type)

View File

@ -134,8 +134,7 @@
get_countries_test/1,
get_trade_bloc_by_id_test/1,
get_trade_bloc_by_id_not_found_test/1,
get_trade_blocs_test/1,
check_support_decrypt_v2_test/1
get_trade_blocs_test/1
]).
-type test_case_name() :: atom().
@ -152,8 +151,7 @@ init([]) ->
all() ->
[
{group, operations_by_api_key_token},
{group, operations_by_user_session_token},
{group, payment_tool_token_support}
{group, operations_by_user_session_token}
].
-spec groups() -> [{group_name(), list(), [test_case_name()]}].
@ -288,9 +286,6 @@ groups() ->
download_report_file_ok_test,
download_report_file_for_party_ok_test,
download_report_file_not_found_test
]},
{payment_tool_token_support, [], [
check_support_decrypt_v2_test
]}
].
@ -724,7 +719,7 @@ create_payment_ok_test(Config) ->
?STRING,
Config
),
PaymentTool = {bank_card, ?BANK_CARD(visa, ?EXP_DATE(2, 2020), <<"Degus">>)},
PaymentTool = {bank_card, ?BANK_CARD(<<"visa">>, ?EXP_DATE(2, 2020), <<"Degus">>)},
PaymentToolToken = capi_crypto:encode_token(#{payment_tool => PaymentTool, valid_until => undefined}),
Req = ?PAYMENT_PARAMS(ExternalID, PaymentToolToken),
{ok, _} = capi_client_payments:create_payment(?config(context, Config), Req, ?STRING).
@ -2565,25 +2560,3 @@ get_trade_blocs_test(Config) ->
]},
capi_client_trade_blocs:get_trade_blocs(?config(context, Config))
).
-spec check_support_decrypt_v2_test(config()) -> _.
check_support_decrypt_v2_test(_Config) ->
PaymentToolToken = <<
"v2.eyJhbGciOiJFQ0RILUVTIiwiZW5jIjoiQTEyOEdDTSIsImVwayI6eyJhbGciOiJFQ0RILUVTIiwiY3J2IjoiUC0yNTYiLCJrdHkiOi"
"JFQyIsInVzZSI6ImVuYyIsIngiOiJRanFmNFVrOTJGNzd3WXlEUjNqY3NwR2dpYnJfdVRmSXpMUVplNzVQb1R3IiwieSI6InA5cjJGV3F"
"mU2xBTFJXYWhUSk8xY3VneVZJUXVvdzRwMGdHNzFKMFJkUVEifSwia2lkIjoia3hkRDBvclZQR29BeFdycUFNVGVRMFU1TVJvSzQ3dVp4"
"V2lTSmRnbzB0MCJ9..j3zEyCqyfQjpEtQM.JAc3kqJm6zbn0fMZGlK_t14Yt4PvgOuoVL2DtkEgIXIqrxxWFbykKBGxQvwYisJYIUJJwt"
"YbwvuGEODcK2uTC2quPD2Ejew66DLJF2xcAwE.MNVimzi8r-5uTATNalgoBQ"
>>,
{ok, #{payment_tool := PaymentTool, valid_until := ValidUntil}} = capi_crypto:decode_token(PaymentToolToken),
?assertEqual(
{mobile_commerce, #domain_MobileCommerce{
phone = #domain_MobilePhone{
cc = <<"7">>,
ctn = <<"9210001122">>
},
operator_deprecated = megafone
}},
PaymentTool
),
?assertEqual(<<"2020-10-29T23:44:15.499Z">>, capi_utils:deadline_to_binary(ValidUntil)).

View File

@ -20,6 +20,7 @@
-export([
get_customer_ok_test/1,
create_binding_ok_test/1,
create_binding_fail_test/1,
create_binding_expired_test/1,
get_bindings_ok_test/1,
get_binding_ok_test/1,
@ -48,6 +49,7 @@ customer_access_token_tests() ->
[
get_customer_ok_test,
create_binding_ok_test,
create_binding_fail_test,
create_binding_expired_test,
get_bindings_ok_test,
get_binding_ok_test,
@ -162,7 +164,9 @@ create_binding_ok_test(Config) ->
],
Config
),
PaymentToolToken = ?TEST_PAYMENT_TOKEN,
PaymentTool = {bank_card, ?BANK_CARD},
ValidUntil = capi_utils:deadline_from_timeout(10000),
PaymentToolToken = capi_crypto:encode_token(#{payment_tool => PaymentTool, valid_until => ValidUntil}),
Req2 = #{
<<"paymentResource">> => #{
<<"paymentSession">> => ?TEST_PAYMENT_SESSION,
@ -192,6 +196,24 @@ create_binding_expired_test(Config) ->
Resp = capi_client_customers:create_binding(?config(context, Config), ?STRING, Req),
{error, {400, #{<<"code">> := <<"invalidPaymentToolToken">>}}} = Resp.
-spec create_binding_fail_test(config()) -> _.
create_binding_fail_test(Config) ->
_ = capi_ct_helper:mock_services(
[
{customer_management, fun('Get', _) -> {ok, ?CUSTOMER} end},
{generator, fun('GenerateID', _) -> capi_ct_helper_bender:generate_id(<<"bender_key">>) end}
],
Config
),
Req = #{
<<"paymentResource">> => #{
<<"paymentSession">> => ?TEST_PAYMENT_SESSION,
<<"paymentToolToken">> => <<"wrongPaymentToolToken">>
}
},
Resp = capi_client_customers:create_binding(?config(context, Config), ?STRING, Req),
{error, {400, #{<<"code">> := <<"invalidPaymentToolToken">>}}} = Resp.
-spec get_bindings_ok_test(config()) -> _.
get_bindings_ok_test(Config) ->
_ = capi_ct_helper:mock_services(

View File

@ -189,17 +189,19 @@
invoice_lifetime = ?LIFETIME_INTERVAL
}).
-define(BANK_CARD, #domain_BankCard{
token = ?STRING,
payment_system_deprecated = visa,
-define(BANK_CARD, ?BANK_CARD(<<"visa">>)).
-define(BANK_CARD(PS), #domain_BankCard{
token = PS,
payment_system = #domain_PaymentSystemRef{id = PS},
bin = <<"411111">>,
last_digits = <<"411111******1111">>
}).
-define(BANK_CARD(PS, ExpDate, CardHolder), ?BANK_CARD(PS, ExpDate, CardHolder, undefined)).
-define(BANK_CARD(PS, ExpDate, CardHolder, Category), #domain_BankCard{
token = ?TEST_PAYMENT_TOKEN(PS),
payment_system_deprecated = PS,
token = PS,
payment_system = #domain_PaymentSystemRef{id = PS},
exp_date = ExpDate,
cardholder_name = CardHolder,
category = Category,
@ -1007,17 +1009,17 @@
-define(STAT_BANK_CARD, #merchstat_BankCard{
token = ?STRING,
payment_system_deprecated = visa,
payment_system = #domain_PaymentSystemRef{id = <<"visa">>},
bin = <<"411111">>,
masked_pan = <<"411111******1111">>
}).
-define(STAT_BANK_CARD_WITH_TP, #merchstat_BankCard{
token = ?STRING,
payment_system_deprecated = visa,
payment_system = #domain_PaymentSystemRef{id = <<"visa">>},
bin = <<"411111">>,
masked_pan = <<"411111******1111">>,
token_provider_deprecated = applepay
payment_token = #domain_BankCardTokenServiceRef{id = <<"APPLE PAY">>}
}).
-define(REPORT_TYPE, <<"paymentRegistry">>).
@ -1159,26 +1161,6 @@
}}
}
}
}},
{payment_system_legacy, #domain_LegacyBankCardPaymentSystemRef{id = visa}} =>
{payment_system_legacy, #domain_LegacyBankCardPaymentSystemObject{
ref = #domain_LegacyBankCardPaymentSystemRef{id = visa},
data = #domain_PaymentSystemRef{id = <<"visa">>}
}},
{payment_system_legacy, #domain_LegacyBankCardPaymentSystemRef{id = mastercard}} =>
{payment_system_legacy, #domain_LegacyBankCardPaymentSystemObject{
ref = #domain_LegacyBankCardPaymentSystemRef{id = mastercard},
data = #domain_PaymentSystemRef{id = <<"mastercard">>}
}},
{payment_service_legacy, #domain_LegacyDigitalWalletProviderRef{id = qiwi}} =>
{payment_service_legacy, #domain_LegacyDigitalWalletProviderObject{
ref = #domain_LegacyDigitalWalletProviderRef{id = qiwi},
data = #domain_PaymentServiceRef{
id = <<"qiwi">>
}
}}
}
}).
@ -1225,68 +1207,62 @@
payment_methods =
{value,
ordsets:from_list([
#domain_PaymentMethodRef{
id = {bank_card_deprecated, mastercard}
},
#domain_PaymentMethodRef{
id = {bank_card_deprecated, visa}
},
#domain_PaymentMethodRef{
id = {crypto_currency_deprecated, bitcoin}
},
#domain_PaymentMethodRef{
id = {crypto_currency_deprecated, bitcoin_cash}
},
#domain_PaymentMethodRef{
id =
{tokenized_bank_card_deprecated, #domain_TokenizedBankCard{
payment_system_deprecated = mastercard,
token_provider_deprecated = applepay
}}
},
#domain_PaymentMethodRef{
id =
{tokenized_bank_card_deprecated, #domain_TokenizedBankCard{
payment_system_deprecated = visa,
token_provider_deprecated = applepay
{bank_card, #domain_BankCardPaymentMethod{
payment_system = #domain_PaymentSystemRef{id = <<"mastercard">>}
}}
},
#domain_PaymentMethodRef{
id =
{bank_card, #domain_BankCardPaymentMethod{
payment_system_deprecated = mastercard,
token_provider_deprecated = applepay,
payment_system = #domain_PaymentSystemRef{id = <<"visa">>}
}}
},
#domain_PaymentMethodRef{
id = {crypto_currency, #domain_CryptoCurrencyRef{id = <<"bitcoin">>}}
},
#domain_PaymentMethodRef{
id = {crypto_currency, #domain_CryptoCurrencyRef{id = <<"bitcoin_cash">>}}
},
#domain_PaymentMethodRef{
id =
{bank_card, #domain_BankCardPaymentMethod{
payment_system = #domain_PaymentSystemRef{id = <<"mastercard">>},
payment_token = #domain_BankCardTokenServiceRef{id = <<"applepay">>}
}}
},
#domain_PaymentMethodRef{
id =
{bank_card, #domain_BankCardPaymentMethod{
payment_system = #domain_PaymentSystemRef{id = <<"visa">>},
payment_token = #domain_BankCardTokenServiceRef{id = <<"applepay">>}
}}
},
#domain_PaymentMethodRef{
id =
{bank_card, #domain_BankCardPaymentMethod{
payment_system = #domain_PaymentSystemRef{id = <<"mastercard">>},
payment_token = #domain_BankCardTokenServiceRef{id = <<"applepay">>},
tokenization_method = dpan
}}
},
#domain_PaymentMethodRef{
id =
{bank_card, #domain_BankCardPaymentMethod{
payment_system_deprecated = visa,
token_provider_deprecated = applepay,
payment_system = #domain_PaymentSystemRef{id = <<"visa">>},
payment_token = #domain_BankCardTokenServiceRef{id = <<"applepay">>},
tokenization_method = dpan
}}
},
#domain_PaymentMethodRef{
id =
{bank_card, #domain_BankCardPaymentMethod{
payment_system_deprecated = mastercard
}}
id = {digital_wallet, #domain_PaymentServiceRef{id = <<"qiwi">>}}
},
#domain_PaymentMethodRef{
id =
{bank_card, #domain_BankCardPaymentMethod{
payment_system_deprecated = visa
}}
id = {mobile, #domain_MobileOperatorRef{id = <<"tele2">>}}
},
#domain_PaymentMethodRef{
id = {digital_wallet_deprecated, qiwi}
},
#domain_PaymentMethodRef{
id = {mobile_deprecated, tele2}
},
#domain_PaymentMethodRef{
id = {payment_terminal_deprecated, euroset}
id = {payment_terminal, #domain_PaymentServiceRef{id = <<"euroset">>}}
}
])}
}).
@ -1334,21 +1310,14 @@
}
}).
-define(TEST_PAYMENT_TOKEN, ?TEST_PAYMENT_TOKEN(visa)).
-define(TEST_PAYMENT_TOKEN(PaymentSystem),
?TEST_PAYMENT_TOKEN(PaymentSystem, ?STRING)
).
-define(TEST_PAYMENT_TOKEN, ?STRING).
-define(TEST_PAYMENT_TOKEN(PaymentSystem, Token),
capi_utils:map_to_base64url(?TEST_PAYMENT_TOOL(PaymentSystem, Token))
).
-define(TEST_PAYMENT_TOOL, ?TEST_PAYMENT_TOOL(visa)).
-define(TEST_PAYMENT_TOOL, ?TEST_PAYMENT_TOOL(<<"visa">>)).
-define(TEST_PAYMENT_TOOL(PaymentSystem), ?TEST_PAYMENT_TOOL(PaymentSystem, ?STRING)).
-define(TEST_PAYMENT_TOOL(PaymentSystem, Token), #{
<<"type">> => <<"bank_card">>,
<<"token">> => Token,
<<"payment_system">> => atom_to_binary(PaymentSystem, utf8),
<<"payment_system">> => PaymentSystem,
<<"bin">> => <<"411111">>,
<<"masked_pan">> => <<"1111">>,
<<"exp_date">> => <<"12/2012">>

View File

@ -202,8 +202,8 @@ create_payment_ok_test(Config) ->
BenderKey = <<"bender_key">>,
ExternalID = <<"merch_id">>,
ContactInfo = #{},
Jwe1 = get_encrypted_token(visa, ?EXP_DATE(2, 2020)),
Jwe2 = get_encrypted_token(visa, ?EXP_DATE(2, 2020)),
Jwe1 = get_encrypted_token(<<"visa">>, ?EXP_DATE(2, 2020)),
Jwe2 = get_encrypted_token(<<"visa">>, ?EXP_DATE(2, 2020)),
Req1 = payment_params(ExternalID, Jwe1, ContactInfo, undefined),
Req2 = payment_params(ExternalID, Jwe2, ContactInfo, false),
[
@ -231,8 +231,8 @@ create_payment_ok_test(Config) ->
create_payment_fail_test(Config) ->
BenderKey = <<"bender_key">>,
ExternalID = <<"merch_id">>,
Jwe1 = get_encrypted_token(visa, ?EXP_DATE(1, 2020)),
Jwe2 = get_encrypted_token(visa, ?EXP_DATE(2, 2020)),
Jwe1 = get_encrypted_token(<<"visa">>, ?EXP_DATE(1, 2020)),
Jwe2 = get_encrypted_token(<<"visa">>, ?EXP_DATE(2, 2020)),
Req1 = payment_params(ExternalID, Jwe1, #{}, undefined),
Req2 = payment_params(ExternalID, Jwe2, #{}, false),
[
@ -246,7 +246,7 @@ different_payment_tools_test(Config) ->
BenderKey = <<"bender_key">>,
ExternalID = <<"merch_id">>,
ContactInfo = #{},
Jwe1 = encrypt_payment_tool({bank_card, ?BANK_CARD(visa, ?EXP_DATE(2, 2020), <<"Mr. Surname">>)}),
Jwe1 = encrypt_payment_tool({bank_card, ?BANK_CARD(<<"visa">>, ?EXP_DATE(2, 2020), <<"Mr. Surname">>)}),
Jwe2 = encrypt_payment_tool({digital_wallet, ?DIGITAL_WALLET(<<"qiwi">>, <<"+79876543210">>, <<"token">>)}),
Req1 = payment_params(ExternalID, Jwe1, ContactInfo, undefined),
Req2 = payment_params(ExternalID, Jwe2, ContactInfo, false),
@ -272,8 +272,8 @@ second_request_without_idempotent_feature_test(Config) ->
BenderKey = <<"bender_key">>,
ExternalID = <<"merch_id">>,
ContactInfo = #{},
Jwe1 = encrypt_payment_tool({bank_card, ?BANK_CARD(visa, ?EXP_DATE(2, 2020), <<"Mr. Surname">>)}),
Jwe2 = encrypt_payment_tool({bank_card, ?BANK_CARD(visa, undefined, <<"Mr. Surname">>)}),
Jwe1 = encrypt_payment_tool({bank_card, ?BANK_CARD(<<"visa">>, ?EXP_DATE(2, 2020), <<"Mr. Surname">>)}),
Jwe2 = encrypt_payment_tool({bank_card, ?BANK_CARD(<<"visa">>, undefined, <<"Mr. Surname">>)}),
Req1 = payment_params(ExternalID, Jwe1, ContactInfo, undefined),
Req2 = payment_params(ExternalID, Jwe2, ContactInfo, undefined),
[
@ -286,8 +286,8 @@ second_request_without_idempotent_feature_test(Config) ->
second_request_with_idempotent_feature_test(Config) ->
BenderKey = <<"bender_key">>,
ExternalID = <<"merch_id">>,
Jwe1 = encrypt_payment_tool({bank_card, ?BANK_CARD(visa, ?EXP_DATE(2, 2020), undefined)}),
Jwe2 = encrypt_payment_tool({bank_card, ?BANK_CARD(visa, ?EXP_DATE(2, 2020), <<"Mr. Surname">>)}),
Jwe1 = encrypt_payment_tool({bank_card, ?BANK_CARD(<<"visa">>, ?EXP_DATE(2, 2020), undefined)}),
Jwe2 = encrypt_payment_tool({bank_card, ?BANK_CARD(<<"visa">>, ?EXP_DATE(2, 2020), <<"Mr. Surname">>)}),
Req1 = payment_params(ExternalID, Jwe1, #{}, undefined),
Req2 = payment_params(ExternalID, Jwe2, #{}, undefined),
[
@ -687,11 +687,14 @@ create_customer_fail_test(Config) ->
-spec create_customer_binding_ok_test(config()) -> _.
create_customer_binding_ok_test(Config) ->
BenderKey = <<"customer_binding_bender_key">>,
PaymentTool = {bank_card, ?BANK_CARD},
ValidUntil = capi_utils:deadline_from_timeout(10000),
PaymentToolToken = capi_crypto:encode_token(#{payment_tool => PaymentTool, valid_until => ValidUntil}),
Req1 = #{
<<"externalID">> => genlib:unique(),
<<"paymentResource">> => #{
<<"paymentSession">> => ?TEST_PAYMENT_SESSION,
<<"paymentToolToken">> => ?TEST_PAYMENT_TOKEN
<<"paymentToolToken">> => PaymentToolToken
}
},
Req2 = Req1#{<<"externalID">> => genlib:unique()},
@ -712,17 +715,23 @@ create_customer_binding_ok_test(Config) ->
create_customer_binding_fail_test(Config) ->
BenderKey = <<"customer_binding_bender_key">>,
ExternalID = genlib:unique(),
PaymentTool1 = {bank_card, ?BANK_CARD},
ValidUntil1 = capi_utils:deadline_from_timeout(10000),
PaymentToolToken1 = capi_crypto:encode_token(#{payment_tool => PaymentTool1, valid_until => ValidUntil1}),
Req1 = #{
<<"externalID">> => ExternalID,
<<"paymentResource">> => #{
<<"paymentSession">> => ?TEST_PAYMENT_SESSION,
<<"paymentToolToken">> => ?TEST_PAYMENT_TOKEN(visa, <<"TOKEN1">>)
<<"paymentToolToken">> => PaymentToolToken1
}
},
PaymentTool2 = {bank_card, ?BANK_CARD(<<"mastercard">>)},
ValidUntil2 = capi_utils:deadline_from_timeout(10000),
PaymentToolToken2 = capi_crypto:encode_token(#{payment_tool => PaymentTool2, valid_until => ValidUntil2}),
Req2 = Req1#{
<<"paymentResource">> => #{
<<"paymentSession">> => ?TEST_PAYMENT_SESSION,
<<"paymentToolToken">> => ?TEST_PAYMENT_TOKEN(mastercard, <<"TOKEN2">>)
<<"paymentToolToken">> => PaymentToolToken2
}
},
@ -855,8 +864,8 @@ get_encrypted_token(PS, ExpDate) ->
get_encrypted_token(PS, ExpDate, IsCvvEmpty) ->
encrypt_payment_tool(
{bank_card, #domain_BankCard{
token = ?TEST_PAYMENT_TOKEN(PS),
payment_system_deprecated = PS,
token = ?TEST_PAYMENT_TOKEN,
payment_system = #domain_PaymentSystemRef{id = PS},
bin = <<"411111">>,
last_digits = <<"1111">>,
exp_date = ExpDate,

View File

@ -297,7 +297,7 @@ create_payment_ok_test(Config) ->
?STRING,
Config
),
PaymentToolToken = get_encrypted_token(visa, ?EXP_DATE(2, 2020)),
PaymentToolToken = get_encrypted_token(<<"visa">>, ?EXP_DATE(2, 2020)),
Req = ?PAYMENT_PARAMS(ExternalID, PaymentToolToken),
{ok, #{
<<"id">> := BenderKey,
@ -383,7 +383,7 @@ create_payment_with_empty_cvv_ok_test(Config) ->
?STRING,
Config
),
PaymentToolToken = get_encrypted_token(visa, ?EXP_DATE(1, 2020), true),
PaymentToolToken = get_encrypted_token(<<"visa">>, ?EXP_DATE(1, 2020), true),
Req2 = #{
<<"flow">> => #{<<"type">> => <<"PaymentFlowInstant">>},
<<"payer">> => #{
@ -464,8 +464,7 @@ create_payment_with_googlepay_encrypt_ok_test(Config) ->
bank_card,
#domain_BankCard{
is_cvv_empty = undefined,
token_provider_deprecated = undefined,
payment_system_deprecated = mastercard
payment_system = #domain_PaymentSystemRef{id = <<"mastercard">>}
}
}
}
@ -486,7 +485,7 @@ create_payment_with_googlepay_encrypt_ok_test(Config) ->
?STRING,
Config
),
PaymentToolToken = get_encrypted_token(mastercard, ?EXP_DATE(1, 2020)),
PaymentToolToken = get_encrypted_token(<<"mastercard">>, ?EXP_DATE(1, 2020)),
Req2 = #{
<<"flow">> => #{<<"type">> => <<"PaymentFlowInstant">>},
<<"payer">> => #{
@ -666,7 +665,7 @@ create_first_recurrent_payment_ok_test(Config) ->
],
Config
),
PaymentToolToken = get_encrypted_token(visa, ?EXP_DATE(1, 2020)),
PaymentToolToken = get_encrypted_token(<<"visa">>, ?EXP_DATE(1, 2020)),
Req2 = #{
<<"flow">> => #{<<"type">> => <<"PaymentFlowInstant">>},
<<"makeRecurrent">> => true,
@ -784,8 +783,8 @@ get_encrypted_token(PS, ExpDate) ->
get_encrypted_token(PS, ExpDate, IsCvvEmpty) ->
PaymentTool =
{bank_card, #domain_BankCard{
token = ?TEST_PAYMENT_TOKEN(PS),
payment_system_deprecated = PS,
token = ?TEST_PAYMENT_TOKEN,
payment_system = #domain_PaymentSystemRef{id = PS},
bin = <<"411111">>,
last_digits = <<"1111">>,
exp_date = ExpDate,

View File

@ -48,7 +48,7 @@
{bouncer_proto, {git, "https://github.com/valitydev/bouncer-proto.git", {branch, master}}},
{bouncer_client, {git, "https://github.com/valitydev/bouncer-client-erlang.git", {branch, master}}},
{token_keeper_client, {git, "https://github.com/valitydev/token-keeper-client.git", {branch, master}}},
{party_client, {git, "https://github.com/valitydev/party_client_erlang.git", {branch, master}}},
{party_client, {git, "https://github.com/valitydev/party-client-erlang.git", {branch, master}}},
{payout_manager_proto, {git, "https://github.com/valitydev/payout-manager-proto.git", {branch, master}}},
{feat, {git, "https://github.com/valitydev/feat.git", {branch, master}}},
%% Libraries generated with swagger-codegen-erlang from valitydev/swag-payments

View File

@ -92,8 +92,8 @@
1},
{<<"parse_trans">>,{pkg,<<"parse_trans">>,<<"3.4.1">>},1},
{<<"party_client">>,
{git,"https://github.com/valitydev/party_client_erlang.git",
{ref,"8fc5595c4c61c0fe3d2dc29a61f48ba94e9bdef7"}},
{git,"https://github.com/valitydev/party-client-erlang.git",
{ref,"602d4dc87b54d2bf899ae36462853f7d7eb014ae"}},
0},
{<<"payout_manager_proto">>,
{git,"https://github.com/valitydev/payout-manager-proto.git",