Compare commits

...

30 Commits

Author SHA1 Message Date
228edf6a1e drop pkg closer from pj, now import it from common 2025-06-19 10:58:09 +03:00
8f7f0db142 added logic recurrent payment 2025-06-15 10:48:37 +03:00
a1f734a87d added init payment method repository 2025-06-14 08:59:36 +03:00
e30209c739 added support auto paid 2025-06-14 05:38:14 +03:00
05089cab41 update proto 2025-06-14 04:33:27 +03:00
87affc4241 added todo
Some checks failed
Lint / Lint (push) Failing after 55s
Deploy / CreateImage (push) Failing after 45s
Deploy / DeployService (push) Has been skipped
2025-06-12 14:48:41 +03:00
8122d31c72 delete debug logs 2025-06-12 14:45:22 +03:00
819d6233ac debug 2025-06-12 14:25:27 +03:00
d8e5dd8822 added deps 2025-06-12 12:43:29 +03:00
16694d31be added todo 2025-06-12 12:34:49 +03:00
7dab765ac3 cleanup: remove duplication in CreatePayment methods 2025-06-12 12:28:16 +03:00
d78b475d2b move package yoomoney to payment_provider 2025-06-12 12:03:12 +03:00
6981eca42e delete interfaces 2025-06-12 11:59:43 +03:00
3aac0570ec - 2025-06-11 18:47:18 +03:00
778f51189b apllyed short naming receivers 2025-06-11 18:39:39 +03:00
654abc04c6 - 2025-06-11 18:28:16 +03:00
fb51df3e98 init payment webhooks in payment rest 2025-06-11 18:23:43 +03:00
dfbff4d86b create CreateInvoice(ctx context.Context, request map[string]string) (string, errors.Error) and move rest payment to grpc 2025-06-11 18:12:44 +03:00
edf077736b update interface 2025-06-09 16:19:07 +03:00
1d51dfe8c2 added logic for handleWebhook 2025-06-05 16:26:31 +03:00
f416b25a65 init create invoice method need todo review and thinking 2025-06-04 17:13:00 +03:00
56cb72ed21 init create invoice method need todo review and thinking 2025-06-04 17:07:21 +03:00
d0f441b4f9 added initialize new payment controller 2025-06-04 15:55:42 +03:00
09638a8ca7 added controller for create payment 2025-06-04 14:06:56 +03:00
fd59a0be68 - 2025-06-04 13:21:42 +03:00
c812e328b6 - 2025-06-04 12:54:48 +03:00
758f3a905a fix layout todo need review and test this 2025-06-03 16:31:31 +03:00
90fd259051 added rest payment logic wit payment provider interface 2025-06-03 12:22:27 +03:00
b605b6674f added yoomoney provider impliment PaymentProvider interface methods 2025-06-02 18:46:52 +03:00
ee8b80c170 create payment provider interface 2025-06-02 17:39:46 +03:00
75 changed files with 2169 additions and 2505 deletions

@ -7,7 +7,7 @@ GRPC_PORT=8081
YOOMONEY_STORE_ID=storeid
YOOMONEY_SECRET_KEY=secret
IS_MOCK=true
IS_MOCK=false
MOCK_SERVICE_HOST=http://treasurer-mock:8080
YOOMONEY_WEBHOOKS_URL=http://treasurer-mock:8080/webhooks
YOOMONEY_PAYMENTS_URL=http://treasurer-mock:8080/payments
@ -17,4 +17,6 @@ MONGO_PORT=27017
MONGO_USER=admin
MONGO_PASSWORD=admin
MONGO_DB_NAME=admin
MONGO_AUTH=admin
MONGO_AUTH=admin
MONGO_URL = mongodb://admin:admin@localhost:27017/?authSource=admin

