diff --git a/apps/capi/src/capi_feature_schemas.erl b/apps/capi/src/capi_feature_schemas.erl index 8397b32..2996cc6 100644 --- a/apps/capi/src/capi_feature_schemas.erl +++ b/apps/capi/src/capi_feature_schemas.erl @@ -36,6 +36,9 @@ -define(price, 30). -define(tax, 31). -define(rate, 32). +-define(bank_account, 33). +-define(account, 34). +-define(bank_bik, 35). -export([payment/0]). -export([invoice/0]). @@ -102,7 +105,8 @@ invoice() -> ?currency => [<<"currency">>], ?product => [<<"product">>], ?due_date => [<<"dueDate">>], - ?cart => [<<"cart">>, {set, cart_line_schema()}] + ?cart => [<<"cart">>, {set, cart_line_schema()}], + ?bank_account => [<<"bankAccount">>, bank_account_schema()] }. -spec refund() -> schema(). @@ -128,6 +132,14 @@ cart_line_schema() -> ] }. +-spec bank_account_schema() -> schema(). +bank_account_schema() -> + #{ + ?discriminator => [<<"accountType">>], + ?account => [<<"account">>], + ?bank_bik => [<<"bankBik">>] + }. + -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). @@ -344,12 +356,18 @@ read_invoice_features_test() -> ?product => capi_idemp_features:hash(Prod2), ?price => capi_idemp_features:hash(Price2) }, + BankAccount = #{ + ?discriminator => capi_idemp_features:hash(<<"InvoiceRussianBankAccount">>), + ?account => capi_idemp_features:hash(<<"12345678901234567890">>), + ?bank_bik => capi_idemp_features:hash(<<"123456789">>) + }, Invoice = #{ ?amount => undefined, ?currency => capi_idemp_features:hash(Cur), ?shop_id => capi_idemp_features:hash(ShopID), ?product => undefined, ?due_date => capi_idemp_features:hash(DueDate), + ?bank_account => BankAccount, ?cart => [ [1, Product], [0, Product2] @@ -361,6 +379,11 @@ read_invoice_features_test() -> <<"shopID">> => ShopID, <<"currency">> => Cur, <<"description">> => <<"Wild birds.">>, + <<"bankAccount">> => #{ + <<"accountType">> => <<"InvoiceRussianBankAccount">>, + <<"account">> => <<"12345678901234567890">>, + <<"bankBik">> => <<"123456789">> + }, <<"cart">> => [ #{<<"product">> => Prod2, <<"quantity">> => 1, <<"price">> => Price2}, #{<<"product">> => Prod1, <<"quantity">> => 1, <<"price">> => Price1, <<"not feature">> => <<"hmm">>} diff --git a/apps/capi/src/capi_handler.erl b/apps/capi/src/capi_handler.erl index e08efcf..fb15df8 100644 --- a/apps/capi/src/capi_handler.erl +++ b/apps/capi/src/capi_handler.erl @@ -21,6 +21,7 @@ swagger_context := swag_server:request_context(), woody_context := woody_context:ctx() }. + -type throw(_T) :: no_return(). -type request_state() :: #{ diff --git a/apps/capi/src/capi_handler_decoder_invoicing.erl b/apps/capi/src/capi_handler_decoder_invoicing.erl index a761c3f..d92c14e 100644 --- a/apps/capi/src/capi_handler_decoder_invoicing.erl +++ b/apps/capi/src/capi_handler_decoder_invoicing.erl @@ -11,6 +11,7 @@ -export([decode_refund/2]). -export([decode_invoice/1]). -export([decode_invoice_cart/1]). +-export([decode_invoice_bank_account/1]). -export([decode_invoice_line_tax_mode/1]). -export([decode_payment_status/2]). -export([decode_payment_operation_failure/2]). @@ -372,8 +373,7 @@ decode_chargeback_reason_code(#domain_InvoicePaymentChargebackReason{code = Code -spec decode_invoice(capi_handler_encoder:encode_data()) -> capi_handler_decoder_utils:decode_data(). decode_invoice(Invoice) -> #domain_Cash{amount = Amount, currency = Currency} = Invoice#domain_Invoice.cost, - #domain_InvoiceDetails{product = Product, description = Description, cart = Cart} = - Invoice#domain_Invoice.details, + Details = Invoice#domain_Invoice.details, capi_handler_utils:merge_and_compact( #{ <<"id">> => Invoice#domain_Invoice.id, @@ -384,9 +384,10 @@ decode_invoice(Invoice) -> <<"amount">> => Amount, <<"currency">> => capi_handler_decoder_utils:decode_currency(Currency), <<"metadata">> => capi_handler_decoder_utils:decode_context(Invoice#domain_Invoice.context), - <<"product">> => Product, - <<"description">> => Description, - <<"cart">> => decode_invoice_cart(Cart), + <<"product">> => Details#domain_InvoiceDetails.product, + <<"description">> => Details#domain_InvoiceDetails.description, + <<"cart">> => decode_invoice_cart(Details#domain_InvoiceDetails.cart), + <<"bankAccount">> => decode_invoice_bank_account(Details#domain_InvoiceDetails.bank_account), <<"invoiceTemplateID">> => Invoice#domain_Invoice.template_id }, decode_invoice_status(Invoice#domain_Invoice.status) @@ -420,6 +421,17 @@ decode_invoice_line(InvoiceLine = #domain_InvoiceLine{quantity = Quantity, price <<"taxMode">> => decode_invoice_line_tax_mode(InvoiceLine#domain_InvoiceLine.metadata) }). +-spec decode_invoice_bank_account(dmsl_domain_thrift:'InvoiceBankAccount'() | undefined) -> + capi_handler_decoder_utils:decode_data() | undefined. +decode_invoice_bank_account({russian, Russian}) -> + genlib_map:compact(#{ + <<"accountType">> => <<"InvoiceRussianBankAccount">>, + <<"account">> => Russian#domain_InvoiceRussianBankAccount.account, + <<"bankBik">> => Russian#domain_InvoiceRussianBankAccount.bank_bik + }); +decode_invoice_bank_account(undefined) -> + undefined. + -spec decode_invoice_line_tax_mode(map()) -> capi_handler_decoder_utils:decode_data() | undefined. decode_invoice_line_tax_mode(#{<<"TaxMode">> := {str, TM}}) -> %% for more info about taxMode look here: diff --git a/apps/capi/src/capi_handler_encoder.erl b/apps/capi/src/capi_handler_encoder.erl index 7c499b3..472eb65 100644 --- a/apps/capi/src/capi_handler_encoder.erl +++ b/apps/capi/src/capi_handler_encoder.erl @@ -10,6 +10,7 @@ -export([encode_cash/2]). -export([encode_currency/1]). -export([encode_invoice_cart/1]). +-export([encode_invoice_bank_account/1]). -export([encode_stat_request/1]). -export([encode_invoice_context/1]). -export([encode_payment_context/1]). @@ -180,6 +181,18 @@ encode_invoice_line_tax_mode(#{<<"type">> := <<"InvoiceLineTaxVAT">>} = TaxMode) %% https://github.com/rbkmoney/starrys/blob/master/docs/settings.md genlib_map:get(<<"rate">>, TaxMode). +-spec encode_invoice_bank_account(request_data()) -> dmsl_domain_thrift:'InvoiceBankAccount'() | undefined. +encode_invoice_bank_account(Params) -> + do_encode_invoice_bank_account(genlib_map:get(<<"bankAccount">>, Params)). + +do_encode_invoice_bank_account(#{<<"accountType">> := <<"InvoiceRussianBankAccount">>} = Account) -> + {russian, #domain_InvoiceRussianBankAccount{ + account = maps:get(<<"account">>, Account), + bank_bik = maps:get(<<"bankBik">>, Account) + }}; +do_encode_invoice_bank_account(undefined) -> + undefined. + -define(DEFAULT_INVOICE_META, #{}). -spec encode_invoice_context(request_data()) -> encode_data(). diff --git a/apps/capi/src/capi_handler_geo.erl b/apps/capi/src/capi_handler_geo.erl index e6811d5..22f2b10 100644 --- a/apps/capi/src/capi_handler_geo.erl +++ b/apps/capi/src/capi_handler_geo.erl @@ -13,7 +13,6 @@ Req :: capi_handler:request_data(), Context :: capi_handler:processing_context() ) -> {ok, capi_handler:request_state()} | {error, noimpl}. - prepare('GetLocationsNames' = OperationID, Req, Context) -> Authorize = fun() -> Prototypes = [{operation, #{id => OperationID}}], diff --git a/apps/capi/src/capi_handler_invoices.erl b/apps/capi/src/capi_handler_invoices.erl index 2b72fa2..42d0e86 100644 --- a/apps/capi/src/capi_handler_invoices.erl +++ b/apps/capi/src/capi_handler_invoices.erl @@ -284,7 +284,8 @@ encode_invoice_details(Params) -> #domain_InvoiceDetails{ product = genlib_map:get(<<"product">>, Params), description = genlib_map:get(<<"description">>, Params), - cart = capi_handler_encoder:encode_invoice_cart(Params) + cart = capi_handler_encoder:encode_invoice_cart(Params), + bank_account = capi_handler_encoder:encode_invoice_bank_account(Params) }. %% diff --git a/apps/capi/src/capi_handler_webhooks.erl b/apps/capi/src/capi_handler_webhooks.erl index 35f564a..6936c30 100644 --- a/apps/capi/src/capi_handler_webhooks.erl +++ b/apps/capi/src/capi_handler_webhooks.erl @@ -6,6 +6,7 @@ -behaviour(capi_handler). -export([prepare/3]). + -import(capi_handler_utils, [general_error/2, logic_error/2]). -spec prepare( diff --git a/apps/capi/test/capi_dummy_data.hrl b/apps/capi/test/capi_dummy_data.hrl index 4569a44..966135b 100644 --- a/apps/capi/test/capi_dummy_data.hrl +++ b/apps/capi/test/capi_dummy_data.hrl @@ -16,7 +16,8 @@ -define(DETAILS, #domain_InvoiceDetails{ product = ?STRING, - description = ?STRING + description = ?STRING, + bank_account = ?INVOICE_BANK_ACCOUNT }). -define(CASH, #domain_Cash{ @@ -83,6 +84,13 @@ } ]). +-define(INVOICE_BANK_ACCOUNT, + {russian, #domain_InvoiceRussianBankAccount{ + account = <<"12345678901234567890">>, + bank_bik = <<"123456789">> + }} +). + -define(PAYPROC_INVOICE(Payments), #payproc_Invoice{ invoice = ?INVOICE, payments = Payments @@ -1270,7 +1278,12 @@ <<"metadata">> => #{<<"invoice_dummy_metadata">> => <<"test_value">>}, <<"dueDate">> => ?TIMESTAMP, <<"product">> => <<"test_product">>, - <<"description">> => <<"test_invoice_description">> + <<"description">> => <<"test_invoice_description">>, + <<"bankAccount">> => #{ + <<"accountType">> => <<"InvoiceRussianBankAccount">>, + <<"account">> => <<"12345678901234567890">>, + <<"bankBik">> => <<"123456789">> + } }). -define(CUSTOMER_PARAMS, #{ diff --git a/apps/capi/test/capi_idempotency_tests_SUITE.erl b/apps/capi/test/capi_idempotency_tests_SUITE.erl index 6300ad1..9fb6f70 100644 --- a/apps/capi/test/capi_idempotency_tests_SUITE.erl +++ b/apps/capi/test/capi_idempotency_tests_SUITE.erl @@ -28,6 +28,7 @@ -export([create_invoice_fail_test/1]). -export([create_invoice_idemp_cart_ok_test/1]). -export([create_invoice_idemp_cart_fail_test/1]). +-export([create_invoice_idemp_bank_account_fail_test/1]). -export([create_refund_idemp_ok_test/1]). -export([create_refund_idemp_fail_test/1]). @@ -66,7 +67,8 @@ groups() -> create_invoice_legacy_fail_test, create_invoice_fail_test, create_invoice_idemp_cart_fail_test, - create_invoice_idemp_cart_ok_test + create_invoice_idemp_cart_ok_test, + create_invoice_idemp_bank_account_fail_test ]}, {refund_creation, [], [ create_refund_idemp_ok_test, @@ -395,6 +397,25 @@ create_invoice_idemp_cart_fail_test(Config) -> ?assertEqual(response_error(409, ExternalID, BenderKey), Response2), ?assertEqual(response_error(409, ExternalID, BenderKey), Response3). +-spec create_invoice_idemp_bank_account_fail_test(config()) -> _. +create_invoice_idemp_bank_account_fail_test(Config) -> + BenderKey = <<"bender_key">>, + ExternalID = <<"merch_id">>, + Req = invoice_params(ExternalID), + Account1 = #{ + <<"accountType">> => <<"InvoiceRussianBankAccount">>, + <<"account">> => <<"12345678901234567890">>, + <<"bankBik">> => <<"123456789">> + }, + Account2 = Account1#{<<"bankBik">> => <<"987654321">>}, + Req1 = Req#{<<"bankAccount">> => Account1}, + Req2 = Req#{<<"bankAccount">> => Account2}, + [ + {{ok, _}, _}, + {Response, _} + ] = create_invoices(BenderKey, [Req1, Req2], Config), + ?assertEqual(response_error(409, ExternalID, BenderKey), Response). + -spec create_refund_idemp_ok_test(config()) -> _. create_refund_idemp_ok_test(Config) -> BenderKey = <<"bender_key">>, diff --git a/rebar.lock b/rebar.lock index 7a8e26c..1c7e4db 100644 --- a/rebar.lock +++ b/rebar.lock @@ -39,7 +39,7 @@ {<<"cowlib">>,{pkg,<<"cowlib">>,<<"2.8.0">>},1}, {<<"damsel">>, {git,"https://github.com/rbkmoney/damsel.git", - {ref,"7a9d7a67d0194ecdb1cc0f9b390015352ac42271"}}, + {ref,"11fe2e86427ed618d2a86ae2577d4c0f8cf7221e"}}, 0}, {<<"dmt_client">>, {git,"https://github.com/rbkmoney/dmt_client.git", diff --git a/schemes/swag b/schemes/swag index c3a0f34..1de808c 160000 --- a/schemes/swag +++ b/schemes/swag @@ -1 +1 @@ -Subproject commit c3a0f346f3c7a46d824562f1037f5dfbde96f12a +Subproject commit 1de808c1d698f63763db049a2399d56f7d4648bf