diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..17c5a18 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +/_build/ +/.git/ +/.github/ +/.vscode/ +/.idea/ +erl_crash.dump +rebar3.crashdump diff --git a/.env b/.env new file mode 100644 index 0000000..7428715 --- /dev/null +++ b/.env @@ -0,0 +1,7 @@ +# NOTE +# You SHOULD specify point releases here so that build time and run time Erlang/OTPs +# are the same. See: https://github.com/erlware/relx/pull/902 +SERVICE_NAME=capi +OTP_VERSION=24.2.0 +REBAR_VERSION=3.18 +THRIFT_VERSION=0.14.2.2 diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml new file mode 100644 index 0000000..d95f0c7 --- /dev/null +++ b/.github/workflows/build-image.yml @@ -0,0 +1,53 @@ +name: Build Docker image + +on: + push: + branches: + - 'master' + - 'epic/**' + pull_request: + branches: [ '**' ] + +env: + REGISTRY: ghcr.io + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup Buildx + uses: docker/setup-buildx-action@v1 + + # https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#setting-an-environment-variable + - name: Update environment variables + run: grep -v '^#' .env >> $GITHUB_ENV + + - name: Log in to the Container registry + uses: docker/login-action@v1.12.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Construct tags / labels for an image + id: meta + uses: docker/metadata-action@v3.6.2 + with: + images: | + ${{ env.REGISTRY }}/${{ github.repository }} + tags: | + type=sha + + - name: Build and push Docker image + uses: docker/build-push-action@v2.9.0 + with: + push: ${{ github.event_name == 'push' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + build-args: | + SERVICE_NAME=${{ env.SERVICE_NAME }} + OTP_VERSION=${{ env.OTP_VERSION }} + THRIFT_VERSION=${{ env.THRIFT_VERSION }} diff --git a/.github/workflows/erlang-checks.yml b/.github/workflows/erlang-checks.yml new file mode 100644 index 0000000..ac24935 --- /dev/null +++ b/.github/workflows/erlang-checks.yml @@ -0,0 +1,38 @@ +name: Erlang CI Checks + +on: + push: + branches: + - 'master' + - 'epic/**' + pull_request: + branches: [ '**' ] + +jobs: + setup: + name: Load .env + runs-on: ubuntu-latest + outputs: + otp-version: ${{ steps.otp-version.outputs.version }} + rebar-version: ${{ steps.rebar-version.outputs.version }} + thrift-version: ${{ steps.thrift-version.outputs.version }} + steps: + - name: Checkout repository + uses: actions/checkout@v2 + - run: grep -v '^#' .env >> $GITHUB_ENV + - id: otp-version + run: echo "::set-output name=version::$OTP_VERSION" + - id: rebar-version + run: echo "::set-output name=version::$REBAR_VERSION" + - id: thrift-version + run: echo "::set-output name=version::$THRIFT_VERSION" + + run: + name: Run checks + needs: setup + uses: valitydev/erlang-workflows/.github/workflows/erlang-parallel-build.yml@v1.0.1 + with: + otp-version: ${{ needs.setup.outputs.otp-version }} + rebar-version: ${{ needs.setup.outputs.rebar-version }} + use-thrift: true + thrift-version: ${{ needs.setup.outputs.thrift-version }} diff --git a/.gitignore b/.gitignore index d1f1a64..a8d7fec 100644 --- a/.gitignore +++ b/.gitignore @@ -12,13 +12,10 @@ erl_crash.dump /_checkouts/ # generated -apps/swag_server/* -apps/swag_client/* *.beam +.image.dev # containerization \#* .\#* -Dockerfile -docker-compose.yml tags diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 472dd58..0000000 --- a/.gitmodules +++ /dev/null @@ -1,8 +0,0 @@ -[submodule "schemes/swag"] - path = schemes/swag - branch = release/v2 - url = git@github.com:rbkmoney/swag.git -[submodule "build_utils"] - path = build_utils - url = git@github.com:rbkmoney/build_utils.git - branch = master diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..5e640fa --- /dev/null +++ b/Dockerfile @@ -0,0 +1,40 @@ +ARG OTP_VERSION + +# Build the release +FROM docker.io/library/erlang:${OTP_VERSION} AS builder + +ARG BUILDARCH + +# 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" \ + | tar -xvz -C /usr/local/bin/ + +# Copy sources +RUN mkdir /build +COPY . /build/ + +# Build the release +WORKDIR /build +RUN rebar3 compile +RUN rebar3 as prod release + +# Make a runner image +FROM docker.io/library/erlang:${OTP_VERSION}-slim + +ARG SERVICE_NAME + +# Set env +ENV CHARSET=UTF-8 +ENV LANG=C.UTF-8 + +# Set runtime +WORKDIR /opt/${SERVICE_NAME} + +COPY --from=builder /build/_build/prod/rel/${SERVICE_NAME} /opt/${SERVICE_NAME} + +ENTRYPOINT [] +CMD /opt/${SERVICE_NAME}/bin/${SERVICE_NAME} foreground + +EXPOSE 8022 diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 0000000..54f1170 --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,18 @@ +ARG OTP_VERSION + +FROM docker.io/library/erlang:${OTP_VERSION} + +ARG BUILDARCH + +# 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" \ + | tar -xvz -C /usr/local/bin/ + +# Set env +ENV CHARSET=UTF-8 +ENV LANG=C.UTF-8 + +# Set runtime +CMD /bin/bash diff --git a/Dockerfile.sh b/Dockerfile.sh deleted file mode 100755 index 9ce7745..0000000 --- a/Dockerfile.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -cat < -COPY ./_build/prod/rel/capi /opt/capi -WORKDIR /opt/capi -CMD /opt/capi/bin/capi foreground -EXPOSE 8080 -# A bit of magic below to get a proper branch name -# even when the HEAD is detached (Hey Jenkins! -# BRANCH_NAME is available in Jenkins env). -LABEL com.rbkmoney.$SERVICE_NAME.parent=$BASE_IMAGE_NAME \ - com.rbkmoney.$SERVICE_NAME.parent_tag=$BASE_IMAGE_TAG \ - com.rbkmoney.$SERVICE_NAME.build_img=build \ - com.rbkmoney.$SERVICE_NAME.build_img_tag=$BUILD_IMAGE_TAG \ - com.rbkmoney.$SERVICE_NAME.commit_id=$(git rev-parse HEAD) \ - com.rbkmoney.$SERVICE_NAME.commit_number=$(git rev-list --count HEAD) \ - com.rbkmoney.$SERVICE_NAME.branch=$( \ - if [ "HEAD" != $(git rev-parse --abbrev-ref HEAD) ]; then \ - echo $(git rev-parse --abbrev-ref HEAD); \ - elif [ -n "$BRANCH_NAME" ]; then \ - echo $BRANCH_NAME; \ - else \ - echo $(git name-rev --name-only HEAD); \ - fi) -EOF diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index 9ff5eee..0000000 --- a/Jenkinsfile +++ /dev/null @@ -1,22 +0,0 @@ -#!groovy -// -*- mode: groovy -*- - -def finalHook = { - runStage('store CT logs') { - archive '_build/test/logs/' - } -} - -build('capi', 'docker-host', finalHook) { - checkoutRepo() - loadBuildUtils() - - def pipeErlangService - runStage('load pipeline') { - env.JENKINS_LIB = "build_utils/jenkins_lib" - env.SH_TOOLS = "build_utils/sh" - pipeErlangService = load("${env.JENKINS_LIB}/pipeErlangService.groovy") - } - - pipeErlangService.runPipe(false, false, 'test') -} diff --git a/Makefile b/Makefile index 6e909ba..238cf3f 100644 --- a/Makefile +++ b/Makefile @@ -1,138 +1,92 @@ -REBAR := $(shell which rebar3 2>/dev/null || which ./rebar3) -SUBMODULES = schemes/swag build_utils -SUBTARGETS = $(patsubst %,%/.git,$(SUBMODULES)) +# HINT +# Use this file to override variables here. +# For example, to run with podman put `DOCKER=podman` there. +-include Makefile.env -COMPOSE_HTTP_TIMEOUT := 300 -export COMPOSE_HTTP_TIMEOUT +# NOTE +# Variables specified in `.env` file are used to pick and setup specific +# component versions, both when building a development image and when running +# CI workflows on GH Actions. This ensures that tasks run with `wc-` prefix +# (like `wc-dialyze`) are reproducible between local machine and CI runners. +DOTENV := $(shell grep -v '^\#' .env) -UTILS_PATH := build_utils -TEMPLATES_PATH := . +# Development images +DEV_IMAGE_TAG = capi-dev +DEV_IMAGE_ID = $(file < .image.dev) -# Name of the service -SERVICE_NAME := capi-v2 -# Service image default tag -SERVICE_IMAGE_TAG ?= $(shell git rev-parse HEAD) -# The tag for service image to be pushed with -SERVICE_IMAGE_PUSH_TAG ?= $(SERVICE_IMAGE_TAG) - -# Base image for the service -BASE_IMAGE_NAME := service-erlang -BASE_IMAGE_TAG := fe43cb7176f34abcde7b101755600ecd8be635e3 - -# Build image tag to be used -BUILD_IMAGE_NAME := build-erlang -BUILD_IMAGE_TAG := 117a2e28e18d41d4c3eb76f5d00af117872af5ac - -CALL_ANYWHERE := \ - submodules \ - all compile xref lint dialyze update_plt test cover \ - start devrel release clean distclean \ - generate regenerate swag_server.regenerate swag_client.regenerate \ - check_format format - -CALL_W_CONTAINER := $(CALL_ANYWHERE) - -.PHONY: $(CALL_W_CONTAINER) all +DOCKER ?= docker +REBAR ?= rebar3 all: compile --include $(UTILS_PATH)/make_lib/utils_container.mk --include $(UTILS_PATH)/make_lib/utils_image.mk +.PHONY: dev-image clean-dev-image wc-shell test -$(SUBTARGETS): %/.git: % - git submodule update --init $< - touch $@ +dev-image: .image.dev -submodules: $(SUBTARGETS) +.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 > $@ -generate: swag_server.generate swag_client.generate +clean-dev-image: +ifneq ($(DEV_IMAGE_ID),) + $(DOCKER) image rm -f $(DEV_IMAGE_TAG) + rm .image.dev +endif -regenerate: swag_server.regenerate swag_client.regenerate +DOCKER_WC_OPTIONS := -v $(PWD):$(PWD) --workdir $(PWD) +DOCKER_WC_EXTRA_OPTIONS ?= --rm +DOCKER_RUN = $(DOCKER) run -t $(DOCKER_WC_OPTIONS) $(DOCKER_WC_EXTRA_OPTIONS) -compile: submodules generate +# Utility tasks + +wc-shell: dev-image + $(DOCKER_RUN) --interactive --tty $(DEV_IMAGE_TAG) + +wc-%: dev-image + $(DOCKER_RUN) $(DEV_IMAGE_TAG) make $* + +# Rebar tasks + +rebar-shell: + $(REBAR) shell + +compile: $(REBAR) compile xref: $(REBAR) xref -lint: generate - elvis rock -V +lint: + $(REBAR) lint -check_format: +check-format: $(REBAR) fmt -c -format: - $(REBAR) fmt -w - dialyze: $(REBAR) as test dialyzer -update_plt: - $(REBAR) dialyzer -u true -s false - -start: submodules - $(REBAR) run - -release: submodules generate +release: $(REBAR) as prod release -clean: - $(REBAR) cover -r - $(REBAR) clean +eunit: + $(REBAR) eunit --cover -distclean: swag_server.distclean swag_client.distclean - rm -rf _build +common-test: + $(REBAR) ct --cover cover: + $(REBAR) covertool generate + +format: + $(REBAR) fmt -w + +clean: + $(REBAR) clean + +distclean: clean-build-image + rm -rf _build + +test: eunit common-test + +cover-report: $(REBAR) cover - -# CALL_W_CONTAINER -test: submodules generate - $(REBAR) do eunit, ct - -# Swagger stuff -SWAGGER_CODEGEN = $(call which, swagger-codegen) -SWAGGER_SCHEME_PATH = schemes/swag -SWAGGER_SCHEME = $(SWAGGER_SCHEME_PATH)/swagger.yaml - -$(SWAGGER_SCHEME): $(SWAGGER_SCHEME_PATH)/.git - -# Swagger server -SWAG_SERVER_PREFIX = swag_server -SWAG_SERVER_APP_PATH = apps/$(SWAG_SERVER_PREFIX) -SWAG_SERVER_APP_TARGET = $(SWAG_SERVER_APP_PATH)/rebar.config - -swag_server.generate: $(SWAG_SERVER_APP_TARGET) - -swag_server.distclean: - rm -rf $(SWAG_SERVER_APP_PATH) - -swag_server.regenerate: swag_server.distclean swag_server.generate - -$(SWAG_SERVER_APP_TARGET): $(SWAGGER_SCHEME) - $(SWAGGER_CODEGEN) generate \ - -i $(SWAGGER_SCHEME) \ - -l erlang-server \ - -o $(SWAG_SERVER_APP_PATH) \ - --additional-properties \ - packageName=$(SWAG_SERVER_PREFIX) - -# Swagger client -SWAG_CLIENT_PREFIX = swag_client -SWAG_CLIENT_APP_PATH = apps/$(SWAG_CLIENT_PREFIX) -SWAG_CLIENT_APP_TARGET = $(SWAG_CLIENT_APP_PATH)/rebar.config - -swag_client.generate: $(SWAG_CLIENT_APP_TARGET) - -swag_client.distclean: - rm -rf $(SWAG_CLIENT_APP_PATH) - -swag_client.regenerate: swag_client.distclean swag_client.generate - -$(SWAG_CLIENT_APP_TARGET): $(SWAGGER_SCHEME) - $(SWAGGER_CODEGEN) generate \ - -i $(SWAGGER_SCHEME) \ - -l erlang-client \ - -o $(SWAG_CLIENT_APP_PATH) \ - --additional-properties \ - packageName=$(SWAG_CLIENT_PREFIX) diff --git a/apps/capi/src/capi.app.src b/apps/capi/src/capi.app.src index 9526310..5b390a0 100644 --- a/apps/capi/src/capi.app.src +++ b/apps/capi/src/capi.app.src @@ -1,8 +1,8 @@ -{application, capi , [ - {description, "A service that does something"}, +{application, capi, [ + {description, "Implementation of swag-payments openapi specification"}, {vsn, "0.1.0"}, {registered, []}, - {mod, {capi , []}}, + {mod, {capi, []}}, {applications, [ kernel, stdlib, @@ -26,8 +26,6 @@ woody_user_identity, payproc_errors, erl_health, - prometheus, - prometheus_cowboy, bouncer_client, token_keeper_client, party_client, diff --git a/apps/capi/src/capi_auth.erl b/apps/capi/src/capi_auth.erl index ee8bf73..a990671 100644 --- a/apps/capi/src/capi_auth.erl +++ b/apps/capi/src/capi_auth.erl @@ -37,8 +37,8 @@ %% Internal types --define(authorized(Ctx), {authorized, Ctx}). --define(unauthorized(Ctx), {unauthorized, Ctx}). +-define(AUTHORIZED(Ctx), {authorized, Ctx}). +-define(UNAUTHORIZED(Ctx), {unauthorized, Ctx}). %% %% API functions @@ -54,19 +54,19 @@ get_subject_id(AuthContext) -> end. -spec get_party_id(auth_context()) -> binary() | undefined. -get_party_id(?authorized(AuthData)) -> +get_party_id(?AUTHORIZED(AuthData)) -> get_metadata(get_metadata_mapped_key(party_id), token_keeper_auth_data:get_metadata(AuthData)). -spec get_user_id(auth_context()) -> binary() | undefined. -get_user_id(?authorized(AuthData)) -> +get_user_id(?AUTHORIZED(AuthData)) -> get_metadata(get_metadata_mapped_key(user_id), token_keeper_auth_data:get_metadata(AuthData)). -spec get_user_email(auth_context()) -> binary() | undefined. -get_user_email(?authorized(AuthData)) -> +get_user_email(?AUTHORIZED(AuthData)) -> get_metadata(get_metadata_mapped_key(user_email), token_keeper_auth_data:get_metadata(AuthData)). -spec get_consumer(auth_context()) -> consumer(). -get_consumer(?authorized(AuthData)) -> +get_consumer(?AUTHORIZED(AuthData)) -> case get_metadata(get_metadata_mapped_key(token_consumer), token_keeper_auth_data:get_metadata(AuthData)) of <<"merchant">> -> merchant; <<"client">> -> client; @@ -80,14 +80,14 @@ get_consumer(?authorized(AuthData)) -> preauthorize_api_key(ApiKey) -> case parse_api_key(ApiKey) of {ok, Token} -> - {ok, ?unauthorized(Token)}; + {ok, ?UNAUTHORIZED(Token)}; {error, Error} -> {error, Error} end. -spec authorize_api_key(preauth_context(), token_keeper_client:source_context(), woody_context:ctx()) -> {ok, auth_context()} | {error, _Reason}. -authorize_api_key(?unauthorized({TokenType, Token}), TokenContext, WoodyContext) -> +authorize_api_key(?UNAUTHORIZED({TokenType, Token}), TokenContext, WoodyContext) -> authorize_token_by_type(TokenType, Token, TokenContext, WoodyContext). -spec authorize_operation( @@ -197,13 +197,13 @@ create_metadata(TokenSpec) -> extract_auth_context(#{swagger_context := #{auth_context := AuthContext}}) -> AuthContext. -get_token_keeper_fragment(?authorized(AuthData)) -> +get_token_keeper_fragment(?AUTHORIZED(AuthData)) -> token_keeper_auth_data:get_context_fragment(AuthData). authorize_token_by_type(bearer, Token, TokenContext, WoodyContext) -> case token_keeper_client:get_by_token(Token, TokenContext, WoodyContext) of {ok, AuthData} -> - {ok, ?authorized(AuthData)}; + {ok, ?AUTHORIZED(AuthData)}; {error, TokenKeeperError} -> _ = logger:warning("Token keeper authorization failed: ~p", [TokenKeeperError]), {error, {auth_failed, TokenKeeperError}} diff --git a/apps/capi/src/capi_handler.erl b/apps/capi/src/capi_handler.erl index 75a5411..744ac10 100644 --- a/apps/capi/src/capi_handler.erl +++ b/apps/capi/src/capi_handler.erl @@ -104,7 +104,6 @@ get_handlers() -> capi_handler_contracts, capi_handler_countries, capi_handler_customers, - capi_handler_geo, capi_handler_invoice_templates, capi_handler_invoices, capi_handler_parties, @@ -162,7 +161,7 @@ handle_function_(OperationID, Req, SwagContext0, HandlerOpts) -> throw:{handler_respond, HandlerResponse} -> {ok, HandlerResponse}; throw:{bad_deadline, _Deadline} -> - {ok, logic_error(invalidDeadline, <<"Invalid data in X-Request-Deadline header">>)}; + {ok, logic_error('invalidDeadline', <<"Invalid data in X-Request-Deadline header">>)}; throw:{handler_function_clause, _OperationID} -> _ = logger:error("Operation ~p failed due to missing handler", [OperationID]), {error, {501, #{}, undefined}}; @@ -300,13 +299,13 @@ set_context_meta(Context) -> -spec set_request_meta(operation_id(), request_data()) -> ok. set_request_meta(OperationID, Req) -> InterestParams = [ - invoiceID, - invoiceTemplateID, - contractID, - webhookID, - reportID, - shopID, - customerID + 'invoiceID', + 'invoiceTemplateID', + 'contractID', + 'webhookID', + 'reportID', + 'shopID', + 'customerID' ], Meta = #{ operation_id => OperationID, diff --git a/apps/capi/src/capi_handler_analytics.erl b/apps/capi/src/capi_handler_analytics.erl index 31654a8..3ead88c 100644 --- a/apps/capi/src/capi_handler_analytics.erl +++ b/apps/capi/src/capi_handler_analytics.erl @@ -44,7 +44,7 @@ process_request('GetPaymentGeoStats', Context, Req) -> process_request('GetPaymentRateStats', Context, Req) -> process_merchant_stat(customers_rate_stat, Req, Context); process_request('GetPaymentMethodStats', Context, Req) -> - bankCard = maps:get(paymentMethod, Req), + 'bankCard' = maps:get('paymentMethod', Req), StatType = payments_pmt_cards_stat, process_merchant_stat(StatType, Req, Context). @@ -90,9 +90,9 @@ process_merchant_stat_result(StatType, Result) -> {ok, {200, #{}, Resp}}; {exception, #'InvalidRequest'{errors = Errors}} -> FormattedErrors = capi_handler_utils:format_request_errors(Errors), - {ok, logic_error(invalidRequest, FormattedErrors)}; + {ok, logic_error('invalidRequest', FormattedErrors)}; {exception, #merchstat_BadToken{}} -> - {ok, logic_error(invalidRequest, <<"Invalid token">>)} + {ok, logic_error('invalidRequest', <<"Invalid token">>)} end. decode_stat_info(payments_conversion_stat, Response) -> diff --git a/apps/capi/src/capi_handler_categories.erl b/apps/capi/src/capi_handler_categories.erl index 9e45a91..bb201ce 100644 --- a/apps/capi/src/capi_handler_categories.erl +++ b/apps/capi/src/capi_handler_categories.erl @@ -29,7 +29,7 @@ prepare(OperationID = 'GetCategoryByRef', Req, Context) -> {ok, capi_auth:authorize_operation(Prototypes, Context)} end, Process = fun() -> - case get_category_by_id(genlib:to_int(maps:get(categoryID, Req)), Context) of + case get_category_by_id(genlib:to_int(maps:get('categoryID', Req)), Context) of {ok, Category} -> {ok, {200, #{}, decode_category(Category)}}; {error, not_found} -> diff --git a/apps/capi/src/capi_handler_claims.erl b/apps/capi/src/capi_handler_claims.erl index 6257d53..553e1d1 100644 --- a/apps/capi/src/capi_handler_claims.erl +++ b/apps/capi/src/capi_handler_claims.erl @@ -38,13 +38,9 @@ prepare(OperationID = 'GetClaimByID', Req, Context) -> Process = fun() -> case capi_party:get_claim(PartyID, genlib:to_int(ClaimID), Context) of {ok, Claim} -> - case is_wallet_claim(Claim) of - true -> - %% filter this out - {ok, general_error(404, <<"Claim not found">>)}; - false -> - {ok, {200, #{}, decode_claim(Claim)}} - end; + %% filter this out + _ = is_wallet_claim(Claim) andalso capi_handler:respond(general_error(404, <<"Claim not found">>)), + {ok, {200, #{}, decode_claim(Claim)}}; {error, #payproc_ClaimNotFound{}} -> {ok, general_error(404, <<"Claim not found">>)} end @@ -64,30 +60,27 @@ prepare(OperationID = 'CreateClaim', Req, Context) -> case capi_party:create_claim(PartyID, Changeset, Context) of {ok, Claim} -> {ok, {201, #{}, decode_claim(Claim)}}; - {error, Exception} -> - case Exception of - #payproc_InvalidPartyStatus{} -> - {ok, logic_error(invalidPartyStatus, <<"Invalid party status">>)}; - #payproc_ChangesetConflict{} -> - {ok, logic_error(changesetConflict, <<"Changeset conflict">>)}; - #payproc_InvalidChangeset{} -> - {ok, logic_error(invalidChangeset, <<"Invalid changeset">>)}; - #'InvalidRequest'{errors = Errors} -> - FormattedErrors = capi_handler_utils:format_request_errors(Errors), - {ok, logic_error(invalidRequest, FormattedErrors)} - end + {error, #payproc_InvalidPartyStatus{}} -> + {ok, logic_error('invalidPartyStatus', <<"Invalid party status">>)}; + {error, #payproc_ChangesetConflict{}} -> + {ok, logic_error('changesetConflict', <<"Changeset conflict">>)}; + {error, #payproc_InvalidChangeset{}} -> + {ok, logic_error('invalidChangeset', <<"Invalid changeset">>)}; + {error, #'InvalidRequest'{errors = Errors}} -> + FormattedErrors = capi_handler_utils:format_request_errors(Errors), + {ok, logic_error('invalidRequest', FormattedErrors)} end end, {ok, #{authorize => Authorize, process => Process}} catch throw:{encode_contract_modification, adjustment_creation_not_supported} -> ErrorResp = logic_error( - invalidChangeset, + 'invalidChangeset', <<"Contract adjustment creation not supported">> ), capi_handler:respond(ErrorResp); throw:{encode_residence, invalid_residence} -> - capi_handler:respond(logic_error(invalidRequest, <<"Invalid residence">>)) + capi_handler:respond(logic_error('invalidRequest', <<"Invalid residence">>)) end; % TODO disabled temporary, exception handling must be fixed befor enabling % prepare(OperationID = 'UpdateClaimByID', Req, Context) -> @@ -130,17 +123,14 @@ prepare(OperationID = 'RevokeClaimByID', Req, Context) -> case Result of ok -> {ok, {204, #{}, undefined}}; - {error, Exception} -> - case Exception of - #payproc_InvalidPartyStatus{} -> - {ok, logic_error(invalidPartyStatus, <<"Invalid party status">>)}; - #payproc_ClaimNotFound{} -> - {ok, general_error(404, <<"Claim not found">>)}; - #payproc_InvalidClaimStatus{} -> - {ok, logic_error(invalidClaimStatus, <<"Invalid claim status">>)}; - #payproc_InvalidClaimRevision{} -> - {ok, logic_error(invalidClaimRevision, <<"Invalid claim revision">>)} - end + {error, #payproc_InvalidPartyStatus{}} -> + {ok, logic_error('invalidPartyStatus', <<"Invalid party status">>)}; + {error, #payproc_ClaimNotFound{}} -> + {ok, general_error(404, <<"Claim not found">>)}; + {error, #payproc_InvalidClaimStatus{}} -> + {ok, logic_error('invalidClaimStatus', <<"Invalid claim status">>)}; + {error, #payproc_InvalidClaimRevision{}} -> + {ok, logic_error('invalidClaimRevision', <<"Invalid claim revision">>)} end end, {ok, #{authorize => Authorize, process => Process}}; diff --git a/apps/capi/src/capi_handler_contracts.erl b/apps/capi/src/capi_handler_contracts.erl index aff2c11..d4812c9 100644 --- a/apps/capi/src/capi_handler_contracts.erl +++ b/apps/capi/src/capi_handler_contracts.erl @@ -56,13 +56,9 @@ prepare(OperationID = 'GetContractAdjustments', Req, Context) -> {ok, capi_auth:authorize_operation(Prototypes, Context)} end, Process = fun() -> - case capi_party:get_contract(PartyID, ContractID, Context) of - {ok, #domain_Contract{adjustments = Adjustments}} -> - Resp = [decode_contract_adjustment(A) || A <- Adjustments], - {ok, {200, #{}, Resp}}; - {error, #payproc_ContractNotFound{}} -> - {ok, general_error(404, <<"Contract not found">>)} - end + Contract = get_contract_or_fail(PartyID, ContractID, Context), + Resp = [decode_contract_adjustment(A) || A <- Contract#domain_Contract.adjustments], + {ok, {200, #{}, Resp}} end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetContractAdjustmentByID', Req, Context) -> @@ -75,17 +71,14 @@ prepare(OperationID = 'GetContractAdjustmentByID', Req, Context) -> {ok, capi_auth:authorize_operation(Prototypes, Context)} end, Process = fun() -> - case capi_party:get_contract(PartyID, ContractID, Context) of - {ok, #domain_Contract{adjustments = Adjustments}} -> - AdjustmentID = maps:get('adjustmentID', Req), - case lists:keyfind(AdjustmentID, #domain_ContractAdjustment.id, Adjustments) of - #domain_ContractAdjustment{} = A -> - {ok, {200, #{}, decode_contract_adjustment(A)}}; - false -> - {ok, general_error(404, <<"Adjustment not found">>)} - end; - {error, #payproc_ContractNotFound{}} -> - {ok, general_error(404, <<"Contract not found">>)} + Contract = get_contract_or_fail(PartyID, ContractID, Context), + AdjustmentID = maps:get('adjustmentID', Req), + Adjustments = Contract#domain_Contract.adjustments, + case lists:keyfind(AdjustmentID, #domain_ContractAdjustment.id, Adjustments) of + #domain_ContractAdjustment{} = A -> + {ok, {200, #{}, decode_contract_adjustment(A)}}; + false -> + {ok, general_error(404, <<"Adjustment not found">>)} end end, {ok, #{authorize => Authorize, process => Process}}; @@ -118,14 +111,10 @@ prepare(OperationID = 'GetContractByIDForParty', Req, Context) -> {ok, capi_auth:authorize_operation(Prototypes, Context)} end, Process = fun() -> - case capi_party:get_contract(PartyID, ContractID, Context) of - {ok, Contract} -> - % Получение Party требуется для извлечения domain_Party.contractors - {ok, Party} = capi_party:get_party(PartyID, Context), - {ok, {200, #{}, decode_contract(Contract, Party#domain_Party.contractors)}}; - {error, #payproc_ContractNotFound{}} -> - {ok, general_error(404, <<"Contract not found">>)} - end + Contract = get_contract_or_fail(PartyID, ContractID, Context), + % Получение Party требуется для извлечения domain_Party.contractors + {ok, Party} = capi_party:get_party(PartyID, Context), + {ok, {200, #{}, decode_contract(Contract, Party#domain_Party.contractors)}} end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetContractAdjustmentsForParty', Req, Context) -> @@ -138,17 +127,9 @@ prepare(OperationID = 'GetContractAdjustmentsForParty', Req, Context) -> {ok, capi_auth:authorize_operation(Prototypes, Context)} end, Process = fun() -> - case capi_party:get_contract(PartyID, ContractID, Context) of - {ok, #domain_Contract{adjustments = Adjustments}} -> - Resp = [decode_contract_adjustment(A) || A <- Adjustments], - {ok, {200, #{}, Resp}}; - {error, #payproc_InvalidUser{}} -> - {ok, general_error(404, <<"Party not found">>)}; - {error, #payproc_PartyNotFound{}} -> - {ok, general_error(404, <<"Party not found">>)}; - {error, #payproc_ContractNotFound{}} -> - {ok, general_error(404, <<"Contract not found">>)} - end + Contract = get_contract_or_fail(PartyID, ContractID, Context), + Resp = [decode_contract_adjustment(A) || A <- Contract#domain_Contract.adjustments], + {ok, {200, #{}, Resp}} end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetContractAdjustmentByIDForParty', Req, Context) -> @@ -161,27 +142,32 @@ prepare(OperationID = 'GetContractAdjustmentByIDForParty', Req, Context) -> {ok, capi_auth:authorize_operation(Prototypes, Context)} end, Process = fun() -> - case capi_party:get_contract(PartyID, ContractID, Context) of - {ok, #domain_Contract{adjustments = Adjustments}} -> - AdjustmentID = maps:get('adjustmentID', Req), - case lists:keyfind(AdjustmentID, #domain_ContractAdjustment.id, Adjustments) of - #domain_ContractAdjustment{} = A -> - {ok, {200, #{}, decode_contract_adjustment(A)}}; - false -> - {ok, general_error(404, <<"Adjustment not found">>)} - end; - {error, #payproc_InvalidUser{}} -> - {ok, general_error(404, <<"Party not found">>)}; - {error, #payproc_PartyNotFound{}} -> - {ok, general_error(404, <<"Party not found">>)}; - {error, #payproc_ContractNotFound{}} -> - {ok, general_error(404, <<"Contract not found">>)} + Contract = get_contract_or_fail(PartyID, ContractID, Context), + AdjustmentID = maps:get('adjustmentID', Req), + Adjustments = Contract#domain_Contract.adjustments, + case lists:keyfind(AdjustmentID, #domain_ContractAdjustment.id, Adjustments) of + #domain_ContractAdjustment{} = A -> + {ok, {200, #{}, decode_contract_adjustment(A)}}; + false -> + {ok, general_error(404, <<"Adjustment not found">>)} end end, {ok, #{authorize => Authorize, process => Process}}; prepare(_OperationID, _Req, _Context) -> {error, noimpl}. +get_contract_or_fail(PartyID, ContractID, Context) -> + case capi_party:get_contract(PartyID, ContractID, Context) of + {ok, Contract} -> + Contract; + {error, #payproc_InvalidUser{}} -> + capi_handler:respond(general_error(404, <<"Party not found">>)); + {error, #payproc_PartyNotFound{}} -> + capi_handler:respond(general_error(404, <<"Party not found">>)); + {error, #payproc_ContractNotFound{}} -> + capi_handler:respond(general_error(404, <<"Contract not found">>)) + end. + %% decode_contracts_map(Contracts, Contractors) -> diff --git a/apps/capi/src/capi_handler_countries.erl b/apps/capi/src/capi_handler_countries.erl index 066b10b..ffcc6a4 100644 --- a/apps/capi/src/capi_handler_countries.erl +++ b/apps/capi/src/capi_handler_countries.erl @@ -28,7 +28,7 @@ process_request('GetCountries', _Req, Context) -> Countries = unwrap(capi_domain:get_objects_by_type(country, Context)), {ok, {200, #{}, lists:map(fun decode_country_object/1, Countries)}}; process_request('GetCountryByID', Req, Context) -> - CountryCode = capi_coder_utils:encode_country_code(maps:get(countryID, Req)), + CountryCode = capi_coder_utils:encode_country_code(maps:get('countryID', Req)), Ref = {country, #domain_CountryRef{id = CountryCode}}, case capi_domain:get(Ref, Context) of {ok, CountryObject} -> diff --git a/apps/capi/src/capi_handler_customers.erl b/apps/capi/src/capi_handler_customers.erl index c4c095d..7877417 100644 --- a/apps/capi/src/capi_handler_customers.erl +++ b/apps/capi/src/capi_handler_customers.erl @@ -31,21 +31,21 @@ prepare('CreateCustomer' = OperationID, Req, Context) -> {ok, Customer} -> {ok, {201, #{}, make_customer_and_token(Customer, Context)}}; {exception, #payproc_InvalidUser{}} -> - {ok, logic_error(invalidPartyID, <<"Party not found">>)}; + {ok, logic_error('invalidPartyID', <<"Party not found">>)}; {exception, #payproc_InvalidPartyStatus{}} -> - {ok, logic_error(<<"invalidPartyStatus">>, <<"Invalid party status">>)}; + {ok, logic_error('invalidPartyStatus', <<"Invalid party status">>)}; {exception, #payproc_InvalidShopStatus{}} -> - {ok, logic_error(invalidShopStatus, <<"Invalid shop status">>)}; + {ok, logic_error('invalidShopStatus', <<"Invalid shop status">>)}; {exception, #payproc_ShopNotFound{}} -> - {ok, logic_error(invalidShopID, <<"Shop not found">>)}; + {ok, logic_error('invalidShopID', <<"Shop not found">>)}; {exception, #payproc_PartyNotFound{}} -> - {ok, logic_error(<<"invalidPartyID">>, <<"Party not found">>)}; + {ok, logic_error('invalidPartyID', <<"Party not found">>)}; {exception, #payproc_OperationNotPermitted{}} -> - {ok, logic_error(operationNotPermitted, <<"Operation not permitted">>)} + {ok, logic_error('operationNotPermitted', <<"Operation not permitted">>)} end catch throw:{external_id_conflict, ID, UsedExternalID, _Schema} -> - {ok, logic_error(externalIDConflict, {ID, UsedExternalID})} + {ok, logic_error('externalIDConflict', {ID, UsedExternalID})} end end, {ok, #{authorize => Authorize, process => Process}}; @@ -87,9 +87,9 @@ prepare('DeleteCustomer' = OperationID, Req, Context) -> {exception, #payproc_CustomerNotFound{}} -> {ok, general_error(404, <<"Customer not found">>)}; {exception, #payproc_InvalidPartyStatus{}} -> - {ok, logic_error(invalidPartyStatus, <<"Invalid party status">>)}; + {ok, logic_error('invalidPartyStatus', <<"Invalid party status">>)}; {exception, #payproc_InvalidShopStatus{}} -> - {ok, logic_error(invalidShopStatus, <<"Invalid shop status">>)} + {ok, logic_error('invalidShopStatus', <<"Invalid shop status">>)} end end, {ok, #{authorize => Authorize, process => Process}}; @@ -114,7 +114,7 @@ prepare('CreateCustomerAccessToken' = OperationID, Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare('CreateBinding' = OperationID, Req, Context) -> - CustomerID = maps:get(customerID, Req), + CustomerID = maps:get('customerID', Req), Authorize = fun() -> Prototypes = [ {operation, #{id => OperationID, customer => CustomerID}}, @@ -149,28 +149,28 @@ prepare('CreateBinding' = OperationID, Req, Context) -> end, case Result of {ok, CustomerBinding} -> - {ok, {201, #{}, decode_customer_binding(CustomerBinding, Context)}}; + {ok, {201, #{}, decode_customer_binding(CustomerBinding)}}; {exception, #payproc_InvalidUser{}} -> {ok, general_error(404, <<"Customer not found">>)}; {exception, #payproc_CustomerNotFound{}} -> {ok, general_error(404, <<"Customer not found">>)}; {exception, #payproc_InvalidPartyStatus{}} -> - {ok, logic_error(invalidPartyStatus, <<"Invalid party status">>)}; + {ok, logic_error('invalidPartyStatus', <<"Invalid party status">>)}; {exception, #payproc_InvalidShopStatus{}} -> - {ok, logic_error(invalidShopStatus, <<"Invalid shop status">>)}; + {ok, logic_error('invalidShopStatus', <<"Invalid shop status">>)}; {exception, #payproc_InvalidContractStatus{}} -> - {ok, logic_error(invalidRequest, <<"Invalid contract status">>)}; + {ok, logic_error('invalidRequest', <<"Invalid contract status">>)}; {exception, #payproc_OperationNotPermitted{}} -> - {ok, logic_error(operationNotPermitted, <<"Operation not permitted">>)}; + {ok, logic_error('operationNotPermitted', <<"Operation not permitted">>)}; {error, invalid_payment_session} -> - {ok, logic_error(invalidPaymentSession, <<"Specified payment session is invalid">>)}; + {ok, logic_error('invalidPaymentSession', <<"Specified payment session is invalid">>)}; {error, {external_id_conflict, ID, UsedExternalID, _Schema}} -> - {ok, logic_error(externalIDConflict, {ID, UsedExternalID})} + {ok, logic_error('externalIDConflict', {ID, UsedExternalID})} end end, {ok, #{authorize => Authorize, process => Process}}; prepare('GetBindings' = OperationID, Req, Context) -> - CustomerID = maps:get(customerID, Req), + CustomerID = maps:get('customerID', Req), Customer = map_service_result(get_customer_by_id(CustomerID, Context)), Authorize = fun() -> Prototypes = [ @@ -180,17 +180,13 @@ prepare('GetBindings' = OperationID, Req, Context) -> {ok, mask_customer_notfound(capi_auth:authorize_operation(Prototypes, Context))} end, Process = fun() -> - case Customer of - #payproc_Customer{bindings = Bindings} -> - {ok, {200, #{}, [decode_customer_binding(B, Context) || B <- Bindings]}}; - undefined -> - {ok, general_error(404, <<"Customer not found">>)} - end + _ = capi_handler:respond_if_undefined(Customer, general_error(404, <<"Customer not found">>)), + {ok, {200, #{}, [decode_customer_binding(B) || B <- Customer#payproc_Customer.bindings]}} end, {ok, #{authorize => Authorize, process => Process}}; prepare('GetBinding' = OperationID, Req, Context) -> - CustomerID = maps:get(customerID, Req), - CustomerBindingID = maps:get(customerBindingID, Req), + CustomerID = maps:get('customerID', Req), + CustomerBindingID = maps:get('customerBindingID', Req), Customer = map_service_result(get_customer_by_id(CustomerID, Context)), Authorize = fun() -> Prototypes = [ @@ -200,21 +196,18 @@ prepare('GetBinding' = OperationID, Req, Context) -> {ok, mask_customer_notfound(capi_auth:authorize_operation(Prototypes, Context))} end, Process = fun() -> - case Customer of - #payproc_Customer{bindings = Bindings} -> - case lists:keyfind(CustomerBindingID, #payproc_CustomerBinding.id, Bindings) of - #payproc_CustomerBinding{} = B -> - {ok, {200, #{}, decode_customer_binding(B, Context)}}; - false -> - {ok, general_error(404, <<"Customer binding not found">>)} - end; - undefined -> - {ok, general_error(404, <<"Customer not found">>)} + _ = capi_handler:respond_if_undefined(Customer, general_error(404, <<"Customer not found">>)), + Bindings = Customer#payproc_Customer.bindings, + case lists:keyfind(CustomerBindingID, #payproc_CustomerBinding.id, Bindings) of + #payproc_CustomerBinding{} = B -> + {ok, {200, #{}, decode_customer_binding(B)}}; + false -> + {ok, general_error(404, <<"Customer binding not found">>)} end end, {ok, #{authorize => Authorize, process => Process}}; prepare('GetCustomerEvents' = OperationID, Req, Context) -> - CustomerID = maps:get(customerID, Req), + CustomerID = maps:get('customerID', Req), Authorize = fun() -> Prototypes = [ {operation, #{id => OperationID, customer => CustomerID}}, @@ -230,11 +223,10 @@ prepare('GetCustomerEvents' = OperationID, Req, Context) -> ) end, Result = capi_handler_utils:collect_events( - maps:get(limit, Req), - genlib_map:get(eventID, Req), + maps:get('limit', Req), + genlib_map:get('eventID', Req), GetterFun, - fun decode_customer_event/2, - undefined + fun decode_customer_event/1 ), case Result of {ok, Events} when is_list(Events) -> @@ -249,7 +241,7 @@ prepare('GetCustomerEvents' = OperationID, Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare('GetCustomerPaymentMethods' = OperationID, Req, Context) -> - CustomerID = maps:get(customerID, Req), + CustomerID = maps:get('customerID', Req), Customer = map_service_result(get_customer_by_id(CustomerID, Context)), Authorize = fun() -> Prototypes = [ @@ -270,13 +262,10 @@ prepare('GetCustomerPaymentMethods' = OperationID, Req, Context) -> PaymentMethods1 = capi_utils:deduplicate_payment_methods(PaymentMethods0), PaymentMethods = capi_handler_utils:emplace_token_provider_data(Customer, PaymentMethods1, Context), {ok, {200, #{}, PaymentMethods}}; - {exception, Exception} -> - case Exception of - #payproc_InvalidUser{} -> - {ok, general_error(404, <<"Customer not found">>)}; - #payproc_CustomerNotFound{} -> - {ok, general_error(404, <<"Customer not found">>)} - end + {exception, #payproc_InvalidUser{}} -> + {ok, general_error(404, <<"Customer not found">>)}; + {exception, #payproc_CustomerNotFound{}} -> + {ok, general_error(404, <<"Customer not found">>)} end end, {ok, #{authorize => Authorize, process => Process}}; @@ -377,7 +366,7 @@ encode_payment_tool_token(Token) -> 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)); + capi_handler:respond(logic_error('invalidPaymentToolToken')); _ -> PaymentTool end; @@ -385,7 +374,7 @@ encode_payment_tool_token(Token) -> encode_legacy_payment_tool_token(Token); {error, {decryption_failed, Error}} -> logger:warning("Payment tool token decryption failed: ~p", [Error]), - capi_handler:respond(logic_error(invalidPaymentToolToken)) + capi_handler:respond(logic_error('invalidPaymentToolToken')) end. encode_legacy_payment_tool_token(Token) -> @@ -393,7 +382,7 @@ encode_legacy_payment_tool_token(Token) -> capi_handler_encoder:encode_payment_tool(capi_utils:base64url_to_map(Token)) catch error:badarg -> - capi_handler:respond(logic_error(invalidPaymentToolToken)) + capi_handler:respond(logic_error('invalidPaymentToolToken')) end. make_customer_and_token(Customer, ProcessingContext) -> @@ -418,7 +407,7 @@ decode_customer_status({Status, _}) -> decode_customer_metadata(Meta) -> capi_json_marshalling:unmarshal(Meta). -decode_customer_binding(CustomerBinding, Context) -> +decode_customer_binding(CustomerBinding) -> capi_handler_utils:merge_and_compact( #{ <<"id">> => CustomerBinding#payproc_CustomerBinding.id, @@ -427,14 +416,14 @@ decode_customer_binding(CustomerBinding, Context) -> CustomerBinding#payproc_CustomerBinding.payment_resource ) }, - decode_customer_binding_status(CustomerBinding#payproc_CustomerBinding.status, Context) + decode_customer_binding_status(CustomerBinding#payproc_CustomerBinding.status) ). -decode_customer_binding_status({Status, StatusInfo}, Context) -> +decode_customer_binding_status({Status, StatusInfo}) -> Error = case StatusInfo of #payproc_CustomerBindingFailed{failure = OperationFailure} -> - capi_handler_decoder_utils:decode_operation_failure(OperationFailure, Context); + capi_handler_decoder_utils:decode_operation_failure(OperationFailure); _ -> undefined end, @@ -443,8 +432,8 @@ decode_customer_binding_status({Status, StatusInfo}, Context) -> <<"error">> => Error }. -decode_customer_event(Event = #payproc_Event{source = {customer_id, _}, payload = Payload}, Context) -> - case decode_customer_changes(Payload, Context) of +decode_customer_event(Event = #payproc_Event{source = {customer_id, _}, payload = Payload}) -> + case decode_customer_changes(Payload) of [_Something | _] = Changes -> {true, #{ <<"id">> => Event#payproc_Event.id, @@ -455,25 +444,22 @@ decode_customer_event(Event = #payproc_Event{source = {customer_id, _}, payload false end. -decode_customer_changes({customer_changes, CustomerChanges}, Context) -> - lists:filtermap( - fun(V) -> decode_customer_change(V, Context) end, - CustomerChanges - ). +decode_customer_changes({customer_changes, CustomerChanges}) -> + lists:filtermap(fun decode_customer_change/1, CustomerChanges). -decode_customer_change({customer_binding_changed, CustomerBindingChanged}, Context) -> +decode_customer_change({customer_binding_changed, CustomerBindingChanged}) -> #payproc_CustomerBindingChanged{id = BindingID, payload = Payload} = CustomerBindingChanged, - decode_customer_binding_change(BindingID, Payload, Context); -decode_customer_change(_, _) -> + decode_customer_binding_change(BindingID, Payload); +decode_customer_change(_) -> false. -decode_customer_binding_change(_, {started, Start}, Context) -> +decode_customer_binding_change(_, {started, Start}) -> #payproc_CustomerBindingStarted{binding = CustomerBinding} = Start, {true, #{ <<"changeType">> => <<"CustomerBindingStarted">>, - <<"customerBinding">> => decode_customer_binding(CustomerBinding, Context) + <<"customerBinding">> => decode_customer_binding(CustomerBinding) }}; -decode_customer_binding_change(BindingID, {status_changed, StatusChange}, Context) -> +decode_customer_binding_change(BindingID, {status_changed, StatusChange}) -> #payproc_CustomerBindingStatusChanged{status = Status} = StatusChange, {true, capi_handler_utils:merge_and_compact( @@ -481,9 +467,9 @@ decode_customer_binding_change(BindingID, {status_changed, StatusChange}, Contex <<"changeType">> => <<"CustomerBindingStatusChanged">>, <<"customerBindingID">> => BindingID }, - decode_customer_binding_status(Status, Context) + decode_customer_binding_status(Status) )}; -decode_customer_binding_change(BindingID, {interaction_requested, InteractionRequest}, _) -> +decode_customer_binding_change(BindingID, {interaction_requested, InteractionRequest}) -> #payproc_CustomerBindingInteractionRequested{interaction = UserInteraction} = InteractionRequest, {true, #{ <<"changeType">> => <<"CustomerBindingInteractionRequested">>, diff --git a/apps/capi/src/capi_handler_decoder_invoicing.erl b/apps/capi/src/capi_handler_decoder_invoicing.erl index 1240376..5636c37 100644 --- a/apps/capi/src/capi_handler_decoder_invoicing.erl +++ b/apps/capi/src/capi_handler_decoder_invoicing.erl @@ -8,7 +8,7 @@ -export([decode_invoice_payment/3]). -export([decode_payment/3]). -export([decode_chargeback/2]). --export([decode_refund/2]). +-export([decode_refund/1]). -export([decode_invoice/1]). -export([decode_invoice_cart/1]). -export([decode_invoice_bank_account/1]). @@ -16,7 +16,7 @@ -export([decode_payment_methods/1]). -export([decode_payment_status/2]). -export([decode_payment_operation_failure/2]). --export([decode_refund_status/2]). +-export([decode_refund_status/1]). -export([decode_recurrent_parent/1]). -export([decode_make_recurrent/1]). @@ -317,9 +317,9 @@ payment_error_client_maping({authorization_failed, {insufficient_funds, _}}) -> payment_error_client_maping(_) -> <<"PaymentRejected">>. --spec decode_refund(capi_handler_encoder:encode_data(), processing_context()) -> +-spec decode_refund(capi_handler_encoder:encode_data()) -> decode_data(). -decode_refund(Refund, Context) -> +decode_refund(Refund) -> #domain_Cash{amount = Amount, currency = Currency} = Refund#domain_InvoicePaymentRefund.cash, capi_handler_utils:merge_and_compact( #{ @@ -331,15 +331,15 @@ decode_refund(Refund, Context) -> <<"externalID">> => Refund#domain_InvoicePaymentRefund.external_id, <<"allocation">> => capi_allocation:decode(Refund#domain_InvoicePaymentRefund.allocation) }, - decode_refund_status(Refund#domain_InvoicePaymentRefund.status, Context) + decode_refund_status(Refund#domain_InvoicePaymentRefund.status) ). --spec decode_refund_status({atom(), _}, processing_context()) -> decode_data(). -decode_refund_status({Status, StatusInfo}, Context) -> +-spec decode_refund_status({atom(), _}) -> decode_data(). +decode_refund_status({Status, StatusInfo}) -> Error = case StatusInfo of #domain_InvoicePaymentRefundFailed{failure = OperationFailure} -> - capi_handler_decoder_utils:decode_operation_failure(OperationFailure, Context); + capi_handler_decoder_utils:decode_operation_failure(OperationFailure); _ -> undefined end, @@ -452,8 +452,6 @@ decode_invoice_bank_account(undefined) -> -spec decode_invoice_line_tax_mode(map()) -> decode_data() | undefined. decode_invoice_line_tax_mode(#{<<"TaxMode">> := {str, TM}}) -> - %% for more info about taxMode look here: - %% https://github.com/rbkmoney/starrys/blob/master/docs/settings.md #{ <<"type">> => <<"InvoiceLineTaxVAT">>, <<"rate">> => TM diff --git a/apps/capi/src/capi_handler_decoder_utils.erl b/apps/capi/src/capi_handler_decoder_utils.erl index 0663a64..fa24401 100644 --- a/apps/capi/src/capi_handler_decoder_utils.erl +++ b/apps/capi/src/capi_handler_decoder_utils.erl @@ -10,10 +10,13 @@ -export([decode_bank_card_bin/1]). -export([decode_last_digits/1]). -export([decode_masked_pan/2]). --export([decode_operation_failure/2]). +-export([decode_operation_failure/1]). -export([decode_category_ref/1]). -export([decode_context/1]). -export([decode_optional/2]). +-export([decode_metadata/1]). +-export([decode_namespaced_metadata/1]). + -export([convert_crypto_currency_to_swag/1]). -export_type([decode_data/0]). @@ -61,10 +64,10 @@ decode_last_digits(MaskedPan) when byte_size(MaskedPan) > ?MASKED_PAN_MAX_LENGTH decode_last_digits(MaskedPan) -> MaskedPan. --spec decode_operation_failure(_, _) -> decode_data(). -decode_operation_failure({operation_timeout, _}, _) -> +-spec decode_operation_failure(_) -> decode_data(). +decode_operation_failure({operation_timeout, _}) -> logic_error(timeout, <<"timeout">>); -decode_operation_failure({failure, #domain_Failure{code = Code, reason = Reason}}, _) -> +decode_operation_failure({failure, #domain_Failure{code = Code, reason = Reason}}) -> logic_error(Code, Reason). logic_error(Code, Message) -> @@ -87,6 +90,17 @@ decode_optional(Arg, DecodeFun) when Arg /= undefined -> decode_optional(undefined, _) -> undefined. +-spec decode_metadata(dmsl_domain_thrift:'Metadata'()) -> capi_json_marshalling:value(). +decode_metadata(MD) -> + capi_json_marshalling:unmarshal(MD). + +-spec decode_namespaced_metadata(#{NS => dmsl_domain_thrift:'Metadata'()}) -> + #{NS => capi_json_marshalling:value()} +when + NS :: binary(). +decode_namespaced_metadata(NamespacedMD) -> + maps:map(fun(_NS, MD) -> decode_metadata(MD) end, NamespacedMD). + -spec convert_crypto_currency_to_swag(atom()) -> binary(). convert_crypto_currency_to_swag(bitcoin_cash) -> <<"bitcoinCash">>; diff --git a/apps/capi/src/capi_handler_encoder.erl b/apps/capi/src/capi_handler_encoder.erl index df0024e..7ff70b9 100644 --- a/apps/capi/src/capi_handler_encoder.erl +++ b/apps/capi/src/capi_handler_encoder.erl @@ -204,8 +204,6 @@ encode_invoice_line_meta(Line) -> end. encode_invoice_line_tax_mode(#{<<"type">> := <<"InvoiceLineTaxVAT">>} = TaxMode) -> - %% for more info about taxMode look here: - %% 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. diff --git a/apps/capi/src/capi_handler_geo.erl b/apps/capi/src/capi_handler_geo.erl deleted file mode 100644 index bd32a6a..0000000 --- a/apps/capi/src/capi_handler_geo.erl +++ /dev/null @@ -1,48 +0,0 @@ --module(capi_handler_geo). - --include_lib("damsel/include/dmsl_domain_thrift.hrl"). - --behaviour(capi_handler). - --export([prepare/3]). - --import(capi_handler_utils, [logic_error/2]). - --spec prepare( - OperationID :: capi_handler:operation_id(), - 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}}], - {ok, capi_auth:authorize_operation(Prototypes, Context)} - end, - Process = fun() -> - GeoIDs = ordsets:from_list(maps:get('geoIDs', Req)), - Language = maps:get('language', Req), - Call = {geo_ip_service, 'GetLocationName', {GeoIDs, Language}}, - case capi_handler_utils:service_call(Call, Context) of - {ok, LocationNames} -> - PreparedLocationNames = maps:fold( - fun(GeoID, Name, Acc) -> [decode_location_name(GeoID, Name) | Acc] end, - [], - LocationNames - ), - {ok, {200, #{}, PreparedLocationNames}}; - {exception, #'InvalidRequest'{errors = Errors}} -> - FormattedErrors = capi_handler_utils:format_request_errors(Errors), - {ok, logic_error(invalidRequest, FormattedErrors)} - end - end, - {ok, #{authorize => Authorize, process => Process}}; -prepare(_OperationID, _Req, _Context) -> - {error, noimpl}. - -%% - -decode_location_name(GeoID, Name) -> - #{ - <<"geoID">> => GeoID, - <<"name">> => Name - }. diff --git a/apps/capi/src/capi_handler_invoice_templates.erl b/apps/capi/src/capi_handler_invoice_templates.erl index 05f24db..a4ce23b 100644 --- a/apps/capi/src/capi_handler_invoice_templates.erl +++ b/apps/capi/src/capi_handler_invoice_templates.erl @@ -36,27 +36,24 @@ prepare('CreateInvoiceTemplate' = OperationID, Req, Context) -> of {ok, InvoiceTpl} -> {ok, {201, #{}, make_invoice_tpl_and_token(InvoiceTpl, Context)}}; - {exception, Exception} -> - case Exception of - #'InvalidRequest'{errors = Errors} -> - FormattedErrors = capi_handler_utils:format_request_errors(Errors), - {ok, logic_error(invalidRequest, FormattedErrors)}; - #payproc_InvalidUser{} -> - {ok, logic_error(invalidPartyID, <<"Party not found">>)}; - #payproc_ShopNotFound{} -> - {ok, logic_error(invalidShopID, <<"Shop not found">>)}; - #payproc_InvalidPartyStatus{} -> - {ok, logic_error(invalidPartyStatus, <<"Invalid party status">>)}; - #payproc_InvalidShopStatus{} -> - {ok, logic_error(invalidShopStatus, <<"Invalid shop status">>)} - end + {exception, #'InvalidRequest'{errors = Errors}} -> + FormattedErrors = capi_handler_utils:format_request_errors(Errors), + {ok, logic_error('invalidRequest', FormattedErrors)}; + {exception, #payproc_InvalidUser{}} -> + {ok, logic_error('invalidPartyID', <<"Party not found">>)}; + {exception, #payproc_ShopNotFound{}} -> + {ok, logic_error('invalidShopID', <<"Shop not found">>)}; + {exception, #payproc_InvalidPartyStatus{}} -> + {ok, logic_error('invalidPartyStatus', <<"Invalid party status">>)}; + {exception, #payproc_InvalidShopStatus{}} -> + {ok, logic_error('invalidShopStatus', <<"Invalid shop status">>)} catch throw:invoice_cart_empty -> - {ok, logic_error(invalidInvoiceCart, <<"Wrong size. Path to item: cart">>)}; + {ok, logic_error('invalidInvoiceCart', <<"Wrong size. Path to item: cart">>)}; throw:zero_invoice_lifetime -> - {ok, logic_error(invalidRequest, <<"Lifetime cannot be zero">>)}; + {ok, logic_error('invalidRequest', <<"Lifetime cannot be zero">>)}; throw:{external_id_conflict, ID, UsedExternalID, _Schema} -> - {ok, logic_error(externalIDConflict, {ID, UsedExternalID})} + {ok, logic_error('externalIDConflict', {ID, UsedExternalID})} end end, {ok, #{authorize => Authorize, process => Process}}; @@ -94,22 +91,19 @@ prepare('UpdateInvoiceTemplate' = OperationID, Req, Context) -> of {ok, UpdatedInvoiceTpl} -> {ok, {200, #{}, decode_invoice_tpl(UpdatedInvoiceTpl)}}; - {exception, Exception} -> - case Exception of - #payproc_InvalidUser{} -> - {ok, general_error(404, <<"Invoice Template not found">>)}; - #'InvalidRequest'{errors = Errors} -> - FormattedErrors = capi_handler_utils:format_request_errors(Errors), - {ok, logic_error(invalidRequest, FormattedErrors)}; - #payproc_InvalidPartyStatus{} -> - {ok, logic_error(invalidPartyStatus, <<"Invalid party status">>)}; - #payproc_InvalidShopStatus{} -> - {ok, logic_error(invalidShopStatus, <<"Invalid shop status">>)}; - #payproc_InvoiceTemplateNotFound{} -> - {ok, general_error(404, <<"Invoice Template not found">>)}; - #payproc_InvoiceTemplateRemoved{} -> - {ok, general_error(404, <<"Invoice Template not found">>)} - end + {exception, #payproc_InvalidUser{}} -> + {ok, general_error(404, <<"Invoice Template not found">>)}; + {exception, #'InvalidRequest'{errors = Errors}} -> + FormattedErrors = capi_handler_utils:format_request_errors(Errors), + {ok, logic_error('invalidRequest', FormattedErrors)}; + {exception, #payproc_InvalidPartyStatus{}} -> + {ok, logic_error('invalidPartyStatus', <<"Invalid party status">>)}; + {exception, #payproc_InvalidShopStatus{}} -> + {ok, logic_error('invalidShopStatus', <<"Invalid shop status">>)}; + {exception, #payproc_InvoiceTemplateNotFound{}} -> + {ok, general_error(404, <<"Invoice Template not found">>)}; + {exception, #payproc_InvoiceTemplateRemoved{}} -> + {ok, general_error(404, <<"Invoice Template not found">>)} catch throw:#payproc_InvalidUser{} -> {ok, general_error(404, <<"Invoice Template not found">>)}; @@ -118,9 +112,9 @@ prepare('UpdateInvoiceTemplate' = OperationID, Req, Context) -> throw:#payproc_InvoiceTemplateRemoved{} -> {ok, general_error(404, <<"Invoice Template not found">>)}; throw:invoice_cart_empty -> - {ok, logic_error(invalidInvoiceCart, <<"Wrong size. Path to item: cart">>)}; + {ok, logic_error('invalidInvoiceCart', <<"Wrong size. Path to item: cart">>)}; throw:zero_invoice_lifetime -> - {ok, logic_error(invalidRequest, <<"Lifetime cannot be zero">>)} + {ok, logic_error('invalidRequest', <<"Lifetime cannot be zero">>)} end end, {ok, #{authorize => Authorize, process => Process}}; @@ -139,19 +133,16 @@ prepare('DeleteInvoiceTemplate' = OperationID, Req, Context) -> case capi_handler_utils:service_call_with([user_info], Call, Context) of {ok, _R} -> {ok, {204, #{}, undefined}}; - {exception, Exception} -> - case Exception of - #payproc_InvalidUser{} -> - {ok, general_error(404, <<"Invoice Template not found">>)}; - #payproc_InvalidPartyStatus{} -> - {ok, logic_error(invalidPartyStatus, <<"Invalid party status">>)}; - #payproc_InvalidShopStatus{} -> - {ok, logic_error(invalidShopStatus, <<"Invalid shop status">>)}; - #payproc_InvoiceTemplateNotFound{} -> - {ok, general_error(404, <<"Invoice Template not found">>)}; - #payproc_InvoiceTemplateRemoved{} -> - {ok, general_error(404, <<"Invoice Template not found">>)} - end + {exception, #payproc_InvalidUser{}} -> + {ok, general_error(404, <<"Invoice Template not found">>)}; + {exception, #payproc_InvalidPartyStatus{}} -> + {ok, logic_error('invalidPartyStatus', <<"Invalid party status">>)}; + {exception, #payproc_InvalidShopStatus{}} -> + {ok, logic_error('invalidShopStatus', <<"Invalid shop status">>)}; + {exception, #payproc_InvoiceTemplateNotFound{}} -> + {ok, general_error(404, <<"Invoice Template not found">>)}; + {exception, #payproc_InvoiceTemplateRemoved{}} -> + {ok, general_error(404, <<"Invoice Template not found">>)} end end, {ok, #{authorize => Authorize, process => Process}}; @@ -173,31 +164,28 @@ prepare('CreateInvoiceWithTemplate' = OperationID, Req, Context) -> try create_invoice(PartyID, InvoiceTplID, InvoiceParams, Context, OperationID) of {ok, #'payproc_Invoice'{invoice = Invoice}} -> {ok, {201, #{}, capi_handler_decoder_invoicing:make_invoice_and_token(Invoice, Context)}}; - {exception, Reason} -> - case Reason of - #payproc_InvalidUser{} -> - {ok, general_error(404, <<"Invoice Template not found">>)}; - #'InvalidRequest'{errors = Errors} -> - FormattedErrors = capi_handler_utils:format_request_errors(Errors), - {ok, logic_error(invalidRequest, FormattedErrors)}; - #payproc_InvalidPartyStatus{} -> - {ok, logic_error(invalidPartyStatus, <<"Invalid party status">>)}; - #payproc_InvalidShopStatus{} -> - {ok, logic_error(invalidShopStatus, <<"Invalid shop status">>)}; - #payproc_InvoiceTemplateNotFound{} -> - {ok, general_error(404, <<"Invoice Template not found">>)}; - #payproc_InvoiceTemplateRemoved{} -> - {ok, general_error(404, <<"Invoice Template not found">>)}; - #payproc_InvoiceTermsViolated{} -> - {ok, logic_error(invoiceTermsViolated, <<"Invoice parameters violate contract terms">>)} - end + {exception, #payproc_InvalidUser{}} -> + {ok, general_error(404, <<"Invoice Template not found">>)}; + {exception, #'InvalidRequest'{errors = Errors}} -> + FormattedErrors = capi_handler_utils:format_request_errors(Errors), + {ok, logic_error('invalidRequest', FormattedErrors)}; + {exception, #payproc_InvalidPartyStatus{}} -> + {ok, logic_error('invalidPartyStatus', <<"Invalid party status">>)}; + {exception, #payproc_InvalidShopStatus{}} -> + {ok, logic_error('invalidShopStatus', <<"Invalid shop status">>)}; + {exception, #payproc_InvoiceTemplateNotFound{}} -> + {ok, general_error(404, <<"Invoice Template not found">>)}; + {exception, #payproc_InvoiceTemplateRemoved{}} -> + {ok, general_error(404, <<"Invoice Template not found">>)}; + {exception, #payproc_InvoiceTermsViolated{}} -> + {ok, logic_error('invoiceTermsViolated', <<"Invoice parameters violate contract terms">>)} catch throw:{bad_invoice_params, currency_no_amount} -> - {ok, logic_error(invalidRequest, <<"Amount is required for the currency">>)}; + {ok, logic_error('invalidRequest', <<"Amount is required for the currency">>)}; throw:{bad_invoice_params, amount_no_currency} -> - {ok, logic_error(invalidRequest, <<"Currency is required for the amount">>)}; + {ok, logic_error('invalidRequest', <<"Currency is required for the amount">>)}; throw:{external_id_conflict, InvoiceID, ExternalID, _Schema} -> - {ok, logic_error(externalIDConflict, {InvoiceID, ExternalID})} + {ok, logic_error('externalIDConflict', {InvoiceID, ExternalID})} end end, {ok, #{authorize => Authorize, process => Process}}; diff --git a/apps/capi/src/capi_handler_invoices.erl b/apps/capi/src/capi_handler_invoices.erl index 4f3eebd..2ee7d9a 100644 --- a/apps/capi/src/capi_handler_invoices.erl +++ b/apps/capi/src/capi_handler_invoices.erl @@ -34,46 +34,43 @@ prepare('CreateInvoice' = OperationID, Req, Context) -> case create_invoice(PartyID, InvoiceParams, Context, OperationID) of {ok, #'payproc_Invoice'{invoice = Invoice}} -> {ok, {201, #{}, capi_handler_decoder_invoicing:make_invoice_and_token(Invoice, Context)}}; - {exception, Exception} -> - case Exception of - #'payproc_InvalidUser'{} -> - {ok, logic_error(invalidPartyID, <<"Party not found">>)}; - #'InvalidRequest'{errors = Errors} -> - FormattedErrors = capi_handler_utils:format_request_errors(Errors), - {ok, logic_error(invalidRequest, FormattedErrors)}; - #payproc_ShopNotFound{} -> - {ok, logic_error(invalidShopID, <<"Shop not found">>)}; - #payproc_InvalidPartyStatus{} -> - {ok, logic_error(invalidPartyStatus, <<"Invalid party status">>)}; - #payproc_InvalidShopStatus{} -> - {ok, logic_error(invalidShopStatus, <<"Invalid shop status">>)}; - #payproc_InvoiceTermsViolated{} -> - {ok, logic_error(invoiceTermsViolated, <<"Invoice parameters violate contract terms">>)}; - #payproc_AllocationNotAllowed{} -> - {ok, logic_error(allocationNotPermitted, <<"Not allowed">>)}; - #payproc_AllocationExceededPaymentAmount{} -> - {ok, logic_error(invalidAllocation, <<"Exceeded payment amount">>)}; - #payproc_AllocationInvalidTransaction{} = InvalidTransaction -> - Message = capi_allocation:transaction_error(InvalidTransaction), - {ok, logic_error(invalidAllocation, Message)} - end + {exception, #'payproc_InvalidUser'{}} -> + {ok, logic_error('invalidPartyID', <<"Party not found">>)}; + {exception, #'InvalidRequest'{errors = Errors}} -> + FormattedErrors = capi_handler_utils:format_request_errors(Errors), + {ok, logic_error('invalidRequest', FormattedErrors)}; + {exception, #payproc_ShopNotFound{}} -> + {ok, logic_error('invalidShopID', <<"Shop not found">>)}; + {exception, #payproc_InvalidPartyStatus{}} -> + {ok, logic_error('invalidPartyStatus', <<"Invalid party status">>)}; + {exception, #payproc_InvalidShopStatus{}} -> + {ok, logic_error('invalidShopStatus', <<"Invalid shop status">>)}; + {exception, #payproc_InvoiceTermsViolated{}} -> + {ok, logic_error('invoiceTermsViolated', <<"Invoice parameters violate contract terms">>)}; + {exception, #payproc_AllocationNotAllowed{}} -> + {ok, logic_error('allocationNotPermitted', <<"Not allowed">>)}; + {exception, #payproc_AllocationExceededPaymentAmount{}} -> + {ok, logic_error('invalidAllocation', <<"Exceeded payment amount">>)}; + {exception, #payproc_AllocationInvalidTransaction{} = InvalidTransaction} -> + Message = capi_allocation:transaction_error(InvalidTransaction), + {ok, logic_error('invalidAllocation', Message)} end catch throw:invoice_cart_empty -> - {ok, logic_error(invalidInvoiceCart, <<"Wrong size. Path to item: cart">>)}; + {ok, logic_error('invalidInvoiceCart', <<"Wrong size. Path to item: cart">>)}; throw:invalid_invoice_cost -> - {ok, logic_error(invalidInvoiceCost, <<"Invalid invoice amount">>)}; + {ok, logic_error('invalidInvoiceCost', <<"Invalid invoice amount">>)}; throw:{external_id_conflict, InvoiceID, ExternalID, _Schema} -> - {ok, logic_error(externalIDConflict, {InvoiceID, ExternalID})}; + {ok, logic_error('externalIDConflict', {InvoiceID, ExternalID})}; throw:allocation_wrong_cart -> - {ok, logic_error(invalidAllocation, <<"Wrong cart">>)}; + {ok, logic_error('invalidAllocation', <<"Wrong cart">>)}; throw:allocation_duplicate -> - {ok, logic_error(invalidAllocation, <<"Duplicate shop">>)} + {ok, logic_error('invalidAllocation', <<"Duplicate shop">>)} end end, {ok, #{authorize => Authorize, process => Process}}; prepare('CreateInvoiceAccessToken' = OperationID, Req, Context) -> - InvoiceID = maps:get(invoiceID, Req), + InvoiceID = maps:get('invoiceID', Req), ResultInvoice = map_service_result(capi_handler_utils:get_invoice_by_id(InvoiceID, Context)), Authorize = fun() -> Prototypes = [ @@ -91,7 +88,7 @@ prepare('CreateInvoiceAccessToken' = OperationID, Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare('GetInvoiceByID' = OperationID, Req, Context) -> - InvoiceID = maps:get(invoiceID, Req), + InvoiceID = maps:get('invoiceID', Req), ResultInvoice = map_service_result(capi_handler_utils:get_invoice_by_id(InvoiceID, Context)), Authorize = fun() -> Prototypes = [ @@ -108,7 +105,7 @@ prepare('GetInvoiceByID' = OperationID, Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare('GetInvoiceByExternalID' = OperationID, Req, Context) -> - ExternalID = maps:get(externalID, Req), + ExternalID = maps:get('externalID', Req), {InvoiceID, ResultInvoice} = case get_invoice_by_external_id(ExternalID, Context) of {ok, Result} -> @@ -133,7 +130,7 @@ prepare('GetInvoiceByExternalID' = OperationID, Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare('FulfillInvoice' = OperationID, Req, Context) -> - InvoiceID = maps:get(invoiceID, Req), + InvoiceID = maps:get('invoiceID', Req), Authorize = fun() -> Prototypes = [ {operation, #{id => OperationID, invoice => InvoiceID}}, @@ -148,24 +145,21 @@ prepare('FulfillInvoice' = OperationID, Req, Context) -> case capi_handler_utils:service_call_with([user_info], Call, Context) of {ok, _} -> {ok, {204, #{}, undefined}}; - {exception, Exception} -> - case Exception of - #payproc_InvalidInvoiceStatus{} -> - {ok, logic_error(invalidInvoiceStatus, <<"Invalid invoice status">>)}; - #payproc_InvalidPartyStatus{} -> - {ok, logic_error(invalidPartyStatus, <<"Invalid party status">>)}; - #payproc_InvalidShopStatus{} -> - {ok, logic_error(invalidShopStatus, <<"Invalid shop status">>)}; - #payproc_InvalidUser{} -> - {ok, general_error(404, <<"Invoice not found">>)}; - #payproc_InvoiceNotFound{} -> - {ok, general_error(404, <<"Invoice not found">>)} - end + {exception, #payproc_InvalidInvoiceStatus{}} -> + {ok, logic_error('invalidInvoiceStatus', <<"Invalid invoice status">>)}; + {exception, #payproc_InvalidPartyStatus{}} -> + {ok, logic_error('invalidPartyStatus', <<"Invalid party status">>)}; + {exception, #payproc_InvalidShopStatus{}} -> + {ok, logic_error('invalidShopStatus', <<"Invalid shop status">>)}; + {exception, #payproc_InvalidUser{}} -> + {ok, general_error(404, <<"Invoice not found">>)}; + {exception, #payproc_InvoiceNotFound{}} -> + {ok, general_error(404, <<"Invoice not found">>)} end end, {ok, #{authorize => Authorize, process => Process}}; prepare('RescindInvoice' = OperationID, Req, Context) -> - InvoiceID = maps:get(invoiceID, Req), + InvoiceID = maps:get('invoiceID', Req), Authorize = fun() -> Prototypes = [ {operation, #{id => OperationID, invoice => InvoiceID}}, @@ -180,27 +174,23 @@ prepare('RescindInvoice' = OperationID, Req, Context) -> case capi_handler_utils:service_call_with([user_info], Call, Context) of {ok, _} -> {ok, {204, #{}, undefined}}; - {exception, Exception} -> - case Exception of - #payproc_InvalidInvoiceStatus{} -> - {ok, logic_error(invalidInvoiceStatus, <<"Invalid invoice status">>)}; - #payproc_InvoicePaymentPending{} -> - ErrorResp = logic_error(invoicePaymentPending, <<"Invoice payment pending">>), - {ok, ErrorResp}; - #payproc_InvalidPartyStatus{} -> - {ok, logic_error(invalidPartyStatus, <<"Invalid party status">>)}; - #payproc_InvalidShopStatus{} -> - {ok, logic_error(invalidShopStatus, <<"Invalid shop status">>)}; - #payproc_InvalidUser{} -> - {ok, general_error(404, <<"Invoice not found">>)}; - #payproc_InvoiceNotFound{} -> - {ok, general_error(404, <<"Invoice not found">>)} - end + {exception, #payproc_InvalidInvoiceStatus{}} -> + {ok, logic_error('invalidInvoiceStatus', <<"Invalid invoice status">>)}; + {exception, #payproc_InvoicePaymentPending{}} -> + {ok, logic_error('invoicePaymentPending', <<"Invoice payment pending">>)}; + {exception, #payproc_InvalidPartyStatus{}} -> + {ok, logic_error('invalidPartyStatus', <<"Invalid party status">>)}; + {exception, #payproc_InvalidShopStatus{}} -> + {ok, logic_error('invalidShopStatus', <<"Invalid shop status">>)}; + {exception, #payproc_InvalidUser{}} -> + {ok, general_error(404, <<"Invoice not found">>)}; + {exception, #payproc_InvoiceNotFound{}} -> + {ok, general_error(404, <<"Invoice not found">>)} end end, {ok, #{authorize => Authorize, process => Process}}; prepare('GetInvoiceEvents' = OperationID, Req, Context) -> - InvoiceID = maps:get(invoiceID, Req), + InvoiceID = maps:get('invoiceID', Req), Authorize = fun() -> Prototypes = [ {operation, #{id => OperationID, invoice => InvoiceID}}, @@ -212,38 +202,34 @@ prepare('GetInvoiceEvents' = OperationID, Req, Context) -> Process = fun() -> Result = capi_handler_utils:collect_events( - maps:get(limit, Req), - genlib_map:get(eventID, Req), + maps:get('limit', Req), + genlib_map:get('eventID', Req), fun(Range) -> capi_handler_utils:service_call_with( [user_info], - {invoicing, 'GetEvents', {maps:get(invoiceID, Req), Range}}, + {invoicing, 'GetEvents', {maps:get('invoiceID', Req), Range}}, Context ) end, - fun decode_invoice_event/2, - Context + fun(E) -> decode_invoice_event(E, Context) end ), case Result of {ok, Events} when is_list(Events) -> {ok, {200, #{}, Events}}; - {exception, Exception} -> - case Exception of - #payproc_InvalidUser{} -> - {ok, general_error(404, <<"Invoice not found">>)}; - #payproc_InvoiceNotFound{} -> - {ok, general_error(404, <<"Invoice not found">>)}; - #payproc_EventNotFound{} -> - {ok, general_error(404, <<"Event not found">>)}; - #'InvalidRequest'{errors = Errors} -> - FormattedErrors = capi_handler_utils:format_request_errors(Errors), - {ok, logic_error(invalidRequest, FormattedErrors)} - end + {exception, #payproc_InvalidUser{}} -> + {ok, general_error(404, <<"Invoice not found">>)}; + {exception, #payproc_InvoiceNotFound{}} -> + {ok, general_error(404, <<"Invoice not found">>)}; + {exception, #payproc_EventNotFound{}} -> + {ok, general_error(404, <<"Event not found">>)}; + {exception, #'InvalidRequest'{errors = Errors}} -> + FormattedErrors = capi_handler_utils:format_request_errors(Errors), + {ok, logic_error('invalidRequest', FormattedErrors)} end end, {ok, #{authorize => Authorize, process => Process}}; prepare('GetInvoicePaymentMethods' = OperationID, Req, Context) -> - InvoiceID = maps:get(invoiceID, Req), + InvoiceID = maps:get('invoiceID', Req), ResultInvoice = map_service_result(capi_handler_utils:get_invoice_by_id(InvoiceID, Context)), Authorize = fun() -> Prototypes = [ @@ -266,13 +252,10 @@ prepare('GetInvoicePaymentMethods' = OperationID, Req, Context) -> PaymentMethods1 = capi_utils:deduplicate_payment_methods(PaymentMethods0), PaymentMethods = capi_handler_utils:emplace_token_provider_data(Invoice, PaymentMethods1, Context), {ok, {200, #{}, PaymentMethods}}; - {exception, Exception} -> - case Exception of - #payproc_InvalidUser{} -> - {ok, general_error(404, <<"Invoice not found">>)}; - #payproc_InvoiceNotFound{} -> - {ok, general_error(404, <<"Invoice not found">>)} - end + {exception, #payproc_InvalidUser{}} -> + {ok, general_error(404, <<"Invoice not found">>)}; + {exception, #payproc_InvoiceNotFound{}} -> + {ok, general_error(404, <<"Invoice not found">>)} end end, {ok, #{authorize => Authorize, process => Process}}; @@ -448,7 +431,7 @@ decode_refund_change(InvoiceID, PaymentID, _RefundID, {invoice_payment_refund_cr <<"paymentID">> => PaymentID, <<"refund">> => decode_refund_for_event(Refund, InvoiceID, PaymentID, Context) }; -decode_refund_change(_, PaymentID, RefundID, {invoice_payment_refund_status_changed, StatusChanged}, Context) -> +decode_refund_change(_, PaymentID, RefundID, {invoice_payment_refund_status_changed, StatusChanged}, _Context) -> #payproc_InvoicePaymentRefundStatusChanged{status = Status} = StatusChanged, capi_handler_utils:merge_and_compact( #{ @@ -456,18 +439,18 @@ decode_refund_change(_, PaymentID, RefundID, {invoice_payment_refund_status_chan <<"paymentID">> => PaymentID, <<"refundID">> => RefundID }, - capi_handler_decoder_invoicing:decode_refund_status(Status, Context) + capi_handler_decoder_invoicing:decode_refund_status(Status) ); decode_refund_change(_, _, _, _, _) -> undefined. -decode_refund_for_event(#domain_InvoicePaymentRefund{cash = #domain_Cash{}} = Refund, _, _, Context) -> - capi_handler_decoder_invoicing:decode_refund(Refund, Context); +decode_refund_for_event(#domain_InvoicePaymentRefund{cash = #domain_Cash{}} = Refund, _, _, _Context) -> + capi_handler_decoder_invoicing:decode_refund(Refund); decode_refund_for_event(#domain_InvoicePaymentRefund{cash = undefined} = Refund, InvoiceID, PaymentID, Context) -> % Need to fix it! {ok, #payproc_InvoicePayment{payment = #domain_InvoicePayment{cost = Cash}}} = capi_handler_utils:get_payment_by_id(InvoiceID, PaymentID, Context), - capi_handler_decoder_invoicing:decode_refund(Refund#domain_InvoicePaymentRefund{cash = Cash}, Context). + capi_handler_decoder_invoicing:decode_refund(Refund#domain_InvoicePaymentRefund{cash = Cash}). get_invoice_by_external_id(ExternalID, #{woody_context := WoodyContext} = Context) -> PartyID = capi_handler_utils:get_party_id(Context), diff --git a/apps/capi/src/capi_handler_parties.erl b/apps/capi/src/capi_handler_parties.erl index de31c28..cfac988 100644 --- a/apps/capi/src/capi_handler_parties.erl +++ b/apps/capi/src/capi_handler_parties.erl @@ -72,7 +72,7 @@ prepare('SuspendMyParty' = OperationID, _Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare('GetPartyByID' = OperationID, Req, Context) -> - PartyID = maps:get(partyID, Req), + PartyID = maps:get('partyID', Req), Authorize = fun() -> Prototypes = [{operation, #{id => OperationID, party => PartyID}}], {ok, mask_party_notfound(capi_auth:authorize_operation(Prototypes, Context))} @@ -90,7 +90,7 @@ prepare('GetPartyByID' = OperationID, Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare('ActivatePartyByID' = OperationID, Req, Context) -> - PartyID = maps:get(partyID, Req), + PartyID = maps:get('partyID', Req), Authorize = fun() -> Prototypes = [{operation, #{id => OperationID, party => PartyID}}], {ok, capi_auth:authorize_operation(Prototypes, Context)} @@ -109,7 +109,7 @@ prepare('ActivatePartyByID' = OperationID, Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare('SuspendPartyByID' = OperationID, Req, Context) -> - PartyID = maps:get(partyID, Req), + PartyID = maps:get('partyID', Req), Authorize = fun() -> Prototypes = [{operation, #{id => OperationID, party => PartyID}}], {ok, capi_auth:authorize_operation(Prototypes, Context)} diff --git a/apps/capi/src/capi_handler_payment_institutions.erl b/apps/capi/src/capi_handler_payment_institutions.erl index 5a072df..8159549 100644 --- a/apps/capi/src/capi_handler_payment_institutions.erl +++ b/apps/capi/src/capi_handler_payment_institutions.erl @@ -8,7 +8,7 @@ -import(capi_handler_utils, [general_error/2, logic_error/2]). --define(payment_institution_ref(PaymentInstitutionID), #domain_PaymentInstitutionRef{id = PaymentInstitutionID}). +-define(PAYMENT_INSTITUTION_REF(PaymentInstitutionID), #domain_PaymentInstitutionRef{id = PaymentInstitutionID}). -spec prepare( OperationID :: capi_handler:operation_id(), @@ -22,33 +22,22 @@ prepare(OperationID = 'GetPaymentInstitutions', Req, Context) -> Residence = capi_handler_encoder:encode_residence(genlib_map:get(residence, Req)), Realm = genlib_map:get(realm, Req), {ok, PaymentInstObjects} = capi_domain:get_payment_institutions(Context), - Resp = - lists:filtermap( - fun(P) -> - case check_payment_institution(Realm, Residence, P) of - true -> - {true, decode_payment_institution_obj(P)}; - false -> - false - end - end, - PaymentInstObjects - ), + Resp = filter_payment_institutions(Realm, Residence, PaymentInstObjects), {ok, {200, #{}, Resp}} catch throw:{encode_residence, invalid_residence} -> - {ok, logic_error(invalidRequest, <<"Invalid residence">>)} + {ok, logic_error('invalidRequest', <<"Invalid residence">>)} end end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetPaymentInstitutionByRef', Req, Context) -> Authorize = mk_authorize_operation(OperationID, Context), Process = fun() -> - PaymentInstitutionID = genlib:to_int(maps:get(paymentInstitutionID, Req)), - PaymentInstitutionRef = ?payment_institution_ref(PaymentInstitutionID), + PaymentInstitutionID = genlib:to_int(maps:get('paymentInstitutionID', Req)), + PaymentInstitutionRef = ?PAYMENT_INSTITUTION_REF(PaymentInstitutionID), case capi_domain:get({payment_institution, PaymentInstitutionRef}, Context) of {ok, PaymentInstitution} -> - {ok, {200, #{}, decode_payment_institution_obj(PaymentInstitution)}}; + {ok, {200, #{}, decode_payment_institution(PaymentInstitution)}}; {error, not_found} -> {ok, general_error(404, <<"Payment institution not found">>)} end @@ -57,7 +46,7 @@ prepare(OperationID = 'GetPaymentInstitutionByRef', Req, Context) -> prepare(OperationID = 'GetPaymentInstitutionPaymentTerms', Req, Context) -> Authorize = mk_authorize_operation(OperationID, Context), Process = fun() -> - PaymentInstitutionID = genlib:to_int(maps:get(paymentInstitutionID, Req)), + PaymentInstitutionID = genlib:to_int(maps:get('paymentInstitutionID', Req)), case compute_payment_institution_terms(PaymentInstitutionID, #payproc_Varset{}, Context) of {ok, #domain_TermSet{payments = PaymentTerms}} -> {ok, {200, #{}, decode_payment_terms(PaymentTerms)}}; @@ -69,7 +58,7 @@ prepare(OperationID = 'GetPaymentInstitutionPaymentTerms', Req, Context) -> prepare(OperationID = 'GetPaymentInstitutionPayoutMethods', Req, Context) -> Authorize = mk_authorize_operation(OperationID, Context), Process = fun() -> - PaymentInstitutionID = genlib:to_int(maps:get(paymentInstitutionID, Req)), + PaymentInstitutionID = genlib:to_int(maps:get('paymentInstitutionID', Req)), case compute_payment_institution_terms(PaymentInstitutionID, prepare_request_varset(Req, Context), Context) of {ok, #domain_TermSet{payouts = #domain_PayoutsServiceTerms{payout_methods = PayoutMethods}}} -> {ok, {200, #{}, decode_payout_methods_selector(PayoutMethods)}}; @@ -83,7 +72,7 @@ prepare(OperationID = 'GetPaymentInstitutionPayoutMethods', Req, Context) -> prepare(OperationID = 'GetPaymentInstitutionPayoutSchedules', Req, Context) -> Authorize = mk_authorize_operation(OperationID, Context), Process = fun() -> - PaymentInstitutionID = genlib:to_int(maps:get(paymentInstitutionID, Req)), + PaymentInstitutionID = genlib:to_int(maps:get('paymentInstitutionID', Req)), case compute_payment_institution_terms(PaymentInstitutionID, prepare_request_varset(Req, Context), Context) of {ok, #domain_TermSet{payouts = #domain_PayoutsServiceTerms{payout_schedules = Schedules}}} -> {ok, {200, #{}, decode_business_schedules_selector(Schedules)}}; @@ -94,6 +83,19 @@ prepare(OperationID = 'GetPaymentInstitutionPayoutSchedules', Req, Context) -> end end, {ok, #{authorize => Authorize, process => Process}}; +prepare(OperationID = 'GetServiceProviderByID', Req, Context) -> + Authorize = mk_authorize_operation(OperationID, Context), + Process = fun() -> + ServiceProviderID = maps:get('serviceProviderID', Req), + PaymentServiceRef = {payment_service, #domain_PaymentServiceRef{id = ServiceProviderID}}, + case capi_domain:get(PaymentServiceRef, Context) of + {ok, #domain_PaymentServiceObject{data = PaymentService}} -> + {ok, {200, #{}, decode_payment_service(ServiceProviderID, PaymentService)}}; + {error, not_found} -> + {ok, general_error(404, <<"Service provider not found">>)} + end + end, + {ok, #{authorize => Authorize, process => Process}}; prepare(_OperationID, _Req, _Context) -> {error, noimpl}. @@ -107,6 +109,19 @@ mk_authorize_operation(OperationID, Context) -> {ok, capi_auth:authorize_operation(Prototypes, Context)} end. +filter_payment_institutions(Realm, Residence, PaymentInstObjects) -> + lists:filtermap( + fun(P) -> + case check_payment_institution(Realm, Residence, P) of + true -> + {true, decode_payment_institution(P)}; + false -> + false + end + end, + PaymentInstObjects + ). + check_payment_institution(Realm, Residence, PaymentInstitution) -> check_payment_institution_realm(Realm, PaymentInstitution) andalso check_payment_institution_residence(Residence, PaymentInstitution). @@ -126,13 +141,13 @@ check_payment_institution_residence(Residence, #domain_PaymentInstitutionObject{ ordsets:is_element(Residence, Residences). compute_payment_institution_terms(PaymentInstitutionID, VS, Context) -> - Ref = ?payment_institution_ref(PaymentInstitutionID), + Ref = ?PAYMENT_INSTITUTION_REF(PaymentInstitutionID), capi_party:compute_payment_institution_terms(Ref, VS, Context). prepare_request_varset(Req, Context) -> #payproc_Varset{ - currency = encode_optional_currency(genlib_map:get(currency, Req)), - payout_method = encode_optional_payout_method(genlib_map:get(payoutMethod, Req)), + currency = encode_optional_currency(genlib_map:get('currency', Req)), + payout_method = encode_optional_payout_method(genlib_map:get('payoutMethod', Req)), party_id = capi_handler_utils:get_party_id(Context) }. @@ -154,7 +169,7 @@ encode_optional_currency(SymbolicCode) -> capi_handler_encoder:encode_currency(S % -decode_payment_institution_obj(#domain_PaymentInstitutionObject{ref = Ref, data = Data}) -> +decode_payment_institution(#domain_PaymentInstitutionObject{ref = Ref, data = Data}) -> genlib_map:compact(#{ <<"id">> => Ref#domain_PaymentInstitutionRef.id, <<"name">> => Data#domain_PaymentInstitution.name, @@ -197,3 +212,16 @@ decode_business_schedules_selector({value, Val}) when is_list(Val) -> lists:map(fun capi_handler_decoder_utils:decode_business_schedule_ref/1, Val); decode_business_schedules_selector(_) -> []. + +%% + +decode_payment_service(ID, PaymentService = #domain_PaymentService{}) -> + genlib_map:compact(#{ + <<"id">> => ID, + <<"brandName">> => PaymentService#domain_PaymentService.brand_name, + <<"category">> => PaymentService#domain_PaymentService.category, + <<"metadata">> => capi_utils:maybe( + PaymentService#domain_PaymentService.metadata, + fun capi_handler_decoder_utils:decode_namespaced_metadata/1 + ) + }). diff --git a/apps/capi/src/capi_handler_payments.erl b/apps/capi/src/capi_handler_payments.erl index 4a34d0f..3349644 100644 --- a/apps/capi/src/capi_handler_payments.erl +++ b/apps/capi/src/capi_handler_payments.erl @@ -16,7 +16,7 @@ Context :: capi_handler:processing_context() ) -> {ok, capi_handler:request_state()} | {error, noimpl}. prepare(OperationID = 'CreatePayment', Req, Context) -> - InvoiceID = maps:get(invoiceID, Req), + InvoiceID = maps:get('invoiceID', Req), Invoice = get_invoice_by_id(InvoiceID, Context), PaymentParams = maps:get('PaymentParams', Req), Authorize = fun() -> @@ -35,26 +35,20 @@ prepare(OperationID = 'CreatePayment', Req, Context) -> {ok, Payment} -> {ok, {201, #{}, decode_invoice_payment(InvoiceID, Payment, Context)}}; {exception, #payproc_InvalidInvoiceStatus{}} -> - {ok, logic_error(invalidInvoiceStatus, <<"Invalid invoice status">>)}; + {ok, logic_error('invalidInvoiceStatus', <<"Invalid invoice status">>)}; {exception, #payproc_InvoicePaymentPending{}} -> - ErrorResp = logic_error( - invoicePaymentPending, - <<"Invoice payment pending">> - ), - {ok, ErrorResp}; + {ok, logic_error('invoicePaymentPending', <<"Invoice payment pending">>)}; {exception, #'InvalidRequest'{errors = Errors}} -> FormattedErrors = capi_handler_utils:format_request_errors(Errors), - {ok, logic_error(invalidRequest, FormattedErrors)}; + {ok, logic_error('invalidRequest', FormattedErrors)}; {exception, #payproc_InvalidPartyStatus{}} -> - {ok, logic_error(invalidPartyStatus, <<"Invalid party status">>)}; + {ok, logic_error('invalidPartyStatus', <<"Invalid party status">>)}; {exception, #payproc_InvalidShopStatus{}} -> - {ok, logic_error(invalidShopStatus, <<"Invalid shop status">>)}; + {ok, logic_error('invalidShopStatus', <<"Invalid shop status">>)}; {exception, #payproc_InvalidContractStatus{}} -> - ErrorResp = logic_error(invalidContractStatus, <<"Invalid contract status">>), - {ok, ErrorResp}; + {ok, logic_error('invalidContractStatus', <<"Invalid contract status">>)}; {exception, #payproc_InvalidRecurrentParentPayment{}} -> - ErrorResp = logic_error(invalidRecurrentParent, <<"Specified recurrent parent is invalid">>), - {ok, ErrorResp}; + {ok, logic_error('invalidRecurrentParent', <<"Specified recurrent parent is invalid">>)}; {exception, #payproc_InvalidUser{}} -> {ok, general_error(404, <<"Invoice not found">>)}; {exception, #payproc_InvoiceNotFound{}} -> @@ -62,24 +56,16 @@ prepare(OperationID = 'CreatePayment', Req, Context) -> end catch throw:invalid_payment_session -> - {ok, - logic_error( - invalidPaymentSession, - <<"Specified payment session is invalid">> - )}; + {ok, logic_error('invalidPaymentSession', <<"Specified payment session is invalid">>)}; throw:invalid_processing_deadline -> - {ok, - logic_error( - invalidProcessingDeadline, - <<"Specified processing deadline is invalid">> - )}; + {ok, logic_error('invalidProcessingDeadline', <<"Specified processing deadline is invalid">>)}; throw:{external_id_conflict, PaymentID, ExternalID, _Schema} -> - {ok, logic_error(externalIDConflict, {PaymentID, ExternalID})} + {ok, logic_error('externalIDConflict', {PaymentID, ExternalID})} end end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetPayments', Req, Context) -> - InvoiceID = maps:get(invoiceID, Req), + InvoiceID = maps:get('invoiceID', Req), Invoice = get_invoice_by_id(InvoiceID, Context), Authorize = fun() -> Prototypes = [ @@ -95,8 +81,8 @@ prepare(OperationID = 'GetPayments', Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetPaymentByID', Req, Context) -> - InvoiceID = maps:get(invoiceID, Req), - PaymentID = maps:get(paymentID, Req), + InvoiceID = maps:get('invoiceID', Req), + PaymentID = maps:get('paymentID', Req), Invoice = get_invoice_by_id(InvoiceID, Context), Authorize = fun() -> Prototypes = [ @@ -116,7 +102,7 @@ prepare(OperationID = 'GetPaymentByID', Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetPaymentByExternalID', Req, Context) -> - ExternalID = maps:get(externalID, Req), + ExternalID = maps:get('externalID', Req), InternalID = get_payment_by_external_id(ExternalID, Context), Invoice = maybe( InternalID, @@ -150,8 +136,8 @@ prepare(OperationID = 'GetPaymentByExternalID', Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'CapturePayment', Req, Context) -> - InvoiceID = maps:get(invoiceID, Req), - PaymentID = maps:get(paymentID, Req), + InvoiceID = maps:get('invoiceID', Req), + PaymentID = maps:get('paymentID', Req), PartyID = capi_handler_utils:get_party_id(Context), Invoice = get_invoice_by_id(InvoiceID, Context), Authorize = fun() -> @@ -178,62 +164,55 @@ prepare(OperationID = 'CapturePayment', Req, Context) -> of {ok, _} -> {ok, {202, #{}, undefined}}; - {exception, Exception} -> - case Exception of - #payproc_InvoicePaymentNotFound{} -> - {ok, general_error(404, <<"Payment not found">>)}; - #payproc_InvalidPaymentStatus{} -> - {ok, logic_error(invalidPaymentStatus, <<"Invalid payment status">>)}; - #payproc_InvalidUser{} -> - {ok, general_error(404, <<"Invoice not found">>)}; - #payproc_InvoiceNotFound{} -> - {ok, general_error(404, <<"Invoice not found">>)}; - #'InvalidRequest'{errors = Errors} -> - FormattedErrors = capi_handler_utils:format_request_errors(Errors), - {ok, logic_error(invalidRequest, FormattedErrors)}; - #payproc_OperationNotPermitted{} -> - ErrorResp = logic_error( - operationNotPermitted, - <<"Operation not permitted">> - ), - {ok, ErrorResp}; - #payproc_InvalidPartyStatus{} -> - {ok, logic_error(invalidPartyStatus, <<"Invalid party status">>)}; - #payproc_InvalidShopStatus{} -> - {ok, logic_error(invalidShopStatus, <<"Invalid shop status">>)}; - #payproc_InconsistentCaptureCurrency{payment_currency = PaymentCurrency} -> - {ok, - logic_error( - inconsistentCaptureCurrency, - io_lib:format("Correct currency: ~p", [PaymentCurrency]) - )}; - #payproc_AmountExceededCaptureBalance{payment_amount = PaymentAmount} -> - {ok, - logic_error( - amountExceededCaptureBalance, - io_lib:format("Max amount: ~p", [PaymentAmount]) - )}; - #payproc_AllocationNotAllowed{} -> - {ok, logic_error(allocationNotPermitted, <<"Not allowed">>)}; - #payproc_AllocationExceededPaymentAmount{} -> - {ok, logic_error(invalidAllocation, <<"Exceeded payment amount">>)}; - #payproc_AllocationInvalidTransaction{} = InvalidTransaction -> - Message = capi_allocation:transaction_error(InvalidTransaction), - {ok, logic_error(invalidAllocation, Message)} - end + {exception, #payproc_InvoicePaymentNotFound{}} -> + {ok, general_error(404, <<"Payment not found">>)}; + {exception, #payproc_InvalidPaymentStatus{}} -> + {ok, logic_error('invalidPaymentStatus', <<"Invalid payment status">>)}; + {exception, #payproc_InvalidUser{}} -> + {ok, general_error(404, <<"Invoice not found">>)}; + {exception, #payproc_InvoiceNotFound{}} -> + {ok, general_error(404, <<"Invoice not found">>)}; + {exception, #'InvalidRequest'{errors = Errors}} -> + FormattedErrors = capi_handler_utils:format_request_errors(Errors), + {ok, logic_error('invalidRequest', FormattedErrors)}; + {exception, #payproc_OperationNotPermitted{}} -> + {ok, logic_error('operationNotPermitted', <<"Operation not permitted">>)}; + {exception, #payproc_InvalidPartyStatus{}} -> + {ok, logic_error('invalidPartyStatus', <<"Invalid party status">>)}; + {exception, #payproc_InvalidShopStatus{}} -> + {ok, logic_error('invalidShopStatus', <<"Invalid shop status">>)}; + {exception, #payproc_InconsistentCaptureCurrency{payment_currency = PaymentCurrency}} -> + {ok, + logic_error( + 'inconsistentCaptureCurrency', + io_lib:format("Correct currency: ~p", [PaymentCurrency]) + )}; + {exception, #payproc_AmountExceededCaptureBalance{payment_amount = PaymentAmount}} -> + {ok, + logic_error( + 'amountExceededCaptureBalance', + io_lib:format("Max amount: ~p", [PaymentAmount]) + )}; + {exception, #payproc_AllocationNotAllowed{}} -> + {ok, logic_error('allocationNotPermitted', <<"Not allowed">>)}; + {exception, #payproc_AllocationExceededPaymentAmount{}} -> + {ok, logic_error('invalidAllocation', <<"Exceeded payment amount">>)}; + {exception, #payproc_AllocationInvalidTransaction{} = InvalidTransaction} -> + Message = capi_allocation:transaction_error(InvalidTransaction), + {ok, logic_error('invalidAllocation', Message)} catch throw:invoice_cart_empty -> - {ok, logic_error(invalidInvoiceCart, <<"Wrong size. Path to item: cart">>)}; + {ok, logic_error('invalidInvoiceCart', <<"Wrong size. Path to item: cart">>)}; throw:allocation_wrong_cart -> - {ok, logic_error(invalidAllocation, <<"Wrong cart">>)}; + {ok, logic_error('invalidAllocation', <<"Wrong cart">>)}; throw:allocation_duplicate -> - {ok, logic_error(invalidAllocation, <<"Duplicate shop">>)} + {ok, logic_error('invalidAllocation', <<"Duplicate shop">>)} end end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'CancelPayment', Req, Context) -> - InvoiceID = maps:get(invoiceID, Req), - PaymentID = maps:get(paymentID, Req), + InvoiceID = maps:get('invoiceID', Req), + PaymentID = maps:get('paymentID', Req), Authorize = fun() -> Prototypes = [ {operation, #{id => OperationID, invoice => InvoiceID, payment => PaymentID}}, @@ -248,36 +227,29 @@ prepare(OperationID = 'CancelPayment', Req, Context) -> case capi_handler_utils:service_call_with([user_info], Call, Context) of {ok, _} -> {ok, {202, #{}, undefined}}; - {exception, Exception} -> - case Exception of - #payproc_InvoicePaymentNotFound{} -> - {ok, general_error(404, <<"Payment not found">>)}; - #payproc_InvalidPaymentStatus{} -> - {ok, logic_error(invalidPaymentStatus, <<"Invalid payment status">>)}; - #payproc_InvalidUser{} -> - {ok, general_error(404, <<"Invoice not found">>)}; - #payproc_InvoiceNotFound{} -> - {ok, general_error(404, <<"Invoice not found">>)}; - #'InvalidRequest'{errors = Errors} -> - FormattedErrors = capi_handler_utils:format_request_errors(Errors), - {ok, logic_error(invalidRequest, FormattedErrors)}; - #payproc_OperationNotPermitted{} -> - ErrorResp = logic_error( - operationNotPermitted, - <<"Operation not permitted">> - ), - {ok, ErrorResp}; - #payproc_InvalidPartyStatus{} -> - {ok, logic_error(invalidPartyStatus, <<"Invalid party status">>)}; - #payproc_InvalidShopStatus{} -> - {ok, logic_error(invalidShopStatus, <<"Invalid shop status">>)} - end + {exception, #payproc_InvoicePaymentNotFound{}} -> + {ok, general_error(404, <<"Payment not found">>)}; + {exception, #payproc_InvalidPaymentStatus{}} -> + {ok, logic_error('invalidPaymentStatus', <<"Invalid payment status">>)}; + {exception, #payproc_InvalidUser{}} -> + {ok, general_error(404, <<"Invoice not found">>)}; + {exception, #payproc_InvoiceNotFound{}} -> + {ok, general_error(404, <<"Invoice not found">>)}; + {exception, #'InvalidRequest'{errors = Errors}} -> + FormattedErrors = capi_handler_utils:format_request_errors(Errors), + {ok, logic_error('invalidRequest', FormattedErrors)}; + {exception, #payproc_OperationNotPermitted{}} -> + {ok, logic_error('operationNotPermitted', <<"Operation not permitted">>)}; + {exception, #payproc_InvalidPartyStatus{}} -> + {ok, logic_error('invalidPartyStatus', <<"Invalid party status">>)}; + {exception, #payproc_InvalidShopStatus{}} -> + {ok, logic_error('invalidShopStatus', <<"Invalid shop status">>)} end end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'CreateRefund', Req, Context) -> - InvoiceID = maps:get(invoiceID, Req), - PaymentID = maps:get(paymentID, Req), + InvoiceID = maps:get('invoiceID', Req), + PaymentID = maps:get('paymentID', Req), RefundParams = maps:get('RefundParams', Req), Authorize = fun() -> Prototypes = [ @@ -292,85 +264,62 @@ prepare(OperationID = 'CreateRefund', Req, Context) -> create_refund(InvoiceID, PaymentID, RefundParams, Context, OperationID) of {ok, Refund} -> - {ok, {201, #{}, capi_handler_decoder_invoicing:decode_refund(Refund, Context)}}; - {exception, Exception} -> - case Exception of - #payproc_InvalidUser{} -> - {ok, general_error(404, <<"Invoice not found">>)}; - #payproc_InvoicePaymentNotFound{} -> - {ok, general_error(404, <<"Payment not found">>)}; - #payproc_InvoiceNotFound{} -> - {ok, general_error(404, <<"Invoice not found">>)}; - #payproc_InvalidPartyStatus{} -> - {ok, logic_error(invalidPartyStatus, <<"Invalid party status">>)}; - #payproc_InvalidShopStatus{} -> - {ok, logic_error(invalidShopStatus, <<"Invalid shop status">>)}; - #payproc_InvalidContractStatus{} -> - ErrorResp = logic_error( - invalidContractStatus, - <<"Invalid contract status">> - ), - {ok, ErrorResp}; - #payproc_OperationNotPermitted{} -> - ErrorResp = logic_error( - operationNotPermitted, - <<"Operation not permitted">> - ), - {ok, ErrorResp}; - #payproc_InvalidPaymentStatus{} -> - ErrorResp = logic_error( - invalidPaymentStatus, - <<"Invalid invoice payment status">> - ), - {ok, ErrorResp}; - #payproc_InsufficientAccountBalance{} -> - ErrResp = logic_error( - insufficentAccountBalance, - <<"Operation can not be conducted because of insufficient funds on the merchant account">> - ), - {ok, ErrResp}; - #payproc_InvoicePaymentAmountExceeded{} -> - ErrorResp = logic_error( - invoicePaymentAmountExceeded, - <<"Payment amount exceeded">> - ), - {ok, ErrorResp}; - #payproc_InconsistentRefundCurrency{} -> - ErrorResp = logic_error( - inconsistentRefundCurrency, - <<"Inconsistent refund currency">> - ), - {ok, ErrorResp}; - #'InvalidRequest'{errors = Errors} -> - FormattedErrors = capi_handler_utils:format_request_errors(Errors), - {ok, logic_error(invalidRequest, FormattedErrors)}; - #payproc_AllocationNotAllowed{} -> - {ok, logic_error(allocationNotPermitted, <<"Not allowed">>)}; - #payproc_AllocationExceededPaymentAmount{} -> - {ok, logic_error(invalidAllocation, <<"Exceeded payment amount">>)}; - #payproc_AllocationInvalidTransaction{} = InvalidTransaction -> - Message = capi_allocation:transaction_error(InvalidTransaction), - {ok, logic_error(invalidAllocation, Message)}; - #payproc_AllocationNotFound{} -> - {ok, logic_error(invalidAllocation, <<"Not found">>)} - end + {ok, {201, #{}, capi_handler_decoder_invoicing:decode_refund(Refund)}}; + {exception, #payproc_InvalidUser{}} -> + {ok, general_error(404, <<"Invoice not found">>)}; + {exception, #payproc_InvoicePaymentNotFound{}} -> + {ok, general_error(404, <<"Payment not found">>)}; + {exception, #payproc_InvoiceNotFound{}} -> + {ok, general_error(404, <<"Invoice not found">>)}; + {exception, #payproc_InvalidPartyStatus{}} -> + {ok, logic_error('invalidPartyStatus', <<"Invalid party status">>)}; + {exception, #payproc_InvalidShopStatus{}} -> + {ok, logic_error('invalidShopStatus', <<"Invalid shop status">>)}; + {exception, #payproc_InvalidContractStatus{}} -> + {ok, logic_error('invalidContractStatus', <<"Invalid contract status">>)}; + {exception, #payproc_OperationNotPermitted{}} -> + {ok, logic_error('operationNotPermitted', <<"Operation not permitted">>)}; + {exception, #payproc_InvalidPaymentStatus{}} -> + {ok, logic_error('invalidPaymentStatus', <<"Invalid invoice payment status">>)}; + {exception, #payproc_InsufficientAccountBalance{}} -> + ErrResp = logic_error( + 'insufficentAccountBalance', + <<"Operation can not be conducted because of insufficient funds on the merchant account">> + ), + {ok, ErrResp}; + {exception, #payproc_InvoicePaymentAmountExceeded{}} -> + {ok, logic_error('invoicePaymentAmountExceeded', <<"Payment amount exceeded">>)}; + {exception, #payproc_InconsistentRefundCurrency{}} -> + {ok, logic_error('inconsistentRefundCurrency', <<"Inconsistent refund currency">>)}; + {exception, #'InvalidRequest'{errors = Errors}} -> + FormattedErrors = capi_handler_utils:format_request_errors(Errors), + {ok, logic_error('invalidRequest', FormattedErrors)}; + {exception, #payproc_AllocationNotAllowed{}} -> + {ok, logic_error('allocationNotPermitted', <<"Not allowed">>)}; + {exception, #payproc_AllocationExceededPaymentAmount{}} -> + {ok, logic_error('invalidAllocation', <<"Exceeded payment amount">>)}; + {exception, #payproc_AllocationInvalidTransaction{} = InvalidTransaction} -> + Message = capi_allocation:transaction_error(InvalidTransaction), + {ok, logic_error('invalidAllocation', Message)}; + {exception, #payproc_AllocationNotFound{}} -> + {ok, logic_error('invalidAllocation', <<"Not found">>)} catch throw:invoice_cart_empty -> - {ok, logic_error(invalidInvoiceCart, <<"Wrong size. Path to item: cart">>)}; + {ok, logic_error('invalidInvoiceCart', <<"Wrong size. Path to item: cart">>)}; throw:{external_id_conflict, RefundID, ExternalID, _Schema} -> - {ok, logic_error(externalIDConflict, {RefundID, ExternalID})}; + {ok, logic_error('externalIDConflict', {RefundID, ExternalID})}; throw:allocation_duplicate -> - {ok, logic_error(invalidAllocation, <<"Duplicate shop">>)}; + {ok, logic_error('invalidAllocation', <<"Duplicate shop">>)}; throw:allocation_wrong_cart -> - {ok, logic_error(invalidAllocation, <<"Wrong cart">>)}; + {ok, logic_error('invalidAllocation', <<"Wrong cart">>)}; throw:refund_cart_conflict -> - {ok, logic_error(refundCartConflict, <<"Inconsistent Refund Cart">>)} + {ok, logic_error('refundCartConflict', <<"Inconsistent Refund Cart">>)} end end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetRefunds', Req, Context) -> - InvoiceID = maps:get(invoiceID, Req), - PaymentID = maps:get(paymentID, Req), + InvoiceID = maps:get('invoiceID', Req), + PaymentID = maps:get('paymentID', Req), Invoice = get_invoice_by_id(InvoiceID, Context), Authorize = fun() -> Prototypes = [ @@ -385,7 +334,7 @@ prepare(OperationID = 'GetRefunds', Req, Context) -> #payproc_InvoicePayment{refunds = Refunds} -> {ok, {200, #{}, [ - capi_handler_decoder_invoicing:decode_refund(R, Context) + capi_handler_decoder_invoicing:decode_refund(R) || #payproc_InvoicePaymentRefund{refund = R} <- Refunds ]}}; undefined -> @@ -394,9 +343,9 @@ prepare(OperationID = 'GetRefunds', Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetRefundByID', Req, Context) -> - InvoiceID = maps:get(invoiceID, Req), - PaymentID = maps:get(paymentID, Req), - RefundID = maps:get(refundID, Req), + InvoiceID = maps:get('invoiceID', Req), + PaymentID = maps:get('paymentID', Req), + RefundID = maps:get('refundID', Req), Invoice = get_invoice_by_id(InvoiceID, Context), Payment = find_payment_by_id(PaymentID, Invoice), Authorize = fun() -> @@ -410,17 +359,16 @@ prepare(OperationID = 'GetRefundByID', Req, Context) -> Process = fun() -> capi_handler:respond_if_undefined(Invoice, general_error(404, <<"Invoice not found">>)), capi_handler:respond_if_undefined(Payment, general_error(404, <<"Payment not found">>)), - case find_refund_by_id(RefundID, Payment) of #payproc_InvoicePaymentRefund{refund = Refund} -> - {ok, {200, #{}, capi_handler_decoder_invoicing:decode_refund(Refund, Context)}}; + {ok, {200, #{}, capi_handler_decoder_invoicing:decode_refund(Refund)}}; undefined -> {ok, general_error(404, <<"Invoice payment refund not found">>)} end end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetRefundByExternalID', Req, Context) -> - ExternalID = maps:get(externalID, Req), + ExternalID = maps:get('externalID', Req), InternalID = get_refund_by_external_id(ExternalID, Context), Invoice = maybe( InternalID, @@ -449,15 +397,15 @@ prepare(OperationID = 'GetRefundByExternalID', Req, Context) -> capi_handler:respond_if_undefined(Payment, general_error(404, <<"Payment not found">>)), case find_refund_by_id(RefundID, Payment) of #payproc_InvoicePaymentRefund{refund = Refund} -> - {ok, {200, #{}, capi_handler_decoder_invoicing:decode_refund(Refund, Context)}}; + {ok, {200, #{}, capi_handler_decoder_invoicing:decode_refund(Refund)}}; undefined -> {ok, general_error(404, <<"Invoice payment refund not found">>)} end end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetChargebacks', Req, Context) -> - InvoiceID = maps:get(invoiceID, Req), - PaymentID = maps:get(paymentID, Req), + InvoiceID = maps:get('invoiceID', Req), + PaymentID = maps:get('paymentID', Req), Invoice = get_invoice_by_id(InvoiceID, Context), Authorize = fun() -> Prototypes = [ @@ -480,9 +428,9 @@ prepare(OperationID = 'GetChargebacks', Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetChargebackByID', Req, Context) -> - InvoiceID = maps:get(invoiceID, Req), - PaymentID = maps:get(paymentID, Req), - ChargebackID = maps:get(chargebackID, Req), + InvoiceID = maps:get('invoiceID', Req), + PaymentID = maps:get('paymentID', Req), + ChargebackID = maps:get('chargebackID', Req), Invoice = get_invoice_by_id(InvoiceID, Context), Payment = find_payment_by_id(PaymentID, Invoice), Authorize = fun() -> @@ -541,10 +489,6 @@ create_payment_id(Invoice, PaymentParams0, Context, OperationID, PaymentToolThri Payer = maps:get(<<"payer">>, PaymentParams0), PaymentTool = capi_utils:maybe(PaymentToolThrift, fun capi_handler_decoder_party:decode_payment_tool/1), - % Temporary decision for analytics team - % TODO: delete this after analytics research will be down - _ = log_payer_client_url(Payer, InvoiceID), - PaymentParams = PaymentParams0#{ % Требуется для последующей кодировки параметров плательщика <<"invoiceID">> => InvoiceID, @@ -563,20 +507,6 @@ create_payment_id(Invoice, PaymentParams0, Context, OperationID, PaymentToolThri CtxData = #{<<"invoice_id">> => InvoiceID}, capi_bender:try_gen_sequence(IdempotentKey, Identity, SequenceID, SequenceParams, WoodyCtx, CtxData). -log_payer_client_url(#{<<"payerType">> := <<"PaymentResourcePayer">>} = Payer, InvoiceID) -> - EncodedSession = maps:get(<<"paymentSession">>, Payer), - {ClientInfo, _} = capi_handler_utils:unwrap_payment_session(EncodedSession), - ClientUrl = maps:get(<<"url">>, ClientInfo, undefined), - ClientIP = maps:get(<<"ip">>, ClientInfo, undefined), - MetaInfo = genlib_map:compact(#{ - invoice_id => InvoiceID, - ip => ClientIP, - client_url => ClientUrl - }), - logger:info("Request location info.", [], MetaInfo); -log_payer_client_url(_, _) -> - skipped. - find_payment_by_id(PaymentID, #payproc_Invoice{payments = Payments}) -> Fun = fun(#payproc_InvoicePayment{payment = #domain_InvoicePayment{id = ID}}) -> PaymentID == ID @@ -717,15 +647,15 @@ decode_payment_token(#{<<"paymentToolToken">> := Token}) -> 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)); + capi_handler:respond(logic_error('invalidPaymentToolToken')); _ -> TokenData end; unrecognized -> - capi_handler:respond(logic_error(invalidPaymentToolToken)); + 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)) + capi_handler:respond(logic_error('invalidPaymentToolToken')) end; decode_payment_token(_Other) -> undefined. diff --git a/apps/capi/src/capi_handler_payouts.erl b/apps/capi/src/capi_handler_payouts.erl index dd02341..b8a4b75 100644 --- a/apps/capi/src/capi_handler_payouts.erl +++ b/apps/capi/src/capi_handler_payouts.erl @@ -1,6 +1,5 @@ -module(capi_handler_payouts). --include_lib("damsel/include/dmsl_domain_thrift.hrl"). -include_lib("damsel/include/dmsl_payment_processing_thrift.hrl"). -include_lib("payout_manager_proto/include/payouts_payout_manager_thrift.hrl"). @@ -16,7 +15,7 @@ Context :: capi_handler:processing_context() ) -> {ok, capi_handler:request_state()} | {error, noimpl}. prepare(OperationID, Req, Context) when OperationID =:= 'GetPayout' -> - PayoutID = maps:get(payoutID, Req), + PayoutID = maps:get('payoutID', Req), PartyID = capi_handler_utils:get_party_id(Context), OperationContext = #{ id => OperationID, @@ -69,18 +68,15 @@ prepare(OperationID, Req, Context) when OperationID =:= 'CreatePayout' -> {ok, Payout} -> {ok, PayoutTool} = get_payout_tool(Payout, Context), {ok, {201, #{}, decode_payout(Payout, PayoutTool)}}; - {exception, Exception} -> - case Exception of - #payouts_InsufficientFunds{} -> - {ok, logic_error(invalidCash, <<"Invalid amount or currency">>)}; - #payouts_InvalidRequest{errors = Errors} -> - FormattedErrors = capi_handler_utils:format_request_errors(Errors), - {ok, logic_error(invalidRequest, FormattedErrors)}; - #payouts_PayoutAlreadyExists{} -> - {ok, logic_error(invalidRequest, <<"Payout already exists">>)}; - #payouts_NotFound{message = Message} -> - {ok, logic_error(invalidRequest, Message)} - end + {exception, #payouts_InsufficientFunds{}} -> + {ok, logic_error('invalidCash', <<"Invalid amount or currency">>)}; + {exception, #payouts_InvalidRequest{errors = Errors}} -> + FormattedErrors = capi_handler_utils:format_request_errors(Errors), + {ok, logic_error('invalidRequest', FormattedErrors)}; + {exception, #payouts_PayoutAlreadyExists{}} -> + {ok, logic_error('invalidRequest', <<"Payout already exists">>)}; + {exception, #payouts_NotFound{message = Message}} -> + {ok, logic_error('invalidRequest', Message)} end end, {ok, #{authorize => Authorize, process => Process}}; @@ -173,7 +169,7 @@ prepare(OperationID, Req, Context) when OperationID =:= 'GetScheduleByRef' -> {ok, capi_auth:authorize_operation([{operation, OperationContext}], Context)} end, Process = fun() -> - case get_schedule_by_id(genlib:to_int(maps:get(scheduleID, Req)), Context) of + case get_schedule_by_id(genlib:to_int(maps:get('scheduleID', Req)), Context) of {ok, Schedule} -> {ok, {200, #{}, decode_business_schedule(Schedule)}}; {error, not_found} -> diff --git a/apps/capi/src/capi_handler_reports.erl b/apps/capi/src/capi_handler_reports.erl index ad79cae..5f14843 100644 --- a/apps/capi/src/capi_handler_reports.erl +++ b/apps/capi/src/capi_handler_reports.erl @@ -27,14 +27,14 @@ prepare(OperationID = 'GetReports', Req, Context) -> {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetReportsForParty', Req, Context) -> Authorize = fun() -> - PartyID = maps:get(partyID, Req), + PartyID = maps:get('partyID', Req), Prototypes = build_prototypes(OperationID, PartyID, undefined, Req), {ok, capi_auth:authorize_operation(Prototypes, Context)} end, Process = fun() -> process_request(OperationID, Context, Req) end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetReport', Req, Context) -> - ReportID = maps:get(reportID, Req), + ReportID = maps:get('reportID', Req), Report = case get_report_by_id(ReportID, Context) of {ok, R} -> @@ -50,7 +50,7 @@ prepare(OperationID = 'GetReport', Req, Context) -> Process = fun() -> process_request(OperationID, Context, Req) end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetReportForParty', Req, Context) -> - ReportID = maps:get(reportID, Req), + ReportID = maps:get('reportID', Req), Report = case get_report_by_id(ReportID, Context) of {ok, R} -> @@ -59,7 +59,7 @@ prepare(OperationID = 'GetReportForParty', Req, Context) -> undefined end, Authorize = fun() -> - PartyID = maps:get(partyID, Req), + PartyID = maps:get('partyID', Req), Prototypes = build_prototypes(OperationID, PartyID, Report, Req), {ok, capi_auth:authorize_operation(Prototypes, Context)} end, @@ -75,14 +75,14 @@ prepare(OperationID = 'CreateReport', Req, Context) -> {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'CreateReportForParty', Req, Context) -> Authorize = fun() -> - PartyID = maps:get(partyID, Req), + PartyID = maps:get('partyID', Req), Prototypes = build_prototypes(OperationID, PartyID, undefined, Req), {ok, capi_auth:authorize_operation(Prototypes, Context)} end, Process = fun() -> process_request(OperationID, Context, Req) end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'DownloadFile', Req, Context) -> - ReportID = maps:get(reportID, Req), + ReportID = maps:get('reportID', Req), Report = case get_report_by_id(ReportID, Context) of {ok, R} -> @@ -98,7 +98,7 @@ prepare(OperationID = 'DownloadFile', Req, Context) -> Process = fun() -> process_request(OperationID, Context, Req) end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'DownloadFileForParty', Req, Context) -> - ReportID = maps:get(reportID, Req), + ReportID = maps:get('reportID', Req), Report = case get_report_by_id(ReportID, Context) of {ok, R} -> @@ -107,7 +107,7 @@ prepare(OperationID = 'DownloadFileForParty', Req, Context) -> undefined end, Authorize = fun() -> - PartyID = maps:get(partyID, Req), + PartyID = maps:get('partyID', Req), Prototypes = build_prototypes(OperationID, PartyID, Report, Req), {ok, capi_auth:authorize_operation(Prototypes, Context)} end, @@ -126,7 +126,7 @@ process_request('GetReports', Context, Req) -> get_reports(PartyID, Req, Context); process_request('GetReportsForParty', Context, Req) -> UserID = capi_handler_utils:get_user_id(Context), - PartyID = maps:get(partyID, Req), + PartyID = maps:get('partyID', Req), capi_handler_utils:run_if_party_accessible(UserID, PartyID, fun() -> get_reports(PartyID, Req, Context) end); @@ -135,7 +135,7 @@ process_request('GetReport', Context, Req) -> get_report(PartyID, Req, Context); process_request('GetReportForParty', Context, Req) -> UserID = capi_handler_utils:get_user_id(Context), - PartyID = maps:get(partyID, Req), + PartyID = maps:get('partyID', Req), capi_handler_utils:run_if_party_accessible(UserID, PartyID, fun() -> get_report(PartyID, Req, Context) end); @@ -144,7 +144,7 @@ process_request('CreateReport', Context, Req) -> create_report(PartyID, Req, Context); process_request('CreateReportForParty', Context, Req) -> UserID = capi_handler_utils:get_user_id(Context), - PartyID = maps:get(partyID, Req), + PartyID = maps:get('partyID', Req), capi_handler_utils:run_if_party_accessible(UserID, PartyID, fun() -> create_report(PartyID, Req, Context) end); @@ -153,7 +153,7 @@ process_request('DownloadFile', Context, Req) -> download_file(PartyID, Req, Context); process_request('DownloadFileForParty', Context, Req) -> UserID = capi_handler_utils:get_user_id(Context), - PartyID = maps:get(partyID, Req), + PartyID = maps:get('partyID', Req), capi_handler_utils:run_if_party_accessible(UserID, PartyID, fun() -> download_file(PartyID, Req, Context) end). @@ -161,7 +161,7 @@ process_request('DownloadFileForParty', Context, Req) -> %% create_report(PartyID, Req, Context) -> - ShopID = maps:get(shopID, Req), + ShopID = maps:get('shopID', Req), ReportParams = maps:get('ReportParams', Req), ReportRequest = #reports_ReportRequest{ party_id = PartyID, @@ -183,15 +183,15 @@ create_report(PartyID, Req, Context) -> case Exception of #reporter_base_InvalidRequest{errors = Errors} -> FormattedErrors = capi_handler_utils:format_request_errors(Errors), - {ok, logic_error(invalidRequest, FormattedErrors)}; + {ok, logic_error('invalidRequest', FormattedErrors)}; #reports_ShopNotFound{} -> - {ok, logic_error(invalidShopID, <<"Shop not found">>)} + {ok, logic_error('invalidShopID', <<"Shop not found">>)} end end. get_report(PartyID, Req, Context) -> - ShopID = maps:get(shopID, Req), - ReportID = maps:get(reportID, Req), + ShopID = maps:get('shopID', Req), + ReportID = maps:get('reportID', Req), Call = {reporting, 'GetReport', {ReportID}}, case capi_handler_utils:service_call(Call, Context) of {ok, Report = #'reports_Report'{party_id = PartyID, shop_id = ShopID}} -> @@ -203,7 +203,7 @@ get_report(PartyID, Req, Context) -> end. get_reports(PartyID, Req, Context) -> - ShopID = maps:get(shopID, Req), + ShopID = maps:get('shopID', Req), FromTime = capi_handler_utils:get_time('fromTime', Req), ToTime = capi_handler_utils:get_time('toTime', Req), ReportRequest = #reports_ReportRequest{ @@ -225,18 +225,18 @@ get_reports(PartyID, Req, Context) -> case Exception of #reporter_base_InvalidRequest{errors = Errors} -> FormattedErrors = capi_handler_utils:format_request_errors(Errors), - {ok, logic_error(invalidRequest, FormattedErrors)}; + {ok, logic_error('invalidRequest', FormattedErrors)}; #reports_DatasetTooBig{limit = Limit} -> - {ok, logic_error(<<"limitExceeded">>, io_lib:format("Max limit: ~p", [Limit]))} + {ok, logic_error('limitExceeded', io_lib:format("Max limit: ~p", [Limit]))} end end. download_file(PartyID, Req, Context) -> - ShopID = maps:get(shopID, Req), - ReportID = maps:get(reportID, Req), + ShopID = maps:get('shopID', Req), + ReportID = maps:get('reportID', Req), case get_report_by_id(ReportID, Context) of {ok, #reports_Report{status = created, files = Files, party_id = PartyID, shop_id = ShopID}} -> - FileID = maps:get(fileID, Req), + FileID = maps:get('fileID', Req), case lists:keymember(FileID, #reports_FileMeta.file_id, Files) of true -> generate_report_presigned_url(FileID, Context); @@ -263,7 +263,7 @@ generate_report_presigned_url(FileID, Context) -> case Exception of #reporter_base_InvalidRequest{errors = Errors} -> FormattedErrors = capi_handler_utils:format_request_errors(Errors), - {ok, logic_error(invalidRequest, FormattedErrors)}; + {ok, logic_error('invalidRequest', FormattedErrors)}; #reports_FileNotFound{} -> {ok, general_error(404, <<"File not found">>)} end @@ -310,9 +310,9 @@ decode_report_file_signature(#reports_Signature{md5 = MD5, sha256 = SHA256}) -> #{<<"md5">> => MD5, <<"sha256">> => SHA256}. build_prototypes(OperationID, PartyID, Report, Req) -> - ReportID = genlib_map:get(reportID, Req), - ShopID = genlib_map:get(shopID, Req), - FileID = genlib_map:get(fileID, Req), + ReportID = genlib_map:get('reportID', Req), + ShopID = genlib_map:get('shopID', Req), + FileID = genlib_map:get('fileID', Req), [ {operation, #{ id => OperationID, diff --git a/apps/capi/src/capi_handler_search.erl b/apps/capi/src/capi_handler_search.erl index b898e9b..f52a14c 100644 --- a/apps/capi/src/capi_handler_search.erl +++ b/apps/capi/src/capi_handler_search.erl @@ -129,9 +129,9 @@ process_search_request_result(QueryType, Result, Context, #{decode_fun := Decode {ok, {200, #{}, Resp}}; {exception, #'InvalidRequest'{errors = Errors}} -> FormattedErrors = capi_handler_utils:format_request_errors(Errors), - {ok, logic_error(invalidRequest, FormattedErrors)}; + {ok, logic_error('invalidRequest', FormattedErrors)}; {exception, #merchstat_BadToken{}} -> - {ok, logic_error(invalidRequest, <<"Invalid token">>)} + {ok, logic_error('invalidRequest', <<"Invalid token">>)} end. %% @@ -466,7 +466,7 @@ decode_stat_payout_status({Status, _}) -> decode_payout_tool_details(ToolInfo) -> capi_handler_decoder_party:decode_payout_tool_details(ToolInfo). -decode_stat_refund(Refund, Context) -> +decode_stat_refund(Refund, _Context) -> capi_handler_utils:merge_and_compact( #{ <<"invoiceID">> => Refund#merchstat_StatRefund.invoice_id, @@ -482,14 +482,14 @@ decode_stat_refund(Refund, Context) -> ), <<"allocation">> => capi_allocation:decode(Refund#merchstat_StatRefund.allocation) }, - decode_stat_refund_status(Refund#merchstat_StatRefund.status, Context) + decode_stat_refund_status(Refund#merchstat_StatRefund.status) ). -decode_stat_refund_status({Status, StatusInfo}, Context) -> +decode_stat_refund_status({Status, StatusInfo}) -> Error = case StatusInfo of #merchstat_InvoicePaymentRefundFailed{failure = OperationFailure} -> - capi_handler_decoder_utils:decode_operation_failure(OperationFailure, Context); + capi_handler_decoder_utils:decode_operation_failure(OperationFailure); _ -> undefined end, diff --git a/apps/capi/src/capi_handler_shops.erl b/apps/capi/src/capi_handler_shops.erl index 81b46bd..c0818ea 100644 --- a/apps/capi/src/capi_handler_shops.erl +++ b/apps/capi/src/capi_handler_shops.erl @@ -15,7 +15,7 @@ ) -> {ok, capi_handler:request_state()} | {error, noimpl}. prepare(OperationID = 'ActivateShop', Req, Context) -> PartyID = capi_handler_utils:get_party_id(Context), - ShopID = maps:get(shopID, Req), + ShopID = maps:get('shopID', Req), Authorize = fun() -> Prototypes = [{operation, #{id => OperationID, party => PartyID, shop => ShopID}}], {ok, capi_auth:authorize_operation(Prototypes, Context)} @@ -24,19 +24,16 @@ prepare(OperationID = 'ActivateShop', Req, Context) -> case capi_party:activate_shop(PartyID, ShopID, Context) of ok -> {ok, {204, #{}, undefined}}; - {error, Exception} -> - case Exception of - #payproc_ShopNotFound{} -> - {ok, general_error(404, <<"Shop not found">>)}; - #payproc_InvalidShopStatus{status = {suspension, {active, _}}} -> - {ok, {204, #{}, undefined}} - end + {error, #payproc_ShopNotFound{}} -> + {ok, general_error(404, <<"Shop not found">>)}; + {error, #payproc_InvalidShopStatus{status = {suspension, {active, _}}}} -> + {ok, {204, #{}, undefined}} end end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'SuspendShop', Req, Context) -> PartyID = capi_handler_utils:get_party_id(Context), - ShopID = maps:get(shopID, Req), + ShopID = maps:get('shopID', Req), Authorize = fun() -> Prototypes = [{operation, #{id => OperationID, party => PartyID, shop => ShopID}}], {ok, capi_auth:authorize_operation(Prototypes, Context)} @@ -45,13 +42,10 @@ prepare(OperationID = 'SuspendShop', Req, Context) -> case capi_party:suspend_shop(PartyID, ShopID, Context) of ok -> {ok, {204, #{}, undefined}}; - {error, Exception} -> - case Exception of - #payproc_ShopNotFound{} -> - {ok, general_error(404, <<"Shop not found">>)}; - #payproc_InvalidShopStatus{status = {suspension, {suspended, _}}} -> - {ok, {204, #{}, undefined}} - end + {error, #payproc_ShopNotFound{}} -> + {ok, general_error(404, <<"Shop not found">>)}; + {error, #payproc_InvalidShopStatus{status = {suspension, {suspended, _}}}} -> + {ok, {204, #{}, undefined}} end end, {ok, #{authorize => Authorize, process => Process}}; @@ -68,7 +62,7 @@ prepare(OperationID = 'GetShops', _Req, Context) -> {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetShopByID', Req, Context) -> PartyID = capi_handler_utils:get_party_id(Context), - ShopID = maps:get(shopID, Req), + ShopID = maps:get('shopID', Req), Authorize = fun() -> Prototypes = [{operation, #{id => OperationID, party => PartyID, shop => ShopID}}], {ok, capi_auth:authorize_operation(Prototypes, Context)} @@ -83,7 +77,7 @@ prepare(OperationID = 'GetShopByID', Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetShopsForParty', Req, Context) -> - PartyID = maps:get(partyID, Req), + PartyID = maps:get('partyID', Req), Authorize = fun() -> Prototypes = [{operation, #{id => OperationID, party => PartyID}}], {ok, capi_auth:authorize_operation(Prototypes, Context)} @@ -100,8 +94,8 @@ prepare(OperationID = 'GetShopsForParty', Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'GetShopByIDForParty', Req, Context) -> - PartyID = maps:get(partyID, Req), - ShopID = maps:get(shopID, Req), + PartyID = maps:get('partyID', Req), + ShopID = maps:get('shopID', Req), Authorize = fun() -> Prototypes = [{operation, #{id => OperationID, party => PartyID, shop => ShopID}}], {ok, capi_auth:authorize_operation(Prototypes, Context)} @@ -120,8 +114,8 @@ prepare(OperationID = 'GetShopByIDForParty', Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'ActivateShopForParty', Req, Context) -> - PartyID = maps:get(partyID, Req), - ShopID = maps:get(shopID, Req), + PartyID = maps:get('partyID', Req), + ShopID = maps:get('shopID', Req), Authorize = fun() -> Prototypes = [{operation, #{id => OperationID, party => PartyID, shop => ShopID}}], {ok, capi_auth:authorize_operation(Prototypes, Context)} @@ -130,23 +124,20 @@ prepare(OperationID = 'ActivateShopForParty', Req, Context) -> case capi_party:activate_shop(PartyID, ShopID, Context) of ok -> {ok, {204, #{}, undefined}}; - {error, Exception} -> - case Exception of - #payproc_InvalidUser{} -> - {ok, general_error(404, <<"Party not found">>)}; - #payproc_PartyNotFound{} -> - {ok, general_error(404, <<"Party not found">>)}; - #payproc_ShopNotFound{} -> - {ok, general_error(404, <<"Shop not found">>)}; - #payproc_InvalidShopStatus{status = {suspension, {active, _}}} -> - {ok, {204, #{}, undefined}} - end + {error, #payproc_InvalidUser{}} -> + {ok, general_error(404, <<"Party not found">>)}; + {error, #payproc_PartyNotFound{}} -> + {ok, general_error(404, <<"Party not found">>)}; + {error, #payproc_ShopNotFound{}} -> + {ok, general_error(404, <<"Shop not found">>)}; + {error, #payproc_InvalidShopStatus{status = {suspension, {active, _}}}} -> + {ok, {204, #{}, undefined}} end end, {ok, #{authorize => Authorize, process => Process}}; prepare(OperationID = 'SuspendShopForParty', Req, Context) -> - PartyID = maps:get(partyID, Req), - ShopID = maps:get(shopID, Req), + PartyID = maps:get('partyID', Req), + ShopID = maps:get('shopID', Req), Authorize = fun() -> Prototypes = [{operation, #{id => OperationID, party => PartyID, shop => ShopID}}], {ok, capi_auth:authorize_operation(Prototypes, Context)} @@ -155,17 +146,14 @@ prepare(OperationID = 'SuspendShopForParty', Req, Context) -> case capi_party:suspend_shop(PartyID, ShopID, Context) of ok -> {ok, {204, #{}, undefined}}; - {error, Exception} -> - case Exception of - #payproc_InvalidUser{} -> - {ok, general_error(404, <<"Party not found">>)}; - #payproc_PartyNotFound{} -> - {ok, general_error(404, <<"Party not found">>)}; - #payproc_ShopNotFound{} -> - {ok, general_error(404, <<"Shop not found">>)}; - #payproc_InvalidShopStatus{status = {suspension, {suspended, _}}} -> - {ok, {204, #{}, undefined}} - end + {error, #payproc_InvalidUser{}} -> + {ok, general_error(404, <<"Party not found">>)}; + {error, #payproc_PartyNotFound{}} -> + {ok, general_error(404, <<"Party not found">>)}; + {error, #payproc_ShopNotFound{}} -> + {ok, general_error(404, <<"Shop not found">>)}; + {error, #payproc_InvalidShopStatus{status = {suspension, {suspended, _}}}} -> + {ok, {204, #{}, undefined}} end end, {ok, #{authorize => Authorize, process => Process}}; diff --git a/apps/capi/src/capi_handler_utils.erl b/apps/capi/src/capi_handler_utils.erl index 9892714..673ef0f 100644 --- a/apps/capi/src/capi_handler_utils.erl +++ b/apps/capi/src/capi_handler_utils.erl @@ -28,7 +28,7 @@ -export([get_time/2]). -export([get_split_interval/2]). -export([get_time_diff/2]). --export([collect_events/5]). +-export([collect_events/4]). -export([unwrap_payment_session/1]). -export([wrap_payment_session/2]). @@ -54,22 +54,22 @@ general_error(Code, Message) -> create_error_resp(Code, #{<<"message">> => genlib:to_binary(Message)}). -spec logic_error(term()) -> response(). -logic_error(invalidPaymentToolToken) -> - logic_error(invalidPaymentToolToken, <<"Specified payment tool token is invalid">>). +logic_error('invalidPaymentToolToken') -> + logic_error('invalidPaymentToolToken', <<"Specified payment tool token is invalid">>). -spec logic_error (term(), io_lib:chars() | binary()) -> response(); (term(), {binary(), binary() | undefined}) -> response(). -logic_error(externalIDConflict, {ID, undefined}) -> - logic_error(externalIDConflict, {ID, <<"undefined">>}); -logic_error(externalIDConflict, {ID, ExternalID}) -> +logic_error('externalIDConflict', {ID, undefined}) -> + logic_error('externalIDConflict', {ID, <<"undefined">>}); +logic_error('externalIDConflict', {ID, ExternalID}) -> Data = #{ <<"externalID">> => ExternalID, <<"id">> => ID, <<"message">> => <<"This 'externalID' has been used by another request">> }, create_error_resp(409, Data); -logic_error(externalIDConflict, ExternalID) -> +logic_error('externalIDConflict', ExternalID) -> Data = #{ <<"externalID">> => ExternalID, <<"message">> => <<"This 'externalID' has been used by another request">> @@ -216,18 +216,17 @@ get_time_diff(From, To) -> integer(), integer(), fun((_) -> {exception, _} | {ok, _}), - fun((_, _) -> false | {true, #{binary() => binary() | [any()] | integer()}}), - undefined + fun((_) -> false | {true, #{binary() => binary() | [any()] | integer()}}) ) -> {ok, _} | {exception, _}. -collect_events(Limit, After, GetterFun, DecodeFun, Context) -> - collect_events([], Limit, After, GetterFun, DecodeFun, Context). +collect_events(Limit, After, GetterFun, DecodeFun) -> + collect_events([], Limit, After, GetterFun, DecodeFun). -collect_events(Collected, 0, _, _, _, _) -> +collect_events(Collected, 0, _, _, _) -> {ok, Collected}; -collect_events(Collected0, Left, After, GetterFun, DecodeFun, Context) when Left > 0 -> +collect_events(Collected0, Left, After, GetterFun, DecodeFun) when Left > 0 -> case get_events(Left, After, GetterFun) of {ok, Events} -> - Filtered = decode_and_filter_events(DecodeFun, Context, Events), + Filtered = decode_and_filter_events(DecodeFun, Events), Collected = Collected0 ++ Filtered, case length(Events) of Left -> @@ -236,8 +235,7 @@ collect_events(Collected0, Left, After, GetterFun, DecodeFun, Context) when Left Left - length(Filtered), get_last_event_id(Events), GetterFun, - DecodeFun, - Context + DecodeFun ); N when N < Left -> {ok, Collected} @@ -246,10 +244,10 @@ collect_events(Collected0, Left, After, GetterFun, DecodeFun, Context) when Left Error end. -decode_and_filter_events(DecodeFun, Context, Events) -> +decode_and_filter_events(DecodeFun, Events) -> lists:foldr( fun(Event, Acc) -> - case DecodeFun(Event, Context) of + case DecodeFun(Event) of {true, Ev} -> [Ev | Acc]; false -> diff --git a/apps/capi/src/capi_handler_webhooks.erl b/apps/capi/src/capi_handler_webhooks.erl index 9363ac2..1d0cdc2 100644 --- a/apps/capi/src/capi_handler_webhooks.erl +++ b/apps/capi/src/capi_handler_webhooks.erl @@ -28,16 +28,17 @@ prepare('CreateWebhook' = OperationID, Req, Context) -> ShopID = validate_webhook_params(WebhookParams), case capi_party:get_shop(PartyID, ShopID, Context) of {ok, _} -> - case capi_handler_utils:service_call({webhook_manager, 'Create', {WebhookParams}}, Context) of - {ok, Webhook} -> - {ok, {201, #{}, decode_webhook(Webhook)}}; - {exception, #webhooker_LimitExceeded{}} -> - {ok, general_error(429, <<"Webhook limit exceeded">>)} - end; + ok; {error, #payproc_InvalidUser{}} -> - {ok, logic_error(invalidPartyID, <<"Party not found">>)}; + capi_handler:respond(logic_error('invalidPartyID', <<"Party not found">>)); {error, #payproc_ShopNotFound{}} -> - {ok, logic_error(invalidShopID, <<"Shop not found">>)} + capi_handler:respond(logic_error('invalidShopID', <<"Shop not found">>)) + end, + case capi_handler_utils:service_call({webhook_manager, 'Create', {WebhookParams}}, Context) of + {ok, Webhook} -> + {ok, {201, #{}, decode_webhook(Webhook)}}; + {exception, #webhooker_LimitExceeded{}} -> + {ok, general_error(429, <<"Webhook limit exceeded">>)} end end, {ok, #{authorize => Authorize, process => Process}}; @@ -56,7 +57,7 @@ prepare('GetWebhooks' = OperationID, _Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare('GetWebhookByID' = OperationID, Req, Context) -> - WebhookID = maps:get(webhookID, Req), + WebhookID = maps:get('webhookID', Req), Webhook = case encode_webhook_id(WebhookID) of {ok, ID} -> @@ -83,7 +84,7 @@ prepare('GetWebhookByID' = OperationID, Req, Context) -> end, {ok, #{authorize => Authorize, process => Process}}; prepare('DeleteWebhookByID' = OperationID, Req, Context) -> - WebhookID = maps:get(webhookID, Req), + WebhookID = maps:get('webhookID', Req), {EncodedWebhookID, Webhook} = case encode_webhook_id(WebhookID) of {ok, ID} -> @@ -177,53 +178,53 @@ encode_webhook_scope(#{<<"topic">> := <<"CustomersTopic">>, <<"shopID">> := Shop types = ordsets:from_list([encode_customer_event_type(V) || V <- EventTypes]) }}. --define(invpaid(), {paid, #webhooker_InvoicePaid{}}). --define(invcancelled(), {cancelled, #webhooker_InvoiceCancelled{}}). --define(invfulfilled(), {fulfilled, #webhooker_InvoiceFulfilled{}}). +-define(INVPAID(), {paid, #webhooker_InvoicePaid{}}). +-define(INVCANCELLED(), {cancelled, #webhooker_InvoiceCancelled{}}). +-define(INVFULFILLED(), {fulfilled, #webhooker_InvoiceFulfilled{}}). --define(pmtprocessed(), {processed, #webhooker_InvoicePaymentProcessed{}}). --define(pmtcaptured(), {captured, #webhooker_InvoicePaymentCaptured{}}). --define(pmtcancelled(), {cancelled, #webhooker_InvoicePaymentCancelled{}}). --define(pmtrefunded(), {refunded, #webhooker_InvoicePaymentRefunded{}}). --define(pmtfailed(), {failed, #webhooker_InvoicePaymentFailed{}}). +-define(PMTPROCESSED(), {processed, #webhooker_InvoicePaymentProcessed{}}). +-define(PMTCAPTURED(), {captured, #webhooker_InvoicePaymentCaptured{}}). +-define(PMTCANCELLED(), {cancelled, #webhooker_InvoicePaymentCancelled{}}). +-define(PMTREFUNDED(), {refunded, #webhooker_InvoicePaymentRefunded{}}). +-define(PMTFAILED(), {failed, #webhooker_InvoicePaymentFailed{}}). --define(pmtrfndcreated(), {invoice_payment_refund_created, #webhooker_InvoicePaymentRefundCreated{}}). --define(pmtrfndstatus(Value), +-define(PMTRFNDCREATED(), {invoice_payment_refund_created, #webhooker_InvoicePaymentRefundCreated{}}). +-define(PMTRFNDSTATUS(Value), { invoice_payment_refund_status_changed, #webhooker_InvoicePaymentRefundStatusChanged{value = Value} } ). --define(pmtrfndfailed(), {failed, #webhooker_InvoicePaymentRefundFailed{}}). --define(pmtrfndsucceeded(), {succeeded, #webhooker_InvoicePaymentRefundSucceeded{}}). +-define(PMTRFNDFAILED(), {failed, #webhooker_InvoicePaymentRefundFailed{}}). +-define(PMTRFNDSUCCEEDED(), {succeeded, #webhooker_InvoicePaymentRefundSucceeded{}}). encode_invoice_event_type(<<"InvoiceCreated">>) -> {created, #webhooker_InvoiceCreated{}}; encode_invoice_event_type(<<"InvoicePaid">>) -> - {status_changed, #webhooker_InvoiceStatusChanged{value = ?invpaid()}}; + {status_changed, #webhooker_InvoiceStatusChanged{value = ?INVPAID()}}; encode_invoice_event_type(<<"InvoiceCancelled">>) -> - {status_changed, #webhooker_InvoiceStatusChanged{value = ?invcancelled()}}; + {status_changed, #webhooker_InvoiceStatusChanged{value = ?INVCANCELLED()}}; encode_invoice_event_type(<<"InvoiceFulfilled">>) -> - {status_changed, #webhooker_InvoiceStatusChanged{value = ?invfulfilled()}}; + {status_changed, #webhooker_InvoiceStatusChanged{value = ?INVFULFILLED()}}; encode_invoice_event_type(<<"PaymentStarted">>) -> {payment, {created, #webhooker_InvoicePaymentCreated{}}}; encode_invoice_event_type(<<"PaymentProcessed">>) -> - {payment, {status_changed, #webhooker_InvoicePaymentStatusChanged{value = ?pmtprocessed()}}}; + {payment, {status_changed, #webhooker_InvoicePaymentStatusChanged{value = ?PMTPROCESSED()}}}; encode_invoice_event_type(<<"PaymentCaptured">>) -> - {payment, {status_changed, #webhooker_InvoicePaymentStatusChanged{value = ?pmtcaptured()}}}; + {payment, {status_changed, #webhooker_InvoicePaymentStatusChanged{value = ?PMTCAPTURED()}}}; encode_invoice_event_type(<<"PaymentCancelled">>) -> - {payment, {status_changed, #webhooker_InvoicePaymentStatusChanged{value = ?pmtcancelled()}}}; + {payment, {status_changed, #webhooker_InvoicePaymentStatusChanged{value = ?PMTCANCELLED()}}}; encode_invoice_event_type(<<"PaymentRefunded">>) -> - {payment, {status_changed, #webhooker_InvoicePaymentStatusChanged{value = ?pmtrefunded()}}}; + {payment, {status_changed, #webhooker_InvoicePaymentStatusChanged{value = ?PMTREFUNDED()}}}; encode_invoice_event_type(<<"PaymentFailed">>) -> - {payment, {status_changed, #webhooker_InvoicePaymentStatusChanged{value = ?pmtfailed()}}}; + {payment, {status_changed, #webhooker_InvoicePaymentStatusChanged{value = ?PMTFAILED()}}}; encode_invoice_event_type(<<"PaymentRefundCreated">>) -> - {payment, {invoice_payment_refund_change, ?pmtrfndcreated()}}; + {payment, {invoice_payment_refund_change, ?PMTRFNDCREATED()}}; encode_invoice_event_type(<<"PaymentRefundFailed">>) -> - {payment, {invoice_payment_refund_change, ?pmtrfndstatus(?pmtrfndfailed())}}; + {payment, {invoice_payment_refund_change, ?PMTRFNDSTATUS(?PMTRFNDFAILED())}}; encode_invoice_event_type(<<"PaymentRefundSucceeded">>) -> - {payment, {invoice_payment_refund_change, ?pmtrfndstatus(?pmtrfndsucceeded())}}. + {payment, {invoice_payment_refund_change, ?PMTRFNDSTATUS(?PMTRFNDSUCCEEDED())}}. encode_customer_event_type(<<"CustomerCreated">>) -> {created, #webhooker_CustomerCreated{}}; @@ -269,9 +270,9 @@ decode_invoice_event_type({status_changed, #webhooker_InvoiceStatusChanged{value [ decode_invoice_status_event_type(V) || V <- [ - ?invpaid(), - ?invcancelled(), - ?invfulfilled() + ?INVPAID(), + ?INVCANCELLED(), + ?INVFULFILLED() ] ]; decode_invoice_event_type({status_changed, #webhooker_InvoiceStatusChanged{value = Value}}) -> @@ -283,32 +284,32 @@ decode_invoice_event_type({payment, {status_changed, #webhooker_InvoicePaymentSt [ decode_payment_status_event_type(V) || V <- [ - ?pmtprocessed(), - ?pmtcaptured(), - ?pmtcancelled(), - ?pmtrefunded(), - ?pmtfailed() + ?PMTPROCESSED(), + ?PMTCAPTURED(), + ?PMTCANCELLED(), + ?PMTREFUNDED(), + ?PMTFAILED() ] ]; decode_invoice_event_type({payment, {status_changed, #webhooker_InvoicePaymentStatusChanged{value = Value}}}) -> [decode_payment_status_event_type(Value)]; -decode_invoice_event_type({payment, {invoice_payment_refund_change, ?pmtrfndcreated()}}) -> +decode_invoice_event_type({payment, {invoice_payment_refund_change, ?PMTRFNDCREATED()}}) -> [<<"PaymentRefundCreated">>]; -decode_invoice_event_type({payment, {invoice_payment_refund_change, ?pmtrfndstatus(Value)}}) -> +decode_invoice_event_type({payment, {invoice_payment_refund_change, ?PMTRFNDSTATUS(Value)}}) -> [decode_payment_refund_status_event_type(Value)]. -decode_invoice_status_event_type(?invpaid()) -> <<"InvoicePaid">>; -decode_invoice_status_event_type(?invcancelled()) -> <<"InvoiceCancelled">>; -decode_invoice_status_event_type(?invfulfilled()) -> <<"InvoiceFulfilled">>. +decode_invoice_status_event_type(?INVPAID()) -> <<"InvoicePaid">>; +decode_invoice_status_event_type(?INVCANCELLED()) -> <<"InvoiceCancelled">>; +decode_invoice_status_event_type(?INVFULFILLED()) -> <<"InvoiceFulfilled">>. -decode_payment_status_event_type(?pmtprocessed()) -> <<"PaymentProcessed">>; -decode_payment_status_event_type(?pmtcaptured()) -> <<"PaymentCaptured">>; -decode_payment_status_event_type(?pmtcancelled()) -> <<"PaymentCancelled">>; -decode_payment_status_event_type(?pmtrefunded()) -> <<"PaymentRefunded">>; -decode_payment_status_event_type(?pmtfailed()) -> <<"PaymentFailed">>. +decode_payment_status_event_type(?PMTPROCESSED()) -> <<"PaymentProcessed">>; +decode_payment_status_event_type(?PMTCAPTURED()) -> <<"PaymentCaptured">>; +decode_payment_status_event_type(?PMTCANCELLED()) -> <<"PaymentCancelled">>; +decode_payment_status_event_type(?PMTREFUNDED()) -> <<"PaymentRefunded">>; +decode_payment_status_event_type(?PMTFAILED()) -> <<"PaymentFailed">>. -decode_payment_refund_status_event_type(?pmtrfndfailed()) -> <<"PaymentRefundFailed">>; -decode_payment_refund_status_event_type(?pmtrfndsucceeded()) -> <<"PaymentRefundSucceeded">>. +decode_payment_refund_status_event_type(?PMTRFNDFAILED()) -> <<"PaymentRefundFailed">>; +decode_payment_refund_status_event_type(?PMTRFNDSUCCEEDED()) -> <<"PaymentRefundSucceeded">>. decode_customer_event_type({created, #webhooker_CustomerCreated{}}) -> <<"CustomerCreated">>; diff --git a/apps/capi/src/capi_json_marshalling.erl b/apps/capi/src/capi_json_marshalling.erl index 5dff8a3..93b8f56 100644 --- a/apps/capi/src/capi_json_marshalling.erl +++ b/apps/capi/src/capi_json_marshalling.erl @@ -6,6 +6,8 @@ -export([marshal/1]). -export([unmarshal/1]). +-export_type([value/0]). + %% -type value() :: term(). diff --git a/apps/capi/src/capi_swagger_server.erl b/apps/capi/src/capi_swagger_server.erl index 425343c..526666c 100644 --- a/apps/capi/src/capi_swagger_server.erl +++ b/apps/capi/src/capi_swagger_server.erl @@ -77,15 +77,18 @@ mk_operation_id_getter(#{env := Env}) -> (Req = #{host := _Host, path := _Path}) -> case cowboy_router:execute(Req, Env) of {ok, _, #{handler_opts := {_Operations, _LogicHandler, _SwaggerHandlerOpts} = HandlerOpts}} -> - case swag_server_utils:get_operation_id(Req, HandlerOpts) of - undefined -> - #{}; - OperationID -> - #{operation_id => OperationID} - end; + try_get_operation_id(Req, HandlerOpts); _ -> #{} end; (_Req) -> #{} end. + +try_get_operation_id(Req, HandlerOpts) -> + case swag_server_utils:get_operation_id(Req, HandlerOpts) of + undefined -> + #{}; + OperationID -> + #{operation_id => OperationID} + end. diff --git a/apps/capi/src/capi_utils.erl b/apps/capi/src/capi_utils.erl index 58036ab..5a220f2 100644 --- a/apps/capi/src/capi_utils.erl +++ b/apps/capi/src/capi_utils.erl @@ -324,7 +324,7 @@ merge_deduplication_card_test() -> ], SamsungPayMethod = #{ <<"method">> => <<"BankCard">>, - <<"PaymentSystems">> => Systems1, + <<"paymentSystems">> => Systems1, <<"tokenProviders">> => [<<"samsungpay">>] }, Methods = [ diff --git a/apps/capi/test/capi_authorization_tests_SUITE.erl b/apps/capi/test/capi_authorization_tests_SUITE.erl index c31068d..cbec96e 100644 --- a/apps/capi/test/capi_authorization_tests_SUITE.erl +++ b/apps/capi/test/capi_authorization_tests_SUITE.erl @@ -31,7 +31,7 @@ get_customer_forbidden_notfound/1 ]). --define(emptyresp(Code), {error, {Code, #{}}}). +-define(EMPTYRESP(Code), {error, {Code, #{}}}). -type test_case_name() :: atom(). -type config() :: [{atom(), any()}]. @@ -113,13 +113,13 @@ end_per_group(_Group, C) -> authorization_error_no_header_test(Config) -> Token = <<>>, _ = capi_ct_helper_bouncer:mock_arbiter(capi_ct_helper_bouncer:judge_always_allowed(), Config), - ?emptyresp(401) = capi_client_categories:get_categories(capi_ct_helper:get_context(Token)). + ?EMPTYRESP(401) = capi_client_categories:get_categories(capi_ct_helper:get_context(Token)). -spec authorization_error_no_permission_test(config()) -> _. authorization_error_no_permission_test(Config) -> Token = ?API_TOKEN, _ = capi_ct_helper_bouncer:mock_arbiter(capi_ct_helper_bouncer:judge_always_forbidden(), Config), - ?emptyresp(401) = capi_client_parties:get_my_party(capi_ct_helper:get_context(Token)). + ?EMPTYRESP(401) = capi_client_parties:get_my_party(capi_ct_helper:get_context(Token)). %%% diff --git a/apps/capi/test/capi_base_api_token_tests_SUITE.erl b/apps/capi/test/capi_base_api_token_tests_SUITE.erl index 04f9b24..6f7cd64 100644 --- a/apps/capi/test/capi_base_api_token_tests_SUITE.erl +++ b/apps/capi/test/capi_base_api_token_tests_SUITE.erl @@ -98,7 +98,6 @@ get_webhooks/1, get_webhook_by_id/1, delete_webhook_by_id/1, - get_locations_names_ok_test/1, search_invoices_ok_test/1, search_payments_ok_test/1, search_refunds_ok_test/1, @@ -126,6 +125,7 @@ get_payment_institution_payment_terms/1, get_payment_institution_payout_terms/1, get_payment_institution_payout_schedules/1, + get_service_provider_by_id/1, check_no_payment_by_external_id_test/1, check_no_internal_id_for_external_id_test/1, retrieve_payment_by_external_id_test/1, @@ -198,8 +198,6 @@ groups() -> activate_shop_ok_test, suspend_shop_ok_test, - get_locations_names_ok_test, - get_account_by_id_ok_test, get_categories_ok_test, @@ -247,6 +245,7 @@ groups() -> get_payment_institution_payment_terms, get_payment_institution_payout_terms, get_payment_institution_payout_schedules, + get_service_provider_by_id, get_category_by_ref_ok_test, get_schedule_by_ref_ok_test, @@ -1905,19 +1904,6 @@ delete_webhook_by_id(Config) -> ), ok = capi_client_webhooks:delete_webhook_by_id(?config(context, Config), ?INTEGER_BINARY). --spec get_locations_names_ok_test(config()) -> _. -get_locations_names_ok_test(Config) -> - _ = capi_ct_helper:mock_services( - [{geo_ip_service, fun('GetLocationName', _) -> {ok, #{123 => ?STRING}} end}], - Config - ), - _ = capi_ct_helper_bouncer:mock_assert_op_ctx(<<"GetLocationsNames">>, Config), - Query = #{ - <<"geoIDs">> => <<"5,3,6,5,4">>, - <<"language">> => <<"ru">> - }, - {ok, _} = capi_client_geo:get_location_names(?config(context, Config), Query). - -spec search_invoices_ok_test(config()) -> _. search_invoices_ok_test(Config) -> _ = capi_ct_helper:mock_services( @@ -1945,23 +1931,23 @@ search_invoices_ok_test_(BankCardTokenProvider, Config) -> {limit, 2}, {from_time, {{2015, 08, 11}, {19, 42, 35}}}, {to_time, {{2020, 08, 11}, {19, 42, 35}}}, - {invoiceStatus, <<"fulfilled">>}, - {payerEmail, <<"test@test.ru">>}, - {payerIP, <<"192.168.0.1">>}, - {paymentStatus, <<"processed">>}, - {paymentFlow, <<"instant">>}, - {paymentMethod, <<"bankCard">>}, - {invoiceID, <<"testInvoiceID">>}, - {paymentID, <<"testPaymentID">>}, - {customerID, <<"testCustomerID">>}, - {payerFingerprint, <<"blablablalbalbal">>}, - {first6, <<"424242">>}, - {last4, <<"2222">>}, - {rrn, <<"090909090909">>}, - {bankCardTokenProvider, BankCardTokenProvider}, - {bankCardPaymentSystem, <<"visa">>}, - {paymentAmount, 10000}, - {continuationToken, <<"come_back_next_time">>} + {'invoiceStatus', <<"fulfilled">>}, + {'payerEmail', <<"test@test.ru">>}, + {'payerIP', <<"192.168.0.1">>}, + {'paymentStatus', <<"processed">>}, + {'paymentFlow', <<"instant">>}, + {'paymentMethod', <<"bankCard">>}, + {'invoiceID', <<"testInvoiceID">>}, + {'paymentID', <<"testPaymentID">>}, + {'customerID', <<"testCustomerID">>}, + {'payerFingerprint', <<"blablablalbalbal">>}, + {'first6', <<"424242">>}, + {'last4', <<"2222">>}, + {'rrn', <<"090909090909">>}, + {'bankCardTokenProvider', BankCardTokenProvider}, + {'bankCardPaymentSystem', <<"visa">>}, + {'paymentAmount', 10000}, + {'continuationToken', <<"come_back_next_time">>} ], {ok, _, _} = capi_client_searches:search_invoices(?config(context, Config), ?STRING, Query), ok. @@ -1991,22 +1977,22 @@ search_payments_ok_(BankCardTokenProvider, Config) -> {limit, 2}, {from_time, {{2015, 08, 11}, {19, 42, 35}}}, {to_time, {{2020, 08, 11}, {19, 42, 35}}}, - {payerEmail, <<"test@test.ru">>}, - {payerIP, <<"192.168.0.1">>}, - {paymentStatus, <<"processed">>}, - {paymentFlow, <<"instant">>}, - {paymentMethod, <<"bankCard">>}, - {invoiceID, <<"testInvoiceID">>}, - {paymentID, <<"testPaymentID">>}, - {payerFingerprint, <<"blablablalbalbal">>}, - {first6, <<"424242">>}, - {last4, <<"2222">>}, - {rrn, <<"090909090909">>}, - {approvalCode, <<"808080">>}, - {bankCardTokenProvider, BankCardTokenProvider}, - {bankCardPaymentSystem, <<"visa">>}, - {paymentAmount, 10000}, - {continuationToken, <<"come_back_next_time">>} + {'payerEmail', <<"test@test.ru">>}, + {'payerIP', <<"192.168.0.1">>}, + {'paymentStatus', <<"processed">>}, + {'paymentFlow', <<"instant">>}, + {'paymentMethod', <<"bankCard">>}, + {'invoiceID', <<"testInvoiceID">>}, + {'paymentID', <<"testPaymentID">>}, + {'payerFingerprint', <<"blablablalbalbal">>}, + {'first6', <<"424242">>}, + {'last4', <<"2222">>}, + {'rrn', <<"090909090909">>}, + {'approvalCode', <<"808080">>}, + {'bankCardTokenProvider', BankCardTokenProvider}, + {'bankCardPaymentSystem', <<"visa">>}, + {'paymentAmount', 10000}, + {'continuationToken', <<"come_back_next_time">>} ], {ok, _, _} = capi_client_searches:search_payments(?config(context, Config), ?STRING, Query), ok. @@ -2036,13 +2022,13 @@ search_refunds_ok_test(Config) -> {offset, 2}, {from_time, {{2015, 08, 11}, {19, 42, 35}}}, {to_time, {{2020, 08, 11}, {19, 42, 35}}}, - {shopID, ShopID}, - {invoiceID, <<"testInvoiceID">>}, - {paymentID, <<"testPaymentID">>}, - {refundID, <<"testRefundID">>}, + {'shopID', ShopID}, + {'invoiceID', <<"testInvoiceID">>}, + {'paymentID', <<"testPaymentID">>}, + {'refundID', <<"testRefundID">>}, % {rrn, <<"090909090909">>}, % {approvalCode, <<"808080">>}, - {refundStatus, <<"succeeded">>} + {'refundStatus', <<"succeeded">>} ], {ok, _, _} = capi_client_searches:search_refunds(?config(context, Config), ShopID, Query). @@ -2066,8 +2052,8 @@ search_payouts_ok_test(Config) -> {offset, 2}, {from_time, {{2015, 08, 11}, {19, 42, 35}}}, {to_time, {{2020, 08, 11}, {19, 42, 35}}}, - {payoutID, <<"testPayoutID">>}, - {payoutToolType, <<"Wallet">>} + {'payoutID', <<"testPayoutID">>}, + {'payoutToolType', <<"Wallet">>} ], {ok, _, _} = capi_client_searches:search_payouts(?config(context, Config), ShopID, Query). @@ -2164,7 +2150,7 @@ get_payment_method_stats_ok_test(Config) -> {to_time, {{2020, 08, 11}, {19, 42, 35}}}, {split_unit, minute}, {split_size, 1}, - {paymentMethod, <<"bankCard">>} + {'paymentMethod', <<"bankCard">>} ], {ok, _} = capi_client_analytics:get_payment_method_stats(?config(context, Config), ?STRING, Query). @@ -2497,6 +2483,26 @@ get_payment_institution_payout_schedules(Config) -> <<"BankAccount">> ). +-spec get_service_provider_by_id(config()) -> _. +get_service_provider_by_id(Config) -> + _ = capi_ct_helper_bouncer:mock_assert_op_ctx(<<"GetServiceProviderByID">>, Config), + ?assertEqual( + {ok, #{ + <<"id">> => <<"qiwi">>, + <<"brandName">> => <<"QIWI">>, + <<"category">> => <<"wallets">>, + <<"metadata">> => #{ + <<"test.ns">> => #{ + <<"answer">> => 42, + <<"localization">> => #{ + <<"ru_RU">> => [<<"КИВИ Кошелёк">>] + } + } + } + }}, + capi_client_payment_institutions:get_service_provider_by_id(?config(context, Config), <<"qiwi">>) + ). + -spec get_country_by_id_test(config()) -> _. get_country_by_id_test(Config) -> _ = capi_ct_helper_bouncer:mock_assert_op_ctx(<<"GetCountryByID">>, Config), diff --git a/apps/capi/test/capi_ct_helper.erl b/apps/capi/test/capi_ct_helper.erl index 3b8aad1..8f9b7a7 100644 --- a/apps/capi/test/capi_ct_helper.erl +++ b/apps/capi/test/capi_ct_helper.erl @@ -28,8 +28,8 @@ -define(CAPI_HOST_NAME, "localhost"). -define(CAPI_URL, ?CAPI_HOST_NAME ++ ":" ++ integer_to_list(?CAPI_PORT)). --define(TK_META_NS_KEYCLOAK, <<"test.rbkmoney.keycloak">>). --define(TK_META_NS_APIKEYMGMT, <<"test.rbkmoney.apikeymgmt">>). +-define(TK_META_NS_KEYCLOAK, <<"dev.vality.keycloak">>). +-define(TK_META_NS_APIKEYMGMT, <<"dev.vality.apikeymgmt">>). %% -type config() :: [{atom(), any()}]. @@ -190,26 +190,28 @@ mock_services(Services, SupOrConfig) -> replace_env(Env) -> maps:fold( fun(App, AppEnv, Acc) -> - AppReplaces = - maps:fold( - fun(Key, Value, AppAcc) -> - AccValue = - case application:get_env(App, Key) of - undefined -> undefined; - {ok, Original} -> {value, Original} - end, - application:set_env(App, Key, Value), - AppAcc#{Key => AccValue} - end, - #{}, - AppEnv - ), + AppReplaces = replace_env(App, AppEnv), Acc#{App => AppReplaces} end, #{}, Env ). +replace_env(App, AppEnv) -> + maps:fold( + fun(Key, Value, Acc) -> + AccValue = + case application:get_env(App, Key) of + undefined -> undefined; + {ok, Original} -> {value, Original} + end, + application:set_env(App, Key, Value), + Acc#{Key => AccValue} + end, + #{}, + AppEnv + ). + -spec restore_env(replaces()) -> ok. restore_env(Replaces) -> maps:foreach( diff --git a/apps/capi/test/capi_ct_helper_token_keeper.erl b/apps/capi/test/capi_ct_helper_token_keeper.erl index 9f88a02..f6e0f5a 100644 --- a/apps/capi/test/capi_ct_helper_token_keeper.erl +++ b/apps/capi/test/capi_ct_helper_token_keeper.erl @@ -89,7 +89,7 @@ mock_invoice_access_token(PartyID, InvoiceID, SupOrConfig) -> token => #{id => ?STRING}, scope => [#{party => #{id => PartyID}, invoice => #{id => InvoiceID}}] }, - {<<"com.rbkmoney.capi">>, create_bouncer_context(AuthParams), [ + {<<"dev.vality.capi">>, create_bouncer_context(AuthParams), [ api_key_metadata(), consumer_metadata(<<"client">>) ]} end), @@ -104,7 +104,7 @@ mock_invoice_template_access_token(PartyID, InvoiceTemplateID, SupOrConfig) -> token => #{id => ?STRING}, scope => [#{party => #{id => PartyID}, invoice_template => #{id => InvoiceTemplateID}}] }, - {<<"com.rbkmoney.capi">>, create_bouncer_context(AuthParams), api_key_metadata()} + {<<"dev.vality.capi">>, create_bouncer_context(AuthParams), api_key_metadata()} end), mock_token(Handler, SupOrConfig). @@ -117,7 +117,7 @@ mock_customer_access_token(PartyID, CustomerID, SupOrConfig) -> token => #{id => ?STRING}, scope => [#{party => #{id => PartyID}, customer => #{id => CustomerID}}] }, - {<<"com.rbkmoney.capi">>, create_bouncer_context(AuthParams), api_key_metadata()} + {<<"dev.vality.capi">>, create_bouncer_context(AuthParams), api_key_metadata()} end), mock_token(Handler, SupOrConfig). diff --git a/apps/capi/test/capi_deadline_tests_SUITE.erl b/apps/capi/test/capi_deadline_tests_SUITE.erl index 9050828..9981a4c 100644 --- a/apps/capi/test/capi_deadline_tests_SUITE.erl +++ b/apps/capi/test/capi_deadline_tests_SUITE.erl @@ -22,7 +22,7 @@ deadline_relative_ok_test/1 ]). --define(badresp(Code), {error, {invalid_response_code, Code}}). +-define(BADRESP(Code), {error, {invalid_response_code, Code}}). -type test_case_name() :: atom(). -type config() :: [{atom(), any()}]. @@ -106,7 +106,7 @@ deadline_absolute_ok_test(Config) -> Config ), Deadline = woody_deadline:from_timeout(3000), - ?badresp(504) = capi_client_invoices:get_invoice_by_id(Context#{deadline => Deadline}, ?STRING), + ?BADRESP(504) = capi_client_invoices:get_invoice_by_id(Context#{deadline => Deadline}, ?STRING), Deadline2 = woody_deadline:from_timeout(3000), {ok, _} = capi_client_categories:get_categories(Context#{deadline => Deadline2}). @@ -123,5 +123,5 @@ deadline_relative_ok_test(Config) -> ], Config ), - ?badresp(504) = capi_client_invoices:get_invoice_by_id(Context, ?STRING), + ?BADRESP(504) = capi_client_invoices:get_invoice_by_id(Context, ?STRING), {ok, _} = capi_client_categories:get_categories(Context). diff --git a/apps/capi/test/capi_dummy_data.hrl b/apps/capi/test/capi_dummy_data.hrl index 3291635..bce69d6 100644 --- a/apps/capi/test/capi_dummy_data.hrl +++ b/apps/capi/test/capi_dummy_data.hrl @@ -1132,7 +1132,21 @@ {payment_service, #domain_PaymentServiceRef{id = <<"qiwi">>}} => {payment_service, #domain_PaymentServiceObject{ ref = #domain_PaymentServiceRef{id = <<"qiwi">>}, - data = #domain_PaymentService{name = <<"Qiwi">>} + data = #domain_PaymentService{ + name = <<"Qiwi">>, + brand_name = <<"QIWI">>, + category = <<"wallets">>, + metadata = #{ + <<"test.ns">> => + {obj, #{ + <<"answer">> => {i, 42}, + <<"localization">> => + {obj, #{ + <<"ru_RU">> => {arr, [{str, <<"КИВИ Кошелёк">>}]} + }} + }} + } + } }}, {payment_system_legacy, #domain_LegacyBankCardPaymentSystemRef{id = visa}} => diff --git a/apps/capi/test/capi_invoice_template_access_token_tests_SUITE.erl b/apps/capi/test/capi_invoice_template_access_token_tests_SUITE.erl index 98bb9d1..745050d 100644 --- a/apps/capi/test/capi_invoice_template_access_token_tests_SUITE.erl +++ b/apps/capi/test/capi_invoice_template_access_token_tests_SUITE.erl @@ -3,10 +3,8 @@ -include_lib("common_test/include/ct.hrl"). -include_lib("stdlib/include/assert.hrl"). --include_lib("damsel/include/dmsl_domain_config_thrift.hrl"). -include_lib("damsel/include/dmsl_payment_processing_thrift.hrl"). -include_lib("capi_dummy_data.hrl"). --include_lib("jose/include/jose_jwk.hrl"). -export([all/0]). -export([groups/0]). @@ -25,12 +23,6 @@ get_invoice_payment_methods_by_tpl_id_ok_test/1 ]). --define(CAPI_PORT, 8080). --define(CAPI_HOST_NAME, "localhost"). --define(CAPI_URL, ?CAPI_HOST_NAME ++ ":" ++ integer_to_list(?CAPI_PORT)). - --define(badresp(Code), {error, {invalid_response_code, Code}}). - -type test_case_name() :: atom(). -type config() :: [{atom(), any()}]. -type group_name() :: atom(). diff --git a/apps/capi/test/capi_self_tests_SUITE.erl b/apps/capi/test/capi_self_tests_SUITE.erl index 5eaf8ce..f4dfb02 100644 --- a/apps/capi/test/capi_self_tests_SUITE.erl +++ b/apps/capi/test/capi_self_tests_SUITE.erl @@ -141,19 +141,12 @@ schema_param_validation(Config) -> query_param_validation(Config) -> _ = capi_ct_helper:mock_services( [ - {merchant_stat, fun('GetInvoices', _) -> {ok, ?STAT_RESPONSE_INVOICES} end}, - {geo_ip_service, fun('GetLocationName', _) -> {ok, #{123 => ?STRING}} end} + {merchant_stat, fun('GetInvoices', _) -> {ok, ?STAT_RESPONSE_INVOICES} end} ], Config ), Query0 = [ - {payerEmail, <<"te%^st@test.ru">>} + {'payerEmail', <<"te%^st@test.ru">>} ], {error, {request_validation_failed, _}} = - capi_client_searches:search_invoices(?config(context, Config), ?STRING, Query0), - Query1 = #{ - <<"geoIDs">> => <<"no,also no">>, - <<"language">> => <<"ru">> - }, - {error, {request_validation_failed, _}} = - capi_client_geo:get_location_names(?config(context, Config), Query1). + capi_client_searches:search_invoices(?config(context, Config), ?STRING, Query0). diff --git a/apps/capi/test/capi_token_keeper_data.hrl b/apps/capi/test/capi_token_keeper_data.hrl index 1d7667b..d3b72e7 100644 --- a/apps/capi/test/capi_token_keeper_data.hrl +++ b/apps/capi/test/capi_token_keeper_data.hrl @@ -1,7 +1,7 @@ --define(TK_AUTHORITY_KEYCLOAK, <<"test.rbkmoney.keycloak">>). --define(TK_AUTHORITY_APIKEYMGMT, <<"test.rbkmoney.apikeymgmt">>). +-define(TK_AUTHORITY_KEYCLOAK, <<"dev.vality.keycloak">>). +-define(TK_AUTHORITY_APIKEYMGMT, <<"dev.vality.apikeymgmt">>). --define(TK_META_PARTY_ID, <<"test.rbkmoney.party.id">>). --define(TK_META_TOKEN_CONSUMER, <<"test.rbkmoney.capi.consumer">>). --define(TK_META_USER_ID, <<"test.rbkmoney.user.id">>). --define(TK_META_USER_EMAIL, <<"test.rbkmoney.user.email">>). +-define(TK_META_PARTY_ID, <<"dev.vality.party.id">>). +-define(TK_META_TOKEN_CONSUMER, <<"dev.vality.capi.consumer">>). +-define(TK_META_USER_ID, <<"dev.vality.user.id">>). +-define(TK_META_USER_EMAIL, <<"dev.vality.user.email">>). diff --git a/apps/capi/test/capi_woody_tests_SUITE.erl b/apps/capi/test/capi_woody_tests_SUITE.erl index 863fd0b..444978f 100644 --- a/apps/capi/test/capi_woody_tests_SUITE.erl +++ b/apps/capi/test/capi_woody_tests_SUITE.erl @@ -22,7 +22,7 @@ woody_unknown_test/1 ]). --define(badresp(Code), {error, {invalid_response_code, Code}}). +-define(BADRESP(Code), {error, {invalid_response_code, Code}}). -type test_case_name() :: atom(). -type config() :: [{atom(), any()}]. @@ -93,7 +93,7 @@ end_per_testcase(_Name, C) -> -spec woody_unexpected_test(config()) -> _. woody_unexpected_test(Config) -> _ = capi_ct_helper:mock_services([{invoicing, fun('Get', _) -> {ok, "spanish inquisition"} end}], Config), - ?badresp(500) = capi_client_invoices:get_invoice_by_id(?config(context, Config), ?STRING). + ?BADRESP(500) = capi_client_invoices:get_invoice_by_id(?config(context, Config), ?STRING). -spec woody_unavailable_test(config()) -> _. woody_unavailable_test(Config) -> @@ -102,7 +102,7 @@ woody_unavailable_test(Config) -> invoicing => #{url => <<"http://spanish.inquision/v1/partymgmt">>} }} ]), - ?badresp(503) = capi_client_invoices:get_invoice_by_id(?config(context, Config), ?STRING). + ?BADRESP(503) = capi_client_invoices:get_invoice_by_id(?config(context, Config), ?STRING). -spec woody_retry_test(config()) -> _. woody_retry_test(Config) -> @@ -120,10 +120,10 @@ woody_retry_test(Config) -> invoicing => 5000 }} ]), - {Time, ?badresp(503)} = timer:tc(capi_client_invoices, get_invoice_by_id, [?config(context, Config), ?STRING]), + {Time, ?BADRESP(503)} = timer:tc(capi_client_invoices, get_invoice_by_id, [?config(context, Config), ?STRING]), true = (Time > 3000000) and (Time < 10000000). -spec woody_unknown_test(config()) -> _. woody_unknown_test(Config) -> _ = capi_ct_helper:mock_services([{invoicing, fun('Get', _) -> timer:sleep(60000) end}], Config), - ?badresp(504) = capi_client_invoices:get_invoice_by_id(?config(context, Config), ?STRING). + ?BADRESP(504) = capi_client_invoices:get_invoice_by_id(?config(context, Config), ?STRING). diff --git a/apps/capi_client/src/capi_client_geo.erl b/apps/capi_client/src/capi_client_geo.erl deleted file mode 100644 index 3a114c7..0000000 --- a/apps/capi_client/src/capi_client_geo.erl +++ /dev/null @@ -1,15 +0,0 @@ --module(capi_client_geo). - --export([get_location_names/2]). - --type context() :: capi_client_lib:context(). --type query_string() :: map(). - --spec get_location_names(context(), query_string()) -> {ok, term()} | {error, term()}. -get_location_names(Context, Query) -> - Params = #{ - qs_val => Query - }, - {Url, PreparedParams, Opts} = capi_client_lib:make_request(Context, Params), - Response = swag_client_geo_api:get_locations_names(Url, PreparedParams, Opts), - capi_client_lib:handle_response(Response). diff --git a/apps/capi_client/src/capi_client_payment_institutions.erl b/apps/capi_client/src/capi_client_payment_institutions.erl index 4de4d72..dd4726f 100644 --- a/apps/capi_client/src/capi_client_payment_institutions.erl +++ b/apps/capi_client/src/capi_client_payment_institutions.erl @@ -8,6 +8,7 @@ -export([get_payment_institution_payout_methods/3]). -export([get_payment_institution_payout_schedules/2]). -export([get_payment_institution_payout_schedules/4]). +-export([get_service_provider_by_id/2]). -type context() :: capi_client_lib:context(). @@ -80,10 +81,21 @@ get_payment_institution_payout_schedules(Context, PaymentInstitutionID, Currency <<"paymentInstitutionID">> => genlib:to_list(PaymentInstitutionID) }, qs_val => genlib_map:compact(#{ - currency => Currency, - payoutMethod => Method + 'currency' => Currency, + 'payoutMethod' => Method }) }, {Url, PreparedParams, Opts} = capi_client_lib:make_request(Context, Params), Response = swag_client_payment_institutions_api:get_payment_institution_payout_schedules(Url, PreparedParams, Opts), capi_client_lib:handle_response(Response). + +-spec get_service_provider_by_id(context(), binary()) -> {ok, term()} | {error, term()}. +get_service_provider_by_id(Context, ServiceProviderID) -> + Params = #{ + binding => #{ + <<"serviceProviderID">> => ServiceProviderID + } + }, + {Url, PreparedParams, Opts} = capi_client_lib:make_request(Context, Params), + Response = swag_client_payment_institutions_api:get_service_provider_by_id(Url, PreparedParams, Opts), + capi_client_lib:handle_response(Response). diff --git a/apps/capi_woody_client/src/capi_woody_client.erl b/apps/capi_woody_client/src/capi_woody_client.erl index b6ddd8c..3b445d0 100644 --- a/apps/capi_woody_client/src/capi_woody_client.erl +++ b/apps/capi_woody_client/src/capi_woody_client.erl @@ -85,8 +85,6 @@ get_service_modname(payouts) -> {payouts_payout_manager_thrift, 'PayoutManagement'}; get_service_modname(accounter) -> {dmsl_accounter_thrift, 'Accounter'}; -get_service_modname(geo_ip_service) -> - {dmsl_geo_ip_thrift, 'GeoIpService'}; get_service_modname(webhook_manager) -> {dmsl_webhooker_thrift, 'WebhookManager'}; get_service_modname(customer_management) -> diff --git a/build_utils b/build_utils deleted file mode 160000 index be44d69..0000000 --- a/build_utils +++ /dev/null @@ -1 +0,0 @@ -Subproject commit be44d69fc87b22a0bb82d98d6eae7658d1647f98 diff --git a/config/sys.config b/config/sys.config index c6b3ff9..621dbc1 100644 --- a/config/sys.config +++ b/config/sys.config @@ -76,10 +76,10 @@ }}, {auth_config, #{ metadata_mappings => #{ - party_id => <<"test.rbkmoney.party.id">>, - token_consumer => <<"test.rbkmoney.capi.consumer">>, - user_id => <<"test.rbkmoney.user.id">>, - user_email => <<"test.rbkmoney.user.email">> + party_id => <<"dev.vality.party.id">>, + token_consumer => <<"dev.vality.capi.consumer">>, + user_id => <<"dev.vality.user.id">>, + user_email => <<"dev.vality.user.email">> } }} ]}, @@ -94,8 +94,7 @@ webhook_manager => <<"http://hooker:8022/hook">>, merchant_stat => <<"http://magista:8022/stat">>, reporting => <<"http://reporter:8022/reports">>, - payouts => <<"http://payouter:8022/reports">>, - geo_ip_service => <<"http://columbus:8022/repo">> + payouts => <<"http://payouter:8022/reports">> }}, {service_deadlines, #{ party_management => 5000, % milliseconds @@ -107,7 +106,7 @@ % '_' work as "any" % default value is 'finish' % for more info look genlib_retry :: strategy() - % https://github.com/rbkmoney/genlib/blob/master/src/genlib_retry.erl#L19 + % https://github.com/valitydev/genlib/blob/master/src/genlib_retry.erl#L19 'Get' => {linear, 3, 1000}, '_' => finish } @@ -121,8 +120,8 @@ memory => 52428800 % 50Mb }}, {service_urls, #{ - 'Repository' => <<"dominant:8022/v1/domain/repository">>, - 'RepositoryClient' => <<"dominant:8022/v1/domain/repository_client">> + 'Repository' => <<"http://dominant:8022/v1/domain/repository">>, + 'RepositoryClient' => <<"http://dominant:8022/v1/domain/repository_client">> }} ]}, diff --git a/elvis.config b/elvis.config index 331d16e..dc246b7 100644 --- a/elvis.config +++ b/elvis.config @@ -1,33 +1,64 @@ [ {elvis, [ + {verbose, true}, {config, [ #{ - dirs => ["apps/*/**"], + dirs => ["apps/**/src", "apps/**/include"], filter => "*.erl", - ignore => ["apps/swag_*"], + ruleset => erl_files, rules => [ - {elvis_text_style, line_length, #{limit => 120, skip_comments => false}}, - {elvis_text_style, no_tabs}, - {elvis_text_style, no_trailing_whitespace}, - {elvis_style, macro_module_names}, - {elvis_style, operator_spaces, #{rules => [{right, ","}, {right, "++"}, {left, "++"}]}}, - {elvis_style, nesting_level, #{level => 4}}, - {elvis_style, god_modules, #{ - limit => 30, + %% Common settings + {elvis_text_style, line_length, #{limit => 120}}, + {elvis_style, nesting_level, #{level => 3}}, + {elvis_style, function_naming_convention, #{regex => "^([a-z][a-z0-9]*_?)*$"}}, + {elvis_style, no_if_expression, disable}, + %% Project settings + {elvis_style, numeric_format, #{ ignore => [ - capi_base_api_token_tests_SUITE, capi_idempotency_tests_SUITE + % Elvis fails with `bararg` here + capi_handler_utils ] }}, - {elvis_style, no_if_expression}, - {elvis_style, invalid_dynamic_call, #{ignore => [capi_domain]}}, - {elvis_style, used_ignored_variable}, - {elvis_style, no_behavior_info}, - {elvis_style, module_naming_convention, #{regex => "^[a-z]([a-z0-9]*_?)*(_SUITE)?$"}}, - {elvis_style, function_naming_convention, #{regex => "^[a-z]([a-z0-9]*_?)*$"}}, - {elvis_style, state_record_and_type, #{ignore => []}}, - {elvis_style, no_spec_with_records}, + % Verbose authorization code triggers this otherwise {elvis_style, dont_repeat_yourself, #{min_complexity => 30}}, - {elvis_style, no_debug_call, #{}} + {elvis_style, god_modules, #{ + ignore => [ + % TODO + % Need to rethink its responsibilities + capi_handler_utils + ] + }}, + {elvis_style, invalid_dynamic_call, #{ + ignore => [ + % Uses thrift types reflection through generated code + capi_domain + ] + }}, + {elvis_style, macro_names, #{ + ignore => [ + % Abuses lowercase macros too much + capi_feature_schemas, + capi_feature_schemas_legacy + ] + }} + ] + }, + #{ + dirs => ["apps/**/test"], + filter => "*.erl", + ruleset => erl_files, + rules => [ + {elvis_text_style, line_length, #{limit => 120}}, + {elvis_style, nesting_level, #{level => 3}}, + {elvis_style, no_if_expression, disable}, + % We want to use `ct:pal/2` and friends in test code. + {elvis_style, no_debug_call, disable}, + % Assert macros can trigger use of ignored binding, yet we want them for better + % readability. + {elvis_style, used_ignored_variable, disable}, + % Tests are usually more comprehensible when a bit more verbose. + {elvis_style, dont_repeat_yourself, #{min_complexity => 50}}, + {elvis_style, god_modules, disable} ] }, #{ @@ -41,21 +72,22 @@ ruleset => elvis_config }, #{ - dirs => [".", "apps/*/*"], + dirs => [".", "apps/*"], filter => "rebar.config", - ignore => ["apps/swag_*"], + ruleset => rebar_config, rules => [ - {elvis_text_style, line_length, #{limit => 120, skip_comments => false}}, + {elvis_text_style, line_length, #{limit => 120}}, {elvis_text_style, no_tabs}, - {elvis_text_style, no_trailing_whitespace} + {elvis_text_style, no_trailing_whitespace}, + %% Temporarily disabled till regex pattern is available + {elvis_project, no_deps_master_rebar, disable} ] }, #{ - dirs => ["apps/**"], + dirs => ["apps/*/src"], filter => "*.app.src", - ignore => ["apps/swag_*"], rules => [ - {elvis_text_style, line_length, #{limit => 120, skip_comments => false}}, + {elvis_text_style, line_length, #{limit => 120}}, {elvis_text_style, no_tabs}, {elvis_text_style, no_trailing_whitespace} ] diff --git a/rebar.config b/rebar.config index 32128b5..abf690d 100644 --- a/rebar.config +++ b/rebar.config @@ -27,32 +27,33 @@ %% Common project dependencies. {deps, [ {cowboy, "2.9.0"}, - {jose, "1.11.2"}, - {genlib, {git, "https://github.com/rbkmoney/genlib.git", {branch, "master"}}}, - {cowboy_draining_server, {git, "https://github.com/rbkmoney/cowboy_draining_server.git", {branch, "master"}}}, - {woody, {git, "https://github.com/rbkmoney/woody_erlang.git", {branch, "master"}}}, - {woody_user_identity, {git, "https://github.com/rbkmoney/woody_erlang_user_identity.git", {branch, "master"}}}, - {woody_api_hay, {git, "https://github.com/rbkmoney/woody_api_hay.git", {branch, "master"}}}, - {damsel, {git, "https://github.com/rbkmoney/damsel.git", {branch, "master"}}}, - {bender_proto, {git, "https://github.com/rbkmoney/bender-proto.git", {branch, "master"}}}, - {bender_client, {git, "https://github.com/rbkmoney/bender_client_erlang.git", {branch, "master"}}}, - {reporter_proto, {git, "https://github.com/rbkmoney/reporter-proto.git", {branch, "master"}}}, - {dmt_client, {git, "https://github.com/rbkmoney/dmt_client.git", {branch, "master"}}}, - {cowboy_cors, {git, "https://github.com/rbkmoney/cowboy_cors.git", {branch, "master"}}}, - {cowboy_access_log, {git, "https://github.com/rbkmoney/cowboy_access_log.git", {branch, "master"}}}, - {payproc_errors, {git, "https://github.com/rbkmoney/payproc-errors-erlang.git", {branch, "master"}}}, - {scoper, {git, "https://github.com/rbkmoney/scoper.git", {branch, master}}}, - {erl_health, {git, "https://github.com/rbkmoney/erlang-health.git", {branch, master}}}, - {lechiffre, {git, "https://github.com/rbkmoney/lechiffre.git", {branch, master}}}, - {prometheus, "4.8.1"}, - {prometheus_cowboy, "0.1.8"}, - {bouncer_proto, {git, "https://github.com/rbkmoney/bouncer-proto.git", {branch, master}}}, - {bouncer_client, {git, "https://github.com/rbkmoney/bouncer_client_erlang.git", {branch, master}}}, - {token_keeper_client, {git, "https://github.com/rbkmoney/token-keeper-client.git", {branch, master}}}, - {party_client, {git, "https://github.com/rbkmoney/party_client_erlang.git", {branch, master}}}, - {payout_manager_proto, {git, "https://github.com/rbkmoney/payout-manager-proto.git", {branch, master}}}, - {how_are_you, {git, "https://github.com/rbkmoney/how_are_you.git", {branch, master}}}, - {feat, {git, "https://github.com/rbkmoney/feat.git", {branch, master}}} + %% NOTE + %% Pinning to version "1.11.2" from hex here causes constant upgrading and recompilation of the entire project + {jose, {git, "https://github.com/potatosalad/erlang-jose.git", {tag, "1.11.2"}}}, + {genlib, {git, "https://github.com/valitydev/genlib.git", {branch, "master"}}}, + {cowboy_draining_server, {git, "https://github.com/valitydev/cowboy_draining_server.git", {branch, "master"}}}, + {woody, {git, "https://github.com/valitydev/woody_erlang.git", {branch, "master"}}}, + {woody_user_identity, {git, "https://github.com/valitydev/woody_erlang_user_identity.git", {branch, "master"}}}, + {damsel, {git, "https://github.com/valitydev/damsel.git", {branch, "master"}}}, + {bender_proto, {git, "https://github.com/valitydev/bender-proto.git", {branch, "master"}}}, + {bender_client, {git, "https://github.com/valitydev/bender_client_erlang.git", {branch, "master"}}}, + {reporter_proto, {git, "https://github.com/valitydev/reporter-proto.git", {branch, "master"}}}, + {dmt_client, {git, "https://github.com/valitydev/dmt_client.git", {branch, "master"}}}, + {cowboy_cors, {git, "https://github.com/valitydev/cowboy_cors.git", {branch, "master"}}}, + {cowboy_access_log, {git, "https://github.com/valitydev/cowboy_access_log.git", {branch, "master"}}}, + {payproc_errors, {git, "https://github.com/valitydev/payproc-errors-erlang.git", {branch, "master"}}}, + {scoper, {git, "https://github.com/valitydev/scoper.git", {branch, master}}}, + {erl_health, {git, "https://github.com/valitydev/erlang-health.git", {branch, master}}}, + {lechiffre, {git, "https://github.com/valitydev/lechiffre.git", {branch, master}}}, + {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}}}, + {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 + {swag_server, {git, "https://github.com/valitydev/swag-payments", {branch, "release/erlang/server/v2"}}}, + {swag_client, {git, "https://github.com/valitydev/swag-payments", {branch, "release/erlang/client/v2"}}} ]}. %% XRef checks @@ -84,12 +85,20 @@ {profiles, [ {prod, [ {deps, [ + %% NOTE + %% Because of a dependency conflict, prometheus libs are only included in production build for now + %% https://github.com/project-fifo/rebar3_lint/issues/42 + %% https://github.com/valitydev/hellgate/pull/2/commits/884724c1799703cee4d1033850fe32c17f986d9e + {prometheus, "4.8.1"}, + {prometheus_cowboy, "0.1.8"}, {recon, "2.3.6"}, {logger_logstash_formatter, - {git, "https://github.com/rbkmoney/logger_logstash_formatter.git", {ref, "87e52c7"}}} + {git, "https://github.com/valitydev/logger_logstash_formatter.git", {ref, "87e52c7"}}}, + {iosetopts, {git, "https://github.com/valitydev/iosetopts.git", {ref, "edb445c"}}} ]}, {relx, [ {release, {capi, "0.1.0"}, [ + iosetopts, % tools for introspection {recon, load}, % debugger @@ -97,18 +106,14 @@ % profiler {tools, load}, logger_logstash_formatter, - capi, + prometheus, + prometheus_cowboy, sasl, - woody_api_hay, - how_are_you + capi ]}, {mode, minimal}, {sys_config, "./config/sys.config"}, {vm_args, "./config/vm.args"}, - {overlay, [ - {mkdir, "var/keys/capi"}, - {copy, "var/keys/capi/private.pem", "var/keys/capi/private.pem"} - ]}, {extended_start_script, true} ]} ]}, @@ -118,7 +123,9 @@ ]}. {plugins, [ - {erlfmt, "1.0.0"} + {covertool, "2.0.4"}, + {erlfmt, "1.0.0"}, + {rebar3_lint, "1.0.1"} ]}. {erlfmt, [ @@ -126,6 +133,9 @@ {files, ["apps/capi*/{src,include,test}/*.{hrl,erl}", "rebar.config", "elvis.config"]} ]}. -{pre_hooks, [ - {thrift, "git submodule update --init"} +{covertool, [ + {coverdata_files, [ + "eunit.coverdata", + "ct.coverdata" + ]} ]}. diff --git a/rebar.lock b/rebar.lock index c6e4125..f329324 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,69 +1,63 @@ {"1.2.0", -[{<<"accept">>,{pkg,<<"accept">>,<<"0.3.5">>},2}, - {<<"bear">>,{pkg,<<"bear">>,<<"0.9.0">>},2}, - {<<"bender_client">>, - {git,"https://github.com/rbkmoney/bender_client_erlang.git", +[{<<"bender_client">>, + {git,"https://github.com/valitydev/bender_client_erlang.git", {ref,"29501d6f6425bc310ef6b37b62790126bdff356b"}}, 0}, {<<"bender_proto">>, - {git,"https://github.com/rbkmoney/bender-proto.git", - {ref,"dfe271b09a2b8e457f50e4732b905a0b846bf529"}}, + {git,"https://github.com/valitydev/bender-proto.git", + {ref,"e08deadaab22019ff50a5d96ca6befff0034dab3"}}, 0}, {<<"bouncer_client">>, - {git,"https://github.com/rbkmoney/bouncer_client_erlang.git", + {git,"https://github.com/valitydev/bouncer_client_erlang.git", {ref,"535449a459b70643836c440a863b42656f2a1409"}}, 0}, {<<"bouncer_proto">>, - {git,"https://github.com/rbkmoney/bouncer-proto.git", - {ref,"19bd3d674fd4182927063e17e274559a08d422c5"}}, + {git,"https://github.com/valitydev/bouncer-proto.git", + {ref,"96bd74dbf1db33ce1cbc6f6d3ce5a9b598ee29f5"}}, 0}, {<<"cache">>,{pkg,<<"cache">>,<<"2.3.3">>},1}, - {<<"certifi">>,{pkg,<<"certifi">>,<<"2.6.1">>},1}, + {<<"certifi">>,{pkg,<<"certifi">>,<<"2.6.1">>},2}, {<<"cg_mon">>, - {git,"https://github.com/rbkmoney/cg_mon.git", + {git,"https://github.com/valitydev/cg_mon.git", {ref,"5a87a37694e42b6592d3b4164ae54e0e87e24e18"}}, 1}, {<<"cowboy">>,{pkg,<<"cowboy">>,<<"2.9.0">>},0}, {<<"cowboy_access_log">>, - {git,"https://github.com/rbkmoney/cowboy_access_log.git", - {ref,"c058ad42cd11c6503feb398fb8587c2f72155a60"}}, + {git,"https://github.com/valitydev/cowboy_access_log.git", + {ref,"04da359e022cf05c5c93812504d5791d6bc97453"}}, 0}, {<<"cowboy_cors">>, - {git,"https://github.com/rbkmoney/cowboy_cors.git", + {git,"https://github.com/valitydev/cowboy_cors.git", {ref,"5a3b084fb8c5a4ff58e3c915a822d709d6023c3b"}}, 0}, {<<"cowboy_draining_server">>, - {git,"https://github.com/rbkmoney/cowboy_draining_server.git", + {git,"https://github.com/valitydev/cowboy_draining_server.git", {ref,"186cf4d0722d4ad79afe73d371df6b1371e51905"}}, 0}, {<<"cowlib">>,{pkg,<<"cowlib">>,<<"2.11.0">>},1}, {<<"damsel">>, - {git,"https://github.com/rbkmoney/damsel.git", - {ref,"af7c970159e8575de98c1b2d85cfdd8e00b7545d"}}, + {git,"https://github.com/valitydev/damsel.git", + {ref,"b25d3365e1f2b075ffea30b3a2e1c41eb3f6145b"}}, 0}, {<<"dmt_client">>, - {git,"https://github.com/rbkmoney/dmt_client.git", - {ref,"3f66402843ffeb488010f707a193858cb09325e0"}}, + {git,"https://github.com/valitydev/dmt_client.git", + {ref,"e9b1961b96ce138a34f6cf9cebef6ddf66af1942"}}, 0}, {<<"dmt_core">>, - {git,"https://github.com/rbkmoney/dmt_core.git", - {ref,"5a0ff399dee3fd606bb864dd0e27ddde539345e2"}}, + {git,"https://github.com/valitydev/dmt_core.git", + {ref,"910e20edbe03ae4645aa3923baea8054003753b5"}}, 1}, - {<<"email_validator">>,{pkg,<<"email_validator">>,<<"1.1.0">>},0}, + {<<"email_validator">>,{pkg,<<"email_validator">>,<<"1.1.0">>},1}, {<<"erl_health">>, - {git,"https://github.com/rbkmoney/erlang-health.git", + {git,"https://github.com/valitydev/erlang-health.git", {ref,"5958e2f35cd4d09f40685762b82b82f89b4d9333"}}, 0}, {<<"feat">>, - {git,"https://github.com/rbkmoney/feat.git", + {git,"https://github.com/valitydev/feat.git", {ref,"bf7dff68c822e58769da962e7f99c3e428a88551"}}, 0}, - {<<"folsom">>, - {git,"https://github.com/folsom-project/folsom.git", - {ref,"62fd0714e6f0b4e7833880afe371a9c882ea0fc2"}}, - 1}, {<<"genlib">>, - {git,"https://github.com/rbkmoney/genlib.git", + {git,"https://github.com/valitydev/genlib.git", {ref,"82c5ff3866e3019eb347c7f1d8f1f847bed28c10"}}, 0}, {<<"gproc">>,{pkg,<<"gproc">>,<<"0.9.0">>},1}, @@ -71,92 +65,89 @@ {git,"https://github.com/ninenines/gun.git", {ref,"e7dd9f227e46979d8073e71c683395a809b78cb4"}}, 1}, - {<<"hackney">>,{pkg,<<"hackney">>,<<"1.17.4">>},0}, - {<<"how_are_you">>, - {git,"https://github.com/rbkmoney/how_are_you.git", - {ref,"2fd8013420328464c2c84302af2781b86577b39f"}}, - 0}, - {<<"idna">>,{pkg,<<"idna">>,<<"6.1.1">>},1}, + {<<"hackney">>,{pkg,<<"hackney">>,<<"1.17.4">>},1}, + {<<"idna">>,{pkg,<<"idna">>,<<"6.1.1">>},2}, {<<"jesse">>, - {git,"https://github.com/rbkmoney/jesse.git", + {git,"https://github.com/valitydev/jesse.git", {ref,"9b980b7f9ce09b6a136fe5a23d404d1b903f3061"}}, + 1}, + {<<"jose">>, + {git,"https://github.com/potatosalad/erlang-jose.git", + {ref,"991649695aaccd92c8effb1c1e88e6159fe8e9a6"}}, 0}, - {<<"jose">>,{pkg,<<"jose">>,<<"1.11.2">>},0}, - {<<"jsx">>,{pkg,<<"jsx">>,<<"3.1.0">>},0}, + {<<"jsx">>,{pkg,<<"jsx">>,<<"3.1.0">>},1}, {<<"lechiffre">>, - {git,"https://github.com/rbkmoney/lechiffre.git", + {git,"https://github.com/valitydev/lechiffre.git", {ref,"ab894bc7c0e830f4372d302036f044d20c76ca73"}}, 0}, - {<<"metrics">>,{pkg,<<"metrics">>,<<"1.0.1">>},1}, - {<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.2.0">>},1}, + {<<"metrics">>,{pkg,<<"metrics">>,<<"1.0.1">>},2}, + {<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.2.0">>},2}, {<<"msgpack_proto">>, - {git,"https://github.com/rbkmoney/msgpack-proto.git", + {git,"https://github.com/valitydev/msgpack-proto.git", {ref,"ec15d5e854ea60c58467373077d90c2faf6273d8"}}, 1}, {<<"org_management_proto">>, - {git,"git@github.com:rbkmoney/org-management-proto.git", + {git,"https://github.com/valitydev/org-management-proto.git", {ref,"06c5c8430e445cb7874e54358e457cbb5697fc32"}}, 1}, - {<<"parse_trans">>,{pkg,<<"parse_trans">>,<<"3.4.0">>},0}, + {<<"parse_trans">>,{pkg,<<"parse_trans">>,<<"3.4.1">>},1}, {<<"party_client">>, - {git,"https://github.com/rbkmoney/party_client_erlang.git", - {ref,"8afd535d96a9994d63c678c87688f3b4ff016781"}}, + {git,"https://github.com/valitydev/party_client_erlang.git", + {ref,"8fc5595c4c61c0fe3d2dc29a61f48ba94e9bdef7"}}, 0}, {<<"payout_manager_proto">>, - {git,"https://github.com/rbkmoney/payout-manager-proto.git", + {git,"https://github.com/valitydev/payout-manager-proto.git", {ref,"b6cd2286a438685fceb1f020e24dc42750b74a3e"}}, 0}, {<<"payproc_errors">>, - {git,"https://github.com/rbkmoney/payproc-errors-erlang.git", + {git,"https://github.com/valitydev/payproc-errors-erlang.git", {ref,"ebbfa3775c77d665f519d39ca9afa08c28d7733f"}}, 0}, - {<<"prometheus">>,{pkg,<<"prometheus">>,<<"4.8.1">>},0}, - {<<"prometheus_cowboy">>,{pkg,<<"prometheus_cowboy">>,<<"0.1.8">>},0}, - {<<"prometheus_httpd">>,{pkg,<<"prometheus_httpd">>,<<"2.1.11">>},1}, - {<<"quantile_estimator">>,{pkg,<<"quantile_estimator">>,<<"0.2.1">>},1}, {<<"ranch">>,{pkg,<<"ranch">>,<<"1.8.0">>},1}, {<<"reporter_proto">>, - {git,"https://github.com/rbkmoney/reporter-proto.git", + {git,"https://github.com/valitydev/reporter-proto.git", {ref,"aafbfac4463711d43f8e8ed4da103967b95e1fb6"}}, 0}, {<<"scoper">>, - {git,"https://github.com/rbkmoney/scoper.git", - {ref,"a2c2b7a4b1770205b7b1dbe2e0df6c88044e6244"}}, + {git,"https://github.com/valitydev/scoper.git", + {ref,"7f3183df279bc8181efe58dafd9cae164f495e6f"}}, 0}, {<<"snowflake">>, - {git,"https://github.com/rbkmoney/snowflake.git", + {git,"https://github.com/valitydev/snowflake.git", {ref,"de159486ef40cec67074afe71882bdc7f7deab72"}}, 1}, - {<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.6">>},1}, + {<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.6">>},2}, + {<<"swag_client">>, + {git,"https://github.com/valitydev/swag-payments", + {ref,"d42fe53131e605b86a6fafd731c8d17275a2d1c3"}}, + 0}, + {<<"swag_server">>, + {git,"https://github.com/valitydev/swag-payments", + {ref,"d66adf6f04071cf587ae1d11c6d3502fbe5fe0af"}}, + 0}, {<<"thrift">>, - {git,"https://github.com/rbkmoney/thrift_erlang.git", + {git,"https://github.com/valitydev/thrift_erlang.git", {ref,"846a0819d9b6d09d0c31f160e33a78dbad2067b4"}}, 1}, {<<"token_keeper_client">>, - {git,"https://github.com/rbkmoney/token-keeper-client.git", + {git,"https://github.com/valitydev/token-keeper-client.git", {ref,"27158ea5d3e3c74f0090f8d2ac3f2ca52ab39584"}}, 0}, {<<"token_keeper_proto">>, - {git,"https://github.com/rbkmoney/token-keeper-proto.git", - {ref,"15781716691a72de8c8f065c11c5b08173fc8434"}}, + {git,"https://github.com/valitydev/token-keeper-proto.git", + {ref,"c7f48d24a561c95b8135d3b07fd2ff55a62eb308"}}, 1}, - {<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.0">>},1}, + {<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.0">>},2}, {<<"woody">>, - {git,"https://github.com/rbkmoney/woody_erlang.git", - {ref,"330bdcf71e99c2ea7aed424cd718939cb360ec1c"}}, - 0}, - {<<"woody_api_hay">>, - {git,"https://github.com/rbkmoney/woody_api_hay.git", - {ref,"3cb6404bfbe80478a71c88b33c0bd352e94cd3c3"}}, + {git,"https://github.com/valitydev/woody_erlang.git", + {ref,"0c2e16dfc8a51f6f63fcd74df982178a9aeab322"}}, 0}, {<<"woody_user_identity">>, - {git,"https://github.com/rbkmoney/woody_erlang_user_identity.git", + {git,"https://github.com/valitydev/woody_erlang_user_identity.git", {ref,"a480762fea8d7c08f105fb39ca809482b6cb042e"}}, 0}]}. [ {pkg_hash,[ - {<<"accept">>, <<"B33B127ABCA7CC948BBE6CAA4C263369ABF1347CFA9D8E699C6D214660F10CD1">>}, - {<<"bear">>, <<"A31CCF5361791DD5E708F4789D67E2FEF496C4F05935FC59ADC11622F834D128">>}, {<<"cache">>, <<"B23A5FE7095445A88412A6E614C933377E0137B44FFED77C9B3FEF1A731A20B2">>}, {<<"certifi">>, <<"DBAB8E5E155A0763EEA978C913CA280A6B544BFA115633FA20249C3D396D9493">>}, {<<"cowboy">>, <<"865DD8B6607E14CF03282E10E934023A1BD8BE6F6BACF921A7E2A96D800CD452">>}, @@ -165,21 +156,14 @@ {<<"gproc">>, <<"853CCB7805E9ADA25D227A157BA966F7B34508F386A3E7E21992B1B484230699">>}, {<<"hackney">>, <<"99DA4674592504D3FB0CFEF0DB84C3BA02B4508BAE2DFF8C0108BAA0D6E0977C">>}, {<<"idna">>, <<"8A63070E9F7D0C62EB9D9FCB360A7DE382448200FBBD1B106CC96D3D8099DF8D">>}, - {<<"jose">>, <<"F4C018CCF4FDCE22C71E44D471F15F723CB3EFAB5D909AB2BA202B5BF35557B3">>}, {<<"jsx">>, <<"D12516BAA0BB23A59BB35DCCAF02A1BD08243FCBB9EFE24F2D9D056CCFF71268">>}, {<<"metrics">>, <<"25F094DEA2CDA98213CECC3AEFF09E940299D950904393B2A29D191C346A8486">>}, {<<"mimerl">>, <<"67E2D3F571088D5CFD3E550C383094B47159F3EEE8FFA08E64106CDF5E981BE3">>}, - {<<"parse_trans">>, <<"BB87AC362A03CA674EBB7D9D498F45C03256ADED7214C9101F7035EF44B798C7">>}, - {<<"prometheus">>, <<"FA76B152555273739C14B06F09F485CF6D5D301FE4E9D31B7FF803D26025D7A0">>}, - {<<"prometheus_cowboy">>, <<"CFCE0BC7B668C5096639084FCD873826E6220EA714BF60A716F5BD080EF2A99C">>}, - {<<"prometheus_httpd">>, <<"F616ED9B85B536B195D94104063025A91F904A4CFC20255363F49A197D96C896">>}, - {<<"quantile_estimator">>, <<"EF50A361F11B5F26B5F16D0696E46A9E4661756492C981F7B2229EF42FF1CD15">>}, + {<<"parse_trans">>, <<"6E6AA8167CB44CC8F39441D05193BE6E6F4E7C2946CB2759F015F8C56B76E5FF">>}, {<<"ranch">>, <<"8C7A100A139FD57F17327B6413E4167AC559FBC04CA7448E9BE9057311597A1D">>}, {<<"ssl_verify_fun">>, <<"CF344F5692C82D2CD7554F5EC8FD961548D4FD09E7D22F5B62482E5AEAEBD4B0">>}, {<<"unicode_util_compat">>, <<"BC84380C9AB48177092F43AC89E4DFA2C6D62B40B8BD132B1059ECC7232F9A78">>}]}, {pkg_hash_ext,[ - {<<"accept">>, <<"11B18C220BCC2EAB63B5470C038EF10EB6783BCB1FCDB11AA4137DEFA5AC1BB8">>}, - {<<"bear">>, <<"47F71F098F2E3CD05E124A896C5EC2F155967A2B6FF6731E0D627312CCAB7E28">>}, {<<"cache">>, <<"44516CE6FA03594D3A2AF025DD3A87BFE711000EB730219E1DDEFC816E0AA2F4">>}, {<<"certifi">>, <<"524C97B4991B3849DD5C17A631223896272C6B0AF446778BA4675A1DFF53BB7E">>}, {<<"cowboy">>, <<"2C729F934B4E1AA149AFF882F57C6372C15399A20D54F65C8D67BEF583021BDE">>}, @@ -188,15 +172,10 @@ {<<"gproc">>, <<"587E8AF698CCD3504CF4BA8D90F893EDE2B0F58CABB8A916E2BF9321DE3CF10B">>}, {<<"hackney">>, <<"DE16FF4996556C8548D512F4DBE22DD58A587BF3332E7FD362430A7EF3986B16">>}, {<<"idna">>, <<"92376EB7894412ED19AC475E4A86F7B413C1B9FBB5BD16DCCD57934157944CEA">>}, - {<<"jose">>, <<"98143FBC48D55F3A18DABA82D34FE48959D44538E9697C08F34200FA5F0947D2">>}, {<<"jsx">>, <<"0C5CC8FDC11B53CC25CF65AC6705AD39E54ECC56D1C22E4ADB8F5A53FB9427F3">>}, {<<"metrics">>, <<"69B09ADDDC4F74A40716AE54D140F93BEB0FB8978D8636EADED0C31B6F099F16">>}, {<<"mimerl">>, <<"F278585650AA581986264638EBF698F8BB19DF297F66AD91B18910DFC6E19323">>}, - {<<"parse_trans">>, <<"F99E368830BEA44552224E37E04943A54874F08B8590485DE8D13832B63A2DC3">>}, - {<<"prometheus">>, <<"6EDFBE928D271C7F657A6F2C46258738086584BD6CAE4A000B8B9A6009BA23A5">>}, - {<<"prometheus_cowboy">>, <<"BA286BECA9302618418892D37BCD5DC669A6CC001F4EB6D6AF85FF81F3F4F34C">>}, - {<<"prometheus_httpd">>, <<"0BBE831452CFDF9588538EB2F570B26F30C348ADAE5E95A7D87F35A5910BCF92">>}, - {<<"quantile_estimator">>, <<"282A8A323CA2A845C9E6F787D166348F776C1D4A41EDE63046D72D422E3DA946">>}, + {<<"parse_trans">>, <<"620A406CE75DADA827B82E453C19CF06776BE266F5A67CFF34E1EF2CBB60E49A">>}, {<<"ranch">>, <<"49FBCFD3682FAB1F5D109351B61257676DA1A2FDBE295904176D5E521A2DDFE5">>}, {<<"ssl_verify_fun">>, <<"BDB0D2471F453C88FF3908E7686F86F9BE327D065CC1EC16FA4540197EA04680">>}, {<<"unicode_util_compat">>, <<"25EEE6D67DF61960CF6A794239566599B09E17E668D3700247BC498638152521">>}]} diff --git a/schemes/swag b/schemes/swag deleted file mode 160000 index 42257c4..0000000 --- a/schemes/swag +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 42257c406df732cc5b6cd7a864fca94ec9df59bf diff --git a/var/keys/capi/private.pem b/var/keys/capi/private.pem deleted file mode 100644 index 670e82a..0000000 --- a/var/keys/capi/private.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEA4MUtYkvoIAHNgvYtHSydanyY1qD8nJ+D/A1FFp5LF4SmM9nn -vSfTFC2T3D53sCR/DtUzCFIQwZIXXHob22ndFydZqhahrYLLJkpH5IXMy593Sho/ -oXzxgwkbXaOMevcLFZcj5AneG+q2vFjaDGeQAJaAAPGinMo6UN94DYguNH2s6zqo -yRc8ng6KWD5UgEFTIEWni1RIZvp2NAnSkh/SeI1zs9uY6AR7bf6oFSChTd9m+li5 -d20L5tc0aX7LG842SJEM2dJKckI4ZDZHvU6nDitH3TGrxkMa0CqLe7nUOfvSff2c -H9m0CzSbPy/SnyTQLklWoFsi9z2cqqtY6SvR7QIDAQABAoIBADAoz1KSZQgGmtwG -lx/7ITdhvvWtxLJiU0s8JKN2Ayzk1R+i/s4+rDFUmqvEDq0FBNxOvgJ4YvK2tJ6x -4yoeAqslWUbiVn3w2ko3/DNwn7K5VjvgZ+XX+X9UAjMMCduG9y8HFT+VBawBnGm6 -t+2UevxFQuPw4iCqC9isKPLtTMkeBXfaCA+tzBqVytlBeW5nJG1Bh9GSV6OeeNoc -x6lh1X+7kxk/qLQZsogNwZXxPLuIK0qJCfsGzMYodSi43nv2mFtl5vBt0M+iU42i -KrL32SlQmkBI4st/HIie9YpSjj55llOU6L0KBPhH58wc8LDEc2Kwcxeow4/McO0E -fSwf9pkCgYEA+4v+371szXbUTfOBOBO7+bGbTo0gzJ8JnMaSdVDLhBaqyp5dbztS -TPiaCqfEYk4AYnl2dR7nLYRca/WRDle7hvDqB7K2RWWS58RDifiQ4gfJM9lW4Ocu -SIhnxVmr4iVdo4eOs6pxe8yRtF1U+uK8WuoV06+lgL/esEJB2JPyeQsCgYEA5L/U -osQFOogSk1Ycjl66UEXm0Y2HzFONTKMSellUnkdSSscx6+mLOn7eL5voSNSJrnCw -Tfh3uZ0NOh63Yw3aPGCwtn+EIflW1hzx+DJMvCS5TaU3BZF954rljklJL6VpaIPP -fXrc0z1FcsAT2s3aQNmEK2SWp7Y44V6mpQn7a+cCgYEA0Tf+dD+MOFRmfrNSvb6E -MUkMwMfXCPoaN6BdfmAF9cYYpdAULIjtigGXtdcWGyF/ZmhaI03hv9UAPfcQgBpu -ae0E6gQ1YAD8r/Jorl/kuWr6aTqS7Rq7Py7dCKLtuHmVqYb9JOhV3T8nzRl3rfhZ -61AZeWj1QeHUKUvikm1zVkMCgYEAyan42xn3BhgKUEw9VqJanQRTLnEYxGDwlBy7 -4JM6j2OPQA+GilXVgddxKAXJ7dM6IkiElei0HDZB//gucqw2tr4DbJDUu2LnVFIm -XEpz7fZuSu6ZqFYQ6n1ATYV8eP3aBOMXnKchYTWGMVj26BJNFJju9ZZzXx293aol -PiCjwAcCgYAmOtRZRtf/p1eXPz1JN1OwEVSrnghJP5KBA8XGsnBmQUTeMmHo3Wl7 -rELKg0O2bsPtTTAvm5bfLsRgvee+EY28mAY6MA8xJNHB6OabOHuRHqX7ow/LOagK -15mUtZ9f8AaKamZ3Bmg/XWWJxNmeCt5LJDr1OnmCDyItbfF9DxnXXg== ------END RSA PRIVATE KEY-----