@ -1,25 +1,32 @@
package main
import (
"log"
"go.uber.org/zap"
"context"
"fmt"
"gitea.pena/PenaSide/treasurer/internal/app"
"gitea.pena/PenaSide/treasurer/internal/initialize"
"go.uber.org/zap"
"os"
"os/signal"
"syscall"
)
func main() {
logger, err := zap.NewProduction(zap.AddStacktrace(zap.DPanicLevel))
logger, err := zap.NewProduction()
if err != nil {
log.Fatalf("failed to init zap logger: %v", err)
fmt.Printf("Failed to initialize logger: %v\n", err)
os.Exit(1)
}
config, err := initialize.Configuration(".env.test")
config, err := initialize.LoadConfig()
if err != nil {
logger.Fatal("failed to init config: %v", zap.Error(err))
logger.Fatal("Failed to load config", zap.Error(err))
}
if err := app.Run(config, logger); err != nil {
logger.Fatal("failed to run app: %v", zap.Error(err))
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
if err = app.Run(ctx, *config, logger); err != nil {
logger.Fatal("App exited with error", zap.Error(err))
}
}

43
go.mod

@ -1,56 +1,53 @@
module gitea.pena/PenaSide/treasurer
go 1.20
go 1.23.2
toolchain go1.23.9
require (
github.com/getkin/kin-openapi v0.118.0
gitea.pena/PenaSide/common v0.0.0-20250421103113-7e4b3ae9e1e0
github.com/caarlos0/env/v8 v8.0.0
github.com/go-resty/resty/v2 v2.7.0
github.com/gofiber/fiber/v2 v2.52.8
github.com/google/uuid v1.6.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.9.0
github.com/walkerus/go-wiremock v0.0.0-20230813141957-44e2a700708c
go.mongodb.org/mongo-driver v1.11.7
go.mongodb.org/mongo-driver v1.13.1
go.uber.org/zap v1.27.0
google.golang.org/grpc v1.62.1
google.golang.org/protobuf v1.33.0
)
require (
github.com/andybalholm/brotli v1.1.0 // 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.4 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/invopop/yaml v0.2.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/compress v1.17.7 // indirect
github.com/klauspost/compress v1.17.11 // 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.19 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/montanaflynn/stats v0.7.1 // 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/rivo/uniseg v0.2.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/valyala/fasthttp v1.51.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/net v0.22.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/crypto v0.28.0 // indirect
golang.org/x/net v0.30.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.19.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

111
go.sum

@ -1,6 +1,12 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
gitea.pena/PenaSide/common v0.0.0-20250421103113-7e4b3ae9e1e0 h1:+gvpAPo1+1WtCpA+QaCWNy4R9/cIERBBzrVSYrx7hNo=
gitea.pena/PenaSide/common v0.0.0-20250421103113-7e4b3ae9e1e0/go.mod h1:91EuBCgcqgJ6mG36n2pds8sPwwfaJytLWOzY3h2YFKU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/caarlos0/env/v8 v8.0.0 h1:POhxHhSpuxrLMIdvTGARuZqR4Jjm8AYmoi/JKlcScs0=
github.com/caarlos0/env/v8 v8.0.0/go.mod h1:7K4wMY9bH0esiXSSHlfHLX5xKGQMnkH5Fk4TDSSSzfo=
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=
@ -12,26 +18,15 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
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.118.0 h1:z43njxPmJ7TaPpMSCQb7PN0dEYno4tyBPQcrFdHoLuM=
github.com/getkin/kin-openapi v0.118.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/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
github.com/go-openapi/swag v0.22.4/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/gofiber/fiber/v2 v2.52.8 h1:xl4jJQ0BV5EJTA2aWiKw/VddRpHrKeZLF0QPUxqn0x4=
github.com/gofiber/fiber/v2 v2.52.8/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
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/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=
@ -45,23 +40,18 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
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.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
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/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY=
github.com/invopop/yaml v0.2.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/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.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
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=
@ -71,36 +61,24 @@ 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.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/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/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
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/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
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=
@ -108,37 +86,24 @@ github.com/sethvargo/go-envconfig v0.9.0/go.mod h1:Iz1Gy1Sf3T64TQlJSvee81qDhf7YI
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
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.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
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/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/walkerus/go-wiremock v0.0.0-20230813141957-44e2a700708c h1:+grD3yL1MBZzsYLHx8drdzLjzLe0WLskqA3V9HW/qNI=
github.com/walkerus/go-wiremock v0.0.0-20230813141957-44e2a700708c/go.mod h1:gMzQpReT5mG5T/PaW8pSFiPhazrcHb1mnf6JHdKwY5w=
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/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
@ -147,11 +112,12 @@ github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.mongodb.org/mongo-driver v1.11.7 h1:LIwYxASDLGUg/8wOhgOOZhX8tQa/9tgZPgzZoVqJvcs=
go.mongodb.org/mongo-driver v1.11.7/go.mod h1:G9TgswdsWjX4tmDA5zfs2+6AEPpYJwqblyjsfuh8oXY=
go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk=
go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
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=
@ -164,8 +130,8 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
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=
@ -186,18 +152,17 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
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.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
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.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
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=
@ -206,16 +171,13 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/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.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -223,10 +185,9 @@ 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.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
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/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
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=
@ -263,10 +224,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
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=

@ -4,25 +4,18 @@ import (
"context"
"errors"
"fmt"
"os/signal"
"syscall"
"gitea.pena/PenaSide/common/closer"
"gitea.pena/PenaSide/common/mongo"
"gitea.pena/PenaSide/treasurer/internal/server/grpc"
"gitea.pena/PenaSide/treasurer/internal/server/http"
"time"
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/initialize"
"gitea.pena/PenaSide/treasurer/internal/interface/swagger"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/server"
"gitea.pena/PenaSide/treasurer/internal/worker"
"gitea.pena/PenaSide/treasurer/pkg/closer"
"gitea.pena/PenaSide/treasurer/pkg/mongo"
"go.uber.org/zap"
)
const (
shutdownTimeout = 5 * time.Second
)
func Run(config *models.Config, logger *zap.Logger) (appErr error) {
func Run(ctx context.Context, config initialize.Config, logger *zap.Logger) (appErr error) {
defer func() {
if recovered := recover(); recovered != nil {
appErr = errors.New("recovered panic on application run")
@ -30,22 +23,17 @@ func Run(config *models.Config, logger *zap.Logger) (appErr error) {
}
}()
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
ctx, cancel := context.WithCancel(ctx)
defer cancel()
mongoDB, connectionErr := mongo.Connect(ctx, &mongo.ConnectDeps{
shutdownGroup := closer.NewCloserGroup()
mongoDB, err := mongo.Connect(ctx, &mongo.ConnectDeps{
Configuration: &config.Database,
Timeout: 10 * time.Second,
})
if connectionErr != nil {
return fmt.Errorf("failed connection to db: %w", connectionErr)
}
closer := closer.New()
openapi, swaggerErr := swagger.GetSwagger()
if swaggerErr != nil {
return fmt.Errorf("failed to loading openapi spec: %w", swaggerErr)
if err != nil {
return fmt.Errorf("failed connection to db: %w", err)
}
repositories, err := initialize.NewRepositories(initialize.RepositoriesDeps{
@ -53,86 +41,86 @@ func Run(config *models.Config, logger *zap.Logger) (appErr error) {
Database: mongoDB,
})
if err != nil {
return err.Wrap("failed to initialize repositories")
return err
}
clients, err := initialize.NewClients(initialize.ClientsDeps{
Logger: logger,
YoomoneyConfiguration: &config.Service.YoomomeyConfiguration,
Logger: logger,
Config: config,
})
if err != nil {
return err.Wrap("failed to initialize clients")
return err
}
services, err := initialize.NewServices(initialize.ServicesDeps{
Logger: logger,
Repositories: *repositories,
Clients: *clients,
ConfigurationHTTP: &config.HTTP,
Configuration: &config.Service,
Logger: logger,
Repositories: *repositories,
Clients: *clients,
Config: config,
})
if err != nil {
return err.Wrap("failed to initialize services")
return err
}
workers, err := initialize.NewWorkers(initialize.WorkersDeps{
Logger: logger,
Services: *services,
Logger: logger,
Service: services.Mock,
})
if err != nil {
return err.Wrap("failed to initialize workers")
return err
}
controllers, err := initialize.NewControllers(initialize.ControllersDeps{
Logger: logger,
Services: *services,
Logger: logger,
Services: *services,
Repositories: *repositories,
})
if err != nil {
return err.Wrap("failed to initialize controllers")
return err
}
api, err := initialize.NewAPI(controllers)
if err != nil {
return err.Wrap("failed to initialize api")
}
httpServer, err := server.NewHTTP(server.DepsHTTP{
Logger: logger,
Swagger: openapi,
httpServer := http.NewServer(http.ServerConfig{
Logger: logger,
Controllers: []http.Controller{controllers.YandexStatusREST, controllers.PaymentRest},
})
if err != nil {
return err.Wrap("failed to initialize http server")
}
httpServer.Register(api)
grpcServer, err := server.NewGRPC(server.DepsGRPC{Logger: logger})
grpcServer, err := grpc.NewGRPC(logger)
if err != nil {
return err.Wrap("failed to initialize grpc server")
return err
}
grpcServer.Register(controllers.PaymentGRPC)
go httpServer.Run(&config.HTTP)
go grpcServer.Run(&config.GRPC)
go func() {
if err := httpServer.Start(config.HttpURL); err != nil {
logger.Error("Client server startup error", zap.Error(err))
cancel()
}
}()
go grpcServer.Run(config.GrpcURL)
go worker.Run(ctx, workers)
closer.Add(mongoDB.Client().Disconnect)
closer.Add(httpServer.Stop)
closer.Add(grpcServer.Stop)
httpServer.ListRoutes()
shutdownGroup.Add(closer.CloserFunc(mongoDB.Client().Disconnect))
shutdownGroup.Add(closer.CloserFunc(httpServer.Shutdown))
shutdownGroup.Add(closer.CloserFunc(grpcServer.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)
timeoutCtx, timeoutCancel := context.WithTimeout(context.Background(), 10*time.Second)
defer timeoutCancel()
if err := shutdownGroup.Call(timeoutCtx); err != nil {
if errors.Is(err, context.DeadlineExceeded) {
logger.Error("Shutdown timed out", zap.Error(err))
} else {
logger.Error("Failed to shutdown services gracefully", zap.Error(err))
}
return err
}
logger.Info("Application has stopped")
return nil
}

@ -4,12 +4,12 @@ import (
"context"
"fmt"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/proto/payment_callback"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
type CallbackClientDeps struct {
@ -28,15 +28,15 @@ func NewCallbackClient(deps CallbackClientDeps) (*CallbackClient, errors.Error)
return &CallbackClient{logger: deps.Logger}, nil
}
func (receiver *CallbackClient) SendOnSuccess(ctx context.Context, host string, event *models.Event) errors.Error {
func (c *CallbackClient) SendOnSuccess(ctx context.Context, host string, event *models.Event) errors.Error {
connection, err := grpc.Dial(host, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
receiver.logger.Error("failed to connect on <SendOnSuccess> of <CallbackClient>", zap.Error(err), zap.String("host", host))
c.logger.Error("failed to connect on <SendOnSuccess> of <CallbackClient>", zap.Error(err), zap.String("host", host))
return errors.NewWithError(fmt.Errorf("failed connect to callback service: %w", err), errors.ErrInternalError)
}
defer func() {
if closeErr := connection.Close(); closeErr != nil {
receiver.logger.Error("failed to close connection on <SendOnSuccess> of <CallbackClient>", zap.Error(closeErr))
c.logger.Error("failed to close connection on <SendOnSuccess> of <CallbackClient>", zap.Error(closeErr))
}
}()
@ -57,7 +57,7 @@ func (receiver *CallbackClient) SendOnSuccess(ctx context.Context, host string,
Completed: event.Payment.Completed,
},
}); err != nil {
receiver.logger.Error("failed to send success callback on <SendOnSuccess> of <CallbackClient>",
c.logger.Error("failed to send success callback on <SendOnSuccess> of <CallbackClient>",
zap.Error(err),
zap.String("host", host),
zap.Any("event", event),
@ -68,15 +68,15 @@ func (receiver *CallbackClient) SendOnSuccess(ctx context.Context, host string,
return nil
}
func (receiver *CallbackClient) SendOnFailure(ctx context.Context, host string, event *models.Event) errors.Error {
func (c *CallbackClient) SendOnFailure(ctx context.Context, host string, event *models.Event) errors.Error {
connection, err := grpc.Dial(host, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
receiver.logger.Error("failed to connect on <SendOnFailure> of <CallbackClient>", zap.Error(err), zap.String("host", host))
c.logger.Error("failed to connect on <SendOnFailure> of <CallbackClient>", zap.Error(err), zap.String("host", host))
return errors.NewWithError(fmt.Errorf("failed connect to callback service: %w", err), errors.ErrInternalError)
}
defer func() {
if closeErr := connection.Close(); closeErr != nil {
receiver.logger.Error("failed to close connection on <SendOnFailure> of <CallbackClient>", zap.Error(closeErr))
c.logger.Error("failed to close connection on <SendOnFailure> of <CallbackClient>", zap.Error(closeErr))
}
}()
@ -97,7 +97,7 @@ func (receiver *CallbackClient) SendOnFailure(ctx context.Context, host string,
Completed: event.Payment.Completed,
},
}); err != nil {
receiver.logger.Error("failed to send failure callback on <SendOnFailure> of <CallbackClient>",
c.logger.Error("failed to send failure callback on <SendOnFailure> of <CallbackClient>",
zap.Error(err),
zap.String("host", host),
zap.Any("event", event),

81
internal/client/yandex.go Normal file

@ -0,0 +1,81 @@
package client
import (
"context"
"fmt"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/utils"
"gitea.pena/PenaSide/treasurer/pkg/client"
"go.uber.org/zap"
)
type YandexClientDeps struct {
Logger *zap.Logger
YooMoneyStoreID string
YooMoneySecretKey string
YooMoneyWebhooksURL string
YooMoneyPaymentsURL string
}
type YandexClient struct {
logger *zap.Logger
yooMoneyStoreID string
yooMoneySecretKey string
yooMoneyWebhooksURL string
yooMoneyPaymentsURL string
}
func NewYandexClient(deps YandexClientDeps) (*YandexClient, errors.Error) {
if deps.Logger == nil {
return nil, errors.NewWithMessage("Logger is nil on <NewYandexClient>", errors.ErrInvalidArgs)
}
return &YandexClient{
logger: deps.Logger,
yooMoneyStoreID: deps.YooMoneyStoreID,
yooMoneySecretKey: deps.YooMoneySecretKey,
yooMoneyWebhooksURL: deps.YooMoneyWebhooksURL,
yooMoneyPaymentsURL: deps.YooMoneyPaymentsURL,
}, nil
}
func (c *YandexClient) CreatePayment(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodType]) (*yandex.Payment, errors.Error) {
return CreateYandexPayment(ctx, c.logger, request, c.yooMoneyPaymentsURL, idempotenceKey,
utils.ConvertYoomoneySercetsToAuth("Basic", c.yooMoneyStoreID, c.yooMoneySecretKey))
}
func (c *YandexClient) CreatePaymentB2B(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodB2B]) (*yandex.Payment, errors.Error) {
return CreateYandexPayment(ctx, c.logger, request, c.yooMoneyPaymentsURL, idempotenceKey,
utils.ConvertYoomoneySercetsToAuth("Basic", c.yooMoneyStoreID, c.yooMoneySecretKey))
}
func (c *YandexClient) CreatePaymentBankCard(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodBankCard]) (*yandex.Payment, errors.Error) {
return CreateYandexPayment(ctx, c.logger, request, c.yooMoneyPaymentsURL, idempotenceKey,
utils.ConvertYoomoneySercetsToAuth("Basic", c.yooMoneyStoreID, c.yooMoneySecretKey))
}
func CreateYandexPayment[T any](ctx context.Context, logger *zap.Logger, request *yandex.CreatePaymentRequest[T],
url string, idempotenceKey string, auth string) (*yandex.Payment, errors.Error) {
response, err := client.Post[yandex.Payment, any](ctx, &client.RequestSettings{
URL: url,
Body: request,
Headers: map[string]string{
"Content-Type": "application/json",
"Idempotence-Key": idempotenceKey,
"Authorization": auth,
},
})
if err != nil {
logger.Error("failed to make request", zap.Error(err))
return nil, errors.NewWithError(fmt.Errorf("failed to make request: %w", err), errors.ErrInternalError)
}
if response.Error != nil {
logger.Error("failed to create payment", zap.Any("response", response.Error))
return nil, errors.NewWithMessage("failed to create payment", errors.ErrInternalError)
}
return response.Body, nil
}

@ -0,0 +1,149 @@
package grpc
import (
"context"
"fmt"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/payment_provider"
"gitea.pena/PenaSide/treasurer/internal/repository"
"gitea.pena/PenaSide/treasurer/internal/utils"
"google.golang.org/protobuf/types/known/emptypb"
"strconv"
"strings"
"sync"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/proto/treasurer"
"go.uber.org/zap"
)
type PaymentControllerDeps struct {
Logger *zap.Logger
PaymentProviders []payment_provider.PaymentProvider
PaymentMethodRepository *repository.PaymentMethodRepository
}
type PaymentController struct {
logger *zap.Logger
paymentProviders []payment_provider.PaymentProvider
paymentMethodRepository *repository.PaymentMethodRepository
providerMap map[models.PaymentType][]payment_provider.PaymentProvider
mu sync.RWMutex
treasurer.UnimplementedTreasurerServiceServer
}
func NewPaymentController(deps PaymentControllerDeps) (*PaymentController, errors.Error) {
if deps.Logger == nil {
return nil, errors.NewWithMessage("Logger in nil on <NewPaymentController>", errors.ErrInvalidArgs)
}
if len(deps.PaymentProviders) == 0 {
return nil, errors.NewWithMessage("No payment providers provided on <NewPaymentController>", errors.ErrInvalidArgs)
}
controller := &PaymentController{
logger: deps.Logger,
paymentProviders: deps.PaymentProviders,
providerMap: make(map[models.PaymentType][]payment_provider.PaymentProvider),
paymentMethodRepository: deps.PaymentMethodRepository,
}
for _, provider := range deps.PaymentProviders {
for _, method := range provider.GetSupportedPaymentMethods() {
controller.providerMap[method] = append(controller.providerMap[method], provider)
}
}
return controller, nil
}
func (r *PaymentController) getProviderForPaymentMethod(method models.PaymentType) (payment_provider.PaymentProvider, errors.Error) {
r.mu.RLock()
defer r.mu.RUnlock()
providers, exists := r.providerMap[method]
if !exists || len(providers) == 0 {
return nil, errors.NewWithMessage("no provider found for payment method", errors.ErrNotFound)
}
return providers[0], nil
}
func (r *PaymentController) createPayment(ctx context.Context, paymentType models.PaymentType, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
provider, err := r.getProviderForPaymentMethod(paymentType)
if err != nil {
r.logger.Error("failed to get payment provider",
zap.String("paymentMethod", string(paymentType)),
zap.Error(err))
return nil, errors.GRPC("failed to get payment provider", err)
}
request := map[string]string{
"type": string(paymentType),
"currency": in.MainSettings.Currency,
"amount": fmt.Sprintf("%d", in.MainSettings.Amount),
"callback_host_grpc": strings.Join(in.MainSettings.CallbackHostGRPC, ","),
"return_url": in.MainSettings.ReturnURL,
"user_id": in.MainSettings.UserID,
"client_ip": in.MainSettings.ClientIP,
"requisites": utils.ToJSON(yandex.Receipt{
TaxSystemCode: 2,
Customer: yandex.Customer{
FullName: in.MainSettings.Customer.FullName,
INN: in.MainSettings.Customer.INN,
Email: in.MainSettings.Customer.Email,
Phone: in.MainSettings.Customer.Phone,
},
Items: utils.ProtoItems2ReceiptItems(in.MainSettings.Items),
}),
"save_payment_method": strconv.FormatBool(in.MainSettings.Auto),
"recurrent": strconv.FormatBool(in.MainSettings.Recurrent),
}
link, err := provider.CreateInvoice(ctx, request)
if err != nil {
r.logger.Error("failed to create payment",
zap.String("provider", provider.GetName()),
zap.Error(err))
return nil, errors.GRPC("failed to create payment", err)
}
return &treasurer.GetPaymentLinkResponse{RedirectURL: link}, nil
}
func (r *PaymentController) GetPaymentLinkBankCard(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
r.logger.Info("f<GetPaymentLinkBankCard> of <PaymentController>", zap.Any("Customer", in.MainSettings.Customer))
return r.createPayment(ctx, models.PaymentTypeBankCard, in)
}
func (r *PaymentController) GetPaymentLinkYooMoney(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
return r.createPayment(ctx, models.PaymentTypeYoomoney, in)
}
func (r *PaymentController) GetPaymentLinkTinkoff(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
return r.createPayment(ctx, models.PaymentTypeTinkoff, in)
}
func (r *PaymentController) GetPaymentLinkSBP(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
return r.createPayment(ctx, models.PaymentTypeSBP, in)
}
func (r *PaymentController) GetPaymentLinkSberPay(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
return r.createPayment(ctx, models.PaymentTypeSberPay, in)
}
func (r *PaymentController) GetPaymentLinkSberbankB2B(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
return r.createPayment(ctx, models.PaymentTypeSberB2B, in)
}
func (r *PaymentController) DeleteSavedPaymentMethods(ctx context.Context, in *treasurer.DeleteSavedPaymentMethodsRequest) (*emptypb.Empty, error) {
if in.UserID == "" {
r.logger.Error("empty user id provided")
return nil, errors.GRPC("user id is required", errors.NewWithMessage("user id is required", errors.ErrInvalidArgs))
}
err := r.paymentMethodRepository.DeleteByUserID(ctx, in.UserID)
if err != nil {
r.logger.Error("failed to delete payment methods", zap.Error(err), zap.String("userId", in.UserID))
return nil, errors.GRPC("failed to delete payment methods", errors.NewWithMessage("failed to delete payment methods", errors.ErrInternalError))
}
return &emptypb.Empty{}, nil
}

@ -1,14 +1,13 @@
package rest
package http_controllers
import (
"github.com/labstack/echo/v4"
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/errors"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
)
type PaymentService interface {
// GetAvailablePaymentMethods(context.Context) ([]models.PaymentType, errors.Error)
// GetAvailablePaymentMethods(context.Context) ([]models.PaymentType, errors.Error)
}
type CommonControllerDeps struct {
@ -36,7 +35,7 @@ func NewCommonController(deps CommonControllerDeps) (*CommonController, errors.E
}, nil
}
func (receiver *CommonController) GetAvailablePayments(ctx echo.Context) error {
func (r *CommonController) GetAvailablePayments(ctx *fiber.Ctx) error {
// methods, err := receiver.paymentService.GetAvailablePaymentMethods(ctx.Request().Context())
// if err != nil {
// receiver.logger.Error("failed to get payment link on <GetAvailablePayments> of <CommonController>", zap.Error(err))

@ -0,0 +1,28 @@
package payment
import (
"gitea.pena/PenaSide/treasurer/internal/payment_provider"
"github.com/gofiber/fiber/v2"
)
type PaymentController struct {
paymentProviders []payment_provider.PaymentProvider
}
// todo нужно реализовать как сказал Миша, без создания отдельного пакета
func NewPaymentController(paymentProviders []payment_provider.PaymentProvider) *PaymentController {
return &PaymentController{
paymentProviders: paymentProviders,
}
}
func (r *PaymentController) Register(router fiber.Router) {
// вебхуки для каждого провайдера
for _, provider := range r.paymentProviders {
provider.RegisterWebhookHandlers(router)
}
}
func (r *PaymentController) Name() string {
return ""
}

@ -0,0 +1,15 @@
package yandex
import "github.com/gofiber/fiber/v2"
func (r *YandexStatusController) Register(router fiber.Router) {
router.Post("/yandex/payment/status/canceled", r.SetPaymentStatusCanceled)
router.Post("/yandex/refund/status/succeeded", r.SetRefundStatusSucceeded)
router.Post("/yandex/payment/status/succeeded", r.SetPaymentStatusSucceeded)
router.Post("/yandex/payment/status/waiting", r.SetPaymentStatusWaiting)
}
func (r *YandexStatusController) Name() string {
return ""
}

@ -0,0 +1,126 @@
package yandex
import (
"fmt"
"gitea.pena/PenaSide/treasurer/internal/service/callback"
"gitea.pena/PenaSide/treasurer/internal/service/status"
"github.com/gofiber/fiber/v2"
"net/http"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"go.uber.org/zap"
)
type YandexStatusControllerDeps struct {
Logger *zap.Logger
StatusService *status.Service
CallbackService *callback.Service
}
type YandexStatusController struct {
logger *zap.Logger
statusService *status.Service
callbackService *callback.Service
}
func NewYandexStatusController(deps YandexStatusControllerDeps) (*YandexStatusController, errors.Error) {
if deps.Logger == nil {
return nil, errors.NewWithMessage("logger is nil on <NewYandexStatusController>", errors.ErrInvalidArgs)
}
if deps.StatusService == nil {
return nil, errors.NewWithMessage("StatusService is nil on <NewYandexStatusController>", errors.ErrInvalidArgs)
}
if deps.CallbackService == nil {
return nil, errors.NewWithMessage("CallbackService is nil on <NewYandexStatusController>", errors.ErrInvalidArgs)
}
return &YandexStatusController{
logger: deps.Logger,
statusService: deps.StatusService,
callbackService: deps.CallbackService,
}, nil
}
func (r *YandexStatusController) SetPaymentStatusCanceled(ctx *fiber.Ctx) error {
var request yandex.WebhookNotification[yandex.Payment]
if err := ctx.BodyParser(&request); err != nil {
r.logger.Error("failed to parse body on <SetPaymentStatusCanceled> of <YandexStatusController>", zap.Error(err))
return errors.HTTP(ctx, errors.NewWithError(fmt.Errorf("failed to parse input body: %w", err), errors.ErrInternalError))
}
payment, setStatusErr := r.statusService.SetStatusCanceled(ctx.Context(), request.Object.ID)
if setStatusErr != nil {
r.logger.Error("failed to set canceled payment status on <SetPaymentStatusCanceled> of <YandexStatusController>", zap.Error(setStatusErr))
return errors.HTTP(ctx, setStatusErr)
}
if err := r.callbackService.OnFailure(ctx.Context(), &models.Event{
Key: string(request.Event),
Message: "yandex send event: payment canceled",
Payment: payment,
}); err != nil {
r.logger.Error("failed send success callback on <SetPaymentStatusSucceeded> of <YandexStatusController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.SendStatus(http.StatusOK)
}
func (r *YandexStatusController) SetPaymentStatusSucceeded(ctx *fiber.Ctx) error {
var request yandex.WebhookNotification[yandex.Payment]
if err := ctx.BodyParser(&request); err != nil {
r.logger.Error("failed to parse body on <SetPaymentStatusSucceeded> of <YandexStatusController>", zap.Error(err))
return errors.HTTP(ctx, errors.NewWithError(fmt.Errorf("failed to parse input body: %w", err), errors.ErrInternalError))
}
payment, setStatusErr := r.statusService.SetStatusSuccess(ctx.Context(), request.Object.ID)
if setStatusErr != nil {
r.logger.Error("failed to set success payment status on <SetPaymentStatusSucceeded> of <YandexStatusController>", zap.Error(setStatusErr))
return errors.HTTP(ctx, setStatusErr)
}
if err := r.callbackService.OnSuccess(ctx.Context(), &models.Event{
Key: string(request.Event),
Message: "yandex send event: payment succeeded",
Payment: payment,
}); err != nil {
r.logger.Error("failed send success callback on <SetPaymentStatusSucceeded> of <YandexStatusController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.SendStatus(http.StatusOK)
}
func (r *YandexStatusController) SetPaymentStatusWaiting(ctx *fiber.Ctx) error {
var request yandex.WebhookNotification[yandex.Payment]
if err := ctx.BodyParser(&request); err != nil {
r.logger.Error("failed to parse body on <SetPaymentStatusWaiting> of <YandexStatusController>", zap.Error(err))
return errors.HTTP(ctx, errors.NewWithError(fmt.Errorf("failed to parse input body: %w", err), errors.ErrInternalError))
}
if _, err := r.statusService.SetStatusWaiting(ctx.Context(), request.Object.ID); err != nil {
r.logger.Error("failed to set waiting payment status on <SetPaymentStatusWaiting> of <YandexStatusController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.SendStatus(http.StatusOK)
}
func (r *YandexStatusController) SetRefundStatusSucceeded(ctx *fiber.Ctx) error {
var request yandex.WebhookNotification[yandex.Payment]
if err := ctx.BodyParser(&request); err != nil {
r.logger.Error("failed to parse body on <SetRefundStatusSucceeded> of <YandexStatusController>", zap.Error(err))
return errors.HTTP(ctx, errors.NewWithError(fmt.Errorf("failed to parse input body: %w", err), errors.ErrInternalError))
}
if _, err := r.statusService.SetStatusRefund(ctx.Context(), request.Object.ID); err != nil {
r.logger.Error("failed to set payment status refund on <SetRefundStatusSucceeded> of <YandexStatusController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.SendStatus(http.StatusOK)
}

@ -5,6 +5,8 @@ import (
"fmt"
)
// todo rework errors package
type ErrorType error
var (
@ -43,22 +45,22 @@ func NewWithMessage(message string, errorType ErrorType) Error {
}
}
func (receiver *customError) Error() string {
return receiver.err.Error()
func (e *customError) Error() string {
return e.err.Error()
}
func (receiver *customError) Type() ErrorType {
return receiver.errorType
func (e *customError) Type() ErrorType {
return e.errorType
}
func (receiver *customError) Wrap(message string) Error {
receiver.err = fmt.Errorf("%s: %w", message, receiver.err)
func (e *customError) Wrap(message string) Error {
e.err = fmt.Errorf("%s: %w", message, e.err)
return receiver
return e
}
func (receiver *customError) SetType(errorType ErrorType) Error {
receiver.errorType = errorType
func (e *customError) SetType(errorType ErrorType) Error {
e.errorType = errorType
return receiver
return e
}

@ -1,34 +1,29 @@
package errors
import (
"net/http"
"github.com/labstack/echo/v4"
"gitea.pena/PenaSide/treasurer/internal/models"
"github.com/gofiber/fiber/v2"
)
const defaultHTTPCode = http.StatusInternalServerError
const defaultHTTPCode = fiber.StatusInternalServerError
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,
ErrInternalError: fiber.StatusInternalServerError,
ErrInvalidArgs: fiber.StatusBadRequest,
ErrNoAccess: fiber.StatusForbidden,
ErrNotFound: fiber.StatusNotFound,
ErrMethodNotImplemented: fiber.StatusNotImplemented,
ErrConflict: fiber.StatusConflict,
ErrInsufficientFunds: fiber.StatusPaymentRequired,
}
func HTTP(ctx echo.Context, err Error) error {
func HTTP(ctx *fiber.Ctx, err Error) error {
status, ok := httpStatuses[err.Type()]
if !ok {
return ctx.JSON(http.StatusInternalServerError, models.ResponseErrorHTTP{
StatusCode: defaultHTTPCode,
Message: err.Error(),
})
status = defaultHTTPCode
}
return ctx.JSON(status, models.ResponseErrorHTTP{
return ctx.Status(status).JSON(models.ResponseErrorHTTP{
StatusCode: status,
Message: err.Error(),
})

@ -1,13 +0,0 @@
package initialize
import (
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/interface/swagger"
)
func NewAPI(controllers *Controllers) (*swagger.API, errors.Error) {
return swagger.New(swagger.Deps{
CommonController: controllers.CommonREST,
YandexStatusController: controllers.YandexStatusREST,
})
}

@ -1,15 +1,14 @@
package initialize
import (
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/client"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/interface/client"
"gitea.pena/PenaSide/treasurer/internal/models"
"go.uber.org/zap"
)
type ClientsDeps struct {
Logger *zap.Logger
YoomoneyConfiguration *models.YoomomeyConfiguration
Logger *zap.Logger
Config Config
}
type Clients struct {
@ -24,8 +23,11 @@ func NewClients(deps ClientsDeps) (*Clients, errors.Error) {
}
yandexClient, err := client.NewYandexClient(client.YandexClientDeps{
Logger: deps.Logger,
Configuration: deps.YoomoneyConfiguration,
Logger: deps.Logger,
YooMoneyStoreID: deps.Config.YooMoneyStoreID,
YooMoneySecretKey: deps.Config.YooMoneySecretKey,
YooMoneyWebhooksURL: deps.Config.YooMoneyWebhooksURL,
YooMoneyPaymentsURL: deps.Config.YooMoneyPaymentsURL,
})
if err != nil {
return nil, err

@ -1,15 +1,27 @@
package initialize
import (
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/pkg/env"
"gitea.pena/PenaSide/common/mongo"
"github.com/caarlos0/env/v8"
)
func Configuration(path string) (*models.Config, error) {
config, err := env.Parse[models.Config](path)
if err != nil {
type Config struct {
HttpURL string `env:"HTTP_URL" envDefault:"0.0.0.0:8080"`
HttpDomain string `env:"HTTP_DOMAIN" envDefault:"http://localhost:8080"`
GrpcURL string `env:"GRPC_URL,required" envDefault:"localhost:9000"`
YooMoneyStoreID string `env:"YOOMONEY_STORE_ID" envDefault:"storeid"`
YooMoneySecretKey string `env:"YOOMONEY_SECRET_KEY" envDefault:"secret"`
IsMock bool `env:"IS_MOCK" envDefault:"false"`
MockServiceHost string `env:"MOCK_SERVICE_HOST" envDefault:"http://treasurer-mock:8080"`
YooMoneyWebhooksURL string `env:"YOOMONEY_WEBHOOKS_URL" envDefault:"http://treasurer-mock:8080/webhooks"`
YooMoneyPaymentsURL string `env:"YOOMONEY_PAYMENTS_URL" envDefault:"http://treasurer-mock:8080/payments"`
Database mongo.Configuration
}
func LoadConfig() (*Config, error) {
var config Config
if err := env.Parse(&config); err != nil {
return nil, err
}
return config, nil
return &config, nil
}

@ -1,33 +1,27 @@
package initialize
import (
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/controller/grpc"
"gitea.pena/PenaSide/treasurer/internal/controller/http_controllers/payment"
"gitea.pena/PenaSide/treasurer/internal/controller/http_controllers/yandex"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/interface/controller/grpc"
"gitea.pena/PenaSide/treasurer/internal/interface/controller/rest"
"go.uber.org/zap"
)
type ControllersDeps struct {
Logger *zap.Logger
Services Services
Logger *zap.Logger
Services Services
Repositories Repositories
}
type Controllers struct {
CommonREST *rest.CommonController
YandexStatusREST *rest.YandexStatusController
YandexStatusREST *yandex.YandexStatusController
PaymentGRPC *grpc.PaymentController
PaymentRest *payment.PaymentController
}
func NewControllers(deps ControllersDeps) (*Controllers, errors.Error) {
commonControllerREST, err := rest.NewCommonController(rest.CommonControllerDeps{
Logger: deps.Logger,
PaymentService: deps.Services.Payment,
})
if err != nil {
return nil, err
}
yandexStatusControllerREST, err := rest.NewYandexStatusController(rest.YandexStatusControllerDeps{
yandexStatusControllerREST, err := yandex.NewYandexStatusController(yandex.YandexStatusControllerDeps{
Logger: deps.Logger,
StatusService: deps.Services.Status,
CallbackService: deps.Services.Callback,
@ -37,16 +31,19 @@ func NewControllers(deps ControllersDeps) (*Controllers, errors.Error) {
}
paymentControllerGRPC, err := grpc.NewPaymentController(grpc.PaymentControllerDeps{
Logger: deps.Logger,
PaymentService: deps.Services.Payment,
Logger: deps.Logger,
PaymentProviders: deps.Services.PaymentProviders,
PaymentMethodRepository: deps.Repositories.PaymentMethod,
})
if err != nil {
return nil, err
}
paymentControllerRest := payment.NewPaymentController(deps.Services.PaymentProviders)
return &Controllers{
CommonREST: commonControllerREST,
YandexStatusREST: yandexStatusControllerREST,
PaymentGRPC: paymentControllerGRPC,
PaymentRest: paymentControllerRest,
}, nil
}

@ -1,10 +1,10 @@
package initialize
import (
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/repository"
"go.mongodb.org/mongo-driver/mongo"
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/interface/repository"
)
type RepositoriesDeps struct {
@ -13,7 +13,8 @@ type RepositoriesDeps struct {
}
type Repositories struct {
Payment *repository.PaymentRepository
Payment *repository.PaymentRepository
PaymentMethod *repository.PaymentMethodRepository
}
func NewRepositories(deps RepositoriesDeps) (*Repositories, errors.Error) {
@ -25,5 +26,10 @@ func NewRepositories(deps RepositoriesDeps) (*Repositories, errors.Error) {
return nil, err
}
return &Repositories{Payment: paymentRepository}, nil
paymentMethod := repository.NewPaymentMethodRepository(repository.PaymentMethodRepositoryDeps{
Logger: deps.Logger,
Collection: deps.Database.Collection("payment_methods"),
})
return &Repositories{Payment: paymentRepository, PaymentMethod: paymentMethod}, nil
}

@ -1,22 +1,21 @@
package initialize
import (
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/payment_provider"
"gitea.pena/PenaSide/treasurer/internal/payment_provider/yoomoney"
"gitea.pena/PenaSide/treasurer/internal/service/callback"
"gitea.pena/PenaSide/treasurer/internal/service/mock"
"gitea.pena/PenaSide/treasurer/internal/service/payment"
"gitea.pena/PenaSide/treasurer/internal/service/status"
"gitea.pena/PenaSide/treasurer/internal/service/webhook"
"go.uber.org/zap"
)
type ServicesDeps struct {
Logger *zap.Logger
Repositories Repositories
Clients Clients
ConfigurationHTTP *models.ConfigurationHTTP
Configuration *models.ServiceConfiguration
Logger *zap.Logger
Repositories Repositories
Clients Clients
Config Config
}
type Services struct {
@ -24,8 +23,9 @@ type Services struct {
Payment *payment.Service
YandexPayment *payment.Yandex
Status *status.Service
YandexWebhook *webhook.Yandex
Mock *mock.Service
//YandexWebhook *webhook.Yandex
Mock *mock.Service
PaymentProviders []payment_provider.PaymentProvider
}
func NewServices(deps ServicesDeps) (*Services, errors.Error) {
@ -63,18 +63,19 @@ func NewServices(deps ServicesDeps) (*Services, errors.Error) {
return nil, err
}
yandexWebhookService, err := webhook.NewYandex(webhook.YandexDeps{
Logger: deps.Logger,
YandexWebhookClient: deps.Clients.Yandex,
Configuration: deps.ConfigurationHTTP,
})
if err != nil {
return nil, err
}
// todo не используется
//yandexWebhookService, err := webhook.NewYandex(webhook.YandexDeps{
// Logger: deps.Logger,
// YandexWebhookClient: deps.Clients.Yandex,
// HttpDomain: deps.Config.HttpDomain,
//})
//if err != nil {
// return nil, err
//}
yoomoneyMockService, err := mock.NewYoomoneyMockService(mock.YoomoneyMockServiceDeps{
Logger: deps.Logger,
YoomoneyURL: &deps.Configuration.MockConfiguration.YoomomeyURL,
Logger: deps.Logger,
YooMoneyPaymentsURL: deps.Config.YooMoneyPaymentsURL,
})
if err != nil {
return nil, err
@ -82,20 +83,37 @@ func NewServices(deps ServicesDeps) (*Services, errors.Error) {
mockService, err := mock.New(mock.Deps{
Logger: deps.Logger,
Enabled: deps.Configuration.MockConfiguration.IsMock,
MockServiceHost: deps.Configuration.MockConfiguration.Host,
Enabled: deps.Config.IsMock,
MockServiceHost: deps.Config.MockServiceHost,
YoomoneyMockService: yoomoneyMockService,
})
if err != nil {
return nil, err
}
yooMoneyProvider, err := yoomoney.New(yoomoney.Deps{
Logger: deps.Logger,
Config: &yoomoney.Config{
StoreID: deps.Config.YooMoneyStoreID,
SecretKey: deps.Config.YooMoneySecretKey,
WebhooksURL: deps.Config.YooMoneyWebhooksURL,
PaymentsURL: deps.Config.YooMoneyPaymentsURL,
},
Repository: deps.Repositories.Payment,
CallbackService: callbackService,
PaymentMethodRepository: deps.Repositories.PaymentMethod,
})
if err != nil {
return nil, err
}
return &Services{
Callback: callbackService,
Payment: paymentService,
YandexPayment: yandexPaymentService,
Status: statusService,
YandexWebhook: yandexWebhookService,
Mock: mockService,
//YandexWebhook: yandexWebhookService,
Mock: mockService,
PaymentProviders: []payment_provider.PaymentProvider{yooMoneyProvider},
}, nil
}

@ -1,14 +1,15 @@
package initialize
import (
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/errors"
svc_mock "gitea.pena/PenaSide/treasurer/internal/service/mock"
"gitea.pena/PenaSide/treasurer/internal/worker/mock"
"go.uber.org/zap"
)
type WorkersDeps struct {
Logger *zap.Logger
Services Services
Logger *zap.Logger
Service *svc_mock.Service
}
type Workers struct {
@ -18,7 +19,7 @@ type Workers struct {
func NewWorkers(deps WorkersDeps) (*Workers, errors.Error) {
mockWorker, err := mock.New(mock.WorkerDeps{
Logger: deps.Logger,
MockService: deps.Services.Mock,
MockService: deps.Service,
})
if err != nil {
return nil, err

@ -1,107 +0,0 @@
package client
import (
"context"
"fmt"
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/utils"
"gitea.pena/PenaSide/treasurer/pkg/client"
)
type YandexClientDeps struct {
Logger *zap.Logger
Configuration *models.YoomomeyConfiguration
}
type YandexClient struct {
logger *zap.Logger
configuration *models.YoomomeyConfiguration
}
func NewYandexClient(deps YandexClientDeps) (*YandexClient, errors.Error) {
if deps.Logger == nil {
return nil, errors.NewWithMessage("Logger is nil on <NewYandexClient>", errors.ErrInvalidArgs)
}
if deps.Configuration == nil {
return nil, errors.NewWithMessage("Configuration is nil on <NewYandexClient>", errors.ErrInvalidArgs)
}
return &YandexClient{
logger: deps.Logger,
configuration: deps.Configuration,
}, nil
}
func (receiver *YandexClient) CreatePayment(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodType]) (*yandex.Payment, errors.Error) {
receiver.logger.Info("fai<CreatePayment> of <YandexClient>", zap.Any("CRP",request))
response, err := client.Post[yandex.Payment, any](ctx, &client.RequestSettings{
URL: receiver.configuration.URL.Payments,
Body: request,
Headers: map[string]string{
"Content-Type": "application/json",
"Idempotence-Key": idempotenceKey,
"Authorization": utils.ConvertYoomoneySercetsToAuth("Basic", receiver.configuration.StoreID, receiver.configuration.SecretKey),
},
})
if err != nil {
receiver.logger.Error("failed to make request on <CreatePayment> of <YandexClient>", zap.Error(err))
return nil, errors.NewWithError(fmt.Errorf("failed to make request: %w", err), errors.ErrInternalError)
}
if response.Error != nil {
receiver.logger.Error("failed to create payment on <CreatePayment> of <YandexClient>", zap.Any("response", response.Error))
return nil, errors.NewWithMessage("failed to create payment", errors.ErrInternalError)
}
return response.Body, nil
}
func (receiver *YandexClient) CreatePaymentB2B(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodB2B]) (*yandex.Payment, errors.Error) {
receiver.logger.Info("fai2<CreatePayment> of <YandexClient>", zap.Any("CRP",request))
response, err := client.Post[yandex.Payment, any](ctx, &client.RequestSettings{
URL: receiver.configuration.URL.Payments,
Body: request,
Headers: map[string]string{
"Content-Type": "application/json",
"Idempotence-Key": idempotenceKey,
"Authorization": utils.ConvertYoomoneySercetsToAuth("Basic", receiver.configuration.StoreID, receiver.configuration.SecretKey),
},
})
if err != nil {
receiver.logger.Error("failed to make request on <CreatePaymentB2B> of <YandexClient>", zap.Error(err))
return nil, errors.NewWithError(fmt.Errorf("failed to make request: %w", err), errors.ErrInternalError)
}
if response.Error != nil {
receiver.logger.Error("failed to create payment on <CreatePaymentB2B> of <YandexClient>", zap.Any("response", response.Error))
return nil, errors.NewWithMessage("failed to create payment", errors.ErrInternalError)
}
return response.Body, nil
}
func (receiver *YandexClient) CreatePaymentBankCard(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodBankCard]) (*yandex.Payment, errors.Error) {
receiver.logger.Info("fai3<CreatePayment> of <YandexClient>", zap.Any("CRP",request))
response, err := client.Post[yandex.Payment, any](ctx, &client.RequestSettings{
URL: receiver.configuration.URL.Payments,
Body: request,
Headers: map[string]string{
"Content-Type": "application/json",
"Idempotence-Key": idempotenceKey,
"Authorization": utils.ConvertYoomoneySercetsToAuth("Basic", receiver.configuration.StoreID, receiver.configuration.SecretKey),
},
})
if err != nil {
receiver.logger.Error("failed to make request on <CreatePaymentBankCard> of <YandexClient>", zap.Error(err))
return nil, errors.NewWithError(fmt.Errorf("failed to make request: %w", err), errors.ErrInternalError)
}
if response.Error != nil {
receiver.logger.Error("failed to create payment on <CreatePaymentBankCard> of <YandexClient>", zap.Any("response", response.Error))
return nil, errors.NewWithMessage("failed to create payment", errors.ErrInternalError)
}
return response.Body, nil
}

@ -1,205 +0,0 @@
package grpc
import (
"context"
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/utils"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/proto/treasurer"
)
type PaymentService interface {
CreatePaymentBankCard(context.Context, *models.CreatePayment[yandex.Receipt]) (string, errors.Error)
CreatePayment(context.Context, *models.CreatePayment[yandex.Receipt]) (string, errors.Error)
}
type PaymentControllerDeps struct {
Logger *zap.Logger
PaymentService PaymentService
}
type PaymentController struct {
logger *zap.Logger
paymentService PaymentService
}
func NewPaymentController(deps PaymentControllerDeps) (*PaymentController, errors.Error) {
if deps.Logger == nil {
return nil, errors.NewWithMessage("Logger in nil on <NewPaymentController>", errors.ErrInvalidArgs)
}
if deps.PaymentService == nil {
return nil, errors.NewWithMessage("PaymentService in nil on <NewPaymentController>", errors.ErrInvalidArgs)
}
return &PaymentController{
logger: deps.Logger,
paymentService: deps.PaymentService,
}, nil
}
func (receiver *PaymentController) GetPaymentLinkBankCard(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
receiver.logger.Info("f<GetPaymentLinkBankCard> of <PaymentController>", zap.Any("Customer", in.MainSettings.Customer))
link, err := receiver.paymentService.CreatePaymentBankCard(ctx, &models.CreatePayment[yandex.Receipt]{
Type: models.PaymentTypeBankCard,
Currency: in.MainSettings.Currency,
UserID: in.MainSettings.UserID,
ClientIP: in.MainSettings.ClientIP,
Amount: in.MainSettings.Amount,
CallbackHostGRPC: in.MainSettings.CallbackHostGRPC,
ReturnURL: in.MainSettings.ReturnURL,
Requisites: yandex.Receipt{
TaxSystemCode: 2,
Customer: yandex.Customer{
FullName: in.MainSettings.Customer.FullName,
Email: in.MainSettings.Customer.Email,
},
Items: utils.ProtoItems2ReceiptItems(in.MainSettings.Items),
},
})
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLinkBankCard> of <PaymentController>", zap.Error(err))
return nil, errors.GRPC("failed to get payment link", err)
}
return &treasurer.GetPaymentLinkResponse{RedirectURL: link}, nil
}
func (receiver *PaymentController) GetPaymentLinkYooMoney(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
link, err := receiver.paymentService.CreatePayment(ctx, &models.CreatePayment[yandex.Receipt]{
Type: models.PaymentTypeYoomoney,
Currency: in.MainSettings.Currency,
UserID: in.MainSettings.UserID,
ClientIP: in.MainSettings.ClientIP,
Amount: in.MainSettings.Amount,
CallbackHostGRPC: in.MainSettings.CallbackHostGRPC,
ReturnURL: in.MainSettings.ReturnURL,
Requisites: yandex.Receipt{
TaxSystemCode: 2,
Customer: yandex.Customer{
FullName: in.MainSettings.Customer.FullName,
Email: in.MainSettings.Customer.Email,
},
Items: utils.ProtoItems2ReceiptItems(in.MainSettings.Items),
},
})
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLinkYooMoney> of <PaymentController>", zap.Error(err))
return nil, errors.GRPC("failed to get payment link", err)
}
return &treasurer.GetPaymentLinkResponse{RedirectURL: link}, nil
}
func (receiver *PaymentController) GetPaymentLinkTinkoff(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
link, err := receiver.paymentService.CreatePayment(ctx, &models.CreatePayment[yandex.Receipt]{
Type: models.PaymentTypeTinkoff,
Currency: in.MainSettings.Currency,
UserID: in.MainSettings.UserID,
ClientIP: in.MainSettings.ClientIP,
Amount: in.MainSettings.Amount,
CallbackHostGRPC: in.MainSettings.CallbackHostGRPC,
ReturnURL: in.MainSettings.ReturnURL,
Requisites: yandex.Receipt{
TaxSystemCode: 2,
Customer: yandex.Customer{
FullName: in.MainSettings.Customer.FullName,
Email: in.MainSettings.Customer.Email,
},
Items: utils.ProtoItems2ReceiptItems(in.MainSettings.Items),
},
})
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLinkTinkoff> of <PaymentController>", zap.Error(err))
return nil, errors.GRPC("failed to get payment link", err)
}
return &treasurer.GetPaymentLinkResponse{RedirectURL: link}, nil
}
func (receiver *PaymentController) GetPaymentLinkSBP(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
link, err := receiver.paymentService.CreatePayment(ctx, &models.CreatePayment[yandex.Receipt]{
Type: models.PaymentTypeSBP,
Currency: in.MainSettings.Currency,
UserID: in.MainSettings.UserID,
ClientIP: in.MainSettings.ClientIP,
Amount: in.MainSettings.Amount,
CallbackHostGRPC: in.MainSettings.CallbackHostGRPC,
ReturnURL: in.MainSettings.ReturnURL,
Requisites: yandex.Receipt{
TaxSystemCode: 2,
Customer: yandex.Customer{
FullName: in.MainSettings.Customer.FullName,
Email: in.MainSettings.Customer.Email,
},
Items: utils.ProtoItems2ReceiptItems(in.MainSettings.Items),
},
})
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLinkSBP> of <PaymentController>", zap.Error(err))
return nil, errors.GRPC("failed to get payment link", err)
}
return &treasurer.GetPaymentLinkResponse{RedirectURL: link}, nil
}
func (receiver *PaymentController) GetPaymentLinkSberPay(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
link, err := receiver.paymentService.CreatePayment(ctx, &models.CreatePayment[yandex.Receipt]{
Type: models.PaymentTypeSberPay,
Currency: in.MainSettings.Currency,
UserID: in.MainSettings.UserID,
ClientIP: in.MainSettings.ClientIP,
Amount: in.MainSettings.Amount,
CallbackHostGRPC: in.MainSettings.CallbackHostGRPC,
ReturnURL: in.MainSettings.ReturnURL,
Requisites: yandex.Receipt{
TaxSystemCode: 2,
Customer: yandex.Customer{
FullName: in.MainSettings.Customer.FullName,
Email: in.MainSettings.Customer.Email,
},
Items: utils.ProtoItems2ReceiptItems(in.MainSettings.Items),
},
})
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLinkSberPay> of <PaymentController>", zap.Error(err))
return nil, errors.GRPC("failed to get payment link", err)
}
return &treasurer.GetPaymentLinkResponse{RedirectURL: link}, nil
}
func (receiver *PaymentController) GetPaymentLinkSberbankB2B(ctx context.Context, in *treasurer.GetPaymentLinkRequest) (*treasurer.GetPaymentLinkResponse, error) {
link, err := receiver.paymentService.CreatePayment(ctx, &models.CreatePayment[yandex.Receipt]{
Type: models.PaymentTypeSberB2B,
Currency: in.MainSettings.Currency,
UserID: in.MainSettings.UserID,
ClientIP: in.MainSettings.ClientIP,
Amount: in.MainSettings.Amount,
CallbackHostGRPC: in.MainSettings.CallbackHostGRPC,
ReturnURL: in.MainSettings.ReturnURL,
Requisites: yandex.Receipt{
TaxSystemCode: 2,
Customer: yandex.Customer{
FullName: in.MainSettings.Customer.FullName,
Email: in.MainSettings.Customer.Email,
},
Items: utils.ProtoItems2ReceiptItems(in.MainSettings.Items),
},
})
if err != nil {
receiver.logger.Error("failed to get payment link on <GetPaymentLinkB2B> of <PaymentController>", zap.Error(err))
return nil, errors.GRPC("failed to get payment link", err)
}
return &treasurer.GetPaymentLinkResponse{RedirectURL: link}, nil
}

@ -1,141 +0,0 @@
package rest
import (
"context"
"fmt"
"net/http"
"github.com/labstack/echo/v4"
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/pkg/echotools"
)
type StatusService interface {
SetStatusCanceled(context.Context, string) (*models.Payment, errors.Error)
SetStatusSuccess(context.Context, string) (*models.Payment, errors.Error)
SetStatusWaiting(context.Context, string) (*models.Payment, errors.Error)
SetStatusRefund(context.Context, string) (*models.Payment, errors.Error)
}
type CallbackService interface {
OnSuccess(context.Context, *models.Event) errors.Error
OnFailure(context.Context, *models.Event) errors.Error
}
type YandexStatusControllerDeps struct {
Logger *zap.Logger
StatusService StatusService
CallbackService CallbackService
}
type YandexStatusController struct {
logger *zap.Logger
statusService StatusService
callbackService CallbackService
}
func NewYandexStatusController(deps YandexStatusControllerDeps) (*YandexStatusController, errors.Error) {
if deps.Logger == nil {
return nil, errors.NewWithMessage("logger is nil on <NewYandexStatusController>", errors.ErrInvalidArgs)
}
if deps.StatusService == nil {
return nil, errors.NewWithMessage("StatusService is nil on <NewYandexStatusController>", errors.ErrInvalidArgs)
}
if deps.CallbackService == nil {
return nil, errors.NewWithMessage("CallbackService is nil on <NewYandexStatusController>", errors.ErrInvalidArgs)
}
return &YandexStatusController{
logger: deps.Logger,
statusService: deps.StatusService,
callbackService: deps.CallbackService,
}, nil
}
func (receiver *YandexStatusController) SetPaymentStatusCanceled(ctx echo.Context) error {
request, err := echotools.Bind[yandex.WebhookNotification[yandex.Payment]](ctx)
if err != nil {
receiver.logger.Error("failed to parse body on <SetPaymentStatusCanceled> of <YandexStatusController>", zap.Error(err))
return errors.HTTP(ctx, errors.NewWithError(fmt.Errorf("failed to parse input body: %w", err), errors.ErrInternalError))
}
payment, setStatusErr := receiver.statusService.SetStatusCanceled(ctx.Request().Context(), request.Object.ID)
if setStatusErr != nil {
receiver.logger.Error("failed to set canceled payment status on <SetPaymentStatusCanceled> of <YandexStatusController>", zap.Error(setStatusErr))
return errors.HTTP(ctx, setStatusErr)
}
if err := receiver.callbackService.OnFailure(ctx.Request().Context(), &models.Event{
Key: string(request.Event),
Message: "yandex send event: payment canceled",
Payment: payment,
}); err != nil {
receiver.logger.Error("failed send success callback on <SetPaymentStatusSucceeded> of <YandexStatusController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, nil)
}
func (receiver *YandexStatusController) SetPaymentStatusSucceeded(ctx echo.Context) error {
fmt.Println("SUUUUUUUUUUUU0")
request, err := echotools.Bind[yandex.WebhookNotification[yandex.Payment]](ctx)
if err != nil {
receiver.logger.Error("failed to parse body on <SetPaymentStatusSucceeded> of <YandexStatusController>", zap.Error(err))
return errors.HTTP(ctx, errors.NewWithError(fmt.Errorf("failed to parse input body: %w", err), errors.ErrInternalError))
}
fmt.Println("SUUUUUUUUUUUU1", request)
payment, setStatusErr := receiver.statusService.SetStatusSuccess(ctx.Request().Context(), request.Object.ID)
if setStatusErr != nil {
receiver.logger.Error("failed to set success payment status on <SetPaymentStatusSucceeded> of <YandexStatusController>", zap.Error(setStatusErr))
return errors.HTTP(ctx, setStatusErr)
}
fmt.Println("SUUUUUUUUUUUU2", payment, setStatusErr)
if err := receiver.callbackService.OnSuccess(ctx.Request().Context(), &models.Event{
Key: string(request.Event),
Message: "yandex send event: payment succeeded",
Payment: payment,
}); err != nil {
receiver.logger.Error("failed send success callback on <SetPaymentStatusSucceeded> of <YandexStatusController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, nil)
}
func (receiver *YandexStatusController) SetPaymentStatusWaiting(ctx echo.Context) error {
request, err := echotools.Bind[yandex.WebhookNotification[yandex.Payment]](ctx)
if err != nil {
receiver.logger.Error("failed to parse body on <SetPaymentStatusWaiting> of <YandexStatusController>", zap.Error(err))
return errors.HTTP(ctx, errors.NewWithError(fmt.Errorf("failed to parse input body: %w", err), errors.ErrInternalError))
}
if _, err := receiver.statusService.SetStatusWaiting(ctx.Request().Context(), request.Object.ID); err != nil {
receiver.logger.Error("failed to set waiting payment status on <SetPaymentStatusWaiting> of <YandexStatusController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, nil)
}
func (receiver *YandexStatusController) SetRefundStatusSucceeded(ctx echo.Context) error {
request, err := echotools.Bind[yandex.WebhookNotification[yandex.Payment]](ctx)
if err != nil {
receiver.logger.Error("failed to parse body on <SetRefundStatusSucceeded> of <YandexStatusController>", zap.Error(err))
return errors.HTTP(ctx, errors.NewWithError(fmt.Errorf("failed to parse input body: %w", err), errors.ErrInternalError))
}
if _, err := receiver.statusService.SetStatusRefund(ctx.Request().Context(), request.Object.ID); err != nil {
receiver.logger.Error("failed to set payment status refund on <SetRefundStatusSucceeded> of <YandexStatusController>", zap.Error(err))
return errors.HTTP(ctx, err)
}
return ctx.JSON(http.StatusOK, nil)
}

@ -1,225 +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{
"H4sIAAAAAAAC/+xYzW7bRhB+FWLbQwIwlpw2DeBbUhRF0EMDG0VRJIaxoVYOU4tkSMqJEQjQT9IEddAg",
"QQ89FCnS9lxIsmXT+qFfYfYV+iTFzC4lUtrYVoHccmnlJbkz+33zfTObJ8zxa4HvCS+O2NoTFjn3RY3T",
"zxs1v+7F+CsI/UCEsSto3amHofCcPfxdEZETukHs+h5bY/CnbMJAPoOe7MAQ+jCACUzkPpxYMIQUDi3o",
"QxdG8hfZlvsW9C35FFLZhDF0ZRsG1q2Nb698fnX1OrOZeMxrwY5ga2z9u5vMZvFegH9Eceh626xhs12+",
"UxeGHN7JDoxxR9wf+nIferIJXcwEUsxkmgIMCnFWyyvl8mKkhs1C8bDuhqLC1u7osPYMhc3pF/69B8KJ",
"MbevdoVCTnj1Gn4V8L2a8OKVR9yNXW97q+qHWw4P4nqIe2VPo7rjCFERldyawz1H7NBSKKp1r5J7a9MA",
"y2313UbM43qUT+E9oYVXwS9tlg8+DWqKsC4cN3CFqTS442DNbLkVAzG/wSEWhGxDIp9CAkMiPZVNC9mC",
"A+jCMSQw0cz98w2PIm5ifpvH4hHfWzaKbMkO9KALQ1rs0EvdcwnPnakQ2sT7hogL+K+Lh3URGYASWYF8",
"GooqW2OflGYyLGkNllQVNewswDmv/8C9inis4+NnKr1FkUICpxak0JM/wwCGiMKKBX8jWLIFiWxCSiJR",
"ihlYcIykyOck5wQG1r/NXy3Pj92q63Dc1bokO6T2Q0hhDKPsxcsFfeW/OBd1emprnKYImDAvHnuxJKcu",
"dhZ22usaWPokjcoWjw3YvUGDg7F8ZcEpGpps47llE45U2UGiHo2UocGRqcBs5vhe1Q1rCgpTlJxpkX3K",
"FsaTLWTt/4SeweWEgsfnH49CHcMh5UA7H5NyUKPGIxV2Wtj4LZxCIltqtznfNTxc2F08DtxQROdkbVtY",
"gdRrlOYhhQNc6GO3GUMKRzCgRgM9GBCmCq0JvoTfjDWSbfnSggRGkMyjfZg9zSFtynhZCywQVzTAGVQ8",
"qlSv8+gL/O+16jX80xjbc/ya2Fq29ANuTPoP2YREeQAM0Td0qoipsSju+f6O4J7akmS5VRPxfb9i7NZt",
"2cRpQbZlB0seeUKOUqy9eVguzUhUfI0gkc8pmZeyhVWaynZBLAt7XDaJIsy3tLPAmvW+RtaP+b0dk8u+",
"If2odCeYja4a7a4DXMDq6tN7fTw6HuoUUuvG7VtGMFU81O6SxEbTYeCs94uTA/YP3brOrAfElc6S0lFO",
"VIEM6Dw/QQKJ4ShzXk+dVedoZ4adJ6XgWjovXa4FFhbbQ4PUUPWNltSjutDEpFrhLfV/1fw0SbJFB+or",
"l7KuKE8YyY58nrmBmlrkM5pyadIYw1h27JwZ4fRBLyqTQulQNVDPbcuXtqVCKTNMUWvoFic6pQROCrvR",
"VD3dDedcSiqzL5s8BIOotBOsxazotEpwBNgnM3pV0DVi7MbKnN/Njn6FprQDctuDBeeSr7HS5b58ZtEt",
"4IWeAk6YzXZFGCnYV1fKK2WaaQLh8cBla+yzlfLKKvEZ36ciLfFd7u5kutoWpiKcmgSCNMr6saIka4ZT",
"LIdIzqEWYQdOdZo45FAtd8mSUwRMb1YEA+cJ6tW3KmyNfS3iG1mCWjMR1WEU+F6kpo6r5TJdlXwv1q7C",
"g2BHDz+lB5Fqkkp5NA9mFn+HPXQfuQiZq4Zf1/vRr1axtN1Y1GjzBb/XCzwM+Z6q+SJa80V1ESDyCOCO",
"Md+O9E2GbeJCaY8Gr5K2+JIScGl6dcBJzDcayO/z3MkOFWaX5s0+DEkHuEBNobXYB+4yeJt1a/kaJnfZ",
"AksbIi5MhsrWvszfpmg2v+lX9pai6iwLfd/832goz1uskDlo/iKqUDw4cRuQ6c4hg/RfM271Biayg91V",
"38Jfqfb4AhLo4UZLsTq7HH5gWvMApBemdSN3d/3I6xK86n8U+OBihSNIsssEDC7M6/c6vY+sns2qmoE+",
"tFgLo+qScl2nDD+q9SK8zlaeMI/XsLXjk8Zm478AAAD//0NwNQGuFQAA",
}
// 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"
"gitea.pena/PenaSide/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,104 +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 Event.
const (
PaymentCanceled Event = "payment.canceled"
PaymentSucceeded Event = "payment.succeeded"
PaymentWaitingForCapture Event = "payment.waiting_for_capture"
RefundSucceeded Event = "refund.succeeded"
)
// 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"`
}
// Event defines model for Event.
type Event string
// 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 Event `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,45 +0,0 @@
package models
import (
"gitea.pena/PenaSide/treasurer/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"`
Domen string `env:"HTTP_DOMEN,required"`
}
type ConfigurationGRPC struct {
Host string `env:"GRPC_HOST,default=0.0.0.0"`
Port string `env:"GRPC_PORT,default=8081"`
}
type ServiceConfiguration struct {
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 {
StoreID string `env:"YOOMONEY_STORE_ID,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"`
}

@ -31,17 +31,17 @@ type Payment struct {
CallbackHostGRPC []string `json:"callbackHostGrpc" bson:"callbackHostGrpc"`
}
func (receiver *Payment) Sanitize() *Payment {
func (p *Payment) Sanitize() *Payment {
now := time.Now()
receiver.ID = ""
receiver.CreatedAt = now
receiver.UpdatedAt = now
receiver.DeletedAt = nil
receiver.IsDeleted = false
receiver.Completed = false
p.ID = ""
p.CreatedAt = now
p.UpdatedAt = now
p.DeletedAt = nil
p.IsDeleted = false
p.Completed = false
return receiver
return p
}
type CreatePaymentResult struct {
@ -58,6 +58,8 @@ type CreatePayment[T any] struct {
UserID string
ClientIP string
Requisites T
Auto bool
Recurrent bool
}
type BankCard struct {
@ -71,23 +73,23 @@ type BankCard struct {
type PaymentType string
const (
PaymentTypeBankCard PaymentType = "bankCard"
PaymentTypeTinkoff PaymentType = "tinkoffBank"
PaymentTypeSberPay PaymentType = "sberbank"
PaymentTypeYoomoney PaymentType = "yoomoney"
PaymentTypeMobile PaymentType = "mobile"
PaymentTypeSBP PaymentType = "sbp"
PaymentTypeSberB2B PaymentType = "b2bSberbank"
PaymentTypeBankCard PaymentType = "bankCard"
PaymentTypeTinkoff PaymentType = "tinkoffBank"
PaymentTypeSberPay PaymentType = "sberbank"
PaymentTypeYoomoney PaymentType = "yoomoney"
PaymentTypeMobile PaymentType = "mobile"
PaymentTypeSBP PaymentType = "sbp"
PaymentTypeSberB2B PaymentType = "b2bSberbank"
)
var (
YandexPaymentTypeMap = map[PaymentType]yandex.PaymentType{
PaymentTypeBankCard: yandex.PaymentTypeBankCard,
PaymentTypeTinkoff: yandex.PaymentTypeTinkoff,
PaymentTypeSberPay: yandex.PaymentTypeSberPay,
PaymentTypeYoomoney: yandex.PaymentTypeYoomoney,
PaymentTypeMobile: yandex.PaymentTypeMobile,
PaymentTypeSBP: yandex.PaymentTypeSBP,
PaymentTypeSberB2B: yandex.PaymentTypeSberB2B,
PaymentTypeBankCard: yandex.PaymentTypeBankCard,
PaymentTypeTinkoff: yandex.PaymentTypeTinkoff,
PaymentTypeSberPay: yandex.PaymentTypeSberPay,
PaymentTypeYoomoney: yandex.PaymentTypeYoomoney,
PaymentTypeMobile: yandex.PaymentTypeMobile,
PaymentTypeSBP: yandex.PaymentTypeSBP,
PaymentTypeSberB2B: yandex.PaymentTypeSberB2B,
}
)

@ -1,5 +1,7 @@
package yandex
import "time"
// Payment description https://yookassa.ru/developers/api#payment_object
type Payment struct {
ID string `json:"id" bson:"id"`
@ -8,7 +10,7 @@ type Payment struct {
Confirmation *ConfirmationRedirect `json:"confirmation" bson:"confirmation"`
IncomeAmount *Amount `json:"income_amount,omitempty" bson:"income_amount,omitempty"`
Description string `json:"description,omitempty" bson:"description,omitempty"`
PaymentMethod any `json:"payment_method,omitempty" bson:"payment_method,omitempty"`
PaymentMethod *PaymentMethod `json:"payment_method,omitempty" bson:"payment_method,omitempty"`
Recipient Recipient `json:"recipient" bson:"recipient"`
CapturedAt string `json:"captured_at,omitempty" bson:"captured_at,omitempty"`
ExpiresAt string `json:"expires_at,omitempty" bson:"expires_at,omitempty"`
@ -42,3 +44,31 @@ const (
PaymentStatusSuccessfully PaymentStatus = "succeeded"
PaymentStatusCanceled PaymentStatus = "canceled"
)
type PaymentMethod struct {
ID string `json:"_id" bson:"_id,omitempty"`
UserID string `json:"userId" bson:"userId"`
Type string `json:"type" bson:"type"`
MethodID string `json:"id" bson:"id"`
Saved bool `json:"saved" bson:"saved"`
Card *Card `json:"card,omitempty" bson:"card,omitempty"`
Title string `json:"title" bson:"title"`
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"`
}
type Card struct {
First6 string `json:"first6" bson:"first6"`
Last4 string `json:"last4" bson:"last4"`
ExpiryMonth string `json:"expiry_month" bson:"expiry_month"`
ExpiryYear string `json:"expiry_year" bson:"expiry_year"`
CardType string `json:"card_type" bson:"card_type"`
CardProduct *CardProduct `json:"card_product,omitempty" bson:"card_product,omitempty"`
IssuerCountry string `json:"issuer_country" bson:"issuer_country"`
IssuerName string `json:"issuer_name" bson:"issuer_name"`
}
type CardProduct struct {
Code string `json:"code" bson:"code"`
Name string `json:"name" bson:"name"`
}

@ -10,33 +10,41 @@ type CreatePaymentRequest[T any] struct {
ClientIP string `json:"client_ip,omitempty"`
Deal any `json:"deal,omitempty"`
MerchantCustomerID any `json:"merchant_customer_id,omitempty"`
Receipt Receipt `json:"receipt,omitempty"`
Receipt Receipt `json:"receipt,omitempty"`
SavePaymentMethod bool `json:"save_payment_method"`
}
type Receipt struct {
Customer Customer `json:"customer,omitempty"`
Items []Item `json:"items,omitempty"`
TaxSystemCode int `json:"tax_system_code,omitempty"`
Customer Customer `json:"customer,omitempty"`
Items []Item `json:"items,omitempty"`
TaxSystemCode int `json:"tax_system_code,omitempty"`
}
type Item struct {
Description string `json:"description,omitempty"`
Amount ReceiptAmount `json:"amount,omitempty"`
VatCode int `json:"vat_code,omitempty"`
Quantity int64 `json:"quantity,omitempty"`
Measure string `json:"measure,omitempty"`
PaymentSubject string `json:"payment_subject,omitempty"`
PaymentMode string `json:"payment_mode,omitempty"`
Description string `json:"description,omitempty"`
Amount ReceiptAmount `json:"amount,omitempty"`
VatCode int `json:"vat_code,omitempty"`
Quantity int64 `json:"quantity,omitempty"`
Measure string `json:"measure,omitempty"`
PaymentSubject string `json:"payment_subject,omitempty"`
PaymentMode string `json:"payment_mode,omitempty"`
}
type ReceiptAmount struct {
Value string `json:"value,omitempty"`
Value string `json:"value,omitempty"`
Currency string `json:"currency,omitempty"`
}
type Customer struct {
FullName string `json:"full_name,omitempty"`
INN string `json:"inn,omitempty"`
Email string `json:"email,omitempty"`
Phone string `json:"phone,omitempty"`
INN string `json:"inn,omitempty"`
Email string `json:"email,omitempty"`
Phone string `json:"phone,omitempty"`
}
type CreateRecurrentPayment struct {
Amount Amount `json:"amount"`
Capture bool `json:"capture"`
PaymentMethodID string `json:"payment_method_id"`
Description string `json:"description,omitempty"`
}

@ -0,0 +1,15 @@
package payment_provider
import (
"context"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models"
"github.com/gofiber/fiber/v2"
)
type PaymentProvider interface {
GetName() string
RegisterWebhookHandlers(router fiber.Router)
GetSupportedPaymentMethods() []models.PaymentType
CreateInvoice(ctx context.Context, request map[string]string) (string, errors.Error)
}

@ -0,0 +1,331 @@
package yoomoney
import (
"context"
"encoding/json"
"fmt"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/repository"
"gitea.pena/PenaSide/treasurer/internal/service/callback"
"gitea.pena/PenaSide/treasurer/internal/utils"
"github.com/go-resty/resty/v2"
"github.com/gofiber/fiber/v2"
"github.com/google/uuid"
"go.uber.org/zap"
"net/http"
)
const (
ProviderName = "yoomoney"
)
type Config struct {
StoreID string `env:"YOOMONEY_STORE_ID"`
SecretKey string `env:"YOOMONEY_SECRET_KEY"`
WebhooksURL string `env:"YOOMONEY_WEBHOOKS_URL"`
PaymentsURL string `env:"YOOMONEY_PAYMENTS_URL"`
}
type Provider struct {
logger *zap.Logger
config *Config
httpClient *resty.Client
repository *repository.PaymentRepository
callbackService *callback.Service
paymentMethodRepository *repository.PaymentMethodRepository
}
type Deps struct {
Logger *zap.Logger
Config *Config
Repository *repository.PaymentRepository
CallbackService *callback.Service
PaymentMethodRepository *repository.PaymentMethodRepository
}
func New(deps Deps) (*Provider, errors.Error) {
return &Provider{
logger: deps.Logger,
config: deps.Config,
httpClient: resty.New(),
repository: deps.Repository,
callbackService: deps.CallbackService,
paymentMethodRepository: deps.PaymentMethodRepository,
}, nil
}
func (p *Provider) GetName() string {
return ProviderName
}
func (p *Provider) GetSupportedPaymentMethods() []models.PaymentType {
return []models.PaymentType{
models.PaymentTypeBankCard,
models.PaymentTypeTinkoff,
models.PaymentTypeSberPay,
models.PaymentTypeYoomoney,
models.PaymentTypeMobile,
models.PaymentTypeSBP,
models.PaymentTypeSberB2B,
}
}
// *models.CreatePayment[yandex.Receipt]
func (p *Provider) CreateInvoice(ctx context.Context, req map[string]string) (string, errors.Error) {
request, err := utils.MapToCreatePaymentYandexReceipt(req)
if err != nil {
p.logger.Error("failed to create payment yandex receipt by parse map", zap.Error(err))
return "", errors.NewWithMessage("failed to parse input request by parse map", errors.ErrInvalidArgs)
}
if request.Recurrent {
return p.CreateRecurrentPayment(ctx, request)
}
idempotenceKey := uuid.New().String()
yandexPayment, err := p.httpClient.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json").
SetHeader("Idempotence-Key", idempotenceKey).
SetHeader("Authorization", utils.ConvertYoomoneySercetsToAuth("Basic", p.config.StoreID, p.config.SecretKey)).
SetBody(&yandex.CreatePaymentRequest[yandex.PaymentMethodType]{
Amount: yandex.Amount{
Value: utils.ConvertAmountToStringFloat(request.Amount),
Currency: request.Currency,
},
Receipt: yandex.Receipt{
TaxSystemCode: 2, //https://yookassa.ru/developers/payment-acceptance/receipts/54fz/other-services/parameters-values#tax-systems
Customer: request.Requisites.Customer,
Items: request.Requisites.Items,
},
PaymentMethodData: &yandex.PaymentMethodType{Type: models.YandexPaymentTypeMap[request.Type]},
Confirmation: &yandex.CreateConfirmationRedirect{
Type: yandex.ConfirmationTypeRedirect,
Locale: "ru_RU",
ReturnURL: request.ReturnURL,
Enforce: true,
},
Capture: true,
ClientIP: request.ClientIP,
SavePaymentMethod: request.Auto,
}).
Post(p.config.PaymentsURL)
if err != nil {
p.logger.Error("failed to create payment", zap.Error(err), zap.String("payment_method", string(request.Type)))
return "", errors.NewWithError(fmt.Errorf("failed to create payment: %w", err), errors.ErrInternalError)
}
if yandexPayment.StatusCode() != http.StatusOK {
p.logger.Error("failed to create payment", zap.Int("status_code", yandexPayment.StatusCode()), zap.String("response", yandexPayment.String()))
return "", errors.NewWithMessage("failed to create payment", errors.ErrInternalError)
}
var payment yandex.Payment
if err := json.Unmarshal(yandexPayment.Body(), &payment); err != nil {
p.logger.Error("failed to unmarshal payment response", zap.Error(err))
return "", errors.NewWithError(fmt.Errorf("failed to unmarshal payment response: %w", err), errors.ErrInternalError)
}
_, err = p.repository.Insert(ctx, &models.Payment{
UserID: request.UserID,
PaymentID: payment.ID,
IdempotencePaymentID: idempotenceKey,
ClientIP: request.ClientIP,
Currency: request.Currency,
Amount: request.Amount,
Type: request.Type,
Status: models.PaymentStatusMap[string(payment.Status)],
Completed: false,
RawPaymentBody: payment,
CallbackHostGRPC: request.CallbackHostGRPC,
})
if err != nil {
p.logger.Error("failed to save payment to database", zap.Error(err))
return "", errors.NewWithError(fmt.Errorf("failed to save payment to database: %w", err), errors.ErrInternalError)
}
return payment.Confirmation.ConfirmationURL, nil
}
func (p *Provider) RegisterWebhookHandlers(router fiber.Router) {
router.Post(p.config.WebhooksURL, p.handleWebhook)
}
func (p *Provider) handleWebhook(ctx *fiber.Ctx) error {
var notification yandex.WebhookNotification[yandex.Payment]
if err := ctx.BodyParser(&notification); err != nil {
p.logger.Error("failed to parse webhook notification", zap.Error(err))
return errors.HTTP(ctx, errors.NewWithError(fmt.Errorf("failed to parse webhook notification: %w", err), errors.ErrInternalError))
}
var payment *models.Payment
var err errors.Error
switch notification.Event {
case yandex.WebhookEventPaymentSucceeded:
payment, err = p.repository.SetPaymentStatus(ctx.Context(), notification.Object.ID, models.PaymentStatusSuccessfully)
if err != nil {
p.logger.Error("failed to set payment complete", zap.Error(err))
return errors.HTTP(ctx, err)
}
if notification.Object.PaymentMethod != nil && notification.Object.PaymentMethod.Saved {
method := &yandex.PaymentMethod{
UserID: payment.UserID,
MethodID: notification.Object.PaymentMethod.ID,
Type: notification.Object.PaymentMethod.Type,
Title: notification.Object.PaymentMethod.Title,
Saved: notification.Object.PaymentMethod.Saved,
}
if notification.Object.PaymentMethod.Card != nil {
method.Card = &yandex.Card{
First6: notification.Object.PaymentMethod.Card.First6,
Last4: notification.Object.PaymentMethod.Card.Last4,
ExpiryMonth: notification.Object.PaymentMethod.Card.ExpiryMonth,
ExpiryYear: notification.Object.PaymentMethod.Card.ExpiryYear,
CardType: notification.Object.PaymentMethod.Card.CardType,
IssuerName: notification.Object.PaymentMethod.Card.IssuerName,
IssuerCountry: notification.Object.PaymentMethod.Card.IssuerCountry,
}
}
if notification.Object.PaymentMethod.Card.CardProduct != nil {
method.Card.CardProduct = &yandex.CardProduct{
Code: notification.Object.PaymentMethod.Card.CardProduct.Code,
Name: notification.Object.PaymentMethod.Card.CardProduct.Name,
}
}
if err := p.paymentMethodRepository.Save(ctx.Context(), method); err != nil {
p.logger.Error("failed to save payment method", zap.Error(err),
zap.String("userId", payment.UserID), zap.String("methodId", method.MethodID))
// todo стоит ли возвращать ошибку?
}
}
case yandex.WebhookEventPaymentCanceled:
payment, err = p.repository.SetPaymentStatus(ctx.Context(), notification.Object.ID, models.PaymentStatusCanceled)
if err != nil {
p.logger.Error("failed to set payment status canceled", zap.Error(err))
return errors.HTTP(ctx, err)
}
case yandex.WebhookEventPaymentWaiting:
payment, err = p.repository.SetPaymentStatus(ctx.Context(), notification.Object.ID, models.PaymentStatusWaiting)
if err != nil {
p.logger.Error("failed to set payment status waiting", zap.Error(err))
return errors.HTTP(ctx, err)
}
case yandex.WebhookEventRefundSucceeded:
payment, err = p.repository.SetPaymentStatus(ctx.Context(), notification.Object.ID, models.PaymentStatusRefund)
if err != nil {
p.logger.Error("failed to set payment status refund", zap.Error(err))
return errors.HTTP(ctx, err)
}
default:
p.logger.Warn("unknown webhook event type", zap.String("event", string(notification.Event)))
return errors.HTTP(ctx, errors.NewWithMessage(fmt.Sprintf("unknown webhook event type: %s", notification.Event), errors.ErrInvalidArgs))
}
if payment != nil {
event := &models.Event{
Key: string(notification.Event),
Message: fmt.Sprintf("yoomoney send event: %s", notification.Event),
Payment: payment,
}
if notification.Event == yandex.WebhookEventPaymentSucceeded {
if err := p.callbackService.OnSuccess(ctx.Context(), event); err != nil {
p.logger.Error("failed to send success callback", zap.Error(err))
return errors.HTTP(ctx, err)
}
}
if notification.Event == yandex.WebhookEventPaymentCanceled {
if err := p.callbackService.OnFailure(ctx.Context(), event); err != nil {
p.logger.Error("failed to send failure callback", zap.Error(err))
return errors.HTTP(ctx, err)
}
}
}
return ctx.SendStatus(http.StatusOK)
}
func (p *Provider) CreateRecurrentPayment(ctx context.Context, request *models.CreatePayment[yandex.Receipt]) (string, errors.Error) {
methods, err := p.paymentMethodRepository.GetByUserID(ctx, request.UserID)
if err != nil {
p.logger.Error("failed to get payment methods", zap.Error(err), zap.String("userId", request.UserID))
return "", errors.NewWithError(err, errors.ErrInternalError)
}
if len(methods) == 0 {
p.logger.Warn("no saved payment methods found", zap.String("userId", request.UserID))
return "", errors.NewWithMessage("no saved payment methods found", errors.ErrInvalidArgs)
}
for _, method := range methods {
idempotenceKey := uuid.New().String()
yandexPayment, err := p.httpClient.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json").
SetHeader("Idempotence-Key", idempotenceKey).
SetHeader("Authorization", utils.ConvertYoomoneySercetsToAuth("Basic", p.config.StoreID, p.config.SecretKey)).
SetBody(&yandex.CreateRecurrentPayment{
Amount: yandex.Amount{
Value: utils.ConvertAmountToStringFloat(request.Amount),
Currency: request.Currency,
},
PaymentMethodID: method.MethodID,
Capture: true,
}).
Post(p.config.PaymentsURL)
if err != nil {
p.logger.Error("failed to create recurrent payment", zap.Error(err), zap.String("userId", request.UserID))
return "", errors.NewWithError(fmt.Errorf("failed to create recurrent payment"), errors.ErrInternalError)
}
if yandexPayment.StatusCode() != http.StatusOK {
p.logger.Error("unexpected status code from yandex", zap.Int("statusCode", yandexPayment.StatusCode()), zap.String("userId", request.UserID))
return "", errors.NewWithError(fmt.Errorf("unexpected status code: %d", yandexPayment.StatusCode()), errors.ErrInternalError)
}
var payment yandex.Payment
if err := json.Unmarshal(yandexPayment.Body(), &payment); err != nil {
p.logger.Error("failed to unmarshal payment response", zap.Error(err), zap.String("userId", request.UserID), zap.String("methodId", method.MethodID))
return "", errors.NewWithError(err, errors.ErrInternalError)
}
if payment.Status != yandex.PaymentStatusSuccessfully {
p.logger.Error("payment not succeeded", zap.String("userId", request.UserID), zap.String("status", string(payment.Status)))
continue
}
_, err = p.repository.Insert(ctx, &models.Payment{
UserID: request.UserID,
PaymentID: payment.ID,
IdempotencePaymentID: idempotenceKey,
ClientIP: request.ClientIP,
Currency: request.Currency,
Amount: request.Amount,
Type: request.Type,
Status: models.PaymentStatusMap[string(payment.Status)],
Completed: false,
RawPaymentBody: payment,
CallbackHostGRPC: request.CallbackHostGRPC,
})
if err != nil {
p.logger.Error("failed to save payment to database", zap.Error(err))
return "", errors.NewWithError(fmt.Errorf("failed to save payment to database: %w", err), errors.ErrInternalError)
}
return payment.ID, nil
}
return "", errors.NewWithMessage("failed to create recurrent payment with any saved method", errors.ErrInternalError)
}

@ -1,408 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.33.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"`
Customer *Customer `protobuf:"bytes,7,opt,name=Customer,proto3" json:"Customer,omitempty"`
Items []*Item `protobuf:"bytes,8,rep,name=Items,proto3" json:"Items,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 ""
}
func (x *MainPaymentSettings) GetCustomer() *Customer {
if x != nil {
return x.Customer
}
return nil
}
func (x *MainPaymentSettings) GetItems() []*Item {
if x != nil {
return x.Items
}
return nil
}
type Customer struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
FullName string `protobuf:"bytes,1,opt,name=FullName,proto3" json:"FullName,omitempty"`
INN string `protobuf:"bytes,2,opt,name=INN,proto3" json:"INN,omitempty"`
Email string `protobuf:"bytes,3,opt,name=Email,proto3" json:"Email,omitempty"`
Phone string `protobuf:"bytes,4,opt,name=Phone,proto3" json:"Phone,omitempty"`
}
func (x *Customer) Reset() {
*x = Customer{}
if protoimpl.UnsafeEnabled {
mi := &file_treasurer_payment_model_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Customer) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Customer) ProtoMessage() {}
func (x *Customer) 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 Customer.ProtoReflect.Descriptor instead.
func (*Customer) Descriptor() ([]byte, []int) {
return file_treasurer_payment_model_proto_rawDescGZIP(), []int{1}
}
func (x *Customer) GetFullName() string {
if x != nil {
return x.FullName
}
return ""
}
func (x *Customer) GetINN() string {
if x != nil {
return x.INN
}
return ""
}
func (x *Customer) GetEmail() string {
if x != nil {
return x.Email
}
return ""
}
func (x *Customer) GetPhone() string {
if x != nil {
return x.Phone
}
return ""
}
type Item struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Description string `protobuf:"bytes,1,opt,name=Description,proto3" json:"Description,omitempty"`
Measure string `protobuf:"bytes,2,opt,name=Measure,proto3" json:"Measure,omitempty"`
Quantity string `protobuf:"bytes,3,opt,name=Quantity,proto3" json:"Quantity,omitempty"`
Money string `protobuf:"bytes,4,opt,name=Money,proto3" json:"Money,omitempty"`
Currency string `protobuf:"bytes,5,opt,name=Currency,proto3" json:"Currency,omitempty"`
}
func (x *Item) Reset() {
*x = Item{}
if protoimpl.UnsafeEnabled {
mi := &file_treasurer_payment_model_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Item) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Item) ProtoMessage() {}
func (x *Item) ProtoReflect() protoreflect.Message {
mi := &file_treasurer_payment_model_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 Item.ProtoReflect.Descriptor instead.
func (*Item) Descriptor() ([]byte, []int) {
return file_treasurer_payment_model_proto_rawDescGZIP(), []int{2}
}
func (x *Item) GetDescription() string {
if x != nil {
return x.Description
}
return ""
}
func (x *Item) GetMeasure() string {
if x != nil {
return x.Measure
}
return ""
}
func (x *Item) GetQuantity() string {
if x != nil {
return x.Quantity
}
return ""
}
func (x *Item) GetMoney() string {
if x != nil {
return x.Money
}
return ""
}
func (x *Item) GetCurrency() string {
if x != nil {
return x.Currency
}
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, 0x9f, 0x02, 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, 0x12, 0x2f, 0x0a, 0x08, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72,
0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72,
0x65, 0x72, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x52, 0x08, 0x43, 0x75, 0x73,
0x74, 0x6f, 0x6d, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x05, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x08,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72,
0x2e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x22, 0x64, 0x0a, 0x08,
0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x46, 0x75, 0x6c, 0x6c,
0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x46, 0x75, 0x6c, 0x6c,
0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x49, 0x4e, 0x4e, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x03, 0x49, 0x4e, 0x4e, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x18,
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x14, 0x0a, 0x05,
0x50, 0x68, 0x6f, 0x6e, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x50, 0x68, 0x6f,
0x6e, 0x65, 0x22, 0x90, 0x01, 0x0a, 0x04, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x20, 0x0a, 0x0b, 0x44,
0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a,
0x07, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x51, 0x75, 0x61, 0x6e, 0x74,
0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x51, 0x75, 0x61, 0x6e, 0x74,
0x69, 0x74, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x4d, 0x6f, 0x6e, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01,
0x28, 0x09, 0x52, 0x05, 0x4d, 0x6f, 0x6e, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x43, 0x75, 0x72,
0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x43, 0x75, 0x72,
0x72, 0x65, 0x6e, 0x63, 0x79, 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, 3)
var file_treasurer_payment_model_proto_goTypes = []interface{}{
(*MainPaymentSettings)(nil), // 0: treasurer.MainPaymentSettings
(*Customer)(nil), // 1: treasurer.Customer
(*Item)(nil), // 2: treasurer.Item
}
var file_treasurer_payment_model_proto_depIdxs = []int32{
1, // 0: treasurer.MainPaymentSettings.Customer:type_name -> treasurer.Customer
2, // 1: treasurer.MainPaymentSettings.Items:type_name -> treasurer.Item
2, // [2:2] is the sub-list for method output_type
2, // [2:2] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] 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.(*Customer); 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[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Item); 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_payment_model_proto_rawDesc,
NumEnums: 0,
NumMessages: 3,
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
}

@ -1,8 +1,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.33.0
// protoc (unknown)
// source: treasurer/service.proto
// protoc-gen-go v1.25.0-devel
// protoc v3.14.0
// source: service.proto
package treasurer
@ -32,7 +32,7 @@ type GetBankCardPaymentLinkRequest struct {
func (x *GetBankCardPaymentLinkRequest) Reset() {
*x = GetBankCardPaymentLinkRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_treasurer_service_proto_msgTypes[0]
mi := &file_service_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -45,7 +45,7 @@ func (x *GetBankCardPaymentLinkRequest) String() string {
func (*GetBankCardPaymentLinkRequest) ProtoMessage() {}
func (x *GetBankCardPaymentLinkRequest) ProtoReflect() protoreflect.Message {
mi := &file_treasurer_service_proto_msgTypes[0]
mi := &file_service_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -58,7 +58,7 @@ func (x *GetBankCardPaymentLinkRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetBankCardPaymentLinkRequest.ProtoReflect.Descriptor instead.
func (*GetBankCardPaymentLinkRequest) Descriptor() ([]byte, []int) {
return file_treasurer_service_proto_rawDescGZIP(), []int{0}
return file_service_proto_rawDescGZIP(), []int{0}
}
func (x *GetBankCardPaymentLinkRequest) GetMainSettings() *MainPaymentSettings {
@ -79,7 +79,7 @@ type GetPaymentLinkRequest struct {
func (x *GetPaymentLinkRequest) Reset() {
*x = GetPaymentLinkRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_treasurer_service_proto_msgTypes[1]
mi := &file_service_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -92,7 +92,7 @@ func (x *GetPaymentLinkRequest) String() string {
func (*GetPaymentLinkRequest) ProtoMessage() {}
func (x *GetPaymentLinkRequest) ProtoReflect() protoreflect.Message {
mi := &file_treasurer_service_proto_msgTypes[1]
mi := &file_service_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -105,7 +105,7 @@ func (x *GetPaymentLinkRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetPaymentLinkRequest.ProtoReflect.Descriptor instead.
func (*GetPaymentLinkRequest) Descriptor() ([]byte, []int) {
return file_treasurer_service_proto_rawDescGZIP(), []int{1}
return file_service_proto_rawDescGZIP(), []int{1}
}
func (x *GetPaymentLinkRequest) GetMainSettings() *MainPaymentSettings {
@ -128,7 +128,7 @@ type GetB2BPaymentLinkRequest struct {
func (x *GetB2BPaymentLinkRequest) Reset() {
*x = GetB2BPaymentLinkRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_treasurer_service_proto_msgTypes[2]
mi := &file_service_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -141,7 +141,7 @@ func (x *GetB2BPaymentLinkRequest) String() string {
func (*GetB2BPaymentLinkRequest) ProtoMessage() {}
func (x *GetB2BPaymentLinkRequest) ProtoReflect() protoreflect.Message {
mi := &file_treasurer_service_proto_msgTypes[2]
mi := &file_service_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -154,7 +154,7 @@ func (x *GetB2BPaymentLinkRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetB2BPaymentLinkRequest.ProtoReflect.Descriptor instead.
func (*GetB2BPaymentLinkRequest) Descriptor() ([]byte, []int) {
return file_treasurer_service_proto_rawDescGZIP(), []int{2}
return file_service_proto_rawDescGZIP(), []int{2}
}
func (x *GetB2BPaymentLinkRequest) GetMainSettings() *MainPaymentSettings {
@ -189,7 +189,7 @@ type GetPaymentLinkResponse struct {
func (x *GetPaymentLinkResponse) Reset() {
*x = GetPaymentLinkResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_treasurer_service_proto_msgTypes[3]
mi := &file_service_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -202,7 +202,7 @@ func (x *GetPaymentLinkResponse) String() string {
func (*GetPaymentLinkResponse) ProtoMessage() {}
func (x *GetPaymentLinkResponse) ProtoReflect() protoreflect.Message {
mi := &file_treasurer_service_proto_msgTypes[3]
mi := &file_service_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -215,7 +215,7 @@ func (x *GetPaymentLinkResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetPaymentLinkResponse.ProtoReflect.Descriptor instead.
func (*GetPaymentLinkResponse) Descriptor() ([]byte, []int) {
return file_treasurer_service_proto_rawDescGZIP(), []int{3}
return file_service_proto_rawDescGZIP(), []int{3}
}
func (x *GetPaymentLinkResponse) GetRedirectURL() string {
@ -225,43 +225,397 @@ func (x *GetPaymentLinkResponse) GetRedirectURL() string {
return ""
}
var File_treasurer_service_proto protoreflect.FileDescriptor
type DeleteSavedPaymentMethodsRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
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, 0x63, 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, 0x22, 0x5b, 0x0a, 0x15, 0x47, 0x65, 0x74, 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, 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, 0xd4, 0x04, 0x0a, 0x10, 0x54, 0x72,
UserID string `protobuf:"bytes,1,opt,name=UserID,proto3" json:"UserID,omitempty"`
}
func (x *DeleteSavedPaymentMethodsRequest) Reset() {
*x = DeleteSavedPaymentMethodsRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_service_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeleteSavedPaymentMethodsRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeleteSavedPaymentMethodsRequest) ProtoMessage() {}
func (x *DeleteSavedPaymentMethodsRequest) ProtoReflect() protoreflect.Message {
mi := &file_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 DeleteSavedPaymentMethodsRequest.ProtoReflect.Descriptor instead.
func (*DeleteSavedPaymentMethodsRequest) Descriptor() ([]byte, []int) {
return file_service_proto_rawDescGZIP(), []int{4}
}
func (x *DeleteSavedPaymentMethodsRequest) GetUserID() string {
if x != nil {
return x.UserID
}
return ""
}
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"`
Customer *Customer `protobuf:"bytes,7,opt,name=Customer,proto3" json:"Customer,omitempty"`
Items []*Item `protobuf:"bytes,8,rep,name=Items,proto3" json:"Items,omitempty"`
Auto bool `protobuf:"varint,9,opt,name=Auto,proto3" json:"Auto,omitempty"`
Recurrent bool `protobuf:"varint,10,opt,name=Recurrent,proto3" json:"Recurrent,omitempty"`
}
func (x *MainPaymentSettings) Reset() {
*x = MainPaymentSettings{}
if protoimpl.UnsafeEnabled {
mi := &file_service_proto_msgTypes[5]
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_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 MainPaymentSettings.ProtoReflect.Descriptor instead.
func (*MainPaymentSettings) Descriptor() ([]byte, []int) {
return file_service_proto_rawDescGZIP(), []int{5}
}
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 ""
}
func (x *MainPaymentSettings) GetCustomer() *Customer {
if x != nil {
return x.Customer
}
return nil
}
func (x *MainPaymentSettings) GetItems() []*Item {
if x != nil {
return x.Items
}
return nil
}
func (x *MainPaymentSettings) GetAuto() bool {
if x != nil {
return x.Auto
}
return false
}
func (x *MainPaymentSettings) GetRecurrent() bool {
if x != nil {
return x.Recurrent
}
return false
}
type Customer struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
FullName string `protobuf:"bytes,1,opt,name=FullName,proto3" json:"FullName,omitempty"`
INN string `protobuf:"bytes,2,opt,name=INN,proto3" json:"INN,omitempty"`
Email string `protobuf:"bytes,3,opt,name=Email,proto3" json:"Email,omitempty"`
Phone string `protobuf:"bytes,4,opt,name=Phone,proto3" json:"Phone,omitempty"`
}
func (x *Customer) Reset() {
*x = Customer{}
if protoimpl.UnsafeEnabled {
mi := &file_service_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Customer) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Customer) ProtoMessage() {}
func (x *Customer) ProtoReflect() protoreflect.Message {
mi := &file_service_proto_msgTypes[6]
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 Customer.ProtoReflect.Descriptor instead.
func (*Customer) Descriptor() ([]byte, []int) {
return file_service_proto_rawDescGZIP(), []int{6}
}
func (x *Customer) GetFullName() string {
if x != nil {
return x.FullName
}
return ""
}
func (x *Customer) GetINN() string {
if x != nil {
return x.INN
}
return ""
}
func (x *Customer) GetEmail() string {
if x != nil {
return x.Email
}
return ""
}
func (x *Customer) GetPhone() string {
if x != nil {
return x.Phone
}
return ""
}
type Item struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Description string `protobuf:"bytes,1,opt,name=Description,proto3" json:"Description,omitempty"`
Measure string `protobuf:"bytes,2,opt,name=Measure,proto3" json:"Measure,omitempty"`
Quantity string `protobuf:"bytes,3,opt,name=Quantity,proto3" json:"Quantity,omitempty"`
Money string `protobuf:"bytes,4,opt,name=Money,proto3" json:"Money,omitempty"`
Currency string `protobuf:"bytes,5,opt,name=Currency,proto3" json:"Currency,omitempty"`
}
func (x *Item) Reset() {
*x = Item{}
if protoimpl.UnsafeEnabled {
mi := &file_service_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Item) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Item) ProtoMessage() {}
func (x *Item) ProtoReflect() protoreflect.Message {
mi := &file_service_proto_msgTypes[7]
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 Item.ProtoReflect.Descriptor instead.
func (*Item) Descriptor() ([]byte, []int) {
return file_service_proto_rawDescGZIP(), []int{7}
}
func (x *Item) GetDescription() string {
if x != nil {
return x.Description
}
return ""
}
func (x *Item) GetMeasure() string {
if x != nil {
return x.Measure
}
return ""
}
func (x *Item) GetQuantity() string {
if x != nil {
return x.Quantity
}
return ""
}
func (x *Item) GetMoney() string {
if x != nil {
return x.Money
}
return ""
}
func (x *Item) GetCurrency() string {
if x != nil {
return x.Currency
}
return ""
}
var File_service_proto protoreflect.FileDescriptor
var file_service_proto_rawDesc = []byte{
0x0a, 0x0d, 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, 0x22, 0x63, 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, 0x22, 0x5b, 0x0a, 0x15,
0x47, 0x65, 0x74, 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, 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,
0x22, 0x3a, 0x0a, 0x20, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x61, 0x76, 0x65, 0x64, 0x50,
0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x22, 0xd1, 0x02, 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, 0x12, 0x2f, 0x0a, 0x08, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d,
0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73,
0x75, 0x72, 0x65, 0x72, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x52, 0x08, 0x43,
0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x05, 0x49, 0x74, 0x65, 0x6d, 0x73,
0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72,
0x65, 0x72, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x12,
0x0a, 0x04, 0x41, 0x75, 0x74, 0x6f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x41, 0x75,
0x74, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x52, 0x65, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x18,
0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x52, 0x65, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74,
0x22, 0x64, 0x0a, 0x08, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08,
0x46, 0x75, 0x6c, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
0x46, 0x75, 0x6c, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x49, 0x4e, 0x4e, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x49, 0x4e, 0x4e, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x6d,
0x61, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x6d, 0x61, 0x69, 0x6c,
0x12, 0x14, 0x0a, 0x05, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
0x05, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x22, 0x90, 0x01, 0x0a, 0x04, 0x49, 0x74, 0x65, 0x6d, 0x12,
0x20, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
0x6e, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x51,
0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x51,
0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x4d, 0x6f, 0x6e, 0x65, 0x79,
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x4d, 0x6f, 0x6e, 0x65, 0x79, 0x12, 0x1a, 0x0a,
0x08, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52,
0x08, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x32, 0xb8, 0x05, 0x0a, 0x10, 0x54, 0x72,
0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f,
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, 0x20, 0x2e, 0x74, 0x72, 0x65, 0x61, 0x73,
@ -299,63 +653,75 @@ var file_treasurer_service_proto_rawDesc = []byte{
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,
0x42, 0x0d, 0x5a, 0x0b, 0x2e, 0x2f, 0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x12, 0x62, 0x0a, 0x19, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x61, 0x76, 0x65, 0x64, 0x50,
0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x12, 0x2b, 0x2e,
0x74, 0x72, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x72, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
0x53, 0x61, 0x76, 0x65, 0x64, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x68,
0x6f, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 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, 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
file_service_proto_rawDescOnce sync.Once
file_service_proto_rawDescData = file_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)
func file_service_proto_rawDescGZIP() []byte {
file_service_proto_rawDescOnce.Do(func() {
file_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_proto_rawDescData)
})
return file_treasurer_service_proto_rawDescData
return file_service_proto_rawDescData
}
var file_treasurer_service_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_treasurer_service_proto_goTypes = []interface{}{
(*GetBankCardPaymentLinkRequest)(nil), // 0: treasurer.GetBankCardPaymentLinkRequest
(*GetPaymentLinkRequest)(nil), // 1: treasurer.GetPaymentLinkRequest
(*GetB2BPaymentLinkRequest)(nil), // 2: treasurer.GetB2BPaymentLinkRequest
(*GetPaymentLinkResponse)(nil), // 3: treasurer.GetPaymentLinkResponse
(*MainPaymentSettings)(nil), // 4: treasurer.MainPaymentSettings
(*emptypb.Empty)(nil), // 5: google.protobuf.Empty
var file_service_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_service_proto_goTypes = []interface{}{
(*GetBankCardPaymentLinkRequest)(nil), // 0: treasurer.GetBankCardPaymentLinkRequest
(*GetPaymentLinkRequest)(nil), // 1: treasurer.GetPaymentLinkRequest
(*GetB2BPaymentLinkRequest)(nil), // 2: treasurer.GetB2BPaymentLinkRequest
(*GetPaymentLinkResponse)(nil), // 3: treasurer.GetPaymentLinkResponse
(*DeleteSavedPaymentMethodsRequest)(nil), // 4: treasurer.DeleteSavedPaymentMethodsRequest
(*MainPaymentSettings)(nil), // 5: treasurer.MainPaymentSettings
(*Customer)(nil), // 6: treasurer.Customer
(*Item)(nil), // 7: treasurer.Item
(*emptypb.Empty)(nil), // 8: google.protobuf.Empty
}
var file_treasurer_service_proto_depIdxs = []int32{
4, // 0: treasurer.GetBankCardPaymentLinkRequest.MainSettings:type_name -> treasurer.MainPaymentSettings
4, // 1: treasurer.GetPaymentLinkRequest.MainSettings:type_name -> treasurer.MainPaymentSettings
4, // 2: treasurer.GetB2BPaymentLinkRequest.MainSettings:type_name -> treasurer.MainPaymentSettings
5, // 3: treasurer.GetB2BPaymentLinkRequest.VatData:type_name -> google.protobuf.Empty
1, // 4: treasurer.TreasurerService.GetPaymentLinkBankCard:input_type -> treasurer.GetPaymentLinkRequest
1, // 5: treasurer.TreasurerService.GetPaymentLinkYooMoney:input_type -> treasurer.GetPaymentLinkRequest
1, // 6: treasurer.TreasurerService.GetPaymentLinkTinkoff:input_type -> treasurer.GetPaymentLinkRequest
1, // 7: treasurer.TreasurerService.GetPaymentLinkSberbankB2B:input_type -> treasurer.GetPaymentLinkRequest
1, // 8: treasurer.TreasurerService.GetPaymentLinkSBP:input_type -> treasurer.GetPaymentLinkRequest
1, // 9: treasurer.TreasurerService.GetPaymentLinkSberPay:input_type -> treasurer.GetPaymentLinkRequest
3, // 10: treasurer.TreasurerService.GetPaymentLinkBankCard:output_type -> treasurer.GetPaymentLinkResponse
3, // 11: treasurer.TreasurerService.GetPaymentLinkYooMoney:output_type -> treasurer.GetPaymentLinkResponse
3, // 12: treasurer.TreasurerService.GetPaymentLinkTinkoff:output_type -> treasurer.GetPaymentLinkResponse
3, // 13: treasurer.TreasurerService.GetPaymentLinkSberbankB2B:output_type -> treasurer.GetPaymentLinkResponse
3, // 14: treasurer.TreasurerService.GetPaymentLinkSBP:output_type -> treasurer.GetPaymentLinkResponse
3, // 15: treasurer.TreasurerService.GetPaymentLinkSberPay:output_type -> treasurer.GetPaymentLinkResponse
10, // [10:16] is the sub-list for method output_type
4, // [4:10] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
var file_service_proto_depIdxs = []int32{
5, // 0: treasurer.GetBankCardPaymentLinkRequest.MainSettings:type_name -> treasurer.MainPaymentSettings
5, // 1: treasurer.GetPaymentLinkRequest.MainSettings:type_name -> treasurer.MainPaymentSettings
5, // 2: treasurer.GetB2BPaymentLinkRequest.MainSettings:type_name -> treasurer.MainPaymentSettings
8, // 3: treasurer.GetB2BPaymentLinkRequest.VatData:type_name -> google.protobuf.Empty
6, // 4: treasurer.MainPaymentSettings.Customer:type_name -> treasurer.Customer
7, // 5: treasurer.MainPaymentSettings.Items:type_name -> treasurer.Item
1, // 6: treasurer.TreasurerService.GetPaymentLinkBankCard:input_type -> treasurer.GetPaymentLinkRequest
1, // 7: treasurer.TreasurerService.GetPaymentLinkYooMoney:input_type -> treasurer.GetPaymentLinkRequest
1, // 8: treasurer.TreasurerService.GetPaymentLinkTinkoff:input_type -> treasurer.GetPaymentLinkRequest
1, // 9: treasurer.TreasurerService.GetPaymentLinkSberbankB2B:input_type -> treasurer.GetPaymentLinkRequest
1, // 10: treasurer.TreasurerService.GetPaymentLinkSBP:input_type -> treasurer.GetPaymentLinkRequest
1, // 11: treasurer.TreasurerService.GetPaymentLinkSberPay:input_type -> treasurer.GetPaymentLinkRequest
4, // 12: treasurer.TreasurerService.DeleteSavedPaymentMethods:input_type -> treasurer.DeleteSavedPaymentMethodsRequest
3, // 13: treasurer.TreasurerService.GetPaymentLinkBankCard:output_type -> treasurer.GetPaymentLinkResponse
3, // 14: treasurer.TreasurerService.GetPaymentLinkYooMoney:output_type -> treasurer.GetPaymentLinkResponse
3, // 15: treasurer.TreasurerService.GetPaymentLinkTinkoff:output_type -> treasurer.GetPaymentLinkResponse
3, // 16: treasurer.TreasurerService.GetPaymentLinkSberbankB2B:output_type -> treasurer.GetPaymentLinkResponse
3, // 17: treasurer.TreasurerService.GetPaymentLinkSBP:output_type -> treasurer.GetPaymentLinkResponse
3, // 18: treasurer.TreasurerService.GetPaymentLinkSberPay:output_type -> treasurer.GetPaymentLinkResponse
8, // 19: treasurer.TreasurerService.DeleteSavedPaymentMethods:output_type -> google.protobuf.Empty
13, // [13:20] is the sub-list for method output_type
6, // [6:13] 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_treasurer_service_proto_init() }
func file_treasurer_service_proto_init() {
if File_treasurer_service_proto != nil {
func init() { file_service_proto_init() }
func file_service_proto_init() {
if File_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{} {
file_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetBankCardPaymentLinkRequest); i {
case 0:
return &v.state
@ -367,7 +733,7 @@ func file_treasurer_service_proto_init() {
return nil
}
}
file_treasurer_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
file_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetPaymentLinkRequest); i {
case 0:
return &v.state
@ -379,7 +745,7 @@ func file_treasurer_service_proto_init() {
return nil
}
}
file_treasurer_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
file_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetB2BPaymentLinkRequest); i {
case 0:
return &v.state
@ -391,7 +757,7 @@ func file_treasurer_service_proto_init() {
return nil
}
}
file_treasurer_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
file_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetPaymentLinkResponse); i {
case 0:
return &v.state
@ -403,23 +769,71 @@ func file_treasurer_service_proto_init() {
return nil
}
}
file_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteSavedPaymentMethodsRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_service_proto_msgTypes[5].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_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Customer); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Item); 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,
RawDescriptor: file_service_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumMessages: 8,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_treasurer_service_proto_goTypes,
DependencyIndexes: file_treasurer_service_proto_depIdxs,
MessageInfos: file_treasurer_service_proto_msgTypes,
GoTypes: file_service_proto_goTypes,
DependencyIndexes: file_service_proto_depIdxs,
MessageInfos: file_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
File_service_proto = out.File
file_service_proto_rawDesc = nil
file_service_proto_goTypes = nil
file_service_proto_depIdxs = nil
}

@ -1,8 +1,4 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc (unknown)
// source: treasurer/service.proto
package treasurer
@ -11,6 +7,7 @@ import (
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
@ -18,15 +15,6 @@ import (
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
const (
TreasurerService_GetPaymentLinkBankCard_FullMethodName = "/treasurer.TreasurerService/GetPaymentLinkBankCard"
TreasurerService_GetPaymentLinkYooMoney_FullMethodName = "/treasurer.TreasurerService/GetPaymentLinkYooMoney"
TreasurerService_GetPaymentLinkTinkoff_FullMethodName = "/treasurer.TreasurerService/GetPaymentLinkTinkoff"
TreasurerService_GetPaymentLinkSberbankB2B_FullMethodName = "/treasurer.TreasurerService/GetPaymentLinkSberbankB2B"
TreasurerService_GetPaymentLinkSBP_FullMethodName = "/treasurer.TreasurerService/GetPaymentLinkSBP"
TreasurerService_GetPaymentLinkSberPay_FullMethodName = "/treasurer.TreasurerService/GetPaymentLinkSberPay"
)
// 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.
@ -37,6 +25,7 @@ type TreasurerServiceClient interface {
GetPaymentLinkSberbankB2B(ctx context.Context, in *GetPaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error)
GetPaymentLinkSBP(ctx context.Context, in *GetPaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error)
GetPaymentLinkSberPay(ctx context.Context, in *GetPaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error)
DeleteSavedPaymentMethods(ctx context.Context, in *DeleteSavedPaymentMethodsRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
}
type treasurerServiceClient struct {
@ -49,7 +38,7 @@ func NewTreasurerServiceClient(cc grpc.ClientConnInterface) TreasurerServiceClie
func (c *treasurerServiceClient) GetPaymentLinkBankCard(ctx context.Context, in *GetPaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error) {
out := new(GetPaymentLinkResponse)
err := c.cc.Invoke(ctx, TreasurerService_GetPaymentLinkBankCard_FullMethodName, in, out, opts...)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/GetPaymentLinkBankCard", in, out, opts...)
if err != nil {
return nil, err
}
@ -58,7 +47,7 @@ func (c *treasurerServiceClient) GetPaymentLinkBankCard(ctx context.Context, in
func (c *treasurerServiceClient) GetPaymentLinkYooMoney(ctx context.Context, in *GetPaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error) {
out := new(GetPaymentLinkResponse)
err := c.cc.Invoke(ctx, TreasurerService_GetPaymentLinkYooMoney_FullMethodName, in, out, opts...)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/GetPaymentLinkYooMoney", in, out, opts...)
if err != nil {
return nil, err
}
@ -67,7 +56,7 @@ func (c *treasurerServiceClient) GetPaymentLinkYooMoney(ctx context.Context, in
func (c *treasurerServiceClient) GetPaymentLinkTinkoff(ctx context.Context, in *GetPaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error) {
out := new(GetPaymentLinkResponse)
err := c.cc.Invoke(ctx, TreasurerService_GetPaymentLinkTinkoff_FullMethodName, in, out, opts...)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/GetPaymentLinkTinkoff", in, out, opts...)
if err != nil {
return nil, err
}
@ -76,7 +65,7 @@ func (c *treasurerServiceClient) GetPaymentLinkTinkoff(ctx context.Context, in *
func (c *treasurerServiceClient) GetPaymentLinkSberbankB2B(ctx context.Context, in *GetPaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error) {
out := new(GetPaymentLinkResponse)
err := c.cc.Invoke(ctx, TreasurerService_GetPaymentLinkSberbankB2B_FullMethodName, in, out, opts...)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/GetPaymentLinkSberbankB2B", in, out, opts...)
if err != nil {
return nil, err
}
@ -85,7 +74,7 @@ func (c *treasurerServiceClient) GetPaymentLinkSberbankB2B(ctx context.Context,
func (c *treasurerServiceClient) GetPaymentLinkSBP(ctx context.Context, in *GetPaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error) {
out := new(GetPaymentLinkResponse)
err := c.cc.Invoke(ctx, TreasurerService_GetPaymentLinkSBP_FullMethodName, in, out, opts...)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/GetPaymentLinkSBP", in, out, opts...)
if err != nil {
return nil, err
}
@ -94,7 +83,16 @@ func (c *treasurerServiceClient) GetPaymentLinkSBP(ctx context.Context, in *GetP
func (c *treasurerServiceClient) GetPaymentLinkSberPay(ctx context.Context, in *GetPaymentLinkRequest, opts ...grpc.CallOption) (*GetPaymentLinkResponse, error) {
out := new(GetPaymentLinkResponse)
err := c.cc.Invoke(ctx, TreasurerService_GetPaymentLinkSberPay_FullMethodName, in, out, opts...)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/GetPaymentLinkSberPay", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *treasurerServiceClient) DeleteSavedPaymentMethods(ctx context.Context, in *DeleteSavedPaymentMethodsRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
out := new(emptypb.Empty)
err := c.cc.Invoke(ctx, "/treasurer.TreasurerService/DeleteSavedPaymentMethods", in, out, opts...)
if err != nil {
return nil, err
}
@ -102,7 +100,7 @@ func (c *treasurerServiceClient) GetPaymentLinkSberPay(ctx context.Context, in *
}
// TreasurerServiceServer is the server API for TreasurerService service.
// All implementations should embed UnimplementedTreasurerServiceServer
// All implementations must embed UnimplementedTreasurerServiceServer
// for forward compatibility
type TreasurerServiceServer interface {
GetPaymentLinkBankCard(context.Context, *GetPaymentLinkRequest) (*GetPaymentLinkResponse, error)
@ -111,9 +109,11 @@ type TreasurerServiceServer interface {
GetPaymentLinkSberbankB2B(context.Context, *GetPaymentLinkRequest) (*GetPaymentLinkResponse, error)
GetPaymentLinkSBP(context.Context, *GetPaymentLinkRequest) (*GetPaymentLinkResponse, error)
GetPaymentLinkSberPay(context.Context, *GetPaymentLinkRequest) (*GetPaymentLinkResponse, error)
DeleteSavedPaymentMethods(context.Context, *DeleteSavedPaymentMethodsRequest) (*emptypb.Empty, error)
mustEmbedUnimplementedTreasurerServiceServer()
}
// UnimplementedTreasurerServiceServer should be embedded to have forward compatible implementations.
// UnimplementedTreasurerServiceServer must be embedded to have forward compatible implementations.
type UnimplementedTreasurerServiceServer struct {
}
@ -135,6 +135,10 @@ func (UnimplementedTreasurerServiceServer) GetPaymentLinkSBP(context.Context, *G
func (UnimplementedTreasurerServiceServer) GetPaymentLinkSberPay(context.Context, *GetPaymentLinkRequest) (*GetPaymentLinkResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPaymentLinkSberPay not implemented")
}
func (UnimplementedTreasurerServiceServer) DeleteSavedPaymentMethods(context.Context, *DeleteSavedPaymentMethodsRequest) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteSavedPaymentMethods not implemented")
}
func (UnimplementedTreasurerServiceServer) mustEmbedUnimplementedTreasurerServiceServer() {}
// 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
@ -157,7 +161,7 @@ func _TreasurerService_GetPaymentLinkBankCard_Handler(srv interface{}, ctx conte
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: TreasurerService_GetPaymentLinkBankCard_FullMethodName,
FullMethod: "/treasurer.TreasurerService/GetPaymentLinkBankCard",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).GetPaymentLinkBankCard(ctx, req.(*GetPaymentLinkRequest))
@ -175,7 +179,7 @@ func _TreasurerService_GetPaymentLinkYooMoney_Handler(srv interface{}, ctx conte
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: TreasurerService_GetPaymentLinkYooMoney_FullMethodName,
FullMethod: "/treasurer.TreasurerService/GetPaymentLinkYooMoney",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).GetPaymentLinkYooMoney(ctx, req.(*GetPaymentLinkRequest))
@ -193,7 +197,7 @@ func _TreasurerService_GetPaymentLinkTinkoff_Handler(srv interface{}, ctx contex
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: TreasurerService_GetPaymentLinkTinkoff_FullMethodName,
FullMethod: "/treasurer.TreasurerService/GetPaymentLinkTinkoff",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).GetPaymentLinkTinkoff(ctx, req.(*GetPaymentLinkRequest))
@ -211,7 +215,7 @@ func _TreasurerService_GetPaymentLinkSberbankB2B_Handler(srv interface{}, ctx co
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: TreasurerService_GetPaymentLinkSberbankB2B_FullMethodName,
FullMethod: "/treasurer.TreasurerService/GetPaymentLinkSberbankB2B",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).GetPaymentLinkSberbankB2B(ctx, req.(*GetPaymentLinkRequest))
@ -229,7 +233,7 @@ func _TreasurerService_GetPaymentLinkSBP_Handler(srv interface{}, ctx context.Co
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: TreasurerService_GetPaymentLinkSBP_FullMethodName,
FullMethod: "/treasurer.TreasurerService/GetPaymentLinkSBP",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).GetPaymentLinkSBP(ctx, req.(*GetPaymentLinkRequest))
@ -247,7 +251,7 @@ func _TreasurerService_GetPaymentLinkSberPay_Handler(srv interface{}, ctx contex
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: TreasurerService_GetPaymentLinkSberPay_FullMethodName,
FullMethod: "/treasurer.TreasurerService/GetPaymentLinkSberPay",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).GetPaymentLinkSberPay(ctx, req.(*GetPaymentLinkRequest))
@ -255,6 +259,24 @@ func _TreasurerService_GetPaymentLinkSberPay_Handler(srv interface{}, ctx contex
return interceptor(ctx, in, info, handler)
}
func _TreasurerService_DeleteSavedPaymentMethods_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteSavedPaymentMethodsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TreasurerServiceServer).DeleteSavedPaymentMethods(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/treasurer.TreasurerService/DeleteSavedPaymentMethods",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TreasurerServiceServer).DeleteSavedPaymentMethods(ctx, req.(*DeleteSavedPaymentMethodsRequest))
}
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)
@ -286,7 +308,11 @@ var TreasurerService_ServiceDesc = grpc.ServiceDesc{
MethodName: "GetPaymentLinkSberPay",
Handler: _TreasurerService_GetPaymentLinkSberPay_Handler,
},
{
MethodName: "DeleteSavedPaymentMethods",
Handler: _TreasurerService_DeleteSavedPaymentMethods_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "treasurer/service.proto",
Metadata: "service.proto",
}

@ -75,7 +75,7 @@ func NewPaymentRepository(deps PaymentRepositoryDeps) (*PaymentRepository, error
}, nil
}
func (receiver *PaymentRepository) SetPaymentComplete(ctx context.Context, paymentID string) (*models.Payment, errors.Error) {
func (r *PaymentRepository) SetPaymentComplete(ctx context.Context, paymentID string) (*models.Payment, errors.Error) {
payment := models.Payment{}
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
filter := bson.M{PaymentFields.PaymentID: paymentID}
@ -84,8 +84,8 @@ func (receiver *PaymentRepository) SetPaymentComplete(ctx context.Context, payme
PaymentFields.UpdatedAt: time.Now(),
}}
if err := receiver.collection.FindOneAndUpdate(ctx, filter, update, options).Decode(&payment); err != nil {
receiver.logger.Error("failed to set payment complete on <SetPaymentComplete> of <PaymentRepository>",
if err := r.collection.FindOneAndUpdate(ctx, filter, update, options).Decode(&payment); err != nil {
r.logger.Error("failed to set payment complete on <SetPaymentComplete> of <PaymentRepository>",
zap.Error(err),
zap.String("paymentID", paymentID),
)
@ -105,12 +105,12 @@ func (receiver *PaymentRepository) SetPaymentComplete(ctx context.Context, payme
return &payment, nil
}
func (receiver *PaymentRepository) Insert(ctx context.Context, payment *models.Payment) (*models.Payment, errors.Error) {
func (r *PaymentRepository) Insert(ctx context.Context, payment *models.Payment) (*models.Payment, errors.Error) {
sanitizedPayment := payment.Sanitize()
result, err := receiver.collection.InsertOne(ctx, sanitizedPayment)
result, err := r.collection.InsertOne(ctx, sanitizedPayment)
if err != nil {
receiver.logger.Error("failed to insert payment on <Insert> of <PaymentRepository>",
r.logger.Error("failed to insert payment on <Insert> of <PaymentRepository>",
zap.Any("payment", sanitizedPayment),
zap.Error(err),
)
@ -127,7 +127,7 @@ func (receiver *PaymentRepository) Insert(ctx context.Context, payment *models.P
return sanitizedPayment, nil
}
func (receiver *PaymentRepository) SetPaymentStatus(ctx context.Context, paymentID string, status models.PaymentStatus) (*models.Payment, errors.Error) {
func (r *PaymentRepository) SetPaymentStatus(ctx context.Context, paymentID string, status models.PaymentStatus) (*models.Payment, errors.Error) {
payment := models.Payment{}
options := options.FindOneAndUpdate().SetReturnDocument(options.After)
filter := bson.M{PaymentFields.PaymentID: paymentID}
@ -136,8 +136,8 @@ func (receiver *PaymentRepository) SetPaymentStatus(ctx context.Context, payment
PaymentFields.UpdatedAt: time.Now(),
}}
if err := receiver.collection.FindOneAndUpdate(ctx, filter, update, options).Decode(&payment); err != nil {
receiver.logger.Error("failed to set payment status on <SetPaymentStatus> of <PaymentRepository>",
if err := r.collection.FindOneAndUpdate(ctx, filter, update, options).Decode(&payment); err != nil {
r.logger.Error("failed to set payment status on <SetPaymentStatus> of <PaymentRepository>",
zap.Error(err),
zap.String("paymentID", paymentID),
)

@ -0,0 +1,61 @@
package repository
import (
"context"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.uber.org/zap"
)
type PaymentMethodRepositoryDeps struct {
Logger *zap.Logger
Collection *mongo.Collection
}
type PaymentMethodRepository struct {
logger *zap.Logger
collection *mongo.Collection
}
func NewPaymentMethodRepository(deps PaymentMethodRepositoryDeps) *PaymentMethodRepository {
return &PaymentMethodRepository{
logger: deps.Logger,
collection: deps.Collection,
}
}
func (r *PaymentMethodRepository) Save(ctx context.Context, method *yandex.PaymentMethod) error {
_, err := r.collection.InsertOne(ctx, method)
if err != nil {
r.logger.Error("failed to save payment method", zap.Error(err), zap.String("userId", method.UserID))
return err
}
return nil
}
func (r *PaymentMethodRepository) GetByUserID(ctx context.Context, userID string) ([]*yandex.PaymentMethod, error) {
cursor, err := r.collection.Find(ctx, bson.M{"userId": userID})
if err != nil {
r.logger.Error("failed to find payment methods", zap.Error(err), zap.String("userId", userID))
return nil, err
}
defer cursor.Close(ctx)
var methods []*yandex.PaymentMethod
if err := cursor.All(ctx, &methods); err != nil {
r.logger.Error("failed to decode payment methods", zap.Error(err), zap.String("userId", userID))
return nil, err
}
return methods, nil
}
func (r *PaymentMethodRepository) DeleteByUserID(ctx context.Context, userID string) error {
_, err := r.collection.DeleteMany(ctx, bson.M{"userId": userID})
if err != nil {
r.logger.Error("failed to delete payment methods", zap.Error(err), zap.String("userId", userID))
return err
}
return nil
}

@ -1,79 +0,0 @@
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"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/proto/treasurer"
)
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(server treasurer.TreasurerServiceServer) *GRPC {
treasurer.RegisterTreasurerServiceServer(receiver.grpc, server)
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)
}

@ -0,0 +1,69 @@
package grpc
import (
"context"
"fmt"
"net"
"time"
"gitea.pena/PenaSide/treasurer/internal/proto/treasurer"
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"
)
type GRPC struct {
grpc *grpc.Server
logger *zap.Logger
}
func NewGRPC(logger *zap.Logger) (*GRPC, error) {
grpcStreamInterceptor := grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
grpc_zap.StreamServerInterceptor(logger),
grpc_recovery.StreamServerInterceptor(),
))
grpcUnaryInterceptor := grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
grpc_zap.UnaryServerInterceptor(logger),
grpc_recovery.UnaryServerInterceptor(),
))
return &GRPC{
grpc: grpc.NewServer(grpcStreamInterceptor, grpcUnaryInterceptor, grpc.ConnectionTimeout(5*time.Second)),
logger: logger,
}, nil
}
func (s *GRPC) Run(addr string) {
connectionString := fmt.Sprintf(addr)
s.logger.Info("Starting GRPC Server", zap.String("host", connectionString))
if err := s.listen(connectionString); err != nil && err != grpc.ErrServerStopped {
s.logger.Error("GRPC Listen error", zap.Error(err))
}
}
func (s *GRPC) Stop(_ context.Context) error {
s.grpc.GracefulStop()
s.logger.Info("Shutting down GRPC server...")
return nil
}
func (s *GRPC) Register(server treasurer.TreasurerServiceServer) *GRPC {
treasurer.RegisterTreasurerServiceServer(s.grpc, server)
return s
}
func (s *GRPC) listen(address string) error {
listener, err := net.Listen("tcp", address)
if err != nil {
return err
}
return s.grpc.Serve(listener)
}

@ -1,86 +0,0 @@
package server
import (
"context"
"fmt"
"net/http"
"time"
"github.com/getkin/kin-openapi/openapi3"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/interface/swagger"
"gitea.pena/PenaSide/treasurer/internal/models"
)
type DepsHTTP struct {
Logger *zap.Logger
Swagger *openapi3.T
}
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("Logger is nil on <NewHTTP>", errors.ErrInvalidArgs)
}
if deps.Swagger == nil {
return nil, errors.NewWithMessage("Swagger is nil on <NewHTTP>", errors.ErrInvalidArgs)
}
echo := echo.New()
echo.Use(middleware.Recover())
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,65 @@
package http
import (
"context"
"fmt"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
)
type ServerConfig struct {
Logger *zap.Logger
Controllers []Controller
}
type Server struct {
Logger *zap.Logger
Controllers []Controller
app *fiber.App
}
func NewServer(config ServerConfig) *Server {
app := fiber.New()
s := &Server{
Logger: config.Logger,
Controllers: config.Controllers,
app: app,
}
s.registerRoutes()
return s
}
func (s *Server) Start(addr string) error {
if err := s.app.Listen(addr); err != nil {
s.Logger.Error("Failed to start server", zap.Error(err))
return err
}
return nil
}
func (s *Server) Shutdown(ctx context.Context) error {
return s.app.Shutdown()
}
func (s *Server) registerRoutes() {
for _, c := range s.Controllers {
router := s.app.Group(c.Name())
c.Register(router)
}
}
type Controller interface {
Register(router fiber.Router)
Name() string
}
func (s *Server) ListRoutes() {
fmt.Println("Registered routes:")
for _, stack := range s.app.Stack() {
for _, route := range stack {
fmt.Printf("%s %s\n", route.Method, route.Path)
}
}
}

@ -2,32 +2,25 @@ package callback
import (
"context"
"gitea.pena/PenaSide/treasurer/internal/client"
"gitea.pena/PenaSide/treasurer/internal/repository"
"sync"
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models"
"go.uber.org/zap"
)
type CallbackClient interface {
SendOnSuccess(ctx context.Context, host string, event *models.Event) errors.Error
SendOnFailure(ctx context.Context, host string, event *models.Event) errors.Error
}
type PaymentRepository interface {
SetPaymentComplete(ctx context.Context, paymentID string) (*models.Payment, errors.Error)
}
type Deps struct {
Logger *zap.Logger
CallbackClient CallbackClient
PaymentRepository PaymentRepository
CallbackClient *client.CallbackClient
PaymentRepository *repository.PaymentRepository
}
type Service struct {
logger *zap.Logger
callbackClient CallbackClient
paymentRepository PaymentRepository
callbackClient *client.CallbackClient
paymentRepository *repository.PaymentRepository
}
func New(deps Deps) (*Service, errors.Error) {
@ -50,7 +43,7 @@ func New(deps Deps) (*Service, errors.Error) {
}, nil
}
func (receiver *Service) OnSuccess(ctx context.Context, event *models.Event) errors.Error {
func (s *Service) OnSuccess(ctx context.Context, event *models.Event) errors.Error {
waitGroup := sync.WaitGroup{}
mutex := sync.Mutex{}
executeErrors := make([]error, 0)
@ -61,8 +54,8 @@ func (receiver *Service) OnSuccess(ctx context.Context, event *models.Event) err
go func(url string) {
defer waitGroup.Done()
if err := receiver.callbackClient.SendOnSuccess(ctx, url, event); err != nil {
receiver.logger.Error("failid to send callback on <OnSuccess> of <CallbackService>")
if err := s.callbackClient.SendOnSuccess(ctx, url, event); err != nil {
s.logger.Error("failid to send callback on <OnSuccess> of <CallbackService>")
mutex.Lock()
executeErrors = append(executeErrors, err)
@ -71,8 +64,8 @@ func (receiver *Service) OnSuccess(ctx context.Context, event *models.Event) err
return
}
if _, err := receiver.paymentRepository.SetPaymentComplete(ctx, event.Payment.PaymentID); err != nil {
receiver.logger.Error("failid to set payment complete on <OnSuccess> of <CallbackService>")
if _, err := s.paymentRepository.SetPaymentComplete(ctx, event.Payment.PaymentID); err != nil {
s.logger.Error("failid to set payment complete on <OnSuccess> of <CallbackService>")
mutex.Lock()
executeErrors = append(executeErrors, err)
@ -86,14 +79,14 @@ func (receiver *Service) OnSuccess(ctx context.Context, event *models.Event) err
waitGroup.Wait()
if len(executeErrors) >= len(event.Payment.CallbackHostGRPC) {
receiver.logger.Error("failid to success payment on <OnSuccess> of <CallbackService>", zap.Errors("errors", executeErrors))
s.logger.Error("failid to success payment on <OnSuccess> of <CallbackService>", zap.Errors("errors", executeErrors))
return errors.NewWithMessage("failed to success payment: all operations failed", errors.ErrInternalError)
}
return nil
}
func (receiver *Service) OnFailure(ctx context.Context, event *models.Event) errors.Error {
func (s *Service) OnFailure(ctx context.Context, event *models.Event) errors.Error {
waitGroup := sync.WaitGroup{}
mutex := sync.Mutex{}
executeErrors := make([]error, 0)
@ -104,8 +97,8 @@ func (receiver *Service) OnFailure(ctx context.Context, event *models.Event) err
go func(url string) {
defer waitGroup.Done()
if err := receiver.callbackClient.SendOnFailure(ctx, url, event); err != nil {
receiver.logger.Error("failid to send callback on <OnFailure> of <CallbackService>")
if err := s.callbackClient.SendOnFailure(ctx, url, event); err != nil {
s.logger.Error("failid to send callback on <OnFailure> of <CallbackService>")
mutex.Lock()
executeErrors = append(executeErrors, err)
@ -119,7 +112,7 @@ func (receiver *Service) OnFailure(ctx context.Context, event *models.Event) err
waitGroup.Wait()
if len(executeErrors) >= len(event.Payment.CallbackHostGRPC) {
receiver.logger.Error("failid to success payment on <OnFailure> of <CallbackService>", zap.Errors("errors", executeErrors))
s.logger.Error("failid to success payment on <OnFailure> of <CallbackService>", zap.Errors("errors", executeErrors))
return errors.NewWithMessage("failed to success payment: all operations failed", errors.ErrInternalError)
}

@ -1,27 +1,23 @@
package mock
import (
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/pkg/validate"
"go.uber.org/zap"
)
type MockStrategyService interface {
Register(host string) errors.Error
}
type Deps struct {
Logger *zap.Logger
MockServiceHost string
Enabled bool
YoomoneyMockService MockStrategyService
YoomoneyMockService *YoomoneyMockService
}
type Service struct {
logger *zap.Logger
mockServiceHost string
enabled bool
yoomoneyMockService MockStrategyService
yoomoneyMockService *YoomoneyMockService
}
func New(deps Deps) (*Service, errors.Error) {
@ -45,14 +41,14 @@ func New(deps Deps) (*Service, errors.Error) {
}, nil
}
func (receiver *Service) Register() bool {
if !receiver.enabled {
receiver.logger.Info("register mocks is disabled")
func (s *Service) Register() bool {
if !s.enabled {
s.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))
if err := s.yoomoneyMockService.Register(s.mockServiceHost); err != nil {
s.logger.Error("failed to register yoomoney mocks", zap.Error(err), zap.String("host", s.mockServiceHost))
return false
}

@ -4,21 +4,20 @@ import (
"fmt"
"net/url"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"github.com/walkerus/go-wiremock"
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
)
type YoomoneyMockServiceDeps struct {
Logger *zap.Logger
YoomoneyURL *models.YoomomeyURL
Logger *zap.Logger
YooMoneyPaymentsURL string
}
type YoomoneyMockService struct {
logger *zap.Logger
yoomoneyURL *models.YoomomeyURL
logger *zap.Logger
yooMoneyPaymentsURL string
}
func NewYoomoneyMockService(deps YoomoneyMockServiceDeps) (*YoomoneyMockService, errors.Error) {
@ -26,26 +25,22 @@ func NewYoomoneyMockService(deps YoomoneyMockServiceDeps) (*YoomoneyMockService,
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,
logger: deps.Logger,
yooMoneyPaymentsURL: deps.YooMoneyPaymentsURL,
}, nil
}
func (receiver *YoomoneyMockService) Register(host string) errors.Error {
return receiver.RegisterPayments(host)
func (s *YoomoneyMockService) Register(host string) errors.Error {
return s.RegisterPayments(host)
}
func (receiver *YoomoneyMockService) RegisterPayments(host string) errors.Error {
paymentsURL, parseErr := url.Parse(receiver.yoomoneyURL.Payments)
func (s *YoomoneyMockService) RegisterPayments(host string) errors.Error {
paymentsURL, parseErr := url.Parse(s.yooMoneyPaymentsURL)
if parseErr != nil {
receiver.logger.Error("failed to parse payment url on <RegisterPayment> of <YoomoneyMockService>",
s.logger.Error("failed to parse payment url on <RegisterPayment> of <YoomoneyMockService>",
zap.Error(parseErr),
zap.String("url", receiver.yoomoneyURL.Payments),
zap.String("url", s.yooMoneyPaymentsURL),
)
return errors.NewWithError(fmt.Errorf("failed to parse payment url: %w", parseErr), errors.ErrInternalError)
@ -53,9 +48,9 @@ func (receiver *YoomoneyMockService) RegisterPayments(host string) errors.Error
hostURL, parseErr := url.Parse(host)
if parseErr != nil {
receiver.logger.Error("failed to parse payment url on <RegisterPayment> of <YoomoneyMockService>",
s.logger.Error("failed to parse payment url on <RegisterPayment> of <YoomoneyMockService>",
zap.Error(parseErr),
zap.String("url", receiver.yoomoneyURL.Payments),
zap.String("url", s.yooMoneyPaymentsURL),
)
return errors.NewWithError(fmt.Errorf("failed to parse payment url: %w", parseErr), errors.ErrInternalError)
@ -92,9 +87,9 @@ func (receiver *YoomoneyMockService) RegisterPayments(host string) errors.Error
AtPriority(1)
if err := mockClient.StubFor(rule); err != nil {
receiver.logger.Error("failed to init payment mock handler on <RegisterPayment> of <YoomoneyMockService>",
s.logger.Error("failed to init payment mock handler on <RegisterPayment> of <YoomoneyMockService>",
zap.Error(err),
zap.String("payments full url", receiver.yoomoneyURL.Payments),
zap.String("payments full url", s.yooMoneyPaymentsURL),
zap.String("payments path", paymentsURL.Path),
)
@ -103,9 +98,9 @@ func (receiver *YoomoneyMockService) RegisterPayments(host string) errors.Error
isVerified, err := mockClient.Verify(wiremock.NewRequest("post", wiremock.URLPathEqualTo(paymentsURL.Path)), 0)
if err != nil {
receiver.logger.Error("failed to verify payment mock handler on <RegisterPayment> of <YoomoneyMockService>",
s.logger.Error("failed to verify payment mock handler on <RegisterPayment> of <YoomoneyMockService>",
zap.Error(err),
zap.String("payments full url", receiver.yoomoneyURL.Payments),
zap.String("payments full url", s.yooMoneyPaymentsURL),
zap.String("payments path", paymentsURL.Path),
)

@ -3,33 +3,25 @@ package payment
import (
"context"
"fmt"
"gitea.pena/PenaSide/treasurer/internal/repository"
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/utils"
"go.uber.org/zap"
)
type PaymentStrategyService interface {
CreatePaymentBankCard(ctx context.Context, uuid string, payment *models.CreatePayment[yandex.Receipt]) (*models.CreatePaymentResult, errors.Error)
CreatePayment(ctx context.Context, uuid string, payment *models.CreatePayment[yandex.Receipt]) (*models.CreatePaymentResult, errors.Error)
}
type PaymentRepository interface {
Insert(context.Context, *models.Payment) (*models.Payment, errors.Error)
}
type Deps struct {
Logger *zap.Logger
PaymentStrategyService PaymentStrategyService
PaymentRepository PaymentRepository
PaymentStrategyService *Yandex
PaymentRepository *repository.PaymentRepository
}
type Service struct {
logger *zap.Logger
paymentStrategyService PaymentStrategyService
paymentRepository PaymentRepository
paymentStrategyService *Yandex
paymentRepository *repository.PaymentRepository
}
func New(deps Deps) (*Service, errors.Error) {
@ -52,43 +44,43 @@ func New(deps Deps) (*Service, errors.Error) {
}, nil
}
func (receiver *Service) CreatePaymentBankCard(ctx context.Context, request *models.CreatePayment[yandex.Receipt]) (string, errors.Error) {
receiver.logger.Info("f<CreatePaymentBankCard> of <YandexPaymentService>", zap.Any("Customer", request.Requisites.Customer), zap.Any("Items",request.Requisites.Items))
func (s *Service) CreatePaymentBankCard(ctx context.Context, request *models.CreatePayment[yandex.Receipt]) (string, errors.Error) {
s.logger.Info("f<CreatePaymentBankCard> of <YandexPaymentService>", zap.Any("Customer", request.Requisites.Customer), zap.Any("Items", request.Requisites.Items))
paymentUUID, generateErr := utils.GenerateUUID()
if generateErr != nil {
receiver.logger.Error("failed to generate uuid on <CreatePaymentBankCard> of <PaymentService>", zap.Error(generateErr))
s.logger.Error("failed to generate uuid on <CreatePaymentBankCard> of <PaymentService>", zap.Error(generateErr))
return "", errors.NewWithError(fmt.Errorf("failed to generate uuid: %w", generateErr), errors.ErrInternalError)
}
response, err := receiver.paymentStrategyService.CreatePaymentBankCard(ctx, paymentUUID, request)
response, err := s.paymentStrategyService.CreatePaymentBankCard(ctx, paymentUUID, request)
if err != nil {
receiver.logger.Error("failed to create payment on <CreatePaymentBankCard> of <PaymentService>", zap.Error(err))
s.logger.Error("failed to create payment on <CreatePaymentBankCard> of <PaymentService>", zap.Error(err))
return "", err
}
if _, err := receiver.paymentRepository.Insert(ctx, response.Payment); err != nil {
receiver.logger.Error("failed to insert payment on <CreatePaymentBankCard> of <PaymentService>", zap.Error(err))
if _, err := s.paymentRepository.Insert(ctx, response.Payment); err != nil {
s.logger.Error("failed to insert payment on <CreatePaymentBankCard> of <PaymentService>", zap.Error(err))
return "", err
}
return response.RedirectURL, nil
}
func (receiver *Service) CreatePayment(ctx context.Context, request *models.CreatePayment[yandex.Receipt]) (string, errors.Error) {
func (s *Service) CreatePayment(ctx context.Context, request *models.CreatePayment[yandex.Receipt]) (string, errors.Error) {
paymentUUID, generateErr := utils.GenerateUUID()
if generateErr != nil {
receiver.logger.Error("failed to generate uuid on <CreatePayment> of <PaymentService>", zap.Error(generateErr))
s.logger.Error("failed to generate uuid on <CreatePayment> of <PaymentService>", zap.Error(generateErr))
return "", errors.NewWithError(fmt.Errorf("failed to generate uuid: %w", generateErr), errors.ErrInternalError)
}
response, err := receiver.paymentStrategyService.CreatePayment(ctx, paymentUUID, request)
response, err := s.paymentStrategyService.CreatePayment(ctx, paymentUUID, request)
if err != nil {
receiver.logger.Error("failed to create payment on <CreatePayment> of <PaymentService>", zap.Error(err))
s.logger.Error("failed to create payment on <CreatePayment> of <PaymentService>", zap.Error(err))
return "", err
}
if _, err := receiver.paymentRepository.Insert(ctx, response.Payment); err != nil {
receiver.logger.Error("failed to insert payment on <CreatePayment> of <PaymentService>", zap.Error(err))
if _, err := s.paymentRepository.Insert(ctx, response.Payment); err != nil {
s.logger.Error("failed to insert payment on <CreatePayment> of <PaymentService>", zap.Error(err))
return "", err
}

@ -2,28 +2,23 @@ package payment
import (
"context"
"gitea.pena/PenaSide/treasurer/internal/client"
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/utils"
"go.uber.org/zap"
)
type YandexPaymentClient interface {
CreatePayment(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodType]) (*yandex.Payment, errors.Error)
CreatePaymentBankCard(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodBankCard]) (*yandex.Payment, errors.Error)
CreatePaymentB2B(ctx context.Context, idempotenceKey string, request *yandex.CreatePaymentRequest[yandex.PaymentMethodB2B]) (*yandex.Payment, errors.Error)
}
type YandexPaymentServiceDeps struct {
Logger *zap.Logger
YandexPaymentClient YandexPaymentClient
YandexPaymentClient *client.YandexClient
}
type Yandex struct {
logger *zap.Logger
yandexPaymentClient YandexPaymentClient
yandexPaymentClient *client.YandexClient
}
func NewYandex(deps YandexPaymentServiceDeps) (*Yandex, errors.Error) {
@ -41,9 +36,9 @@ func NewYandex(deps YandexPaymentServiceDeps) (*Yandex, errors.Error) {
}, nil
}
func (receiver *Yandex) CreatePaymentBankCard(ctx context.Context, uuid string, request *models.CreatePayment[yandex.Receipt]) (*models.CreatePaymentResult, errors.Error) {
receiver.logger.Info("f<CreatePaymentBankCard> of <YandexPaymentService>", zap.Any("Customer", request.Requisites.Customer), zap.Any("Items",request.Requisites.Items))
yandexPayment, err := receiver.yandexPaymentClient.CreatePaymentBankCard(ctx, uuid, &yandex.CreatePaymentRequest[yandex.PaymentMethodBankCard]{
func (s *Yandex) CreatePaymentBankCard(ctx context.Context, uuid string, request *models.CreatePayment[yandex.Receipt]) (*models.CreatePaymentResult, errors.Error) {
s.logger.Info("f<CreatePaymentBankCard> of <YandexPaymentService>", zap.Any("Customer", request.Requisites.Customer), zap.Any("Items", request.Requisites.Items))
yandexPayment, err := s.yandexPaymentClient.CreatePaymentBankCard(ctx, uuid, &yandex.CreatePaymentRequest[yandex.PaymentMethodBankCard]{
Amount: yandex.Amount{
Value: utils.ConvertAmountToStringFloat(request.Amount),
Currency: request.Currency,
@ -51,8 +46,8 @@ func (receiver *Yandex) CreatePaymentBankCard(ctx context.Context, uuid string,
Description: "Пополнение пользовательского баланса платформы Pena Hub",
Receipt: yandex.Receipt{
TaxSystemCode: 2, //https://yookassa.ru/developers/payment-acceptance/receipts/54fz/other-services/parameters-values#tax-systems
Customer: request.Requisites.Customer,
Items: request.Requisites.Items,
Customer: request.Requisites.Customer,
Items: request.Requisites.Items,
},
PaymentMethodData: &yandex.PaymentMethodBankCard{
Type: models.YandexPaymentTypeMap[request.Type],
@ -67,7 +62,7 @@ func (receiver *Yandex) CreatePaymentBankCard(ctx context.Context, uuid string,
ClientIP: request.ClientIP,
})
if err != nil {
receiver.logger.Error("failed to create payment on <CreatePaymentBankCard> of <YandexPaymentService>", zap.Error(err))
s.logger.Error("failed to create payment on <CreatePaymentBankCard> of <YandexPaymentService>", zap.Error(err))
return nil, err
}
@ -89,16 +84,16 @@ func (receiver *Yandex) CreatePaymentBankCard(ctx context.Context, uuid string,
}, nil
}
func (receiver *Yandex) CreatePayment(ctx context.Context, uuid string, request *models.CreatePayment[yandex.Receipt]) (*models.CreatePaymentResult, errors.Error) {
yandexPayment, err := receiver.yandexPaymentClient.CreatePayment(ctx, uuid, &yandex.CreatePaymentRequest[yandex.PaymentMethodType]{
func (s *Yandex) CreatePayment(ctx context.Context, uuid string, request *models.CreatePayment[yandex.Receipt]) (*models.CreatePaymentResult, errors.Error) {
yandexPayment, err := s.yandexPaymentClient.CreatePayment(ctx, uuid, &yandex.CreatePaymentRequest[yandex.PaymentMethodType]{
Amount: yandex.Amount{
Value: utils.ConvertAmountToStringFloat(request.Amount),
Currency: request.Currency,
},
Receipt: yandex.Receipt{
TaxSystemCode: 2, //https://yookassa.ru/developers/payment-acceptance/receipts/54fz/other-services/parameters-values#tax-systems
Customer: request.Requisites.Customer,
Items: request.Requisites.Items,
Customer: request.Requisites.Customer,
Items: request.Requisites.Items,
},
PaymentMethodData: &yandex.PaymentMethodType{Type: models.YandexPaymentTypeMap[request.Type]},
Confirmation: &yandex.CreateConfirmationRedirect{
@ -111,7 +106,7 @@ func (receiver *Yandex) CreatePayment(ctx context.Context, uuid string, request
ClientIP: request.ClientIP,
})
if err != nil {
receiver.logger.Error("failed to create payment on <CreatePayment> of <YandexPaymentService>", zap.Error(err))
s.logger.Error("failed to create payment on <CreatePayment> of <YandexPaymentService>", zap.Error(err))
return nil, err
}

@ -2,24 +2,21 @@ package status
import (
"context"
"gitea.pena/PenaSide/treasurer/internal/repository"
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models"
"go.uber.org/zap"
)
type PaymentRepository interface {
SetPaymentStatus(ctx context.Context, paymentID string, status models.PaymentStatus) (*models.Payment, errors.Error)
}
type Deps struct {
Logger *zap.Logger
PaymentRepository PaymentRepository
PaymentRepository *repository.PaymentRepository
}
type Service struct {
logger *zap.Logger
paymentRepository PaymentRepository
paymentRepository *repository.PaymentRepository
}
func New(deps Deps) (*Service, errors.Error) {
@ -37,40 +34,40 @@ func New(deps Deps) (*Service, errors.Error) {
}, nil
}
func (receiver *Service) SetStatusCanceled(ctx context.Context, paymentID string) (*models.Payment, errors.Error) {
payment, err := receiver.paymentRepository.SetPaymentStatus(ctx, paymentID, models.PaymentStatusCanceled)
func (s *Service) SetStatusCanceled(ctx context.Context, paymentID string) (*models.Payment, errors.Error) {
payment, err := s.paymentRepository.SetPaymentStatus(ctx, paymentID, models.PaymentStatusCanceled)
if err != nil {
receiver.logger.Error("failed to set payment status on <SetStatusCanceled> of <StatusService>", zap.Error(err))
s.logger.Error("failed to set payment status on <SetStatusCanceled> of <StatusService>", zap.Error(err))
return nil, err
}
return payment, nil
}
func (receiver *Service) SetStatusSuccess(ctx context.Context, paymentID string) (*models.Payment, errors.Error) {
payment, err := receiver.paymentRepository.SetPaymentStatus(ctx, paymentID, models.PaymentStatusSuccessfully)
func (s *Service) SetStatusSuccess(ctx context.Context, paymentID string) (*models.Payment, errors.Error) {
payment, err := s.paymentRepository.SetPaymentStatus(ctx, paymentID, models.PaymentStatusSuccessfully)
if err != nil {
receiver.logger.Error("failed to set payment status on <SetStatusSuccess> of <StatusService>", zap.Error(err))
s.logger.Error("failed to set payment status on <SetStatusSuccess> of <StatusService>", zap.Error(err))
return nil, err
}
return payment, nil
}
func (receiver *Service) SetStatusWaiting(ctx context.Context, paymentID string) (*models.Payment, errors.Error) {
payment, err := receiver.paymentRepository.SetPaymentStatus(ctx, paymentID, models.PaymentStatusWaiting)
func (s *Service) SetStatusWaiting(ctx context.Context, paymentID string) (*models.Payment, errors.Error) {
payment, err := s.paymentRepository.SetPaymentStatus(ctx, paymentID, models.PaymentStatusWaiting)
if err != nil {
receiver.logger.Error("failed to set payment status on <SetStatusWaiting> of <StatusService>", zap.Error(err))
s.logger.Error("failed to set payment status on <SetStatusWaiting> of <StatusService>", zap.Error(err))
return nil, err
}
return payment, nil
}
func (receiver *Service) SetStatusRefund(ctx context.Context, paymentID string) (*models.Payment, errors.Error) {
payment, err := receiver.paymentRepository.SetPaymentStatus(ctx, paymentID, models.PaymentStatusRefund)
func (s *Service) SetStatusRefund(ctx context.Context, paymentID string) (*models.Payment, errors.Error) {
payment, err := s.paymentRepository.SetPaymentStatus(ctx, paymentID, models.PaymentStatusRefund)
if err != nil {
receiver.logger.Error("failed to set payment status on <SetStatusRefund> of <StatusService>", zap.Error(err))
s.logger.Error("failed to set payment status on <SetStatusRefund> of <StatusService>", zap.Error(err))
return nil, err
}

@ -5,10 +5,9 @@ import (
"fmt"
"net/url"
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/errors"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"go.uber.org/zap"
)
const (
@ -23,132 +22,129 @@ type YandexWebhookClient interface {
type YandexDeps struct {
Logger *zap.Logger
Configuration *models.ConfigurationHTTP
HttpDomain string
YandexWebhookClient YandexWebhookClient
}
type Yandex struct {
logger *zap.Logger
configuration *models.ConfigurationHTTP
httpDomain string
yandexWebhookClient YandexWebhookClient
}
// todo не используется
func NewYandex(deps YandexDeps) (*Yandex, errors.Error) {
if deps.Logger == nil {
return nil, errors.NewWithMessage("logger is nil on <NewYandexWebhookService>", errors.ErrInvalidArgs)
}
if deps.Configuration == nil {
return nil, errors.NewWithMessage("Configuration is nil on <NewYandexWebhookService>", errors.ErrInvalidArgs)
}
if deps.YandexWebhookClient == nil {
return nil, errors.NewWithMessage("PaymentRepository is nil on <NewYandexWebhookService>", errors.ErrInvalidArgs)
}
return &Yandex{
logger: deps.Logger,
configuration: deps.Configuration,
httpDomain: deps.HttpDomain,
yandexWebhookClient: deps.YandexWebhookClient,
}, nil
}
func (receiver *Yandex) SetOnPaymentSuccess(ctx context.Context) errors.Error {
url, urlErr := url.JoinPath(receiver.configuration.Domen, "yandex", "payment", "status", "succeeded")
func (s *Yandex) SetOnPaymentSuccess(ctx context.Context) errors.Error {
url, urlErr := url.JoinPath(s.httpDomain, "yandex", "payment", "status", "succeeded")
if urlErr != nil {
receiver.logger.Error("failed to join url path on <SetOnPaymentSuccess> of <WebhookService>", zap.Error(urlErr))
s.logger.Error("failed to join url path on <SetOnPaymentSuccess> of <WebhookService>", zap.Error(urlErr))
return errors.NewWithError(fmt.Errorf("failed to join url path: %w", urlErr), errors.ErrInternalError)
}
if err := receiver.SetWebhook(ctx, onYandexSuccessWebhookEventKey, &yandex.CreateWebhookRequest{
if err := s.SetWebhook(ctx, onYandexSuccessWebhookEventKey, &yandex.CreateWebhookRequest{
Event: yandex.WebhookEventPaymentSucceeded,
URL: url,
}); err != nil {
receiver.logger.Error("failed to set webhook on <SetOnPaymentSuccess> of <WebhookService>", zap.Error(err))
s.logger.Error("failed to set webhook on <SetOnPaymentSuccess> of <WebhookService>", zap.Error(err))
return err
}
return nil
}
func (receiver *Yandex) SetOnPaymentCanceled(ctx context.Context) errors.Error {
url, urlErr := url.JoinPath(receiver.configuration.Domen, "yandex", "payment", "status", "canceled")
func (s *Yandex) SetOnPaymentCanceled(ctx context.Context) errors.Error {
url, urlErr := url.JoinPath(s.httpDomain, "yandex", "payment", "status", "canceled")
if urlErr != nil {
receiver.logger.Error("failed to join url path on <SetOnPaymentCanceled> of <WebhookService>", zap.Error(urlErr))
s.logger.Error("failed to join url path on <SetOnPaymentCanceled> of <WebhookService>", zap.Error(urlErr))
return errors.NewWithError(fmt.Errorf("failed to join url path: %w", urlErr), errors.ErrInternalError)
}
if err := receiver.SetWebhook(ctx, onYandexCanceledWebhookEventKey, &yandex.CreateWebhookRequest{
if err := s.SetWebhook(ctx, onYandexCanceledWebhookEventKey, &yandex.CreateWebhookRequest{
Event: yandex.WebhookEventPaymentCanceled,
URL: url,
}); err != nil {
receiver.logger.Error("failed to set webhook on <SetOnPaymentCanceled> of <WebhookService>", zap.Error(err))
s.logger.Error("failed to set webhook on <SetOnPaymentCanceled> of <WebhookService>", zap.Error(err))
return err
}
return nil
}
func (receiver *Yandex) SetOnPaymentWaiting(ctx context.Context) errors.Error {
url, urlErr := url.JoinPath(receiver.configuration.Domen, "yandex", "payment", "status", "waiting")
func (s *Yandex) SetOnPaymentWaiting(ctx context.Context) errors.Error {
url, urlErr := url.JoinPath(s.httpDomain, "yandex", "payment", "status", "waiting")
if urlErr != nil {
receiver.logger.Error("failed to join url path on <SetOnPaymentWaiting> of <WebhookService>", zap.Error(urlErr))
s.logger.Error("failed to join url path on <SetOnPaymentWaiting> of <WebhookService>", zap.Error(urlErr))
return errors.NewWithError(fmt.Errorf("failed to join url path: %w", urlErr), errors.ErrInternalError)
}
if err := receiver.SetWebhook(ctx, onYandexWaitingWebhookEventKey, &yandex.CreateWebhookRequest{
if err := s.SetWebhook(ctx, onYandexWaitingWebhookEventKey, &yandex.CreateWebhookRequest{
Event: yandex.WebhookEventPaymentWaiting,
URL: url,
}); err != nil {
receiver.logger.Error("failed to set webhook on <SetOnPaymentWaiting> of <WebhookService>", zap.Error(err))
s.logger.Error("failed to set webhook on <SetOnPaymentWaiting> of <WebhookService>", zap.Error(err))
return err
}
return nil
}
func (receiver *Yandex) SetOnPaymentRefund(ctx context.Context) errors.Error {
url, urlErr := url.JoinPath(receiver.configuration.Domen, "yandex", "refund", "status", "canceled")
func (s *Yandex) SetOnPaymentRefund(ctx context.Context) errors.Error {
url, urlErr := url.JoinPath(s.httpDomain, "yandex", "refund", "status", "canceled")
if urlErr != nil {
receiver.logger.Error("failed to join url path on <SetOnPaymentRefund> of <WebhookService>", zap.Error(urlErr))
s.logger.Error("failed to join url path on <SetOnPaymentRefund> of <WebhookService>", zap.Error(urlErr))
return errors.NewWithError(fmt.Errorf("failed to join url path: %w", urlErr), errors.ErrInternalError)
}
if err := receiver.SetWebhook(ctx, onYandexRefundWebhookEventKey, &yandex.CreateWebhookRequest{
if err := s.SetWebhook(ctx, onYandexRefundWebhookEventKey, &yandex.CreateWebhookRequest{
Event: yandex.WebhookEventRefundSucceeded,
URL: url,
}); err != nil {
receiver.logger.Error("failed to set webhook on <SetOnPaymentRefund> of <WebhookService>", zap.Error(err))
s.logger.Error("failed to set webhook on <SetOnPaymentRefund> of <WebhookService>", zap.Error(err))
return err
}
return nil
}
func (receiver *Yandex) SetWebhook(ctx context.Context, idempotenceKey string, request *yandex.CreateWebhookRequest) errors.Error {
webhook, err := receiver.GetWebhookByType(ctx, request.Event)
func (s *Yandex) SetWebhook(ctx context.Context, idempotenceKey string, request *yandex.CreateWebhookRequest) errors.Error {
webhook, err := s.GetWebhookByType(ctx, request.Event)
if err != nil && err.Type() != errors.ErrNotFound {
receiver.logger.Error("failed to get webhook on <SetWebhook> of <WebhookService>", zap.Error(err))
s.logger.Error("failed to get webhook on <SetWebhook> of <WebhookService>", zap.Error(err))
return err
}
if webhook != nil {
receiver.logger.Error("webhook already exist on <SetWebhook> of <WebhookService>")
s.logger.Error("webhook already exist on <SetWebhook> of <WebhookService>")
return errors.NewWithError(
fmt.Errorf("yandex webhook with type <%s> already exist", request.Event),
errors.ErrConflict,
)
}
// if _, err := receiver.yandexWebhookClient.SetWebhookEvent(ctx, idempotenceKey, request); err != nil {
// receiver.logger.Error("failed to set webhook on <SetWebhook> of <WebhookService>", zap.Error(err))
// return err
// }
//if _, err := receiver.yandexWebhookClient.SetWebhookEvent(ctx, idempotenceKey, request); err != nil {
// receiver.logger.Error("failed to set webhook on <SetWebhook> of <WebhookService>", zap.Error(err))
// return err
//}
return nil
}
func (receiver *Yandex) GetWebhookByType(ctx context.Context, event yandex.WebhookEventType) (*yandex.Webhook, errors.Error) {
func (s *Yandex) GetWebhookByType(ctx context.Context, event yandex.WebhookEventType) (*yandex.Webhook, errors.Error) {
// webhooks, err := receiver.yandexWebhookClient.GetWebhookEvents(ctx)
// if err != nil {
// receiver.logger.Error("failed to get webhooks list on <GetWebhookByKey> of <WebhookService>", zap.Error(err))
@ -171,10 +167,10 @@ func (receiver *Yandex) GetWebhookByType(ctx context.Context, event yandex.Webho
return nil, nil
}
func (receiver *Yandex) UnsetWebhook(ctx context.Context, event yandex.WebhookEventType) errors.Error {
_, err := receiver.GetWebhookByType(ctx, event)
func (s *Yandex) UnsetWebhook(ctx context.Context, event yandex.WebhookEventType) errors.Error {
_, err := s.GetWebhookByType(ctx, event)
if err != nil {
receiver.logger.Error("failed to get webhook on <UnsetWebhook> of <WebhookService>", zap.Error(err), zap.String("event", string(event)))
s.logger.Error("failed to get webhook on <UnsetWebhook> of <WebhookService>", zap.Error(err), zap.String("event", string(event)))
return err
}

@ -0,0 +1,61 @@
package utils
import (
"encoding/json"
"fmt"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"strconv"
"strings"
)
func MapToCreatePaymentYandexReceipt(data map[string]string) (*models.CreatePayment[yandex.Receipt], error) {
amount, err := strconv.ParseInt(data["amount"], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid amount: %w", err)
}
var callbackHosts []string
if val, ok := data["callback_host_grpc"]; ok && val != "" {
callbackHosts = strings.Split(val, ",")
}
var requisites yandex.Receipt
if val, ok := data["requisites"]; ok && val != "" {
if err := json.Unmarshal([]byte(val), &requisites); err != nil {
return nil, fmt.Errorf("invalid requisites JSON: %w", err)
}
} else {
return nil, fmt.Errorf("missing requisites field")
}
auto := false
if val, ok := data["save_payment_method"]; ok && val != "" {
auto, err = strconv.ParseBool(val)
if err != nil {
return nil, fmt.Errorf("invalid save_payment_method field: %w", err)
}
}
recurrent := false
if val, ok := data["recurrent"]; ok && val != "" {
recurrent, err = strconv.ParseBool(val)
if err != nil {
return nil, fmt.Errorf("invalid recurrent field: %w", err)
}
}
payment := &models.CreatePayment[yandex.Receipt]{
Type: models.PaymentType(data["type"]),
Currency: data["currency"],
Amount: amount,
CallbackHostGRPC: callbackHosts,
ReturnURL: data["return_url"],
UserID: data["user_id"],
ClientIP: data["client_ip"],
Requisites: requisites,
Auto: auto,
Recurrent: recurrent,
}
return payment, nil
}

@ -2,10 +2,11 @@ package utils
import (
"encoding/base64"
"encoding/json"
"fmt"
"strings"
"gitea.pena/PenaSide/treasurer/internal/proto/treasurer"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/proto/treasurer"
"strings"
)
func ConvertYoomoneySercetsToAuth(authType, storeID, secretKey string) string {
@ -20,14 +21,14 @@ func ProtoItem2ReceiptItem(in *treasurer.Item) yandex.Item {
return yandex.Item{
Description: in.Description,
Amount: yandex.ReceiptAmount{
Value: in.Money,
Value: in.Money,
Currency: in.Currency,
},
VatCode: 1,
Quantity: 1,
Measure: in.Measure,
VatCode: 1,
Quantity: 1,
Measure: in.Measure,
PaymentSubject: "service",
PaymentMode: "full_prepayment",
PaymentMode: "full_prepayment",
}
}
@ -37,7 +38,12 @@ func ProtoItems2ReceiptItems(in []*treasurer.Item) []yandex.Item {
for i, item := range in {
out[i] = ProtoItem2ReceiptItem(item)
}
}
return out
}
func ToJSON(v any) string {
b, _ := json.Marshal(v)
return string(b)
}

@ -4,22 +4,19 @@ import (
"context"
"time"
"go.uber.org/zap"
"gitea.pena/PenaSide/treasurer/internal/errors"
svc_mock "gitea.pena/PenaSide/treasurer/internal/service/mock"
"go.uber.org/zap"
)
type mockService interface {
Register() bool
}
type WorkerDeps struct {
Logger *zap.Logger
MockService mockService
MockService *svc_mock.Service
}
type Worker struct {
logger *zap.Logger
mockService mockService
mockService *svc_mock.Service
}
func New(deps WorkerDeps) (*Worker, errors.Error) {
@ -37,24 +34,24 @@ func New(deps WorkerDeps) (*Worker, errors.Error) {
}, nil
}
func (receiver *Worker) Run(ctx context.Context) {
func (w *Worker) Run(ctx context.Context) {
after := time.After(10 * time.Second)
select {
case <-ctx.Done():
receiver.logger.Info("register mocks operations canceled <mocks>")
w.logger.Info("register mocks operations canceled <mocks>")
return
case <-after:
receiver.logger.Info("register yoomoney mocks <mocks>")
w.logger.Info("register yoomoney mocks <mocks>")
isSuccess := receiver.mockService.Register()
isSuccess := w.mockService.Register()
if isSuccess {
receiver.logger.Info("register yoomoney mocks complete <mocks>")
w.logger.Info("register yoomoney mocks complete <mocks>")
}
if !isSuccess {
receiver.logger.Info("register yoomoney mocks failure <mocks>")
w.logger.Info("register yoomoney mocks failure <mocks>")
}
}
}

@ -1,50 +0,0 @@
package closer
import (
"context"
"fmt"
"log"
"sync"
)
type Callback func(ctx context.Context) error
type Closer struct {
mutex sync.Mutex
callbacks []Callback
}
func New() *Closer {
return &Closer{}
}
func (receiver *Closer) Add(callback Callback) {
receiver.mutex.Lock()
defer receiver.mutex.Unlock()
receiver.callbacks = append(receiver.callbacks, callback)
}
func (receiver *Closer) Close(ctx context.Context) error {
receiver.mutex.Lock()
defer receiver.mutex.Unlock()
complete := make(chan struct{}, 1)
go func() {
for index, callback := range receiver.callbacks {
if err := callback(ctx); err != nil {
log.Printf("[! (%d)] %v", index, err)
}
}
complete <- struct{}{}
}()
select {
case <-complete:
return nil
case <-ctx.Done():
return fmt.Errorf("shutdown cancelled: %v", ctx.Err())
}
}

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

23
pkg/env/parse.go vendored

@ -1,23 +0,0 @@
package env
import (
"context"
"fmt"
"log"
envLoader "github.com/joho/godotenv"
envParser "github.com/sethvargo/go-envconfig"
)
func Parse[T interface{}](envFilePath string) (*T, error) {
var configuration T
if err := envLoader.Load(envFilePath); err != nil {
log.Printf("load local env file error: %s", err.Error())
}
if err := envParser.Process(context.Background(), &configuration); err != nil {
return nil, fmt.Errorf("parsing env error: %s", err.Error())
}
return &configuration, nil
}

@ -1,16 +0,0 @@
package json
import (
"bytes"
"encoding/json"
)
func EncodeBuffer(body interface{}) (*bytes.Buffer, error) {
buffer := new(bytes.Buffer)
if err := json.NewEncoder(buffer).Encode(body); err != nil {
return nil, err
}
return buffer, nil
}

@ -1,22 +0,0 @@
package mongo
import (
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type Configuration struct {
Host string `env:"MONGO_HOST,default=localhost"`
Port string `env:"MONGO_PORT,default=27017"`
User string `env:"MONGO_USER,required"`
Password string `env:"MONGO_PASSWORD,required"`
Auth string `env:"MONGO_AUTH,required"`
DatabaseName string `env:"MONGO_DB_NAME,required"`
}
type RequestSettings struct {
Driver *mongo.Collection
Options *options.FindOptions
Filter primitive.M
}

@ -1,74 +0,0 @@
package mongo
import (
"context"
"fmt"
"log"
"net"
"net/url"
"time"
"go.mongodb.org/mongo-driver/event"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type ConnectDeps struct {
Configuration *Configuration
Timeout time.Duration
}
func Connect(ctx context.Context, deps *ConnectDeps) (*mongo.Database, error) {
if deps == nil {
return nil, ErrEmptyArgs
}
mongoURI := &url.URL{
Scheme: "mongodb",
Host: net.JoinHostPort(deps.Configuration.Host, deps.Configuration.Port),
}
cmdMonitor := &event.CommandMonitor{
Started: func(_ context.Context, evt *event.CommandStartedEvent) {
log.Println(evt.Command)
},
Succeeded: func(_ context.Context, evt *event.CommandSucceededEvent) {
log.Println(evt.Reply)
},
Failed: func(_ context.Context, evt *event.CommandFailedEvent) {
log.Println(evt.Failure)
},
}
connectionOptions := options.Client().
ApplyURI(mongoURI.String()).
SetAuth(options.Credential{
AuthMechanism: "SCRAM-SHA-1",
AuthSource: deps.Configuration.Auth,
Username: deps.Configuration.User,
Password: deps.Configuration.Password,
}).
SetMonitor(cmdMonitor)
ticker := time.NewTicker(1 * time.Second)
timeoutExceeded := time.After(deps.Timeout)
defer ticker.Stop()
for {
select {
case <-ticker.C:
connection, err := mongo.Connect(ctx, connectionOptions)
if err == nil {
return connection.Database(deps.Configuration.DatabaseName), nil
}
log.Printf("failed to connect to db <%s>: %s", mongoURI.String(), err.Error())
case <-timeoutExceeded:
return nil, fmt.Errorf("db connection <%s> failed after %d timeout", mongoURI, deps.Timeout)
default:
}
time.Sleep(1 * time.Second)
}
}

@ -1,7 +0,0 @@
package mongo
import "errors"
var (
ErrEmptyArgs = errors.New("arguments are empty")
)

@ -1,55 +0,0 @@
package mongo
import (
"context"
"log"
)
func Find[T any](ctx context.Context, settings *RequestSettings) ([]T, error) {
if settings == nil {
return []T{}, ErrEmptyArgs
}
results := make([]T, 0)
cursor, err := settings.Driver.Find(ctx, settings.Filter, settings.Options)
if err != nil {
return []T{}, err
}
defer func() {
if err := cursor.Close(ctx); err != nil {
log.Printf("failed to close cursor: %v", err)
}
}()
for cursor.Next(ctx) {
result := new(T)
if err := cursor.Decode(result); err != nil {
return []T{}, err
}
results = append(results, *result)
}
if err := cursor.Err(); err != nil {
return []T{}, err
}
return results, nil
}
func FindOne[T any](ctx context.Context, settings *RequestSettings) (*T, error) {
if settings == nil {
return nil, ErrEmptyArgs
}
result := new(T)
if err := settings.Driver.FindOne(ctx, settings.Filter).Decode(result); err != nil {
return nil, err
}
return result, nil
}

@ -1,31 +0,0 @@
syntax = "proto3";
package treasurer;
option go_package = "./treasurer";
message MainPaymentSettings {
string Currency = 1;
int64 Amount = 2;
repeated string CallbackHostGRPC = 3;
string ReturnURL = 4;
string UserID = 5;
string ClientIP = 6;
Customer Customer = 7;
repeated Item Items = 8;
}
message Customer {
string FullName = 1;
string INN = 2;
string Email = 3;
string Phone = 4;
}
message Item {
string Description = 1;
string Measure = 2;
string Quantity = 3;
string Money = 4;
string Currency = 5;
}

@ -3,7 +3,6 @@ syntax = "proto3";
package treasurer;
import "google/protobuf/empty.proto";
import "treasurer/payment.model.proto";
option go_package = "./treasurer";
@ -14,6 +13,7 @@ service TreasurerService {
rpc GetPaymentLinkSberbankB2B(GetPaymentLinkRequest) returns (GetPaymentLinkResponse) {}
rpc GetPaymentLinkSBP(GetPaymentLinkRequest) returns (GetPaymentLinkResponse) {}
rpc GetPaymentLinkSberPay(GetPaymentLinkRequest) returns (GetPaymentLinkResponse) {}
rpc DeleteSavedPaymentMethods(DeleteSavedPaymentMethodsRequest) returns (google.protobuf.Empty) {}
}
message GetBankCardPaymentLinkRequest {
@ -33,3 +33,36 @@ message GetB2BPaymentLinkRequest {
message GetPaymentLinkResponse {
string RedirectURL = 1;
}
message DeleteSavedPaymentMethodsRequest {
string UserID = 1;
}
message MainPaymentSettings {
string Currency = 1;
int64 Amount = 2;
repeated string CallbackHostGRPC = 3;
string ReturnURL = 4;
string UserID = 5;
string ClientIP = 6;
Customer Customer = 7;
repeated Item Items = 8;
bool Auto = 9;
bool Recurrent = 10;
}
message Customer {
string FullName = 1;
string INN = 2;
string Email = 3;
string Phone = 4;
}
message Item {
string Description = 1;
string Measure = 2;
string Quantity = 3;
string Money = 4;
string Currency = 5;
}

@ -4,10 +4,9 @@ import (
"context"
"time"
"gitea.pena/PenaSide/treasurer/internal/models"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"gitea.pena/PenaSide/treasurer/internal/models"
mongopkg "gitea.pena/PenaSide/treasurer/pkg/mongo"
)
type MongoHelper struct {
@ -26,15 +25,15 @@ func NewMongoHelper(ctx context.Context, config *mongopkg.Configuration) (*Mongo
return &MongoHelper{collection: database.Collection("payments")}, nil
}
func (receiver *MongoHelper) GetPayments(ctx context.Context) ([]models.Payment, error) {
func (h *MongoHelper) GetPayments(ctx context.Context) ([]models.Payment, error) {
return mongopkg.Find[models.Payment](ctx, &mongopkg.RequestSettings{
Driver: receiver.collection,
Driver: h.collection,
Filter: bson.M{},
})
}
func (receiver *MongoHelper) Clear(ctx context.Context) error {
if _, err := receiver.collection.DeleteMany(ctx, bson.M{}); err != nil {
func (h *MongoHelper) Clear(ctx context.Context) error {
if _, err := h.collection.DeleteMany(ctx, bson.M{}); err != nil {
return err
}

@ -4,17 +4,16 @@ import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/proto/treasurer"
"gitea.pena/PenaSide/treasurer/pkg/array"
"gitea.pena/PenaSide/treasurer/pkg/mongo"
"gitea.pena/PenaSide/treasurer/tests/data"
"gitea.pena/PenaSide/treasurer/tests/helpers"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func TestCreatePaymentAlfaClick(t *testing.T) {

@ -4,17 +4,16 @@ import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/proto/treasurer"
"gitea.pena/PenaSide/treasurer/pkg/array"
"gitea.pena/PenaSide/treasurer/pkg/mongo"
"gitea.pena/PenaSide/treasurer/tests/data"
"gitea.pena/PenaSide/treasurer/tests/helpers"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func TestCreatePaymentBankCard(t *testing.T) {

@ -4,17 +4,16 @@ import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/proto/treasurer"
"gitea.pena/PenaSide/treasurer/pkg/array"
"gitea.pena/PenaSide/treasurer/pkg/mongo"
"gitea.pena/PenaSide/treasurer/tests/data"
"gitea.pena/PenaSide/treasurer/tests/helpers"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func TestCreatePaymentCash(t *testing.T) {

@ -4,17 +4,16 @@ import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/proto/treasurer"
"gitea.pena/PenaSide/treasurer/pkg/array"
"gitea.pena/PenaSide/treasurer/pkg/mongo"
"gitea.pena/PenaSide/treasurer/tests/data"
"gitea.pena/PenaSide/treasurer/tests/helpers"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func TestCreatePaymentInstallments(t *testing.T) {

@ -4,17 +4,16 @@ import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/proto/treasurer"
"gitea.pena/PenaSide/treasurer/pkg/array"
"gitea.pena/PenaSide/treasurer/pkg/mongo"
"gitea.pena/PenaSide/treasurer/tests/data"
"gitea.pena/PenaSide/treasurer/tests/helpers"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func TestCreatePaymentMobile(t *testing.T) {

@ -4,17 +4,16 @@ import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/proto/treasurer"
"gitea.pena/PenaSide/treasurer/pkg/array"
"gitea.pena/PenaSide/treasurer/pkg/mongo"
"gitea.pena/PenaSide/treasurer/tests/data"
"gitea.pena/PenaSide/treasurer/tests/helpers"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func TestCreatePaymentQIWI(t *testing.T) {

@ -4,17 +4,16 @@ import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/proto/treasurer"
"gitea.pena/PenaSide/treasurer/pkg/array"
"gitea.pena/PenaSide/treasurer/pkg/mongo"
"gitea.pena/PenaSide/treasurer/tests/data"
"gitea.pena/PenaSide/treasurer/tests/helpers"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func TestCreatePaymentSberpay(t *testing.T) {

@ -4,17 +4,16 @@ import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/proto/treasurer"
"gitea.pena/PenaSide/treasurer/pkg/array"
"gitea.pena/PenaSide/treasurer/pkg/mongo"
"gitea.pena/PenaSide/treasurer/tests/data"
"gitea.pena/PenaSide/treasurer/tests/helpers"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func TestCreatePaymentSBP(t *testing.T) {

@ -4,17 +4,16 @@ import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/proto/treasurer"
"gitea.pena/PenaSide/treasurer/pkg/array"
"gitea.pena/PenaSide/treasurer/pkg/mongo"
"gitea.pena/PenaSide/treasurer/tests/data"
"gitea.pena/PenaSide/treasurer/tests/helpers"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func TestCreatePaymentTinkoff(t *testing.T) {

@ -4,17 +4,16 @@ import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"gitea.pena/PenaSide/treasurer/internal/models"
"gitea.pena/PenaSide/treasurer/internal/models/yandex"
"gitea.pena/PenaSide/treasurer/internal/proto/treasurer"
"gitea.pena/PenaSide/treasurer/pkg/array"
"gitea.pena/PenaSide/treasurer/pkg/mongo"
"gitea.pena/PenaSide/treasurer/tests/data"
"gitea.pena/PenaSide/treasurer/tests/helpers"
"github.com/stretchr/testify/assert"
"github.com/walkerus/go-wiremock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func TestCreatePaymentYoomoney(t *testing.T) {