feat: mocks service
This commit is contained in:
parent
d7534b3d23
commit
db62b73335
100
.gitlab-ci.yml
Normal file
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 ./...
|
||||||
|
- 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
|
@ -25,6 +25,11 @@ MONGO_DB_NAME - название базы данных для подключе
|
|||||||
MONGO_PASSWORD - пароль пользователя MongoDB
|
MONGO_PASSWORD - пароль пользователя MongoDB
|
||||||
MONGO_AUTH - имя базы данных Mongo, по которой будет производится авторизация
|
MONGO_AUTH - имя базы данных Mongo, по которой будет производится авторизация
|
||||||
|
|
||||||
|
IS_MOCK - отвечает за инициализацию настроек моков в моковом сервисе (true | false)
|
||||||
|
MOCK_SERVICE_HOST - хост сервиса моков
|
||||||
|
|
||||||
YOOMONEY_STORE_ID - id магазина, зарегистрированного на yoomoney
|
YOOMONEY_STORE_ID - id магазина, зарегистрированного на yoomoney
|
||||||
YOOMONEY_SECRET_KEY - секретный ключ yoomoney
|
YOOMONEY_SECRET_KEY - секретный ключ yoomoney
|
||||||
|
YOOMONEY_WEBHOOKS_URL - адрес к обработчику вебхуков yoomoney
|
||||||
|
YOOMONEY_PAYMENTS_URL - адрес к обработчику платажей yoomoney
|
||||||
```
|
```
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
func MockWebhooks() {}
|
|
@ -11,13 +11,18 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- HTTP_HOST=0.0.0.0
|
- HTTP_HOST=0.0.0.0
|
||||||
- HTTP_PORT=8085
|
- HTTP_PORT=8085
|
||||||
- HTTP_DOMEN=http://localhost:8080
|
- HTTP_DOMEN=http://localhost:8085
|
||||||
|
|
||||||
- GRPC_HOST=0.0.0.0
|
- GRPC_HOST=0.0.0.0
|
||||||
- GRPC_PORT=9085
|
- GRPC_PORT=9085
|
||||||
|
|
||||||
|
- IS_MOCK=true
|
||||||
|
- MOCK_SERVICE_HOST=http://treasurer-mock:8080
|
||||||
|
|
||||||
- YOOMONEY_STORE_ID=id
|
- YOOMONEY_STORE_ID=id
|
||||||
- YOOMONEY_SECRET_KEY=secret
|
- YOOMONEY_SECRET_KEY=secret
|
||||||
|
- YOOMONEY_WEBHOOKS_URL=http://treasurer-mock:8080/webhooks
|
||||||
|
- YOOMONEY_PAYMENTS_URL=http://treasurer-mock:8080/payments
|
||||||
|
|
||||||
- MONGO_HOST=mongo
|
- MONGO_HOST=mongo
|
||||||
- MONGO_PORT=27017
|
- MONGO_PORT=27017
|
||||||
|
56
deployments/staging/docker-compose.yaml
Normal file
56
deployments/staging/docker-compose.yaml
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
version: "3.3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
treasurer-app:
|
||||||
|
container_name: treasurer-service
|
||||||
|
tty: true
|
||||||
|
build:
|
||||||
|
context: ../../.
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
target: production
|
||||||
|
environment:
|
||||||
|
- HTTP_HOST=0.0.0.0
|
||||||
|
- HTTP_PORT=8085
|
||||||
|
- HTTP_DOMEN=http://localhost:8085
|
||||||
|
|
||||||
|
- GRPC_HOST=0.0.0.0
|
||||||
|
- GRPC_PORT=9085
|
||||||
|
|
||||||
|
- IS_MOCK=true
|
||||||
|
- MOCK_SERVICE_HOST=http://treasurer-mock:8080
|
||||||
|
|
||||||
|
- YOOMONEY_STORE_ID=id
|
||||||
|
- YOOMONEY_SECRET_KEY=secret
|
||||||
|
- YOOMONEY_WEBHOOKS_URL=http://treasurer-mock:8080/webhooks
|
||||||
|
- YOOMONEY_PAYMENTS_URL=http://treasurer-mock:8080/payments
|
||||||
|
|
||||||
|
- MONGO_HOST=mongo
|
||||||
|
- MONGO_PORT=27017
|
||||||
|
- MONGO_USER=test
|
||||||
|
- MONGO_PASSWORD=test
|
||||||
|
- MONGO_DB_NAME=admin
|
||||||
|
- MONGO_AUTH=admin
|
||||||
|
ports:
|
||||||
|
- 8085:8085
|
||||||
|
- 9085:9085
|
||||||
|
networks:
|
||||||
|
- backend_external
|
||||||
|
- default
|
||||||
|
depends_on:
|
||||||
|
- treasurer-mock
|
||||||
|
|
||||||
|
treasurer-mock:
|
||||||
|
container_name: treasurermock-container
|
||||||
|
image: 'wiremock/wiremock:2.35.0'
|
||||||
|
ports:
|
||||||
|
- 8080:8080
|
||||||
|
networks:
|
||||||
|
- backend_external
|
||||||
|
- default
|
||||||
|
|
||||||
|
networks:
|
||||||
|
backend_external:
|
||||||
|
driver: bridge
|
||||||
|
attachable: true
|
||||||
|
internal: true
|
||||||
|
|
@ -8,26 +8,31 @@ services:
|
|||||||
target: test
|
target: test
|
||||||
environment:
|
environment:
|
||||||
- HTTP_HOST=0.0.0.0
|
- HTTP_HOST=0.0.0.0
|
||||||
- HTTP_PORT=8080
|
- HTTP_PORT=8085
|
||||||
- HTTP_DOMEN=http://localhost:8080
|
- HTTP_DOMEN=http://localhost:8085
|
||||||
|
|
||||||
- GRPC_HOST=0.0.0.0
|
- GRPC_HOST=0.0.0.0
|
||||||
- GRPC_PORT=8081
|
- GRPC_PORT=9085
|
||||||
|
|
||||||
- YOOMONEY_STORE_ID=storeid
|
- IS_MOCK=false
|
||||||
|
- MOCK_SERVICE_HOST=http://mock:8080
|
||||||
|
|
||||||
|
- YOOMONEY_STORE_ID=id
|
||||||
- YOOMONEY_SECRET_KEY=secret
|
- YOOMONEY_SECRET_KEY=secret
|
||||||
|
- YOOMONEY_WEBHOOKS_URL=http://mock:8080/webhooks
|
||||||
|
- YOOMONEY_PAYMENTS_URL=http://mock:8080/payments
|
||||||
|
|
||||||
- MONGO_HOST=mongo
|
- MONGO_HOST=mongo
|
||||||
- MONGO_PORT=27017
|
- MONGO_PORT=27017
|
||||||
- MONGO_USER=admin
|
- MONGO_USER=test
|
||||||
- MONGO_PASSWORD=admin
|
- MONGO_PASSWORD=test
|
||||||
- MONGO_DB_NAME=admin
|
- MONGO_DB_NAME=admin
|
||||||
- MONGO_AUTH=admin
|
- MONGO_AUTH=admin
|
||||||
ports:
|
ports:
|
||||||
- 8080:8080
|
- 8080:8080
|
||||||
- 8081:8081
|
- 8081:8081
|
||||||
networks:
|
networks:
|
||||||
- dev
|
- integartion_test
|
||||||
depends_on:
|
depends_on:
|
||||||
- mongo
|
- mongo
|
||||||
|
|
||||||
@ -39,16 +44,16 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- '27017:27017'
|
- '27017:27017'
|
||||||
networks:
|
networks:
|
||||||
- dev
|
- integartion_test
|
||||||
|
|
||||||
mock:
|
mock:
|
||||||
image: 'wiremock/wiremock:2.35.0'
|
image: 'wiremock/wiremock:2.35.0'
|
||||||
ports:
|
ports:
|
||||||
- 8000:8080
|
- 8000:8080
|
||||||
networks:
|
networks:
|
||||||
- dev
|
- integartion_test
|
||||||
depends_on:
|
depends_on:
|
||||||
- treasurer-app
|
- treasurer-app
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
dev:
|
integartion_test:
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/interface/swagger"
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/interface/swagger"
|
||||||
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/models"
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/models"
|
||||||
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/server"
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/server"
|
||||||
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/worker"
|
||||||
"penahub.gitlab.yandexcloud.net/external/treasurer/pkg/closer"
|
"penahub.gitlab.yandexcloud.net/external/treasurer/pkg/closer"
|
||||||
"penahub.gitlab.yandexcloud.net/external/treasurer/pkg/mongo"
|
"penahub.gitlab.yandexcloud.net/external/treasurer/pkg/mongo"
|
||||||
)
|
)
|
||||||
@ -60,6 +61,15 @@ func Run(ctx context.Context, config *models.Config, logger *zap.Logger) error {
|
|||||||
return err.Wrap("failed to initialize services")
|
return err.Wrap("failed to initialize services")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
workers, err := initialize.NewWorkers(initialize.WorkersDeps{
|
||||||
|
Logger: logger,
|
||||||
|
Services: *services,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err.Wrap("failed to initialize workers")
|
||||||
|
}
|
||||||
|
|
||||||
controllers, err := initialize.NewControllers(initialize.ControllersDeps{
|
controllers, err := initialize.NewControllers(initialize.ControllersDeps{
|
||||||
Logger: logger,
|
Logger: logger,
|
||||||
Services: *services,
|
Services: *services,
|
||||||
@ -94,6 +104,7 @@ func Run(ctx context.Context, config *models.Config, logger *zap.Logger) error {
|
|||||||
|
|
||||||
go httpServer.Run(&config.HTTP)
|
go httpServer.Run(&config.HTTP)
|
||||||
go grpcServer.Run(&config.GRPC)
|
go grpcServer.Run(&config.GRPC)
|
||||||
|
go worker.Run(ctx, workers)
|
||||||
|
|
||||||
closer.Add(mongoDB.Client().Disconnect)
|
closer.Add(mongoDB.Client().Disconnect)
|
||||||
closer.Add(httpServer.Stop)
|
closer.Add(httpServer.Stop)
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/errors"
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/errors"
|
||||||
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/models"
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/models"
|
||||||
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/service/callback"
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/service/callback"
|
||||||
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/service/mock"
|
||||||
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/service/payment"
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/service/payment"
|
||||||
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/service/status"
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/service/status"
|
||||||
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/service/webhook"
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/service/webhook"
|
||||||
@ -15,6 +16,7 @@ type ServicesDeps struct {
|
|||||||
Repositories Repositories
|
Repositories Repositories
|
||||||
Clients Clients
|
Clients Clients
|
||||||
ConfigurationHTTP *models.ConfigurationHTTP
|
ConfigurationHTTP *models.ConfigurationHTTP
|
||||||
|
Configuration *models.ServiceConfiguration
|
||||||
}
|
}
|
||||||
|
|
||||||
type Services struct {
|
type Services struct {
|
||||||
@ -23,6 +25,7 @@ type Services struct {
|
|||||||
YandexPayment *payment.Yandex
|
YandexPayment *payment.Yandex
|
||||||
Status *status.Service
|
Status *status.Service
|
||||||
YandexWebhook *webhook.Yandex
|
YandexWebhook *webhook.Yandex
|
||||||
|
Mock *mock.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServices(deps ServicesDeps) (*Services, errors.Error) {
|
func NewServices(deps ServicesDeps) (*Services, errors.Error) {
|
||||||
@ -69,11 +72,30 @@ func NewServices(deps ServicesDeps) (*Services, errors.Error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
yoomoneyMockService, err := mock.NewYoomoneyMockService(mock.YoomoneyMockServiceDeps{
|
||||||
|
Logger: deps.Logger,
|
||||||
|
YoomoneyURL: &deps.Configuration.MockConfiguration.YoomomeyURL,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mockService, err := mock.New(mock.Deps{
|
||||||
|
Logger: deps.Logger,
|
||||||
|
Enabled: deps.Configuration.MockConfiguration.IsMock,
|
||||||
|
MockServiceHost: deps.Configuration.MockConfiguration.Host,
|
||||||
|
YoomoneyMockService: yoomoneyMockService,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &Services{
|
return &Services{
|
||||||
Callback: callbackService,
|
Callback: callbackService,
|
||||||
Payment: paymentService,
|
Payment: paymentService,
|
||||||
YandexPayment: yandexPaymentService,
|
YandexPayment: yandexPaymentService,
|
||||||
Status: statusService,
|
Status: statusService,
|
||||||
YandexWebhook: yandexWebhookService,
|
YandexWebhook: yandexWebhookService,
|
||||||
|
Mock: mockService,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
30
internal/initialize/workers.go
Normal file
30
internal/initialize/workers.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package initialize
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/errors"
|
||||||
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/worker/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WorkersDeps struct {
|
||||||
|
Logger *zap.Logger
|
||||||
|
Services Services
|
||||||
|
}
|
||||||
|
|
||||||
|
type Workers struct {
|
||||||
|
Mock *mock.Worker
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWorkers(deps WorkersDeps) (*Workers, errors.Error) {
|
||||||
|
mockWorker, err := mock.New(mock.WorkerDeps{
|
||||||
|
Logger: deps.Logger,
|
||||||
|
MockService: deps.Services.Mock,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Workers{
|
||||||
|
Mock: mockWorker,
|
||||||
|
}, nil
|
||||||
|
}
|
@ -13,19 +13,6 @@ import (
|
|||||||
"penahub.gitlab.yandexcloud.net/external/treasurer/pkg/client"
|
"penahub.gitlab.yandexcloud.net/external/treasurer/pkg/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
yandexPaymentsMockURL = "http://treasurer-mock:8080/payments"
|
|
||||||
yandexPaymentsProdURL = "https://api.yookassa.ru/v3/payments"
|
|
||||||
|
|
||||||
yandexWebhooksMockURL = "http://treasurer-mock:8080/webhooks"
|
|
||||||
yandexWebhooksProdURL = "https://api.yookassa.ru/v3/webhooks"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
yandexPaymentsURL = yandexPaymentsMockURL
|
|
||||||
yandexWebhooksURL = yandexWebhooksMockURL
|
|
||||||
)
|
|
||||||
|
|
||||||
type YandexClientDeps struct {
|
type YandexClientDeps struct {
|
||||||
Logger *zap.Logger
|
Logger *zap.Logger
|
||||||
Configuration *models.YoomomeyConfiguration
|
Configuration *models.YoomomeyConfiguration
|
||||||
@ -53,7 +40,7 @@ func NewYandexClient(deps YandexClientDeps) (*YandexClient, errors.Error) {
|
|||||||
|
|
||||||
func (receiver *YandexClient) CreatePayment(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodType]) (*yandex.Payment, errors.Error) {
|
func (receiver *YandexClient) CreatePayment(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodType]) (*yandex.Payment, errors.Error) {
|
||||||
response, err := client.Post[yandex.Payment, any](ctx, &client.RequestSettings{
|
response, err := client.Post[yandex.Payment, any](ctx, &client.RequestSettings{
|
||||||
URL: yandexPaymentsURL,
|
URL: receiver.configuration.URL.Payments,
|
||||||
Body: request,
|
Body: request,
|
||||||
Headers: map[string]string{
|
Headers: map[string]string{
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@ -75,7 +62,7 @@ func (receiver *YandexClient) CreatePayment(ctx context.Context, idempotenceKey
|
|||||||
|
|
||||||
func (receiver *YandexClient) CreatePaymentB2B(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodB2B]) (*yandex.Payment, errors.Error) {
|
func (receiver *YandexClient) CreatePaymentB2B(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodB2B]) (*yandex.Payment, errors.Error) {
|
||||||
response, err := client.Post[yandex.Payment, any](ctx, &client.RequestSettings{
|
response, err := client.Post[yandex.Payment, any](ctx, &client.RequestSettings{
|
||||||
URL: yandexPaymentsURL,
|
URL: receiver.configuration.URL.Payments,
|
||||||
Body: request,
|
Body: request,
|
||||||
Headers: map[string]string{
|
Headers: map[string]string{
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@ -97,7 +84,7 @@ func (receiver *YandexClient) CreatePaymentB2B(ctx context.Context, idempotenceK
|
|||||||
|
|
||||||
func (receiver *YandexClient) CreatePaymentBankCard(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodBankCard]) (*yandex.Payment, errors.Error) {
|
func (receiver *YandexClient) CreatePaymentBankCard(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodBankCard]) (*yandex.Payment, errors.Error) {
|
||||||
response, err := client.Post[yandex.Payment, any](ctx, &client.RequestSettings{
|
response, err := client.Post[yandex.Payment, any](ctx, &client.RequestSettings{
|
||||||
URL: yandexPaymentsURL,
|
URL: receiver.configuration.URL.Payments,
|
||||||
Body: request,
|
Body: request,
|
||||||
Headers: map[string]string{
|
Headers: map[string]string{
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@ -119,7 +106,7 @@ func (receiver *YandexClient) CreatePaymentBankCard(ctx context.Context, idempot
|
|||||||
|
|
||||||
func (receiver *YandexClient) CreatePaymentLogin(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodLogin]) (*yandex.Payment, errors.Error) {
|
func (receiver *YandexClient) CreatePaymentLogin(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodLogin]) (*yandex.Payment, errors.Error) {
|
||||||
response, err := client.Post[yandex.Payment, any](ctx, &client.RequestSettings{
|
response, err := client.Post[yandex.Payment, any](ctx, &client.RequestSettings{
|
||||||
URL: yandexPaymentsURL,
|
URL: receiver.configuration.URL.Payments,
|
||||||
Body: request,
|
Body: request,
|
||||||
Headers: map[string]string{
|
Headers: map[string]string{
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@ -141,7 +128,7 @@ func (receiver *YandexClient) CreatePaymentLogin(ctx context.Context, idempotenc
|
|||||||
|
|
||||||
func (receiver *YandexClient) CreatePaymentPhone(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodPhone]) (*yandex.Payment, errors.Error) {
|
func (receiver *YandexClient) CreatePaymentPhone(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodPhone]) (*yandex.Payment, errors.Error) {
|
||||||
response, err := client.Post[yandex.Payment, any](ctx, &client.RequestSettings{
|
response, err := client.Post[yandex.Payment, any](ctx, &client.RequestSettings{
|
||||||
URL: yandexPaymentsURL,
|
URL: receiver.configuration.URL.Payments,
|
||||||
Body: request,
|
Body: request,
|
||||||
Headers: map[string]string{
|
Headers: map[string]string{
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@ -162,11 +149,11 @@ func (receiver *YandexClient) CreatePaymentPhone(ctx context.Context, idempotenc
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (receiver *YandexClient) DeleteWebhook(ctx context.Context, webhookID string) errors.Error {
|
func (receiver *YandexClient) DeleteWebhook(ctx context.Context, webhookID string) errors.Error {
|
||||||
url, err := url.JoinPath(yandexWebhooksURL, webhookID)
|
url, err := url.JoinPath(receiver.configuration.URL.Webhooks, webhookID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
receiver.logger.Error("failed to join path url on <DeleteWebhook> of <YandexClient>",
|
receiver.logger.Error("failed to join path url on <DeleteWebhook> of <YandexClient>",
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.String("yandex webhook url", yandexWebhooksURL),
|
zap.String("yandex webhook url", receiver.configuration.URL.Webhooks),
|
||||||
zap.String("webhookID", webhookID),
|
zap.String("webhookID", webhookID),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -200,7 +187,7 @@ func (receiver *YandexClient) DeleteWebhook(ctx context.Context, webhookID strin
|
|||||||
|
|
||||||
func (receiver *YandexClient) GetWebhookEvents(ctx context.Context) ([]yandex.Webhook, errors.Error) {
|
func (receiver *YandexClient) GetWebhookEvents(ctx context.Context) ([]yandex.Webhook, errors.Error) {
|
||||||
response, err := client.Delete[[]yandex.Webhook, any](ctx, &client.RequestSettings{
|
response, err := client.Delete[[]yandex.Webhook, any](ctx, &client.RequestSettings{
|
||||||
URL: yandexWebhooksURL,
|
URL: receiver.configuration.URL.Webhooks,
|
||||||
Headers: map[string]string{
|
Headers: map[string]string{
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
||||||
@ -215,7 +202,7 @@ func (receiver *YandexClient) GetWebhookEvents(ctx context.Context) ([]yandex.We
|
|||||||
if response.Error != nil {
|
if response.Error != nil {
|
||||||
receiver.logger.Error("failed to delete webhook on <DeleteWebhook> of <YandexClient>",
|
receiver.logger.Error("failed to delete webhook on <DeleteWebhook> of <YandexClient>",
|
||||||
zap.Any("response", response.Error),
|
zap.Any("response", response.Error),
|
||||||
zap.String("url", yandexWebhooksURL),
|
zap.String("url", receiver.configuration.URL.Webhooks),
|
||||||
)
|
)
|
||||||
|
|
||||||
return []yandex.Webhook{}, errors.NewWithMessage("failed to create payment", errors.ErrInternalError)
|
return []yandex.Webhook{}, errors.NewWithMessage("failed to create payment", errors.ErrInternalError)
|
||||||
@ -226,7 +213,7 @@ func (receiver *YandexClient) GetWebhookEvents(ctx context.Context) ([]yandex.We
|
|||||||
|
|
||||||
func (receiver *YandexClient) SetWebhookEvent(ctx context.Context, idempotenceKey string, request *yandex.CreateWebhookRequest) (string, errors.Error) {
|
func (receiver *YandexClient) SetWebhookEvent(ctx context.Context, idempotenceKey string, request *yandex.CreateWebhookRequest) (string, errors.Error) {
|
||||||
response, err := client.Post[yandex.Webhook, any](ctx, &client.RequestSettings{
|
response, err := client.Post[yandex.Webhook, any](ctx, &client.RequestSettings{
|
||||||
URL: yandexWebhooksURL,
|
URL: receiver.configuration.URL.Webhooks,
|
||||||
Body: request,
|
Body: request,
|
||||||
Headers: map[string]string{
|
Headers: map[string]string{
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@ -243,7 +230,7 @@ func (receiver *YandexClient) SetWebhookEvent(ctx context.Context, idempotenceKe
|
|||||||
if response.Error != nil {
|
if response.Error != nil {
|
||||||
receiver.logger.Error("failed to delete webhook on <DeleteWebhook> of <YandexClient>",
|
receiver.logger.Error("failed to delete webhook on <DeleteWebhook> of <YandexClient>",
|
||||||
zap.Any("response", response.Error),
|
zap.Any("response", response.Error),
|
||||||
zap.String("url", yandexWebhooksURL),
|
zap.String("url", receiver.configuration.URL.Webhooks),
|
||||||
)
|
)
|
||||||
|
|
||||||
return "", errors.NewWithMessage("failed to create payment", errors.ErrInternalError)
|
return "", errors.NewWithMessage("failed to create payment", errors.ErrInternalError)
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
|
|
||||||
// ServerInterface represents all server handlers.
|
// ServerInterface represents all server handlers.
|
||||||
type ServerInterface interface {
|
type ServerInterface interface {
|
||||||
|
|
||||||
// (GET /available)
|
// (GET /available)
|
||||||
GetAvailablePayments(ctx echo.Context) error
|
GetAvailablePayments(ctx echo.Context) error
|
||||||
|
|
||||||
@ -123,32 +124,32 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
|
|||||||
// Base64 encoded, gzipped, json marshaled Swagger object
|
// Base64 encoded, gzipped, json marshaled Swagger object
|
||||||
var swaggerSpec = []string{
|
var swaggerSpec = []string{
|
||||||
|
|
||||||
"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",
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSwagger returns the content of the embedded swagger specification file
|
// GetSwagger returns the content of the embedded swagger specification file
|
||||||
|
@ -5,8 +5,8 @@ import (
|
|||||||
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/errors"
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate oapi-codegen --config api.yaml ../../openapi.yaml
|
//go:generate oapi-codegen --config api.yaml ../../../openapi.yaml
|
||||||
//go:generate oapi-codegen --config models.yaml ../../openapi.yaml
|
//go:generate oapi-codegen --config models.yaml ../../../openapi.yaml
|
||||||
|
|
||||||
type commonController interface {
|
type commonController interface {
|
||||||
// (GET /available)
|
// (GET /available)
|
||||||
|
@ -3,6 +3,14 @@
|
|||||||
// Code generated by github.com/deepmap/oapi-codegen version v1.12.4 DO NOT EDIT.
|
// Code generated by github.com/deepmap/oapi-codegen version v1.12.4 DO NOT EDIT.
|
||||||
package swagger
|
package swagger
|
||||||
|
|
||||||
|
// Defines values for Event.
|
||||||
|
const (
|
||||||
|
PaymentCanceled Event = "payment.canceled"
|
||||||
|
PaymentSucceeded Event = "payment.succeeded"
|
||||||
|
PaymentWaitingForCapture Event = "payment.waiting_for_capture"
|
||||||
|
RefundSucceeded Event = "refund.succeeded"
|
||||||
|
)
|
||||||
|
|
||||||
// Defines values for PaymentStatus.
|
// Defines values for PaymentStatus.
|
||||||
const (
|
const (
|
||||||
Canceled PaymentStatus = "canceled"
|
Canceled PaymentStatus = "canceled"
|
||||||
@ -20,6 +28,9 @@ type Amount struct {
|
|||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Event defines model for Event.
|
||||||
|
type Event string
|
||||||
|
|
||||||
// PaymentStatus defines model for PaymentStatus.
|
// PaymentStatus defines model for PaymentStatus.
|
||||||
type PaymentStatus string
|
type PaymentStatus string
|
||||||
|
|
||||||
@ -34,8 +45,7 @@ type Recipient struct {
|
|||||||
|
|
||||||
// SetPaymentStatusRequest defines model for SetPaymentStatusRequest.
|
// SetPaymentStatusRequest defines model for SetPaymentStatusRequest.
|
||||||
type SetPaymentStatusRequest struct {
|
type SetPaymentStatusRequest struct {
|
||||||
// Event Событие, о котором уведомляет ЮKassa
|
Event Event `json:"event"`
|
||||||
Event string `json:"event"`
|
|
||||||
Object YandexPayment `json:"object"`
|
Object YandexPayment `json:"object"`
|
||||||
|
|
||||||
// Type Тип объекта. Фиксированное значение — notification (уведомление)
|
// Type Тип объекта. Фиксированное значение — notification (уведомление)
|
||||||
|
@ -24,9 +24,22 @@ type ConfigurationGRPC struct {
|
|||||||
|
|
||||||
type ServiceConfiguration struct {
|
type ServiceConfiguration struct {
|
||||||
YoomomeyConfiguration YoomomeyConfiguration
|
YoomomeyConfiguration YoomomeyConfiguration
|
||||||
|
MockConfiguration MockConfiguration
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockConfiguration struct {
|
||||||
|
IsMock bool `env:"IS_MOCK,default=false"`
|
||||||
|
Host string `env:"MOCK_SERVICE_HOST,default=http://localhost:8080"`
|
||||||
|
YoomomeyURL YoomomeyURL
|
||||||
}
|
}
|
||||||
|
|
||||||
type YoomomeyConfiguration struct {
|
type YoomomeyConfiguration struct {
|
||||||
StoreID string `env:"YOOMONEY_STORE_ID,required"`
|
StoreID string `env:"YOOMONEY_STORE_ID,required"`
|
||||||
SecretKey string `env:"YOOMONEY_SECRET_KEY,required"`
|
SecretKey string `env:"YOOMONEY_SECRET_KEY,required"`
|
||||||
|
URL YoomomeyURL
|
||||||
|
}
|
||||||
|
|
||||||
|
type YoomomeyURL struct {
|
||||||
|
Webhooks string `env:"YOOMONEY_WEBHOOKS_URL,required"`
|
||||||
|
Payments string `env:"YOOMONEY_PAYMENTS_URL,required"`
|
||||||
}
|
}
|
||||||
|
60
internal/service/mock/mock.go
Normal file
60
internal/service/mock/mock.go
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package mock
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/errors"
|
||||||
|
"penahub.gitlab.yandexcloud.net/external/treasurer/pkg/validate"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MockStrategyService interface {
|
||||||
|
Register(host string) errors.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
type Deps struct {
|
||||||
|
Logger *zap.Logger
|
||||||
|
MockServiceHost string
|
||||||
|
Enabled bool
|
||||||
|
YoomoneyMockService MockStrategyService
|
||||||
|
}
|
||||||
|
|
||||||
|
type Service struct {
|
||||||
|
logger *zap.Logger
|
||||||
|
mockServiceHost string
|
||||||
|
enabled bool
|
||||||
|
yoomoneyMockService MockStrategyService
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(deps Deps) (*Service, errors.Error) {
|
||||||
|
if deps.Logger == nil {
|
||||||
|
return nil, errors.NewWithMessage("logger is nil on <NewMockService>", errors.ErrInvalidArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
if deps.YoomoneyMockService == nil {
|
||||||
|
return nil, errors.NewWithMessage("YoomoneyMockService is nil on <NewMockService>", errors.ErrInvalidArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
if validate.IsStringEmpty(deps.MockServiceHost) {
|
||||||
|
return nil, errors.NewWithMessage("mock service host is empty on <NewMockService>", errors.ErrInvalidArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Service{
|
||||||
|
logger: deps.Logger,
|
||||||
|
mockServiceHost: deps.MockServiceHost,
|
||||||
|
yoomoneyMockService: deps.YoomoneyMockService,
|
||||||
|
enabled: deps.Enabled,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (receiver *Service) Register() bool {
|
||||||
|
if !receiver.enabled {
|
||||||
|
receiver.logger.Info("register mocks is disabled")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := receiver.yoomoneyMockService.Register(receiver.mockServiceHost); err != nil {
|
||||||
|
receiver.logger.Error("failed to register yoomoney mocks", zap.Error(err), zap.String("host", receiver.mockServiceHost))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
96
internal/service/mock/yoomoney.go
Normal file
96
internal/service/mock/yoomoney.go
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
package mock
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/walkerus/go-wiremock"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/errors"
|
||||||
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/models"
|
||||||
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/models/yandex"
|
||||||
|
)
|
||||||
|
|
||||||
|
type YoomoneyMockServiceDeps struct {
|
||||||
|
Logger *zap.Logger
|
||||||
|
YoomoneyURL *models.YoomomeyURL
|
||||||
|
}
|
||||||
|
|
||||||
|
type YoomoneyMockService struct {
|
||||||
|
logger *zap.Logger
|
||||||
|
yoomoneyURL *models.YoomomeyURL
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewYoomoneyMockService(deps YoomoneyMockServiceDeps) (*YoomoneyMockService, errors.Error) {
|
||||||
|
if deps.Logger == nil {
|
||||||
|
return nil, errors.NewWithMessage("logger is nil on <NewYoomoneyMockService>", errors.ErrInvalidArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
if deps.YoomoneyURL == nil {
|
||||||
|
return nil, errors.NewWithMessage("yoomoney urls is nil on <NewYoomoneyMockService>", errors.ErrInvalidArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &YoomoneyMockService{
|
||||||
|
logger: deps.Logger,
|
||||||
|
yoomoneyURL: deps.YoomoneyURL,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (receiver *YoomoneyMockService) Register(host string) errors.Error {
|
||||||
|
return receiver.RegisterPayments(host)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (receiver *YoomoneyMockService) RegisterPayments(host string) errors.Error {
|
||||||
|
url, parseErr := url.Parse(receiver.yoomoneyURL.Payments)
|
||||||
|
if parseErr != nil {
|
||||||
|
receiver.logger.Error("failed to parse payment url on <RegisterPayment> of <YoomoneyMockService>",
|
||||||
|
zap.Error(parseErr),
|
||||||
|
zap.String("url", receiver.yoomoneyURL.Payments),
|
||||||
|
)
|
||||||
|
|
||||||
|
return errors.NewWithError(fmt.Errorf("failed to parse payment url: %w", parseErr), errors.ErrInternalError)
|
||||||
|
}
|
||||||
|
|
||||||
|
if url.Host != host {
|
||||||
|
return errors.NewWithMessage("yoomoney hosts not equal", errors.ErrInternalError)
|
||||||
|
}
|
||||||
|
|
||||||
|
mockClient := wiremock.NewClient(host)
|
||||||
|
|
||||||
|
rule := wiremock.
|
||||||
|
Post(wiremock.URLPathEqualTo(url.Path)).
|
||||||
|
WillReturnJSON(
|
||||||
|
&yandex.Payment{
|
||||||
|
ID: "f32d71f4-214b-464b-94bb-f7b4d5299af0",
|
||||||
|
Status: yandex.PaymentStatusPending,
|
||||||
|
Amount: yandex.Amount{
|
||||||
|
Value: "150.00",
|
||||||
|
Currency: "RUB",
|
||||||
|
},
|
||||||
|
Confirmation: &yandex.ConfirmationRedirect{
|
||||||
|
Type: yandex.ConfirmationTypeRedirect,
|
||||||
|
ConfirmationURL: "https://yandex-redirect-url.com",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
map[string]string{"Content-Type": "application/json"},
|
||||||
|
200,
|
||||||
|
).
|
||||||
|
AtPriority(1)
|
||||||
|
|
||||||
|
if err := mockClient.StubFor(rule); err != nil {
|
||||||
|
receiver.logger.Error("failed to init payment mock handler on <RegisterPayment> of <YoomoneyMockService>", zap.Error(err))
|
||||||
|
return errors.NewWithError(fmt.Errorf("failed to init payment mock handler: %w", err), errors.ErrInternalError)
|
||||||
|
}
|
||||||
|
|
||||||
|
isVerified, err := mockClient.Verify(wiremock.NewRequest("post", wiremock.URLPathEqualTo(url.Path)), 0)
|
||||||
|
if err != nil {
|
||||||
|
receiver.logger.Error("failed to verify payment mock handler on <RegisterPayment> of <YoomoneyMockService>", zap.Error(err))
|
||||||
|
return errors.NewWithError(fmt.Errorf("failed to verify payment mock handler: %w", err), errors.ErrInternalError)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isVerified {
|
||||||
|
return errors.NewWithMessage("payment mock handler not verified", errors.ErrInternalError)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -1,224 +0,0 @@
|
|||||||
// 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/url"
|
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/getkin/kin-openapi/openapi3"
|
|
||||||
"github.com/labstack/echo/v4"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ServerInterface represents all server handlers.
|
|
||||||
type ServerInterface interface {
|
|
||||||
// (GET /available)
|
|
||||||
GetAvailablePayments(ctx echo.Context) error
|
|
||||||
|
|
||||||
// (POST /yandex/payment/status/canceled)
|
|
||||||
SetYandexPaymentStatusCanceled(ctx echo.Context) error
|
|
||||||
|
|
||||||
// (POST /yandex/payment/status/succeeded)
|
|
||||||
SetYandexPaymentStatusSucceeded(ctx echo.Context) error
|
|
||||||
|
|
||||||
// (POST /yandex/payment/status/waiting)
|
|
||||||
SetYandexPaymentStatusWaiting(ctx echo.Context) error
|
|
||||||
|
|
||||||
// (POST /yandex/refund/status/succeeded)
|
|
||||||
SetYandexRefundStatusSucceeded(ctx echo.Context) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServerInterfaceWrapper converts echo contexts to parameters.
|
|
||||||
type ServerInterfaceWrapper struct {
|
|
||||||
Handler ServerInterface
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAvailablePayments converts echo context to params.
|
|
||||||
func (w *ServerInterfaceWrapper) GetAvailablePayments(ctx echo.Context) error {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// Invoke the callback with all the unmarshalled arguments
|
|
||||||
err = w.Handler.GetAvailablePayments(ctx)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetYandexPaymentStatusCanceled converts echo context to params.
|
|
||||||
func (w *ServerInterfaceWrapper) SetYandexPaymentStatusCanceled(ctx echo.Context) error {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// Invoke the callback with all the unmarshalled arguments
|
|
||||||
err = w.Handler.SetYandexPaymentStatusCanceled(ctx)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetYandexPaymentStatusSucceeded converts echo context to params.
|
|
||||||
func (w *ServerInterfaceWrapper) SetYandexPaymentStatusSucceeded(ctx echo.Context) error {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// Invoke the callback with all the unmarshalled arguments
|
|
||||||
err = w.Handler.SetYandexPaymentStatusSucceeded(ctx)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetYandexPaymentStatusWaiting converts echo context to params.
|
|
||||||
func (w *ServerInterfaceWrapper) SetYandexPaymentStatusWaiting(ctx echo.Context) error {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// Invoke the callback with all the unmarshalled arguments
|
|
||||||
err = w.Handler.SetYandexPaymentStatusWaiting(ctx)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetYandexRefundStatusSucceeded converts echo context to params.
|
|
||||||
func (w *ServerInterfaceWrapper) SetYandexRefundStatusSucceeded(ctx echo.Context) error {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// Invoke the callback with all the unmarshalled arguments
|
|
||||||
err = w.Handler.SetYandexRefundStatusSucceeded(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.GET(baseURL+"/available", wrapper.GetAvailablePayments)
|
|
||||||
router.POST(baseURL+"/yandex/payment/status/canceled", wrapper.SetYandexPaymentStatusCanceled)
|
|
||||||
router.POST(baseURL+"/yandex/payment/status/succeeded", wrapper.SetYandexPaymentStatusSucceeded)
|
|
||||||
router.POST(baseURL+"/yandex/payment/status/waiting", wrapper.SetYandexPaymentStatusWaiting)
|
|
||||||
router.POST(baseURL+"/yandex/refund/status/succeeded", wrapper.SetYandexRefundStatusSucceeded)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base64 encoded, gzipped, json marshaled Swagger object
|
|
||||||
var swaggerSpec = []string{
|
|
||||||
|
|
||||||
"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",
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
package swagger
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/labstack/echo/v4"
|
|
||||||
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:generate oapi-codegen --config api.yaml ../../openapi.yaml
|
|
||||||
//go:generate oapi-codegen --config models.yaml ../../openapi.yaml
|
|
||||||
|
|
||||||
type commonController interface {
|
|
||||||
// (GET /available)
|
|
||||||
GetAvailablePayments(ctx echo.Context) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type yandexStatusController interface {
|
|
||||||
// (POST /yandex/payment/status/canceled)
|
|
||||||
SetPaymentStatusCanceled(ctx echo.Context) error
|
|
||||||
|
|
||||||
// (POST /yandex/payment/status/succeeded)
|
|
||||||
SetPaymentStatusSucceeded(ctx echo.Context) error
|
|
||||||
|
|
||||||
// (POST /yandex/payment/status/waiting)
|
|
||||||
SetPaymentStatusWaiting(ctx echo.Context) error
|
|
||||||
|
|
||||||
// (POST /yandex/refund/status/succeeded)
|
|
||||||
SetRefundStatusSucceeded(ctx echo.Context) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type Deps struct {
|
|
||||||
CommonController commonController
|
|
||||||
YandexStatusController yandexStatusController
|
|
||||||
}
|
|
||||||
|
|
||||||
type API struct {
|
|
||||||
commonController commonController
|
|
||||||
yandexStatusController yandexStatusController
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(deps Deps) (*API, errors.Error) {
|
|
||||||
if deps.CommonController == nil {
|
|
||||||
return nil, errors.NewWithMessage("CommonController in nil on <NewSwaggerAPI>", errors.ErrInvalidArgs)
|
|
||||||
}
|
|
||||||
|
|
||||||
if deps.YandexStatusController == nil {
|
|
||||||
return nil, errors.NewWithMessage("YandexStatusController in nil on <NewSwaggerAPI>", errors.ErrInvalidArgs)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &API{
|
|
||||||
commonController: deps.CommonController,
|
|
||||||
yandexStatusController: deps.YandexStatusController,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Common
|
|
||||||
|
|
||||||
func (receiver *API) GetAvailablePayments(ctx echo.Context) error {
|
|
||||||
return receiver.commonController.GetAvailablePayments(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status (Yandex)
|
|
||||||
|
|
||||||
func (receiver *API) SetYandexPaymentStatusCanceled(ctx echo.Context) error {
|
|
||||||
return receiver.yandexStatusController.SetPaymentStatusCanceled(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver *API) SetYandexPaymentStatusSucceeded(ctx echo.Context) error {
|
|
||||||
return receiver.yandexStatusController.SetPaymentStatusSucceeded(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver *API) SetYandexPaymentStatusWaiting(ctx echo.Context) error {
|
|
||||||
return receiver.yandexStatusController.SetPaymentStatusWaiting(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver *API) SetYandexRefundStatusSucceeded(ctx echo.Context) error {
|
|
||||||
return receiver.yandexStatusController.SetRefundStatusSucceeded(ctx)
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
output: api.gen.go
|
|
||||||
package: swagger
|
|
||||||
generate:
|
|
||||||
echo-server: true
|
|
||||||
models: false
|
|
||||||
embedded-spec: true
|
|
@ -1,94 +0,0 @@
|
|||||||
// 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
|
|
||||||
|
|
||||||
// Defines values for PaymentStatus.
|
|
||||||
const (
|
|
||||||
Canceled PaymentStatus = "canceled"
|
|
||||||
Pending PaymentStatus = "pending"
|
|
||||||
Succeeded PaymentStatus = "succeeded"
|
|
||||||
WaitingForCapture PaymentStatus = "waiting_for_capture"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Amount defines model for Amount.
|
|
||||||
type Amount struct {
|
|
||||||
// Currency Трехбуквенный код валюты в формате ISO-4217
|
|
||||||
Currency string `json:"currency"`
|
|
||||||
|
|
||||||
// Value Сумма в выбранной валюте
|
|
||||||
Value string `json:"value"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// PaymentStatus defines model for PaymentStatus.
|
|
||||||
type PaymentStatus string
|
|
||||||
|
|
||||||
// Recipient defines model for Recipient.
|
|
||||||
type Recipient struct {
|
|
||||||
// AccountId Идентификатор магазина в ЮKassa
|
|
||||||
AccountId string `json:"account_id"`
|
|
||||||
|
|
||||||
// GatewayId Идентификатор субаккаунта
|
|
||||||
GatewayId string `json:"gateway_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetPaymentStatusRequest defines model for SetPaymentStatusRequest.
|
|
||||||
type SetPaymentStatusRequest struct {
|
|
||||||
// Event Событие, о котором уведомляет ЮKassa
|
|
||||||
Event string `json:"event"`
|
|
||||||
Object YandexPayment `json:"object"`
|
|
||||||
|
|
||||||
// Type Тип объекта. Фиксированное значение — notification (уведомление)
|
|
||||||
Type string `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// YandexPayment defines model for YandexPayment.
|
|
||||||
type YandexPayment struct {
|
|
||||||
Amount Amount `json:"amount"`
|
|
||||||
|
|
||||||
// CapturedAt Время подтверждения платежа
|
|
||||||
CapturedAt *string `json:"captured_at,omitempty"`
|
|
||||||
|
|
||||||
// Confirmation Выбранный способ подтверждения платежа
|
|
||||||
Confirmation *map[string]interface{} `json:"confirmation,omitempty"`
|
|
||||||
|
|
||||||
// CreatedAt Время создания заказа
|
|
||||||
CreatedAt string `json:"created_at"`
|
|
||||||
|
|
||||||
// Description Описание
|
|
||||||
Description *string `json:"description,omitempty"`
|
|
||||||
|
|
||||||
// ExpiresAt Время, до которого вы можете бесплатно отменить или подтвердить платеж
|
|
||||||
ExpiresAt *string `json:"expires_at,omitempty"`
|
|
||||||
|
|
||||||
// Id Идентификатор платежа в ЮKassa
|
|
||||||
Id string `json:"id"`
|
|
||||||
IncomeAmount *Amount `json:"income_amount,omitempty"`
|
|
||||||
|
|
||||||
// Paid Признак оплаты заказа
|
|
||||||
Paid bool `json:"paid"`
|
|
||||||
|
|
||||||
// PaymentMethod Структура метода платежа (может отличаться от способа платежа)
|
|
||||||
PaymentMethod *map[string]interface{} `json:"payment_method,omitempty"`
|
|
||||||
Recipient Recipient `json:"recipient"`
|
|
||||||
|
|
||||||
// Refundable Возможность провести возврат по API
|
|
||||||
Refundable bool `json:"refundable"`
|
|
||||||
RefundedAmount *Amount `json:"refunded_amount,omitempty"`
|
|
||||||
Status PaymentStatus `json:"status"`
|
|
||||||
|
|
||||||
// Test Признак тестовой операции
|
|
||||||
Test bool `json:"test"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetYandexPaymentStatusCanceledJSONRequestBody defines body for SetYandexPaymentStatusCanceled for application/json ContentType.
|
|
||||||
type SetYandexPaymentStatusCanceledJSONRequestBody = SetPaymentStatusRequest
|
|
||||||
|
|
||||||
// SetYandexPaymentStatusSucceededJSONRequestBody defines body for SetYandexPaymentStatusSucceeded for application/json ContentType.
|
|
||||||
type SetYandexPaymentStatusSucceededJSONRequestBody = SetPaymentStatusRequest
|
|
||||||
|
|
||||||
// SetYandexPaymentStatusWaitingJSONRequestBody defines body for SetYandexPaymentStatusWaiting for application/json ContentType.
|
|
||||||
type SetYandexPaymentStatusWaitingJSONRequestBody = SetPaymentStatusRequest
|
|
||||||
|
|
||||||
// SetYandexRefundStatusSucceededJSONRequestBody defines body for SetYandexRefundStatusSucceeded for application/json ContentType.
|
|
||||||
type SetYandexRefundStatusSucceededJSONRequestBody = SetPaymentStatusRequest
|
|
@ -1,4 +0,0 @@
|
|||||||
output: models.gen.go
|
|
||||||
package: swagger
|
|
||||||
generate:
|
|
||||||
models: true
|
|
@ -1,13 +0,0 @@
|
|||||||
package echotools
|
|
||||||
|
|
||||||
import "github.com/labstack/echo/v4"
|
|
||||||
|
|
||||||
func Bind[T any](ctx echo.Context) (*T, error) {
|
|
||||||
item := new(T)
|
|
||||||
|
|
||||||
if err := ctx.Bind(item); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return item, nil
|
|
||||||
}
|
|
60
internal/worker/mock/mock.go
Normal file
60
internal/worker/mock/mock.go
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package mock
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type mockService interface {
|
||||||
|
Register() bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type WorkerDeps struct {
|
||||||
|
Logger *zap.Logger
|
||||||
|
MockService mockService
|
||||||
|
}
|
||||||
|
|
||||||
|
type Worker struct {
|
||||||
|
logger *zap.Logger
|
||||||
|
mockService mockService
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(deps WorkerDeps) (*Worker, errors.Error) {
|
||||||
|
if deps.Logger == nil {
|
||||||
|
return nil, errors.NewWithMessage("logger is nil on <NewMockWorker>", errors.ErrInvalidArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
if deps.MockService == nil {
|
||||||
|
return nil, errors.NewWithMessage("MockService urls is nil on <NewMockWorker>", errors.ErrInvalidArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Worker{
|
||||||
|
logger: deps.Logger,
|
||||||
|
mockService: deps.MockService,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (receiver *Worker) Run(ctx context.Context) {
|
||||||
|
after := time.After(10 * time.Second)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
receiver.logger.Info("register mocks operations canceled <mocks>")
|
||||||
|
return
|
||||||
|
case <-after:
|
||||||
|
receiver.logger.Info("register yoomoney mocks <mocks>")
|
||||||
|
|
||||||
|
isSuccess := receiver.mockService.Register()
|
||||||
|
|
||||||
|
if isSuccess {
|
||||||
|
receiver.logger.Info("register yoomoney mocks complete <mocks>")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isSuccess {
|
||||||
|
receiver.logger.Info("register yoomoney mocks failure <mocks>")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
internal/worker/run.go
Normal file
11
internal/worker/run.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package worker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"penahub.gitlab.yandexcloud.net/external/treasurer/internal/initialize"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Run(ctx context.Context, workers *initialize.Workers) {
|
||||||
|
go workers.Mock.Run(ctx)
|
||||||
|
}
|
@ -1 +0,0 @@
|
|||||||
[{ "delete": "amocrm", "deletes": [{ "q": {} }] }]
|
|
@ -1,85 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"insert": "amocrm",
|
|
||||||
"ordered": true,
|
|
||||||
"documents": [
|
|
||||||
{
|
|
||||||
"amocrmId": "1",
|
|
||||||
"userId": "1",
|
|
||||||
"information": {
|
|
||||||
"id": 30228997,
|
|
||||||
"name": "ООО ПЕНА",
|
|
||||||
"subdomain": "penadigital",
|
|
||||||
"created_at": 1683680509,
|
|
||||||
"created_by": 0,
|
|
||||||
"updated_at": 1683680509,
|
|
||||||
"updated_by": 0,
|
|
||||||
"current_user_id": 8110726,
|
|
||||||
"country": "RU",
|
|
||||||
"customers_mode": "disabled",
|
|
||||||
"is_unsorted_on": true,
|
|
||||||
"is_loss_reason_enabled": true,
|
|
||||||
"is_helpbot_enabled": false,
|
|
||||||
"is_technical_account": true,
|
|
||||||
"contact_name_display_order": 1,
|
|
||||||
"amojo_id": "",
|
|
||||||
"uuid": "",
|
|
||||||
"version": 0,
|
|
||||||
"_links": { "self": { "href": "https://penadigital.amocrm.ru/api/v4/account" } },
|
|
||||||
"_embedded": {
|
|
||||||
"amojo_rights": { "can_direct": false, "can_create_groups": false },
|
|
||||||
"users_groups": null,
|
|
||||||
"task_types": null,
|
|
||||||
"entity_names": {
|
|
||||||
"leads": {
|
|
||||||
"ru": {
|
|
||||||
"gender": "",
|
|
||||||
"plural_form": {
|
|
||||||
"dative": "",
|
|
||||||
"default": "",
|
|
||||||
"genitive": "",
|
|
||||||
"accusative": "",
|
|
||||||
"instrumental": "",
|
|
||||||
"prepositional": ""
|
|
||||||
},
|
|
||||||
"singular_form": {
|
|
||||||
"dative": "",
|
|
||||||
"default": "",
|
|
||||||
"genitive": "",
|
|
||||||
"accusative": "",
|
|
||||||
"instrumental": "",
|
|
||||||
"prepositional": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"en": {
|
|
||||||
"singular_form": { "default": "" },
|
|
||||||
"plural_form": { "default": "" },
|
|
||||||
"gender": ""
|
|
||||||
},
|
|
||||||
"es": {
|
|
||||||
"singular_form": { "default": "" },
|
|
||||||
"plural_form": { "default": "" },
|
|
||||||
"gender": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"datetime_settings": {
|
|
||||||
"date_pattern": "",
|
|
||||||
"short_date_pattern": "",
|
|
||||||
"short_time_pattern": "",
|
|
||||||
"date_formant": "",
|
|
||||||
"time_format": "",
|
|
||||||
"timezone": "",
|
|
||||||
"timezone_offset": ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"audit": {
|
|
||||||
"createdAt": "2022-12-31T00:00:00.000Z",
|
|
||||||
"updatedAt": "2022-12-31T00:00:00.000Z",
|
|
||||||
"deleted": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
7
pkg/validate/string.go
Normal file
7
pkg/validate/string.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package validate
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
func IsStringEmpty(text string) bool {
|
||||||
|
return strings.TrimSpace(text) == ""
|
||||||
|
}
|
16
pkg/validate/string_test.go
Normal file
16
pkg/validate/string_test.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package validate_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"penahub.gitlab.yandexcloud.net/external/treasurer/pkg/validate"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIsStringEmpty(t *testing.T) {
|
||||||
|
assert.True(t, validate.IsStringEmpty(""))
|
||||||
|
assert.True(t, validate.IsStringEmpty(" "))
|
||||||
|
assert.True(t, validate.IsStringEmpty(" "))
|
||||||
|
assert.False(t, validate.IsStringEmpty("tett"))
|
||||||
|
assert.False(t, validate.IsStringEmpty(" t "))
|
||||||
|
}
|
28
pkg/validate/url.go
Normal file
28
pkg/validate/url.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package validate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"net/url"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func URL(text string) bool {
|
||||||
|
url, err := url.Parse(text)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
address := net.ParseIP(url.Host)
|
||||||
|
|
||||||
|
if address == nil {
|
||||||
|
regex := regexp.MustCompile(`\b\w+:\d+\b`)
|
||||||
|
return strings.Contains(url.Host, ".") || regex.MatchString(url.Host)
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsStringEmpty(url.Scheme) || IsStringEmpty(url.Host) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
25
pkg/validate/url_test.go
Normal file
25
pkg/validate/url_test.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package validate_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"penahub.gitlab.yandexcloud.net/external/treasurer/pkg/validate"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestValidateURL(t *testing.T) {
|
||||||
|
assert.True(t, validate.URL("http://google.com"))
|
||||||
|
assert.True(t, validate.URL("http://w.com/cn"))
|
||||||
|
assert.True(t, validate.URL("http://192.158.0.1:90"))
|
||||||
|
assert.False(t, validate.URL("192.158.0.1:9090"))
|
||||||
|
assert.False(t, validate.URL("http://w"))
|
||||||
|
assert.False(t, validate.URL("fsw"))
|
||||||
|
assert.True(t, validate.URL("http://192.158.1/1"))
|
||||||
|
assert.True(t, validate.URL("https://www.googleapis.com/oauth2/v3"))
|
||||||
|
assert.True(t, validate.URL("http://localhost:8080/google/callback"))
|
||||||
|
assert.True(t, validate.URL("https://oauth.pena.digital/amocrm/callback"))
|
||||||
|
assert.True(t, validate.URL("https://www.amocrm.ru/oauth"))
|
||||||
|
assert.True(t, validate.URL("https://www.amocrm.ru/oauth/access_token"))
|
||||||
|
assert.True(t, validate.URL("http://localhost:8080/vk/callback"))
|
||||||
|
assert.True(t, validate.URL("http://mock:8000/api/v4/account"))
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user