Files
payouts/internal/service/yookassa/gen/oas_handlers_gen.go

5981 lines
160 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Code generated by ogen, DO NOT EDIT.
package gen
import (
"context"
"net/http"
"time"
"github.com/go-faster/errors"
ht "github.com/ogen-go/ogen/http"
"github.com/ogen-go/ogen/middleware"
"github.com/ogen-go/ogen/ogenerrors"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/metric"
semconv "go.opentelemetry.io/otel/semconv/v1.39.0"
"go.opentelemetry.io/otel/trace"
)
type codeRecorder struct {
http.ResponseWriter
status int
}
func (c *codeRecorder) WriteHeader(status int) {
c.status = status
c.ResponseWriter.WriteHeader(status)
}
func (c *codeRecorder) Unwrap() http.ResponseWriter {
return c.ResponseWriter
}
// handleDealsDealIDGetRequest handles GET /deals/{deal_id} operation.
//
// Запрос позволяет получить информацию о текущем
// состоянии сделки по ее уникальному идентификатору.
//
// GET /deals/{deal_id}
func (s *Server) handleDealsDealIDGetRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
semconv.HTTPRouteKey.String("/deals/{deal_id}"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), DealsDealIDGetOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: DealsDealIDGetOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, DealsDealIDGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, DealsDealIDGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodeDealsDealIDGetParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
var response DealsDealIDGetRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: DealsDealIDGetOperation,
OperationSummary: "Информация о сделке",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "deal_id",
In: "path",
}: params.DealID,
},
Raw: r,
}
type (
Request = struct{}
Params = DealsDealIDGetParams
Response = DealsDealIDGetRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackDealsDealIDGetParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.DealsDealIDGet(ctx, params)
return response, err
},
)
} else {
response, err = s.h.DealsDealIDGet(ctx, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodeDealsDealIDGetResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handleDealsGetRequest handles GET /deals operation.
//
// Запрос позволяет получить список сделок,
// отфильтрованный по заданным критериям. Подробнее о
// работе со списками: https://yookassa.ru/developers/using-api/lists.
//
// GET /deals
func (s *Server) handleDealsGetRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
semconv.HTTPRouteKey.String("/deals"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), DealsGetOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: DealsGetOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, DealsGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, DealsGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodeDealsGetParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
var response DealsGetRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: DealsGetOperation,
OperationSummary: "Список сделок",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "created_at.gte",
In: "query",
}: params.CreatedAtGte,
{
Name: "created_at.gt",
In: "query",
}: params.CreatedAtGt,
{
Name: "created_at.lte",
In: "query",
}: params.CreatedAtLte,
{
Name: "created_at.lt",
In: "query",
}: params.CreatedAtLt,
{
Name: "expires_at.gte",
In: "query",
}: params.ExpiresAtGte,
{
Name: "expires_at.gt",
In: "query",
}: params.ExpiresAtGt,
{
Name: "expires_at.lte",
In: "query",
}: params.ExpiresAtLte,
{
Name: "expires_at.lt",
In: "query",
}: params.ExpiresAtLt,
{
Name: "status",
In: "query",
}: params.Status,
{
Name: "full_text_search",
In: "query",
}: params.FullTextSearch,
{
Name: "limit",
In: "query",
}: params.Limit,
{
Name: "cursor",
In: "query",
}: params.Cursor,
},
Raw: r,
}
type (
Request = struct{}
Params = DealsGetParams
Response = DealsGetRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackDealsGetParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.DealsGet(ctx, params)
return response, err
},
)
} else {
response, err = s.h.DealsGet(ctx, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodeDealsGetResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handleDealsPostRequest handles POST /deals operation.
//
// Запрос позволяет создать сделку, в рамках которой
// необходимо принять оплату от покупателя и
// перечислить ее продавцу.
//
// POST /deals
func (s *Server) handleDealsPostRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("POST"),
semconv.HTTPRouteKey.String("/deals"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), DealsPostOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: DealsPostOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, DealsPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, DealsPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodeDealsPostParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
request, rawBody, close, err := s.decodeDealsPostRequest(r)
if err != nil {
err = &ogenerrors.DecodeRequestError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeRequest", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
defer func() {
if err := close(); err != nil {
recordError("CloseRequest", err)
}
}()
var response DealsPostRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: DealsPostOperation,
OperationSummary: "Создание сделки",
OperationID: "",
Body: request,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "Idempotence-Key",
In: "header",
}: params.IdempotenceKey,
},
Raw: r,
}
type (
Request = *SafeDealRequest
Params = DealsPostParams
Response = DealsPostRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackDealsPostParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.DealsPost(ctx, request, params)
return response, err
},
)
} else {
response, err = s.h.DealsPost(ctx, request, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodeDealsPostResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handleMeGetRequest handles GET /me operation.
//
// С помощью этого запроса вы можете получить
// информацию о магазине или шлюзе: * Для Сплитования
// платежей: https://yookassa.ru/developers/solutions-for-platforms/split-payments/basics: в
// запросе необходимо передать параметр on_behalf_of с
// идентификатором магазина продавца и ваши данные для
// аутентификации: https://yookassa.ru/developers/using-api/interaction-format#auth
// (идентификатор и секретный ключ вашей платформы). *
// Для партнеров: https://yookassa.
// ru/developers/solutions-for-platforms/partners-api/basics: в запросе необходимо
// передать OAuth-токен магазина. * Для выплат: https://yookassa.
// ru/developers/payouts/overview: в запросе необходимо передать ваши
// данные для аутентификации: https://yookassa.
// ru/developers/using-api/interaction-format#auth (идентификатор и секретный
// ключ вашего шлюза).
//
// GET /me
func (s *Server) handleMeGetRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
semconv.HTTPRouteKey.String("/me"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), MeGetOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: MeGetOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, MeGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, MeGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodeMeGetParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
var response MeGetRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: MeGetOperation,
OperationSummary: "Информация о настройках магазина или шлюза",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "on_behalf_of",
In: "query",
}: params.OnBehalfOf,
},
Raw: r,
}
type (
Request = struct{}
Params = MeGetParams
Response = MeGetRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackMeGetParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.MeGet(ctx, params)
return response, err
},
)
} else {
response, err = s.h.MeGet(ctx, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodeMeGetResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handlePaymentMethodsPaymentMethodIDGetRequest handles GET /payment_methods/{payment_method_id} operation.
//
// Используйте этот запрос, чтобы получить информацию о
// текущем состоянии способа оплаты по его уникальному
// идентификатору.
//
// GET /payment_methods/{payment_method_id}
func (s *Server) handlePaymentMethodsPaymentMethodIDGetRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
semconv.HTTPRouteKey.String("/payment_methods/{payment_method_id}"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), PaymentMethodsPaymentMethodIDGetOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: PaymentMethodsPaymentMethodIDGetOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, PaymentMethodsPaymentMethodIDGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, PaymentMethodsPaymentMethodIDGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodePaymentMethodsPaymentMethodIDGetParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
var response PaymentMethodsPaymentMethodIDGetRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: PaymentMethodsPaymentMethodIDGetOperation,
OperationSummary: "Информация о способе оплаты",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "payment_method_id",
In: "path",
}: params.PaymentMethodID,
},
Raw: r,
}
type (
Request = struct{}
Params = PaymentMethodsPaymentMethodIDGetParams
Response = PaymentMethodsPaymentMethodIDGetRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackPaymentMethodsPaymentMethodIDGetParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.PaymentMethodsPaymentMethodIDGet(ctx, params)
return response, err
},
)
} else {
response, err = s.h.PaymentMethodsPaymentMethodIDGet(ctx, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodePaymentMethodsPaymentMethodIDGetResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handlePaymentMethodsPostRequest handles POST /payment_methods operation.
//
// Используйте этот запрос, чтобы создать в ЮKassa объект
// способа оплаты: https://yookassa.ru/developers/api#payment_method_object. В
// запросе необходимо передать код способа оплаты,
// который вы хотите сохранить, и при необходимости
// дополнительные параметры, связанные с той
// функциональностью, которую вы хотите использовать.
// Идентификатор созданного способа оплаты вы можете
// использовать при проведении автоплатежей: https://yookassa.
// ru/developers/payment-acceptance/scenario-extensions/recurring-payments/create-recurring или
// выплат: https://yookassa.ru/developers/payouts/scenario-extensions/multipurpose-token.
//
// POST /payment_methods
func (s *Server) handlePaymentMethodsPostRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("POST"),
semconv.HTTPRouteKey.String("/payment_methods"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), PaymentMethodsPostOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: PaymentMethodsPostOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, PaymentMethodsPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, PaymentMethodsPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodePaymentMethodsPostParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
request, rawBody, close, err := s.decodePaymentMethodsPostRequest(r)
if err != nil {
err = &ogenerrors.DecodeRequestError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeRequest", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
defer func() {
if err := close(); err != nil {
recordError("CloseRequest", err)
}
}()
var response PaymentMethodsPostRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: PaymentMethodsPostOperation,
OperationSummary: "Создание способа оплаты",
OperationID: "",
Body: request,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "Idempotence-Key",
In: "header",
}: params.IdempotenceKey,
},
Raw: r,
}
type (
Request = PaymentMethodsPostReq
Params = PaymentMethodsPostParams
Response = PaymentMethodsPostRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackPaymentMethodsPostParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.PaymentMethodsPost(ctx, request, params)
return response, err
},
)
} else {
response, err = s.h.PaymentMethodsPost(ctx, request, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodePaymentMethodsPostResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handlePaymentsGetRequest handles GET /payments operation.
//
// Use this request to get a list of payments. You can download payments created over the last 3
// years. You can filter the list by specified criteria. More about working with lists:
// https://yookassa.ru/developers/using-api/lists.
//
// GET /payments
func (s *Server) handlePaymentsGetRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
semconv.HTTPRouteKey.String("/payments"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), PaymentsGetOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: PaymentsGetOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, PaymentsGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, PaymentsGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodePaymentsGetParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
var response PaymentsGetRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: PaymentsGetOperation,
OperationSummary: "List payments",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "created_at.gte",
In: "query",
}: params.CreatedAtGte,
{
Name: "created_at.gt",
In: "query",
}: params.CreatedAtGt,
{
Name: "created_at.lte",
In: "query",
}: params.CreatedAtLte,
{
Name: "created_at.lt",
In: "query",
}: params.CreatedAtLt,
{
Name: "captured_at.gte",
In: "query",
}: params.CapturedAtGte,
{
Name: "captured_at.gt",
In: "query",
}: params.CapturedAtGt,
{
Name: "captured_at.lte",
In: "query",
}: params.CapturedAtLte,
{
Name: "captured_at.lt",
In: "query",
}: params.CapturedAtLt,
{
Name: "payment_method",
In: "query",
}: params.PaymentMethod,
{
Name: "status",
In: "query",
}: params.Status,
{
Name: "limit",
In: "query",
}: params.Limit,
{
Name: "cursor",
In: "query",
}: params.Cursor,
},
Raw: r,
}
type (
Request = struct{}
Params = PaymentsGetParams
Response = PaymentsGetRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackPaymentsGetParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.PaymentsGet(ctx, params)
return response, err
},
)
} else {
response, err = s.h.PaymentsGet(ctx, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodePaymentsGetResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handlePaymentsPaymentIDCancelPostRequest handles POST /payments/{payment_id}/cancel operation.
//
// Cancel payments with the waiting_for_capture status. Payment cancelation means you are not ready
// to dispatch a product or to provide a service to the user. Once you cancel the payment, we will
// start returning the money to the payers account. If the payment was made from a bank card, a
// YooMoney wallet, or via SberPay, the money will be refunded instantly. If the payment was made
// using other payment methods, the process can take up to several days. More about capturing and
// canceling payments: https://yookassa.
// ru/developers/payment-acceptance/getting-started/payment-process#capture-and-cancel.
//
// POST /payments/{payment_id}/cancel
func (s *Server) handlePaymentsPaymentIDCancelPostRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("POST"),
semconv.HTTPRouteKey.String("/payments/{payment_id}/cancel"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), PaymentsPaymentIDCancelPostOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: PaymentsPaymentIDCancelPostOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, PaymentsPaymentIDCancelPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, PaymentsPaymentIDCancelPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodePaymentsPaymentIDCancelPostParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
var response PaymentsPaymentIDCancelPostRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: PaymentsPaymentIDCancelPostOperation,
OperationSummary: "Cancel a payment",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "payment_id",
In: "path",
}: params.PaymentID,
{
Name: "Idempotence-Key",
In: "header",
}: params.IdempotenceKey,
},
Raw: r,
}
type (
Request = struct{}
Params = PaymentsPaymentIDCancelPostParams
Response = PaymentsPaymentIDCancelPostRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackPaymentsPaymentIDCancelPostParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.PaymentsPaymentIDCancelPost(ctx, params)
return response, err
},
)
} else {
response, err = s.h.PaymentsPaymentIDCancelPost(ctx, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodePaymentsPaymentIDCancelPostResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handlePaymentsPaymentIDCapturePostRequest handles POST /payments/{payment_id}/capture operation.
//
// Confirm youre ready to accept the payment. Once the payment is captured, the status will change
// to succeeded. After that, you can provide the customer with the product or service. You can only
// capture payments with the waiting_for_capture status, and only for a certain amount of time
// (depending on the payment method). If you do not capture the payment within the allotted time, the
// status will change to canceled, and the money will be returned to the user. More about capturing
// and canceling payments: https://yookassa.
// ru/developers/payment-acceptance/getting-started/payment-process#capture-and-cancel.
//
// POST /payments/{payment_id}/capture
func (s *Server) handlePaymentsPaymentIDCapturePostRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("POST"),
semconv.HTTPRouteKey.String("/payments/{payment_id}/capture"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), PaymentsPaymentIDCapturePostOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: PaymentsPaymentIDCapturePostOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, PaymentsPaymentIDCapturePostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, PaymentsPaymentIDCapturePostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodePaymentsPaymentIDCapturePostParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
request, rawBody, close, err := s.decodePaymentsPaymentIDCapturePostRequest(r)
if err != nil {
err = &ogenerrors.DecodeRequestError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeRequest", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
defer func() {
if err := close(); err != nil {
recordError("CloseRequest", err)
}
}()
var response PaymentsPaymentIDCapturePostRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: PaymentsPaymentIDCapturePostOperation,
OperationSummary: "Capture a payment",
OperationID: "",
Body: request,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "payment_id",
In: "path",
}: params.PaymentID,
{
Name: "Idempotence-Key",
In: "header",
}: params.IdempotenceKey,
},
Raw: r,
}
type (
Request = *PaymentsPaymentIDCapturePostReq
Params = PaymentsPaymentIDCapturePostParams
Response = PaymentsPaymentIDCapturePostRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackPaymentsPaymentIDCapturePostParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.PaymentsPaymentIDCapturePost(ctx, request, params)
return response, err
},
)
} else {
response, err = s.h.PaymentsPaymentIDCapturePost(ctx, request, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodePaymentsPaymentIDCapturePostResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handlePaymentsPaymentIDGetRequest handles GET /payments/{payment_id} operation.
//
// This request allows you to get the information about the current payment status by its unique ID.
//
// GET /payments/{payment_id}
func (s *Server) handlePaymentsPaymentIDGetRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
semconv.HTTPRouteKey.String("/payments/{payment_id}"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), PaymentsPaymentIDGetOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: PaymentsPaymentIDGetOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, PaymentsPaymentIDGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, PaymentsPaymentIDGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodePaymentsPaymentIDGetParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
var response PaymentsPaymentIDGetRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: PaymentsPaymentIDGetOperation,
OperationSummary: "Get payment information",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "payment_id",
In: "path",
}: params.PaymentID,
},
Raw: r,
}
type (
Request = struct{}
Params = PaymentsPaymentIDGetParams
Response = PaymentsPaymentIDGetRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackPaymentsPaymentIDGetParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.PaymentsPaymentIDGet(ctx, params)
return response, err
},
)
} else {
response, err = s.h.PaymentsPaymentIDGet(ctx, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodePaymentsPaymentIDGetResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handlePaymentsPostRequest handles POST /payments operation.
//
// To accept a payment, you need to create a payment object: https://yookassa.
// ru/developers/api#payment_object, Payment. It contains all the necessary payment information
// (amount, currency, and status). Payments have a linear life cycle, going from one status to the
// next sequentially.
//
// POST /payments
func (s *Server) handlePaymentsPostRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("POST"),
semconv.HTTPRouteKey.String("/payments"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), PaymentsPostOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: PaymentsPostOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, PaymentsPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, PaymentsPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodePaymentsPostParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
request, rawBody, close, err := s.decodePaymentsPostRequest(r)
if err != nil {
err = &ogenerrors.DecodeRequestError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeRequest", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
defer func() {
if err := close(); err != nil {
recordError("CloseRequest", err)
}
}()
var response PaymentsPostRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: PaymentsPostOperation,
OperationSummary: "Create a payment",
OperationID: "",
Body: request,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "Idempotence-Key",
In: "header",
}: params.IdempotenceKey,
},
Raw: r,
}
type (
Request = *PaymentsPostReq
Params = PaymentsPostParams
Response = PaymentsPostRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackPaymentsPostParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.PaymentsPost(ctx, request, params)
return response, err
},
)
} else {
response, err = s.h.PaymentsPost(ctx, request, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodePaymentsPostResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handlePayoutsGetRequest handles GET /payouts operation.
//
// Use this request to get a list of payouts. You can download payments created over the last 3 years.
//
// You can filter the list by specified criteria. Request authentication details: https://yookassa.
//
// ru/developers/using-api/interaction-format#auth depend on which payment solution you are using:
// basic payouts: https://yookassa.ru/developers/payouts/overview or payouts within the Safe Deal:
// https://yookassa.ru/developers/solutions-for-platforms/safe-deal/basics. More about working with
// lists: https://yookassa.ru/developers/using-api/lists.
//
// GET /payouts
func (s *Server) handlePayoutsGetRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
semconv.HTTPRouteKey.String("/payouts"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), PayoutsGetOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: PayoutsGetOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, PayoutsGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, PayoutsGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodePayoutsGetParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
var response PayoutsGetRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: PayoutsGetOperation,
OperationSummary: "List of payouts",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "created_at.gte",
In: "query",
}: params.CreatedAtGte,
{
Name: "created_at.gt",
In: "query",
}: params.CreatedAtGt,
{
Name: "created_at.lte",
In: "query",
}: params.CreatedAtLte,
{
Name: "created_at.lt",
In: "query",
}: params.CreatedAtLt,
{
Name: "payout_destination.type",
In: "query",
}: params.PayoutDestinationType,
{
Name: "status",
In: "query",
}: params.Status,
{
Name: "limit",
In: "query",
}: params.Limit,
{
Name: "cursor",
In: "query",
}: params.Cursor,
},
Raw: r,
}
type (
Request = struct{}
Params = PayoutsGetParams
Response = PayoutsGetRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackPayoutsGetParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.PayoutsGet(ctx, params)
return response, err
},
)
} else {
response, err = s.h.PayoutsGet(ctx, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodePayoutsGetResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handlePayoutsPayoutIDGetRequest handles GET /payouts/{payout_id} operation.
//
// Используйте этот запрос, чтобы получить информацию о
// текущем состоянии выплаты по ее уникальному
// идентификатору. Данные для аутентификации: https://yookassa.
// ru/developers/using-api/interaction-format#auth запросов зависят от того,
// какое платежное решение вы используете — обычные
// выплаты: https://yookassa.ru/developers/payouts/overview или выплаты в
// рамках Безопасной сделки: https://yookassa.
// ru/developers/solutions-for-platforms/safe-deal/basics.
//
// GET /payouts/{payout_id}
func (s *Server) handlePayoutsPayoutIDGetRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
semconv.HTTPRouteKey.String("/payouts/{payout_id}"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), PayoutsPayoutIDGetOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: PayoutsPayoutIDGetOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, PayoutsPayoutIDGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, PayoutsPayoutIDGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodePayoutsPayoutIDGetParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
var response PayoutsPayoutIDGetRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: PayoutsPayoutIDGetOperation,
OperationSummary: "Информация о выплате",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "payout_id",
In: "path",
}: params.PayoutID,
},
Raw: r,
}
type (
Request = struct{}
Params = PayoutsPayoutIDGetParams
Response = PayoutsPayoutIDGetRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackPayoutsPayoutIDGetParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.PayoutsPayoutIDGet(ctx, params)
return response, err
},
)
} else {
response, err = s.h.PayoutsPayoutIDGet(ctx, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodePayoutsPayoutIDGetResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handlePayoutsPostRequest handles POST /payouts operation.
//
// Используйте этот запрос, чтобы создать в ЮKassa объект
// выплаты: https://yookassa.ru/developers/api#payout_object. В запросе
// необходимо передать сумму выплаты, данные о способе
// получения выплаты (например, номер кошелька ЮMoney),
// описание выплаты и при необходимости дополнительные
// параметры, связанные с той функциональностью,
// которую вы хотите использовать. Передаваемые
// параметры и данные для аутентификации: https://yookassa.
// ru/developers/using-api/interaction-format#auth запросов зависят от того,
// какое платежное решение вы используете — обычные
// выплаты: https://yookassa.ru/developers/payouts/overview или выплаты в
// рамках Безопасной сделки: https://yookassa.
// ru/developers/solutions-for-platforms/safe-deal/basics.
//
// POST /payouts
func (s *Server) handlePayoutsPostRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("POST"),
semconv.HTTPRouteKey.String("/payouts"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), PayoutsPostOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: PayoutsPostOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, PayoutsPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, PayoutsPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodePayoutsPostParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
request, rawBody, close, err := s.decodePayoutsPostRequest(r)
if err != nil {
err = &ogenerrors.DecodeRequestError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeRequest", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
defer func() {
if err := close(); err != nil {
recordError("CloseRequest", err)
}
}()
var response PayoutsPostRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: PayoutsPostOperation,
OperationSummary: "Создание выплаты",
OperationID: "",
Body: request,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "Idempotence-Key",
In: "header",
}: params.IdempotenceKey,
},
Raw: r,
}
type (
Request = *PayoutRequest
Params = PayoutsPostParams
Response = PayoutsPostRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackPayoutsPostParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.PayoutsPost(ctx, request, params)
return response, err
},
)
} else {
response, err = s.h.PayoutsPost(ctx, request, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodePayoutsPostResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handlePayoutsSearchGetRequest handles GET /payouts/search operation.
//
// Use this request to search for payouts by the specified criteria. Available only for payouts
// created over the last 3 months. At this time, only search by the metadata parameter is available.
// You can also specify the date and time when the payout was created (the created_at parameter).
// Request authentication details: https://yookassa.ru/developers/using-api/interaction-format#auth
// depend on which payment solution you are using: basic payouts: https://yookassa.
// ru/developers/payouts/overview or payouts within the Safe Deal: https://yookassa.
// ru/developers/solutions-for-platforms/safe-deal/basics.
//
// GET /payouts/search
func (s *Server) handlePayoutsSearchGetRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
semconv.HTTPRouteKey.String("/payouts/search"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), PayoutsSearchGetOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: PayoutsSearchGetOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, PayoutsSearchGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, PayoutsSearchGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodePayoutsSearchGetParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
var response PayoutsSearchGetRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: PayoutsSearchGetOperation,
OperationSummary: "Search for payouts",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "created_at.gte",
In: "query",
}: params.CreatedAtGte,
{
Name: "created_at.gt",
In: "query",
}: params.CreatedAtGt,
{
Name: "created_at.lte",
In: "query",
}: params.CreatedAtLte,
{
Name: "created_at.lt",
In: "query",
}: params.CreatedAtLt,
{
Name: "metadata",
In: "query",
}: params.Metadata,
{
Name: "limit",
In: "query",
}: params.Limit,
{
Name: "cursor",
In: "query",
}: params.Cursor,
},
Raw: r,
}
type (
Request = struct{}
Params = PayoutsSearchGetParams
Response = PayoutsSearchGetRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackPayoutsSearchGetParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.PayoutsSearchGet(ctx, params)
return response, err
},
)
} else {
response, err = s.h.PayoutsSearchGet(ctx, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodePayoutsSearchGetResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handlePersonalDataPersonalDataIDGetRequest handles GET /personal_data/{personal_data_id} operation.
//
// С помощью этого запроса вы можете получить
// информацию о текущем статусе объекта персональных
// данных по его уникальному идентификатору.
//
// GET /personal_data/{personal_data_id}
func (s *Server) handlePersonalDataPersonalDataIDGetRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
semconv.HTTPRouteKey.String("/personal_data/{personal_data_id}"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), PersonalDataPersonalDataIDGetOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: PersonalDataPersonalDataIDGetOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, PersonalDataPersonalDataIDGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, PersonalDataPersonalDataIDGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodePersonalDataPersonalDataIDGetParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
var response PersonalDataPersonalDataIDGetRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: PersonalDataPersonalDataIDGetOperation,
OperationSummary: "Информация о персональных данных",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "personal_data_id",
In: "path",
}: params.PersonalDataID,
},
Raw: r,
}
type (
Request = struct{}
Params = PersonalDataPersonalDataIDGetParams
Response = PersonalDataPersonalDataIDGetRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackPersonalDataPersonalDataIDGetParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.PersonalDataPersonalDataIDGet(ctx, params)
return response, err
},
)
} else {
response, err = s.h.PersonalDataPersonalDataIDGet(ctx, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodePersonalDataPersonalDataIDGetResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handlePersonalDataPostRequest handles POST /personal_data operation.
//
// Используйте этот запрос, чтобы создать в ЮKassa объект
// персональных данных: https://yookassa.ru/developers/api#personal_data_object. В
// запросе необходимо указать тип данных (с какой целью
// они будут использоваться) и передать информацию о
// пользователе: фамилию, имя, отчество и другие — в
// зависимости от выбранного типа. Идентификатор
// созданного объекта персональных данных необходимо
// использовать в запросе на создание выплаты: https://yookassa.
// ru/developers/api#create_payout.
//
// POST /personal_data
func (s *Server) handlePersonalDataPostRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("POST"),
semconv.HTTPRouteKey.String("/personal_data"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), PersonalDataPostOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: PersonalDataPostOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, PersonalDataPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, PersonalDataPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodePersonalDataPostParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
request, rawBody, close, err := s.decodePersonalDataPostRequest(r)
if err != nil {
err = &ogenerrors.DecodeRequestError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeRequest", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
defer func() {
if err := close(); err != nil {
recordError("CloseRequest", err)
}
}()
var response PersonalDataPostRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: PersonalDataPostOperation,
OperationSummary: "Создание персональных данных",
OperationID: "",
Body: request,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "Idempotence-Key",
In: "header",
}: params.IdempotenceKey,
},
Raw: r,
}
type (
Request = PersonalDataPostReq
Params = PersonalDataPostParams
Response = PersonalDataPostRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackPersonalDataPostParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.PersonalDataPost(ctx, request, params)
return response, err
},
)
} else {
response, err = s.h.PersonalDataPost(ctx, request, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodePersonalDataPostResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handleReceiptsGetRequest handles GET /receipts operation.
//
// Запрос позволяет получить список чеков,
// отфильтрованный по заданным критериям. Можно
// запросить чеки по конкретному платежу, чеки по
// конкретному возврату или все чеки магазина.
// Подробнее о работе со списками: https://yookassa.
// ru/developers/using-api/lists.
//
// GET /receipts
func (s *Server) handleReceiptsGetRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
semconv.HTTPRouteKey.String("/receipts"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), ReceiptsGetOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: ReceiptsGetOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, ReceiptsGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, ReceiptsGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodeReceiptsGetParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
var response ReceiptsGetRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: ReceiptsGetOperation,
OperationSummary: "Список чеков",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "created_at.gte",
In: "query",
}: params.CreatedAtGte,
{
Name: "created_at.gt",
In: "query",
}: params.CreatedAtGt,
{
Name: "created_at.lte",
In: "query",
}: params.CreatedAtLte,
{
Name: "created_at.lt",
In: "query",
}: params.CreatedAtLt,
{
Name: "status",
In: "query",
}: params.Status,
{
Name: "payment_id",
In: "query",
}: params.PaymentID,
{
Name: "refund_id",
In: "query",
}: params.RefundID,
{
Name: "limit",
In: "query",
}: params.Limit,
{
Name: "cursor",
In: "query",
}: params.Cursor,
},
Raw: r,
}
type (
Request = struct{}
Params = ReceiptsGetParams
Response = ReceiptsGetRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackReceiptsGetParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.ReceiptsGet(ctx, params)
return response, err
},
)
} else {
response, err = s.h.ReceiptsGet(ctx, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodeReceiptsGetResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handleReceiptsPostRequest handles POST /receipts operation.
//
// Используйте этот запрос при оплате с соблюдением
// требований 54-ФЗ: https://yookassa.
// ru/developers/payment-acceptance/receipts/54fz/basics, чтобы создать чек
// зачета предоплаты. Если вы работаете по сценарию
// Сначала платеж, потом чек: https://yookassa.
// ru/developers/payment-acceptance/receipts/54fz/other-services/basics#receipt-after-payment, в
// запросе также нужно передавать данные для
// формирования чека прихода и чека возврата прихода.
//
// POST /receipts
func (s *Server) handleReceiptsPostRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("POST"),
semconv.HTTPRouteKey.String("/receipts"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), ReceiptsPostOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: ReceiptsPostOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, ReceiptsPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, ReceiptsPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodeReceiptsPostParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
request, rawBody, close, err := s.decodeReceiptsPostRequest(r)
if err != nil {
err = &ogenerrors.DecodeRequestError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeRequest", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
defer func() {
if err := close(); err != nil {
recordError("CloseRequest", err)
}
}()
var response ReceiptsPostRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: ReceiptsPostOperation,
OperationSummary: "Создание чека",
OperationID: "",
Body: request,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "Idempotence-Key",
In: "header",
}: params.IdempotenceKey,
},
Raw: r,
}
type (
Request = PostReceiptData
Params = ReceiptsPostParams
Response = ReceiptsPostRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackReceiptsPostParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.ReceiptsPost(ctx, request, params)
return response, err
},
)
} else {
response, err = s.h.ReceiptsPost(ctx, request, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodeReceiptsPostResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handleReceiptsReceiptIDGetRequest handles GET /receipts/{receipt_id} operation.
//
// Запрос позволяет получить информацию о текущем
// состоянии чека по его уникальному идентификатору.
//
// GET /receipts/{receipt_id}
func (s *Server) handleReceiptsReceiptIDGetRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
semconv.HTTPRouteKey.String("/receipts/{receipt_id}"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), ReceiptsReceiptIDGetOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: ReceiptsReceiptIDGetOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, ReceiptsReceiptIDGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, ReceiptsReceiptIDGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodeReceiptsReceiptIDGetParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
var response ReceiptsReceiptIDGetRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: ReceiptsReceiptIDGetOperation,
OperationSummary: "Информация о чеке",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "receipt_id",
In: "path",
}: params.ReceiptID,
},
Raw: r,
}
type (
Request = struct{}
Params = ReceiptsReceiptIDGetParams
Response = ReceiptsReceiptIDGetRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackReceiptsReceiptIDGetParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.ReceiptsReceiptIDGet(ctx, params)
return response, err
},
)
} else {
response, err = s.h.ReceiptsReceiptIDGet(ctx, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodeReceiptsReceiptIDGetResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handleRefundsGetRequest handles GET /refunds operation.
//
// Use this request to get a list of refunds. You can download refunds created over the last 3 years.
// You can filter the list by specified criteria. More about working with lists: https://yookassa.
// ru/developers/using-api/lists.
//
// GET /refunds
func (s *Server) handleRefundsGetRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
semconv.HTTPRouteKey.String("/refunds"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), RefundsGetOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: RefundsGetOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, RefundsGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, RefundsGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodeRefundsGetParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
var response RefundsGetRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: RefundsGetOperation,
OperationSummary: "Список возвратов",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "created_at.gte",
In: "query",
}: params.CreatedAtGte,
{
Name: "created_at.gt",
In: "query",
}: params.CreatedAtGt,
{
Name: "created_at.lte",
In: "query",
}: params.CreatedAtLte,
{
Name: "created_at.lt",
In: "query",
}: params.CreatedAtLt,
{
Name: "payment_id",
In: "query",
}: params.PaymentID,
{
Name: "status",
In: "query",
}: params.Status,
{
Name: "limit",
In: "query",
}: params.Limit,
{
Name: "cursor",
In: "query",
}: params.Cursor,
},
Raw: r,
}
type (
Request = struct{}
Params = RefundsGetParams
Response = RefundsGetRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackRefundsGetParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.RefundsGet(ctx, params)
return response, err
},
)
} else {
response, err = s.h.RefundsGet(ctx, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodeRefundsGetResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handleRefundsPostRequest handles POST /refunds operation.
//
// Создает возврат успешного платежа на указанную сумму.
//
// Платеж можно вернуть только в течение трех лет с
//
// момента его создания: https://yookassa.ru/developers/api#create_payment.
// Комиссия ЮKassa за проведение платежа не возвращается.
//
// POST /refunds
func (s *Server) handleRefundsPostRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("POST"),
semconv.HTTPRouteKey.String("/refunds"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), RefundsPostOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: RefundsPostOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, RefundsPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, RefundsPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodeRefundsPostParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
request, rawBody, close, err := s.decodeRefundsPostRequest(r)
if err != nil {
err = &ogenerrors.DecodeRequestError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeRequest", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
defer func() {
if err := close(); err != nil {
recordError("CloseRequest", err)
}
}()
var response RefundsPostRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: RefundsPostOperation,
OperationSummary: "Создание возврата",
OperationID: "",
Body: request,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "Idempotence-Key",
In: "header",
}: params.IdempotenceKey,
},
Raw: r,
}
type (
Request = *RefundsPostReq
Params = RefundsPostParams
Response = RefundsPostRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackRefundsPostParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.RefundsPost(ctx, request, params)
return response, err
},
)
} else {
response, err = s.h.RefundsPost(ctx, request, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodeRefundsPostResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handleRefundsRefundIDGetRequest handles GET /refunds/{refund_id} operation.
//
// Запрос позволяет получить информацию о текущем
// состоянии возврата по его уникальному
// идентификатору.
//
// GET /refunds/{refund_id}
func (s *Server) handleRefundsRefundIDGetRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
semconv.HTTPRouteKey.String("/refunds/{refund_id}"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), RefundsRefundIDGetOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: RefundsRefundIDGetOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, RefundsRefundIDGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, RefundsRefundIDGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodeRefundsRefundIDGetParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
var response RefundsRefundIDGetRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: RefundsRefundIDGetOperation,
OperationSummary: "Информация о возврате",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "refund_id",
In: "path",
}: params.RefundID,
},
Raw: r,
}
type (
Request = struct{}
Params = RefundsRefundIDGetParams
Response = RefundsRefundIDGetRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackRefundsRefundIDGetParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.RefundsRefundIDGet(ctx, params)
return response, err
},
)
} else {
response, err = s.h.RefundsRefundIDGet(ctx, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodeRefundsRefundIDGetResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handleSbpBanksGetRequest handles GET /sbp_banks operation.
//
// С помощью этого запроса вы можете получить
// актуальный список всех участников СБП. Список нужно
// вывести получателю выплаты, идентификатор
// выбранного участника СБП необходимо использовать в
// запросе на создание выплаты: https://yookassa.
// ru/developers/api#create_payout. Подробнее о выплатах через СБП:
// https://yookassa.ru/developers/payouts/making-payouts/sbp.
//
// GET /sbp_banks
func (s *Server) handleSbpBanksGetRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
semconv.HTTPRouteKey.String("/sbp_banks"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), SbpBanksGetOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: SbpBanksGetOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, SbpBanksGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, SbpBanksGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
var rawBody []byte
var response SbpBanksGetRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: SbpBanksGetOperation,
OperationSummary: "Список участников СБП",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{},
Raw: r,
}
type (
Request = struct{}
Params = struct{}
Response = SbpBanksGetRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
nil,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.SbpBanksGet(ctx)
return response, err
},
)
} else {
response, err = s.h.SbpBanksGet(ctx)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodeSbpBanksGetResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handleWebhooksGetRequest handles GET /webhooks operation.
//
// Запрос позволяет узнать, какие webhook есть для
// переданного OAuth-токена.
//
// GET /webhooks
func (s *Server) handleWebhooksGetRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("GET"),
semconv.HTTPRouteKey.String("/webhooks"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), WebhooksGetOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: WebhooksGetOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, WebhooksGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, WebhooksGetOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
var rawBody []byte
var response WebhooksGetRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: WebhooksGetOperation,
OperationSummary: "Список созданных webhook",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{},
Raw: r,
}
type (
Request = struct{}
Params = struct{}
Response = WebhooksGetRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
nil,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.WebhooksGet(ctx)
return response, err
},
)
} else {
response, err = s.h.WebhooksGet(ctx)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodeWebhooksGetResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handleWebhooksPostRequest handles POST /webhooks operation.
//
// Запрос позволяет подписаться на уведомления о
// событиях: https://yookassa.ru/developers/using-api/webhooks#events (например,
// переход платежа в статус succeeded). C помощью webhook можно
// подписаться только на события платежей и возвратов.
// Если вы хотите получать уведомления о нескольких
// событиях, вам нужно для каждого из них создать свой
// webhook. Для каждого OAuth-токена нужно создавать свой
// набор webhook.
//
// POST /webhooks
func (s *Server) handleWebhooksPostRequest(args [0]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("POST"),
semconv.HTTPRouteKey.String("/webhooks"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), WebhooksPostOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: WebhooksPostOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, WebhooksPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, WebhooksPostOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodeWebhooksPostParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
request, rawBody, close, err := s.decodeWebhooksPostRequest(r)
if err != nil {
err = &ogenerrors.DecodeRequestError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeRequest", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
defer func() {
if err := close(); err != nil {
recordError("CloseRequest", err)
}
}()
var response WebhooksPostRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: WebhooksPostOperation,
OperationSummary: "Создание webhook",
OperationID: "",
Body: request,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "Idempotence-Key",
In: "header",
}: params.IdempotenceKey,
},
Raw: r,
}
type (
Request = *WebhooksPostReq
Params = WebhooksPostParams
Response = WebhooksPostRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackWebhooksPostParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.WebhooksPost(ctx, request, params)
return response, err
},
)
} else {
response, err = s.h.WebhooksPost(ctx, request, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodeWebhooksPostResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}
// handleWebhooksWebhookIDDeleteRequest handles DELETE /webhooks/{webhook_id} operation.
//
// Запрос позволяет отписаться от уведомлений о событии
// для переданного OAuth-токена. Чтобы удалить webhook, вам
// нужно передать в запросе его идентификатор.
//
// DELETE /webhooks/{webhook_id}
func (s *Server) handleWebhooksWebhookIDDeleteRequest(args [1]string, argsEscaped bool, w http.ResponseWriter, r *http.Request) {
statusWriter := &codeRecorder{ResponseWriter: w}
w = statusWriter
otelAttrs := []attribute.KeyValue{
semconv.HTTPRequestMethodKey.String("DELETE"),
semconv.HTTPRouteKey.String("/webhooks/{webhook_id}"),
}
// Add attributes from config.
otelAttrs = append(otelAttrs, s.cfg.Attributes...)
// Start a span for this request.
ctx, span := s.cfg.Tracer.Start(r.Context(), WebhooksWebhookIDDeleteOperation,
trace.WithAttributes(otelAttrs...),
serverSpanKind,
)
defer span.End()
// Add Labeler to context.
labeler := &Labeler{attrs: otelAttrs}
ctx = contextWithLabeler(ctx, labeler)
// Run stopwatch.
startTime := time.Now()
defer func() {
elapsedDuration := time.Since(startTime)
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
code := statusWriter.status
if code != 0 {
codeAttr := semconv.HTTPResponseStatusCode(code)
attrs = append(attrs, codeAttr)
span.SetAttributes(codeAttr)
}
attrOpt := metric.WithAttributes(attrs...)
// Increment request counter.
s.requests.Add(ctx, 1, attrOpt)
// Use floating point division here for higher precision (instead of Millisecond method).
s.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), attrOpt)
}()
var (
recordError = func(stage string, err error) {
span.RecordError(err)
// https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
// Span Status MUST be left unset if HTTP status code was in the 1xx, 2xx or 3xx ranges,
// unless there was another error (e.g., network error receiving the response body; or 3xx codes with
// max redirects exceeded), in which case status MUST be set to Error.
code := statusWriter.status
if code < 100 || code >= 500 {
span.SetStatus(codes.Error, stage)
}
attrSet := labeler.AttributeSet()
attrs := attrSet.ToSlice()
if code != 0 {
attrs = append(attrs, semconv.HTTPResponseStatusCode(code))
}
s.errors.Add(ctx, 1, metric.WithAttributes(attrs...))
}
err error
opErrContext = ogenerrors.OperationContext{
Name: WebhooksWebhookIDDeleteOperation,
ID: "",
}
)
{
type bitset = [1]uint8
var satisfied bitset
{
sctx, ok, err := s.securityBasicAuth(ctx, WebhooksWebhookIDDeleteOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "BasicAuth",
Err: err,
}
defer recordError("Security:BasicAuth", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 0
ctx = sctx
}
}
{
sctx, ok, err := s.securityOAuth2(ctx, WebhooksWebhookIDDeleteOperation, r)
if err != nil {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Security: "OAuth2",
Err: err,
}
defer recordError("Security:OAuth2", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if ok {
satisfied[0] |= 1 << 1
ctx = sctx
}
}
if ok := func() bool {
nextRequirement:
for _, requirement := range []bitset{
{0b00000001},
{0b00000010},
} {
for i, mask := range requirement {
if satisfied[i]&mask != mask {
continue nextRequirement
}
}
return true
}
return false
}(); !ok {
err = &ogenerrors.SecurityError{
OperationContext: opErrContext,
Err: ogenerrors.ErrSecurityRequirementIsNotSatisfied,
}
defer recordError("Security", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
}
params, err := decodeWebhooksWebhookIDDeleteParams(args, argsEscaped, r)
if err != nil {
err = &ogenerrors.DecodeParamsError{
OperationContext: opErrContext,
Err: err,
}
defer recordError("DecodeParams", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
var rawBody []byte
var response WebhooksWebhookIDDeleteRes
if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{
Context: ctx,
OperationName: WebhooksWebhookIDDeleteOperation,
OperationSummary: "Удаление webhook",
OperationID: "",
Body: nil,
RawBody: rawBody,
Params: middleware.Parameters{
{
Name: "webhook_id",
In: "path",
}: params.WebhookID,
},
Raw: r,
}
type (
Request = struct{}
Params = WebhooksWebhookIDDeleteParams
Response = WebhooksWebhookIDDeleteRes
)
response, err = middleware.HookMiddleware[
Request,
Params,
Response,
](
m,
mreq,
unpackWebhooksWebhookIDDeleteParams,
func(ctx context.Context, request Request, params Params) (response Response, err error) {
response, err = s.h.WebhooksWebhookIDDelete(ctx, params)
return response, err
},
)
} else {
response, err = s.h.WebhooksWebhookIDDelete(ctx, params)
}
if err != nil {
defer recordError("Internal", err)
s.cfg.ErrorHandler(ctx, w, r, err)
return
}
if err := encodeWebhooksWebhookIDDeleteResponse(response, w, span); err != nil {
defer recordError("EncodeResponse", err)
if !errors.Is(err, ht.ErrInternalServerErrorResponse) {
s.cfg.ErrorHandler(ctx, w, r, err)
}
return
}
}