TD-124: Setup CI/CD with GH Actions (#1)

* Drop proprietary CI stuff
* Stop including default secret in release
* Fix io encoding w/ iosetopts
* Bump to valitydev/damsel@dcd92dd
* Implement and test `GetServiceProviderByID` op
* Depend on valitydev/swag-payments@a639270
* Drop geo api handler and tests
* Switch to valitydev upstream
  * valitydev/cowboy_access_log@04da359
  * valitydev/damsel@b25d336
  * valitydev/dmt_client@e9b1961
  * valitydev/dmt_core@910e20e
  * valitydev/party_client_erlang@8fc5595
  * valitydev/woody_erlang@0c2e16d
  * valitydev/woody_api_hay@4c39134
* Drop client url logging
* Setup CI/CD with GH Actions
* Drop dead links

Co-authored-by: ndiezel0 <ndiezel0@gmail.com>
This commit is contained in:
Andrew Mayorov 2022-02-04 19:28:33 +03:00 committed by GitHub
parent 8381da653a
commit 14369d48f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
58 changed files with 1194 additions and 1305 deletions

7
.dockerignore Normal file
View File

@ -0,0 +1,7 @@
/_build/
/.git/
/.github/
/.vscode/
/.idea/
erl_crash.dump
rebar3.crashdump

7
.env Normal file
View File

@ -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

53
.github/workflows/build-image.yml vendored Normal file
View File

@ -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 }}

38
.github/workflows/erlang-checks.yml vendored Normal file
View File

@ -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 }}

5
.gitignore vendored
View File

@ -12,13 +12,10 @@ erl_crash.dump
/_checkouts/
# generated
apps/swag_server/*
apps/swag_client/*
*.beam
.image.dev
# containerization
\#*
.\#*
Dockerfile
docker-compose.yml
tags

8
.gitmodules vendored
View File

@ -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

40
Dockerfile Normal file
View File

@ -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

18
Dockerfile.dev Normal file
View File

@ -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

View File

@ -1,26 +0,0 @@
#!/bin/bash
cat <<EOF
FROM $BASE_IMAGE
MAINTAINER Artem Ocheredko <a.ocheredko@rbkmoney.com>
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

22
Jenkinsfile vendored
View File

@ -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')
}

174
Makefile
View File

@ -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)

View File

@ -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,

View File

@ -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}}

View File

@ -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,

View File

@ -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) ->

View File

@ -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} ->

View File

@ -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}};

View File

@ -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) ->

View File

@ -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} ->

View File

@ -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">>,

View File

@ -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

View File

@ -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">>;

View File

@ -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.

View File

@ -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
}.

View File

@ -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}};

View File

@ -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),

View File

@ -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)}

View File

@ -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
)
}).

View File

@ -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.

View File

@ -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} ->

View File

@ -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,

View File

@ -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,

View File

@ -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}};

View File

@ -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 ->

View File

@ -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">>;

View File

@ -6,6 +6,8 @@
-export([marshal/1]).
-export([unmarshal/1]).
-export_type([value/0]).
%%
-type value() :: term().

View File

@ -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.

View File

@ -324,7 +324,7 @@ merge_deduplication_card_test() ->
],
SamsungPayMethod = #{
<<"method">> => <<"BankCard">>,
<<"PaymentSystems">> => Systems1,
<<"paymentSystems">> => Systems1,
<<"tokenProviders">> => [<<"samsungpay">>]
},
Methods = [

View File

@ -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)).
%%%

View File

@ -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),

View File

@ -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(

View File

@ -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).

View File

@ -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).

View File

@ -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}} =>

View File

@ -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().

View File

@ -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).

View File

@ -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">>).

View File

@ -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).

View File

@ -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).

View File

@ -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).

View File

@ -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) ->

@ -1 +0,0 @@
Subproject commit be44d69fc87b22a0bb82d98d6eae7658d1647f98

View File

@ -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">>
}}
]},

View File

@ -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}
]

View File

@ -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"
]}
]}.

View File

@ -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">>}]}

@ -1 +0,0 @@
Subproject commit 42257c406df732cc5b6cd7a864fca94ec9df59bf

View File

@ -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-----