Merge branch 'dev' into 'staging'

ci: fix env hosts

See merge request pena-services/customer!3
This commit is contained in:
Kirill 2023-06-22 09:36:43 +00:00
commit 6bc5f3868d
137 changed files with 14888 additions and 85 deletions

8
.dockerignore Normal file

@ -0,0 +1,8 @@
.mockery.yaml
.golangci.yaml
.gitlab-ci.yaml
.gitingore
.Makefile
.README.md
deployments
tests

27
.env.test Normal file

@ -0,0 +1,27 @@
# HTTP settings
HTTP_HOST=0.0.0.0
HTTP_PORT=8080
# MONGO settings
MONGO_HOST=localhost
MONGO_PORT=27017
MONGO_USER=test
MONGO_PASSWORD=test
MONGO_AUTH=admin
MONGO_DB_NAME=admin
# Auth Microservice settings
AUTH_MICROSERVICE_USER_URL=http://localhost:8000/user
# Hub Admin Microservice settings
HUBADMIN_MICROSERVICE_TARIFF_URL=http://localhost:8001/tariff
# Currency Microservice settings
CURRENCY_MICROSERVICE_TRANSLATE_URL=http://localhost:8002/change
# Admin
# JWT settings
JWT_ISSUER="pena-auth-service"
JWT_AUDIENCE="pena"
JWT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\nMIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgHgnvr7O2tiApjJfid1orFnIGm6980fZp+Lpbjo+NC/0whMFga2Biw5b1G2Q/B2u0tpO1Fs/E8z7Lv1nYfr5jx2S8x6BdA4TS2kB9Kf0wn0+7wSlyikHoKhbtzwXHZl17GsyEi6wHnsqNBSauyIWhpha8i+Y+3GyaOY536H47qyXAgMBAAE=\n-----END PUBLIC KEY-----"

6
.gitignore vendored Normal file

@ -0,0 +1,6 @@
# Dependency directories (remove the comment below to include it)
# vendor/
.idea/
.vscode
.env

100
.gitlab-ci.yml Normal file

@ -0,0 +1,100 @@
stages:
- lint
- test
- clean
- build
- deploy
lint:
image: golangci/golangci-lint:v1.52-alpine
stage: lint
before_script:
- go install github.com/vektra/mockery/v2@v2.26.0
- go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@v1.12.4
script:
- go generate ./internal/...
- golangci-lint version
- golangci-lint run ./internal/...
test:
image: golang:1.20.3-alpine
stage: test
coverage: /\(statements\)(?:\s+)?(\d+(?:\.\d+)?%)/
script:
- CGO_ENABLED=0 go test ./internal/... -coverprofile=coverage.out
- go tool cover -html=coverage.out -o coverage.html
- go tool cover -func coverage.out
artifacts:
expire_in: "3 days"
paths:
- coverage.html
clean-old:
stage: clean
image:
name: docker/compose:1.28.0
entrypoint: [""]
allow_failure: true
variables:
PRODUCTION_BRANCH: main
STAGING_BRANCH: "staging"
DEPLOY_TO: "staging"
rules:
- if: $CI_COMMIT_BRANCH == $PRODUCTION_BRANCH || $CI_COMMIT_BRANCH == $STAGING_BRANCH
when: on_success
before_script:
- echo DEPLOY_TO = $DEPLOY_TO
script:
- docker-compose -f deployments/$DEPLOY_TO/docker-compose.yaml down --volumes --rmi local
build-app:
stage: build
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
variables:
DOCKER_BUILD_PATH: "./Dockerfile"
STAGING_BRANCH: "staging"
PRODUCTION_BRANCH: "main"
rules:
- if: $CI_COMMIT_BRANCH == $PRODUCTION_BRANCH || $CI_COMMIT_BRANCH == $STAGING_BRANCH
when: on_success
before_script:
- echo PRODUCTION_BRANCH = $PRODUCTION_BRANCH
- echo STAGING_BRANCH = $STAGING_BRANCH
- echo CI_REGISTRY = $CI_REGISTRY
- echo CI_REGISTRY_USER = $CI_REGISTRY_USER
- echo CI_PROJECT_DIR = $CI_PROJECT_DIR
- echo CI_REGISTRY_IMAGE = $CI_REGISTRY_IMAGE
- echo CI_COMMIT_REF_SLUG = $CI_COMMIT_REF_SLUG
- echo DOCKER_BUILD_PATH = $DOCKER_BUILD_PATH
- echo CI_PIPELINE_ID = $CI_PIPELINE_ID
script:
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
- |
/kaniko/executor --context $CI_PROJECT_DIR \
--cache=true --cache-repo=$CI_REGISTRY_IMAGE \
--dockerfile $CI_PROJECT_DIR/$DOCKER_BUILD_PATH --target production \
--destination $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG.$CI_PIPELINE_ID
deploy-to-staging:
stage: deploy
image:
name: docker/compose:1.28.0
entrypoint: [""]
variables:
DEPLOY_TO: "staging"
BRANCH: "staging"
rules:
- if: $CI_COMMIT_BRANCH == $BRANCH
before_script:
- echo CI_PROJECT_NAME = $CI_PROJECT_NAME
- echo CI_REGISTRY = $CI_REGISTRY
- echo REGISTRY_USER = $REGISTRY_USER
- echo REGISTRY_TOKEN = $REGISTRY_TOKEN
- echo DEPLOY_TO = $DEPLOY_TO
- echo BRANCH = $BRANCH
script:
- docker login -u $REGISTRY_USER -p $REGISTRY_TOKEN $CI_REGISTRY
- docker-compose -f deployments/$DEPLOY_TO/docker-compose.yaml up -d

163
.golangci.yaml Normal file

@ -0,0 +1,163 @@
run:
timeout: 5m
skip-files:
- \.pb\.go$
- \.pb\.validate\.go$
- \.pb\.gw\.go$
- \.gen\.go$
skip-dirs:
- mocks
linters:
disable-all: true
enable:
- asasalint
- asciicheck
- bidichk
- bodyclose
- containedctx
- depguard
- dogsled
- dupword
- durationcheck
- errcheck
- errchkjson
- exportloopref
- goconst
- gocritic
- godot
- gofmt
- gci
- goprintffuncname
- gosec
- gosimple
- govet
- importas
- ineffassign
- misspell
- nakedret
- nilerr
- noctx
- nolintlint
- nosprintfhostport
- prealloc
- predeclared
- revive
- rowserrcheck
- staticcheck
- stylecheck
- thelper
- typecheck
- unconvert
- unparam
- unused
- usestdlibvars
- whitespace
linters-settings:
errcheck:
exclude-functions:
- (io.Closer).Close
govet:
check-shadowing: true
gci:
custom-order: false
section-separators:
- newLine
sections:
- standard # Standard section: captures all standard packages.
- default # Default section: contains all imports that could not be matched to another section type.
- blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled.
- dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled.
importas:
no-unaliased: true
alias:
# Foundation libraries
- pkg: git.sbercloud.tech/products/paas/shared/foundation/management-server
alias: mgmtserver
maligned:
suggest-new: true
goconst:
min-len: 2
min-occurrences: 2
lll:
line-length: 140
revive:
rules:
# The following rules are recommended https://github.com/mgechev/revive#recommended-configuration
- name: blank-imports
- name: context-as-argument
- name: context-keys-type
- name: dot-imports
- name: error-return
- name: error-strings
- name: error-naming
# - name: exported
- name: if-return
- name: increment-decrement
- name: var-naming
- name: var-declaration
# - name: package-comments
- name: range
- name: receiver-naming
- name: time-naming
- name: unexported-return
- name: indent-error-flow
- name: errorf
- name: empty-block
- name: superfluous-else
- name: unused-parameter
- name: unreachable-code
- name: redefines-builtin-id
#
# Rules in addition to the recommended configuration above.
#
- name: bool-literal-in-expr
- name: constant-logical-expr
gosec:
excludes:
- G307 # Deferring unsafe method "Close" on type "\*os.File"
- G108 # Profiling endpoint is automatically exposed on /debug/pprof
gocritic:
enabled-tags:
- diagnostic
- experimental
- performance
disabled-checks:
- appendAssign
- dupImport # https://github.com/go-critic/go-critic/issues/845
- evalOrder
- ifElseChain
- octalLiteral
- regexpSimplify
- sloppyReassign
- truncateCmp
- typeDefFirst
- unnamedResult
- unnecessaryDefer
- whyNoLint
- wrapperFunc
- rangeValCopy
- hugeParam
issues:
exclude-rules:
- text: "at least one file in a package should have a package comment"
linters:
- stylecheck
- text: "should have a package comment, unless it's in another file for this package"
linters:
- golint
- text: "should have comment or be unexported"
linters:
- golint
- path: _test\.go
linters:
- gosec
- dupl
exclude-use-default: false
output:
# colored-line-number|line-number|json|tab|checkstyle, default is "colored-line-number"
format: colored-line-number
print-linter-name: true

6
.mockery.yaml Normal file

@ -0,0 +1,6 @@
exported: True
inpackage: False
keeptree: True
case: underscore
with-expecter: True
inpackage-suffix: True

73
Dockerfile Normal file

@ -0,0 +1,73 @@
# BUILD
FROM golang:1.20.3-alpine AS build
# Update depences
RUN apk update && apk add --no-cache curl
# Create build directory
RUN mkdir /app/bin -p
RUN mkdir /bin/golang-migrate -p
# Download migrate app
RUN GOLANG_MIGRATE_VERSION=v4.15.1 && \
curl -L https://github.com/golang-migrate/migrate/releases/download/${GOLANG_MIGRATE_VERSION}/migrate.linux-amd64.tar.gz |\
tar xvz migrate -C /bin/golang-migrate
# Download health check utility
RUN GRPC_HEALTH_PROBE_VERSION=v0.4.6 && \
wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \
chmod +x /bin/grpc_health_probe
# Download debugger
# Set home directory
WORKDIR /app
# Copy go.mod
ADD go.mod go.sum /app/
# Download go depences
RUN go mod download
# Copy all local files
ADD . /app
# Build app
RUN GOOS=linux go build -o bin ./...
# TEST
FROM alpine:latest AS test
# Install packages
RUN apk --no-cache add ca-certificates
ENV GO111MODULE=off
# Create home directory
WORKDIR /app
# Copy build file
COPY --from=build /app/bin/app ./app
# CMD
CMD [ "./app" ]
# MIGRATION
FROM alpine:latest AS migration
# Install packages
RUN apk --no-cache add ca-certificates
# Create home directory
WORKDIR /app
# Copy migration dir
COPY --from=build /app/migrations/test ./migrations
# Install migrate tool
COPY --from=build /bin/golang-migrate /usr/local/bin
# PRODUCTION
FROM alpine:latest AS production
# Install packages
RUN apk --no-cache add ca-certificates
# Create home directory
WORKDIR /app
# Copy build file
COPY --from=build /app/bin/app ./app
# Copy grpc health probe dir
COPY --from=build /bin/grpc_health_probe /bin/grpc_health_probe
# Install migrate tool
COPY --from=build /bin/golang-migrate /usr/local/bin
# CMD
CMD ["./app"]

47
Makefile Normal file

@ -0,0 +1,47 @@
help: ## show this help
@echo 'usage: make [target] ...'
@echo ''
@echo 'targets:'
@egrep '^(.+)\:\ .*##\ (.+)' ${MAKEFILE_LIST} | sed 's/:.*##/#/' | column -t -c 2 -s '#'
install: ## install all go dependencies
go get \
github.com/bufbuild/buf/cmd/buf \
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway \
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2 \
google.golang.org/grpc/cmd/protoc-gen-go-grpc \
google.golang.org/protobuf/cmd/protoc-gen-go
generate: ## generate grpc proto for golang
buf generate
go generate ./internal/interface/swagger
test: ## run all layers tests
@make test.unit
@make test.integration
test.unit: ## run unit tests
go test ./...
test.integration: ## run integration tests
@make test.integration.up
@make test.integration.start
@make test.integration.down
test.integration.up: ## build integration test environment
docker-compose -f deployments/test/docker-compose.yaml --env-file ./.env.test up -d
test.integration.start: ## run integration test
go test -tags integration ./tests/integration/...
test.integration.down: ## shutting down integration environment
docker-compose -f deployments/test/docker-compose.yaml --env-file ./.env.test down --volumes --rmi local
run: ## run app
go run ./cmd/app/main.go
dev.up: ## run dev environment
docker-compose -f deployments/dev/docker-compose.yaml up -d
dev.down: ## shutting down dev environment
docker-compose -f deployments/dev/docker-compose.yaml down --volumes --rmi local

115
README.md

@ -1,92 +1,37 @@
# customer
Сервис customer
| Branch | Pipeline | Code coverage |
| ------------- |:-----------------:| --------------:|
| main | [![pipeline status](https://penahub.gitlab.yandexcloud.net/pena-services/customer/badges/main/pipeline.svg)](https://penahub.gitlab.yandexcloud.net/pena-services/customer/-/pipelines) | [![coverage report](https://penahub.gitlab.yandexcloud.net/pena-services/customer/badges/main/coverage.svg?job=test)](https://penahub.gitlab.yandexcloud.net/pena-services/customer/-/pipelines) |
| staging | [![pipeline status](https://penahub.gitlab.yandexcloud.net/pena-services/customer/badges/staging/pipeline.svg)](https://penahub.gitlab.yandexcloud.net/pena-services/customer/-/pipelines) | [![coverage report](https://penahub.gitlab.yandexcloud.net/pena-services/customer/badges/staging/coverage.svg?job=test)](https://penahub.gitlab.yandexcloud.net/pena-services/customer/-/pipelines) |
| dev | [![pipeline status](https://penahub.gitlab.yandexcloud.net/pena-services/customer/badges/dev/pipeline.svg)](https://penahub.gitlab.yandexcloud.net/pena-services/customer/-/pipelines) | [![coverage report](https://penahub.gitlab.yandexcloud.net/pena-services/customer/badges/dev/coverage.svg?job=test)](https://penahub.gitlab.yandexcloud.net/pena-services/customer/-/pipelines) |
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
## Переменные окружения приложения
```
cd existing_repo
git remote add origin https://penahub.gitlab.yandexcloud.net/pena-services/customer.git
git branch -M main
git push -uf origin main
HTTP_HOST - хост приложения (HTTP)
HTTP_PORT - порт приложения (HTTP)
GRPC_HOST - хост приложения (GRPC)
GRPC_PORT - порт приложения (GRPC)
GRPC_DOMEN - домен приложения (GRPC)
MONGO_HOST - хост MongoDB
MONGO_PORT - порт MongoDB
MONGO_USER - пользователь MongoDB
MONGO_DB_NAME - название базы данных для подключения
MONGO_PASSWORD - пароль пользователя MongoDB
MONGO_AUTH - имя базы данных Mongo, по которой будет производится авторизация
AUTH_MICROSERVICE_USER_URL - ссылка на получение пользователя микросервиса авторизации
HUBADMIN_MICROSERVICE_TARIFF_URL - ссылка на получение тарифов (hub admin)
CURRENCY_MICROSERVICE_TRANSLATE_URL - ссылка на перевод с одной валюты на другую
DISCOUNT_MICROSERVICE_GRPC_HOST - хост микросервиса discount (GRPC)
PAYMENT_MICROSERVICE_GRPC_HOST - хост микросервиса payment (GRPC)
JWT_PUBLIC_KEY - публичный ключ для верификации jwt токена
JWT_ISSUER - издатель токена
JWT_AUDIENCE - аудитория, которая может верифицировать токен
```
## Integrate with your tools
- [ ] [Set up project integrations](https://penahub.gitlab.yandexcloud.net/pena-services/customer/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.

8
buf.gen.yaml Normal file

@ -0,0 +1,8 @@
version: v1
plugins:
- name: go
out: internal/proto
- name: go-grpc
out: internal/proto
opt:
- require_unimplemented_servers=false

3
buf.work.yaml Normal file

@ -0,0 +1,3 @@
version: v1
directories:
- proto

4
buf.yaml Normal file

@ -0,0 +1,4 @@
version: v1
lint:
use:
- DEFAULT

34
cmd/app/main.go Normal file

@ -0,0 +1,34 @@
package main
import (
"encoding/json"
"fmt"
"log"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/app"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
)
func main() {
logger, err := zap.NewProduction(zap.AddStacktrace(zap.DPanicLevel))
if err != nil {
log.Fatalf("failed to init zap logger: %v", err)
}
config, err := initialize.Configuration(".env.test")
if err != nil {
logger.Fatal("failed to init config: %v", zap.Error(err))
}
configJSON, err := json.MarshalIndent(config, "", "\t")
if err != nil {
logger.Error("failed to translate config struct to json for print inromation: %v", zap.Error(err))
}
fmt.Println("env configuration: \n", string(configJSON))
if err := app.Run(config, logger); err != nil {
logger.Fatal("failed to run app: %v", zap.Error(err))
}
}

27
deployments/dev/.env.dev Normal file

@ -0,0 +1,27 @@
# HTTP settings
HTTP_HOST=0.0.0.0
HTTP_PORT=8080
# MONGO settings
MONGO_HOST=localhost
MONGO_PORT=27017
MONGO_USER=test
MONGO_PASSWORD=test
MONGO_AUTH=admin
MONGO_DB_NAME=admin
# Auth Microservice settings
AUTH_MICROSERVICE_USER_URL=http://localhost:8000/user
# Hub Admin Microservice settings
HUBADMIN_MICROSERVICE_TARIFF_URL=http://localhost:8001/tariff
# Currency Microservice settings
CURRENCY_MICROSERVICE_TRANSLATE_URL=http://localhost:8002/change
# Admin
# JWT settings
JWT_ISSUER="pena-auth-service"
JWT_AUDIENCE="pena"
JWT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\nMIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgHgnvr7O2tiApjJfid1orFnIGm6980fZp+Lpbjo+NC/0whMFga2Biw5b1G2Q/B2u0tpO1Fs/E8z7Lv1nYfr5jx2S8x6BdA4TS2kB9Kf0wn0+7wSlyikHoKhbtzwXHZl17GsyEi6wHnsqNBSauyIWhpha8i+Y+3GyaOY536H47qyXAgMBAAE=\n-----END PUBLIC KEY-----"

@ -0,0 +1,43 @@
version: "3"
services:
customer-app:
container_name: customer-service
tty: true
build:
context: ../../.
dockerfile: Dockerfile
target: test
env_file:
- .env.dev
environment:
- HTTP_HOST=0.0.0.0
- HTTP_PORT=8082
- GRPC_HOST=0.0.0.0
- GRPC_PORT=9082
- GRPC_DOMEN=customer-app:9082
- MONGO_HOST=mongo
- MONGO_PORT=27017
- MONGO_USER=test
- MONGO_PASSWORD=test
- MONGO_DB_NAME=admin
- MONGO_AUTH=admin
- JWT_ISSUER=pena-auth-service
- JWT_AUDIENCE=pena
- AUTH_MICROSERVICE_USER_URL=http://pena-auth-service:8000/user
- HUBADMIN_MICROSERVICE_TARIFF_URL=http://hub-admin-service:8010/tariff
- CURRENCY_MICROSERVICE_TRANSLATE_URL=http://cbrf-service:8020/translate
- DISCOUNT_MICROSERVICE_GRPC_HOST=discount-service:9040
- PAYMENT_MICROSERVICE_GRPC_HOST=treasurer-service:9085
ports:
- 8082:8082
- 9082:9082
networks:
- dev
networks:
dev:

@ -0,0 +1,42 @@
version: "3.3"
services:
customer-app-staging:
hostname: customer-service-staging
container_name: customer-service-staging
image: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG.$CI_PIPELINE_ID
tty: true
environment:
- HTTP_HOST=0.0.0.0
- HTTP_PORT=8065
- GRPC_HOST=0.0.0.0
- GRPC_PORT=9085
- GRPC_DOMEN=http://customer-service:9085
- MONGO_HOST=10.6.0.11
- MONGO_PORT=27017
- MONGO_USER=$MONGO_USER
- MONGO_PASSWORD=$MONGO_PASSWORD
- MONGO_DB_NAME=customer
- MONGO_AUTH=customer
- AUTH_MICROSERVICE_USER_URL=https://admin.pena.digital/user
- HUBADMIN_MICROSERVICE_TARIFF_URL=https://admin.pena.digital/strator/tariff
- CURRENCY_MICROSERVICE_TRANSLATE_URL=http://10.6.0.11:3131/change
- DISCOUNT_MICROSERVICE_GRPC_HOST=10.6.0.11:9001
- PAYMENT_MICROSERVICE_GRPC_HOST=10.6.0.11:9085
- JWT_PUBLIC_KEY=$JWT_PUBLIC_KEY
- JWT_ISSUER=pena-auth-service
- JWT_AUDIENCE=pena
ports:
- 8065:8065
- 9065:9065
networks:
- marketplace_penahub_frontend
- default
networks:
marketplace_penahub_frontend:
external: true

@ -0,0 +1,27 @@
# HTTP settings
HTTP_HOST=0.0.0.0
HTTP_PORT=8080
# MONGO settings
MONGO_HOST=localhost
MONGO_PORT=27017
MONGO_USER=test
MONGO_PASSWORD=test
MONGO_AUTH=admin
MONGO_DB_NAME=admin
# Auth Microservice settings
AUTH_MICROSERVICE_USER_URL=http://localhost:8000/user
# Hub Admin Microservice settings
HUBADMIN_MICROSERVICE_TARIFF_URL=http://localhost:8001/tariff
# Currency Microservice settings
CURRENCY_MICROSERVICE_TRANSLATE_URL=http://localhost:8002/change
# Admin
# JWT settings
JWT_ISSUER="pena-auth-service"
JWT_AUDIENCE="pena"
JWT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyt4XuLovUY7i12K2PIMbQZOKn+wFFKUvxvKQDel049/+VMpHMx1FLolUKuyGp9zi6gOwjHsBPgc9oqr/eaXGQSh7Ult7i9f+Ht563Y0er5UU9Zc5ZPSxf9O75KYD48ruGkqiFoncDqPENK4dtUa7w0OqlN4bwVBbmIsP8B3EDC5Dof+vtiNTSHSXPx+zifKeZGyknp+nyOHVrRDhPjOhzQzCom0MSZA/sJYmps8QZgiPA0k4Z6jTupDymPOIwYeD2C57zSxnAv0AfC3/pZYJbZYH/0TszRzmy052DME3zMnhMK0ikdN4nzYqU0dkkA5kb5GtKDymspHIJ9eWbUuwgtg8Rq/LrVBj1I3UFgs0ibio40k6gqinLKslc5Y1I5mro7J3OSEP5eO/XeDLOLlOJjEqkrx4fviI1cL3m5L6QV905xmcoNZG1+RmOg7D7cZQUf27TXqM381jkbNdktm1JLTcMScxuo3vaRftnIVw70V8P8sIkaKY8S8HU1sQgE2LB9t04oog5u59htx2FHv4B13NEm8tt8Tv1PexpB4UVh7PIualF6SxdFBrKbraYej72wgjXVPQ0eGXtGGD57j8DUEzk7DK2OvIWhehlVqtiRnFdAvdBj2ynHT2/5FJ/Zpd4n5dKGJcQvy1U1qWMs+8M7AHfWyt2+nZ04s48+bK3yMCAwEAAQ==\n-----END PUBLIC KEY-----"

@ -0,0 +1,68 @@
version: "3"
services:
app:
build:
context: ../../.
dockerfile: Dockerfile
target: test
env_file:
- .env.test
environment:
- HTTP_HOST=0.0.0.0
- HTTP_PORT=8082
- GRPC_HOST=0.0.0.0
- GRPC_PORT=9082
- GRPC_DOMEN=customer-app:9082
- MONGO_HOST=mongo
- MONGO_PORT=27017
- MONGO_USER=test
- MONGO_PASSWORD=test
- MONGO_DB_NAME=admin
- MONGO_AUTH=admin
- JWT_ISSUER=issuer
- JWT_AUDIENCE=audience
- AUTH_MICROSERVICE_USER_URL=http://pena-auth-service:8000/user
- HUBADMIN_MICROSERVICE_TARIFF_URL=http://hub-admin-service:8010/tariff
- CURRENCY_MICROSERVICE_TRANSLATE_URL=http://cbrf-service:8020/translate
- DISCOUNT_MICROSERVICE_GRPC_HOST=discount-service:9040
- PAYMENT_MICROSERVICE_GRPC_HOST=treasurer-service:9085
ports:
- 8082:8082
depends_on:
- migration
networks:
- integration_test
migration:
build:
context: ../../.
dockerfile: Dockerfile
target: migration
command:
[
"sh",
"-c",
'migrate -source file://migrations -database "mongodb://test:test@mongo:27017/admin?authSource=admin" up',
]
depends_on:
- mongo
networks:
- integration_test
mongo:
image: 'mongo:6.0.3'
environment:
MONGO_INITDB_ROOT_USERNAME: test
MONGO_INITDB_ROOT_PASSWORD: test
ports:
- '27017:27017'
networks:
- integration_test
networks:
integration_test:

62
go.mod Normal file

@ -0,0 +1,62 @@
module penahub.gitlab.yandexcloud.net/pena-services/customer
go 1.20
require (
github.com/deepmap/oapi-codegen v1.12.4
github.com/getkin/kin-openapi v0.116.0
github.com/go-resty/resty/v2 v2.7.0
github.com/golang-jwt/jwt/v5 v5.0.0
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
github.com/joho/godotenv v1.5.1
github.com/labstack/echo/v4 v4.10.2
github.com/sethvargo/go-envconfig v0.9.0
github.com/stretchr/testify v1.8.2
go.mongodb.org/mongo-driver v1.11.4
go.uber.org/zap v1.24.0
google.golang.org/genproto v0.0.0-20230223222841-637eb2293923
google.golang.org/grpc v1.53.0
google.golang.org/protobuf v1.30.0
)
require (
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/benbjohnson/clock v1.3.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/invopop/yaml v0.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/compress v1.16.5 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/labstack/gommon v0.4.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
github.com/perimeterx/marshmallow v1.1.4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.1 // indirect
github.com/xdg-go/stringprep v1.0.3 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sync v0.2.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/time v0.3.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

273
go.sum Normal file

@ -0,0 +1,273 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/clock v1.3.3 h1:g+rSsSaAzhHJYcIQE78hJ3AhyjjtQvleKDjlhdBnIhc=
github.com/benbjohnson/clock v1.3.3/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deepmap/oapi-codegen v1.12.4 h1:pPmn6qI9MuOtCz82WY2Xaw46EQjgvxednXXrP7g5Q2s=
github.com/deepmap/oapi-codegen v1.12.4/go.mod h1:3lgHGMu6myQ2vqbbTXH2H1o4eXFTGnFiDaOaKKl5yas=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/getkin/kin-openapi v0.116.0 h1:o986hwgMzR972JzOG5j6+WTwWqllZLs1EJKMKCivs2E=
github.com/getkin/kin-openapi v0.116.0/go.mod h1:l5e9PaFUo9fyLJCPGQeXI2ML8c3P8BHOEV2VaAVf/pc=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk=
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
github.com/invopop/yaml v0.1.0 h1:YW3WGUoJEXYfzWBjn00zIlrw7brGVD0fUKRYDPAPhrc=
github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/perimeterx/marshmallow v1.1.4 h1:pZLDH9RjlLGGorbXhcaQLhfuV0pFMNfPO55FuFkxqLw=
github.com/perimeterx/marshmallow v1.1.4/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/sethvargo/go-envconfig v0.9.0 h1:Q6FQ6hVEeTECULvkJZakq3dZMeBQ3JUpcKMfPQbKMDE=
github.com/sethvargo/go-envconfig v0.9.0/go.mod h1:Iz1Gy1Sf3T64TQlJSvee81qDhf7YIlt8GMUX6yyNFs0=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs=
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.mongodb.org/mongo-driver v1.11.4 h1:4ayjakA013OdpGyL2K3ZqylTac/rMjrJOMZ1EHizXas=
go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20230223222841-637eb2293923 h1:znp6mq/drrY+6khTAlJUDNFFcDGV2ENLYKpMq8SyCds=
google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

116
internal/app/app.go Normal file

@ -0,0 +1,116 @@
package app
import (
"context"
"errors"
"fmt"
"os/signal"
"syscall"
"time"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/swagger"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/server"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/closer"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/mongo"
)
const (
shutdownTimeout = 5 * time.Second
)
func Run(config *models.Config, logger *zap.Logger) (appErr error) {
defer func() {
if recovered := recover(); recovered != nil {
appErr = errors.New("recovered panic on application run")
logger.Error("recovered panic on application run", zap.Any("recovered", recovered))
}
}()
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer cancel()
closer := closer.New()
mongoDB, err := mongo.Connect(ctx, &mongo.ConnectDeps{
Configuration: &config.Database,
Timeout: 10 * time.Second,
})
if err != nil {
return fmt.Errorf("failed connection to db: %w", err)
}
clients := initialize.NewClients(initialize.ClientsDeps{
Logger: logger,
AuthURL: &config.Service.AuthMicroservice.URL,
HubadminURL: &config.Service.HubadminMicroservice.URL,
CurrencyURL: &config.Service.CurrencyMicroservice.URL,
DiscountServiceConfiguration: &config.Service.DiscountMicroservice,
PaymentServiceConfiguration: &config.Service.PaymentMicroservice,
})
repositories := initialize.NewRepositories(initialize.RepositoriesDeps{
Logger: logger,
MongoDB: mongoDB,
})
services := initialize.NewServices(initialize.ServicesDeps{
Logger: logger,
Repositories: repositories,
Clients: clients,
ConfigurationGRPC: &config.GRPC,
})
controllers := initialize.NewControllers(initialize.ControllersDeps{
Logger: logger,
Services: services,
})
openapi, err := swagger.GetSwagger()
if err != nil {
return fmt.Errorf("failed to loading openapi spec: %w", err)
}
api := initialize.NewAPI(*controllers)
serverHTTP, httpErr := server.NewHTTP(server.DepsHTTP{
Logger: logger,
Swagger: openapi,
AuthenticationFunc: utils.NewAuthenticator(utils.NewJWT(&config.Service.JWT)),
})
if httpErr != nil {
return httpErr.Wrap("failed to init http server")
}
serverGRPC, grpcErr := server.NewGRPC(server.DepsGRPC{Logger: logger})
if grpcErr != nil {
return httpErr.Wrap("failed to init grpc server")
}
serverHTTP.Register(api)
serverGRPC.Register(controllers)
go serverHTTP.Run(&config.HTTP)
go serverGRPC.Run(&config.GRPC)
closer.Add(mongoDB.Client().Disconnect)
closer.Add(serverHTTP.Stop)
closer.Add(serverGRPC.Stop)
<-ctx.Done()
logger.Info("shutting down app gracefully")
shutdownCtx, cancel := context.WithTimeout(context.Background(), shutdownTimeout)
defer cancel()
if err := closer.Close(shutdownCtx); err != nil {
return fmt.Errorf("closer: %w", err)
}
return nil
}

62
internal/errors/errors.go Normal file

@ -0,0 +1,62 @@
package errors
import (
"errors"
"fmt"
)
type ErrorType error
var (
ErrInternalError ErrorType = errors.New("internal error")
ErrInvalidArgs ErrorType = errors.New("invalid arguments")
ErrMethodNotImplemented ErrorType = errors.New("method is not implemented")
ErrNotFound ErrorType = errors.New("record not found")
ErrNoAccess ErrorType = errors.New("no access")
ErrConflict ErrorType = errors.New("record already exist")
ErrInsufficientFunds ErrorType = errors.New("insufficient funds")
)
type Error interface {
Error() string
Type() ErrorType
Wrap(message string) Error
SetType(errorType ErrorType)
}
type customError struct {
errorType ErrorType
err error
}
func New(err error, errorType ErrorType) Error {
return &customError{
errorType: errorType,
err: err,
}
}
func NewWithMessage(message string, errorType ErrorType) Error {
return &customError{
errorType: errorType,
err: errors.New(message),
}
}
func (receiver *customError) Error() string {
return receiver.err.Error()
}
func (receiver *customError) Type() ErrorType {
return receiver.errorType
}
func (receiver *customError) Wrap(message string) Error {
receiver.err = fmt.Errorf("%s: %w", message, receiver.err)
return receiver
}
func (receiver *customError) SetType(errorType ErrorType) {
receiver.errorType = errorType
}

27
internal/errors/grpc.go Normal file

@ -0,0 +1,27 @@
package errors
import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
const defaultGRPCCode = codes.Internal
var grpcCodes = map[error]codes.Code{
ErrInvalidArgs: codes.InvalidArgument,
ErrConflict: codes.AlreadyExists,
ErrInsufficientFunds: codes.Unavailable,
ErrInternalError: codes.Internal,
ErrMethodNotImplemented: codes.Unimplemented,
ErrNoAccess: codes.Unavailable,
ErrNotFound: codes.NotFound,
}
func GRPC(message string, err Error) error {
currentStatus, ok := grpcCodes[err]
if !ok {
return status.Errorf(defaultGRPCCode, message, err)
}
return status.Errorf(currentStatus, message, err)
}

33
internal/errors/http.go Normal file

@ -0,0 +1,33 @@
package errors
import (
"net/http"
"github.com/labstack/echo/v4"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)
var httpStatuses = map[ErrorType]int{
ErrInternalError: http.StatusInternalServerError,
ErrInvalidArgs: http.StatusBadRequest,
ErrNoAccess: http.StatusForbidden,
ErrNotFound: http.StatusNotFound,
ErrMethodNotImplemented: http.StatusNotImplemented,
ErrConflict: http.StatusConflict,
ErrInsufficientFunds: http.StatusPaymentRequired,
}
func HTTP(ctx echo.Context, err Error) error {
status, ok := httpStatuses[err.Type()]
if !ok {
return ctx.JSON(http.StatusInternalServerError, models.ResponseErrorHTTP{
StatusCode: http.StatusInternalServerError,
Message: err.Error(),
})
}
return ctx.JSON(status, models.ResponseErrorHTTP{
StatusCode: status,
Message: err.Error(),
})
}

@ -0,0 +1,25 @@
package fields
var Account = struct {
ID string
UserID string
Cart string
Wallet string
Name string
Status string
IsDeleted string
CreatedAt string
UpdatedAt string
DeletedAt string
}{
ID: "_id",
UserID: "userId",
Cart: "cart",
Wallet: "wallet",
Name: "name",
Status: "status",
IsDeleted: "isDeleted",
CreatedAt: "createdAt",
UpdatedAt: "updatedAt",
DeletedAt: "deletedAt",
}

@ -0,0 +1,19 @@
package fields
var Currency = struct {
ID string
Name string
Currencies string
IsDeleted string
CreatedAt string
UpdatedAt string
DeletedAt string
}{
ID: "_id",
Name: "name",
Currencies: "currencies",
IsDeleted: "isDeleted",
CreatedAt: "createdAt",
UpdatedAt: "updatedAt",
DeletedAt: "deletedAt",
}

@ -0,0 +1,23 @@
package fields
var History = struct {
ID string
UserID string
Comment string
Subject string
Type string
IsDeleted string
CreatedAt string
UpdatedAt string
DeletedAt string
}{
ID: "_id",
UserID: "userId",
Comment: "comment",
Subject: "subject",
Type: "type",
IsDeleted: "isDeleted",
CreatedAt: "createdAt",
UpdatedAt: "updatedAt",
DeletedAt: "deletedAt",
}

@ -0,0 +1,15 @@
package initialize
import (
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/swagger"
)
func NewAPI(controllers Controllers) *swagger.API {
return swagger.New(swagger.Deps{
AccountController: controllers.AccountController,
CurrencyController: controllers.CurrencyController,
CartController: controllers.CartController,
WalletController: controllers.WalletController,
HistoryController: controllers.HistoryController,
})
}

@ -0,0 +1,51 @@
package initialize_test
import (
"testing"
"github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/mongo/integration/mtest"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)
func TestNewAPI(t *testing.T) {
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
mt.Run("API сваггера должен успешно инициализироваться", func(t *mtest.T) {
assert.NotPanics(t, func() {
logger := zap.New(zap.L().Core())
repositories := initialize.NewRepositories(initialize.RepositoriesDeps{
Logger: logger,
MongoDB: t.Client.Database("test"),
})
clients := initialize.NewClients(initialize.ClientsDeps{
Logger: logger,
AuthURL: &models.AuthMicroserviceURL{User: ""},
HubadminURL: &models.HubadminMicroserviceURL{Tariff: ""},
CurrencyURL: &models.CurrencyMicroserviceURL{},
DiscountServiceConfiguration: &models.DiscountMicroserviceConfiguration{HostGRPC: "host"},
PaymentServiceConfiguration: &models.PaymentMicroserviceConfiguration{HostGRPC: "host"},
})
services := initialize.NewServices(initialize.ServicesDeps{
Logger: logger,
Repositories: repositories,
Clients: clients,
ConfigurationGRPC: &models.ConfigurationGRPC{Domen: "domen"},
})
controllers := initialize.NewControllers(initialize.ControllersDeps{
Logger: logger,
Services: services,
})
api := initialize.NewAPI(*controllers)
assert.NotNil(t, api)
})
})
}

@ -0,0 +1,49 @@
package initialize
import (
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/client"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)
type ClientsDeps struct {
Logger *zap.Logger
AuthURL *models.AuthMicroserviceURL
HubadminURL *models.HubadminMicroserviceURL
CurrencyURL *models.CurrencyMicroserviceURL
DiscountServiceConfiguration *models.DiscountMicroserviceConfiguration
PaymentServiceConfiguration *models.PaymentMicroserviceConfiguration
}
type Clients struct {
AuthClient *client.AuthClient
HubadminClient *client.HubadminClient
CurrencyClient *client.CurrencyClient
DiscountClient *client.DiscountClient
PaymentClient *client.PaymentClient
}
func NewClients(deps ClientsDeps) *Clients {
return &Clients{
AuthClient: client.NewAuthClient(client.AuthClientDeps{
Logger: deps.Logger,
URLs: deps.AuthURL,
}),
HubadminClient: client.NewHubadminClient(client.HubadminClientDeps{
Logger: deps.Logger,
URLs: deps.HubadminURL,
}),
CurrencyClient: client.NewCurrencyClient(client.CurrencyClientDeps{
Logger: deps.Logger,
URLs: deps.CurrencyURL,
}),
DiscountClient: client.NewDiscountClient(client.DiscountClientDeps{
Logger: deps.Logger,
DiscountServiceHost: deps.DiscountServiceConfiguration.HostGRPC,
}),
PaymentClient: client.NewPaymentClient(client.PaymentClientDeps{
Logger: deps.Logger,
PaymentServiceHost: deps.PaymentServiceConfiguration.HostGRPC,
}),
}
}

@ -0,0 +1,34 @@
package initialize_test
import (
"testing"
"github.com/stretchr/testify/assert"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)
func TestNewClients(t *testing.T) {
t.Run("Клиенты должны успешно инициализироваться", func(t *testing.T) {
logger := zap.New(zap.L().Core())
assert.NotPanics(t, func() {
clients := initialize.NewClients(initialize.ClientsDeps{
Logger: logger,
AuthURL: &models.AuthMicroserviceURL{},
HubadminURL: &models.HubadminMicroserviceURL{},
CurrencyURL: &models.CurrencyMicroserviceURL{},
DiscountServiceConfiguration: &models.DiscountMicroserviceConfiguration{HostGRPC: "host"},
PaymentServiceConfiguration: &models.PaymentMicroserviceConfiguration{HostGRPC: "host"},
})
assert.NotNil(t, clients)
assert.NotNil(t, clients.AuthClient)
assert.NotNil(t, clients.HubadminClient)
assert.NotNil(t, clients.CurrencyClient)
assert.NotNil(t, clients.DiscountClient)
assert.NotNil(t, clients.PaymentClient)
})
})
}

@ -0,0 +1,30 @@
package initialize
import (
"time"
"github.com/golang-jwt/jwt/v5"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/env"
)
func Configuration(path string) (*models.Config, error) {
config, err := env.Parse[models.Config](path)
if err != nil {
return nil, err
}
if err := utils.ValidateConfigurationURLs(&config.Service); err != nil {
return nil, err
}
iniJWTConfiguration(&config.Service.JWT)
return config, nil
}
func iniJWTConfiguration(config *models.JWTConfiguration) {
config.Algorithm = *jwt.SigningMethodRS256
config.ExpiresIn = 15 * time.Minute
}

@ -0,0 +1,131 @@
package initialize_test
import (
"testing"
"time"
"github.com/golang-jwt/jwt/v5"
"github.com/stretchr/testify/assert"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/mongo"
)
func TestConfiguration(t *testing.T) {
t.Run("Успешная инициализация конфигурации", func(t *testing.T) {
defaultConfiguration := setDefaultTestingENV(t)
assert.NotPanics(t, func() {
configuration, err := initialize.Configuration("")
assert.NoError(t, err)
assert.Equal(t, defaultConfiguration, configuration)
})
})
t.Run("Ошибка при наличии кривого url", func(t *testing.T) {
setDefaultTestingENV(t)
t.Setenv("AUTH_MICROSERVICE_USER_URL", "url")
assert.NotPanics(t, func() {
configuration, err := initialize.Configuration("")
assert.Error(t, err)
assert.Nil(t, configuration)
})
})
t.Run("Ошибка при отсутствии обязательного env", func(t *testing.T) {
assert.NotPanics(t, func() {
configuration, err := initialize.Configuration("")
assert.Error(t, err)
assert.Nil(t, configuration)
})
})
}
func setDefaultTestingENV(t *testing.T) *models.Config {
t.Helper()
defaultAuthURL := models.AuthMicroserviceURL{
User: "http://www.auth.ru/user",
}
defaultHubAdminURL := models.HubadminMicroserviceURL{
Tariff: "http://www.hubadmin.ru/tariff",
}
defaultCurrencyURL := models.CurrencyMicroserviceURL{
Translate: "http://www.currency.ru/change",
}
defaultConfiguration := models.Config{
HTTP: models.ConfigurationHTTP{
Host: "localhost",
Port: "8080",
},
GRPC: models.ConfigurationGRPC{
Host: "localhost",
Port: "8081",
Domen: "domen",
},
Service: models.ServiceConfiguration{
AuthMicroservice: models.AuthMicroserviceConfiguration{
URL: defaultAuthURL,
},
HubadminMicroservice: models.HubadminMicroserviceConfiguration{
URL: defaultHubAdminURL,
},
CurrencyMicroservice: models.CurrencyMicroserviceConfiguration{
URL: defaultCurrencyURL,
},
DiscountMicroservice: models.DiscountMicroserviceConfiguration{
HostGRPC: "domen",
},
PaymentMicroservice: models.PaymentMicroserviceConfiguration{
HostGRPC: "domen",
},
JWT: models.JWTConfiguration{
PrivateKey: "jwt private key",
PublicKey: "jwt public key",
Issuer: "issuer",
Audience: "audience",
Algorithm: *jwt.SigningMethodRS256,
ExpiresIn: 15 * time.Minute,
},
},
Database: mongo.Configuration{
Host: "localhost",
Port: "27017",
User: "user",
Password: "pass",
Auth: "db",
DatabaseName: "db",
},
}
t.Setenv("GRPC_HOST", defaultConfiguration.GRPC.Host)
t.Setenv("GRPC_PORT", defaultConfiguration.GRPC.Port)
t.Setenv("GRPC_DOMEN", defaultConfiguration.GRPC.Domen)
t.Setenv("JWT_PUBLIC_KEY", defaultConfiguration.Service.JWT.PublicKey)
t.Setenv("JWT_PRIVATE_KEY", defaultConfiguration.Service.JWT.PrivateKey)
t.Setenv("JWT_ISSUER", defaultConfiguration.Service.JWT.Issuer)
t.Setenv("JWT_AUDIENCE", defaultConfiguration.Service.JWT.Audience)
t.Setenv("AUTH_MICROSERVICE_USER_URL", defaultConfiguration.Service.AuthMicroservice.URL.User)
t.Setenv("HUBADMIN_MICROSERVICE_TARIFF_URL", defaultConfiguration.Service.HubadminMicroservice.URL.Tariff)
t.Setenv("CURRENCY_MICROSERVICE_TRANSLATE_URL", defaultConfiguration.Service.CurrencyMicroservice.URL.Translate)
t.Setenv("DISCOUNT_MICROSERVICE_GRPC_HOST", defaultConfiguration.Service.DiscountMicroservice.HostGRPC)
t.Setenv("PAYMENT_MICROSERVICE_GRPC_HOST", defaultConfiguration.Service.PaymentMicroservice.HostGRPC)
t.Setenv("MONGO_HOST", defaultConfiguration.Database.Host)
t.Setenv("MONGO_PORT", defaultConfiguration.Database.Port)
t.Setenv("MONGO_USER", defaultConfiguration.Database.User)
t.Setenv("MONGO_PASSWORD", defaultConfiguration.Database.Password)
t.Setenv("MONGO_AUTH", defaultConfiguration.Database.Auth)
t.Setenv("MONGO_DB_NAME", defaultConfiguration.Database.DatabaseName)
return &defaultConfiguration
}

@ -0,0 +1,61 @@
package initialize
import (
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/grpc/customer"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/grpc/payment"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/rest/account"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/rest/cart"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/rest/currency"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/rest/history"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/controller/rest/wallet"
)
type ControllersDeps struct {
Logger *zap.Logger
Services *Services
}
type Controllers struct {
AccountController *account.Controller
CurrencyController *currency.Controller
CartController *cart.Controller
HistoryController *history.Controller
WalletController *wallet.Controller
PaymentController *payment.Controller
CustomerController *customer.Controller
}
func NewControllers(deps ControllersDeps) *Controllers {
return &Controllers{
AccountController: account.New(account.Deps{
Logger: deps.Logger,
Service: deps.Services.AccountService,
}),
CurrencyController: currency.New(currency.Deps{
Logger: deps.Logger,
CurrencyService: deps.Services.CurrencyService,
}),
CartController: cart.New(cart.Deps{
Logger: deps.Logger,
CartService: deps.Services.CartService,
}),
HistoryController: history.New(history.Deps{
Logger: deps.Logger,
HistoryService: deps.Services.HistoryService,
}),
WalletController: wallet.New(wallet.Deps{
Logger: deps.Logger,
WalletService: deps.Services.WalletService,
PaymentService: deps.Services.PaymentService,
}),
PaymentController: payment.New(payment.Deps{
Logger: deps.Logger,
PaymentCallbackService: deps.Services.PaymentCallbackService,
}),
CustomerController: customer.New(customer.Deps{
Logger: deps.Logger,
HistoryService: deps.Services.HistoryService,
}),
}
}

@ -0,0 +1,54 @@
package initialize_test
import (
"testing"
"github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/mongo/integration/mtest"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)
func TestNewControllers(t *testing.T) {
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
mt.Run("Контроллеры должны успешно инициализироваться", func(t *mtest.T) {
logger := zap.New(zap.L().Core())
assert.NotPanics(t, func() {
clients := initialize.NewClients(initialize.ClientsDeps{
Logger: logger,
AuthURL: &models.AuthMicroserviceURL{},
HubadminURL: &models.HubadminMicroserviceURL{},
CurrencyURL: &models.CurrencyMicroserviceURL{},
DiscountServiceConfiguration: &models.DiscountMicroserviceConfiguration{HostGRPC: "host"},
PaymentServiceConfiguration: &models.PaymentMicroserviceConfiguration{HostGRPC: "host"},
})
repositories := initialize.NewRepositories(initialize.RepositoriesDeps{
Logger: logger,
MongoDB: t.Client.Database("test"),
})
services := initialize.NewServices(initialize.ServicesDeps{
Logger: logger,
Clients: clients,
Repositories: repositories,
ConfigurationGRPC: &models.ConfigurationGRPC{Domen: "http://test:8080"},
})
controllers := initialize.NewControllers(initialize.ControllersDeps{
Logger: logger,
Services: services,
})
assert.NotNil(t, controllers)
assert.NotNil(t, controllers.AccountController)
assert.NotNil(t, controllers.CurrencyController)
assert.NotNil(t, controllers.CartController)
assert.NotNil(t, controllers.HistoryController)
assert.NotNil(t, controllers.WalletController)
})
})
}

@ -0,0 +1,37 @@
package initialize
import (
"go.mongodb.org/mongo-driver/mongo"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/repository"
)
type RepositoriesDeps struct {
Logger *zap.Logger
MongoDB *mongo.Database
}
type Repositories struct {
HealthRepository *repository.HealthRepository
AccountRepository *repository.AccountRepository
CurrencyRepository *repository.CurrencyRepository
HistoryRepository *repository.HistoryRepository
}
func NewRepositories(deps RepositoriesDeps) *Repositories {
return &Repositories{
HealthRepository: repository.NewHealthRepository(deps.MongoDB),
AccountRepository: repository.NewAccountRepository(repository.AccountRepositoryDeps{
Logger: deps.Logger,
MongoDB: deps.MongoDB.Collection("accounts"),
}),
CurrencyRepository: repository.NewCurrencyRepository(repository.CurrencyRepositoryDeps{
Logger: deps.Logger,
MongoDB: deps.MongoDB.Collection("currency_lists"),
}),
HistoryRepository: repository.NewHistoryRepository(repository.HistoryRepositoryDeps{
Logger: deps.Logger,
MongoDB: deps.MongoDB.Collection("histories"),
}),
}
}

@ -0,0 +1,31 @@
package initialize_test
import (
"testing"
"github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/mongo/integration/mtest"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
)
func TestNewRepositories(t *testing.T) {
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
mt.Run("Репозитории должны успешно инициализироваться", func(t *mtest.T) {
logger := zap.New(zap.L().Core())
assert.NotPanics(t, func() {
repositories := initialize.NewRepositories(initialize.RepositoriesDeps{
Logger: logger,
MongoDB: t.Client.Database("test"),
})
assert.NotNil(t, repositories)
assert.NotNil(t, repositories.AccountRepository)
assert.NotNil(t, repositories.HealthRepository)
assert.NotNil(t, repositories.CurrencyRepository)
assert.NotNil(t, repositories.HistoryRepository)
})
})
}

@ -0,0 +1,78 @@
package initialize
import (
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/account"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/callback"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/cart"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/currency"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/history"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/payment"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/service/wallet"
)
type ServicesDeps struct {
Logger *zap.Logger
Repositories *Repositories
Clients *Clients
ConfigurationGRPC *models.ConfigurationGRPC
}
type Services struct {
AccountService *account.Service
CurrencyService *currency.Service
CartService *cart.Service
HistoryService *history.Service
WalletService *wallet.Service
PaymentService *payment.Service
PaymentCallbackService *callback.PaymentCallbackService
}
func NewServices(deps ServicesDeps) *Services {
historyService := history.New(history.Deps{
Logger: deps.Logger,
Repository: deps.Repositories.HistoryRepository,
})
walletService := wallet.New(wallet.Deps{
Logger: deps.Logger,
Repository: deps.Repositories.AccountRepository,
CurrencyClient: deps.Clients.CurrencyClient,
HistoryService: historyService,
})
return &Services{
WalletService: walletService,
HistoryService: historyService,
AccountService: account.New(account.Deps{
Logger: deps.Logger,
Repository: deps.Repositories.AccountRepository,
AuthClient: deps.Clients.AuthClient,
}),
CurrencyService: currency.New(currency.Deps{
Logger: deps.Logger,
Repository: deps.Repositories.CurrencyRepository,
}),
CartService: cart.New(cart.Deps{
Logger: deps.Logger,
Repository: deps.Repositories.AccountRepository,
HubadminClient: deps.Clients.HubadminClient,
DiscountClient: deps.Clients.DiscountClient,
WalletService: walletService,
HistoryService: historyService,
}),
PaymentService: payment.New(payment.Deps{
Logger: deps.Logger,
ConfigurationGRPC: deps.ConfigurationGRPC,
PaymentClient: deps.Clients.PaymentClient,
AuthClient: deps.Clients.AuthClient,
}),
PaymentCallbackService: callback.NewPaymentCallbackService(callback.PaymentCallbackServiceDeps{
Logger: deps.Logger,
AccountRepository: deps.Repositories.AccountRepository,
WalletService: walletService,
HistoryService: historyService,
}),
}
}

@ -0,0 +1,51 @@
package initialize_test
import (
"testing"
"github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/mongo/integration/mtest"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)
func TestNewServices(t *testing.T) {
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
mt.Run("Сервисы должны успешно инициализироваться", func(t *mtest.T) {
logger := zap.New(zap.L().Core())
assert.NotPanics(t, func() {
clients := initialize.NewClients(initialize.ClientsDeps{
Logger: logger,
AuthURL: &models.AuthMicroserviceURL{},
HubadminURL: &models.HubadminMicroserviceURL{},
CurrencyURL: &models.CurrencyMicroserviceURL{},
DiscountServiceConfiguration: &models.DiscountMicroserviceConfiguration{HostGRPC: "host"},
PaymentServiceConfiguration: &models.PaymentMicroserviceConfiguration{HostGRPC: "host"},
})
repositories := initialize.NewRepositories(initialize.RepositoriesDeps{
Logger: logger,
MongoDB: t.Client.Database("test"),
})
services := initialize.NewServices(initialize.ServicesDeps{
Logger: logger,
Clients: clients,
Repositories: repositories,
ConfigurationGRPC: &models.ConfigurationGRPC{Domen: "http://test:8080"},
})
assert.NotNil(t, services)
assert.NotNil(t, services.AccountService)
assert.NotNil(t, services.CartService)
assert.NotNil(t, services.CurrencyService)
assert.NotNil(t, services.HistoryService)
assert.NotNil(t, services.WalletService)
assert.NotNil(t, services.PaymentService)
assert.NotNil(t, services.PaymentCallbackService)
})
})
}

@ -0,0 +1,78 @@
package client
import (
"context"
"fmt"
"log"
"net/url"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/client"
)
type AuthClientDeps struct {
Logger *zap.Logger
URLs *models.AuthMicroserviceURL
}
type AuthClient struct {
logger *zap.Logger
urls *models.AuthMicroserviceURL
}
func NewAuthClient(deps AuthClientDeps) *AuthClient {
if deps.Logger == nil {
log.Panicln("logger is nil on <NewAuthClient>")
}
if deps.URLs == nil {
log.Panicln("urls is nil on <NewAuthClient>")
}
return &AuthClient{
logger: deps.Logger,
urls: deps.URLs,
}
}
func (receiver *AuthClient) GetUser(ctx context.Context, userID string) (*models.User, errors.Error) {
userURL, err := url.JoinPath(receiver.urls.User, userID)
if err != nil {
return nil, errors.New(
fmt.Errorf("failed to join path on <GetUser> of <AuthClient>: %w", err),
errors.ErrInternalError,
)
}
response, err := client.Get[models.User, models.FastifyError](ctx, &client.RequestSettings{
URL: userURL,
Headers: map[string]string{"Content-Type": "application/json"},
})
if err != nil {
receiver.logger.Error("failed to request get user on <GetUser> of <AuthClient>",
zap.Error(err),
zap.String("userID", userID),
)
return nil, errors.New(
fmt.Errorf("failed to request get user with <%s> on <GetUser> of <AuthClient>: %w", userID, err),
errors.ErrInternalError,
)
}
if response.Error != nil {
receiver.logger.Error("failed request on <GetUser> of <AuthClient>",
zap.String("error", response.Error.Message),
zap.String("userID", userID),
)
return nil, errors.New(
fmt.Errorf("failed request with <%s> on <GetUser> of <AuthClient>: %s", userID, response.Error.Message),
utils.DetermineClientErrorResponse(response.StatusCode),
)
}
return response.Body, nil
}

@ -0,0 +1,79 @@
package client
import (
"context"
"fmt"
"log"
"strconv"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/client"
)
type CurrencyClientDeps struct {
Logger *zap.Logger
URLs *models.CurrencyMicroserviceURL
}
type CurrencyClient struct {
logger *zap.Logger
urls *models.CurrencyMicroserviceURL
}
func NewCurrencyClient(deps CurrencyClientDeps) *CurrencyClient {
if deps.Logger == nil {
log.Panicln("logger is nil on <NewCurrencyClient>")
}
if deps.URLs == nil {
log.Panicln("urls is nil on <NewCurrencyClient>")
}
return &CurrencyClient{
logger: deps.Logger,
urls: deps.URLs,
}
}
func (receiver *CurrencyClient) Translate(ctx context.Context, request *models.TranslateCurrency) (int64, errors.Error) {
response, err := client.Get[models.CurrencyClientResponse[int64], models.CurrencyClientResponse[string]](ctx, &client.RequestSettings{
URL: receiver.urls.Translate,
Headers: map[string]string{"Content-Type": "application/json"},
QueryParams: map[string]string{
"currencyFrom": request.From,
"currencyTo": request.To,
"value": strconv.FormatInt(request.Money, 10),
},
})
if err != nil {
receiver.logger.Error("failed to request on <Translate> of <CurrencyClient>",
zap.Error(err),
zap.String("from", request.From),
zap.String("to", request.To),
zap.Int64("money", request.Money),
)
return 0, errors.New(
fmt.Errorf("failed to request on <Translate> of <CurrencyClient>: %w", err),
errors.ErrInternalError,
)
}
if response.Error != nil {
receiver.logger.Error("failed translate currency on <Translate> of <CurrencyClient>",
zap.String("error", response.Error.Message),
zap.String("from", request.From),
zap.String("to", request.To),
zap.Int64("money", request.Money),
)
return 0, errors.New(
fmt.Errorf("failed translate currency on <Translate> of <CurrencyClient>: %s", response.Error.Message),
utils.DetermineClientErrorResponse(response.StatusCode),
)
}
return response.Body.Message, nil
}

@ -0,0 +1,62 @@
package client
import (
"context"
"fmt"
"log"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/proto/discount"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/validate"
)
type DiscountClientDeps struct {
Logger *zap.Logger
DiscountServiceHost string
}
type DiscountClient struct {
logger *zap.Logger
discountServiceHost string
}
func NewDiscountClient(deps DiscountClientDeps) *DiscountClient {
if deps.Logger == nil {
log.Panicln("logger is nil on <NewDiscountClient>")
}
if validate.IsStringEmpty(deps.DiscountServiceHost) {
log.Panicln("discount host is empty on <NewDiscountClient>")
}
return &DiscountClient{
logger: deps.Logger,
discountServiceHost: deps.DiscountServiceHost,
}
}
func (receiver *DiscountClient) Apply(ctx context.Context, request *discount.ApplyDiscountRequest) (*discount.ApplyDiscountResponse, errors.Error) {
connection, err := grpc.Dial(receiver.discountServiceHost, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
receiver.logger.Error("failed to connect on <Apply> of <DiscountClient>", zap.Error(err), zap.String("discount host", receiver.discountServiceHost))
return nil, errors.New(fmt.Errorf("failed connect to discount service: %w", err), errors.ErrInternalError)
}
defer func() {
if closeErr := connection.Close(); closeErr != nil {
receiver.logger.Error("failed to close connection on <Apply> of <DiscountClient>", zap.Error(closeErr))
}
}()
client := discount.NewDiscountServiceClient(connection)
response, err := client.ApplyDiscounts(ctx, request)
if err != nil {
receiver.logger.Error("failed to apply discounts on <Apply> of <DiscountClient>", zap.Error(err), zap.Any("request", request))
return nil, errors.New(fmt.Errorf("failed to apply discounts: %w", err), errors.ErrInternalError)
}
return response, nil
}

@ -0,0 +1,94 @@
package client
import (
"context"
"fmt"
"log"
"net/url"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/client"
)
type HubadminClientDeps struct {
Logger *zap.Logger
URLs *models.HubadminMicroserviceURL
}
type HubadminClient struct {
logger *zap.Logger
urls *models.HubadminMicroserviceURL
}
func NewHubadminClient(deps HubadminClientDeps) *HubadminClient {
if deps.Logger == nil {
log.Panicln("logger is nil on <NewHubadminClient>")
}
if deps.URLs == nil {
log.Panicln("urls is nil on <NewHubadminClient>")
}
return &HubadminClient{
logger: deps.Logger,
urls: deps.URLs,
}
}
func (receiver *HubadminClient) GetTariff(ctx context.Context, tariffID string) (*models.Tariff, errors.Error) {
tariffURL, err := url.JoinPath(receiver.urls.Tariff, tariffID)
if err != nil {
return nil, errors.New(
fmt.Errorf("failed to join path on <GetTariff> of <HubadminClient>: %w", err),
errors.ErrInternalError,
)
}
response, err := client.Get[models.Tariff, models.FastifyError](ctx, &client.RequestSettings{
URL: tariffURL,
Headers: map[string]string{"Content-Type": "application/json"},
})
if err != nil {
receiver.logger.Error("failed to request get tariff on <GetTariff> of <HubadminClient>",
zap.Error(err),
zap.String("tariffID", tariffID),
)
return nil, errors.New(
fmt.Errorf("failed to request get tariff with <%s> on <GetTariff> of <HubadminClient>: %w", tariffID, err),
errors.ErrInternalError,
)
}
if response.Error != nil {
receiver.logger.Error("failed request on <GetTariff> of <HubadminClient>",
zap.String("error", response.Error.Message),
zap.String("tariffID", tariffID),
)
return nil, errors.New(
fmt.Errorf("failed request with <%s> on <GetTariff> of <HubadminClient>: %s", tariffID, response.Error.Message),
utils.DetermineClientErrorResponse(response.StatusCode),
)
}
return response.Body, nil
}
func (receiver *HubadminClient) GetTariffs(ctx context.Context, tarriffIDs []string) ([]models.Tariff, errors.Error) {
tariffs := make([]models.Tariff, len(tarriffIDs))
for index, tariffID := range tarriffIDs {
tariff, err := receiver.GetTariff(ctx, tariffID)
if err != nil {
receiver.logger.Error("failed to get tariff on <GetTariffs> of <HubadminClient>", zap.Error(err), zap.String("tariffID", tariffID))
return []models.Tariff{}, err
}
tariffs[index] = *tariff
}
return tariffs, nil
}

@ -0,0 +1,271 @@
package client
import (
"context"
"fmt"
"log"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/proto/treasurer"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/validate"
)
type PaymentClientDeps struct {
Logger *zap.Logger
PaymentServiceHost string
}
type PaymentClient struct {
logger *zap.Logger
paymentServiceHost string
}
func NewPaymentClient(deps PaymentClientDeps) *PaymentClient {
if deps.Logger == nil {
log.Panicln("logger is nil on <NewPaymentClient>")
}
if validate.IsStringEmpty(deps.PaymentServiceHost) {
log.Panicln("payment host is empty on <NewPaymentClient>")
}
return &PaymentClient{
logger: deps.Logger,
paymentServiceHost: deps.PaymentServiceHost,
}
}
func (receiver *PaymentClient) GetPaymentLinkBankCard(ctx context.Context, request *treasurer.GetBankCardPaymentLinkRequest) (string, errors.Error) {
client, closeConnection, connectErr := receiver.connect(ctx)
if connectErr != nil {
receiver.logger.Error("failed to connect on <GetPaymentLinkBankCard> of <PaymentClient>", zap.Error(connectErr))
return "", errors.New(fmt.Errorf("failed connect to payment service: %w", connectErr), errors.ErrInternalError)
}
defer closeConnection()
response, err := client.GetPaymentLinkBankCard(ctx, request)
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLinkBankCard> of <PaymentClient>",
zap.Error(err),
zap.String("host", receiver.paymentServiceHost),
)
return "", errors.New(fmt.Errorf("failed to get payment link: %w", err), errors.ErrInternalError)
}
return response.RedirectURL, nil
}
func (receiver *PaymentClient) GetPaymentLinkYooMoney(ctx context.Context, request *treasurer.GetPaymentLinkBody) (string, errors.Error) {
client, closeConnection, connectErr := receiver.connect(ctx)
if connectErr != nil {
receiver.logger.Error("failed to connect on <GetPaymentLinkYooMoney> of <PaymentClient>", zap.Error(connectErr))
return "", errors.New(fmt.Errorf("failed connect to payment service: %w", connectErr), errors.ErrInternalError)
}
defer closeConnection()
response, err := client.GetPaymentLinkYooMoney(ctx, request)
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLinkYooMoney> of <PaymentClient>",
zap.Error(err),
zap.String("host", receiver.paymentServiceHost),
)
return "", errors.New(fmt.Errorf("failed to get payment link: %w", err), errors.ErrInternalError)
}
return response.RedirectURL, nil
}
func (receiver *PaymentClient) GetPaymentLinkQIWI(ctx context.Context, request *treasurer.GetPhonePaymentLinkRequest) (string, errors.Error) {
client, closeConnection, connectErr := receiver.connect(ctx)
if connectErr != nil {
receiver.logger.Error("failed to connect on <GetPaymentLinkQIWI> of <PaymentClient>", zap.Error(connectErr))
return "", errors.New(fmt.Errorf("failed connect to payment service: %w", connectErr), errors.ErrInternalError)
}
defer closeConnection()
response, err := client.GetPaymentLinkQIWI(ctx, request)
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLinkQIWI> of <PaymentClient>",
zap.Error(err),
zap.String("host", receiver.paymentServiceHost),
)
return "", errors.New(fmt.Errorf("failed to get payment link: %w", err), errors.ErrInternalError)
}
return response.RedirectURL, nil
}
func (receiver *PaymentClient) GetPaymentLinkSberPay(ctx context.Context, request *treasurer.GetPhonePaymentLinkRequest) (string, errors.Error) {
client, closeConnection, connectErr := receiver.connect(ctx)
if connectErr != nil {
receiver.logger.Error("failed to connect on <GetPaymentLinkSberPay> of <PaymentClient>", zap.Error(connectErr))
return "", errors.New(fmt.Errorf("failed connect to payment service: %w", connectErr), errors.ErrInternalError)
}
defer closeConnection()
response, err := client.GetPaymentLinkSberPay(ctx, request)
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLinkSberPay> of <PaymentClient>",
zap.Error(err),
zap.String("host", receiver.paymentServiceHost),
)
return "", errors.New(fmt.Errorf("failed to get payment link: %w", err), errors.ErrInternalError)
}
return response.RedirectURL, nil
}
func (receiver *PaymentClient) GetPaymentLinkAlfaClick(ctx context.Context, request *treasurer.GetLoginPaymentLinkRequest) (string, errors.Error) {
client, closeConnection, connectErr := receiver.connect(ctx)
if connectErr != nil {
receiver.logger.Error("failed to connect on <GetPaymentLinkAlfaClick> of <PaymentClient>", zap.Error(connectErr))
return "", errors.New(fmt.Errorf("failed connect to payment service: %w", connectErr), errors.ErrInternalError)
}
defer closeConnection()
response, err := client.GetPaymentLinkAlfaClick(ctx, request)
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLinkAlfaClick> of <PaymentClient>",
zap.Error(err),
zap.String("host", receiver.paymentServiceHost),
)
return "", errors.New(fmt.Errorf("failed to get payment link: %w", err), errors.ErrInternalError)
}
return response.RedirectURL, nil
}
func (receiver *PaymentClient) GetPaymentLinkTinkoff(ctx context.Context, request *treasurer.GetPaymentLinkBody) (string, errors.Error) {
client, closeConnection, connectErr := receiver.connect(ctx)
if connectErr != nil {
receiver.logger.Error("failed to connect on <GetPaymentLinkTinkoff> of <PaymentClient>", zap.Error(connectErr))
return "", errors.New(fmt.Errorf("failed connect to payment service: %w", connectErr), errors.ErrInternalError)
}
defer closeConnection()
response, err := client.GetPaymentLinkTinkoff(ctx, request)
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLinkTinkoff> of <PaymentClient>",
zap.Error(err),
zap.String("host", receiver.paymentServiceHost),
)
return "", errors.New(fmt.Errorf("failed to get payment link: %w", err), errors.ErrInternalError)
}
return response.RedirectURL, nil
}
func (receiver *PaymentClient) GetPaymentLinkSberbankB2B(ctx context.Context, request *treasurer.GetB2BPaymentLinkRequest) (string, errors.Error) {
client, closeConnection, connectErr := receiver.connect(ctx)
if connectErr != nil {
receiver.logger.Error("failed to connect on <GetPaymentLinkSberbankB2B> of <PaymentClient>", zap.Error(connectErr))
return "", errors.New(fmt.Errorf("failed connect to payment service: %w", connectErr), errors.ErrInternalError)
}
defer closeConnection()
response, err := client.GetPaymentLinkSberbankB2B(ctx, request)
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLinkSberbankB2B> of <PaymentClient>",
zap.Error(err),
zap.String("host", receiver.paymentServiceHost),
)
return "", errors.New(fmt.Errorf("failed to get payment link: %w", err), errors.ErrInternalError)
}
return response.RedirectURL, nil
}
func (receiver *PaymentClient) GetPaymentLinkMobile(ctx context.Context, request *treasurer.GetPhonePaymentLinkRequest) (string, errors.Error) {
client, closeConnection, connectErr := receiver.connect(ctx)
if connectErr != nil {
receiver.logger.Error("failed to connect on <GetPaymentLinkMobile> of <PaymentClient>", zap.Error(connectErr))
return "", errors.New(fmt.Errorf("failed connect to payment service: %w", connectErr), errors.ErrInternalError)
}
defer closeConnection()
response, err := client.GetPaymentLinkMobile(ctx, request)
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLinkMobile> of <PaymentClient>",
zap.Error(err),
zap.String("host", receiver.paymentServiceHost),
)
return "", errors.New(fmt.Errorf("failed to get payment link: %w", err), errors.ErrInternalError)
}
return response.RedirectURL, nil
}
func (receiver *PaymentClient) GetPaymentLinkCash(ctx context.Context, request *treasurer.GetPhonePaymentLinkRequest) (string, errors.Error) {
client, closeConnection, connectErr := receiver.connect(ctx)
if connectErr != nil {
receiver.logger.Error("failed to connect on <GetPaymentLinkCash> of <PaymentClient>", zap.Error(connectErr))
return "", errors.New(fmt.Errorf("failed connect to payment service: %w", connectErr), errors.ErrInternalError)
}
defer closeConnection()
response, err := client.GetPaymentLinkCash(ctx, request)
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLinkCash> of <PaymentClient>",
zap.Error(err),
zap.String("host", receiver.paymentServiceHost),
)
return "", errors.New(fmt.Errorf("failed to get payment link: %w", err), errors.ErrInternalError)
}
return response.RedirectURL, nil
}
func (receiver *PaymentClient) GetPaymentLinkInstallments(ctx context.Context, request *treasurer.GetPaymentLinkBody) (string, errors.Error) {
client, closeConnection, connectErr := receiver.connect(ctx)
if connectErr != nil {
receiver.logger.Error("failed to connect on <GetPaymentLinkInstallments> of <PaymentClient>", zap.Error(connectErr))
return "", errors.New(fmt.Errorf("failed connect to payment service: %w", connectErr), errors.ErrInternalError)
}
defer closeConnection()
response, err := client.GetPaymentLinkInstallments(ctx, request)
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLinkInstallments> of <PaymentClient>",
zap.Error(err),
zap.String("host", receiver.paymentServiceHost),
)
return "", errors.New(fmt.Errorf("failed to get payment link: %w", err), errors.ErrInternalError)
}
return response.RedirectURL, nil
}
func (receiver *PaymentClient) connect(ctx context.Context) (treasurer.TreasurerServiceClient, func(), errors.Error) {
connection, err := grpc.DialContext(ctx, receiver.paymentServiceHost, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
receiver.logger.Error("failed connect to payment service no <connect> of <PaymentClient>",
zap.Error(err),
zap.String("host", receiver.paymentServiceHost),
)
return nil, nil, errors.New(fmt.Errorf("failed connect to payment service: %w", err), errors.ErrInternalError)
}
closeConnect := func() {
if closeErr := connection.Close(); closeErr != nil {
receiver.logger.Error("failed to close connection on <connect> of <PaymentClient>", zap.Error(closeErr))
}
}
client := treasurer.NewTreasurerServiceClient(connection)
return client, closeConnect, nil
}

@ -0,0 +1,55 @@
package customer
import (
"context"
"log"
"go.uber.org/zap"
"google.golang.org/protobuf/types/known/emptypb"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/proto/customer"
)
type historyService interface {
CreateHistory(ctx context.Context, history *models.History) (*models.History, errors.Error)
}
type Deps struct {
Logger *zap.Logger
HistoryService historyService
}
type Controller struct {
logger *zap.Logger
historyService historyService
}
func New(deps Deps) *Controller {
if deps.Logger == nil {
log.Panicln("logger is nil on <NewPaymentController>")
}
if deps.HistoryService == nil {
log.Panicln("HistoryService is nil on <NewPaymentController>")
}
return &Controller{
logger: deps.Logger,
historyService: deps.HistoryService,
}
}
func (receiver *Controller) InsertHistory(ctx context.Context, in *customer.History) (*emptypb.Empty, error) {
if _, err := receiver.historyService.CreateHistory(ctx, &models.History{
UserID: in.UserID,
Comment: in.Comment,
Key: in.Key,
RawDetails: in.RawDetails,
}); err != nil {
receiver.logger.Error("failed to insert history on <InsertHistory> of <HistoryController>", zap.Error(err))
return nil, errors.GRPC("failed to insert history", err)
}
return &emptypb.Empty{}, nil
}

@ -0,0 +1,74 @@
package payment
import (
"context"
"log"
"go.uber.org/zap"
"google.golang.org/protobuf/types/known/emptypb"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/proto/payment_callback"
)
type paymentCallbackService interface {
SuccessEvent(context.Context, *models.PaymentEvent) errors.Error
FailureEvent(context.Context, *models.PaymentEvent) errors.Error
}
type Deps struct {
Logger *zap.Logger
PaymentCallbackService paymentCallbackService
}
type Controller struct {
logger *zap.Logger
paymentCallbackService paymentCallbackService
}
func New(deps Deps) *Controller {
if deps.Logger == nil {
log.Panicln("logger is nil on <NewPaymentController>")
}
if deps.PaymentCallbackService == nil {
log.Panicln("PaymentCallbackService is nil on <NewPaymentController>")
}
return &Controller{
logger: deps.Logger,
paymentCallbackService: deps.PaymentCallbackService,
}
}
func (receiver *Controller) OnSuccess(ctx context.Context, in *payment_callback.Event) (*emptypb.Empty, error) {
if err := receiver.paymentCallbackService.SuccessEvent(ctx, &models.PaymentEvent{
Key: in.Key,
Message: in.Message,
PaymentID: in.Payment.PaymentID,
Currency: in.Payment.Currency,
Amount: in.Payment.Amount,
UserID: in.Payment.UserID,
}); err != nil {
receiver.logger.Error("failed to send success event on <OnSuccess> of <PaymentController>", zap.Error(err))
return nil, errors.GRPC("failed to send success event", err)
}
return &emptypb.Empty{}, nil
}
func (receiver *Controller) OnFailure(ctx context.Context, in *payment_callback.Event) (*emptypb.Empty, error) {
if err := receiver.paymentCallbackService.FailureEvent(ctx, &models.PaymentEvent{
Key: in.Key,
Message: in.Message,
PaymentID: in.Payment.PaymentID,
Currency: in.Payment.Currency,
Amount: in.Payment.Amount,
UserID: in.Payment.UserID,
}); err != nil {
receiver.logger.Error("failed to send failure event on <OnFailure> of <PaymentController>", zap.Error(err))
return nil, errors.GRPC("failed to send failure event", err)
}
return &emptypb.Empty{}, nil
}

@ -0,0 +1,177 @@
package account
import (
"context"
"fmt"
"log"
"net/http"
"github.com/labstack/echo/v4"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/swagger"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/echotools"
)
type accountService interface {
GetAccountByUserID(ctx context.Context, userID string) (*models.Account, errors.Error)
GetAccountsList(ctx context.Context, pagination *models.Pagination) (*models.PaginationResponse[models.Account], errors.Error)
CreateAccount(ctx context.Context, account *models.Account) (*models.Account, errors.Error)
CreateAccountByUserID(ctx context.Context, userID string) (*models.Account, errors.Error)
RemoveAccount(ctx context.Context, userID string) (*models.Account, errors.Error)
DeleteAccount(ctx context.Context, userID string) (*models.Account, errors.Error)
SetVerificationStatus(ctx context.Context, userID string, status models.AccountStatus) (*models.Account, errors.Error)
UpdateAccountName(ctx context.Context, userID string, name *models.Name) (*models.Account, errors.Error)
}
type Deps struct {
Logger *zap.Logger
Service accountService
}
type Controller struct {
logger *zap.Logger
service accountService
}
func New(deps Deps) *Controller {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (account controller)>")
}
if deps.Service == nil {
log.Panicln("account service is nil on <New (account controller)>")
}
return &Controller{
logger: deps.Logger,
service: deps.Service,
}
}
func (receiver *Controller) GetAccount(ctx echo.Context) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <GetAccount> of <AccountController>")
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to convert jwt payload to string: %s", userID),
errors.ErrInvalidArgs,
))
}
account, err := receiver.service.GetAccountByUserID(ctx.Request().Context(), userID)
if err != nil {
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}
func (receiver *Controller) GetDirectAccount(ctx echo.Context, userID string) error {
account, err := receiver.service.GetAccountByUserID(ctx.Request().Context(), userID)
if err != nil {
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}
func (receiver *Controller) GetAccounts(ctx echo.Context, params swagger.PaginationAccountsParams) error {
response, err := receiver.service.GetAccountsList(
ctx.Request().Context(),
utils.DeterminePagination(params.Page, params.Limit),
)
if err != nil {
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, response)
}
func (receiver *Controller) CreateAccount(ctx echo.Context) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <CreateAccount> of <AccountController>")
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to convert jwt payload to string: %s", userID),
errors.ErrInvalidArgs,
))
}
account, err := receiver.service.CreateAccountByUserID(ctx.Request().Context(), userID)
if err != nil {
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}
func (receiver *Controller) RemoveAccount(ctx echo.Context) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <RemoveAccount> of <AccountController>")
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to convert jwt payload to string: %s", userID),
errors.ErrInvalidArgs,
))
}
account, err := receiver.service.RemoveAccount(ctx.Request().Context(), userID)
if err != nil {
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}
func (receiver *Controller) RemoveDirectAccount(ctx echo.Context, userID string) error {
account, err := receiver.service.RemoveAccount(ctx.Request().Context(), userID)
if err != nil {
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}
func (receiver *Controller) SetVerificationStatus(ctx echo.Context, userID string) error {
request, bindErr := echotools.Bind[models.SetAccountStatus](ctx)
if bindErr != nil {
receiver.logger.Error("failed to bind json request on <SetVerificationStatus> of <AccountController>", zap.Error(bindErr))
return errors.HTTP(ctx, errors.New(fmt.Errorf("failed to bind json: %w", bindErr), errors.ErrInternalError))
}
account, err := receiver.service.SetVerificationStatus(ctx.Request().Context(), userID, request.Status)
if err != nil {
receiver.logger.Error("failed set status on <SetVerificationStatus> of <AccountController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}
func (receiver *Controller) UpdateAccountName(ctx echo.Context) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <UpdateAccountName> of <AccountController>")
return errors.HTTP(ctx, errors.New(fmt.Errorf("failed to convert jwt payload to string: %s", userID), errors.ErrInvalidArgs))
}
request, bindErr := echotools.Bind[models.Name](ctx)
if bindErr != nil {
receiver.logger.Error("failed to bind json request on <UpdateAccountName> of <AccountController>", zap.Error(bindErr))
return errors.HTTP(ctx, errors.New(fmt.Errorf("failed to bind json: %w", bindErr), errors.ErrInternalError))
}
account, err := receiver.service.UpdateAccountName(ctx.Request().Context(), userID, request)
if err != nil {
receiver.logger.Error("failed to update account name on <UpdateAccountName> of <AccountController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}

@ -0,0 +1,133 @@
package cart
import (
"context"
"fmt"
"log"
"net/http"
"github.com/labstack/echo/v4"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/swagger"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/validate"
)
type cartService interface {
Remove(ctx context.Context, userID, itemID string) ([]string, errors.Error)
Add(ctx context.Context, userID, itemID string) ([]string, errors.Error)
Pay(ctx context.Context, userID string) (link string, err errors.Error)
}
type Deps struct {
Logger *zap.Logger
CartService cartService
}
type Controller struct {
logger *zap.Logger
cartService cartService
}
func New(deps Deps) *Controller {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (cart controller)>")
}
if deps.CartService == nil {
log.Panicln("cart service is nil on <New (cart controller)>")
}
return &Controller{
logger: deps.Logger,
cartService: deps.CartService,
}
}
func (receiver *Controller) Remove(ctx echo.Context, params swagger.RemoveFromCartParams) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <Remove> of <CartController>")
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to convert jwt payload to string: %s", userID),
errors.ErrInvalidArgs,
))
}
if validate.IsStringEmpty(params.Id) {
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to remove cart item from user <%s>: empty item id", userID),
errors.ErrInvalidArgs,
))
}
cartItems, err := receiver.cartService.Remove(ctx.Request().Context(), userID, params.Id)
if err != nil {
receiver.logger.Error(
"failed to remove item from cart on <Remove> of <CartController>",
zap.Error(err),
)
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, cartItems)
}
func (receiver *Controller) Add(ctx echo.Context, params swagger.Add2cartParams) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <Add> of <CartController>")
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to convert jwt payload to string: %s", userID),
errors.ErrInvalidArgs,
))
}
if validate.IsStringEmpty(params.Id) {
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to add cart item to user <%s>: empty item id", userID),
errors.ErrInvalidArgs,
))
}
cartItems, err := receiver.cartService.Add(ctx.Request().Context(), userID, params.Id)
if err != nil {
receiver.logger.Error(
"failed to add item to cart on <Add> of <CartController>",
zap.Error(err),
)
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, cartItems)
}
func (receiver *Controller) Pay(ctx echo.Context) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <Pay> of <CartController>")
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to convert jwt payload to string: %s", userID),
errors.ErrInvalidArgs,
))
}
link, err := receiver.cartService.Pay(ctx.Request().Context(), userID)
if err != nil {
receiver.logger.Error("failed to pay cart on <Pay> of <CartController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
if !validate.IsStringEmpty(link) {
return ctx.Redirect(http.StatusTemporaryRedirect, link)
}
return ctx.JSON(http.StatusOK, true)
}

@ -0,0 +1,87 @@
package currency
import (
"context"
"fmt"
"log"
"net/http"
"github.com/labstack/echo/v4"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/echotools"
)
type currencyService interface {
GetCurrencies(context.Context) ([]string, errors.Error)
PutCurrencies(context.Context, []string) ([]string, errors.Error)
}
type Deps struct {
Logger *zap.Logger
CurrencyService currencyService
}
type Controller struct {
logger *zap.Logger
currencyService currencyService
}
func New(deps Deps) *Controller {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (account controller)>")
}
if deps.CurrencyService == nil {
log.Panicln("currency service is nil on <New (account controller)>")
}
return &Controller{
logger: deps.Logger,
currencyService: deps.CurrencyService,
}
}
func (receiver *Controller) GetCurrencies(ctx echo.Context) error {
currencies, err := receiver.currencyService.GetCurrencies(ctx.Request().Context())
if err != nil {
receiver.logger.Error(
"failed to get currencies on <GetCurrencies> of <CurrencyController>",
zap.Error(err),
)
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, currencies)
}
func (receiver *Controller) PutCurrencies(ctx echo.Context) error {
currencies, bindErr := echotools.Bind[[]string](ctx)
if bindErr != nil {
receiver.logger.Error(
"failed to parse body on <PutCurrencies> of <CurrencyController>",
zap.Error(bindErr),
)
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to parse body: %w", bindErr),
errors.ErrInvalidArgs,
))
}
currenciesCopy := *currencies
if len(currenciesCopy) < 1 {
currenciesCopy = make([]string, 0)
}
updatedCurrencies, err := receiver.currencyService.PutCurrencies(ctx.Request().Context(), currenciesCopy)
if err != nil {
receiver.logger.Error(
"failed to put currencies on <PutCurrencies> of <CurrencyController>",
zap.Error(err),
)
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, updatedCurrencies)
}

@ -0,0 +1,55 @@
package history
import (
"context"
"log"
"net/http"
"github.com/labstack/echo/v4"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/swagger"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)
type historyService interface {
GetHistoryList(context.Context, *models.Pagination) (*models.PaginationResponse[models.History], errors.Error)
}
type Deps struct {
Logger *zap.Logger
HistoryService historyService
}
type Controller struct {
logger *zap.Logger
historyService historyService
}
func New(deps Deps) *Controller {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (history controller)>")
}
if deps.HistoryService == nil {
log.Panicln("HistoryService is nil on <New (history controller)>")
}
return &Controller{
logger: deps.Logger,
historyService: deps.HistoryService,
}
}
func (receiver *Controller) GetHistoryList(ctx echo.Context, params swagger.GetHistoryParams) error {
histories, err := receiver.historyService.GetHistoryList(ctx.Request().Context(), &models.Pagination{
Page: int64(*params.Page),
Limit: int64(*params.Limit),
})
if err != nil {
receiver.logger.Error("failed to get histories on <GetHistoryList> of <HistoryController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, histories)
}

@ -0,0 +1,131 @@
package wallet
import (
"context"
"fmt"
"log"
"net/http"
"github.com/labstack/echo/v4"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/echotools"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/validate"
)
type walletService interface {
ReplenishAccountWallet(context.Context, *models.ReplenishAccountWallet) (*models.Account, errors.Error)
ChangeCurrency(ctx context.Context, userID string, currency models.CurrencyKey) (*models.Account, errors.Error)
}
type paymentService interface {
GetPaymentLink(context.Context, *models.GetPaymentLinkRequest) (string, errors.Error)
}
type Deps struct {
Logger *zap.Logger
WalletService walletService
PaymentService paymentService
}
type Controller struct {
logger *zap.Logger
walletService walletService
paymentService paymentService
}
func New(deps Deps) *Controller {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (wallet controller)>")
}
if deps.WalletService == nil {
log.Panicln("wallet service is nil on <New (wallet controller)>")
}
if deps.PaymentService == nil {
log.Panicln("payment service is nil on <New (wallet controller)>")
}
return &Controller{
logger: deps.Logger,
walletService: deps.WalletService,
paymentService: deps.PaymentService,
}
}
func (receiver *Controller) ChangeCurrency(ctx echo.Context) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <ChangeCurrency> of <WallerController>")
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to convert jwt payload to string: %s", userID),
errors.ErrInvalidArgs,
))
}
request, bindErr := echotools.Bind[models.ChangeCurrency](ctx)
if bindErr != nil {
receiver.logger.Error("failed to bind body on <ChangeCurrency> of <WalletController>", zap.Error(bindErr))
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to parse body on <ChangeCurrency> of <WalletController>: %w", bindErr),
errors.ErrInvalidArgs,
))
}
if validate.IsStringEmpty(request.Currency) {
return errors.HTTP(ctx, errors.New(
fmt.Errorf("empty currency key on <ChangeCurrency> of <WalletController>: %w", errors.ErrInvalidArgs),
errors.ErrInvalidArgs,
))
}
account, err := receiver.walletService.ChangeCurrency(ctx.Request().Context(), userID, request.Currency)
if err != nil {
receiver.logger.Error("failed to put money on <ChangeCurrency> of <WalletController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, account)
}
func (receiver *Controller) GetPaymentLink(ctx echo.Context) error {
userID, ok := ctx.Get(models.AuthJWTDecodedUserIDKey).(string)
if !ok {
receiver.logger.Error("failed to convert jwt payload to string on <GetPaymentLink> of <WallerController>")
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to convert jwt payload to string: %s", userID),
errors.ErrInvalidArgs,
))
}
request, bindErr := echotools.Bind[models.GetPaymentLinkBody](ctx)
if bindErr != nil {
receiver.logger.Error("failed to bind body on <GetPaymentLink> of <WalletController>", zap.Error(bindErr))
return errors.HTTP(ctx, errors.New(
fmt.Errorf("failed to parse body on <GetPaymentLink> of <WalletController>: %w", bindErr),
errors.ErrInvalidArgs,
))
}
if validateErr := utils.ValidateGetPaymentLinkBody(request); validateErr != nil {
receiver.logger.Error("failed to validate body on <GetPaymentLink> of <WalletController>", zap.Error(validateErr))
return errors.HTTP(ctx, validateErr)
}
link, err := receiver.paymentService.GetPaymentLink(ctx.Request().Context(), &models.GetPaymentLinkRequest{
Body: request,
UserID: userID,
ClientIP: ctx.RealIP(),
})
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLink> of <WalletController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, &models.GetPaymentLinkResponse{Link: link})
}

@ -0,0 +1,418 @@
package repository
import (
"context"
"fmt"
"log"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/fields"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
mongoWrapper "penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/mongo"
)
type AccountRepositoryDeps struct {
Logger *zap.Logger
MongoDB *mongo.Collection
}
type AccountRepository struct {
logger *zap.Logger
mongoDB *mongo.Collection
}
func NewAccountRepository(deps AccountRepositoryDeps) *AccountRepository {
if deps.Logger == nil {
log.Panicln("logger is nil on <NewAccountRepository>")
}
if deps.MongoDB == nil {
log.Panicln("mongodb is nil on <NewAccountRepository>")
}
return &AccountRepository{
logger: deps.Logger,
mongoDB: deps.MongoDB,
}
}
func (receiver *AccountRepository) FindByUserID(ctx context.Context, id string) (*models.Account, errors.Error) {
filter := bson.M{
fields.Account.UserID: id,
fields.Account.IsDeleted: false,
}
account, err := mongoWrapper.FindOne[models.Account](ctx, &mongoWrapper.RequestSettings{
Driver: receiver.mongoDB,
Filter: filter,
})
if err != nil {
receiver.logger.Error("failed to find account by userID on <FindByUserID> of <AccountRepository>",
zap.String("id", id),
zap.Error(err),
)
findError := errors.New(
fmt.Errorf("failed to find account with <%s> on <FindByUserID> of <AccountRepository>: %w", id, err),
errors.ErrInternalError,
)
if err == mongo.ErrNoDocuments {
findError.SetType(errors.ErrNotFound)
}
return nil, findError
}
return account, nil
}
func (receiver *AccountRepository) FindMany(ctx context.Context, page, limit int64) ([]models.Account, errors.Error) {
filter := bson.M{fields.Account.IsDeleted: false}
findOptions := options.Find()
skip := (page - 1) * limit
findOptions.SetSkip(skip)
findOptions.SetLimit(limit)
accounts, err := mongoWrapper.Find[models.Account](ctx, &mongoWrapper.RequestSettings{
Driver: receiver.mongoDB,
Options: findOptions,
Filter: filter,
})
if err != nil {
receiver.logger.Error("failed to find many accounts on <FindMany> of <AccountRepository>",
zap.Int64("page", page),
zap.Int64("limit", limit),
zap.Int64("skip", skip),
zap.Error(err),
)
return nil, errors.New(
fmt.Errorf("failed to find many accounts on <FindMany> of <AccountRepository>: %w", err),
errors.ErrInternalError,
)
}
return accounts, nil
}
func (receiver *AccountRepository) Insert(ctx context.Context, account *models.Account) (*models.Account, errors.Error) {
result, err := receiver.mongoDB.InsertOne(ctx, account.Sanitize())
if err != nil {
receiver.logger.Error("failed to insert account on <Insert> of <AccountRepository>",
zap.Any("account", account),
zap.Error(err),
)
return nil, errors.New(
fmt.Errorf("failed to insert account on <Insert> of <AccountRepository>: %w", err),
errors.ErrInternalError,
)
}
insertedID := result.InsertedID.(primitive.ObjectID).Hex()
account.ID = insertedID
return account, nil
}
func (receiver *AccountRepository) Remove(ctx context.Context, id string) (*models.Account, errors.Error) {
account := models.Account{}
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
filter := bson.M{
fields.Account.UserID: id,
fields.Account.IsDeleted: false,
}
update := bson.M{"$set": bson.M{
fields.Account.IsDeleted: true,
fields.Account.DeletedAt: time.Now(),
}}
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update, options).Decode(&account); err != nil {
receiver.logger.Error("failed to set 'deleted=true' on <Delete> of <AccountRepository>",
zap.String("id", id),
zap.Error(err),
)
removeErr := errors.New(
fmt.Errorf("failed to remove account with <%s> on <Remove> of <AccountRepository>: %w", id, err),
errors.ErrInternalError,
)
if err == mongo.ErrNoDocuments {
removeErr.SetType(errors.ErrNotFound)
}
return nil, removeErr
}
return &account, nil
}
func (receiver *AccountRepository) Delete(ctx context.Context, id string) (*models.Account, errors.Error) {
account := models.Account{}
filter := bson.M{
fields.Account.UserID: id,
fields.Account.IsDeleted: false,
}
if err := receiver.mongoDB.FindOneAndDelete(ctx, filter).Decode(&account); err != nil {
receiver.logger.Error("failed delete account on <Delete> of <AccountRepository>",
zap.String("id", id),
zap.Error(err),
)
removeErr := errors.New(
fmt.Errorf("failed to remove account with <%s> on <Delete> of <AccountRepository>: %w", id, err),
errors.ErrInternalError,
)
if err == mongo.ErrNoDocuments {
removeErr.SetType(errors.ErrNotFound)
}
return nil, removeErr
}
return &account, nil
}
func (receiver *AccountRepository) CountAll(ctx context.Context) (int64, errors.Error) {
count, err := receiver.mongoDB.CountDocuments(ctx, bson.M{fields.Account.IsDeleted: false})
if err != nil {
receiver.logger.Error("failed to count all documents on <CountAll> of <AccountRepository>", zap.Error(err))
return 0, errors.New(
fmt.Errorf("failed to count all documents on <CountAll> of <AccountRepository>: %w", err),
errors.ErrInternalError,
)
}
return count, nil
}
func (receiver *AccountRepository) AddItemToCart(ctx context.Context, userID, itemID string) (*models.Account, errors.Error) {
account := models.Account{}
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
filter := bson.M{
fields.Account.UserID: userID,
fields.Account.IsDeleted: false,
}
update := bson.M{
"$addToSet": bson.M{fields.Account.Cart: itemID},
"$set": bson.M{fields.Account.UpdatedAt: time.Now()},
}
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update, options).Decode(&account); err != nil {
receiver.logger.Error("failed to add item on <AddItemToCart> of <AccountRepository>",
zap.String("userID", userID),
zap.String("itemID", itemID),
zap.Error(err),
)
removeErr := errors.New(
fmt.Errorf("failed to add item <%s> account with <%s> on <AddItemToCart> of <AccountRepository>: %w", itemID, userID, err),
errors.ErrInternalError,
)
if err == mongo.ErrNoDocuments {
removeErr.SetType(errors.ErrNotFound)
}
return nil, removeErr
}
return &account, nil
}
func (receiver *AccountRepository) RemoveItemFromCart(ctx context.Context, userID, itemID string) (*models.Account, errors.Error) {
account := models.Account{}
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
filter := bson.M{
fields.Account.UserID: userID,
fields.Account.IsDeleted: false,
}
update := bson.M{
"$pull": bson.M{fields.Account.Cart: itemID},
"$set": bson.M{fields.Account.UpdatedAt: time.Now()},
}
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update, options).Decode(&account); err != nil {
receiver.logger.Error("failed to add item on <AddItemToCart> of <AccountRepository>",
zap.String("userID", userID),
zap.String("itemID", itemID),
zap.Error(err),
)
removeErr := errors.New(
fmt.Errorf("failed to add item <%s> account with <%s> on <AddItemToCart> of <AccountRepository>: %w", itemID, userID, err),
errors.ErrInternalError,
)
if err == mongo.ErrNoDocuments {
removeErr.SetType(errors.ErrNotFound)
}
return nil, removeErr
}
return &account, nil
}
func (receiver *AccountRepository) ChangeWallet(ctx context.Context, userID string, wallet *models.Wallet) (*models.Account, errors.Error) {
account := models.Account{}
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
filter := bson.M{
fields.Account.UserID: userID,
fields.Account.IsDeleted: false,
}
update := bson.M{"$set": bson.M{
fields.Account.Wallet: wallet,
fields.Account.UpdatedAt: time.Now(),
}}
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update, options).Decode(&account); err != nil {
receiver.logger.Error("failed to change wallet on <ChangeWallet> of <AccountRepository>",
zap.Error(err),
zap.String("userID", userID),
zap.Any("wallet", wallet),
)
removeErr := errors.New(
fmt.Errorf("failed to change wallet of account <%s> on <ChangeWallet> of <AccountRepository>: %w", userID, err),
errors.ErrInternalError,
)
if err == mongo.ErrNoDocuments {
removeErr.SetType(errors.ErrNotFound)
}
return nil, removeErr
}
return &account, nil
}
func (receiver *AccountRepository) ClearCart(ctx context.Context, userID string) (*models.Account, errors.Error) {
account := models.Account{}
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
filter := bson.M{
fields.Account.UserID: userID,
fields.Account.IsDeleted: false,
}
update := bson.M{"$set": bson.M{
fields.Account.Cart: []string{},
fields.Account.UpdatedAt: time.Now(),
}}
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update, options).Decode(&account); err != nil {
receiver.logger.Error("failed to clear cart on <ClearCart> of <AccountRepository>",
zap.String("userID", userID),
zap.Error(err),
)
removeErr := errors.New(
fmt.Errorf("failed to clear cart of account <%s> on <ClearCart> of <AccountRepository>: %w", userID, err),
errors.ErrInternalError,
)
if err == mongo.ErrNoDocuments {
removeErr.SetType(errors.ErrNotFound)
}
return nil, removeErr
}
return &account, nil
}
func (receiver *AccountRepository) SetStatus(ctx context.Context, userID string, status models.AccountStatus) (*models.Account, errors.Error) {
account := models.Account{}
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
filter := bson.M{
fields.Account.UserID: userID,
fields.Account.IsDeleted: false,
}
update := bson.M{"$set": bson.M{
fields.Account.Status: status,
fields.Account.UpdatedAt: time.Now(),
}}
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update, options).Decode(&account); err != nil {
receiver.logger.Error("failed to set status on <SetStatus> of <AccountRepository>",
zap.Error(err),
zap.String("userID", userID),
zap.String("status", string(status)),
)
removeErr := errors.New(
fmt.Errorf("failed to set status <%s> to account <%s> on <SetStatus> of <AccountRepository>: %w", status, userID, err),
errors.ErrInternalError,
)
if err == mongo.ErrNoDocuments {
removeErr.SetType(errors.ErrNotFound)
}
return nil, removeErr
}
return &account, nil
}
func (receiver *AccountRepository) UpdateName(ctx context.Context, userID string, name *models.Name) (*models.Account, errors.Error) {
account := models.Account{}
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
filter := bson.M{
fields.Account.UserID: userID,
fields.Account.IsDeleted: false,
}
update := bson.M{"$set": bson.M{
fields.Account.Name: name,
fields.Account.UpdatedAt: time.Now(),
}}
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update, options).Decode(&account); err != nil {
receiver.logger.Error("failed to change name on <UpdateName> of <AccountRepository>",
zap.Error(err),
zap.String("userID", userID),
zap.Any("name", name),
)
removeErr := errors.New(
fmt.Errorf("failed to change name of account <%s> on <UpdateName> of <AccountRepository>: %w", userID, err),
errors.ErrInternalError,
)
if err == mongo.ErrNoDocuments {
removeErr.SetType(errors.ErrNotFound)
}
return nil, removeErr
}
return &account, nil
}

@ -0,0 +1,129 @@
package repository
import (
"context"
"fmt"
"log"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/fields"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
mongoWrapper "penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/mongo"
)
type CurrencyRepositoryDeps struct {
Logger *zap.Logger
MongoDB *mongo.Collection
}
type CurrencyRepository struct {
logger *zap.Logger
mongoDB *mongo.Collection
}
func NewCurrencyRepository(deps CurrencyRepositoryDeps) *CurrencyRepository {
if deps.Logger == nil {
log.Panicln("logger is nil on <NewCurrencyRepository>")
}
if deps.MongoDB == nil {
log.Panicln("mongodb is nil on <NewCurrencyRepository>")
}
return &CurrencyRepository{
mongoDB: deps.MongoDB,
logger: deps.Logger,
}
}
func (receiver *CurrencyRepository) FindCurrenciesList(ctx context.Context, name string) (*models.CurrencyList, errors.Error) {
filter := bson.M{
fields.Currency.Name: name,
fields.Currency.IsDeleted: false,
}
currencyList, err := mongoWrapper.FindOne[models.CurrencyList](ctx, &mongoWrapper.RequestSettings{
Driver: receiver.mongoDB,
Filter: filter,
})
if err != nil {
receiver.logger.Error("failed to find list on <FindCurrenciesList> of <CurrencyRepository>",
zap.String("name", name),
zap.Error(err),
)
findError := errors.New(
fmt.Errorf("failed to find list with <%s> on <FindCurrenciesList> of <CurrencyRepository>: %w", name, err),
errors.ErrInternalError,
)
if err == mongo.ErrNoDocuments {
findError.SetType(errors.ErrNotFound)
}
return nil, findError
}
return currencyList, nil
}
func (receiver *CurrencyRepository) ReplaceCurrencies(ctx context.Context, list *models.CurrencyList) (*models.CurrencyList, errors.Error) {
currencyList := models.CurrencyList{}
filter := bson.M{
fields.Currency.Name: list.Name,
fields.Currency.IsDeleted: false,
}
update := bson.M{
"$set": bson.M{
fields.Currency.UpdatedAt: time.Now(),
fields.Currency.Currencies: list.Currencies,
},
}
if err := receiver.mongoDB.FindOneAndUpdate(ctx, filter, update).Decode(&currencyList); err != nil {
receiver.logger.Error("failed to insert currencies on <InsertCurrenciesToList> of <CurrencyRepository>",
zap.String("name", list.Name),
zap.Error(err),
)
removeErr := errors.New(
fmt.Errorf("failed to insert currencies <%s> on <InsertCurrenciesToList> of <CurrencyRepository>: %w", list.Name, err),
errors.ErrInternalError,
)
if err == mongo.ErrNoDocuments {
removeErr.SetType(errors.ErrNotFound)
}
return nil, removeErr
}
return &currencyList, nil
}
func (receiver *CurrencyRepository) Insert(ctx context.Context, list *models.CurrencyList) (*models.CurrencyList, errors.Error) {
result, err := receiver.mongoDB.InsertOne(ctx, list.Sanitize())
if err != nil {
receiver.logger.Error("failed to insert currency list on <Insert> of <CurrencyRepository>",
zap.Any("list", list),
zap.Error(err),
)
return nil, errors.New(
fmt.Errorf("failed to insert currency list on <Insert> of <CurrencyRepository>: %w", err),
errors.ErrInternalError,
)
}
insertedID := result.InsertedID.(primitive.ObjectID).Hex()
list.ID = insertedID
return list, nil
}

@ -0,0 +1,19 @@
package repository
import (
"context"
"go.mongodb.org/mongo-driver/mongo"
)
type HealthRepository struct {
MongoDB *mongo.Database
}
func NewHealthRepository(database *mongo.Database) *HealthRepository {
return &HealthRepository{MongoDB: database}
}
func (receiver *HealthRepository) Check(ctx context.Context) error {
return receiver.MongoDB.Client().Ping(ctx, nil)
}

@ -0,0 +1,108 @@
package repository
import (
"context"
"fmt"
"log"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/fields"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
mongoWrapper "penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/mongo"
)
type HistoryRepositoryDeps struct {
Logger *zap.Logger
MongoDB *mongo.Collection
}
type HistoryRepository struct {
logger *zap.Logger
mongoDB *mongo.Collection
}
func NewHistoryRepository(deps HistoryRepositoryDeps) *HistoryRepository {
if deps.Logger == nil {
log.Panicln("logger is nil on <NewHistoryRepository>")
}
if deps.MongoDB == nil {
log.Panicln("mongodb is nil on <NewHistoryRepository>")
}
return &HistoryRepository{
logger: deps.Logger,
mongoDB: deps.MongoDB,
}
}
func (receiver *HistoryRepository) Insert(ctx context.Context, history *models.History) (*models.History, errors.Error) {
result, err := receiver.mongoDB.InsertOne(ctx, history.Sanitize())
if err != nil {
receiver.logger.Error("failed to insert history on <Insert> of <HistoryRepository>",
zap.Any("history", history),
zap.Error(err),
)
return nil, errors.New(
fmt.Errorf("failed to insert history on <Insert> of <HistoryRepository>: %w", err),
errors.ErrInternalError,
)
}
insertedID := result.InsertedID.(primitive.ObjectID).Hex()
history.ID = insertedID
return history, nil
}
func (receiver *HistoryRepository) FindMany(ctx context.Context, page, limit int64) ([]models.History, errors.Error) {
filter := bson.M{fields.Account.IsDeleted: false}
findOptions := options.Find()
skip := (page - 1) * limit
findOptions.SetSkip(skip)
findOptions.SetLimit(limit)
histories, err := mongoWrapper.Find[models.History](ctx, &mongoWrapper.RequestSettings{
Driver: receiver.mongoDB,
Options: findOptions,
Filter: filter,
})
if err != nil {
receiver.logger.Error("failed to find many histories on <FindMany> of <HistoryRepository>",
zap.Int64("page", page),
zap.Int64("limit", limit),
zap.Int64("skip", skip),
zap.Error(err),
)
return nil, errors.New(
fmt.Errorf("failed to find many histories on <FindMany> of <HistoryRepository>: %w", err),
errors.ErrInternalError,
)
}
return histories, nil
}
func (receiver *HistoryRepository) CountAll(ctx context.Context) (int64, errors.Error) {
count, err := receiver.mongoDB.CountDocuments(ctx, bson.M{fields.History.IsDeleted: false})
if err != nil {
receiver.logger.Error("failed to count all documents on <CountAll> of <HistoryRepository>",
zap.Error(err),
)
return 0, errors.New(
fmt.Errorf("failed to count all documents on <CountAll> of <HistoryRepository>: %w", err),
errors.ErrInternalError,
)
}
return count, nil
}

@ -0,0 +1,508 @@
// Package swagger provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/deepmap/oapi-codegen version v1.12.4 DO NOT EDIT.
package swagger
import (
"bytes"
"compress/gzip"
"encoding/base64"
"fmt"
"net/http"
"net/url"
"path"
"strings"
"github.com/deepmap/oapi-codegen/pkg/runtime"
"github.com/getkin/kin-openapi/openapi3"
"github.com/labstack/echo/v4"
)
// ServerInterface represents all server handlers.
type ServerInterface interface {
// удалить собственный аккаунт
// (DELETE /account)
DeleteAccount(ctx echo.Context) error
// Получение текущего аккаунта юзера
// (GET /account)
GetAccount(ctx echo.Context) error
// Отредактировать аккаунт
// (PATCH /account)
ChangeAccount(ctx echo.Context) error
// Создать новый аккаунт
// (POST /account)
AddAccount(ctx echo.Context) error
// Удалить аккаунт по айди
// (DELETE /account/{userId})
DeleteDirectAccount(ctx echo.Context, userId string) error
// Получить аккаунт по ID пользователя системы единой авторизации
// (GET /account/{userId})
GetDirectAccount(ctx echo.Context, userId string) error
// Выставление статуса верификации
// (PATCH /account/{userId})
SetAccountVerificationStatus(ctx echo.Context, userId string) error
// списко аккаунтов с пагинацией
// (GET /accounts)
PaginationAccounts(ctx echo.Context, params PaginationAccountsParams) error
// Удаляем из корзины тариф
// (DELETE /cart)
RemoveFromCart(ctx echo.Context, params RemoveFromCartParams) error
// Добавляем в корзину тариф
// (PATCH /cart)
Add2cart(ctx echo.Context, params Add2cartParams) error
// оплатить козину
// (POST /cart/pay)
PayCart(ctx echo.Context) error
// получить список одобренных валют
// (GET /currencies)
GetCurrencies(ctx echo.Context) error
// обновляет список одобренных валют
// (PUT /currencies)
UpdateCurrencies(ctx echo.Context) error
// Получение лога событий связанных с аккаунтом
// (GET /history)
GetHistory(ctx echo.Context, params GetHistoryParams) error
// Изменить валюту кошелька
// (PATCH /wallet)
ChangeCurrency(ctx echo.Context) error
// Запрос на получение ссылки на оплату
// (POST /wallet)
RequestMoney(ctx echo.Context) error
}
// ServerInterfaceWrapper converts echo contexts to parameters.
type ServerInterfaceWrapper struct {
Handler ServerInterface
}
// DeleteAccount converts echo context to params.
func (w *ServerInterfaceWrapper) DeleteAccount(ctx echo.Context) error {
var err error
ctx.Set(BearerScopes, []string{""})
// Invoke the callback with all the unmarshalled arguments
err = w.Handler.DeleteAccount(ctx)
return err
}
// GetAccount converts echo context to params.
func (w *ServerInterfaceWrapper) GetAccount(ctx echo.Context) error {
var err error
ctx.Set(BearerScopes, []string{""})
// Invoke the callback with all the unmarshalled arguments
err = w.Handler.GetAccount(ctx)
return err
}
// ChangeAccount converts echo context to params.
func (w *ServerInterfaceWrapper) ChangeAccount(ctx echo.Context) error {
var err error
ctx.Set(BearerScopes, []string{""})
// Invoke the callback with all the unmarshalled arguments
err = w.Handler.ChangeAccount(ctx)
return err
}
// AddAccount converts echo context to params.
func (w *ServerInterfaceWrapper) AddAccount(ctx echo.Context) error {
var err error
ctx.Set(BearerScopes, []string{""})
// Invoke the callback with all the unmarshalled arguments
err = w.Handler.AddAccount(ctx)
return err
}
// DeleteDirectAccount converts echo context to params.
func (w *ServerInterfaceWrapper) DeleteDirectAccount(ctx echo.Context) error {
var err error
// ------------- Path parameter "userId" -------------
var userId string
err = runtime.BindStyledParameterWithLocation("simple", false, "userId", runtime.ParamLocationPath, ctx.Param("userId"), &userId)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter userId: %s", err))
}
ctx.Set(BearerScopes, []string{""})
// Invoke the callback with all the unmarshalled arguments
err = w.Handler.DeleteDirectAccount(ctx, userId)
return err
}
// GetDirectAccount converts echo context to params.
func (w *ServerInterfaceWrapper) GetDirectAccount(ctx echo.Context) error {
var err error
// ------------- Path parameter "userId" -------------
var userId string
err = runtime.BindStyledParameterWithLocation("simple", false, "userId", runtime.ParamLocationPath, ctx.Param("userId"), &userId)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter userId: %s", err))
}
ctx.Set(BearerScopes, []string{""})
// Invoke the callback with all the unmarshalled arguments
err = w.Handler.GetDirectAccount(ctx, userId)
return err
}
// SetAccountVerificationStatus converts echo context to params.
func (w *ServerInterfaceWrapper) SetAccountVerificationStatus(ctx echo.Context) error {
var err error
// ------------- Path parameter "userId" -------------
var userId string
err = runtime.BindStyledParameterWithLocation("simple", false, "userId", runtime.ParamLocationPath, ctx.Param("userId"), &userId)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter userId: %s", err))
}
ctx.Set(BearerScopes, []string{""})
// Invoke the callback with all the unmarshalled arguments
err = w.Handler.SetAccountVerificationStatus(ctx, userId)
return err
}
// PaginationAccounts converts echo context to params.
func (w *ServerInterfaceWrapper) PaginationAccounts(ctx echo.Context) error {
var err error
// Parameter object where we will unmarshal all parameters from the context
var params PaginationAccountsParams
// ------------- Optional query parameter "page" -------------
err = runtime.BindQueryParameter("form", false, false, "page", ctx.QueryParams(), &params.Page)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter page: %s", err))
}
// ------------- Optional query parameter "limit" -------------
err = runtime.BindQueryParameter("form", false, false, "limit", ctx.QueryParams(), &params.Limit)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err))
}
// Invoke the callback with all the unmarshalled arguments
err = w.Handler.PaginationAccounts(ctx, params)
return err
}
// RemoveFromCart converts echo context to params.
func (w *ServerInterfaceWrapper) RemoveFromCart(ctx echo.Context) error {
var err error
ctx.Set(BearerScopes, []string{""})
// Parameter object where we will unmarshal all parameters from the context
var params RemoveFromCartParams
// ------------- Required query parameter "id" -------------
err = runtime.BindQueryParameter("form", true, true, "id", ctx.QueryParams(), &params.Id)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err))
}
// Invoke the callback with all the unmarshalled arguments
err = w.Handler.RemoveFromCart(ctx, params)
return err
}
// Add2cart converts echo context to params.
func (w *ServerInterfaceWrapper) Add2cart(ctx echo.Context) error {
var err error
ctx.Set(BearerScopes, []string{""})
// Parameter object where we will unmarshal all parameters from the context
var params Add2cartParams
// ------------- Required query parameter "id" -------------
err = runtime.BindQueryParameter("form", true, true, "id", ctx.QueryParams(), &params.Id)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter id: %s", err))
}
// Invoke the callback with all the unmarshalled arguments
err = w.Handler.Add2cart(ctx, params)
return err
}
// PayCart converts echo context to params.
func (w *ServerInterfaceWrapper) PayCart(ctx echo.Context) error {
var err error
ctx.Set(BearerScopes, []string{""})
// Invoke the callback with all the unmarshalled arguments
err = w.Handler.PayCart(ctx)
return err
}
// GetCurrencies converts echo context to params.
func (w *ServerInterfaceWrapper) GetCurrencies(ctx echo.Context) error {
var err error
// Invoke the callback with all the unmarshalled arguments
err = w.Handler.GetCurrencies(ctx)
return err
}
// UpdateCurrencies converts echo context to params.
func (w *ServerInterfaceWrapper) UpdateCurrencies(ctx echo.Context) error {
var err error
ctx.Set(BearerScopes, []string{""})
// Invoke the callback with all the unmarshalled arguments
err = w.Handler.UpdateCurrencies(ctx)
return err
}
// GetHistory converts echo context to params.
func (w *ServerInterfaceWrapper) GetHistory(ctx echo.Context) error {
var err error
ctx.Set(BearerScopes, []string{""})
// Parameter object where we will unmarshal all parameters from the context
var params GetHistoryParams
// ------------- Optional query parameter "page" -------------
err = runtime.BindQueryParameter("form", false, false, "page", ctx.QueryParams(), &params.Page)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter page: %s", err))
}
// ------------- Optional query parameter "limit" -------------
err = runtime.BindQueryParameter("form", false, false, "limit", ctx.QueryParams(), &params.Limit)
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter limit: %s", err))
}
// Invoke the callback with all the unmarshalled arguments
err = w.Handler.GetHistory(ctx, params)
return err
}
// ChangeCurrency converts echo context to params.
func (w *ServerInterfaceWrapper) ChangeCurrency(ctx echo.Context) error {
var err error
ctx.Set(BearerScopes, []string{""})
// Invoke the callback with all the unmarshalled arguments
err = w.Handler.ChangeCurrency(ctx)
return err
}
// RequestMoney converts echo context to params.
func (w *ServerInterfaceWrapper) RequestMoney(ctx echo.Context) error {
var err error
ctx.Set(BearerScopes, []string{""})
// Invoke the callback with all the unmarshalled arguments
err = w.Handler.RequestMoney(ctx)
return err
}
// This is a simple interface which specifies echo.Route addition functions which
// are present on both echo.Echo and echo.Group, since we want to allow using
// either of them for path registration
type EchoRouter interface {
CONNECT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
HEAD(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
OPTIONS(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
PATCH(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
TRACE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
}
// RegisterHandlers adds each server route to the EchoRouter.
func RegisterHandlers(router EchoRouter, si ServerInterface) {
RegisterHandlersWithBaseURL(router, si, "")
}
// Registers handlers, and prepends BaseURL to the paths, so that the paths
// can be served under a prefix.
func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) {
wrapper := ServerInterfaceWrapper{
Handler: si,
}
router.DELETE(baseURL+"/account", wrapper.DeleteAccount)
router.GET(baseURL+"/account", wrapper.GetAccount)
router.PATCH(baseURL+"/account", wrapper.ChangeAccount)
router.POST(baseURL+"/account", wrapper.AddAccount)
router.DELETE(baseURL+"/account/:userId", wrapper.DeleteDirectAccount)
router.GET(baseURL+"/account/:userId", wrapper.GetDirectAccount)
router.PATCH(baseURL+"/account/:userId", wrapper.SetAccountVerificationStatus)
router.GET(baseURL+"/accounts", wrapper.PaginationAccounts)
router.DELETE(baseURL+"/cart", wrapper.RemoveFromCart)
router.PATCH(baseURL+"/cart", wrapper.Add2cart)
router.POST(baseURL+"/cart/pay", wrapper.PayCart)
router.GET(baseURL+"/currencies", wrapper.GetCurrencies)
router.PUT(baseURL+"/currencies", wrapper.UpdateCurrencies)
router.GET(baseURL+"/history", wrapper.GetHistory)
router.PATCH(baseURL+"/wallet", wrapper.ChangeCurrency)
router.POST(baseURL+"/wallet", wrapper.RequestMoney)
}
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
"H4sIAAAAAAAC/+xb/3MTx5L/V6b27oekbrFlY47g38Akd1wVJBUCKQq7krU0sjdIu2J3FeKjVGVZCYQy",
"geMuVUflArl8qXq/vSfLFpZtSf4Xev6jV90z+31ky4YAfsl7VUSWdnZ6ero//emenrtG0a3WXIc7gW/M",
"3jX84jKvWvTxfLHo1p0AP9Y8t8a9wOb0w2d2Cf/Dv7KqtQo3Zo33CmfLU+WzZxeL5femiqWz587NnD5X",
"mJoyTCNYqeETfuDZzpLRMI2i5QWp0TcPGj7ip2ljwTTsgFdJntwc6gvL86wVmtPjVsBL52nisutVrcCY",
"NUpWwE8FdpXrxCzxCj/iENu/KAellle2Kj6Pnl503Qq3HHzcsaocn/xnj5eNWeOfJuONmFS7MHkFn2mY",
"hh9YQd0/7Gm1YVflww3TqNdKR1133efepZfY3jtWpcKDwyT9VD7VaJiGx2/XbQ+VdpMMKxJBmUr0SqWx",
"SBnRHhnJDU4ueiGSz138ghcDlC+tI1ymU6/i3I6LM9zCf11vKTE2XtsFy7k1Z3mlvEcULa+07FZK3MO/",
"StwvenYtsF3HmDXgKfTFYwYd2IM2bEEX9sRDcQ/aDHahLVbFmlg3zIS6L10/f4XhPx9e1zqQX9RM8gMM",
"YYvNXZ+bZtCDPeixuevXp012Ovxzhokm9KAPHRiiJCaDfeiK+9AWa9CGrlgTTRRzgIINYUOs0i8DGMIO",
"E02xBkOxCkMYQHeU4IUzOnn5VzXbW7nsOsGyRu4foYvzinsMejQLitSFAfTEY5wWp9xN6Yq9c/nyu2PP",
"e4Nbuj35H1LX+FPeuHHjRnrS6cK01gGcenVRawbPYAh96IrVUer7+NqF/AszHqLenlpdWsU6o3/f81wv",
"b7VV7vvWEk87O3ofc9yAld26U9KtUPrfnFtKj5wpzJgxyNhO8K8z8WjbCfgS93LrKeJbzEgSnfD/bvuB",
"661onM6tVrmTDiYGbuF3aKxo7uRs0IY9tPUhfgt90WLiPj0wM611r9cTK14CYo8YZzzrzkUeWHbF1xjl",
"30gz0tzJs/swhE3RYrAvVqELW/TzHgzhBfTEmnhokvXCLvTw6Q3Rgi3REmtMfI04Ix6KNbEq1umtoXsh",
"bvSgZ8pN+C7ahmgK3KJNaItHDDrh7jE1cVc+NpRvwsn3oI1/iIeEStJbcVOb7AvfdSYYg6ewgY9uwR4C",
"Gor7ArZwXWgVa9CDfVzuNrRhH0WEHiNca6PJdGAoHk+k/PLuvBFYnl0u+/PG7M35kXs1b5gH/bjQ0G2m",
"/CJpCsW6H7hV7k3ISd93Slzrhq89uGdcNx2r6dnDQ7IZea1p+HXp4zqnv6LIUdrjy7bnByFvipcAT6ED",
"bRjolly1S6UKHz0GhtCBnrivG+t6S5qBz/H/bH5+HoPXEC3sOdqbCo5t/EGLmrzoOqWDBdHqPKebj6wV",
"1OAnoeUoArMYshPTCGznllsuI18xTOO2fcdGdS9yb1F+s+K6VdfhK4i87qJdwZ2zHT+wKpUqJQLIvfxl",
"GlQzTGNxevFqPNqqlC36qONIn0b8L8uQfF34/1m0oA99aDMSSHISRIUOIoN4AgPUachLMFajs4sH0IMd",
"Rh9XRTPprVOFs4WpMeKQaRTrnsed4opGql+00zDaqD3xaLzIjbpFHedf/z2yDfEQNhF5JO4gAxFrCIod",
"RKwh6gF2iCh8M8HgLwSaGwSsiKaRnkQTx4onyOHENwrDkeFtI58h7NuTWIgEpwubSAflbxgPdxG/oT0h",
"4XsXsVCsihZ0oS/Z4C5C45ZigfH6oWuGmCljAEqPvw8wGNAGDmi+HZMpQRTmd8UTJaWKO/ACZzveFtbq",
"XnHZ8rl/vhpmqhlVP4cN8YAMSDQjU4u1QdFsKGOUWJe6G4gnuNcUfsRD2CaEaJPp7YmHxliC+TV+BHGI",
"mxDfljx0INZxLxN7to2PdUQTldch9fbVO8QDMoI12nQJJEhjKUSj9bRggLZhHIOahf4RgUGIGVm1h+vN",
"A7nEvbpnBytXMfWTWHCBW56kyIv06YNQsv/49BOKIUmdve8E3GPBMmeBe4s77I4dLNOfn8vXzLLPWc3j",
"Zfsrk/GJpQk2r97PrMViiU9Nn545M29gRKfkk8iRnD+SdjkIakYDhbWdsqvftgTtIIPpqIyJPpGxS4rS",
"QxKBrtkhatFmp2KeI59oUyZI+UboBnk7e8TE17h3sCvuoa+iq6EI0l5XYRt6aCYMoQC/+VZaJ275BAWA",
"gIBpTnEJdiolVsiNRItkS0gkCdMeiiYNB/rQM0zjS+75UhlTE4WJAkXHGnesmm3MGqcnChPIF2pWsEwb",
"PGnFpSPJCDRK3Vf50H2ZfWZMlklkgj0ZA8Q6YQRGFAtfgCzGkDQ4LFOh9fo11/GlkU0XCjJJcALli1at",
"VrGLNHwSqWJc7hqzsCJtJL0M0RJNAuNvCSS7kdzxDmddsWEaM4WpVyacTO40osEz6OLeRhR8O4SIlGMa",
"szdjl7y50FhAZlatWphyGdFqeopxUxhKmL1Yx8CQWiLan7XkI4aEdrDQMI0lrkPEp6Q+5QIYecI6hIpz",
"2xjXKAZ1mXgE22TEbUoUmmH6jpFlgsF/wQ5sQY92oge7qcflFK3Y2HqwzSio7tI62plIsBMzkS1oY3yV",
"UnVk3rCpkqIODmdWPVh2Pfs/afdyVvpvPHjLTDShDWWkb4VNoggzr0GEX8hcZTo4An6Jb3bF2viOAj9l",
"dZpkq105WQYJEhY6wmdqVlBc1pYUtxE7YSAeh+ZMNUbJJ2E7ZAK42ajnTfUnehPGk97IhefMd27ZcpZS",
"IHu7zv3ggltaeWV7Jcvcmq36UXo+CkprlLqlqsZbgfVNYtpbsbJPMtbDc0XdcT27yGUopyXjQP2PA/I1",
"19eh/M+hnhBJmUx2NZEj4iWRX5iYMTSpgE1sJPLbrngQZRIbYh3ROGe650ult40c/GMZTLytZCCjtlVr",
"Kw0zoomTd2UZqXEgX/wRkU6W7TErQh4iiQFiH03aQbBrqpoO/tuXIV4S4yFT+IEG/kKaF/TNBBdO8LYc",
"Dx5BPi/aHi8m4nvN8qwqD7jnk+bSS7h0UZeX2fgTUufwhGs2rqrF+Vjg1bmZ2PRsnWjhzVg4/Hoi6e/r",
"ohrPKDqnkWtU4B3f7X5NcfIshO5LpkFc+EhU/Hd2sCzrxK8kEKp6xzDtcl0dk/7T3w7l8n963Kv3uJjc",
"j/Y5tLZR2UQqV11n5CG9sKqa1pgi6EdNCEak0aliFPorFa5WoScLvnE6oHy0I9azRSpZaFyjIN+ikpb+",
"HSYTj3GUTElkuky8TZE5Bs/gB3huMvgr/vF/0BP3pEiyQQF+o6Q8/iHn/1ejTPo69+yyMp2rYTvIm8WC",
"42VF6UOSY7X55I+IGo3G24JOGnsiGpy0p5MODv89xhpH+MxhzJg2Tx+tsxUt0rz08t2sqQ8xctNBU4uO",
"XLZl2I1aeyhSD8jvuuxfmOz/eQBd2eozJKpxPz5n0Lw+56sfWUu2Q3+eD5dyiIcmGmTSMol1OkRqI/qq",
"00DRZFOy76VCbSiq+YHc+XadeyuxP9esJW4kvbfEy1a9EhizU7ojkKxUJMb2CLnGFKFiV+1ghAyFgkaK",
"lyUXaVRJ2lLUMzmWh+c7KQM3sCofWUvyzfGRnVaXeVw6Rmkyp3Sd9ZGzxkXr0BV2tbbK5PFeGzaVPd0j",
"zrkz0hnDltU4NU3b+se86n7JP/Dc6pzsWMzYuc4m7INDzLH6M94YJ02kfENZWk8fU/3RGKiswu7IE9w4",
"3uzQRxkFjp7uIa+SbCmr3uRrYxsmqz2IMz7LJnkUDlXNTwYravhS7XLaZWTOoCXz1BXipot/SNf4HjWc",
"YAbDsMEj2r3Wn87xMs6RUHDoIFkFH+geIb5P1izZYqovYP8vtMM+RNUiHTmK6tOQZy2wT40Caxim0hCY",
"J0grKlq88co09VdFoueaDE5WTTpeh0rVd6lILV1Nv/2y0UWxJcW2c5Wnufipl9yyxM0X2Th27epFwzTm",
"zl88yq2W45KpiBq1E/1cGQKVGBid+yeSiyF1026EbV6yehe/K6HksIWIwlBdo9hr1Bma0e3xUulXpdbG",
"idleRD5Zi907fINfkw9fsxzVDcFLR/LaaCnqSPvlTQ59ezm+PDDKscP7BScyPYX/P/HpqceLrlcaPzsN",
"9+v3z07HKbarjqh1ulewc7JCZb5lhZqaNuVNiMSy6GKEeBzWjcj7kAhlU+t+whFDz5N+GF8LHJWN/BT1",
"e4VES1LFXI4yO++cYvCcSlF0CkZNX4lOhWzG0pa378LW5XYWTdr0wlyJPzqbQjmoXSzd2Flc9MrsHTrw",
"xkf7UvYtBALRUiRxoDp/8Cv51n11ZI6/dN9VM0ct76qFNNFo3sr1dzJZzBtitkVXZuJnJxj8ED38BHFz",
"QMx3KO5T7iHu0YWoIS2yqaIGtfCFOpM95smuCtW+SnXRARGpHQa7dO4n3xq1vTLJvGgbHlH5cCd8jAh+",
"9gKQhE3Z6BfejNuiauOelFo1E4Qd7rJNvpe+rtiRixrIBvgR3UtzcSvzqynUJ+8OxPmoDPQH35qJ49Nb",
"WraX8Uud5LZTdx5ypijhrvDaevbynjyQPCjlzn+ohPon/TUFpZlEpn2EuBB1F4ZQeBAcJSBfgfzoPrBT",
"DH4jVfXjeyYpyCdkScAszpfIqU0m0+98c0JftTQSGG2I7+iYow+9DLS35YxRAz99zAJ7KosXTUZ3bBAL",
"ZZkivCEdPtNKtQ4TJA8oEAzTPcQR/Gu6/XO49bGEqcvqxsWrQS0ruiUTU6MzhemC7gbLYuKu+0GWGd2J",
"P/BG1aWrH56amZ46y8TXav/bxNoPvUJVcZdsJ42y9NVnAfcD3YDasuvwK9Ed7HjY2XOF8H+6cR4P6p5z",
"zaukRy0HQc2fnZz07YBPePVJVcUceY3zIFUl7+1lw4K6Ppm4c6M26/cIE2mrqNjOLf2il1x3qYLLHude",
"4sFhRfYPpTw9ut6E+jvzWqLIz8krMKlanSx4D0QL9hjhWw82YFe0joCamhKh7iwrhJJeHkh0UEqall/m",
"KHO2yVLlc1Z0fJcboe4giRbsh8w2fadRvSKyQ807ErVBQv9wCHrGiMcjQho/rhaoGZC4NE7t6GpAmE80",
"Fhp/DwAA//8+Bz17tEYAAA==",
}
// GetSwagger returns the content of the embedded swagger specification file
// or error if failed to decode
func decodeSpec() ([]byte, error) {
zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, ""))
if err != nil {
return nil, fmt.Errorf("error base64 decoding spec: %s", err)
}
zr, err := gzip.NewReader(bytes.NewReader(zipped))
if err != nil {
return nil, fmt.Errorf("error decompressing spec: %s", err)
}
var buf bytes.Buffer
_, err = buf.ReadFrom(zr)
if err != nil {
return nil, fmt.Errorf("error decompressing spec: %s", err)
}
return buf.Bytes(), nil
}
var rawSpec = decodeSpecCached()
// a naive cached of a decoded swagger spec
func decodeSpecCached() func() ([]byte, error) {
data, err := decodeSpec()
return func() ([]byte, error) {
return data, err
}
}
// Constructs a synthetic filesystem for resolving external references when loading openapi specifications.
func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) {
var res = make(map[string]func() ([]byte, error))
if len(pathToFile) > 0 {
res[pathToFile] = rawSpec
}
return res
}
// GetSwagger returns the Swagger specification corresponding to the generated code
// in this file. The external references of Swagger specification are resolved.
// The logic of resolving external references is tightly connected to "import-mapping" feature.
// Externally referenced files must be embedded in the corresponding golang packages.
// Urls can be supported but this task was out of the scope.
func GetSwagger() (swagger *openapi3.T, err error) {
var resolvePath = PathToRawSpec("")
loader := openapi3.NewLoader()
loader.IsExternalRefsAllowed = true
loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) {
var pathToFile = url.String()
pathToFile = path.Clean(pathToFile)
getSpec, ok := resolvePath[pathToFile]
if !ok {
err1 := fmt.Errorf("path not found: %s", pathToFile)
return nil, err1
}
return getSpec()
}
var specData []byte
specData, err = rawSpec()
if err != nil {
return
}
swagger, err = loader.LoadFromData(specData)
if err != nil {
return
}
return
}

@ -0,0 +1,161 @@
package swagger
import (
"log"
"github.com/labstack/echo/v4"
)
//go:generate oapi-codegen --config api.yaml ../../../openapi.yaml
//go:generate oapi-codegen --config models.yaml ../../../openapi.yaml
type accountController interface {
RemoveAccount(ctx echo.Context) error
GetAccount(ctx echo.Context) error
CreateAccount(ctx echo.Context) error
RemoveDirectAccount(ctx echo.Context, userID string) error
GetDirectAccount(ctx echo.Context, userID string) error
GetAccounts(echo.Context, PaginationAccountsParams) error
SetVerificationStatus(ctx echo.Context, userID string) error
UpdateAccountName(ctx echo.Context) error
}
type currencyController interface {
GetCurrencies(ctx echo.Context) error
PutCurrencies(ctx echo.Context) error
}
type cartController interface {
Remove(echo.Context, RemoveFromCartParams) error
Add(echo.Context, Add2cartParams) error
Pay(echo.Context) error
}
type walletController interface {
ChangeCurrency(ctx echo.Context) error
GetPaymentLink(ctx echo.Context) error
}
type historyController interface {
GetHistoryList(ctx echo.Context, params GetHistoryParams) error
}
type Deps struct {
AccountController accountController
CurrencyController currencyController
CartController cartController
WalletController walletController
HistoryController historyController
}
type API struct {
accountController accountController
currencyController currencyController
cartController cartController
walletController walletController
historyController historyController
}
func New(deps Deps) *API {
if deps.AccountController == nil {
log.Panicln("AccountController is nil on <New (API)>")
}
if deps.CurrencyController == nil {
log.Panicln("currencyController is nil on <New (API)>")
}
if deps.CartController == nil {
log.Panicln("cartController is nil on <New (API)>")
}
if deps.WalletController == nil {
log.Panicln("walletController is nil on <New (API)>")
}
if deps.HistoryController == nil {
log.Panicln("historyController is nil on <New (API)>")
}
return &API{
accountController: deps.AccountController,
currencyController: deps.CurrencyController,
cartController: deps.CartController,
walletController: deps.WalletController,
historyController: deps.HistoryController,
}
}
// Account
func (receiver *API) DeleteAccount(ctx echo.Context) error {
return receiver.accountController.RemoveAccount(ctx)
}
func (receiver *API) ChangeAccount(ctx echo.Context) error {
return receiver.accountController.UpdateAccountName(ctx)
}
func (receiver *API) SetAccountVerificationStatus(ctx echo.Context, userID string) error {
return receiver.accountController.SetVerificationStatus(ctx, userID)
}
func (receiver *API) GetAccount(ctx echo.Context) error {
return receiver.accountController.GetAccount(ctx)
}
func (receiver *API) AddAccount(ctx echo.Context) error {
return receiver.accountController.CreateAccount(ctx)
}
func (receiver *API) DeleteDirectAccount(ctx echo.Context, userID string) error {
return receiver.accountController.RemoveDirectAccount(ctx, userID)
}
func (receiver *API) GetDirectAccount(ctx echo.Context, userID string) error {
return receiver.accountController.GetDirectAccount(ctx, userID)
}
func (receiver *API) PaginationAccounts(ctx echo.Context, params PaginationAccountsParams) error {
return receiver.accountController.GetAccounts(ctx, params)
}
// Cart
func (receiver *API) RemoveFromCart(ctx echo.Context, params RemoveFromCartParams) error {
return receiver.cartController.Remove(ctx, params)
}
func (receiver *API) Add2cart(ctx echo.Context, params Add2cartParams) error {
return receiver.cartController.Add(ctx, params)
}
func (receiver *API) PayCart(ctx echo.Context) error {
return receiver.cartController.Pay(ctx)
}
// Currency
func (receiver *API) GetCurrencies(ctx echo.Context) error {
return receiver.currencyController.GetCurrencies(ctx)
}
func (receiver *API) UpdateCurrencies(ctx echo.Context) error {
return receiver.currencyController.PutCurrencies(ctx)
}
// History
func (receiver *API) GetHistory(ctx echo.Context, params GetHistoryParams) error {
return receiver.historyController.GetHistoryList(ctx, params)
}
// Wallet
func (receiver *API) RequestMoney(ctx echo.Context) error {
return receiver.walletController.GetPaymentLink(ctx)
}
func (receiver *API) ChangeCurrency(ctx echo.Context) error {
return receiver.walletController.ChangeCurrency(ctx)
}

@ -0,0 +1,6 @@
output: api.gen.go
package: swagger
generate:
echo-server: true
models: false
embedded-spec: true

@ -0,0 +1,20 @@
package swagger
import (
"github.com/deepmap/oapi-codegen/pkg/middleware"
"github.com/getkin/kin-openapi/openapi3"
"github.com/getkin/kin-openapi/openapi3filter"
"github.com/labstack/echo/v4"
)
func CreateMiddleware(swagger *openapi3.T, authenticationFunc openapi3filter.AuthenticationFunc) echo.MiddlewareFunc {
validator := middleware.OapiRequestValidatorWithOptions(swagger,
&middleware.Options{
Options: openapi3filter.Options{
AuthenticationFunc: authenticationFunc,
},
},
)
return validator
}

@ -0,0 +1,188 @@
// Package swagger provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/deepmap/oapi-codegen version v1.12.4 DO NOT EDIT.
package swagger
import (
"time"
)
const (
BearerScopes = "Bearer.Scopes"
)
// Defines values for AccountStatus.
const (
Nko AccountStatus = "nko"
No AccountStatus = "no"
Org AccountStatus = "org"
)
// Defines values for PaymentType.
const (
PaymentTypeAlfabank PaymentType = "alfabank"
PaymentTypeB2bSberbank PaymentType = "b2bSberbank"
PaymentTypeBankCard PaymentType = "bankCard"
PaymentTypeCash PaymentType = "cash"
PaymentTypeInstallments PaymentType = "installments"
PaymentTypeMobile PaymentType = "mobile"
PaymentTypeQiwi PaymentType = "qiwi"
PaymentTypeSberbank PaymentType = "sberbank"
PaymentTypeSbp PaymentType = "sbp"
PaymentTypeTinkoffBank PaymentType = "tinkoffBank"
PaymentTypeYoomoney PaymentType = "yoomoney"
)
// Account defines model for Account.
type Account struct {
Id string `json:"_id"`
Cart []string `json:"cart"`
CreatedAt time.Time `json:"createdAt"`
DeletedAt *time.Time `json:"deletedAt,omitempty"`
IsDeleted *bool `json:"isDeleted,omitempty"`
Name Name `json:"name"`
Status AccountStatus `json:"status"`
UpdatedAt time.Time `json:"updatedAt"`
UserId string `json:"userId"`
Wallet Wallet `json:"wallet"`
}
// AccountStatus defines model for AccountStatus.
type AccountStatus string
// BankCard defines model for BankCard.
type BankCard struct {
// Cardholder Имя владельца карты
Cardholder *string `json:"cardholder,omitempty"`
// Csc Код CVC2 или CVV2, 3 или 4 символа, печатается на обратной стороне карты
Csc *string `json:"csc,omitempty"`
// ExpiryMonth Месяц истечения срока карты (MM)
ExpiryMonth string `json:"expiryMonth"`
// ExpiryYear Год истечения срока карты (YYYY)
ExpiryYear string `json:"expiryYear"`
// Number Номер карты
Number string `json:"number"`
}
// Error defines model for Error.
type Error struct {
Message string `json:"message"`
StatusCode *int64 `json:"statusCode,omitempty"`
}
// History defines model for History.
type History struct {
Comment string `json:"comment"`
CreatedAt time.Time `json:"createdAt"`
DeletedAt *time.Time `json:"deletedAt,omitempty"`
Id string `json:"id"`
IsDeleted *bool `json:"isDeleted,omitempty"`
// RawDetails Я пока не могу предположить, какие будут фильтры по истории, поэтому предлагаю в это поле просто класть строку с json. Ибо для каждого типа записи она своя.
RawDetails *string `json:"rawDetails,omitempty"`
Type string `json:"type"`
UpdatedAt time.Time `json:"updatedAt"`
UserId string `json:"userId"`
}
// Name defines model for Name.
type Name struct {
Firstname *string `json:"firstname,omitempty"`
Middlename *string `json:"middlename,omitempty"`
Orgname *string `json:"orgname,omitempty"`
Secondname *string `json:"secondname,omitempty"`
}
// PaymentType defines model for PaymentType.
type PaymentType string
// Wallet defines model for Wallet.
type Wallet struct {
// Cash Сумма money переведённая на текущий курс
Cash int64 `json:"cash"`
// Currency Текущий курс валюты
Currency string `json:"currency"`
// Money Деньги на счету в копейках. Чтобы при перессчётах не возникало денег изниоткуда. фиксируемся к одной валюте, она будет внутренней, никому её не покажем
Money int64 `json:"money"`
// PurchasesAmount Общая сумма денег, которые внёс пользователь
PurchasesAmount int64 `json:"purchasesAmount"`
// Spent Общая сумма потраченных денег за всё время существования аккаунта
Spent int64 `json:"spent"`
}
// SetAccountVerificationStatusJSONBody defines parameters for SetAccountVerificationStatus.
type SetAccountVerificationStatusJSONBody struct {
Status *AccountStatus `json:"status,omitempty"`
}
// PaginationAccountsParams defines parameters for PaginationAccounts.
type PaginationAccountsParams struct {
// Page Номер страницы, начиная с 1
Page *int `form:"page,omitempty" json:"page,omitempty"`
// Limit размер страницы
Limit *int `form:"limit,omitempty" json:"limit,omitempty"`
}
// RemoveFromCartParams defines parameters for RemoveFromCart.
type RemoveFromCartParams struct {
Id string `form:"id" json:"id"`
}
// Add2cartParams defines parameters for Add2cart.
type Add2cartParams struct {
Id string `form:"id" json:"id"`
}
// UpdateCurrenciesJSONBody defines parameters for UpdateCurrencies.
type UpdateCurrenciesJSONBody = []string
// GetHistoryParams defines parameters for GetHistory.
type GetHistoryParams struct {
// Page Номер страницы, начиная с 1
Page *int `form:"page,omitempty" json:"page,omitempty"`
// Limit Размер страницы
Limit *int `form:"limit,omitempty" json:"limit,omitempty"`
}
// ChangeCurrencyJSONBody defines parameters for ChangeCurrency.
type ChangeCurrencyJSONBody struct {
Currency string `json:"currency"`
}
// RequestMoneyJSONBody defines parameters for RequestMoney.
type RequestMoneyJSONBody struct {
Amount int `json:"amount"`
BankCard *BankCard `json:"bankCard,omitempty"`
// Currency ISO-4217 формат
Currency string `json:"currency"`
Login *string `json:"login,omitempty"`
PhoneNumber *string `json:"phoneNumber,omitempty"`
ReturnUrl *string `json:"returnUrl,omitempty"`
Type PaymentType `json:"type"`
}
// ChangeAccountJSONRequestBody defines body for ChangeAccount for application/json ContentType.
type ChangeAccountJSONRequestBody = Name
// SetAccountVerificationStatusJSONRequestBody defines body for SetAccountVerificationStatus for application/json ContentType.
type SetAccountVerificationStatusJSONRequestBody SetAccountVerificationStatusJSONBody
// UpdateCurrenciesJSONRequestBody defines body for UpdateCurrencies for application/json ContentType.
type UpdateCurrenciesJSONRequestBody = UpdateCurrenciesJSONBody
// ChangeCurrencyJSONRequestBody defines body for ChangeCurrency for application/json ContentType.
type ChangeCurrencyJSONRequestBody ChangeCurrencyJSONBody
// RequestMoneyJSONRequestBody defines body for RequestMoney for application/json ContentType.
type RequestMoneyJSONRequestBody RequestMoneyJSONBody

@ -0,0 +1,4 @@
output: models.gen.go
package: swagger
generate:
models: true

@ -0,0 +1,52 @@
package models
import "time"
type Account struct {
ID string `json:"id" bson:"_id,omitempty"`
UserID string `json:"userId" bson:"userId"`
Cart []string `json:"cart" bson:"cart"`
Wallet Wallet `json:"wallet" bson:"wallet"`
Name Name `json:"name" bson:"name"`
Status AccountStatus `json:"status" bson:"status"`
Deleted bool `json:"isDeleted" bson:"isDeleted"`
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"`
DeletedAt *time.Time `json:"deletedAt,omitempty" bson:"deletedAt,omitempty"`
}
func (receiver *Account) Sanitize() *Account {
now := time.Now()
receiver.ID = ""
receiver.Cart = []string{}
receiver.Wallet = Wallet{}
receiver.Name = Name{}
receiver.Status = DefaultAccountStatus
receiver.CreatedAt = now
receiver.UpdatedAt = now
receiver.DeletedAt = nil
receiver.Deleted = false
return receiver
}
type Name struct {
Middlename string `json:"middlename,omitempty"`
FirstName string `json:"firstname,omitempty"`
Orgname string `json:"orgname,omitempty"`
Secondname string `json:"secondname,omitempty"`
}
type SetAccountStatus struct {
Status AccountStatus `json:"status"`
}
type AccountStatus string
const (
AccountStatusNko AccountStatus = "nko"
AccountStatusNo AccountStatus = "no"
AccountStatusOrg AccountStatus = "org"
DefaultAccountStatus AccountStatus = AccountStatusNo
)

16
internal/models/auth.go Normal file

@ -0,0 +1,16 @@
package models
import "time"
type User struct {
ID string `json:"_id"`
Login string `json:"login"`
Email string `json:"email"`
PhoneNumber string `json:"phoneNumber"`
IsDeleted bool `json:"isDeleted"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
DeletedAt *time.Time `json:"deletedAt,omitempty"`
}
const AuthJWTDecodedUserIDKey = "userID"

5
internal/models/cart.go Normal file

@ -0,0 +1,5 @@
package models
type AddItemToCart struct {
ID string `json:"id"`
}

27
internal/models/common.go Normal file

@ -0,0 +1,27 @@
package models
type FastifyError struct {
StatusCode int `json:"statusCode"`
Error string `json:"error"`
Message string `json:"message"`
}
type ResponseErrorHTTP struct {
StatusCode int `json:"statusCode"`
Message string `json:"message"`
}
type PaginationResponse[T any] struct {
TotalPages int64 `json:"totalPages"`
Records []T `json:"records"`
}
type Pagination struct {
Page int64
Limit int64
}
const (
DefaultPageNumber int64 = 1
DefaultLimit int64 = 100
)

76
internal/models/config.go Normal file

@ -0,0 +1,76 @@
package models
import (
"time"
"github.com/golang-jwt/jwt/v5"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/mongo"
)
type Config struct {
HTTP ConfigurationHTTP
GRPC ConfigurationGRPC
Service ServiceConfiguration
Database mongo.Configuration
}
type ConfigurationHTTP struct {
Host string `env:"HTTP_HOST,default=localhost"`
Port string `env:"HTTP_PORT,default=8080"`
}
type ConfigurationGRPC struct {
Host string `env:"GRPC_HOST,default=localhost"`
Port string `env:"GRPC_PORT,default=8081"`
Domen string `env:"GRPC_DOMEN,default=https://domen.ru"`
}
type ServiceConfiguration struct {
AuthMicroservice AuthMicroserviceConfiguration
HubadminMicroservice HubadminMicroserviceConfiguration
CurrencyMicroservice CurrencyMicroserviceConfiguration
DiscountMicroservice DiscountMicroserviceConfiguration
PaymentMicroservice PaymentMicroserviceConfiguration
JWT JWTConfiguration
}
type JWTConfiguration struct {
PrivateKey string `env:"JWT_PRIVATE_KEY"`
PublicKey string `env:"JWT_PUBLIC_KEY,required"`
Issuer string `env:"JWT_ISSUER,required"`
Audience string `env:"JWT_AUDIENCE,required"`
Algorithm jwt.SigningMethodRSA
ExpiresIn time.Duration
}
type AuthMicroserviceConfiguration struct {
URL AuthMicroserviceURL
}
type HubadminMicroserviceConfiguration struct {
URL HubadminMicroserviceURL
}
type CurrencyMicroserviceConfiguration struct {
URL CurrencyMicroserviceURL
}
type PaymentMicroserviceConfiguration struct {
HostGRPC string `env:"PAYMENT_MICROSERVICE_GRPC_HOST,required"`
}
type DiscountMicroserviceConfiguration struct {
HostGRPC string `env:"DISCOUNT_MICROSERVICE_GRPC_HOST,required"`
}
type AuthMicroserviceURL struct {
User string `env:"AUTH_MICROSERVICE_USER_URL,required"`
}
type HubadminMicroserviceURL struct {
Tariff string `env:"HUBADMIN_MICROSERVICE_TARIFF_URL,required"`
}
type CurrencyMicroserviceURL struct {
Translate string `env:"CURRENCY_MICROSERVICE_TRANSLATE_URL,required"`
}

@ -0,0 +1,47 @@
package models
import "time"
type CurrencyKey = string
type CurrencyList struct {
ID string `json:"id" bson:"_id,omitempty"`
Name string `json:"name" bson:"name"`
Currencies []CurrencyKey `json:"currencies" bson:"currencies"`
Deleted bool `json:"isDeleted" bson:"isDeleted"`
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"`
DeletedAt *time.Time `json:"deletedAt,omitempty" bson:"deletedAt,omitempty"`
}
func (receiver *CurrencyList) Sanitize() *CurrencyList {
now := time.Now()
receiver.ID = ""
receiver.CreatedAt = now
receiver.UpdatedAt = now
receiver.DeletedAt = nil
receiver.Deleted = false
return receiver
}
const (
DefaultCurrencyListName = "currency_list"
InternalCurrencyKey CurrencyKey = "RUB"
)
type TranslateCurrency struct {
Money int64 `json:"value"`
From CurrencyKey `json:"currencyFrom"`
To CurrencyKey `json:"currencyTo"`
}
type CurrencyClientResponse[T any] struct {
Success bool `json:"success"`
Message T `json:"message"`
}
type ChangeCurrency struct {
Currency CurrencyKey `json:"currency"`
}

@ -0,0 +1,66 @@
package models
import "time"
type Discount struct {
Target DiscountCalculationTarget `json:"target"`
Condition DiscountCondition `json:"condition"`
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Layer uint32 `json:"layer"`
Audit Audit `json:"audit"`
Deprecated bool `json:"deprecated"`
}
type Audit struct {
UpdatedAt time.Time `json:"updatedAt"`
DeletedAt *time.Time `json:"deletedAt,omitempty"`
CreatedAt time.Time `json:"createdAt"`
Deleted bool `json:"deleted"`
}
type DiscountCalculationTarget struct {
Products []ProductTarget `json:"products"`
Factor float64 `json:"factor"`
TargetScope TargetScope `json:"scope"`
TargetGroup string `json:"group"`
Overhelm bool `json:"overhelm"`
}
type DiscountCondition struct {
Period *PeriodCondition `json:"period,omitempty"`
Product *string `json:"product,omitempty"`
PriceFrom *float64 `json:"priceFrom,omitempty"`
Group *string `json:"group,omitempty"`
User *string `json:"user,omitempty"`
UserType *string `json:"userType,omitempty"`
Coupon *string `json:"coupon,omitempty"`
PurchasesAmount *float64 `json:"purchasesAmount,omitempty"`
CartPurchasesAmount *float64 `json:"cartPurchasesAmount,omitempty"`
/* Срок использования (количество дней использования) */
Term *uint64 `json:"term"`
/* Количество использований (количество попыток) */
Usage *uint64 `json:"usage"`
}
type ProductTarget struct {
ID string `json:"productId"`
Factor float64 `json:"factor"`
Overhelm bool `json:"overhelm"`
}
type PeriodCondition struct {
From time.Time `json:"from"`
To time.Time `json:"to"`
}
type TargetScope string
const (
TargetSum TargetScope = "sum"
TargetGroup TargetScope = "group"
TargetEach TargetScope = "each"
)

@ -0,0 +1,34 @@
package models
import "time"
type History struct {
ID string `json:"id" bson:"_id,omitempty"`
UserID string `json:"userId" bson:"userId"`
Comment string `json:"comment" bson:"comment"`
Key string `json:"key" bson:"key"`
RawDetails string `json:"rawDetails" bson:"rawDetails"`
Deleted bool `json:"isDeleted" bson:"isDeleted"`
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"`
DeletedAt *time.Time `json:"deletedAt,omitempty" bson:"deletedAt,omitempty"`
}
func (receiver *History) Sanitize() *History {
now := time.Now()
receiver.ID = ""
receiver.CreatedAt = now
receiver.UpdatedAt = now
receiver.DeletedAt = nil
receiver.Deleted = false
return receiver
}
type CustomerHistoryKey string
const (
CustomerHistoryKeyReplenish = "customer.replenishWallet"
CustomerHistoryKeyPayCart = "customer.payCart"
)

@ -0,0 +1,54 @@
package models
type GetPaymentLinkBody struct {
Type PaymentType `json:"type"`
Currency string `json:"currency"`
Amount int64 `json:"amount"`
ReturnURL string `json:"returnUrl,omitempty"`
PhoneNumber string `json:"phoneNumber,omitempty"`
Login string `json:"login,omitempty"`
BankCard *BankCard `json:"bankCard,omitempty"`
}
type GetPaymentLinkRequest struct {
Body *GetPaymentLinkBody
ClientIP string
UserID string
}
type GetPaymentLinkResponse struct {
Link string `json:"link"`
}
type BankCard struct {
Number string `json:"number"`
ExpiryYear string `json:"expiryYear"`
ExpiryMonth string `json:"expiryMonth"`
CSC *string `json:"csc,omitempty"`
CardHolderName *string `json:"cardholder,omitempty"`
}
type PaymentType string
const (
PaymentTypeBankCard PaymentType = "bankCard"
PaymentTypeTinkoff PaymentType = "tinkoffBank"
PaymentTypeQiwi PaymentType = "qiwi"
PaymentTypeSberPay PaymentType = "sberbank"
PaymentTypeYoomoney PaymentType = "yoomoney"
PaymentTypeMobile PaymentType = "mobile"
PaymentTypeInstallments PaymentType = "installments"
PaymentTypeCash PaymentType = "cash"
PaymentTypeSBP PaymentType = "sbp"
PaymentTypeSberB2B PaymentType = "b2bSberbank"
PaymentTypeAlfabank PaymentType = "alfabank"
)
type PaymentEvent struct {
Key string
Message string
PaymentID string
UserID string
Currency string
Amount int64
}

26
internal/models/tariff.go Normal file

@ -0,0 +1,26 @@
package models
import "time"
type Tariff struct {
ID string `json:"_id"`
Name string `json:"name"`
Price int64 `json:"price"`
IsCustom bool `json:"isCustom"`
Privileges map[string]Privilege `json:"privileges"`
Deleted bool `json:"isDeleted"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
DeletedAt *time.Time `json:"deletedAt,omitempty"`
}
type Privilege struct {
ID string `json:"_id"`
Name string `json:"name"`
PrivilegeID string `json:"privilegeId"`
ServiceKey string `json:"serviceKey"`
Description string `json:"description"`
Type string `json:"type"`
Value string `json:"value"`
Price int64 `json:"price"`
}

33
internal/models/wallet.go Normal file

@ -0,0 +1,33 @@
package models
type Wallet struct {
Cash int64 `json:"cash" bson:"cash"`
Currency string `json:"currency" bson:"currency"`
/* Общая сумма потраченных денег за всё время существования аккаунта */
Spent int64 `json:"spent" bson:"spent"`
/* Общая сумма денег, которые внёс пользователь */
PurchasesAmount int64 `json:"purchasesAmount" bson:"purchasesAmount"`
/*
Money деньги на счету в копейках. Чтобы при перессчётах не возникало денег из ни откуда.
Фиксируемся к одной валюте, она будет внутренней, никому её не покажем.
*/
Money int64 `json:"money" bson:"money"`
/* Последний ID платежа, по которому было произведено пополнение средств (кошелька) */
LastPaymentID string `json:"lastPaymentId" bson:"lastPaymentId"`
}
type ReplenishAccountWallet struct {
Cash int64
Currency string
PaymentID string
Account *Account
}
type WithdrawAccountWallet struct {
Money int64
Account *Account
}

@ -0,0 +1,182 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc (unknown)
// source: customer/service.proto
package customer
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type History struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
UserID string `protobuf:"bytes,1,opt,name=UserID,proto3" json:"UserID,omitempty"`
Comment string `protobuf:"bytes,2,opt,name=Comment,proto3" json:"Comment,omitempty"`
Key string `protobuf:"bytes,3,opt,name=Key,proto3" json:"Key,omitempty"`
RawDetails string `protobuf:"bytes,4,opt,name=RawDetails,proto3" json:"RawDetails,omitempty"`
}
func (x *History) Reset() {
*x = History{}
if protoimpl.UnsafeEnabled {
mi := &file_customer_service_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *History) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*History) ProtoMessage() {}
func (x *History) ProtoReflect() protoreflect.Message {
mi := &file_customer_service_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use History.ProtoReflect.Descriptor instead.
func (*History) Descriptor() ([]byte, []int) {
return file_customer_service_proto_rawDescGZIP(), []int{0}
}
func (x *History) GetUserID() string {
if x != nil {
return x.UserID
}
return ""
}
func (x *History) GetComment() string {
if x != nil {
return x.Comment
}
return ""
}
func (x *History) GetKey() string {
if x != nil {
return x.Key
}
return ""
}
func (x *History) GetRawDetails() string {
if x != nil {
return x.RawDetails
}
return ""
}
var File_customer_service_proto protoreflect.FileDescriptor
var file_customer_service_proto_rawDesc = []byte{
0x0a, 0x16, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d,
0x65, 0x72, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22,
0x6d, 0x0a, 0x07, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x55, 0x73,
0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x55, 0x73, 0x65, 0x72,
0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03,
0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x4b, 0x65, 0x79, 0x12, 0x1e,
0x0a, 0x0a, 0x52, 0x61, 0x77, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0a, 0x52, 0x61, 0x77, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x32, 0x4f,
0x0a, 0x0f, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x12, 0x3c, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f,
0x72, 0x79, 0x12, 0x11, 0x2e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x2e, 0x48, 0x69,
0x73, 0x74, 0x6f, 0x72, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x42,
0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_customer_service_proto_rawDescOnce sync.Once
file_customer_service_proto_rawDescData = file_customer_service_proto_rawDesc
)
func file_customer_service_proto_rawDescGZIP() []byte {
file_customer_service_proto_rawDescOnce.Do(func() {
file_customer_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_customer_service_proto_rawDescData)
})
return file_customer_service_proto_rawDescData
}
var file_customer_service_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_customer_service_proto_goTypes = []interface{}{
(*History)(nil), // 0: customer.History
(*emptypb.Empty)(nil), // 1: google.protobuf.Empty
}
var file_customer_service_proto_depIdxs = []int32{
0, // 0: customer.CustomerService.InsertHistory:input_type -> customer.History
1, // 1: customer.CustomerService.InsertHistory:output_type -> google.protobuf.Empty
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_customer_service_proto_init() }
func file_customer_service_proto_init() {
if File_customer_service_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_customer_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*History); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_customer_service_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_customer_service_proto_goTypes,
DependencyIndexes: file_customer_service_proto_depIdxs,
MessageInfos: file_customer_service_proto_msgTypes,
}.Build()
File_customer_service_proto = out.File
file_customer_service_proto_rawDesc = nil
file_customer_service_proto_goTypes = nil
file_customer_service_proto_depIdxs = nil
}

@ -0,0 +1,100 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
package customer
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
emptypb "google.golang.org/protobuf/types/known/emptypb"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// CustomerServiceClient is the client API for CustomerService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type CustomerServiceClient interface {
InsertHistory(ctx context.Context, in *History, opts ...grpc.CallOption) (*emptypb.Empty, error)
}
type customerServiceClient struct {
cc grpc.ClientConnInterface
}
func NewCustomerServiceClient(cc grpc.ClientConnInterface) CustomerServiceClient {
return &customerServiceClient{cc}
}
func (c *customerServiceClient) InsertHistory(ctx context.Context, in *History, opts ...grpc.CallOption) (*emptypb.Empty, error) {
out := new(emptypb.Empty)
err := c.cc.Invoke(ctx, "/customer.CustomerService/InsertHistory", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// CustomerServiceServer is the server API for CustomerService service.
// All implementations should embed UnimplementedCustomerServiceServer
// for forward compatibility
type CustomerServiceServer interface {
InsertHistory(context.Context, *History) (*emptypb.Empty, error)
}
// UnimplementedCustomerServiceServer should be embedded to have forward compatible implementations.
type UnimplementedCustomerServiceServer struct {
}
func (UnimplementedCustomerServiceServer) InsertHistory(context.Context, *History) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method InsertHistory not implemented")
}
// UnsafeCustomerServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to CustomerServiceServer will
// result in compilation errors.
type UnsafeCustomerServiceServer interface {
mustEmbedUnimplementedCustomerServiceServer()
}
func RegisterCustomerServiceServer(s grpc.ServiceRegistrar, srv CustomerServiceServer) {
s.RegisterService(&CustomerService_ServiceDesc, srv)
}
func _CustomerService_InsertHistory_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(History)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CustomerServiceServer).InsertHistory(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/customer.CustomerService/InsertHistory",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CustomerServiceServer).InsertHistory(ctx, req.(*History))
}
return interceptor(ctx, in, info, handler)
}
// CustomerService_ServiceDesc is the grpc.ServiceDesc for CustomerService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var CustomerService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "customer.CustomerService",
HandlerType: (*CustomerServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "InsertHistory",
Handler: _CustomerService_InsertHistory_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "customer/service.proto",
}

@ -0,0 +1,192 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc (unknown)
// source: discount/audit.model.proto
package discount
import (
_ "google.golang.org/genproto/googleapis/api/annotations"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
_ "google.golang.org/protobuf/types/known/emptypb"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Audit struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=UpdatedAt,proto3" json:"UpdatedAt,omitempty"`
CreatedAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=CreatedAt,proto3" json:"CreatedAt,omitempty"`
DeletedAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=DeletedAt,proto3,oneof" json:"DeletedAt,omitempty"`
Deleted bool `protobuf:"varint,4,opt,name=Deleted,proto3" json:"Deleted,omitempty"`
}
func (x *Audit) Reset() {
*x = Audit{}
if protoimpl.UnsafeEnabled {
mi := &file_discount_audit_model_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Audit) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Audit) ProtoMessage() {}
func (x *Audit) ProtoReflect() protoreflect.Message {
mi := &file_discount_audit_model_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Audit.ProtoReflect.Descriptor instead.
func (*Audit) Descriptor() ([]byte, []int) {
return file_discount_audit_model_proto_rawDescGZIP(), []int{0}
}
func (x *Audit) GetUpdatedAt() *timestamppb.Timestamp {
if x != nil {
return x.UpdatedAt
}
return nil
}
func (x *Audit) GetCreatedAt() *timestamppb.Timestamp {
if x != nil {
return x.CreatedAt
}
return nil
}
func (x *Audit) GetDeletedAt() *timestamppb.Timestamp {
if x != nil {
return x.DeletedAt
}
return nil
}
func (x *Audit) GetDeleted() bool {
if x != nil {
return x.Deleted
}
return false
}
var File_discount_audit_model_proto protoreflect.FileDescriptor
var file_discount_audit_model_proto_rawDesc = []byte{
0x0a, 0x1a, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x61, 0x75, 0x64, 0x69, 0x74,
0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x64, 0x69,
0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61,
0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x22, 0xe2, 0x01, 0x0a, 0x05, 0x41, 0x75, 0x64, 0x69, 0x74, 0x12, 0x38, 0x0a, 0x09,
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x55, 0x70, 0x64,
0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x38, 0x0a, 0x09, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
0x64, 0x41, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74,
0x12, 0x3d, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x41, 0x74, 0x18, 0x03, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48,
0x00, 0x52, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x41, 0x74, 0x88, 0x01, 0x01, 0x12,
0x18, 0x0a, 0x07, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
0x52, 0x07, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x44, 0x65,
0x6c, 0x65, 0x74, 0x65, 0x64, 0x41, 0x74, 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x64, 0x69, 0x73,
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_discount_audit_model_proto_rawDescOnce sync.Once
file_discount_audit_model_proto_rawDescData = file_discount_audit_model_proto_rawDesc
)
func file_discount_audit_model_proto_rawDescGZIP() []byte {
file_discount_audit_model_proto_rawDescOnce.Do(func() {
file_discount_audit_model_proto_rawDescData = protoimpl.X.CompressGZIP(file_discount_audit_model_proto_rawDescData)
})
return file_discount_audit_model_proto_rawDescData
}
var file_discount_audit_model_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_discount_audit_model_proto_goTypes = []interface{}{
(*Audit)(nil), // 0: discount.Audit
(*timestamppb.Timestamp)(nil), // 1: google.protobuf.Timestamp
}
var file_discount_audit_model_proto_depIdxs = []int32{
1, // 0: discount.Audit.UpdatedAt:type_name -> google.protobuf.Timestamp
1, // 1: discount.Audit.CreatedAt:type_name -> google.protobuf.Timestamp
1, // 2: discount.Audit.DeletedAt:type_name -> google.protobuf.Timestamp
3, // [3:3] is the sub-list for method output_type
3, // [3:3] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name
}
func init() { file_discount_audit_model_proto_init() }
func file_discount_audit_model_proto_init() {
if File_discount_audit_model_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_discount_audit_model_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Audit); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_discount_audit_model_proto_msgTypes[0].OneofWrappers = []interface{}{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_discount_audit_model_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_discount_audit_model_proto_goTypes,
DependencyIndexes: file_discount_audit_model_proto_depIdxs,
MessageInfos: file_discount_audit_model_proto_msgTypes,
}.Build()
File_discount_audit_model_proto = out.File
file_discount_audit_model_proto_rawDesc = nil
file_discount_audit_model_proto_goTypes = nil
file_discount_audit_model_proto_depIdxs = nil
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,524 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc (unknown)
// source: discount/service.proto
package discount
import (
_ "google.golang.org/genproto/googleapis/api/annotations"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type GetDiscountByIDRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
}
func (x *GetDiscountByIDRequest) Reset() {
*x = GetDiscountByIDRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_discount_service_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetDiscountByIDRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetDiscountByIDRequest) ProtoMessage() {}
func (x *GetDiscountByIDRequest) ProtoReflect() protoreflect.Message {
mi := &file_discount_service_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetDiscountByIDRequest.ProtoReflect.Descriptor instead.
func (*GetDiscountByIDRequest) Descriptor() ([]byte, []int) {
return file_discount_service_proto_rawDescGZIP(), []int{0}
}
func (x *GetDiscountByIDRequest) GetID() string {
if x != nil {
return x.ID
}
return ""
}
type ApplyDiscountRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
UserInformation *UserInformation `protobuf:"bytes,1,opt,name=UserInformation,proto3" json:"UserInformation,omitempty"`
Products []*ProductInformation `protobuf:"bytes,2,rep,name=Products,proto3" json:"Products,omitempty"`
Date *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=Date,proto3" json:"Date,omitempty"`
Coupon *string `protobuf:"bytes,4,opt,name=Coupon,proto3,oneof" json:"Coupon,omitempty"`
}
func (x *ApplyDiscountRequest) Reset() {
*x = ApplyDiscountRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_discount_service_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ApplyDiscountRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ApplyDiscountRequest) ProtoMessage() {}
func (x *ApplyDiscountRequest) ProtoReflect() protoreflect.Message {
mi := &file_discount_service_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ApplyDiscountRequest.ProtoReflect.Descriptor instead.
func (*ApplyDiscountRequest) Descriptor() ([]byte, []int) {
return file_discount_service_proto_rawDescGZIP(), []int{1}
}
func (x *ApplyDiscountRequest) GetUserInformation() *UserInformation {
if x != nil {
return x.UserInformation
}
return nil
}
func (x *ApplyDiscountRequest) GetProducts() []*ProductInformation {
if x != nil {
return x.Products
}
return nil
}
func (x *ApplyDiscountRequest) GetDate() *timestamppb.Timestamp {
if x != nil {
return x.Date
}
return nil
}
func (x *ApplyDiscountRequest) GetCoupon() string {
if x != nil && x.Coupon != nil {
return *x.Coupon
}
return ""
}
type ApplyDiscountResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Price float64 `protobuf:"fixed64,1,opt,name=Price,proto3" json:"Price,omitempty"`
AppliedDiscounts []*Discount `protobuf:"bytes,2,rep,name=AppliedDiscounts,proto3" json:"AppliedDiscounts,omitempty"`
}
func (x *ApplyDiscountResponse) Reset() {
*x = ApplyDiscountResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_discount_service_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ApplyDiscountResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ApplyDiscountResponse) ProtoMessage() {}
func (x *ApplyDiscountResponse) ProtoReflect() protoreflect.Message {
mi := &file_discount_service_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ApplyDiscountResponse.ProtoReflect.Descriptor instead.
func (*ApplyDiscountResponse) Descriptor() ([]byte, []int) {
return file_discount_service_proto_rawDescGZIP(), []int{2}
}
func (x *ApplyDiscountResponse) GetPrice() float64 {
if x != nil {
return x.Price
}
return 0
}
func (x *ApplyDiscountResponse) GetAppliedDiscounts() []*Discount {
if x != nil {
return x.AppliedDiscounts
}
return nil
}
type CreateDiscountRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"`
Layer uint32 `protobuf:"varint,2,opt,name=Layer,proto3" json:"Layer,omitempty"`
Description string `protobuf:"bytes,3,opt,name=Description,proto3" json:"Description,omitempty"`
Condition *DiscountCondition `protobuf:"bytes,4,opt,name=Condition,proto3" json:"Condition,omitempty"`
Target *DiscountCalculationTarget `protobuf:"bytes,5,opt,name=Target,proto3" json:"Target,omitempty"`
}
func (x *CreateDiscountRequest) Reset() {
*x = CreateDiscountRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_discount_service_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CreateDiscountRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreateDiscountRequest) ProtoMessage() {}
func (x *CreateDiscountRequest) ProtoReflect() protoreflect.Message {
mi := &file_discount_service_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreateDiscountRequest.ProtoReflect.Descriptor instead.
func (*CreateDiscountRequest) Descriptor() ([]byte, []int) {
return file_discount_service_proto_rawDescGZIP(), []int{3}
}
func (x *CreateDiscountRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *CreateDiscountRequest) GetLayer() uint32 {
if x != nil {
return x.Layer
}
return 0
}
func (x *CreateDiscountRequest) GetDescription() string {
if x != nil {
return x.Description
}
return ""
}
func (x *CreateDiscountRequest) GetCondition() *DiscountCondition {
if x != nil {
return x.Condition
}
return nil
}
func (x *CreateDiscountRequest) GetTarget() *DiscountCalculationTarget {
if x != nil {
return x.Target
}
return nil
}
var File_discount_service_proto protoreflect.FileDescriptor
var file_discount_service_proto_rawDesc = []byte{
0x0a, 0x16, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75,
0x6e, 0x74, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61,
0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d,
0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x28, 0x0a,
0x16, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x22, 0xed, 0x01, 0x0a, 0x14, 0x41, 0x70, 0x70, 0x6c,
0x79, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x43, 0x0a, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x64, 0x69, 0x73, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x55, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74,
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75,
0x6e, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x12,
0x2e, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x44, 0x61, 0x74, 0x65, 0x12,
0x1b, 0x0a, 0x06, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48,
0x00, 0x52, 0x06, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07,
0x5f, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x22, 0x6d, 0x0a, 0x15, 0x41, 0x70, 0x70, 0x6c, 0x79,
0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x14, 0x0a, 0x05, 0x50, 0x72, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52,
0x05, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x3e, 0x0a, 0x10, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x65,
0x64, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x12, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x52, 0x10, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x44, 0x69, 0x73,
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0xdb, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74,
0x65, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0d, 0x52, 0x05, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x44, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x09,
0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1b, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x43, 0x6f,
0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x06, 0x54, 0x61, 0x72, 0x67, 0x65,
0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75,
0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x61, 0x6c, 0x63, 0x75,
0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x54, 0x61,
0x72, 0x67, 0x65, 0x74, 0x32, 0x80, 0x07, 0x0a, 0x0f, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x55, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x41,
0x6c, 0x6c, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d,
0x70, 0x74, 0x79, 0x1a, 0x13, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44,
0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f,
0x12, 0x0d, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x61, 0x6c, 0x6c, 0x12,
0x66, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75,
0x6e, 0x74, 0x73, 0x12, 0x20, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x47,
0x65, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x15, 0x12, 0x13, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x75, 0x73,
0x65, 0x72, 0x2f, 0x7b, 0x49, 0x44, 0x7d, 0x12, 0x69, 0x0a, 0x12, 0x44, 0x65, 0x74, 0x65, 0x72,
0x6d, 0x69, 0x6e, 0x65, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x1e, 0x2e,
0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x44, 0x69,
0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e,
0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x73, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, 0x13, 0x2f,
0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69,
0x6e, 0x65, 0x12, 0x6d, 0x0a, 0x0e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x44, 0x69, 0x73, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x73, 0x12, 0x1e, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e,
0x41, 0x70, 0x70, 0x6c, 0x79, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e,
0x41, 0x70, 0x70, 0x6c, 0x79, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x3a, 0x01, 0x2a,
0x22, 0x0f, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x61, 0x70, 0x70, 0x6c,
0x79, 0x12, 0x5f, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x42, 0x79, 0x49, 0x44, 0x12, 0x20, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e,
0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93,
0x02, 0x10, 0x12, 0x0e, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x7b, 0x49,
0x44, 0x7d, 0x12, 0x58, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e,
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x11, 0x82, 0xd3, 0xe4, 0x93, 0x02,
0x0b, 0x22, 0x09, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x5c, 0x0a, 0x0f,
0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12,
0x1a, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x1a, 0x12, 0x2e, 0x64, 0x69,
0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22,
0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x1a, 0x0e, 0x2f, 0x64, 0x69, 0x73,
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, 0x7b, 0x49, 0x44, 0x7d, 0x12, 0x5b, 0x0a, 0x0e, 0x55, 0x70,
0x64, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x2e, 0x64,
0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x1a, 0x12, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x19, 0x82, 0xd3,
0xe4, 0x93, 0x02, 0x13, 0x3a, 0x01, 0x2a, 0x32, 0x0e, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75,
0x6e, 0x74, 0x2f, 0x7b, 0x49, 0x44, 0x7d, 0x12, 0x5e, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74,
0x65, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x20, 0x2e, 0x64, 0x69, 0x73, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x64, 0x69,
0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22,
0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x2a, 0x0e, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75,
0x6e, 0x74, 0x2f, 0x7b, 0x49, 0x44, 0x7d, 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x2f, 0x64, 0x69, 0x73,
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_discount_service_proto_rawDescOnce sync.Once
file_discount_service_proto_rawDescData = file_discount_service_proto_rawDesc
)
func file_discount_service_proto_rawDescGZIP() []byte {
file_discount_service_proto_rawDescOnce.Do(func() {
file_discount_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_discount_service_proto_rawDescData)
})
return file_discount_service_proto_rawDescData
}
var file_discount_service_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_discount_service_proto_goTypes = []interface{}{
(*GetDiscountByIDRequest)(nil), // 0: discount.GetDiscountByIDRequest
(*ApplyDiscountRequest)(nil), // 1: discount.ApplyDiscountRequest
(*ApplyDiscountResponse)(nil), // 2: discount.ApplyDiscountResponse
(*CreateDiscountRequest)(nil), // 3: discount.CreateDiscountRequest
(*UserInformation)(nil), // 4: discount.UserInformation
(*ProductInformation)(nil), // 5: discount.ProductInformation
(*timestamppb.Timestamp)(nil), // 6: google.protobuf.Timestamp
(*Discount)(nil), // 7: discount.Discount
(*DiscountCondition)(nil), // 8: discount.DiscountCondition
(*DiscountCalculationTarget)(nil), // 9: discount.DiscountCalculationTarget
(*emptypb.Empty)(nil), // 10: google.protobuf.Empty
(*DiscountOptional)(nil), // 11: discount.DiscountOptional
(*Discounts)(nil), // 12: discount.Discounts
}
var file_discount_service_proto_depIdxs = []int32{
4, // 0: discount.ApplyDiscountRequest.UserInformation:type_name -> discount.UserInformation
5, // 1: discount.ApplyDiscountRequest.Products:type_name -> discount.ProductInformation
6, // 2: discount.ApplyDiscountRequest.Date:type_name -> google.protobuf.Timestamp
7, // 3: discount.ApplyDiscountResponse.AppliedDiscounts:type_name -> discount.Discount
8, // 4: discount.CreateDiscountRequest.Condition:type_name -> discount.DiscountCondition
9, // 5: discount.CreateDiscountRequest.Target:type_name -> discount.DiscountCalculationTarget
10, // 6: discount.DiscountService.GetAllDiscounts:input_type -> google.protobuf.Empty
0, // 7: discount.DiscountService.GetUserDiscounts:input_type -> discount.GetDiscountByIDRequest
1, // 8: discount.DiscountService.DetermineDiscounts:input_type -> discount.ApplyDiscountRequest
1, // 9: discount.DiscountService.ApplyDiscounts:input_type -> discount.ApplyDiscountRequest
0, // 10: discount.DiscountService.GetDiscountByID:input_type -> discount.GetDiscountByIDRequest
3, // 11: discount.DiscountService.CreateDiscount:input_type -> discount.CreateDiscountRequest
11, // 12: discount.DiscountService.ReplaceDiscount:input_type -> discount.DiscountOptional
11, // 13: discount.DiscountService.UpdateDiscount:input_type -> discount.DiscountOptional
0, // 14: discount.DiscountService.DeleteDiscount:input_type -> discount.GetDiscountByIDRequest
12, // 15: discount.DiscountService.GetAllDiscounts:output_type -> discount.Discounts
12, // 16: discount.DiscountService.GetUserDiscounts:output_type -> discount.Discounts
12, // 17: discount.DiscountService.DetermineDiscounts:output_type -> discount.Discounts
2, // 18: discount.DiscountService.ApplyDiscounts:output_type -> discount.ApplyDiscountResponse
7, // 19: discount.DiscountService.GetDiscountByID:output_type -> discount.Discount
7, // 20: discount.DiscountService.CreateDiscount:output_type -> discount.Discount
7, // 21: discount.DiscountService.ReplaceDiscount:output_type -> discount.Discount
7, // 22: discount.DiscountService.UpdateDiscount:output_type -> discount.Discount
7, // 23: discount.DiscountService.DeleteDiscount:output_type -> discount.Discount
15, // [15:24] is the sub-list for method output_type
6, // [6:15] is the sub-list for method input_type
6, // [6:6] is the sub-list for extension type_name
6, // [6:6] is the sub-list for extension extendee
0, // [0:6] is the sub-list for field type_name
}
func init() { file_discount_service_proto_init() }
func file_discount_service_proto_init() {
if File_discount_service_proto != nil {
return
}
file_discount_discount_model_proto_init()
if !protoimpl.UnsafeEnabled {
file_discount_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetDiscountByIDRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_discount_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ApplyDiscountRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_discount_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ApplyDiscountResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_discount_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateDiscountRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_discount_service_proto_msgTypes[1].OneofWrappers = []interface{}{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_discount_service_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_discount_service_proto_goTypes,
DependencyIndexes: file_discount_service_proto_depIdxs,
MessageInfos: file_discount_service_proto_msgTypes,
}.Build()
File_discount_service_proto = out.File
file_discount_service_proto_rawDesc = nil
file_discount_service_proto_goTypes = nil
file_discount_service_proto_depIdxs = nil
}

@ -0,0 +1,388 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
package discount
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
emptypb "google.golang.org/protobuf/types/known/emptypb"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// DiscountServiceClient is the client API for DiscountService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type DiscountServiceClient interface {
GetAllDiscounts(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*Discounts, error)
GetUserDiscounts(ctx context.Context, in *GetDiscountByIDRequest, opts ...grpc.CallOption) (*Discounts, error)
DetermineDiscounts(ctx context.Context, in *ApplyDiscountRequest, opts ...grpc.CallOption) (*Discounts, error)
ApplyDiscounts(ctx context.Context, in *ApplyDiscountRequest, opts ...grpc.CallOption) (*ApplyDiscountResponse, error)
GetDiscountByID(ctx context.Context, in *GetDiscountByIDRequest, opts ...grpc.CallOption) (*Discount, error)
CreateDiscount(ctx context.Context, in *CreateDiscountRequest, opts ...grpc.CallOption) (*Discount, error)
ReplaceDiscount(ctx context.Context, in *DiscountOptional, opts ...grpc.CallOption) (*Discount, error)
UpdateDiscount(ctx context.Context, in *DiscountOptional, opts ...grpc.CallOption) (*Discount, error)
DeleteDiscount(ctx context.Context, in *GetDiscountByIDRequest, opts ...grpc.CallOption) (*Discount, error)
}
type discountServiceClient struct {
cc grpc.ClientConnInterface
}
func NewDiscountServiceClient(cc grpc.ClientConnInterface) DiscountServiceClient {
return &discountServiceClient{cc}
}
func (c *discountServiceClient) GetAllDiscounts(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*Discounts, error) {
out := new(Discounts)
err := c.cc.Invoke(ctx, "/discount.DiscountService/GetAllDiscounts", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *discountServiceClient) GetUserDiscounts(ctx context.Context, in *GetDiscountByIDRequest, opts ...grpc.CallOption) (*Discounts, error) {
out := new(Discounts)
err := c.cc.Invoke(ctx, "/discount.DiscountService/GetUserDiscounts", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *discountServiceClient) DetermineDiscounts(ctx context.Context, in *ApplyDiscountRequest, opts ...grpc.CallOption) (*Discounts, error) {
out := new(Discounts)
err := c.cc.Invoke(ctx, "/discount.DiscountService/DetermineDiscounts", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *discountServiceClient) ApplyDiscounts(ctx context.Context, in *ApplyDiscountRequest, opts ...grpc.CallOption) (*ApplyDiscountResponse, error) {
out := new(ApplyDiscountResponse)
err := c.cc.Invoke(ctx, "/discount.DiscountService/ApplyDiscounts", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *discountServiceClient) GetDiscountByID(ctx context.Context, in *GetDiscountByIDRequest, opts ...grpc.CallOption) (*Discount, error) {
out := new(Discount)
err := c.cc.Invoke(ctx, "/discount.DiscountService/GetDiscountByID", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *discountServiceClient) CreateDiscount(ctx context.Context, in *CreateDiscountRequest, opts ...grpc.CallOption) (*Discount, error) {
out := new(Discount)
err := c.cc.Invoke(ctx, "/discount.DiscountService/CreateDiscount", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *discountServiceClient) ReplaceDiscount(ctx context.Context, in *DiscountOptional, opts ...grpc.CallOption) (*Discount, error) {
out := new(Discount)
err := c.cc.Invoke(ctx, "/discount.DiscountService/ReplaceDiscount", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *discountServiceClient) UpdateDiscount(ctx context.Context, in *DiscountOptional, opts ...grpc.CallOption) (*Discount, error) {
out := new(Discount)
err := c.cc.Invoke(ctx, "/discount.DiscountService/UpdateDiscount", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *discountServiceClient) DeleteDiscount(ctx context.Context, in *GetDiscountByIDRequest, opts ...grpc.CallOption) (*Discount, error) {
out := new(Discount)
err := c.cc.Invoke(ctx, "/discount.DiscountService/DeleteDiscount", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// DiscountServiceServer is the server API for DiscountService service.
// All implementations should embed UnimplementedDiscountServiceServer
// for forward compatibility
type DiscountServiceServer interface {
GetAllDiscounts(context.Context, *emptypb.Empty) (*Discounts, error)
GetUserDiscounts(context.Context, *GetDiscountByIDRequest) (*Discounts, error)
DetermineDiscounts(context.Context, *ApplyDiscountRequest) (*Discounts, error)
ApplyDiscounts(context.Context, *ApplyDiscountRequest) (*ApplyDiscountResponse, error)
GetDiscountByID(context.Context, *GetDiscountByIDRequest) (*Discount, error)
CreateDiscount(context.Context, *CreateDiscountRequest) (*Discount, error)
ReplaceDiscount(context.Context, *DiscountOptional) (*Discount, error)
UpdateDiscount(context.Context, *DiscountOptional) (*Discount, error)
DeleteDiscount(context.Context, *GetDiscountByIDRequest) (*Discount, error)
}
// UnimplementedDiscountServiceServer should be embedded to have forward compatible implementations.
type UnimplementedDiscountServiceServer struct {
}
func (UnimplementedDiscountServiceServer) GetAllDiscounts(context.Context, *emptypb.Empty) (*Discounts, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetAllDiscounts not implemented")
}
func (UnimplementedDiscountServiceServer) GetUserDiscounts(context.Context, *GetDiscountByIDRequest) (*Discounts, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetUserDiscounts not implemented")
}
func (UnimplementedDiscountServiceServer) DetermineDiscounts(context.Context, *ApplyDiscountRequest) (*Discounts, error) {
return nil, status.Errorf(codes.Unimplemented, "method DetermineDiscounts not implemented")
}
func (UnimplementedDiscountServiceServer) ApplyDiscounts(context.Context, *ApplyDiscountRequest) (*ApplyDiscountResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ApplyDiscounts not implemented")
}
func (UnimplementedDiscountServiceServer) GetDiscountByID(context.Context, *GetDiscountByIDRequest) (*Discount, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetDiscountByID not implemented")
}
func (UnimplementedDiscountServiceServer) CreateDiscount(context.Context, *CreateDiscountRequest) (*Discount, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateDiscount not implemented")
}
func (UnimplementedDiscountServiceServer) ReplaceDiscount(context.Context, *DiscountOptional) (*Discount, error) {
return nil, status.Errorf(codes.Unimplemented, "method ReplaceDiscount not implemented")
}
func (UnimplementedDiscountServiceServer) UpdateDiscount(context.Context, *DiscountOptional) (*Discount, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateDiscount not implemented")
}
func (UnimplementedDiscountServiceServer) DeleteDiscount(context.Context, *GetDiscountByIDRequest) (*Discount, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteDiscount not implemented")
}
// UnsafeDiscountServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to DiscountServiceServer will
// result in compilation errors.
type UnsafeDiscountServiceServer interface {
mustEmbedUnimplementedDiscountServiceServer()
}
func RegisterDiscountServiceServer(s grpc.ServiceRegistrar, srv DiscountServiceServer) {
s.RegisterService(&DiscountService_ServiceDesc, srv)
}
func _DiscountService_GetAllDiscounts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(emptypb.Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DiscountServiceServer).GetAllDiscounts(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/GetAllDiscounts",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).GetAllDiscounts(ctx, req.(*emptypb.Empty))
}
return interceptor(ctx, in, info, handler)
}
func _DiscountService_GetUserDiscounts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetDiscountByIDRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DiscountServiceServer).GetUserDiscounts(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/GetUserDiscounts",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).GetUserDiscounts(ctx, req.(*GetDiscountByIDRequest))
}
return interceptor(ctx, in, info, handler)
}
func _DiscountService_DetermineDiscounts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ApplyDiscountRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DiscountServiceServer).DetermineDiscounts(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/DetermineDiscounts",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).DetermineDiscounts(ctx, req.(*ApplyDiscountRequest))
}
return interceptor(ctx, in, info, handler)
}
func _DiscountService_ApplyDiscounts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ApplyDiscountRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DiscountServiceServer).ApplyDiscounts(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/ApplyDiscounts",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).ApplyDiscounts(ctx, req.(*ApplyDiscountRequest))
}
return interceptor(ctx, in, info, handler)
}
func _DiscountService_GetDiscountByID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetDiscountByIDRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DiscountServiceServer).GetDiscountByID(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/GetDiscountByID",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).GetDiscountByID(ctx, req.(*GetDiscountByIDRequest))
}
return interceptor(ctx, in, info, handler)
}
func _DiscountService_CreateDiscount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateDiscountRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DiscountServiceServer).CreateDiscount(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/CreateDiscount",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).CreateDiscount(ctx, req.(*CreateDiscountRequest))
}
return interceptor(ctx, in, info, handler)
}
func _DiscountService_ReplaceDiscount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DiscountOptional)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DiscountServiceServer).ReplaceDiscount(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/ReplaceDiscount",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).ReplaceDiscount(ctx, req.(*DiscountOptional))
}
return interceptor(ctx, in, info, handler)
}
func _DiscountService_UpdateDiscount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DiscountOptional)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DiscountServiceServer).UpdateDiscount(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/UpdateDiscount",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).UpdateDiscount(ctx, req.(*DiscountOptional))
}
return interceptor(ctx, in, info, handler)
}
func _DiscountService_DeleteDiscount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetDiscountByIDRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DiscountServiceServer).DeleteDiscount(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/discount.DiscountService/DeleteDiscount",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DiscountServiceServer).DeleteDiscount(ctx, req.(*GetDiscountByIDRequest))
}
return interceptor(ctx, in, info, handler)
}
// DiscountService_ServiceDesc is the grpc.ServiceDesc for DiscountService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var DiscountService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "discount.DiscountService",
HandlerType: (*DiscountServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetAllDiscounts",
Handler: _DiscountService_GetAllDiscounts_Handler,
},
{
MethodName: "GetUserDiscounts",
Handler: _DiscountService_GetUserDiscounts_Handler,
},
{
MethodName: "DetermineDiscounts",
Handler: _DiscountService_DetermineDiscounts_Handler,
},
{
MethodName: "ApplyDiscounts",
Handler: _DiscountService_ApplyDiscounts_Handler,
},
{
MethodName: "GetDiscountByID",
Handler: _DiscountService_GetDiscountByID_Handler,
},
{
MethodName: "CreateDiscount",
Handler: _DiscountService_CreateDiscount_Handler,
},
{
MethodName: "ReplaceDiscount",
Handler: _DiscountService_ReplaceDiscount_Handler,
},
{
MethodName: "UpdateDiscount",
Handler: _DiscountService_UpdateDiscount_Handler,
},
{
MethodName: "DeleteDiscount",
Handler: _DiscountService_DeleteDiscount_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "discount/service.proto",
}

@ -0,0 +1,118 @@
// Copyright (c) 2015, Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc (unknown)
// source: google/api/annotations.proto
package annotations
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
descriptorpb "google.golang.org/protobuf/types/descriptorpb"
reflect "reflect"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
var file_google_api_annotations_proto_extTypes = []protoimpl.ExtensionInfo{
{
ExtendedType: (*descriptorpb.MethodOptions)(nil),
ExtensionType: (*HttpRule)(nil),
Field: 72295728,
Name: "google.api.http",
Tag: "bytes,72295728,opt,name=http",
Filename: "google/api/annotations.proto",
},
}
// Extension fields to descriptorpb.MethodOptions.
var (
// See `HttpRule`.
//
// optional google.api.HttpRule http = 72295728;
E_Http = &file_google_api_annotations_proto_extTypes[0]
)
var File_google_api_annotations_proto protoreflect.FileDescriptor
var file_google_api_annotations_proto_rawDesc = []byte{
0x0a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e,
0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x1a, 0x15, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x3a, 0x4b, 0x0a, 0x04, 0x68, 0x74, 0x74, 0x70, 0x12, 0x1e, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65,
0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xb0, 0xca, 0xbc, 0x22,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70,
0x69, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x68, 0x74, 0x74, 0x70,
0x42, 0x6e, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61,
0x70, 0x69, 0x42, 0x10, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x50,
0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x41, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67,
0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x61, 0x70,
0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3b, 0x61, 0x6e,
0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xa2, 0x02, 0x04, 0x47, 0x41, 0x50, 0x49,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var file_google_api_annotations_proto_goTypes = []interface{}{
(*descriptorpb.MethodOptions)(nil), // 0: google.protobuf.MethodOptions
(*HttpRule)(nil), // 1: google.api.HttpRule
}
var file_google_api_annotations_proto_depIdxs = []int32{
0, // 0: google.api.http:extendee -> google.protobuf.MethodOptions
1, // 1: google.api.http:type_name -> google.api.HttpRule
2, // [2:2] is the sub-list for method output_type
2, // [2:2] is the sub-list for method input_type
1, // [1:2] is the sub-list for extension type_name
0, // [0:1] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_google_api_annotations_proto_init() }
func file_google_api_annotations_proto_init() {
if File_google_api_annotations_proto != nil {
return
}
file_google_api_http_proto_init()
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_google_api_annotations_proto_rawDesc,
NumEnums: 0,
NumMessages: 0,
NumExtensions: 1,
NumServices: 0,
},
GoTypes: file_google_api_annotations_proto_goTypes,
DependencyIndexes: file_google_api_annotations_proto_depIdxs,
ExtensionInfos: file_google_api_annotations_proto_extTypes,
}.Build()
File_google_api_annotations_proto = out.File
file_google_api_annotations_proto_rawDesc = nil
file_google_api_annotations_proto_goTypes = nil
file_google_api_annotations_proto_depIdxs = nil
}

@ -0,0 +1,777 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc (unknown)
// source: google/api/http.proto
package annotations
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// Defines the HTTP configuration for an API service. It contains a list of
// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method
// to one or more HTTP REST API methods.
type Http struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// A list of HTTP configuration rules that apply to individual API methods.
//
// **NOTE:** All service configuration rules follow "last one wins" order.
Rules []*HttpRule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"`
// When set to true, URL path parameters will be fully URI-decoded except in
// cases of single segment matches in reserved expansion, where "%2F" will be
// left encoded.
//
// The default behavior is to not decode RFC 6570 reserved characters in multi
// segment matches.
FullyDecodeReservedExpansion bool `protobuf:"varint,2,opt,name=fully_decode_reserved_expansion,json=fullyDecodeReservedExpansion,proto3" json:"fully_decode_reserved_expansion,omitempty"`
}
func (x *Http) Reset() {
*x = Http{}
if protoimpl.UnsafeEnabled {
mi := &file_google_api_http_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Http) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Http) ProtoMessage() {}
func (x *Http) ProtoReflect() protoreflect.Message {
mi := &file_google_api_http_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Http.ProtoReflect.Descriptor instead.
func (*Http) Descriptor() ([]byte, []int) {
return file_google_api_http_proto_rawDescGZIP(), []int{0}
}
func (x *Http) GetRules() []*HttpRule {
if x != nil {
return x.Rules
}
return nil
}
func (x *Http) GetFullyDecodeReservedExpansion() bool {
if x != nil {
return x.FullyDecodeReservedExpansion
}
return false
}
// # gRPC Transcoding
//
// gRPC Transcoding is a feature for mapping between a gRPC method and one or
// more HTTP REST endpoints. It allows developers to build a single API service
// that supports both gRPC APIs and REST APIs. Many systems, including [Google
// APIs](https://github.com/googleapis/googleapis),
// [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC
// Gateway](https://github.com/grpc-ecosystem/grpc-gateway),
// and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature
// and use it for large scale production services.
//
// `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies
// how different portions of the gRPC request message are mapped to the URL
// path, URL query parameters, and HTTP request body. It also controls how the
// gRPC response message is mapped to the HTTP response body. `HttpRule` is
// typically specified as an `google.api.http` annotation on the gRPC method.
//
// Each mapping specifies a URL path template and an HTTP method. The path
// template may refer to one or more fields in the gRPC request message, as long
// as each field is a non-repeated field with a primitive (non-message) type.
// The path template controls how fields of the request message are mapped to
// the URL path.
//
// Example:
//
// service Messaging {
// rpc GetMessage(GetMessageRequest) returns (Message) {
// option (google.api.http) = {
// get: "/v1/{name=messages/*}"
// };
// }
// }
// message GetMessageRequest {
// string name = 1; // Mapped to URL path.
// }
// message Message {
// string text = 1; // The resource content.
// }
//
// This enables an HTTP REST to gRPC mapping as below:
//
// HTTP | gRPC
// -----|-----
// `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")`
//
// Any fields in the request message which are not bound by the path template
// automatically become HTTP query parameters if there is no HTTP request body.
// For example:
//
// service Messaging {
// rpc GetMessage(GetMessageRequest) returns (Message) {
// option (google.api.http) = {
// get:"/v1/messages/{message_id}"
// };
// }
// }
// message GetMessageRequest {
// message SubMessage {
// string subfield = 1;
// }
// string message_id = 1; // Mapped to URL path.
// int64 revision = 2; // Mapped to URL query parameter `revision`.
// SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`.
// }
//
// This enables a HTTP JSON to RPC mapping as below:
//
// HTTP | gRPC
// -----|-----
// `GET /v1/messages/123456?revision=2&sub.subfield=foo` |
// `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield:
// "foo"))`
//
// Note that fields which are mapped to URL query parameters must have a
// primitive type or a repeated primitive type or a non-repeated message type.
// In the case of a repeated type, the parameter can be repeated in the URL
// as `...?param=A&param=B`. In the case of a message type, each field of the
// message is mapped to a separate parameter, such as
// `...?foo.a=A&foo.b=B&foo.c=C`.
//
// For HTTP methods that allow a request body, the `body` field
// specifies the mapping. Consider a REST update method on the
// message resource collection:
//
// service Messaging {
// rpc UpdateMessage(UpdateMessageRequest) returns (Message) {
// option (google.api.http) = {
// patch: "/v1/messages/{message_id}"
// body: "message"
// };
// }
// }
// message UpdateMessageRequest {
// string message_id = 1; // mapped to the URL
// Message message = 2; // mapped to the body
// }
//
// The following HTTP JSON to RPC mapping is enabled, where the
// representation of the JSON in the request body is determined by
// protos JSON encoding:
//
// HTTP | gRPC
// -----|-----
// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id:
// "123456" message { text: "Hi!" })`
//
// The special name `*` can be used in the body mapping to define that
// every field not bound by the path template should be mapped to the
// request body. This enables the following alternative definition of
// the update method:
//
// service Messaging {
// rpc UpdateMessage(Message) returns (Message) {
// option (google.api.http) = {
// patch: "/v1/messages/{message_id}"
// body: "*"
// };
// }
// }
// message Message {
// string message_id = 1;
// string text = 2;
// }
//
// The following HTTP JSON to RPC mapping is enabled:
//
// HTTP | gRPC
// -----|-----
// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id:
// "123456" text: "Hi!")`
//
// Note that when using `*` in the body mapping, it is not possible to
// have HTTP parameters, as all fields not bound by the path end in
// the body. This makes this option more rarely used in practice when
// defining REST APIs. The common usage of `*` is in custom methods
// which don't use the URL at all for transferring data.
//
// It is possible to define multiple HTTP methods for one RPC by using
// the `additional_bindings` option. Example:
//
// service Messaging {
// rpc GetMessage(GetMessageRequest) returns (Message) {
// option (google.api.http) = {
// get: "/v1/messages/{message_id}"
// additional_bindings {
// get: "/v1/users/{user_id}/messages/{message_id}"
// }
// };
// }
// }
// message GetMessageRequest {
// string message_id = 1;
// string user_id = 2;
// }
//
// This enables the following two alternative HTTP JSON to RPC mappings:
//
// HTTP | gRPC
// -----|-----
// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")`
// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id:
// "123456")`
//
// ## Rules for HTTP mapping
//
// 1. Leaf request fields (recursive expansion nested messages in the request
// message) are classified into three categories:
// - Fields referred by the path template. They are passed via the URL path.
// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They are passed via the HTTP
// request body.
// - All other fields are passed via the URL query parameters, and the
// parameter name is the field path in the request message. A repeated
// field can be represented as multiple query parameters under the same
// name.
// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL query parameter, all fields
// are passed via URL path and HTTP request body.
// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP request body, all
// fields are passed via URL path and URL query parameters.
//
// ### Path template syntax
//
// Template = "/" Segments [ Verb ] ;
// Segments = Segment { "/" Segment } ;
// Segment = "*" | "**" | LITERAL | Variable ;
// Variable = "{" FieldPath [ "=" Segments ] "}" ;
// FieldPath = IDENT { "." IDENT } ;
// Verb = ":" LITERAL ;
//
// The syntax `*` matches a single URL path segment. The syntax `**` matches
// zero or more URL path segments, which must be the last part of the URL path
// except the `Verb`.
//
// The syntax `Variable` matches part of the URL path as specified by its
// template. A variable template must not contain other variables. If a variable
// matches a single path segment, its template may be omitted, e.g. `{var}`
// is equivalent to `{var=*}`.
//
// The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL`
// contains any reserved character, such characters should be percent-encoded
// before the matching.
//
// If a variable contains exactly one path segment, such as `"{var}"` or
// `"{var=*}"`, when such a variable is expanded into a URL path on the client
// side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The
// server side does the reverse decoding. Such variables show up in the
// [Discovery
// Document](https://developers.google.com/discovery/v1/reference/apis) as
// `{var}`.
//
// If a variable contains multiple path segments, such as `"{var=foo/*}"`
// or `"{var=**}"`, when such a variable is expanded into a URL path on the
// client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded.
// The server side does the reverse decoding, except "%2F" and "%2f" are left
// unchanged. Such variables show up in the
// [Discovery
// Document](https://developers.google.com/discovery/v1/reference/apis) as
// `{+var}`.
//
// ## Using gRPC API Service Configuration
//
// gRPC API Service Configuration (service config) is a configuration language
// for configuring a gRPC service to become a user-facing product. The
// service config is simply the YAML representation of the `google.api.Service`
// proto message.
//
// As an alternative to annotating your proto file, you can configure gRPC
// transcoding in your service config YAML files. You do this by specifying a
// `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same
// effect as the proto annotation. This can be particularly useful if you
// have a proto that is reused in multiple services. Note that any transcoding
// specified in the service config will override any matching transcoding
// configuration in the proto.
//
// Example:
//
// http:
// rules:
// # Selects a gRPC method and applies HttpRule to it.
// - selector: example.v1.Messaging.GetMessage
// get: /v1/messages/{message_id}/{sub.subfield}
//
// ## Special notes
//
// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the
// proto to JSON conversion must follow the [proto3
// specification](https://developers.google.com/protocol-buffers/docs/proto3#json).
//
// While the single segment variable follows the semantics of
// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String
// Expansion, the multi segment variable **does not** follow RFC 6570 Section
// 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion
// does not expand special characters like `?` and `#`, which would lead
// to invalid URLs. As the result, gRPC Transcoding uses a custom encoding
// for multi segment variables.
//
// The path variables **must not** refer to any repeated or mapped field,
// because client libraries are not capable of handling such variable expansion.
//
// The path variables **must not** capture the leading "/" character. The reason
// is that the most common use case "{var}" does not capture the leading "/"
// character. For consistency, all path variables must share the same behavior.
//
// Repeated message fields must not be mapped to URL query parameters, because
// no client library can support such complicated mapping.
//
// If an API needs to use a JSON array for request or response body, it can map
// the request or response body to a repeated field. However, some gRPC
// Transcoding implementations may not support this feature.
type HttpRule struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Selects a method to which this rule applies.
//
// Refer to [selector][google.api.DocumentationRule.selector] for syntax details.
Selector string `protobuf:"bytes,1,opt,name=selector,proto3" json:"selector,omitempty"`
// Determines the URL pattern is matched by this rules. This pattern can be
// used with any of the {get|put|post|delete|patch} methods. A custom method
// can be defined using the 'custom' field.
//
// Types that are assignable to Pattern:
//
// *HttpRule_Get
// *HttpRule_Put
// *HttpRule_Post
// *HttpRule_Delete
// *HttpRule_Patch
// *HttpRule_Custom
Pattern isHttpRule_Pattern `protobuf_oneof:"pattern"`
// The name of the request field whose value is mapped to the HTTP request
// body, or `*` for mapping all request fields not captured by the path
// pattern to the HTTP body, or omitted for not having any HTTP request body.
//
// NOTE: the referred field must be present at the top-level of the request
// message type.
Body string `protobuf:"bytes,7,opt,name=body,proto3" json:"body,omitempty"`
// Optional. The name of the response field whose value is mapped to the HTTP
// response body. When omitted, the entire response message will be used
// as the HTTP response body.
//
// NOTE: The referred field must be present at the top-level of the response
// message type.
ResponseBody string `protobuf:"bytes,12,opt,name=response_body,json=responseBody,proto3" json:"response_body,omitempty"`
// Additional HTTP bindings for the selector. Nested bindings must
// not contain an `additional_bindings` field themselves (that is,
// the nesting may only be one level deep).
AdditionalBindings []*HttpRule `protobuf:"bytes,11,rep,name=additional_bindings,json=additionalBindings,proto3" json:"additional_bindings,omitempty"`
}
func (x *HttpRule) Reset() {
*x = HttpRule{}
if protoimpl.UnsafeEnabled {
mi := &file_google_api_http_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *HttpRule) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*HttpRule) ProtoMessage() {}
func (x *HttpRule) ProtoReflect() protoreflect.Message {
mi := &file_google_api_http_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use HttpRule.ProtoReflect.Descriptor instead.
func (*HttpRule) Descriptor() ([]byte, []int) {
return file_google_api_http_proto_rawDescGZIP(), []int{1}
}
func (x *HttpRule) GetSelector() string {
if x != nil {
return x.Selector
}
return ""
}
func (m *HttpRule) GetPattern() isHttpRule_Pattern {
if m != nil {
return m.Pattern
}
return nil
}
func (x *HttpRule) GetGet() string {
if x, ok := x.GetPattern().(*HttpRule_Get); ok {
return x.Get
}
return ""
}
func (x *HttpRule) GetPut() string {
if x, ok := x.GetPattern().(*HttpRule_Put); ok {
return x.Put
}
return ""
}
func (x *HttpRule) GetPost() string {
if x, ok := x.GetPattern().(*HttpRule_Post); ok {
return x.Post
}
return ""
}
func (x *HttpRule) GetDelete() string {
if x, ok := x.GetPattern().(*HttpRule_Delete); ok {
return x.Delete
}
return ""
}
func (x *HttpRule) GetPatch() string {
if x, ok := x.GetPattern().(*HttpRule_Patch); ok {
return x.Patch
}
return ""
}
func (x *HttpRule) GetCustom() *CustomHttpPattern {
if x, ok := x.GetPattern().(*HttpRule_Custom); ok {
return x.Custom
}
return nil
}
func (x *HttpRule) GetBody() string {
if x != nil {
return x.Body
}
return ""
}
func (x *HttpRule) GetResponseBody() string {
if x != nil {
return x.ResponseBody
}
return ""
}
func (x *HttpRule) GetAdditionalBindings() []*HttpRule {
if x != nil {
return x.AdditionalBindings
}
return nil
}
type isHttpRule_Pattern interface {
isHttpRule_Pattern()
}
type HttpRule_Get struct {
// Maps to HTTP GET. Used for listing and getting information about
// resources.
Get string `protobuf:"bytes,2,opt,name=get,proto3,oneof"`
}
type HttpRule_Put struct {
// Maps to HTTP PUT. Used for replacing a resource.
Put string `protobuf:"bytes,3,opt,name=put,proto3,oneof"`
}
type HttpRule_Post struct {
// Maps to HTTP POST. Used for creating a resource or performing an action.
Post string `protobuf:"bytes,4,opt,name=post,proto3,oneof"`
}
type HttpRule_Delete struct {
// Maps to HTTP DELETE. Used for deleting a resource.
Delete string `protobuf:"bytes,5,opt,name=delete,proto3,oneof"`
}
type HttpRule_Patch struct {
// Maps to HTTP PATCH. Used for updating a resource.
Patch string `protobuf:"bytes,6,opt,name=patch,proto3,oneof"`
}
type HttpRule_Custom struct {
// The custom pattern is used for specifying an HTTP method that is not
// included in the `pattern` field, such as HEAD, or "*" to leave the
// HTTP method unspecified for this rule. The wild-card rule is useful
// for services that provide content to Web (HTML) clients.
Custom *CustomHttpPattern `protobuf:"bytes,8,opt,name=custom,proto3,oneof"`
}
func (*HttpRule_Get) isHttpRule_Pattern() {}
func (*HttpRule_Put) isHttpRule_Pattern() {}
func (*HttpRule_Post) isHttpRule_Pattern() {}
func (*HttpRule_Delete) isHttpRule_Pattern() {}
func (*HttpRule_Patch) isHttpRule_Pattern() {}
func (*HttpRule_Custom) isHttpRule_Pattern() {}
// A custom pattern is used for defining custom HTTP verb.
type CustomHttpPattern struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// The name of this custom HTTP verb.
Kind string `protobuf:"bytes,1,opt,name=kind,proto3" json:"kind,omitempty"`
// The path matched by this custom verb.
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
}
func (x *CustomHttpPattern) Reset() {
*x = CustomHttpPattern{}
if protoimpl.UnsafeEnabled {
mi := &file_google_api_http_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CustomHttpPattern) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CustomHttpPattern) ProtoMessage() {}
func (x *CustomHttpPattern) ProtoReflect() protoreflect.Message {
mi := &file_google_api_http_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CustomHttpPattern.ProtoReflect.Descriptor instead.
func (*CustomHttpPattern) Descriptor() ([]byte, []int) {
return file_google_api_http_proto_rawDescGZIP(), []int{2}
}
func (x *CustomHttpPattern) GetKind() string {
if x != nil {
return x.Kind
}
return ""
}
func (x *CustomHttpPattern) GetPath() string {
if x != nil {
return x.Path
}
return ""
}
var File_google_api_http_proto protoreflect.FileDescriptor
var file_google_api_http_proto_rawDesc = []byte{
0x0a, 0x15, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x68, 0x74, 0x74,
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x61, 0x70, 0x69, 0x22, 0x79, 0x0a, 0x04, 0x48, 0x74, 0x74, 0x70, 0x12, 0x2a, 0x0a, 0x05, 0x72,
0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x52, 0x75, 0x6c, 0x65,
0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x1f, 0x66, 0x75, 0x6c, 0x6c, 0x79,
0x5f, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64,
0x5f, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08,
0x52, 0x1c, 0x66, 0x75, 0x6c, 0x6c, 0x79, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73,
0x65, 0x72, 0x76, 0x65, 0x64, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xda,
0x02, 0x0a, 0x08, 0x48, 0x74, 0x74, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73,
0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73,
0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x03, 0x67, 0x65, 0x74, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x67, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x03, 0x70,
0x75, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x70, 0x75, 0x74, 0x12,
0x14, 0x0a, 0x04, 0x70, 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52,
0x04, 0x70, 0x6f, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x06, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18,
0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12,
0x16, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00,
0x52, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x12, 0x37, 0x0a, 0x06, 0x63, 0x75, 0x73, 0x74, 0x6f,
0x6d, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x74, 0x74, 0x70, 0x50,
0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d,
0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x62, 0x6f, 0x64, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x13, 0x61, 0x64, 0x64,
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73,
0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x61, 0x70, 0x69, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x12, 0x61, 0x64,
0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73,
0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x22, 0x3b, 0x0a, 0x11, 0x43,
0x75, 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x74, 0x74, 0x70, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e,
0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x6b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x42, 0x6a, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x42, 0x09, 0x48, 0x74, 0x74, 0x70,
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x41, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x61,
0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3b, 0x61,
0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xf8, 0x01, 0x01, 0xa2, 0x02, 0x04,
0x47, 0x41, 0x50, 0x49, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_google_api_http_proto_rawDescOnce sync.Once
file_google_api_http_proto_rawDescData = file_google_api_http_proto_rawDesc
)
func file_google_api_http_proto_rawDescGZIP() []byte {
file_google_api_http_proto_rawDescOnce.Do(func() {
file_google_api_http_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_api_http_proto_rawDescData)
})
return file_google_api_http_proto_rawDescData
}
var file_google_api_http_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_google_api_http_proto_goTypes = []interface{}{
(*Http)(nil), // 0: google.api.Http
(*HttpRule)(nil), // 1: google.api.HttpRule
(*CustomHttpPattern)(nil), // 2: google.api.CustomHttpPattern
}
var file_google_api_http_proto_depIdxs = []int32{
1, // 0: google.api.Http.rules:type_name -> google.api.HttpRule
2, // 1: google.api.HttpRule.custom:type_name -> google.api.CustomHttpPattern
1, // 2: google.api.HttpRule.additional_bindings:type_name -> google.api.HttpRule
3, // [3:3] is the sub-list for method output_type
3, // [3:3] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name
}
func init() { file_google_api_http_proto_init() }
func file_google_api_http_proto_init() {
if File_google_api_http_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_google_api_http_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Http); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_google_api_http_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*HttpRule); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_google_api_http_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CustomHttpPattern); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_google_api_http_proto_msgTypes[1].OneofWrappers = []interface{}{
(*HttpRule_Get)(nil),
(*HttpRule_Put)(nil),
(*HttpRule_Post)(nil),
(*HttpRule_Delete)(nil),
(*HttpRule_Patch)(nil),
(*HttpRule_Custom)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_google_api_http_proto_rawDesc,
NumEnums: 0,
NumMessages: 3,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_google_api_http_proto_goTypes,
DependencyIndexes: file_google_api_http_proto_depIdxs,
MessageInfos: file_google_api_http_proto_msgTypes,
}.Build()
File_google_api_http_proto = out.File
file_google_api_http_proto_rawDesc = nil
file_google_api_http_proto_goTypes = nil
file_google_api_http_proto_depIdxs = nil
}

@ -0,0 +1,325 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc (unknown)
// source: callback/service.proto
package payment_callback
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb"
_ "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Event struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Key string `protobuf:"bytes,1,opt,name=Key,proto3" json:"Key,omitempty"`
Message string `protobuf:"bytes,2,opt,name=Message,proto3" json:"Message,omitempty"`
Payment *Payment `protobuf:"bytes,3,opt,name=Payment,proto3" json:"Payment,omitempty"`
}
func (x *Event) Reset() {
*x = Event{}
if protoimpl.UnsafeEnabled {
mi := &file_callback_service_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Event) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Event) ProtoMessage() {}
func (x *Event) ProtoReflect() protoreflect.Message {
mi := &file_callback_service_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Event.ProtoReflect.Descriptor instead.
func (*Event) Descriptor() ([]byte, []int) {
return file_callback_service_proto_rawDescGZIP(), []int{0}
}
func (x *Event) GetKey() string {
if x != nil {
return x.Key
}
return ""
}
func (x *Event) GetMessage() string {
if x != nil {
return x.Message
}
return ""
}
func (x *Event) GetPayment() *Payment {
if x != nil {
return x.Payment
}
return nil
}
type Payment struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
UserID string `protobuf:"bytes,2,opt,name=UserID,proto3" json:"UserID,omitempty"`
PaymentID string `protobuf:"bytes,3,opt,name=PaymentID,proto3" json:"PaymentID,omitempty"`
IdempotencePaymentID string `protobuf:"bytes,4,opt,name=IdempotencePaymentID,proto3" json:"IdempotencePaymentID,omitempty"`
Amount int64 `protobuf:"varint,5,opt,name=Amount,proto3" json:"Amount,omitempty"`
Currency string `protobuf:"bytes,6,opt,name=Currency,proto3" json:"Currency,omitempty"`
Type string `protobuf:"bytes,7,opt,name=Type,proto3" json:"Type,omitempty"`
Status string `protobuf:"bytes,8,opt,name=Status,proto3" json:"Status,omitempty"`
Completed bool `protobuf:"varint,9,opt,name=Completed,proto3" json:"Completed,omitempty"`
}
func (x *Payment) Reset() {
*x = Payment{}
if protoimpl.UnsafeEnabled {
mi := &file_callback_service_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Payment) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Payment) ProtoMessage() {}
func (x *Payment) ProtoReflect() protoreflect.Message {
mi := &file_callback_service_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Payment.ProtoReflect.Descriptor instead.
func (*Payment) Descriptor() ([]byte, []int) {
return file_callback_service_proto_rawDescGZIP(), []int{1}
}
func (x *Payment) GetID() string {
if x != nil {
return x.ID
}
return ""
}
func (x *Payment) GetUserID() string {
if x != nil {
return x.UserID
}
return ""
}
func (x *Payment) GetPaymentID() string {
if x != nil {
return x.PaymentID
}
return ""
}
func (x *Payment) GetIdempotencePaymentID() string {
if x != nil {
return x.IdempotencePaymentID
}
return ""
}
func (x *Payment) GetAmount() int64 {
if x != nil {
return x.Amount
}
return 0
}
func (x *Payment) GetCurrency() string {
if x != nil {
return x.Currency
}
return ""
}
func (x *Payment) GetType() string {
if x != nil {
return x.Type
}
return ""
}
func (x *Payment) GetStatus() string {
if x != nil {
return x.Status
}
return ""
}
func (x *Payment) GetCompleted() bool {
if x != nil {
return x.Completed
}
return false
}
var File_callback_service_proto protoreflect.FileDescriptor
var file_callback_service_proto_rawDesc = []byte{
0x0a, 0x16, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e,
0x74, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74,
0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x68, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e,
0x74, 0x12, 0x10, 0x0a, 0x03, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x33, 0x0a,
0x07, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19,
0x2e, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63,
0x6b, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x50, 0x61, 0x79, 0x6d, 0x65,
0x6e, 0x74, 0x22, 0x81, 0x02, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x0e,
0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x16,
0x0a, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e,
0x74, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x79, 0x6d, 0x65,
0x6e, 0x74, 0x49, 0x44, 0x12, 0x32, 0x0a, 0x14, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65,
0x6e, 0x63, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x44, 0x18, 0x04, 0x20, 0x01,
0x28, 0x09, 0x52, 0x14, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x50,
0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x44, 0x12, 0x16, 0x0a, 0x06, 0x41, 0x6d, 0x6f, 0x75,
0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
0x12, 0x1a, 0x0a, 0x08, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01,
0x28, 0x09, 0x52, 0x08, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x12, 0x0a, 0x04,
0x54, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65,
0x12, 0x16, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09,
0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x43, 0x6f, 0x6d, 0x70,
0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x43, 0x6f, 0x6d,
0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x32, 0x98, 0x01, 0x0a, 0x16, 0x50, 0x61, 0x79, 0x6d, 0x65,
0x6e, 0x74, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x12, 0x3e, 0x0a, 0x09, 0x4f, 0x6e, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x17,
0x2e, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63,
0x6b, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22,
0x00, 0x12, 0x3e, 0x0a, 0x09, 0x4f, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x17,
0x2e, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63,
0x6b, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22,
0x00, 0x42, 0x14, 0x5a, 0x12, 0x2e, 0x2f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x63,
0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_callback_service_proto_rawDescOnce sync.Once
file_callback_service_proto_rawDescData = file_callback_service_proto_rawDesc
)
func file_callback_service_proto_rawDescGZIP() []byte {
file_callback_service_proto_rawDescOnce.Do(func() {
file_callback_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_callback_service_proto_rawDescData)
})
return file_callback_service_proto_rawDescData
}
var file_callback_service_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_callback_service_proto_goTypes = []interface{}{
(*Event)(nil), // 0: payment_callback.Event
(*Payment)(nil), // 1: payment_callback.Payment
(*emptypb.Empty)(nil), // 2: google.protobuf.Empty
}
var file_callback_service_proto_depIdxs = []int32{
1, // 0: payment_callback.Event.Payment:type_name -> payment_callback.Payment
0, // 1: payment_callback.PaymentCallbackService.OnSuccess:input_type -> payment_callback.Event
0, // 2: payment_callback.PaymentCallbackService.OnFailure:input_type -> payment_callback.Event
2, // 3: payment_callback.PaymentCallbackService.OnSuccess:output_type -> google.protobuf.Empty
2, // 4: payment_callback.PaymentCallbackService.OnFailure:output_type -> google.protobuf.Empty
3, // [3:5] is the sub-list for method output_type
1, // [1:3] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_callback_service_proto_init() }
func file_callback_service_proto_init() {
if File_callback_service_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_callback_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Event); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_callback_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Payment); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_callback_service_proto_rawDesc,
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_callback_service_proto_goTypes,
DependencyIndexes: file_callback_service_proto_depIdxs,
MessageInfos: file_callback_service_proto_msgTypes,
}.Build()
File_callback_service_proto = out.File
file_callback_service_proto_rawDesc = nil
file_callback_service_proto_goTypes = nil
file_callback_service_proto_depIdxs = nil
}

@ -0,0 +1,136 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
package payment_callback
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
emptypb "google.golang.org/protobuf/types/known/emptypb"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// PaymentCallbackServiceClient is the client API for PaymentCallbackService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type PaymentCallbackServiceClient interface {
OnSuccess(ctx context.Context, in *Event, opts ...grpc.CallOption) (*emptypb.Empty, error)
OnFailure(ctx context.Context, in *Event, opts ...grpc.CallOption) (*emptypb.Empty, error)
}
type paymentCallbackServiceClient struct {
cc grpc.ClientConnInterface
}
func NewPaymentCallbackServiceClient(cc grpc.ClientConnInterface) PaymentCallbackServiceClient {
return &paymentCallbackServiceClient{cc}
}
func (c *paymentCallbackServiceClient) OnSuccess(ctx context.Context, in *Event, opts ...grpc.CallOption) (*emptypb.Empty, error) {
out := new(emptypb.Empty)
err := c.cc.Invoke(ctx, "/payment_callback.PaymentCallbackService/OnSuccess", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *paymentCallbackServiceClient) OnFailure(ctx context.Context, in *Event, opts ...grpc.CallOption) (*emptypb.Empty, error) {
out := new(emptypb.Empty)
err := c.cc.Invoke(ctx, "/payment_callback.PaymentCallbackService/OnFailure", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// PaymentCallbackServiceServer is the server API for PaymentCallbackService service.
// All implementations should embed UnimplementedPaymentCallbackServiceServer
// for forward compatibility
type PaymentCallbackServiceServer interface {
OnSuccess(context.Context, *Event) (*emptypb.Empty, error)
OnFailure(context.Context, *Event) (*emptypb.Empty, error)
}
// UnimplementedPaymentCallbackServiceServer should be embedded to have forward compatible implementations.
type UnimplementedPaymentCallbackServiceServer struct {
}
func (UnimplementedPaymentCallbackServiceServer) OnSuccess(context.Context, *Event) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method OnSuccess not implemented")
}
func (UnimplementedPaymentCallbackServiceServer) OnFailure(context.Context, *Event) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method OnFailure not implemented")
}
// UnsafePaymentCallbackServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to PaymentCallbackServiceServer will
// result in compilation errors.
type UnsafePaymentCallbackServiceServer interface {
mustEmbedUnimplementedPaymentCallbackServiceServer()
}
func RegisterPaymentCallbackServiceServer(s grpc.ServiceRegistrar, srv PaymentCallbackServiceServer) {
s.RegisterService(&PaymentCallbackService_ServiceDesc, srv)
}
func _PaymentCallbackService_OnSuccess_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Event)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PaymentCallbackServiceServer).OnSuccess(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/payment_callback.PaymentCallbackService/OnSuccess",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PaymentCallbackServiceServer).OnSuccess(ctx, req.(*Event))
}
return interceptor(ctx, in, info, handler)
}
func _PaymentCallbackService_OnFailure_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Event)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PaymentCallbackServiceServer).OnFailure(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/payment_callback.PaymentCallbackService/OnFailure",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PaymentCallbackServiceServer).OnFailure(ctx, req.(*Event))
}
return interceptor(ctx, in, info, handler)
}
// PaymentCallbackService_ServiceDesc is the grpc.ServiceDesc for PaymentCallbackService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var PaymentCallbackService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "payment_callback.PaymentCallbackService",
HandlerType: (*PaymentCallbackServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "OnSuccess",
Handler: _PaymentCallbackService_OnSuccess_Handler,
},
{
MethodName: "OnFailure",
Handler: _PaymentCallbackService_OnFailure_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "callback/service.proto",
}

@ -0,0 +1,299 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc (unknown)
// source: treasurer/payment.model.proto
package treasurer
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type MainPaymentSettings struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Currency string `protobuf:"bytes,1,opt,name=Currency,proto3" json:"Currency,omitempty"`
Amount int64 `protobuf:"varint,2,opt,name=Amount,proto3" json:"Amount,omitempty"`
CallbackHostGRPC []string `protobuf:"bytes,3,rep,name=CallbackHostGRPC,proto3" json:"CallbackHostGRPC,omitempty"`
ReturnURL string `protobuf:"bytes,4,opt,name=ReturnURL,proto3" json:"ReturnURL,omitempty"`
UserID string `protobuf:"bytes,5,opt,name=UserID,proto3" json:"UserID,omitempty"`
ClientIP string `protobuf:"bytes,6,opt,name=ClientIP,proto3" json:"ClientIP,omitempty"`
}
func (x *MainPaymentSettings) Reset() {
*x = MainPaymentSettings{}
if protoimpl.UnsafeEnabled {
mi := &file_treasurer_payment_model_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *MainPaymentSettings) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MainPaymentSettings) ProtoMessage() {}
func (x *MainPaymentSettings) ProtoReflect() protoreflect.Message {
mi := &file_treasurer_payment_model_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use MainPaymentSettings.ProtoReflect.Descriptor instead.
func (*MainPaymentSettings) Descriptor() ([]byte, []int) {
return file_treasurer_payment_model_proto_rawDescGZIP(), []int{0}
}
func (x *MainPaymentSettings) GetCurrency() string {
if x != nil {
return x.Currency
}
return ""
}
func (x *MainPaymentSettings) GetAmount() int64 {
if x != nil {
return x.Amount
}
return 0
}
func (x *MainPaymentSettings) GetCallbackHostGRPC() []string {
if x != nil {
return x.CallbackHostGRPC
}
return nil
}
func (x *MainPaymentSettings) GetReturnURL() string {
if x != nil {
return x.ReturnURL
}
return ""
}
func (x *MainPaymentSettings) GetUserID() string {
if x != nil {
return x.UserID
}
return ""
}
func (x *MainPaymentSettings) GetClientIP() string {
if x != nil {
return x.ClientIP
}
return ""
}
type BankCardInformation struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Number string `protobuf:"bytes,1,opt,name=Number,proto3" json:"Number,omitempty"`
ExpiryYear string `protobuf:"bytes,2,opt,name=ExpiryYear,proto3" json:"ExpiryYear,omitempty"`
ExpiryMonth string `protobuf:"bytes,3,opt,name=ExpiryMonth,proto3" json:"ExpiryMonth,omitempty"`
CSC *string `protobuf:"bytes,4,opt,name=CSC,proto3,oneof" json:"CSC,omitempty"`
CardHolderName *string `protobuf:"bytes,5,opt,name=CardHolderName,proto3,oneof" json:"CardHolderName,omitempty"`
}
func (x *BankCardInformation) Reset() {
*x = BankCardInformation{}
if protoimpl.UnsafeEnabled {
mi := &file_treasurer_payment_model_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *BankCardInformation) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*BankCardInformation) ProtoMessage() {}
func (x *BankCardInformation) ProtoReflect() protoreflect.Message {
mi := &file_treasurer_payment_model_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use BankCardInformation.ProtoReflect.Descriptor instead.
func (*BankCardInformation) Descriptor() ([]byte, []int) {
return file_treasurer_payment_model_proto_rawDescGZIP(), []int{1}
}
func (x *BankCardInformation) GetNumber() string {
if x != nil {
return x.Number
}
return ""
}
func (x *BankCardInformation) GetExpiryYear() string {
if x != nil {
return x.ExpiryYear
}
return ""
}
func (x *BankCardInformation) GetExpiryMonth() string {
if x != nil {
return x.ExpiryMonth
}
return ""
}
func (x *BankCardInformation) GetCSC() string {
if x != nil && x.CSC != nil {
return *x.CSC
}
return ""
}
func (x *BankCardInformation) GetCardHolderName() string {
if x != nil && x.CardHolderName != nil {
return *x.CardHolderName
}
return ""
}
var File_treasurer_payment_model_proto protoreflect.FileDescriptor
var file_treasurer_payment_model_proto_rawDesc = []byte{
0x0a, 0x1d, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2f, 0x70, 0x61, 0x79, 0x6d,
0x65, 0x6e, 0x74, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x09, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x22, 0xc7, 0x01, 0x0a, 0x13, 0x4d,
0x61, 0x69, 0x6e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
0x67, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x16,
0x0a, 0x06, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06,
0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x10, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61,
0x63, 0x6b, 0x48, 0x6f, 0x73, 0x74, 0x47, 0x52, 0x50, 0x43, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09,
0x52, 0x10, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x48, 0x6f, 0x73, 0x74, 0x47, 0x52,
0x50, 0x43, 0x12, 0x1c, 0x0a, 0x09, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x55, 0x52, 0x4c, 0x18,
0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x55, 0x52, 0x4c,
0x12, 0x16, 0x0a, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
0x52, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x1a, 0x0a, 0x08, 0x43, 0x6c, 0x69, 0x65,
0x6e, 0x74, 0x49, 0x50, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x43, 0x6c, 0x69, 0x65,
0x6e, 0x74, 0x49, 0x50, 0x22, 0xce, 0x01, 0x0a, 0x13, 0x42, 0x61, 0x6e, 0x6b, 0x43, 0x61, 0x72,
0x64, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06,
0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x4e, 0x75,
0x6d, 0x62, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x59, 0x65,
0x61, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79,
0x59, 0x65, 0x61, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x4d, 0x6f,
0x6e, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x45, 0x78, 0x70, 0x69, 0x72,
0x79, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x12, 0x15, 0x0a, 0x03, 0x43, 0x53, 0x43, 0x18, 0x04, 0x20,
0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x43, 0x53, 0x43, 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a,
0x0e, 0x43, 0x61, 0x72, 0x64, 0x48, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18,
0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0e, 0x43, 0x61, 0x72, 0x64, 0x48, 0x6f, 0x6c,
0x64, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x43,
0x53, 0x43, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x43, 0x61, 0x72, 0x64, 0x48, 0x6f, 0x6c, 0x64, 0x65,
0x72, 0x4e, 0x61, 0x6d, 0x65, 0x42, 0x0d, 0x5a, 0x0b, 0x2e, 0x2f, 0x74, 0x72, 0x65, 0x61, 0x73,
0x75, 0x72, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_treasurer_payment_model_proto_rawDescOnce sync.Once
file_treasurer_payment_model_proto_rawDescData = file_treasurer_payment_model_proto_rawDesc
)
func file_treasurer_payment_model_proto_rawDescGZIP() []byte {
file_treasurer_payment_model_proto_rawDescOnce.Do(func() {
file_treasurer_payment_model_proto_rawDescData = protoimpl.X.CompressGZIP(file_treasurer_payment_model_proto_rawDescData)
})
return file_treasurer_payment_model_proto_rawDescData
}
var file_treasurer_payment_model_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_treasurer_payment_model_proto_goTypes = []interface{}{
(*MainPaymentSettings)(nil), // 0: treasurer.MainPaymentSettings
(*BankCardInformation)(nil), // 1: treasurer.BankCardInformation
}
var file_treasurer_payment_model_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_treasurer_payment_model_proto_init() }
func file_treasurer_payment_model_proto_init() {
if File_treasurer_payment_model_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_treasurer_payment_model_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MainPaymentSettings); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_treasurer_payment_model_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*BankCardInformation); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_treasurer_payment_model_proto_msgTypes[1].OneofWrappers = []interface{}{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_treasurer_payment_model_proto_rawDesc,
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_treasurer_payment_model_proto_goTypes,
DependencyIndexes: file_treasurer_payment_model_proto_depIdxs,
MessageInfos: file_treasurer_payment_model_proto_msgTypes,
}.Build()
File_treasurer_payment_model_proto = out.File
file_treasurer_payment_model_proto_rawDesc = nil
file_treasurer_payment_model_proto_goTypes = nil
file_treasurer_payment_model_proto_depIdxs = nil
}

@ -0,0 +1,633 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.26.0
// protoc (unknown)
// source: treasurer/service.proto
package treasurer
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type GetBankCardPaymentLinkRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
MainSettings *MainPaymentSettings `protobuf:"bytes,1,opt,name=MainSettings,proto3" json:"MainSettings,omitempty"`
BankCard *BankCardInformation `protobuf:"bytes,2,opt,name=BankCard,proto3" json:"BankCard,omitempty"`
}
func (x *GetBankCardPaymentLinkRequest) Reset() {
*x = GetBankCardPaymentLinkRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_treasurer_service_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetBankCardPaymentLinkRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetBankCardPaymentLinkRequest) ProtoMessage() {}
func (x *GetBankCardPaymentLinkRequest) ProtoReflect() protoreflect.Message {
mi := &file_treasurer_service_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetBankCardPaymentLinkRequest.ProtoReflect.Descriptor instead.
func (*GetBankCardPaymentLinkRequest) Descriptor() ([]byte, []int) {
return file_treasurer_service_proto_rawDescGZIP(), []int{0}
}
func (x *GetBankCardPaymentLinkRequest) GetMainSettings() *MainPaymentSettings {
if x != nil {
return x.MainSettings
}
return nil
}
func (x *GetBankCardPaymentLinkRequest) GetBankCard() *BankCardInformation {
if x != nil {
return x.BankCard
}
return nil
}
type GetPaymentLinkBody struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
MainSettings *MainPaymentSettings `protobuf:"bytes,1,opt,name=MainSettings,proto3" json:"MainSettings,omitempty"`
}
func (x *GetPaymentLinkBody) Reset() {
*x = GetPaymentLinkBody{}
if protoimpl.UnsafeEnabled {
mi := &file_treasurer_service_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetPaymentLinkBody) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetPaymentLinkBody) ProtoMessage() {}
func (x *GetPaymentLinkBody) ProtoReflect() protoreflect.Message {
mi := &file_treasurer_service_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetPaymentLinkBody.ProtoReflect.Descriptor instead.
func (*GetPaymentLinkBody) Descriptor() ([]byte, []int) {
return file_treasurer_service_proto_rawDescGZIP(), []int{1}
}
func (x *GetPaymentLinkBody) GetMainSettings() *MainPaymentSettings {
if x != nil {
return x.MainSettings
}
return nil
}
type GetPhonePaymentLinkRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
MainSettings *MainPaymentSettings `protobuf:"bytes,1,opt,name=MainSettings,proto3" json:"MainSettings,omitempty"`
Phone string `protobuf:"bytes,2,opt,name=Phone,proto3" json:"Phone,omitempty"`
}
func (x *GetPhonePaymentLinkRequest) Reset() {
*x = GetPhonePaymentLinkRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_treasurer_service_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetPhonePaymentLinkRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetPhonePaymentLinkRequest) ProtoMessage() {}
func (x *GetPhonePaymentLinkRequest) ProtoReflect() protoreflect.Message {
mi := &file_treasurer_service_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetPhonePaymentLinkRequest.ProtoReflect.Descriptor instead.
func (*GetPhonePaymentLinkRequest) Descriptor() ([]byte, []int) {
return file_treasurer_service_proto_rawDescGZIP(), []int{2}
}
func (x *GetPhonePaymentLinkRequest) GetMainSettings() *MainPaymentSettings {
if x != nil {
return x.MainSettings
}
return nil
}
func (x *GetPhonePaymentLinkRequest) GetPhone() string {
if x != nil {
return x.Phone
}
return ""
}
type GetLoginPaymentLinkRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
MainSettings *MainPaymentSettings `protobuf:"bytes,1,opt,name=MainSettings,proto3" json:"MainSettings,omitempty"`
Login string `protobuf:"bytes,2,opt,name=Login,proto3" json:"Login,omitempty"`
}
func (x *GetLoginPaymentLinkRequest) Reset() {
*x = GetLoginPaymentLinkRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_treasurer_service_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetLoginPaymentLinkRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetLoginPaymentLinkRequest) ProtoMessage() {}
func (x *GetLoginPaymentLinkRequest) ProtoReflect() protoreflect.Message {
mi := &file_treasurer_service_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetLoginPaymentLinkRequest.ProtoReflect.Descriptor instead.
func (*GetLoginPaymentLinkRequest) Descriptor() ([]byte, []int) {
return file_treasurer_service_proto_rawDescGZIP(), []int{3}
}
func (x *GetLoginPaymentLinkRequest) GetMainSettings() *MainPaymentSettings {
if x != nil {
return x.MainSettings
}
return nil
}
func (x *GetLoginPaymentLinkRequest) GetLogin() string {
if x != nil {
return x.Login
}
return ""
}
type GetB2BPaymentLinkRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
MainSettings *MainPaymentSettings `protobuf:"bytes,1,opt,name=MainSettings,proto3" json:"MainSettings,omitempty"`
PaymentPurpose string `protobuf:"bytes,2,opt,name=PaymentPurpose,proto3" json:"PaymentPurpose,omitempty"`
VatData *emptypb.Empty `protobuf:"bytes,3,opt,name=VatData,proto3" json:"VatData,omitempty"`
}
func (x *GetB2BPaymentLinkRequest) Reset() {
*x = GetB2BPaymentLinkRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_treasurer_service_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetB2BPaymentLinkRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetB2BPaymentLinkRequest) ProtoMessage() {}
func (x *GetB2BPaymentLinkRequest) ProtoReflect() protoreflect.Message {
mi := &file_treasurer_service_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetB2BPaymentLinkRequest.ProtoReflect.Descriptor instead.
func (*GetB2BPaymentLinkRequest) Descriptor() ([]byte, []int) {
return file_treasurer_service_proto_rawDescGZIP(), []int{4}
}
func (x *GetB2BPaymentLinkRequest) GetMainSettings() *MainPaymentSettings {
if x != nil {
return x.MainSettings
}
return nil
}
func (x *GetB2BPaymentLinkRequest) GetPaymentPurpose() string {
if x != nil {
return x.PaymentPurpose
}
return ""
}
func (x *GetB2BPaymentLinkRequest) GetVatData() *emptypb.Empty {
if x != nil {
return x.VatData
}
return nil
}
type GetPaymentLinkResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
RedirectURL string `protobuf:"bytes,1,opt,name=RedirectURL,proto3" json:"RedirectURL,omitempty"`
}
func (x *GetPaymentLinkResponse) Reset() {
*x = GetPaymentLinkResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_treasurer_service_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetPaymentLinkResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetPaymentLinkResponse) ProtoMessage() {}
func (x *GetPaymentLinkResponse) ProtoReflect() protoreflect.Message {
mi := &file_treasurer_service_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetPaymentLinkResponse.ProtoReflect.Descriptor instead.
func (*GetPaymentLinkResponse) Descriptor() ([]byte, []int) {
return file_treasurer_service_proto_rawDescGZIP(), []int{5}
}
func (x *GetPaymentLinkResponse) GetRedirectURL() string {
if x != nil {
return x.RedirectURL
}
return ""
}
var File_treasurer_service_proto protoreflect.FileDescriptor
var file_treasurer_service_proto_rawDesc = []byte{
0x0a, 0x17, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x74, 0x72, 0x65, 0x61, 0x73,
0x75, 0x72, 0x65, 0x72, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x1a, 0x1d, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2f, 0x70, 0x61, 0x79,
0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x22, 0x9f, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6e, 0x6b, 0x43, 0x61, 0x72, 0x64,
0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x42, 0x0a, 0x0c, 0x4d, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73,
0x75, 0x72, 0x65, 0x72, 0x2e, 0x4d, 0x61, 0x69, 0x6e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74,
0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x0c, 0x4d, 0x61, 0x69, 0x6e, 0x53, 0x65,
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3a, 0x0a, 0x08, 0x42, 0x61, 0x6e, 0x6b, 0x43, 0x61,
0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73,
0x75, 0x72, 0x65, 0x72, 0x2e, 0x42, 0x61, 0x6e, 0x6b, 0x43, 0x61, 0x72, 0x64, 0x49, 0x6e, 0x66,
0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x42, 0x61, 0x6e, 0x6b, 0x43, 0x61,
0x72, 0x64, 0x22, 0x58, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74,
0x4c, 0x69, 0x6e, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x42, 0x0a, 0x0c, 0x4d, 0x61, 0x69, 0x6e,
0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e,
0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x4d, 0x61, 0x69, 0x6e, 0x50,
0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x0c,
0x4d, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x76, 0x0a, 0x1a,
0x47, 0x65, 0x74, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c,
0x69, 0x6e, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x0c, 0x4d, 0x61,
0x69, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1e, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x4d, 0x61, 0x69,
0x6e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
0x52, 0x0c, 0x4d, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x14,
0x0a, 0x05, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x50,
0x68, 0x6f, 0x6e, 0x65, 0x22, 0x76, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x69, 0x6e,
0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x42, 0x0a, 0x0c, 0x4d, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73,
0x75, 0x72, 0x65, 0x72, 0x2e, 0x4d, 0x61, 0x69, 0x6e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74,
0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x0c, 0x4d, 0x61, 0x69, 0x6e, 0x53, 0x65,
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x22, 0xb8, 0x01, 0x0a,
0x18, 0x47, 0x65, 0x74, 0x42, 0x32, 0x42, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69,
0x6e, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x0c, 0x4d, 0x61, 0x69,
0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1e, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x4d, 0x61, 0x69, 0x6e,
0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52,
0x0c, 0x4d, 0x61, 0x69, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x26, 0x0a,
0x0e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x75, 0x72, 0x70, 0x6f, 0x73, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x50, 0x75,
0x72, 0x70, 0x6f, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x07, 0x56, 0x61, 0x74, 0x44, 0x61, 0x74, 0x61,
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x07,
0x56, 0x61, 0x74, 0x44, 0x61, 0x74, 0x61, 0x22, 0x3a, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x50, 0x61,
0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x20, 0x0a, 0x0b, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x55, 0x52, 0x4c,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
0x55, 0x52, 0x4c, 0x32, 0xcc, 0x08, 0x0a, 0x10, 0x54, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65,
0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x67, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x50,
0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x42, 0x61, 0x6e, 0x6b, 0x43, 0x61,
0x72, 0x64, 0x12, 0x28, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x47,
0x65, 0x74, 0x42, 0x61, 0x6e, 0x6b, 0x43, 0x61, 0x72, 0x64, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e,
0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x74,
0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d,
0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x00, 0x12, 0x5c, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c,
0x69, 0x6e, 0x6b, 0x59, 0x6f, 0x6f, 0x4d, 0x6f, 0x6e, 0x65, 0x79, 0x12, 0x1d, 0x2e, 0x74, 0x72,
0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65,
0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x1a, 0x21, 0x2e, 0x74, 0x72, 0x65,
0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e,
0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
0x60, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e,
0x6b, 0x51, 0x49, 0x57, 0x49, 0x12, 0x25, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65,
0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e,
0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x74,
0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d,
0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x00, 0x12, 0x63, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c,
0x69, 0x6e, 0x6b, 0x53, 0x62, 0x65, 0x72, 0x50, 0x61, 0x79, 0x12, 0x25, 0x2e, 0x74, 0x72, 0x65,
0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x50,
0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x21, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x47, 0x65,
0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79,
0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x41, 0x6c, 0x66, 0x61, 0x43, 0x6c, 0x69, 0x63,
0x6b, 0x12, 0x25, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x47, 0x65,
0x74, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e,
0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73,
0x75, 0x72, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c,
0x69, 0x6e, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5b, 0x0a,
0x15, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x54,
0x69, 0x6e, 0x6b, 0x6f, 0x66, 0x66, 0x12, 0x1d, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72,
0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e,
0x6b, 0x42, 0x6f, 0x64, 0x79, 0x1a, 0x21, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65,
0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x19, 0x47, 0x65,
0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x53, 0x62, 0x65, 0x72,
0x62, 0x61, 0x6e, 0x6b, 0x42, 0x32, 0x42, 0x12, 0x23, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75,
0x72, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x32, 0x42, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e,
0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x74,
0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d,
0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x00, 0x12, 0x57, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c,
0x69, 0x6e, 0x6b, 0x53, 0x42, 0x50, 0x12, 0x1d, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72,
0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e,
0x6b, 0x42, 0x6f, 0x64, 0x79, 0x1a, 0x21, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65,
0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x62, 0x0a, 0x14, 0x47, 0x65,
0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x4d, 0x6f, 0x62, 0x69,
0x6c, 0x65, 0x12, 0x25, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x47,
0x65, 0x74, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69,
0x6e, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x74, 0x72, 0x65, 0x61,
0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74,
0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x60,
0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b,
0x43, 0x61, 0x73, 0x68, 0x12, 0x25, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72,
0x2e, 0x47, 0x65, 0x74, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74,
0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x74, 0x72,
0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65,
0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
0x12, 0x60, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69,
0x6e, 0x6b, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1d,
0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61,
0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x42, 0x6f, 0x64, 0x79, 0x1a, 0x21, 0x2e,
0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x79,
0x6d, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x00, 0x42, 0x0d, 0x5a, 0x0b, 0x2e, 0x2f, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65,
0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_treasurer_service_proto_rawDescOnce sync.Once
file_treasurer_service_proto_rawDescData = file_treasurer_service_proto_rawDesc
)
func file_treasurer_service_proto_rawDescGZIP() []byte {
file_treasurer_service_proto_rawDescOnce.Do(func() {
file_treasurer_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_treasurer_service_proto_rawDescData)
})
return file_treasurer_service_proto_rawDescData
}
var file_treasurer_service_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_treasurer_service_proto_goTypes = []interface{}{
(*GetBankCardPaymentLinkRequest)(nil), // 0: treasurer.GetBankCardPaymentLinkRequest
(*GetPaymentLinkBody)(nil), // 1: treasurer.GetPaymentLinkBody
(*GetPhonePaymentLinkRequest)(nil), // 2: treasurer.GetPhonePaymentLinkRequest
(*GetLoginPaymentLinkRequest)(nil), // 3: treasurer.GetLoginPaymentLinkRequest
(*GetB2BPaymentLinkRequest)(nil), // 4: treasurer.GetB2BPaymentLinkRequest
(*GetPaymentLinkResponse)(nil), // 5: treasurer.GetPaymentLinkResponse
(*MainPaymentSettings)(nil), // 6: treasurer.MainPaymentSettings
(*BankCardInformation)(nil), // 7: treasurer.BankCardInformation
(*emptypb.Empty)(nil), // 8: google.protobuf.Empty
}
var file_treasurer_service_proto_depIdxs = []int32{
6, // 0: treasurer.GetBankCardPaymentLinkRequest.MainSettings:type_name -> treasurer.MainPaymentSettings
7, // 1: treasurer.GetBankCardPaymentLinkRequest.BankCard:type_name -> treasurer.BankCardInformation
6, // 2: treasurer.GetPaymentLinkBody.MainSettings:type_name -> treasurer.MainPaymentSettings
6, // 3: treasurer.GetPhonePaymentLinkRequest.MainSettings:type_name -> treasurer.MainPaymentSettings
6, // 4: treasurer.GetLoginPaymentLinkRequest.MainSettings:type_name -> treasurer.MainPaymentSettings
6, // 5: treasurer.GetB2BPaymentLinkRequest.MainSettings:type_name -> treasurer.MainPaymentSettings
8, // 6: treasurer.GetB2BPaymentLinkRequest.VatData:type_name -> google.protobuf.Empty
0, // 7: treasurer.TreasurerService.GetPaymentLinkBankCard:input_type -> treasurer.GetBankCardPaymentLinkRequest
1, // 8: treasurer.TreasurerService.GetPaymentLinkYooMoney:input_type -> treasurer.GetPaymentLinkBody
2, // 9: treasurer.TreasurerService.GetPaymentLinkQIWI:input_type -> treasurer.GetPhonePaymentLinkRequest
2, // 10: treasurer.TreasurerService.GetPaymentLinkSberPay:input_type -> treasurer.GetPhonePaymentLinkRequest
3, // 11: treasurer.TreasurerService.GetPaymentLinkAlfaClick:input_type -> treasurer.GetLoginPaymentLinkRequest
1, // 12: treasurer.TreasurerService.GetPaymentLinkTinkoff:input_type -> treasurer.GetPaymentLinkBody
4, // 13: treasurer.TreasurerService.GetPaymentLinkSberbankB2B:input_type -> treasurer.GetB2BPaymentLinkRequest
1, // 14: treasurer.TreasurerService.GetPaymentLinkSBP:input_type -> treasurer.GetPaymentLinkBody
2, // 15: treasurer.TreasurerService.GetPaymentLinkMobile:input_type -> treasurer.GetPhonePaymentLinkRequest
2, // 16: treasurer.TreasurerService.GetPaymentLinkCash:input_type -> treasurer.GetPhonePaymentLinkRequest
1, // 17: treasurer.TreasurerService.GetPaymentLinkInstallments:input_type -> treasurer.GetPaymentLinkBody
5, // 18: treasurer.TreasurerService.GetPaymentLinkBankCard:output_type -> treasurer.GetPaymentLinkResponse
5, // 19: treasurer.TreasurerService.GetPaymentLinkYooMoney:output_type -> treasurer.GetPaymentLinkResponse
5, // 20: treasurer.TreasurerService.GetPaymentLinkQIWI:output_type -> treasurer.GetPaymentLinkResponse
5, // 21: treasurer.TreasurerService.GetPaymentLinkSberPay:output_type -> treasurer.GetPaymentLinkResponse
5, // 22: treasurer.TreasurerService.GetPaymentLinkAlfaClick:output_type -> treasurer.GetPaymentLinkResponse
5, // 23: treasurer.TreasurerService.GetPaymentLinkTinkoff:output_type -> treasurer.GetPaymentLinkResponse
5, // 24: treasurer.TreasurerService.GetPaymentLinkSberbankB2B:output_type -> treasurer.GetPaymentLinkResponse
5, // 25: treasurer.TreasurerService.GetPaymentLinkSBP:output_type -> treasurer.GetPaymentLinkResponse
5, // 26: treasurer.TreasurerService.GetPaymentLinkMobile:output_type -> treasurer.GetPaymentLinkResponse
5, // 27: treasurer.TreasurerService.GetPaymentLinkCash:output_type -> treasurer.GetPaymentLinkResponse
5, // 28: treasurer.TreasurerService.GetPaymentLinkInstallments:output_type -> treasurer.GetPaymentLinkResponse
18, // [18:29] is the sub-list for method output_type
7, // [7:18] is the sub-list for method input_type
7, // [7:7] is the sub-list for extension type_name
7, // [7:7] is the sub-list for extension extendee
0, // [0:7] is the sub-list for field type_name
}
func init() { file_treasurer_service_proto_init() }
func file_treasurer_service_proto_init() {
if File_treasurer_service_proto != nil {
return
}
file_treasurer_payment_model_proto_init()
if !protoimpl.UnsafeEnabled {
file_treasurer_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetBankCardPaymentLinkRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_treasurer_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetPaymentLinkBody); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_treasurer_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetPhonePaymentLinkRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_treasurer_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetLoginPaymentLinkRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_treasurer_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetB2BPaymentLinkRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_treasurer_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetPaymentLinkResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_treasurer_service_proto_rawDesc,
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_treasurer_service_proto_goTypes,
DependencyIndexes: file_treasurer_service_proto_depIdxs,
MessageInfos: file_treasurer_service_proto_msgTypes,
}.Build()
File_treasurer_service_proto = out.File
file_treasurer_service_proto_rawDesc = nil
file_treasurer_service_proto_goTypes = nil
file_treasurer_service_proto_depIdxs = nil
}

@ -0,0 +1,459 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
package treasurer
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// TreasurerServiceClient is the client API for TreasurerService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type TreasurerServiceClient interface {
GetPaymentLinkBankCard(ctx context.Context, in *GetBankCardPaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error)
GetPaymentLinkYooMoney(ctx context.Context, in *GetPaymentLinkBody, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error)
GetPaymentLinkQIWI(ctx context.Context, in *GetPhonePaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error)
GetPaymentLinkSberPay(ctx context.Context, in *GetPhonePaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error)
GetPaymentLinkAlfaClick(ctx context.Context, in *GetLoginPaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error)
GetPaymentLinkTinkoff(ctx context.Context, in *GetPaymentLinkBody, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error)
GetPaymentLinkSberbankB2B(ctx context.Context, in *GetB2BPaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error)
GetPaymentLinkSBP(ctx context.Context, in *GetPaymentLinkBody, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error)
GetPaymentLinkMobile(ctx context.Context, in *GetPhonePaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error)
GetPaymentLinkCash(ctx context.Context, in *GetPhonePaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error)
GetPaymentLinkInstallments(ctx context.Context, in *GetPaymentLinkBody, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error)
}
type treasurerServiceClient struct {
cc grpc.ClientConnInterface
}
func NewTreasurerServiceClient(cc grpc.ClientConnInterface) TreasurerServiceClient {
return &treasurerServiceClient{cc}
}
func (c *treasurerServiceClient) GetPaymentLinkBankCard(ctx context.Context, in *GetBankCardPaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error) {
out := new(GetPaymentLinkResponse)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/GetPaymentLinkBankCard", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *treasurerServiceClient) GetPaymentLinkYooMoney(ctx context.Context, in *GetPaymentLinkBody, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error) {
out := new(GetPaymentLinkResponse)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/GetPaymentLinkYooMoney", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *treasurerServiceClient) GetPaymentLinkQIWI(ctx context.Context, in *GetPhonePaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error) {
out := new(GetPaymentLinkResponse)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/GetPaymentLinkQIWI", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *treasurerServiceClient) GetPaymentLinkSberPay(ctx context.Context, in *GetPhonePaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error) {
out := new(GetPaymentLinkResponse)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/GetPaymentLinkSberPay", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *treasurerServiceClient) GetPaymentLinkAlfaClick(ctx context.Context, in *GetLoginPaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error) {
out := new(GetPaymentLinkResponse)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/GetPaymentLinkAlfaClick", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *treasurerServiceClient) GetPaymentLinkTinkoff(ctx context.Context, in *GetPaymentLinkBody, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error) {
out := new(GetPaymentLinkResponse)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/GetPaymentLinkTinkoff", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *treasurerServiceClient) GetPaymentLinkSberbankB2B(ctx context.Context, in *GetB2BPaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error) {
out := new(GetPaymentLinkResponse)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/GetPaymentLinkSberbankB2B", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *treasurerServiceClient) GetPaymentLinkSBP(ctx context.Context, in *GetPaymentLinkBody, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error) {
out := new(GetPaymentLinkResponse)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/GetPaymentLinkSBP", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *treasurerServiceClient) GetPaymentLinkMobile(ctx context.Context, in *GetPhonePaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error) {
out := new(GetPaymentLinkResponse)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/GetPaymentLinkMobile", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *treasurerServiceClient) GetPaymentLinkCash(ctx context.Context, in *GetPhonePaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error) {
out := new(GetPaymentLinkResponse)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/GetPaymentLinkCash", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *treasurerServiceClient) GetPaymentLinkInstallments(ctx context.Context, in *GetPaymentLinkBody, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error) {
out := new(GetPaymentLinkResponse)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/GetPaymentLinkInstallments", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// TreasurerServiceServer is the server API for TreasurerService service.
// All implementations should embed UnimplementedTreasurerServiceServer
// for forward compatibility
type TreasurerServiceServer interface {
GetPaymentLinkBankCard(context.Context, *GetBankCardPaymentLinkRequest) (*GetPaymentLinkResponse, error)
GetPaymentLinkYooMoney(context.Context, *GetPaymentLinkBody) (*GetPaymentLinkResponse, error)
GetPaymentLinkQIWI(context.Context, *GetPhonePaymentLinkRequest) (*GetPaymentLinkResponse, error)
GetPaymentLinkSberPay(context.Context, *GetPhonePaymentLinkRequest) (*GetPaymentLinkResponse, error)
GetPaymentLinkAlfaClick(context.Context, *GetLoginPaymentLinkRequest) (*GetPaymentLinkResponse, error)
GetPaymentLinkTinkoff(context.Context, *GetPaymentLinkBody) (*GetPaymentLinkResponse, error)
GetPaymentLinkSberbankB2B(context.Context, *GetB2BPaymentLinkRequest) (*GetPaymentLinkResponse, error)
GetPaymentLinkSBP(context.Context, *GetPaymentLinkBody) (*GetPaymentLinkResponse, error)
GetPaymentLinkMobile(context.Context, *GetPhonePaymentLinkRequest) (*GetPaymentLinkResponse, error)
GetPaymentLinkCash(context.Context, *GetPhonePaymentLinkRequest) (*GetPaymentLinkResponse, error)
GetPaymentLinkInstallments(context.Context, *GetPaymentLinkBody) (*GetPaymentLinkResponse, error)
}
// UnimplementedTreasurerServiceServer should be embedded to have forward compatible implementations.
type UnimplementedTreasurerServiceServer struct {
}
func (UnimplementedTreasurerServiceServer) GetPaymentLinkBankCard(context.Context, *GetBankCardPaymentLinkRequest) (*GetPaymentLinkResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPaymentLinkBankCard not implemented")
}
func (UnimplementedTreasurerServiceServer) GetPaymentLinkYooMoney(context.Context, *GetPaymentLinkBody) (*GetPaymentLinkResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPaymentLinkYooMoney not implemented")
}
func (UnimplementedTreasurerServiceServer) GetPaymentLinkQIWI(context.Context, *GetPhonePaymentLinkRequest) (*GetPaymentLinkResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPaymentLinkQIWI not implemented")
}
func (UnimplementedTreasurerServiceServer) GetPaymentLinkSberPay(context.Context, *GetPhonePaymentLinkRequest) (*GetPaymentLinkResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPaymentLinkSberPay not implemented")
}
func (UnimplementedTreasurerServiceServer) GetPaymentLinkAlfaClick(context.Context, *GetLoginPaymentLinkRequest) (*GetPaymentLinkResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPaymentLinkAlfaClick not implemented")
}
func (UnimplementedTreasurerServiceServer) GetPaymentLinkTinkoff(context.Context, *GetPaymentLinkBody) (*GetPaymentLinkResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPaymentLinkTinkoff not implemented")
}
func (UnimplementedTreasurerServiceServer) GetPaymentLinkSberbankB2B(context.Context, *GetB2BPaymentLinkRequest) (*GetPaymentLinkResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPaymentLinkSberbankB2B not implemented")
}
func (UnimplementedTreasurerServiceServer) GetPaymentLinkSBP(context.Context, *GetPaymentLinkBody) (*GetPaymentLinkResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPaymentLinkSBP not implemented")
}
func (UnimplementedTreasurerServiceServer) GetPaymentLinkMobile(context.Context, *GetPhonePaymentLinkRequest) (*GetPaymentLinkResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPaymentLinkMobile not implemented")
}
func (UnimplementedTreasurerServiceServer) GetPaymentLinkCash(context.Context, *GetPhonePaymentLinkRequest) (*GetPaymentLinkResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPaymentLinkCash not implemented")
}
func (UnimplementedTreasurerServiceServer) GetPaymentLinkInstallments(context.Context, *GetPaymentLinkBody) (*GetPaymentLinkResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPaymentLinkInstallments not implemented")
}
// UnsafeTreasurerServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to TreasurerServiceServer will
// result in compilation errors.
type UnsafeTreasurerServiceServer interface {
mustEmbedUnimplementedTreasurerServiceServer()
}
func RegisterTreasurerServiceServer(s grpc.ServiceRegistrar, srv TreasurerServiceServer) {
s.RegisterService(&TreasurerService_ServiceDesc, srv)
}
func _TreasurerService_GetPaymentLinkBankCard_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetBankCardPaymentLinkRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TreasurerServiceServer).GetPaymentLinkBankCard(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/treasurer.TreasurerService/GetPaymentLinkBankCard",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).GetPaymentLinkBankCard(ctx, req.(*GetBankCardPaymentLinkRequest))
}
return interceptor(ctx, in, info, handler)
}
func _TreasurerService_GetPaymentLinkYooMoney_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetPaymentLinkBody)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TreasurerServiceServer).GetPaymentLinkYooMoney(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/treasurer.TreasurerService/GetPaymentLinkYooMoney",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).GetPaymentLinkYooMoney(ctx, req.(*GetPaymentLinkBody))
}
return interceptor(ctx, in, info, handler)
}
func _TreasurerService_GetPaymentLinkQIWI_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetPhonePaymentLinkRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TreasurerServiceServer).GetPaymentLinkQIWI(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/treasurer.TreasurerService/GetPaymentLinkQIWI",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).GetPaymentLinkQIWI(ctx, req.(*GetPhonePaymentLinkRequest))
}
return interceptor(ctx, in, info, handler)
}
func _TreasurerService_GetPaymentLinkSberPay_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetPhonePaymentLinkRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TreasurerServiceServer).GetPaymentLinkSberPay(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/treasurer.TreasurerService/GetPaymentLinkSberPay",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).GetPaymentLinkSberPay(ctx, req.(*GetPhonePaymentLinkRequest))
}
return interceptor(ctx, in, info, handler)
}
func _TreasurerService_GetPaymentLinkAlfaClick_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetLoginPaymentLinkRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TreasurerServiceServer).GetPaymentLinkAlfaClick(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/treasurer.TreasurerService/GetPaymentLinkAlfaClick",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).GetPaymentLinkAlfaClick(ctx, req.(*GetLoginPaymentLinkRequest))
}
return interceptor(ctx, in, info, handler)
}
func _TreasurerService_GetPaymentLinkTinkoff_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetPaymentLinkBody)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TreasurerServiceServer).GetPaymentLinkTinkoff(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/treasurer.TreasurerService/GetPaymentLinkTinkoff",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).GetPaymentLinkTinkoff(ctx, req.(*GetPaymentLinkBody))
}
return interceptor(ctx, in, info, handler)
}
func _TreasurerService_GetPaymentLinkSberbankB2B_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetB2BPaymentLinkRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TreasurerServiceServer).GetPaymentLinkSberbankB2B(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/treasurer.TreasurerService/GetPaymentLinkSberbankB2B",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).GetPaymentLinkSberbankB2B(ctx, req.(*GetB2BPaymentLinkRequest))
}
return interceptor(ctx, in, info, handler)
}
func _TreasurerService_GetPaymentLinkSBP_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetPaymentLinkBody)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TreasurerServiceServer).GetPaymentLinkSBP(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/treasurer.TreasurerService/GetPaymentLinkSBP",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).GetPaymentLinkSBP(ctx, req.(*GetPaymentLinkBody))
}
return interceptor(ctx, in, info, handler)
}
func _TreasurerService_GetPaymentLinkMobile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetPhonePaymentLinkRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TreasurerServiceServer).GetPaymentLinkMobile(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/treasurer.TreasurerService/GetPaymentLinkMobile",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).GetPaymentLinkMobile(ctx, req.(*GetPhonePaymentLinkRequest))
}
return interceptor(ctx, in, info, handler)
}
func _TreasurerService_GetPaymentLinkCash_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetPhonePaymentLinkRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TreasurerServiceServer).GetPaymentLinkCash(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/treasurer.TreasurerService/GetPaymentLinkCash",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).GetPaymentLinkCash(ctx, req.(*GetPhonePaymentLinkRequest))
}
return interceptor(ctx, in, info, handler)
}
func _TreasurerService_GetPaymentLinkInstallments_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetPaymentLinkBody)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TreasurerServiceServer).GetPaymentLinkInstallments(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/treasurer.TreasurerService/GetPaymentLinkInstallments",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).GetPaymentLinkInstallments(ctx, req.(*GetPaymentLinkBody))
}
return interceptor(ctx, in, info, handler)
}
// TreasurerService_ServiceDesc is the grpc.ServiceDesc for TreasurerService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var TreasurerService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "treasurer.TreasurerService",
HandlerType: (*TreasurerServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetPaymentLinkBankCard",
Handler: _TreasurerService_GetPaymentLinkBankCard_Handler,
},
{
MethodName: "GetPaymentLinkYooMoney",
Handler: _TreasurerService_GetPaymentLinkYooMoney_Handler,
},
{
MethodName: "GetPaymentLinkQIWI",
Handler: _TreasurerService_GetPaymentLinkQIWI_Handler,
},
{
MethodName: "GetPaymentLinkSberPay",
Handler: _TreasurerService_GetPaymentLinkSberPay_Handler,
},
{
MethodName: "GetPaymentLinkAlfaClick",
Handler: _TreasurerService_GetPaymentLinkAlfaClick_Handler,
},
{
MethodName: "GetPaymentLinkTinkoff",
Handler: _TreasurerService_GetPaymentLinkTinkoff_Handler,
},
{
MethodName: "GetPaymentLinkSberbankB2B",
Handler: _TreasurerService_GetPaymentLinkSberbankB2B_Handler,
},
{
MethodName: "GetPaymentLinkSBP",
Handler: _TreasurerService_GetPaymentLinkSBP_Handler,
},
{
MethodName: "GetPaymentLinkMobile",
Handler: _TreasurerService_GetPaymentLinkMobile_Handler,
},
{
MethodName: "GetPaymentLinkCash",
Handler: _TreasurerService_GetPaymentLinkCash_Handler,
},
{
MethodName: "GetPaymentLinkInstallments",
Handler: _TreasurerService_GetPaymentLinkInstallments_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "treasurer/service.proto",
}

82
internal/server/grpc.go Normal file

@ -0,0 +1,82 @@
package server
import (
"context"
"fmt"
"net"
"time"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpc_zap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap"
grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
"go.uber.org/zap"
"google.golang.org/grpc"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/initialize"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/proto/customer"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/proto/payment_callback"
)
type DepsGRPC struct {
Logger *zap.Logger
}
type GRPC struct {
logger *zap.Logger
grpc *grpc.Server
}
func NewGRPC(deps DepsGRPC) (*GRPC, errors.Error) {
if deps.Logger == nil {
return nil, errors.NewWithMessage("Logger is nil on <NewGRPC>", errors.ErrInvalidArgs)
}
grpcStreamInterceptor := grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
grpc_zap.StreamServerInterceptor(deps.Logger),
grpc_recovery.StreamServerInterceptor(),
))
grpcUnaryInterceptor := grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
grpc_zap.UnaryServerInterceptor(deps.Logger),
grpc_recovery.UnaryServerInterceptor(),
))
return &GRPC{
grpc: grpc.NewServer(grpcStreamInterceptor, grpcUnaryInterceptor, grpc.ConnectionTimeout(5*time.Second)),
logger: deps.Logger,
}, nil
}
func (receiver *GRPC) Run(config *models.ConfigurationGRPC) {
connectionString := fmt.Sprintf("%s:%s", config.Host, config.Port)
receiver.logger.Info("Starting GRPC Server", zap.String("host", connectionString))
if err := receiver.listen(connectionString); err != nil && err != grpc.ErrServerStopped {
receiver.logger.Error("GRPC Listen error", zap.Error(err))
}
}
func (receiver *GRPC) Stop(_ context.Context) error {
receiver.grpc.GracefulStop()
receiver.logger.Info("Shutting down GRPC server...")
return nil
}
func (receiver *GRPC) Register(controllers *initialize.Controllers) *GRPC {
payment_callback.RegisterPaymentCallbackServiceServer(receiver.grpc, controllers.PaymentController)
customer.RegisterCustomerServiceServer(receiver.grpc, controllers.CustomerController)
return receiver
}
func (receiver *GRPC) listen(address string) error {
listener, err := net.Listen("tcp", address)
if err != nil {
return err
}
return receiver.grpc.Serve(listener)
}

93
internal/server/http.go Normal file

@ -0,0 +1,93 @@
package server
import (
"context"
"fmt"
"net/http"
"time"
"github.com/getkin/kin-openapi/openapi3"
"github.com/getkin/kin-openapi/openapi3filter"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/interface/swagger"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)
type DepsHTTP struct {
Logger *zap.Logger
Swagger *openapi3.T
AuthenticationFunc openapi3filter.AuthenticationFunc
}
type HTTP struct {
logger *zap.Logger
server *http.Server
echo *echo.Echo
}
func NewHTTP(deps DepsHTTP) (*HTTP, errors.Error) {
if deps.Logger == nil {
return nil, errors.NewWithMessage("failed to init http server: logger is nil <NewHTTP>", errors.ErrInvalidArgs)
}
if deps.Swagger == nil {
return nil, errors.NewWithMessage("failed to init http server: swagger is nil <NewHTTP>", errors.ErrInvalidArgs)
}
if deps.AuthenticationFunc == nil {
return nil, errors.NewWithMessage("failed to init http server: AuthenticationFunc is nil <NewHTTP>", errors.ErrInvalidArgs)
}
echo := echo.New()
echo.Use(middleware.Recover())
echo.Use(swagger.CreateMiddleware(deps.Swagger, deps.AuthenticationFunc))
return &HTTP{
echo: echo,
logger: deps.Logger,
server: &http.Server{
Handler: echo,
MaxHeaderBytes: 1 << 20,
ReadTimeout: 20 * time.Second,
WriteTimeout: 20 * time.Second,
IdleTimeout: 20 * time.Second,
},
}, nil
}
func (receiver *HTTP) Listen(address string) error {
receiver.server.Addr = address
return receiver.server.ListenAndServe()
}
func (receiver *HTTP) Run(config *models.ConfigurationHTTP) {
connectionString := fmt.Sprintf("%s:%s", config.Host, config.Port)
startServerMessage := fmt.Sprintf("starting http server on %s", connectionString)
receiver.logger.Info(startServerMessage)
if err := receiver.Listen(connectionString); err != nil && err != http.ErrServerClosed {
receiver.logger.Error("http listen error: ", zap.Error(err))
}
}
func (receiver *HTTP) Stop(ctx context.Context) error {
receiver.logger.Info("shutting down server...")
if err := receiver.server.Shutdown(ctx); err != nil {
return fmt.Errorf("failed to shutdown server: %w", err)
}
return nil
}
func (receiver *HTTP) Register(api *swagger.API) *HTTP {
swagger.RegisterHandlers(receiver.echo, api)
return receiver
}

@ -0,0 +1,237 @@
package account
import (
"context"
"fmt"
"log"
"math"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)
type accountRepository interface {
FindByUserID(ctx context.Context, id string) (*models.Account, errors.Error)
FindMany(ctx context.Context, page, limit int64) ([]models.Account, errors.Error)
Insert(ctx context.Context, account *models.Account) (*models.Account, errors.Error)
Remove(ctx context.Context, id string) (*models.Account, errors.Error)
Delete(ctx context.Context, id string) (*models.Account, errors.Error)
CountAll(ctx context.Context) (int64, errors.Error)
SetStatus(ctx context.Context, userID string, status models.AccountStatus) (*models.Account, errors.Error)
UpdateName(ctx context.Context, userID string, name *models.Name) (*models.Account, errors.Error)
}
type authClient interface {
GetUser(ctx context.Context, userID string) (*models.User, errors.Error)
}
type Deps struct {
Logger *zap.Logger
Repository accountRepository
AuthClient authClient
}
type Service struct {
logger *zap.Logger
repository accountRepository
authClient authClient
}
func New(deps Deps) *Service {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (account service)>")
}
if deps.Repository == nil {
log.Panicln("repository is nil on <New (account service)>")
}
if deps.AuthClient == nil {
log.Panicln("auth client is nil on <New (account service)>")
}
return &Service{
logger: deps.Logger,
repository: deps.Repository,
authClient: deps.AuthClient,
}
}
func (receiver *Service) GetAccountByUserID(ctx context.Context, userID string) (*models.Account, errors.Error) {
account, err := receiver.repository.FindByUserID(ctx, userID)
if err != nil {
receiver.logger.Error("failed to get account by id on <GetAccountByUserID> of <AccountService>",
zap.Error(err),
zap.String("userID", userID),
)
return nil, err
}
return account, nil
}
func (receiver *Service) GetAccountsList(ctx context.Context, pagination *models.Pagination) (*models.PaginationResponse[models.Account], errors.Error) {
if pagination == nil {
return nil, errors.New(
fmt.Errorf("pagination is nil on <GetAccountsList> of <AccountService>: %w", errors.ErrInternalError),
errors.ErrInternalError,
)
}
count, err := receiver.repository.CountAll(ctx)
if err != nil {
receiver.logger.Error("failed to count accounts on <GetAccountsList> of <AccountService>",
zap.Error(err),
)
return nil, err
}
if count == 0 {
return &models.PaginationResponse[models.Account]{TotalPages: 0, Records: []models.Account{}}, nil
}
totalPages := int64(math.Ceil(float64(count) / float64(pagination.Limit)))
accounts, err := receiver.repository.FindMany(ctx, pagination.Page, pagination.Limit)
if err != nil {
receiver.logger.Error("failed to get accounts list on <GetAccountsList> of <AccountService>",
zap.Error(err),
zap.Int64("page", pagination.Page),
zap.Int64("limit", pagination.Limit),
)
return nil, err
}
return &models.PaginationResponse[models.Account]{
TotalPages: totalPages,
Records: accounts,
}, nil
}
func (receiver *Service) CreateAccount(ctx context.Context, account *models.Account) (*models.Account, errors.Error) {
findedAccount, err := receiver.GetAccountByUserID(ctx, account.UserID)
if err != nil && err.Type() != errors.ErrNotFound {
receiver.logger.Error("failed to find account on <CreateAccount> of <AccountService>",
zap.Error(err),
)
return nil, err
}
if findedAccount != nil {
return nil, errors.New(
fmt.Errorf("failed to create account with <%s> on <CreateAccount> of <AccountService>: %w",
account.UserID,
errors.ErrConflict,
),
errors.ErrConflict,
)
}
createdAccount, err := receiver.repository.Insert(ctx, account)
if err != nil {
receiver.logger.Error("failed to create account on <CreateAccount> of <AccountService>",
zap.Error(err),
zap.Any("account", account),
)
return nil, err
}
return createdAccount, nil
}
func (receiver *Service) CreateAccountByUserID(ctx context.Context, userID string) (*models.Account, errors.Error) {
account, err := receiver.GetAccountByUserID(ctx, userID)
if err != nil && err.Type() != errors.ErrNotFound {
receiver.logger.Error("failed to find account on <CreateAccountByUserID> of <AccountService>",
zap.Error(err),
)
return nil, err
}
if account != nil {
return nil, errors.New(
fmt.Errorf("failed to create account with <%s> on <CreateAccountByUserID> of <AccountService>: %w",
userID,
errors.ErrConflict,
),
errors.ErrConflict,
)
}
user, err := receiver.authClient.GetUser(ctx, userID)
if err != nil {
receiver.logger.Error("failed to get user on <CreateAccountByUserID> of <AccountService>",
zap.Error(err),
zap.String("userID", userID),
)
return nil, err
}
createdAccount, err := receiver.repository.Insert(ctx, &models.Account{UserID: user.ID})
if err != nil {
receiver.logger.Error("failed to create account on <CreateAccountByUserID> of <AccountService>",
zap.Error(err),
zap.String("userID", userID),
)
return nil, err
}
return createdAccount, nil
}
func (receiver *Service) RemoveAccount(ctx context.Context, userID string) (*models.Account, errors.Error) {
account, err := receiver.repository.Remove(ctx, userID)
if err != nil {
receiver.logger.Error("failed to remove account on <RemoveAccount> of <AccountService>",
zap.Error(err),
zap.String("userID", userID),
)
return nil, err
}
return account, nil
}
func (receiver *Service) DeleteAccount(ctx context.Context, userID string) (*models.Account, errors.Error) {
account, err := receiver.repository.Delete(ctx, userID)
if err != nil {
receiver.logger.Error("failed to delete account on <DeleteAccount> of <AccountService>",
zap.Error(err),
zap.String("userID", userID),
)
return nil, err
}
return account, nil
}
func (receiver *Service) SetVerificationStatus(ctx context.Context, userID string, status models.AccountStatus) (*models.Account, errors.Error) {
account, err := receiver.repository.SetStatus(ctx, userID, status)
if err != nil {
receiver.logger.Error("failed to set status on <SetVerificationStatus> of <AccountService>", zap.Error(err))
return nil, err
}
return account, nil
}
func (receiver *Service) UpdateAccountName(ctx context.Context, userID string, name *models.Name) (*models.Account, errors.Error) {
account, err := receiver.repository.UpdateName(ctx, userID, name)
if err != nil {
receiver.logger.Error("failed to update account name on <UpdateAccountName> of <AccountService>", zap.Error(err))
return nil, err
}
return account, nil
}

@ -0,0 +1,107 @@
package callback
import (
"context"
"log"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)
type accountRepository interface {
FindByUserID(context.Context, string) (*models.Account, errors.Error)
}
type historyService interface {
CreateHistory(ctx context.Context, history *models.History) (*models.History, errors.Error)
}
type walletService interface {
ReplenishAccountWallet(context.Context, *models.ReplenishAccountWallet) (*models.Account, errors.Error)
}
type PaymentCallbackServiceDeps struct {
Logger *zap.Logger
AccountRepository accountRepository
WalletService walletService
HistoryService historyService
}
type PaymentCallbackService struct {
logger *zap.Logger
accountRepository accountRepository
walletService walletService
historyService historyService
}
func NewPaymentCallbackService(deps PaymentCallbackServiceDeps) *PaymentCallbackService {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (payment callback service)>")
}
if deps.AccountRepository == nil {
log.Panicln("AccountRepository is nil on <New (payment callback service)>")
}
if deps.WalletService == nil {
log.Panicln("WalletService is nil on <New (payment callback service)>")
}
if deps.HistoryService == nil {
log.Panicln("HistoryService is nil on <New (payment callback service)>")
}
return &PaymentCallbackService{
logger: deps.Logger,
accountRepository: deps.AccountRepository,
walletService: deps.WalletService,
historyService: deps.HistoryService,
}
}
func (receiver *PaymentCallbackService) SuccessEvent(ctx context.Context, event *models.PaymentEvent) errors.Error {
account, err := receiver.accountRepository.FindByUserID(ctx, event.UserID)
if err != nil {
receiver.logger.Error("failed to get account on <SuccessEvent> of <PaymentCallbackService>", zap.Error(err))
return err
}
if account.Wallet.LastPaymentID == event.PaymentID {
receiver.logger.Info("payment already was executed on <SuccessEvent> of <PaymentCallbackService>", zap.String("paymentID", event.PaymentID))
return nil
}
if _, err := receiver.walletService.ReplenishAccountWallet(ctx, &models.ReplenishAccountWallet{
Cash: event.Amount,
Currency: event.Currency,
PaymentID: event.PaymentID,
Account: account,
}); err != nil {
receiver.logger.Error("failed to replenish wallet on <SuccessEvent> of <PaymentCallbackService>", zap.Error(err))
return err
}
if _, err := receiver.historyService.CreateHistory(ctx, &models.History{
UserID: account.UserID,
Comment: event.Message,
Key: event.Key,
}); err != nil {
receiver.logger.Error("failed to create history on <SuccessEvent> of <PaymentCallbackService>", zap.Error(err))
}
return nil
}
func (receiver *PaymentCallbackService) FailureEvent(ctx context.Context, event *models.PaymentEvent) errors.Error {
if _, err := receiver.historyService.CreateHistory(ctx, &models.History{
UserID: event.UserID,
Comment: event.Message,
Key: event.Key,
}); err != nil {
receiver.logger.Error("failed to create history on <FailureEvent> of <PaymentCallbackService>", zap.Error(err))
return err
}
return nil
}

@ -0,0 +1,188 @@
package cart
import (
"context"
"fmt"
"log"
"time"
"go.uber.org/zap"
"google.golang.org/protobuf/types/known/timestamppb"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/proto/discount"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils/transfer"
)
type accountRepository interface {
FindByUserID(ctx context.Context, id string) (*models.Account, errors.Error)
AddItemToCart(ctx context.Context, userID, itemID string) (*models.Account, errors.Error)
RemoveItemFromCart(ctx context.Context, userID, itemID string) (*models.Account, errors.Error)
ClearCart(ctx context.Context, userID string) (*models.Account, errors.Error)
}
type hubadminClient interface {
GetTariff(ctx context.Context, tariffID string) (*models.Tariff, errors.Error)
GetTariffs(ctx context.Context, tarriffIDs []string) ([]models.Tariff, errors.Error)
}
type discountClient interface {
Apply(context.Context, *discount.ApplyDiscountRequest) (*discount.ApplyDiscountResponse, errors.Error)
}
type walletService interface {
ReplenishAccountWallet(context.Context, *models.ReplenishAccountWallet) (*models.Account, errors.Error)
WithdrawAccountWalletMoney(context.Context, *models.WithdrawAccountWallet) (*models.Account, errors.Error)
}
type historyService interface {
CreateHistory(ctx context.Context, history *models.History) (*models.History, errors.Error)
}
type Deps struct {
Logger *zap.Logger
Repository accountRepository
HubadminClient hubadminClient
DiscountClient discountClient
WalletService walletService
HistoryService historyService
}
type Service struct {
logger *zap.Logger
repository accountRepository
hubadminClient hubadminClient
discountClient discountClient
walletService walletService
historyService historyService
}
func New(deps Deps) *Service {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (cart service)>")
}
if deps.Repository == nil {
log.Panicln("repository is nil on <New (cart service)>")
}
if deps.HubadminClient == nil {
log.Panicln("HubadminClient is nil on <New (cart service)>")
}
if deps.DiscountClient == nil {
log.Panicln("DiscountClient is nil on <New (cart service)>")
}
if deps.WalletService == nil {
log.Panicln("WalletService is nil on <New (cart service)>")
}
if deps.HistoryService == nil {
log.Panicln("HistoryService is nil on <New (cart service)>")
}
return &Service{
logger: deps.Logger,
repository: deps.Repository,
hubadminClient: deps.HubadminClient,
discountClient: deps.DiscountClient,
walletService: deps.WalletService,
historyService: deps.HistoryService,
}
}
func (receiver *Service) Remove(ctx context.Context, userID, itemID string) ([]string, errors.Error) {
account, err := receiver.repository.RemoveItemFromCart(ctx, userID, itemID)
if err != nil {
receiver.logger.Error("failed to remove item from cart on <Remove> of <CartService>", zap.Error(err))
return []string{}, err
}
return account.Cart, nil
}
func (receiver *Service) Add(ctx context.Context, userID, itemID string) ([]string, errors.Error) {
tariff, err := receiver.hubadminClient.GetTariff(ctx, itemID)
if err != nil {
receiver.logger.Error("failed to get tariff on <Add> of <CartService>", zap.Error(err), zap.String("tariffID", itemID))
return []string{}, err
}
if tariff == nil {
return []string{}, errors.New(
fmt.Errorf("failed to get tariff <%s> on <Add> of <CartService>: tariff not found", itemID),
errors.ErrNotFound,
)
}
account, err := receiver.repository.AddItemToCart(ctx, userID, itemID)
if err != nil {
receiver.logger.Error("failed to add item to cart on <Add> of <CartService>", zap.Error(err))
return []string{}, err
}
return account.Cart, nil
}
func (receiver *Service) Pay(ctx context.Context, userID string) (string, errors.Error) {
account, err := receiver.repository.FindByUserID(ctx, userID)
if err != nil {
receiver.logger.Error("failed to find account on <Pay> of <CartService>", zap.String("userID", userID), zap.Error(err))
return "", err
}
tariffs, err := receiver.hubadminClient.GetTariffs(ctx, account.Cart)
if err != nil {
receiver.logger.Error("failed to get tarrifs on <Pay> of <CartService>", zap.Strings("cart", account.Cart), zap.Error(err))
return "", err
}
tariffsAmount := utils.CalculateCartPurchasesAmount(tariffs)
// TODO: убрать все конвертеры чисел: float64, int64
response, err := receiver.discountClient.Apply(ctx, &discount.ApplyDiscountRequest{
UserInformation: &discount.UserInformation{
ID: account.UserID,
Type: string(account.Status),
PurchasesAmount: float64(account.Wallet.PurchasesAmount),
CartPurchasesAmount: float64(tariffsAmount),
},
Products: transfer.TariffsToProductInformations(tariffs),
Date: timestamppb.New(time.Now()),
})
if err != nil {
receiver.logger.Error("failed to discount on <Pay> of <CartService>", zap.Error(err))
return "", err
}
if account.Wallet.Money < int64(response.Price) {
receiver.logger.Error("insufficient funds on <Pay> of <CartService>")
return "", errors.New(fmt.Errorf("insufficient funds: %d", int64(response.Price)-account.Wallet.Money), errors.ErrInsufficientFunds)
}
if _, err := receiver.walletService.WithdrawAccountWalletMoney(ctx, &models.WithdrawAccountWallet{
Money: int64(response.Price),
Account: account,
}); err != nil {
receiver.logger.Error("failed to withdraw money on <Pay> of <CartService>", zap.Error(err))
return "", err
}
if _, historyErr := receiver.historyService.CreateHistory(ctx, &models.History{
Key: models.CustomerHistoryKeyPayCart,
UserID: account.UserID,
Comment: "Успешная оплата корзины",
}); historyErr != nil {
receiver.logger.Error("failed to insert history on <Pay> of <CartService>", zap.Error(historyErr))
}
if _, err := receiver.repository.ClearCart(ctx, account.UserID); err != nil {
receiver.logger.Error("failed to clear cart on <Pay> of <CartService>", zap.Error(err))
return "", err
}
return "", nil
}

@ -0,0 +1,93 @@
package currency
import (
"context"
"log"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)
type currencyRepository interface {
FindCurrenciesList(ctx context.Context, name string) (*models.CurrencyList, errors.Error)
ReplaceCurrencies(ctx context.Context, list *models.CurrencyList) (*models.CurrencyList, errors.Error)
Insert(ctx context.Context, list *models.CurrencyList) (*models.CurrencyList, errors.Error)
}
type Deps struct {
Logger *zap.Logger
Repository currencyRepository
}
type Service struct {
logger *zap.Logger
repository currencyRepository
}
func New(deps Deps) *Service {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (currency service)>")
}
if deps.Repository == nil {
log.Panicln("repository is nil on <New (currency service)>")
}
return &Service{
logger: deps.Logger,
repository: deps.Repository,
}
}
func (receiver *Service) GetCurrencies(ctx context.Context) ([]string, errors.Error) {
currencyList, err := receiver.repository.FindCurrenciesList(ctx, models.DefaultCurrencyListName)
if err != nil && err.Type() != errors.ErrNotFound {
receiver.logger.Error(
"failed to get currencies on <GetCurrencies> of <CurrencyService>",
zap.Error(err),
)
return []string{}, err
}
if err != nil && err.Type() == errors.ErrNotFound {
return []string{}, nil
}
return currencyList.Currencies, nil
}
func (receiver *Service) PutCurrencies(ctx context.Context, currencies []string) ([]string, errors.Error) {
currencyList, err := receiver.repository.ReplaceCurrencies(ctx, &models.CurrencyList{
Name: models.DefaultCurrencyListName,
Currencies: currencies,
})
if err != nil && err.Type() != errors.ErrNotFound {
receiver.logger.Error(
"failed to put currencies on <PutCurrencies> of <CurrencyService>",
zap.Error(err),
)
return []string{}, err
}
if err != nil && err.Type() == errors.ErrNotFound {
newCurrencyList, err := receiver.repository.Insert(ctx, &models.CurrencyList{
Name: models.DefaultCurrencyListName,
Currencies: currencies,
})
if err != nil && err.Type() != errors.ErrNotFound {
receiver.logger.Error(
"failed to insert new currency list on <PutCurrencies> of <CurrencyService>",
zap.Error(err),
)
return []string{}, err
}
return newCurrencyList.Currencies, nil
}
return currencyList.Currencies, nil
}

@ -0,0 +1,93 @@
package history
import (
"context"
"fmt"
"log"
"math"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)
type historyRepository interface {
CountAll(context.Context) (int64, errors.Error)
FindMany(ctx context.Context, page, limit int64) ([]models.History, errors.Error)
Insert(context.Context, *models.History) (*models.History, errors.Error)
}
type Deps struct {
Logger *zap.Logger
Repository historyRepository
}
type Service struct {
logger *zap.Logger
repository historyRepository
}
func New(deps Deps) *Service {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (history service)>")
}
if deps.Repository == nil {
log.Panicln("repository is nil on <New (history service)>")
}
return &Service{
logger: deps.Logger,
repository: deps.Repository,
}
}
func (receiver *Service) GetHistoryList(ctx context.Context, pagination *models.Pagination) (*models.PaginationResponse[models.History], errors.Error) {
if pagination == nil {
return nil, errors.New(
fmt.Errorf("pagination is nil on <GetHistoryList> of <HistoryService>: %w", errors.ErrInternalError),
errors.ErrInternalError,
)
}
count, err := receiver.repository.CountAll(ctx)
if err != nil {
receiver.logger.Error("failed to count histories on <GetHistoryList> of <HistoryService>",
zap.Error(err),
)
return nil, err
}
if count == 0 {
return &models.PaginationResponse[models.History]{TotalPages: 0, Records: []models.History{}}, nil
}
totalPages := int64(math.Ceil(float64(count) / float64(pagination.Limit)))
histories, err := receiver.repository.FindMany(ctx, pagination.Page, pagination.Limit)
if err != nil {
receiver.logger.Error("failed to get historiy list on <GetHistoryList> of <HistoryService>",
zap.Error(err),
zap.Int64("page", pagination.Page),
zap.Int64("limit", pagination.Limit),
)
return nil, err
}
return &models.PaginationResponse[models.History]{
TotalPages: totalPages,
Records: histories,
}, nil
}
func (receiver *Service) CreateHistory(ctx context.Context, history *models.History) (*models.History, errors.Error) {
createdHistory, err := receiver.repository.Insert(ctx, history)
if err != nil {
receiver.logger.Error("failed to create history on <CreateHistory> of <HistoryService>", zap.Error(err))
return nil, err
}
return createdHistory, nil
}

@ -0,0 +1,261 @@
package payment
import (
"context"
"log"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/proto/treasurer"
)
type paymentClient interface {
GetPaymentLinkBankCard(ctx context.Context, request *treasurer.GetBankCardPaymentLinkRequest) (string, errors.Error)
GetPaymentLinkYooMoney(ctx context.Context, request *treasurer.GetPaymentLinkBody) (string, errors.Error)
GetPaymentLinkQIWI(ctx context.Context, request *treasurer.GetPhonePaymentLinkRequest) (string, errors.Error)
GetPaymentLinkSberPay(ctx context.Context, request *treasurer.GetPhonePaymentLinkRequest) (string, errors.Error)
GetPaymentLinkAlfaClick(ctx context.Context, request *treasurer.GetLoginPaymentLinkRequest) (string, errors.Error)
GetPaymentLinkTinkoff(ctx context.Context, request *treasurer.GetPaymentLinkBody) (string, errors.Error)
GetPaymentLinkSberbankB2B(ctx context.Context, request *treasurer.GetB2BPaymentLinkRequest) (string, errors.Error)
GetPaymentLinkMobile(ctx context.Context, request *treasurer.GetPhonePaymentLinkRequest) (string, errors.Error)
GetPaymentLinkCash(ctx context.Context, request *treasurer.GetPhonePaymentLinkRequest) (string, errors.Error)
GetPaymentLinkInstallments(ctx context.Context, request *treasurer.GetPaymentLinkBody) (string, errors.Error)
}
type authClient interface {
GetUser(ctx context.Context, userID string) (*models.User, errors.Error)
}
type Deps struct {
Logger *zap.Logger
ConfigurationGRPC *models.ConfigurationGRPC
PaymentClient paymentClient
AuthClient authClient
}
type Service struct {
logger *zap.Logger
configurationGRPC *models.ConfigurationGRPC
paymentClient paymentClient
authClient authClient
}
func New(deps Deps) *Service {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (payment service)>")
}
if deps.ConfigurationGRPC == nil {
log.Panicln("ConfigurationGRPC is nil on <New (payment service)>")
}
if deps.PaymentClient == nil {
log.Panicln("PaymentClient is nil on <New (payment service)>")
}
if deps.AuthClient == nil {
log.Panicln("AuthClient is nil on <New (payment service)>")
}
return &Service{
logger: deps.Logger,
paymentClient: deps.PaymentClient,
authClient: deps.AuthClient,
configurationGRPC: deps.ConfigurationGRPC,
}
}
func (receiver *Service) GetPaymentLink(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
if _, userErr := receiver.authClient.GetUser(ctx, request.UserID); userErr != nil {
receiver.logger.Error("failed to get user on <GetPaymentLink> on <PaymentService>",
zap.Error(userErr),
zap.String("userID", request.UserID),
)
return "", userErr
}
switch request.Body.Type {
case models.PaymentTypeBankCard:
return receiver.GetPaymentLinkBankCard(ctx, request)
case models.PaymentTypeYoomoney:
return receiver.GetPaymentLinkYooMoney(ctx, request)
case models.PaymentTypeQiwi:
return receiver.GetPaymentLinkQIWI(ctx, request)
case models.PaymentTypeSberPay:
return receiver.GetPaymentLinkSberPay(ctx, request)
case models.PaymentTypeAlfabank:
return receiver.GetPaymentLinkAlfaClick(ctx, request)
case models.PaymentTypeTinkoff:
return receiver.GetPaymentLinkTinkoff(ctx, request)
case models.PaymentTypeMobile:
return receiver.GetPaymentLinkMobile(ctx, request)
case models.PaymentTypeCash:
return receiver.GetPaymentLinkCash(ctx, request)
}
return "", errors.NewWithMessage("invalid payment method type", errors.ErrInvalidArgs)
}
func (receiver *Service) GetPaymentLinkBankCard(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
link, err := receiver.paymentClient.GetPaymentLinkBankCard(ctx, &treasurer.GetBankCardPaymentLinkRequest{
MainSettings: &treasurer.MainPaymentSettings{
Currency: request.Body.Currency,
Amount: request.Body.Amount,
UserID: request.UserID,
ClientIP: request.ClientIP,
CallbackHostGRPC: []string{receiver.configurationGRPC.Domen},
ReturnURL: request.Body.ReturnURL,
},
BankCard: &treasurer.BankCardInformation{
Number: request.Body.BankCard.Number,
ExpiryYear: request.Body.BankCard.ExpiryYear,
ExpiryMonth: request.Body.BankCard.ExpiryMonth,
},
})
if err != nil {
receiver.logger.Error("failed to get bankcard payment link on <GetPaymentLinkBankCard> of <PaymentService>", zap.Error(err))
return "", err
}
return link, nil
}
func (receiver *Service) GetPaymentLinkYooMoney(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
link, err := receiver.paymentClient.GetPaymentLinkYooMoney(ctx, &treasurer.GetPaymentLinkBody{
MainSettings: &treasurer.MainPaymentSettings{
Currency: request.Body.Currency,
Amount: request.Body.Amount,
UserID: request.UserID,
ClientIP: request.ClientIP,
CallbackHostGRPC: []string{receiver.configurationGRPC.Domen},
ReturnURL: request.Body.ReturnURL,
},
})
if err != nil {
receiver.logger.Error("failed to get yoomoney payment link on <GetPaymentLinkYooMoney> of <PaymentService>", zap.Error(err))
return "", err
}
return link, nil
}
func (receiver *Service) GetPaymentLinkQIWI(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
link, err := receiver.paymentClient.GetPaymentLinkQIWI(ctx, &treasurer.GetPhonePaymentLinkRequest{
MainSettings: &treasurer.MainPaymentSettings{
Currency: request.Body.Currency,
Amount: request.Body.Amount,
UserID: request.UserID,
ClientIP: request.ClientIP,
CallbackHostGRPC: []string{receiver.configurationGRPC.Domen},
ReturnURL: request.Body.ReturnURL,
},
Phone: request.Body.PhoneNumber,
})
if err != nil {
receiver.logger.Error("failed to get qiwi payment link on <GetPaymentLinkQIWI> of <PaymentService>", zap.Error(err))
return "", err
}
return link, nil
}
func (receiver *Service) GetPaymentLinkSberPay(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
link, err := receiver.paymentClient.GetPaymentLinkSberPay(ctx, &treasurer.GetPhonePaymentLinkRequest{
MainSettings: &treasurer.MainPaymentSettings{
Currency: request.Body.Currency,
Amount: request.Body.Amount,
UserID: request.UserID,
ClientIP: request.ClientIP,
CallbackHostGRPC: []string{receiver.configurationGRPC.Domen},
ReturnURL: request.Body.ReturnURL,
},
Phone: request.Body.PhoneNumber,
})
if err != nil {
receiver.logger.Error("failed to get sberpay payment link on <GetPaymentLinkSberPay> of <PaymentService>", zap.Error(err))
return "", err
}
return link, nil
}
func (receiver *Service) GetPaymentLinkAlfaClick(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
link, err := receiver.paymentClient.GetPaymentLinkAlfaClick(ctx, &treasurer.GetLoginPaymentLinkRequest{
MainSettings: &treasurer.MainPaymentSettings{
Currency: request.Body.Currency,
Amount: request.Body.Amount,
UserID: request.UserID,
ClientIP: request.ClientIP,
CallbackHostGRPC: []string{receiver.configurationGRPC.Domen},
ReturnURL: request.Body.ReturnURL,
},
Login: request.Body.Login,
})
if err != nil {
receiver.logger.Error("failed to get alfaclick payment link on <GetPaymentLinkAlfaClick> of <PaymentService>", zap.Error(err))
return "", err
}
return link, nil
}
func (receiver *Service) GetPaymentLinkTinkoff(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
link, err := receiver.paymentClient.GetPaymentLinkTinkoff(ctx, &treasurer.GetPaymentLinkBody{
MainSettings: &treasurer.MainPaymentSettings{
Currency: request.Body.Currency,
Amount: request.Body.Amount,
UserID: request.UserID,
ClientIP: request.ClientIP,
CallbackHostGRPC: []string{receiver.configurationGRPC.Domen},
ReturnURL: request.Body.ReturnURL,
},
})
if err != nil {
receiver.logger.Error("failed to get tinkoff payment link on <GetPaymentLinkTinkoff> of <PaymentService>", zap.Error(err))
return "", err
}
return link, nil
}
func (receiver *Service) GetPaymentLinkMobile(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
link, err := receiver.paymentClient.GetPaymentLinkMobile(ctx, &treasurer.GetPhonePaymentLinkRequest{
MainSettings: &treasurer.MainPaymentSettings{
Currency: request.Body.Currency,
Amount: request.Body.Amount,
UserID: request.UserID,
ClientIP: request.ClientIP,
CallbackHostGRPC: []string{receiver.configurationGRPC.Domen},
ReturnURL: request.Body.ReturnURL,
},
Phone: request.Body.PhoneNumber,
})
if err != nil {
receiver.logger.Error("failed to get mobile payment link on <GetPaymentLinkMobile> of <PaymentService>", zap.Error(err))
return "", err
}
return link, nil
}
func (receiver *Service) GetPaymentLinkCash(ctx context.Context, request *models.GetPaymentLinkRequest) (string, errors.Error) {
link, err := receiver.paymentClient.GetPaymentLinkCash(ctx, &treasurer.GetPhonePaymentLinkRequest{
MainSettings: &treasurer.MainPaymentSettings{
Currency: request.Body.Currency,
Amount: request.Body.Amount,
UserID: request.UserID,
ClientIP: request.ClientIP,
CallbackHostGRPC: []string{receiver.configurationGRPC.Domen},
ReturnURL: request.Body.ReturnURL,
},
Phone: request.Body.PhoneNumber,
})
if err != nil {
receiver.logger.Error("failed to get cash payment link on <GetPaymentLinkCash> of <PaymentService>", zap.Error(err))
return "", err
}
return link, nil
}

@ -0,0 +1,249 @@
package wallet
import (
"context"
"fmt"
"log"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/validate"
)
type accountRepository interface {
ChangeWallet(ctx context.Context, userID string, wallet *models.Wallet) (*models.Account, errors.Error)
FindByUserID(ctx context.Context, id string) (*models.Account, errors.Error)
}
type currencyClient interface {
Translate(context.Context, *models.TranslateCurrency) (int64, errors.Error)
}
type historyService interface {
CreateHistory(ctx context.Context, history *models.History) (*models.History, errors.Error)
}
type Deps struct {
Logger *zap.Logger
Repository accountRepository
CurrencyClient currencyClient
HistoryService historyService
}
type Service struct {
logger *zap.Logger
repository accountRepository
currencyClient currencyClient
historyService historyService
}
func New(deps Deps) *Service {
if deps.Logger == nil {
log.Panicln("logger is nil on <New (wallet service)>")
}
if deps.Repository == nil {
log.Panicln("repository is nil on <New (wallet service)>")
}
if deps.CurrencyClient == nil {
log.Panicln("CurrencyClient is nil on <New (wallet service)>")
}
if deps.HistoryService == nil {
log.Panicln("HistoryService is nil on <New (wallet service)>")
}
return &Service{
logger: deps.Logger,
repository: deps.Repository,
currencyClient: deps.CurrencyClient,
historyService: deps.HistoryService,
}
}
func (receiver *Service) ReplenishAccountWallet(ctx context.Context, request *models.ReplenishAccountWallet) (*models.Account, errors.Error) {
if validate.IsStringEmpty(request.Account.Wallet.Currency) {
return nil, errors.New(
fmt.Errorf("currency of account <%s> is empty <ReplenishAccountWallet> of <WalletService>", request.Account.UserID),
errors.ErrInternalError,
)
}
cash := request.Cash
if request.Currency != request.Account.Wallet.Currency {
translatedCash, translateErr := receiver.currencyClient.Translate(ctx, &models.TranslateCurrency{
Money: request.Cash,
From: request.Currency,
To: request.Account.Wallet.Currency,
})
if translateErr != nil {
receiver.logger.Error("failed to translate cash on <ReplenishAccountWallet> of <WalletService>",
zap.Error(translateErr),
)
return nil, translateErr
}
cash = translatedCash
}
if request.Currency == models.InternalCurrencyKey {
updatedAccount, changeErr := receiver.repository.ChangeWallet(ctx, request.Account.UserID, &models.Wallet{
Cash: request.Account.Wallet.Cash + cash,
Money: request.Account.Wallet.Money + request.Cash,
PurchasesAmount: request.Account.Wallet.PurchasesAmount + request.Cash,
Currency: request.Account.Wallet.Currency,
LastPaymentID: request.PaymentID,
})
if changeErr != nil {
receiver.logger.Error("failed to replenish wallet on <ReplenishAccountWallet> of <WalletService>",
zap.Error(changeErr),
zap.String("Currency", request.Account.Wallet.Currency),
zap.Int64("Money", request.Account.Wallet.Money+request.Cash),
zap.Int64("Cash", request.Account.Wallet.Cash+cash),
zap.Bool("Is currensy equal internal", request.Currency == models.InternalCurrencyKey),
)
return nil, changeErr
}
if _, historyErr := receiver.historyService.CreateHistory(ctx, &models.History{
Key: models.CustomerHistoryKeyReplenish,
UserID: request.Account.UserID,
Comment: "Успешное пополнение средств (Без конвертации валюты)",
}); historyErr != nil {
receiver.logger.Error("failed to insert history on <ReplenishAccountWallet> of <WalletService>", zap.Error(historyErr))
}
return updatedAccount, nil
}
money, err := receiver.currencyClient.Translate(ctx, &models.TranslateCurrency{
Money: request.Cash,
From: request.Currency,
To: models.InternalCurrencyKey,
})
if err != nil {
receiver.logger.Error("failed to translate money on <ReplenishAccountWallet> of <WalletService>",
zap.Error(err),
)
return nil, err
}
updatedAccount, err := receiver.repository.ChangeWallet(ctx, request.Account.UserID, &models.Wallet{
Cash: request.Account.Wallet.Cash + cash,
Money: request.Account.Wallet.Money + money,
PurchasesAmount: request.Account.Wallet.PurchasesAmount + money,
Spent: request.Account.Wallet.Spent,
Currency: request.Account.Wallet.Currency,
LastPaymentID: request.PaymentID,
})
if err != nil {
receiver.logger.Error("failed to replenish wallet on <ReplenishAccountWallet> of <WalletService>",
zap.Error(err),
zap.String("Currency", request.Account.Wallet.Currency),
zap.Int64("Money", request.Account.Wallet.Money+request.Cash),
zap.Int64("Cash", request.Account.Wallet.Cash+cash),
zap.Bool("Is currensy equal internal", request.Currency == models.InternalCurrencyKey),
)
return nil, err
}
if _, historyErr := receiver.historyService.CreateHistory(ctx, &models.History{
Key: models.CustomerHistoryKeyReplenish,
UserID: request.Account.UserID,
Comment: "Успешное пополнение средств (C конвертацией валюты)",
}); historyErr != nil {
receiver.logger.Error("failed to insert history on <ReplenishAccountWallet> of <WalletService>", zap.Error(historyErr))
}
return updatedAccount, nil
}
func (receiver *Service) WithdrawAccountWalletMoney(ctx context.Context, request *models.WithdrawAccountWallet) (*models.Account, errors.Error) {
if validate.IsStringEmpty(request.Account.Wallet.Currency) {
return nil, errors.New(
fmt.Errorf("currency of account <%s> is empty <WithdrawAccountWalletMoney> of <WalletService>", request.Account.UserID),
errors.ErrInternalError,
)
}
cash, err := receiver.currencyClient.Translate(ctx, &models.TranslateCurrency{
Money: request.Money,
From: models.InternalCurrencyKey,
To: request.Account.Wallet.Currency,
})
if err != nil {
receiver.logger.Error("failed to translate money on <WithdrawAccountWalletMoney> of <WalletService>",
zap.Error(err),
)
return nil, err
}
updatedAccount, err := receiver.repository.ChangeWallet(ctx, request.Account.UserID, &models.Wallet{
Cash: request.Account.Wallet.Cash - cash,
Money: request.Account.Wallet.Money - request.Money,
Spent: request.Account.Wallet.Spent + request.Money,
PurchasesAmount: request.Account.Wallet.PurchasesAmount,
Currency: request.Account.Wallet.Currency,
})
if err != nil {
receiver.logger.Error("failed to replenish wallet on <ReplenishAccountWallet> of <WalletService>",
zap.Error(err),
zap.String("Currency", request.Account.Wallet.Currency),
zap.Int64("Money", request.Account.Wallet.Money-request.Money),
zap.Int64("Cash", request.Account.Wallet.Cash+cash),
)
return nil, err
}
return updatedAccount, nil
}
func (receiver *Service) ChangeCurrency(ctx context.Context, userID string, currency models.CurrencyKey) (*models.Account, errors.Error) {
account, err := receiver.repository.FindByUserID(ctx, userID)
if err != nil {
receiver.logger.Error("failed to find account on <ChangeCurrency> of <WalletService>",
zap.Error(err),
zap.String("userID", userID),
zap.Any("currency", currency),
)
return nil, err
}
cash, err := receiver.currencyClient.Translate(ctx, &models.TranslateCurrency{
Money: account.Wallet.Cash,
From: account.Wallet.Currency,
To: currency,
})
if err != nil {
receiver.logger.Error("failed to translate currency on <ChangeCurrency> of <WalletService>",
zap.Error(err),
)
return nil, err
}
updatedAccount, err := receiver.repository.ChangeWallet(ctx, account.UserID, &models.Wallet{
Cash: cash,
Currency: currency,
Money: account.Wallet.Money,
})
if err != nil {
receiver.logger.Error("failed to update wallet on <ChangeCurrency> of <WalletService>",
zap.Error(err),
)
return nil, err
}
return updatedAccount, nil
}

@ -0,0 +1,71 @@
package utils
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/deepmap/oapi-codegen/pkg/middleware"
"github.com/getkin/kin-openapi/openapi3filter"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)
const (
prefix = "Bearer "
)
func NewAuthenticator(jwtUtil *JWT) openapi3filter.AuthenticationFunc {
return func(ctx context.Context, input *openapi3filter.AuthenticationInput) error {
if jwtUtil == nil {
return errors.New(
fmt.Errorf("jwt util is nil: %w", errors.ErrInvalidArgs),
errors.ErrInvalidArgs,
)
}
return authenticate(ctx, jwtUtil, input)
}
}
func authenticate(ctx context.Context, jwtUtil *JWT, input *openapi3filter.AuthenticationInput) error {
if input.SecuritySchemeName != "Bearer" {
return fmt.Errorf("security scheme %s != 'Bearer'", input.SecuritySchemeName)
}
// Now, we need to get the JWS from the request, to match the request expectations
// against request contents.
jws, err := parseJWSFromRequest(input.RequestValidationInput.Request)
if err != nil {
return err
}
// if the JWS is valid, we have a JWT, which will contain a bunch of claims.
token, validateErr := jwtUtil.Validate(jws)
if validateErr != nil {
return validateErr
}
// Set the property on the echo context so the handler is able to
// access the claims data we generate in here.
echoCtx := middleware.GetEchoContext(ctx)
echoCtx.Set(models.AuthJWTDecodedUserIDKey, token)
return nil
}
// extracts a JWS string from an Authorization: Bearer <jws> header.
func parseJWSFromRequest(request *http.Request) (string, errors.Error) {
header := request.Header.Get("Authorization")
if header == "" || !strings.HasPrefix(header, prefix) {
return "", errors.New(
fmt.Errorf("failed to parse jws from request header: %s", header),
errors.ErrNoAccess,
)
}
return strings.TrimPrefix(header, prefix), nil
}

@ -0,0 +1,24 @@
package utils
import (
"net/http"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
)
var clientErrors = map[int]error{
http.StatusInternalServerError: errors.ErrInternalError,
http.StatusBadRequest: errors.ErrInvalidArgs,
http.StatusNotImplemented: errors.ErrMethodNotImplemented,
http.StatusNotFound: errors.ErrNotFound,
http.StatusForbidden: errors.ErrNoAccess,
}
func DetermineClientErrorResponse(statusCode int) error {
err, ok := clientErrors[statusCode]
if !ok {
return errors.ErrInternalError
}
return err
}

90
internal/utils/jwt.go Normal file

@ -0,0 +1,90 @@
package utils
import (
"errors"
"fmt"
"time"
"github.com/golang-jwt/jwt/v5"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)
type JWT struct {
privateKey []byte
publicKey []byte
algorithm *jwt.SigningMethodRSA
expiresIn time.Duration
issuer string
audience string
}
func NewJWT(configuration *models.JWTConfiguration) *JWT {
return &JWT{
privateKey: []byte(configuration.PrivateKey),
publicKey: []byte(configuration.PublicKey),
algorithm: &configuration.Algorithm,
expiresIn: configuration.ExpiresIn,
issuer: configuration.Issuer,
audience: configuration.Audience,
}
}
func (receiver *JWT) Create(id string) (string, error) {
privateKey, err := jwt.ParseRSAPrivateKeyFromPEM(receiver.privateKey)
if err != nil {
return "", fmt.Errorf("failed to parse private key on <Create> of <JWT>: %w", err)
}
now := time.Now().UTC()
claims := jwt.MapClaims{
"id": id, // Our userID
"exp": now.Add(receiver.expiresIn).Unix(), // The expiration time after which the token must be disregarded.
"aud": receiver.audience, // Audience
"iss": receiver.issuer, // Issuer
}
token, err := jwt.NewWithClaims(receiver.algorithm, claims).SignedString(privateKey)
if err != nil {
return "", fmt.Errorf("failed to sing on <Create> of <JWT>: %w", err)
}
return token, nil
}
func (receiver *JWT) Validate(tokenString string) (string, error) {
key, err := jwt.ParseRSAPublicKeyFromPEM(receiver.publicKey)
if err != nil {
return "", fmt.Errorf("failed to parse rsa public key on <Validate> of <JWT>: %w", err)
}
parseCallback := func(token *jwt.Token) (any, error) {
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
return nil, fmt.Errorf("unexpected signing method: %s", token.Header["alg"])
}
return key, nil
}
token, err := jwt.Parse(
tokenString,
parseCallback,
jwt.WithAudience(receiver.audience),
jwt.WithIssuer(receiver.issuer),
)
if err != nil {
return "", fmt.Errorf("failed to parse jwt token on <Validate> of <JWT>: %w", err)
}
claims, ok := token.Claims.(jwt.MapClaims)
if !ok || !token.Valid {
return "", errors.New("token is invalid on <Validate> of <JWT>")
}
data, ok := claims["id"].(string)
if !ok {
return "", errors.New("data is empty or not a string on <Validate> of <JWT>")
}
return data, nil
}

129
internal/utils/jwt_test.go Normal file

@ -0,0 +1,129 @@
package utils_test
import (
"strings"
"testing"
"time"
"github.com/golang-jwt/jwt/v5"
"github.com/stretchr/testify/assert"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
)
func TestJWT(t *testing.T) {
type user struct {
Name string `json:"name"`
Age int `json:"age"`
}
testUser := user{
Name: "test",
Age: 80,
}
publicKey := `-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyt4XuLovUY7i12K2PIMb
QZOKn+wFFKUvxvKQDel049/+VMpHMx1FLolUKuyGp9zi6gOwjHsBPgc9oqr/eaXG
QSh7Ult7i9f+Ht563Y0er5UU9Zc5ZPSxf9O75KYD48ruGkqiFoncDqPENK4dtUa7
w0OqlN4bwVBbmIsP8B3EDC5Dof+vtiNTSHSXPx+zifKeZGyknp+nyOHVrRDhPjOh
zQzCom0MSZA/sJYmps8QZgiPA0k4Z6jTupDymPOIwYeD2C57zSxnAv0AfC3/pZYJ
bZYH/0TszRzmy052DME3zMnhMK0ikdN4nzYqU0dkkA5kb5GtKDymspHIJ9eWbUuw
gtg8Rq/LrVBj1I3UFgs0ibio40k6gqinLKslc5Y1I5mro7J3OSEP5eO/XeDLOLlO
JjEqkrx4fviI1cL3m5L6QV905xmcoNZG1+RmOg7D7cZQUf27TXqM381jkbNdktm1
JLTcMScxuo3vaRftnIVw70V8P8sIkaKY8S8HU1sQgE2LB9t04oog5u59htx2FHv4
B13NEm8tt8Tv1PexpB4UVh7PIualF6SxdFBrKbraYej72wgjXVPQ0eGXtGGD57j8
DUEzk7DK2OvIWhehlVqtiRnFdAvdBj2ynHT2/5FJ/Zpd4n5dKGJcQvy1U1qWMs+8
M7AHfWyt2+nZ04s48+bK3yMCAwEAAQ==
-----END PUBLIC KEY-----`
privateKey := `-----BEGIN RSA PRIVATE KEY-----
MIIJKQIBAAKCAgEAyt4XuLovUY7i12K2PIMbQZOKn+wFFKUvxvKQDel049/+VMpH
Mx1FLolUKuyGp9zi6gOwjHsBPgc9oqr/eaXGQSh7Ult7i9f+Ht563Y0er5UU9Zc5
ZPSxf9O75KYD48ruGkqiFoncDqPENK4dtUa7w0OqlN4bwVBbmIsP8B3EDC5Dof+v
tiNTSHSXPx+zifKeZGyknp+nyOHVrRDhPjOhzQzCom0MSZA/sJYmps8QZgiPA0k4
Z6jTupDymPOIwYeD2C57zSxnAv0AfC3/pZYJbZYH/0TszRzmy052DME3zMnhMK0i
kdN4nzYqU0dkkA5kb5GtKDymspHIJ9eWbUuwgtg8Rq/LrVBj1I3UFgs0ibio40k6
gqinLKslc5Y1I5mro7J3OSEP5eO/XeDLOLlOJjEqkrx4fviI1cL3m5L6QV905xmc
oNZG1+RmOg7D7cZQUf27TXqM381jkbNdktm1JLTcMScxuo3vaRftnIVw70V8P8sI
kaKY8S8HU1sQgE2LB9t04oog5u59htx2FHv4B13NEm8tt8Tv1PexpB4UVh7PIual
F6SxdFBrKbraYej72wgjXVPQ0eGXtGGD57j8DUEzk7DK2OvIWhehlVqtiRnFdAvd
Bj2ynHT2/5FJ/Zpd4n5dKGJcQvy1U1qWMs+8M7AHfWyt2+nZ04s48+bK3yMCAwEA
AQKCAgEAhodpK7MsFeWvQC3Rs6ctt/rjftHBPMOeP0wzg0ZBoau0uP264YaTjhy7
mAtp8H9matEvjrkzRbL/iJPk/wKTyjnSLfdEoqQFfOsEh09B/iXa1FIIWY569s2u
WB5PjgvQgdbkThX1vC+VuWmNgdz6Pq7su/Pea/+h/jKZyx2yGHHFn/QyzZH3dKD8
e3vGT8B4kRgKwrYVSf2Y+T+sXtdWgOfpWlT+RPpHgg7QauX9dexPClrP8M3gOmRM
vGkjU1NOd1m7939ugGjOnYrTcTdh4S4Q95L5hbuYwVGyrxqiqkdl8iWeOx4Fa287
+iXp5i3lJKdyMLCnytsp5GHu+2OqFKyYQli23eMEEiTq/7PrzJas0BD3LfuT55Ht
UCwI/pRdgHvc/xEHqr7eF0C3f+PPG9/C85StDbm9WqhCVQ9nGt2ezkLeUSM/DBAh
DgI/LDFqRwLlIDrhkTT7BJGz6+2cmHwV80+eGPG2WzjpI619qhqgqB0fGBjLlVcZ
qoHy0K6NXuBqaoPOQq0TGkhl3SjurSe9EXeZHrrCT3LcSAIT7ZYoZDYuIvKBj7Sh
7r/wdYS9nzsBhU0xeGzfAs+5yxDCp1/GzLK0H8LlJcjJOxqArtEzf55v7ZBB8erR
sqmbpGoQAwzwyw1zosmhzQwZRlAMPNi0yfnjfi8yQu4kZchyJyECggEBAOStATj0
JNYWrPoHSgdW+NkzMRNIjjkHkUM/zs9F1bIlYwYDzmduXUoLChCHcjbOyE2tsPi8
eFbyJ0vpMa0ZgoQmAnqUhYOwceu/tmI2CE7jLB2luq9oFhQIblKR6Fi8TyvPzn4N
Q4iD1I2VjffSSQher+hNVdLmpRkP8s2UiY7OQOZMBWKNqfORddQWcXp3Wrg2Lkbd
7KcAtaMLYWg2W3mRdz6dnsqjMomRMi5arhroG3CtIpb62uiEdq2ZwyGF/Awon/kr
/XnfRLQeH0xVFPuVS/EbP6Ipq0TiieElTh4erhUIbmLZg7B5Fe9z1c528GUzTxhP
geQwN3bS5q71/f8CggEBAOMbosN7S+merANPzCOnRruLDPXukW+u20t/8CrOibJM
MO0embITOJfEdG4jBVRwnm5qacojuzFwfD7C18fJ1Hty010yQkjnB/zch3i8Fjx1
vtsWnYOfbViuIzuEi+9bPWRlMZh504zDjgqo8P24JU5qziw/ySLfMZAX7iNsohRB
R+bBdP933kPoCo5ehSj4QyVgRIWN751x5sZ0eyCUTZIw9OswuOmsmnlw4nMsqWIx
OXlARVkbA97+1pp21pAromekE/bzN8Qo4pn4inZTTy9yAeAvSp+vScCiaVJ4n+ag
WAgLeQBLxqRCU6BMvKiRjQ8dBMAn1DjKCrlV+5zFZt0CggEAd8TZEBBnPq4vuOCa
eE+oFHKIcJYez2XUQkmoMs1byGtmet8BexDF0aMIiXG3c1dId87SEuT7jmZUCKFB
gG0M+9PAlp01dKy0bgpCJxwvq8m18G094uL8NU/ZIGwFKnyuZr73YvPlfBm3+NPs
wHCmCbk2HtBqdASTUhYVUHFMvrvuJ/CHHYAfFFAKS6PZmY/rtvHBuSJA8ZMgjx3F
zcQykvCKaQQ7B90D+iNPChI6gCMzRAeaR0Np5kCCvBf9qJA5W9DnQKU2pF8457Gj
KOKjE8W1ObnQ0UlLx89y8bYNPR9Kg/+feSx9ma9BuuGLiRCohgiik5QI7xAF7Lk3
U0nJ1wKCAQAmkbjwre3UfSgFX/XxUCVJEHJhCeUVLIL9rXqiKnVkHGBqxLmhbnY8
ABct5TCwiHe/lL7mn27ZFJtlJT30Jii51mRi/XgYXXQT03gGXxr/pZeGKa8SfW7a
kqhVIUuKmNoyRKVJmdb9nvBuiwZycGWVjbn59dM44uLN7+J3jalw+y002UH/aOIM
cknop9DBhngQzuqUK+i3unJQ3dNTUxxhaYMOtjWRKckKOsuad8lEbcuu9eVRHq9n
navgi7IgxehM5aamV+PuomrpbzZEph1al2gOJLntqJ1D49EzOl0dk7mflCM2k6fm
mYUOQjn//sgP+wOlhp4aDuYHV7zlgPjZAoIBAQDXPUl6NeA2ZMWbSO+WRc8zzjQ9
qyxRA7g3ZSu+E5OqkxfwayXr/kAVKQNHJvn5wr9rLFhEF6CkBJ7XgOrHN0RjgXq2
z0DpwG5JEFMeqkQWI+rVJ+ZJ4g0SAa9k39+WDxQhpZM8/IlkuIYqRI0mlcHwxhkG
7JhkLtELhlxaGobAIinWiskKqX85tzZtCLe1wkErWOCueWviiuoCY2HWfELoA5+4
wAvKspBO6oa+R2JtjA0nE72jKWuIz4m0QaCE7yInyCG9ikrBHSh/85eMu37nqegU
ziOydfDNcQp17fBjy8NVeQBjdjxVYejl8pKAVcQP9iM4vIyRIx0Ersv1fySA
-----END RSA PRIVATE KEY-----`
publicKey = strings.Replace(publicKey, "\t", "", -1)
privateKey = strings.Replace(privateKey, "\t", "", -1)
jwt := utils.NewJWT(&models.JWTConfiguration{
PrivateKey: privateKey,
PublicKey: publicKey,
Algorithm: *jwt.SigningMethodRS256,
ExpiresIn: 15 * time.Minute,
Issuer: "issuer1",
Audience: "audience1",
})
t.Run("Успешная генерация токена", func(t *testing.T) {
assert.NotPanics(t, func() {
token, err := jwt.Create(testUser.Name)
assert.NoError(t, err)
assert.NotZero(t, token)
assert.NotEmpty(t, token)
})
})
t.Run("Успешная валидация токена", func(t *testing.T) {
assert.NotPanics(t, func() {
token, err := jwt.Create(testUser.Name)
isNoError := assert.NoError(t, err)
if isNoError {
parsedUser, err := jwt.Validate(token)
assert.NoError(t, err)
assert.NotNil(t, parsedUser)
assert.Equal(t, testUser.Name, parsedUser)
}
})
})
}

@ -0,0 +1,38 @@
package utils
import "penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
func DeterminePagination(page, limit interface{}) *models.Pagination {
determinePage := func() int64 {
if page == nil {
return models.DefaultPageNumber
}
pageNumber, isPageNumberOK := page.(int64)
if !isPageNumberOK || pageNumber < 1 {
return models.DefaultPageNumber
}
return pageNumber
}
determineLimit := func() int64 {
if limit == nil {
return models.DefaultLimit
}
limitNumber, isLimitNumberOK := limit.(int64)
if !isLimitNumberOK || limitNumber > models.DefaultLimit || limitNumber < 1 {
return models.DefaultLimit
}
return limitNumber
}
return &models.Pagination{
Page: determinePage(),
Limit: determineLimit(),
}
}

62
internal/utils/payment.go Normal file

@ -0,0 +1,62 @@
package utils
import (
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/validate"
)
func ValidateGetPaymentLinkBody(request *models.GetPaymentLinkBody) errors.Error {
if request == nil {
return errors.NewWithMessage("request body is empty", errors.ErrInvalidArgs)
}
switch request.Type {
case models.PaymentTypeInstallments, models.PaymentTypeSBP, models.PaymentTypeTinkoff, models.PaymentTypeYoomoney:
return nil
case models.PaymentTypeQiwi, models.PaymentTypeSberPay, models.PaymentTypeMobile, models.PaymentTypeCash:
return validateMobilePayment(request)
case models.PaymentTypeAlfabank:
return validateLoginPayment(request)
case models.PaymentTypeBankCard:
return validateBankcardPayment(request)
default:
return errors.NewWithMessage("unknown payment type", errors.ErrInvalidArgs)
}
}
func validateMobilePayment(request *models.GetPaymentLinkBody) errors.Error {
if validate.IsStringEmpty(request.PhoneNumber) {
return errors.NewWithMessage("phone number is empty", errors.ErrInvalidArgs)
}
return nil
}
func validateLoginPayment(request *models.GetPaymentLinkBody) errors.Error {
if validate.IsStringEmpty(request.Login) {
return errors.NewWithMessage("login is empty", errors.ErrInvalidArgs)
}
return nil
}
func validateBankcardPayment(request *models.GetPaymentLinkBody) errors.Error {
if request.BankCard == nil {
return errors.NewWithMessage("bank card is empty", errors.ErrInvalidArgs)
}
if validate.IsStringEmpty(request.BankCard.Number) {
return errors.NewWithMessage("bankcard number is empty", errors.ErrInvalidArgs)
}
if validate.IsStringEmpty(request.BankCard.ExpiryYear) {
return errors.NewWithMessage("bankcard expiry year is empty", errors.ErrInvalidArgs)
}
if validate.IsStringEmpty(request.BankCard.ExpiryMonth) {
return errors.NewWithMessage("bankcard expiry month is empty", errors.ErrInvalidArgs)
}
return nil
}

Some files were not shown because too many files have changed in this diff Show More