// Code generated by ogen, DO NOT EDIT. package gen import ( "context" "net/url" "strings" "time" "github.com/go-faster/errors" "github.com/ogen-go/ogen/conv" ht "github.com/ogen-go/ogen/http" "github.com/ogen-go/ogen/ogenerrors" "github.com/ogen-go/ogen/uri" "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" ) func trimTrailingSlashes(u *url.URL) { u.Path = strings.TrimRight(u.Path, "/") u.RawPath = strings.TrimRight(u.RawPath, "/") } // Invoker invokes operations described by OpenAPI v3 specification. type Invoker interface { // DealsDealIDGet invokes GET /deals/{deal_id} operation. // // Запрос позволяет получить информацию о текущем // состоянии сделки по ее уникальному идентификатору. // // GET /deals/{deal_id} DealsDealIDGet(ctx context.Context, params DealsDealIDGetParams) (DealsDealIDGetRes, error) // DealsGet invokes GET /deals operation. // // Запрос позволяет получить список сделок, // отфильтрованный по заданным критериям. Подробнее о // работе со списками: https://yookassa.ru/developers/using-api/lists. // // GET /deals DealsGet(ctx context.Context, params DealsGetParams) (DealsGetRes, error) // DealsPost invokes POST /deals operation. // // Запрос позволяет создать сделку, в рамках которой // необходимо принять оплату от покупателя и // перечислить ее продавцу. // // POST /deals DealsPost(ctx context.Context, request *SafeDealRequest, params DealsPostParams) (DealsPostRes, error) // MeGet invokes 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 MeGet(ctx context.Context, params MeGetParams) (MeGetRes, error) // PaymentMethodsPaymentMethodIDGet invokes GET /payment_methods/{payment_method_id} operation. // // Используйте этот запрос, чтобы получить информацию о // текущем состоянии способа оплаты по его уникальному // идентификатору. // // GET /payment_methods/{payment_method_id} PaymentMethodsPaymentMethodIDGet(ctx context.Context, params PaymentMethodsPaymentMethodIDGetParams) (PaymentMethodsPaymentMethodIDGetRes, error) // PaymentMethodsPost invokes 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 PaymentMethodsPost(ctx context.Context, request PaymentMethodsPostReq, params PaymentMethodsPostParams) (PaymentMethodsPostRes, error) // PaymentsGet invokes 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 PaymentsGet(ctx context.Context, params PaymentsGetParams) (PaymentsGetRes, error) // PaymentsPaymentIDCancelPost invokes 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 payer’s 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 PaymentsPaymentIDCancelPost(ctx context.Context, params PaymentsPaymentIDCancelPostParams) (PaymentsPaymentIDCancelPostRes, error) // PaymentsPaymentIDCapturePost invokes POST /payments/{payment_id}/capture operation. // // Confirm you’re 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 PaymentsPaymentIDCapturePost(ctx context.Context, request *PaymentsPaymentIDCapturePostReq, params PaymentsPaymentIDCapturePostParams) (PaymentsPaymentIDCapturePostRes, error) // PaymentsPaymentIDGet invokes 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} PaymentsPaymentIDGet(ctx context.Context, params PaymentsPaymentIDGetParams) (PaymentsPaymentIDGetRes, error) // PaymentsPost invokes 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 PaymentsPost(ctx context.Context, request *PaymentsPostReq, params PaymentsPostParams) (PaymentsPostRes, error) // PayoutsGet invokes 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 PayoutsGet(ctx context.Context, params PayoutsGetParams) (PayoutsGetRes, error) // PayoutsPayoutIDGet invokes 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} PayoutsPayoutIDGet(ctx context.Context, params PayoutsPayoutIDGetParams) (PayoutsPayoutIDGetRes, error) // PayoutsPost invokes 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 PayoutsPost(ctx context.Context, request *PayoutRequest, params PayoutsPostParams) (PayoutsPostRes, error) // PayoutsSearchGet invokes 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 PayoutsSearchGet(ctx context.Context, params PayoutsSearchGetParams) (PayoutsSearchGetRes, error) // PersonalDataPersonalDataIDGet invokes GET /personal_data/{personal_data_id} operation. // // С помощью этого запроса вы можете получить // информацию о текущем статусе объекта персональных // данных по его уникальному идентификатору. // // GET /personal_data/{personal_data_id} PersonalDataPersonalDataIDGet(ctx context.Context, params PersonalDataPersonalDataIDGetParams) (PersonalDataPersonalDataIDGetRes, error) // PersonalDataPost invokes POST /personal_data operation. // // Используйте этот запрос, чтобы создать в ЮKassa объект // персональных данных: https://yookassa.ru/developers/api#personal_data_object. В // запросе необходимо указать тип данных (с какой целью // они будут использоваться) и передать информацию о // пользователе: фамилию, имя, отчество и другие — в // зависимости от выбранного типа. Идентификатор // созданного объекта персональных данных необходимо // использовать в запросе на создание выплаты: https://yookassa. // ru/developers/api#create_payout. // // POST /personal_data PersonalDataPost(ctx context.Context, request PersonalDataPostReq, params PersonalDataPostParams) (PersonalDataPostRes, error) // ReceiptsGet invokes GET /receipts operation. // // Запрос позволяет получить список чеков, // отфильтрованный по заданным критериям. Можно // запросить чеки по конкретному платежу, чеки по // конкретному возврату или все чеки магазина. // Подробнее о работе со списками: https://yookassa. // ru/developers/using-api/lists. // // GET /receipts ReceiptsGet(ctx context.Context, params ReceiptsGetParams) (ReceiptsGetRes, error) // ReceiptsPost invokes 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 ReceiptsPost(ctx context.Context, request PostReceiptData, params ReceiptsPostParams) (ReceiptsPostRes, error) // ReceiptsReceiptIDGet invokes GET /receipts/{receipt_id} operation. // // Запрос позволяет получить информацию о текущем // состоянии чека по его уникальному идентификатору. // // GET /receipts/{receipt_id} ReceiptsReceiptIDGet(ctx context.Context, params ReceiptsReceiptIDGetParams) (ReceiptsReceiptIDGetRes, error) // RefundsGet invokes 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 RefundsGet(ctx context.Context, params RefundsGetParams) (RefundsGetRes, error) // RefundsPost invokes POST /refunds operation. // // Создает возврат успешного платежа на указанную сумму. // Платеж можно вернуть только в течение трех лет с // момента его создания: https://yookassa.ru/developers/api#create_payment. // Комиссия ЮKassa за проведение платежа не возвращается. // // POST /refunds RefundsPost(ctx context.Context, request *RefundsPostReq, params RefundsPostParams) (RefundsPostRes, error) // RefundsRefundIDGet invokes GET /refunds/{refund_id} operation. // // Запрос позволяет получить информацию о текущем // состоянии возврата по его уникальному // идентификатору. // // GET /refunds/{refund_id} RefundsRefundIDGet(ctx context.Context, params RefundsRefundIDGetParams) (RefundsRefundIDGetRes, error) // SbpBanksGet invokes GET /sbp_banks operation. // // С помощью этого запроса вы можете получить // актуальный список всех участников СБП. Список нужно // вывести получателю выплаты, идентификатор // выбранного участника СБП необходимо использовать в // запросе на создание выплаты: https://yookassa. // ru/developers/api#create_payout. Подробнее о выплатах через СБП: // https://yookassa.ru/developers/payouts/making-payouts/sbp. // // GET /sbp_banks SbpBanksGet(ctx context.Context) (SbpBanksGetRes, error) // WebhooksGet invokes GET /webhooks operation. // // Запрос позволяет узнать, какие webhook есть для // переданного OAuth-токена. // // GET /webhooks WebhooksGet(ctx context.Context) (WebhooksGetRes, error) // WebhooksPost invokes POST /webhooks operation. // // Запрос позволяет подписаться на уведомления о // событиях: https://yookassa.ru/developers/using-api/webhooks#events (например, // переход платежа в статус succeeded). C помощью webhook можно // подписаться только на события платежей и возвратов. // Если вы хотите получать уведомления о нескольких // событиях, вам нужно для каждого из них создать свой // webhook. Для каждого OAuth-токена нужно создавать свой // набор webhook. // // POST /webhooks WebhooksPost(ctx context.Context, request *WebhooksPostReq, params WebhooksPostParams) (WebhooksPostRes, error) // WebhooksWebhookIDDelete invokes DELETE /webhooks/{webhook_id} operation. // // Запрос позволяет отписаться от уведомлений о событии // для переданного OAuth-токена. Чтобы удалить webhook, вам // нужно передать в запросе его идентификатор. // // DELETE /webhooks/{webhook_id} WebhooksWebhookIDDelete(ctx context.Context, params WebhooksWebhookIDDeleteParams) (WebhooksWebhookIDDeleteRes, error) } // Client implements OAS client. type Client struct { serverURL *url.URL sec SecuritySource baseClient } // NewClient initializes new Client defined by OAS. func NewClient(serverURL string, sec SecuritySource, opts ...ClientOption) (*Client, error) { u, err := url.Parse(serverURL) if err != nil { return nil, err } trimTrailingSlashes(u) c, err := newClientConfig(opts...).baseClient() if err != nil { return nil, err } return &Client{ serverURL: u, sec: sec, baseClient: c, }, nil } type serverURLKey struct{} // WithServerURL sets context key to override server URL. func WithServerURL(ctx context.Context, u *url.URL) context.Context { return context.WithValue(ctx, serverURLKey{}, u) } func (c *Client) requestURL(ctx context.Context) *url.URL { u, ok := ctx.Value(serverURLKey{}).(*url.URL) if !ok { return c.serverURL } return u } // DealsDealIDGet invokes GET /deals/{deal_id} operation. // // Запрос позволяет получить информацию о текущем // состоянии сделки по ее уникальному идентификатору. // // GET /deals/{deal_id} func (c *Client) DealsDealIDGet(ctx context.Context, params DealsDealIDGetParams) (DealsDealIDGetRes, error) { res, err := c.sendDealsDealIDGet(ctx, params) return res, err } func (c *Client) sendDealsDealIDGet(ctx context.Context, params DealsDealIDGetParams) (res DealsDealIDGetRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("GET"), semconv.URLTemplateKey.String("/deals/{deal_id}"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, DealsDealIDGetOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [2]string pathParts[0] = "/deals/" { // Encode "deal_id" parameter. e := uri.NewPathEncoder(uri.PathEncoderConfig{ Param: "deal_id", Style: uri.PathStyleSimple, Explode: false, }) if err := func() error { if unwrapped := string(params.DealID); true { return e.EncodeValue(conv.StringToString(unwrapped)) } return nil }(); err != nil { return res, errors.Wrap(err, "encode path") } encoded, err := e.Result() if err != nil { return res, errors.Wrap(err, "encode path") } pathParts[1] = encoded } uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "GET", u) if err != nil { return res, errors.Wrap(err, "create request") } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, DealsDealIDGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, DealsDealIDGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodeDealsDealIDGetResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // DealsGet invokes GET /deals operation. // // Запрос позволяет получить список сделок, // отфильтрованный по заданным критериям. Подробнее о // работе со списками: https://yookassa.ru/developers/using-api/lists. // // GET /deals func (c *Client) DealsGet(ctx context.Context, params DealsGetParams) (DealsGetRes, error) { res, err := c.sendDealsGet(ctx, params) return res, err } func (c *Client) sendDealsGet(ctx context.Context, params DealsGetParams) (res DealsGetRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("GET"), semconv.URLTemplateKey.String("/deals"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, DealsGetOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [1]string pathParts[0] = "/deals" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeQueryParams" q := uri.NewQueryEncoder() { // Encode "created_at.gte" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.gte", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtGte.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.gt" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.gt", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtGt.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.lte" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.lte", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtLte.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.lt" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.lt", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtLt.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "expires_at.gte" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "expires_at.gte", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.ExpiresAtGte.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "expires_at.gt" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "expires_at.gt", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.ExpiresAtGt.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "expires_at.lte" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "expires_at.lte", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.ExpiresAtLte.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "expires_at.lt" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "expires_at.lt", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.ExpiresAtLt.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "status" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "status", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Status.Get(); ok { return e.EncodeValue(conv.StringToString(string(val))) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "full_text_search" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "full_text_search", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.FullTextSearch.Get(); ok { return e.EncodeValue(conv.StringToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "limit" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "limit", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Limit.Get(); ok { return e.EncodeValue(conv.IntToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "cursor" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "cursor", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Cursor.Get(); ok { return e.EncodeValue(conv.StringToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } u.RawQuery = q.Values().Encode() stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "GET", u) if err != nil { return res, errors.Wrap(err, "create request") } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, DealsGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, DealsGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodeDealsGetResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // DealsPost invokes POST /deals operation. // // Запрос позволяет создать сделку, в рамках которой // необходимо принять оплату от покупателя и // перечислить ее продавцу. // // POST /deals func (c *Client) DealsPost(ctx context.Context, request *SafeDealRequest, params DealsPostParams) (DealsPostRes, error) { res, err := c.sendDealsPost(ctx, request, params) return res, err } func (c *Client) sendDealsPost(ctx context.Context, request *SafeDealRequest, params DealsPostParams) (res DealsPostRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("POST"), semconv.URLTemplateKey.String("/deals"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, DealsPostOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [1]string pathParts[0] = "/deals" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "POST", u) if err != nil { return res, errors.Wrap(err, "create request") } if err := encodeDealsPostRequest(request, r); err != nil { return res, errors.Wrap(err, "encode request") } stage = "EncodeHeaderParams" h := uri.NewHeaderEncoder(r.Header) { cfg := uri.HeaderParameterEncodingConfig{ Name: "Idempotence-Key", Explode: false, } if err := h.EncodeParam(cfg, func(e uri.Encoder) error { return e.EncodeValue(conv.StringToString(params.IdempotenceKey)) }); err != nil { return res, errors.Wrap(err, "encode header") } } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, DealsPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, DealsPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodeDealsPostResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // MeGet invokes 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 (c *Client) MeGet(ctx context.Context, params MeGetParams) (MeGetRes, error) { res, err := c.sendMeGet(ctx, params) return res, err } func (c *Client) sendMeGet(ctx context.Context, params MeGetParams) (res MeGetRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("GET"), semconv.URLTemplateKey.String("/me"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, MeGetOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [1]string pathParts[0] = "/me" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeQueryParams" q := uri.NewQueryEncoder() { // Encode "on_behalf_of" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "on_behalf_of", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.OnBehalfOf.Get(); ok { if unwrapped := string(val); true { return e.EncodeValue(conv.StringToString(unwrapped)) } return nil } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } u.RawQuery = q.Values().Encode() stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "GET", u) if err != nil { return res, errors.Wrap(err, "create request") } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, MeGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, MeGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodeMeGetResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // PaymentMethodsPaymentMethodIDGet invokes GET /payment_methods/{payment_method_id} operation. // // Используйте этот запрос, чтобы получить информацию о // текущем состоянии способа оплаты по его уникальному // идентификатору. // // GET /payment_methods/{payment_method_id} func (c *Client) PaymentMethodsPaymentMethodIDGet(ctx context.Context, params PaymentMethodsPaymentMethodIDGetParams) (PaymentMethodsPaymentMethodIDGetRes, error) { res, err := c.sendPaymentMethodsPaymentMethodIDGet(ctx, params) return res, err } func (c *Client) sendPaymentMethodsPaymentMethodIDGet(ctx context.Context, params PaymentMethodsPaymentMethodIDGetParams) (res PaymentMethodsPaymentMethodIDGetRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("GET"), semconv.URLTemplateKey.String("/payment_methods/{payment_method_id}"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, PaymentMethodsPaymentMethodIDGetOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [2]string pathParts[0] = "/payment_methods/" { // Encode "payment_method_id" parameter. e := uri.NewPathEncoder(uri.PathEncoderConfig{ Param: "payment_method_id", Style: uri.PathStyleSimple, Explode: false, }) if err := func() error { if unwrapped := string(params.PaymentMethodID); true { return e.EncodeValue(conv.StringToString(unwrapped)) } return nil }(); err != nil { return res, errors.Wrap(err, "encode path") } encoded, err := e.Result() if err != nil { return res, errors.Wrap(err, "encode path") } pathParts[1] = encoded } uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "GET", u) if err != nil { return res, errors.Wrap(err, "create request") } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, PaymentMethodsPaymentMethodIDGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, PaymentMethodsPaymentMethodIDGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodePaymentMethodsPaymentMethodIDGetResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // PaymentMethodsPost invokes 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 (c *Client) PaymentMethodsPost(ctx context.Context, request PaymentMethodsPostReq, params PaymentMethodsPostParams) (PaymentMethodsPostRes, error) { res, err := c.sendPaymentMethodsPost(ctx, request, params) return res, err } func (c *Client) sendPaymentMethodsPost(ctx context.Context, request PaymentMethodsPostReq, params PaymentMethodsPostParams) (res PaymentMethodsPostRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("POST"), semconv.URLTemplateKey.String("/payment_methods"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, PaymentMethodsPostOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [1]string pathParts[0] = "/payment_methods" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "POST", u) if err != nil { return res, errors.Wrap(err, "create request") } if err := encodePaymentMethodsPostRequest(request, r); err != nil { return res, errors.Wrap(err, "encode request") } stage = "EncodeHeaderParams" h := uri.NewHeaderEncoder(r.Header) { cfg := uri.HeaderParameterEncodingConfig{ Name: "Idempotence-Key", Explode: false, } if err := h.EncodeParam(cfg, func(e uri.Encoder) error { return e.EncodeValue(conv.StringToString(params.IdempotenceKey)) }); err != nil { return res, errors.Wrap(err, "encode header") } } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, PaymentMethodsPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, PaymentMethodsPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodePaymentMethodsPostResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // PaymentsGet invokes 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 (c *Client) PaymentsGet(ctx context.Context, params PaymentsGetParams) (PaymentsGetRes, error) { res, err := c.sendPaymentsGet(ctx, params) return res, err } func (c *Client) sendPaymentsGet(ctx context.Context, params PaymentsGetParams) (res PaymentsGetRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("GET"), semconv.URLTemplateKey.String("/payments"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, PaymentsGetOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [1]string pathParts[0] = "/payments" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeQueryParams" q := uri.NewQueryEncoder() { // Encode "created_at.gte" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.gte", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtGte.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.gt" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.gt", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtGt.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.lte" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.lte", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtLte.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.lt" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.lt", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtLt.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "captured_at.gte" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "captured_at.gte", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CapturedAtGte.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "captured_at.gt" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "captured_at.gt", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CapturedAtGt.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "captured_at.lte" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "captured_at.lte", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CapturedAtLte.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "captured_at.lt" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "captured_at.lt", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CapturedAtLt.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "payment_method" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "payment_method", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.PaymentMethod.Get(); ok { return e.EncodeValue(conv.StringToString(string(val))) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "status" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "status", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Status.Get(); ok { return e.EncodeValue(conv.StringToString(string(val))) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "limit" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "limit", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Limit.Get(); ok { return e.EncodeValue(conv.IntToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "cursor" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "cursor", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Cursor.Get(); ok { return e.EncodeValue(conv.StringToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } u.RawQuery = q.Values().Encode() stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "GET", u) if err != nil { return res, errors.Wrap(err, "create request") } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, PaymentsGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, PaymentsGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodePaymentsGetResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // PaymentsPaymentIDCancelPost invokes 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 payer’s 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 (c *Client) PaymentsPaymentIDCancelPost(ctx context.Context, params PaymentsPaymentIDCancelPostParams) (PaymentsPaymentIDCancelPostRes, error) { res, err := c.sendPaymentsPaymentIDCancelPost(ctx, params) return res, err } func (c *Client) sendPaymentsPaymentIDCancelPost(ctx context.Context, params PaymentsPaymentIDCancelPostParams) (res PaymentsPaymentIDCancelPostRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("POST"), semconv.URLTemplateKey.String("/payments/{payment_id}/cancel"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, PaymentsPaymentIDCancelPostOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [3]string pathParts[0] = "/payments/" { // Encode "payment_id" parameter. e := uri.NewPathEncoder(uri.PathEncoderConfig{ Param: "payment_id", Style: uri.PathStyleSimple, Explode: false, }) if err := func() error { if unwrapped := string(params.PaymentID); true { return e.EncodeValue(conv.StringToString(unwrapped)) } return nil }(); err != nil { return res, errors.Wrap(err, "encode path") } encoded, err := e.Result() if err != nil { return res, errors.Wrap(err, "encode path") } pathParts[1] = encoded } pathParts[2] = "/cancel" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "POST", u) if err != nil { return res, errors.Wrap(err, "create request") } stage = "EncodeHeaderParams" h := uri.NewHeaderEncoder(r.Header) { cfg := uri.HeaderParameterEncodingConfig{ Name: "Idempotence-Key", Explode: false, } if err := h.EncodeParam(cfg, func(e uri.Encoder) error { return e.EncodeValue(conv.StringToString(params.IdempotenceKey)) }); err != nil { return res, errors.Wrap(err, "encode header") } } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, PaymentsPaymentIDCancelPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, PaymentsPaymentIDCancelPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodePaymentsPaymentIDCancelPostResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // PaymentsPaymentIDCapturePost invokes POST /payments/{payment_id}/capture operation. // // Confirm you’re 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 (c *Client) PaymentsPaymentIDCapturePost(ctx context.Context, request *PaymentsPaymentIDCapturePostReq, params PaymentsPaymentIDCapturePostParams) (PaymentsPaymentIDCapturePostRes, error) { res, err := c.sendPaymentsPaymentIDCapturePost(ctx, request, params) return res, err } func (c *Client) sendPaymentsPaymentIDCapturePost(ctx context.Context, request *PaymentsPaymentIDCapturePostReq, params PaymentsPaymentIDCapturePostParams) (res PaymentsPaymentIDCapturePostRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("POST"), semconv.URLTemplateKey.String("/payments/{payment_id}/capture"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, PaymentsPaymentIDCapturePostOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [3]string pathParts[0] = "/payments/" { // Encode "payment_id" parameter. e := uri.NewPathEncoder(uri.PathEncoderConfig{ Param: "payment_id", Style: uri.PathStyleSimple, Explode: false, }) if err := func() error { if unwrapped := string(params.PaymentID); true { return e.EncodeValue(conv.StringToString(unwrapped)) } return nil }(); err != nil { return res, errors.Wrap(err, "encode path") } encoded, err := e.Result() if err != nil { return res, errors.Wrap(err, "encode path") } pathParts[1] = encoded } pathParts[2] = "/capture" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "POST", u) if err != nil { return res, errors.Wrap(err, "create request") } if err := encodePaymentsPaymentIDCapturePostRequest(request, r); err != nil { return res, errors.Wrap(err, "encode request") } stage = "EncodeHeaderParams" h := uri.NewHeaderEncoder(r.Header) { cfg := uri.HeaderParameterEncodingConfig{ Name: "Idempotence-Key", Explode: false, } if err := h.EncodeParam(cfg, func(e uri.Encoder) error { return e.EncodeValue(conv.StringToString(params.IdempotenceKey)) }); err != nil { return res, errors.Wrap(err, "encode header") } } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, PaymentsPaymentIDCapturePostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, PaymentsPaymentIDCapturePostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodePaymentsPaymentIDCapturePostResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // PaymentsPaymentIDGet invokes 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 (c *Client) PaymentsPaymentIDGet(ctx context.Context, params PaymentsPaymentIDGetParams) (PaymentsPaymentIDGetRes, error) { res, err := c.sendPaymentsPaymentIDGet(ctx, params) return res, err } func (c *Client) sendPaymentsPaymentIDGet(ctx context.Context, params PaymentsPaymentIDGetParams) (res PaymentsPaymentIDGetRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("GET"), semconv.URLTemplateKey.String("/payments/{payment_id}"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, PaymentsPaymentIDGetOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [2]string pathParts[0] = "/payments/" { // Encode "payment_id" parameter. e := uri.NewPathEncoder(uri.PathEncoderConfig{ Param: "payment_id", Style: uri.PathStyleSimple, Explode: false, }) if err := func() error { if unwrapped := string(params.PaymentID); true { return e.EncodeValue(conv.StringToString(unwrapped)) } return nil }(); err != nil { return res, errors.Wrap(err, "encode path") } encoded, err := e.Result() if err != nil { return res, errors.Wrap(err, "encode path") } pathParts[1] = encoded } uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "GET", u) if err != nil { return res, errors.Wrap(err, "create request") } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, PaymentsPaymentIDGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, PaymentsPaymentIDGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodePaymentsPaymentIDGetResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // PaymentsPost invokes 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 (c *Client) PaymentsPost(ctx context.Context, request *PaymentsPostReq, params PaymentsPostParams) (PaymentsPostRes, error) { res, err := c.sendPaymentsPost(ctx, request, params) return res, err } func (c *Client) sendPaymentsPost(ctx context.Context, request *PaymentsPostReq, params PaymentsPostParams) (res PaymentsPostRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("POST"), semconv.URLTemplateKey.String("/payments"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, PaymentsPostOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [1]string pathParts[0] = "/payments" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "POST", u) if err != nil { return res, errors.Wrap(err, "create request") } if err := encodePaymentsPostRequest(request, r); err != nil { return res, errors.Wrap(err, "encode request") } stage = "EncodeHeaderParams" h := uri.NewHeaderEncoder(r.Header) { cfg := uri.HeaderParameterEncodingConfig{ Name: "Idempotence-Key", Explode: false, } if err := h.EncodeParam(cfg, func(e uri.Encoder) error { return e.EncodeValue(conv.StringToString(params.IdempotenceKey)) }); err != nil { return res, errors.Wrap(err, "encode header") } } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, PaymentsPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, PaymentsPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodePaymentsPostResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // PayoutsGet invokes 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 (c *Client) PayoutsGet(ctx context.Context, params PayoutsGetParams) (PayoutsGetRes, error) { res, err := c.sendPayoutsGet(ctx, params) return res, err } func (c *Client) sendPayoutsGet(ctx context.Context, params PayoutsGetParams) (res PayoutsGetRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("GET"), semconv.URLTemplateKey.String("/payouts"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, PayoutsGetOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [1]string pathParts[0] = "/payouts" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeQueryParams" q := uri.NewQueryEncoder() { // Encode "created_at.gte" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.gte", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtGte.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.gt" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.gt", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtGt.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.lte" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.lte", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtLte.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.lt" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.lt", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtLt.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "payout_destination.type" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "payout_destination.type", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.PayoutDestinationType.Get(); ok { return e.EncodeValue(conv.StringToString(string(val))) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "status" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "status", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Status.Get(); ok { return e.EncodeValue(conv.StringToString(string(val))) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "limit" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "limit", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Limit.Get(); ok { return e.EncodeValue(conv.IntToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "cursor" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "cursor", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Cursor.Get(); ok { return e.EncodeValue(conv.StringToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } u.RawQuery = q.Values().Encode() stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "GET", u) if err != nil { return res, errors.Wrap(err, "create request") } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, PayoutsGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, PayoutsGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodePayoutsGetResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // PayoutsPayoutIDGet invokes 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 (c *Client) PayoutsPayoutIDGet(ctx context.Context, params PayoutsPayoutIDGetParams) (PayoutsPayoutIDGetRes, error) { res, err := c.sendPayoutsPayoutIDGet(ctx, params) return res, err } func (c *Client) sendPayoutsPayoutIDGet(ctx context.Context, params PayoutsPayoutIDGetParams) (res PayoutsPayoutIDGetRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("GET"), semconv.URLTemplateKey.String("/payouts/{payout_id}"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, PayoutsPayoutIDGetOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [2]string pathParts[0] = "/payouts/" { // Encode "payout_id" parameter. e := uri.NewPathEncoder(uri.PathEncoderConfig{ Param: "payout_id", Style: uri.PathStyleSimple, Explode: false, }) if err := func() error { if unwrapped := string(params.PayoutID); true { return e.EncodeValue(conv.StringToString(unwrapped)) } return nil }(); err != nil { return res, errors.Wrap(err, "encode path") } encoded, err := e.Result() if err != nil { return res, errors.Wrap(err, "encode path") } pathParts[1] = encoded } uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "GET", u) if err != nil { return res, errors.Wrap(err, "create request") } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, PayoutsPayoutIDGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, PayoutsPayoutIDGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodePayoutsPayoutIDGetResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // PayoutsPost invokes 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 (c *Client) PayoutsPost(ctx context.Context, request *PayoutRequest, params PayoutsPostParams) (PayoutsPostRes, error) { res, err := c.sendPayoutsPost(ctx, request, params) return res, err } func (c *Client) sendPayoutsPost(ctx context.Context, request *PayoutRequest, params PayoutsPostParams) (res PayoutsPostRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("POST"), semconv.URLTemplateKey.String("/payouts"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, PayoutsPostOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [1]string pathParts[0] = "/payouts" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "POST", u) if err != nil { return res, errors.Wrap(err, "create request") } if err := encodePayoutsPostRequest(request, r); err != nil { return res, errors.Wrap(err, "encode request") } stage = "EncodeHeaderParams" h := uri.NewHeaderEncoder(r.Header) { cfg := uri.HeaderParameterEncodingConfig{ Name: "Idempotence-Key", Explode: false, } if err := h.EncodeParam(cfg, func(e uri.Encoder) error { return e.EncodeValue(conv.StringToString(params.IdempotenceKey)) }); err != nil { return res, errors.Wrap(err, "encode header") } } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, PayoutsPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, PayoutsPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodePayoutsPostResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // PayoutsSearchGet invokes 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 (c *Client) PayoutsSearchGet(ctx context.Context, params PayoutsSearchGetParams) (PayoutsSearchGetRes, error) { res, err := c.sendPayoutsSearchGet(ctx, params) return res, err } func (c *Client) sendPayoutsSearchGet(ctx context.Context, params PayoutsSearchGetParams) (res PayoutsSearchGetRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("GET"), semconv.URLTemplateKey.String("/payouts/search"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, PayoutsSearchGetOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [1]string pathParts[0] = "/payouts/search" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeQueryParams" q := uri.NewQueryEncoder() { // Encode "created_at.gte" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.gte", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtGte.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.gt" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.gt", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtGt.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.lte" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.lte", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtLte.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.lt" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.lt", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtLt.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "metadata" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "metadata", Style: uri.QueryStyleDeepObject, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Metadata.Get(); ok { return val.EncodeURI(e) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "limit" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "limit", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Limit.Get(); ok { return e.EncodeValue(conv.IntToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "cursor" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "cursor", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Cursor.Get(); ok { return e.EncodeValue(conv.StringToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } u.RawQuery = q.Values().Encode() stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "GET", u) if err != nil { return res, errors.Wrap(err, "create request") } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, PayoutsSearchGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, PayoutsSearchGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodePayoutsSearchGetResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // PersonalDataPersonalDataIDGet invokes GET /personal_data/{personal_data_id} operation. // // С помощью этого запроса вы можете получить // информацию о текущем статусе объекта персональных // данных по его уникальному идентификатору. // // GET /personal_data/{personal_data_id} func (c *Client) PersonalDataPersonalDataIDGet(ctx context.Context, params PersonalDataPersonalDataIDGetParams) (PersonalDataPersonalDataIDGetRes, error) { res, err := c.sendPersonalDataPersonalDataIDGet(ctx, params) return res, err } func (c *Client) sendPersonalDataPersonalDataIDGet(ctx context.Context, params PersonalDataPersonalDataIDGetParams) (res PersonalDataPersonalDataIDGetRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("GET"), semconv.URLTemplateKey.String("/personal_data/{personal_data_id}"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, PersonalDataPersonalDataIDGetOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [2]string pathParts[0] = "/personal_data/" { // Encode "personal_data_id" parameter. e := uri.NewPathEncoder(uri.PathEncoderConfig{ Param: "personal_data_id", Style: uri.PathStyleSimple, Explode: false, }) if err := func() error { if unwrapped := string(params.PersonalDataID); true { return e.EncodeValue(conv.StringToString(unwrapped)) } return nil }(); err != nil { return res, errors.Wrap(err, "encode path") } encoded, err := e.Result() if err != nil { return res, errors.Wrap(err, "encode path") } pathParts[1] = encoded } uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "GET", u) if err != nil { return res, errors.Wrap(err, "create request") } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, PersonalDataPersonalDataIDGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, PersonalDataPersonalDataIDGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodePersonalDataPersonalDataIDGetResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // PersonalDataPost invokes POST /personal_data operation. // // Используйте этот запрос, чтобы создать в ЮKassa объект // персональных данных: https://yookassa.ru/developers/api#personal_data_object. В // запросе необходимо указать тип данных (с какой целью // они будут использоваться) и передать информацию о // пользователе: фамилию, имя, отчество и другие — в // зависимости от выбранного типа. Идентификатор // созданного объекта персональных данных необходимо // использовать в запросе на создание выплаты: https://yookassa. // ru/developers/api#create_payout. // // POST /personal_data func (c *Client) PersonalDataPost(ctx context.Context, request PersonalDataPostReq, params PersonalDataPostParams) (PersonalDataPostRes, error) { res, err := c.sendPersonalDataPost(ctx, request, params) return res, err } func (c *Client) sendPersonalDataPost(ctx context.Context, request PersonalDataPostReq, params PersonalDataPostParams) (res PersonalDataPostRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("POST"), semconv.URLTemplateKey.String("/personal_data"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, PersonalDataPostOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [1]string pathParts[0] = "/personal_data" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "POST", u) if err != nil { return res, errors.Wrap(err, "create request") } if err := encodePersonalDataPostRequest(request, r); err != nil { return res, errors.Wrap(err, "encode request") } stage = "EncodeHeaderParams" h := uri.NewHeaderEncoder(r.Header) { cfg := uri.HeaderParameterEncodingConfig{ Name: "Idempotence-Key", Explode: false, } if err := h.EncodeParam(cfg, func(e uri.Encoder) error { return e.EncodeValue(conv.StringToString(params.IdempotenceKey)) }); err != nil { return res, errors.Wrap(err, "encode header") } } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, PersonalDataPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, PersonalDataPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodePersonalDataPostResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // ReceiptsGet invokes GET /receipts operation. // // Запрос позволяет получить список чеков, // отфильтрованный по заданным критериям. Можно // запросить чеки по конкретному платежу, чеки по // конкретному возврату или все чеки магазина. // Подробнее о работе со списками: https://yookassa. // ru/developers/using-api/lists. // // GET /receipts func (c *Client) ReceiptsGet(ctx context.Context, params ReceiptsGetParams) (ReceiptsGetRes, error) { res, err := c.sendReceiptsGet(ctx, params) return res, err } func (c *Client) sendReceiptsGet(ctx context.Context, params ReceiptsGetParams) (res ReceiptsGetRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("GET"), semconv.URLTemplateKey.String("/receipts"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, ReceiptsGetOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [1]string pathParts[0] = "/receipts" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeQueryParams" q := uri.NewQueryEncoder() { // Encode "created_at.gte" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.gte", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtGte.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.gt" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.gt", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtGt.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.lte" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.lte", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtLte.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.lt" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.lt", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtLt.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "status" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "status", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Status.Get(); ok { return e.EncodeValue(conv.StringToString(string(val))) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "payment_id" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "payment_id", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.PaymentID.Get(); ok { if unwrapped := string(val); true { return e.EncodeValue(conv.StringToString(unwrapped)) } return nil } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "refund_id" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "refund_id", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.RefundID.Get(); ok { if unwrapped := string(val); true { return e.EncodeValue(conv.StringToString(unwrapped)) } return nil } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "limit" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "limit", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Limit.Get(); ok { return e.EncodeValue(conv.IntToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "cursor" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "cursor", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Cursor.Get(); ok { return e.EncodeValue(conv.StringToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } u.RawQuery = q.Values().Encode() stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "GET", u) if err != nil { return res, errors.Wrap(err, "create request") } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, ReceiptsGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, ReceiptsGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodeReceiptsGetResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // ReceiptsPost invokes 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 (c *Client) ReceiptsPost(ctx context.Context, request PostReceiptData, params ReceiptsPostParams) (ReceiptsPostRes, error) { res, err := c.sendReceiptsPost(ctx, request, params) return res, err } func (c *Client) sendReceiptsPost(ctx context.Context, request PostReceiptData, params ReceiptsPostParams) (res ReceiptsPostRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("POST"), semconv.URLTemplateKey.String("/receipts"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, ReceiptsPostOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [1]string pathParts[0] = "/receipts" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "POST", u) if err != nil { return res, errors.Wrap(err, "create request") } if err := encodeReceiptsPostRequest(request, r); err != nil { return res, errors.Wrap(err, "encode request") } stage = "EncodeHeaderParams" h := uri.NewHeaderEncoder(r.Header) { cfg := uri.HeaderParameterEncodingConfig{ Name: "Idempotence-Key", Explode: false, } if err := h.EncodeParam(cfg, func(e uri.Encoder) error { return e.EncodeValue(conv.StringToString(params.IdempotenceKey)) }); err != nil { return res, errors.Wrap(err, "encode header") } } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, ReceiptsPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, ReceiptsPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodeReceiptsPostResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // ReceiptsReceiptIDGet invokes GET /receipts/{receipt_id} operation. // // Запрос позволяет получить информацию о текущем // состоянии чека по его уникальному идентификатору. // // GET /receipts/{receipt_id} func (c *Client) ReceiptsReceiptIDGet(ctx context.Context, params ReceiptsReceiptIDGetParams) (ReceiptsReceiptIDGetRes, error) { res, err := c.sendReceiptsReceiptIDGet(ctx, params) return res, err } func (c *Client) sendReceiptsReceiptIDGet(ctx context.Context, params ReceiptsReceiptIDGetParams) (res ReceiptsReceiptIDGetRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("GET"), semconv.URLTemplateKey.String("/receipts/{receipt_id}"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, ReceiptsReceiptIDGetOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [2]string pathParts[0] = "/receipts/" { // Encode "receipt_id" parameter. e := uri.NewPathEncoder(uri.PathEncoderConfig{ Param: "receipt_id", Style: uri.PathStyleSimple, Explode: false, }) if err := func() error { if unwrapped := string(params.ReceiptID); true { return e.EncodeValue(conv.StringToString(unwrapped)) } return nil }(); err != nil { return res, errors.Wrap(err, "encode path") } encoded, err := e.Result() if err != nil { return res, errors.Wrap(err, "encode path") } pathParts[1] = encoded } uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "GET", u) if err != nil { return res, errors.Wrap(err, "create request") } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, ReceiptsReceiptIDGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, ReceiptsReceiptIDGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodeReceiptsReceiptIDGetResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // RefundsGet invokes 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 (c *Client) RefundsGet(ctx context.Context, params RefundsGetParams) (RefundsGetRes, error) { res, err := c.sendRefundsGet(ctx, params) return res, err } func (c *Client) sendRefundsGet(ctx context.Context, params RefundsGetParams) (res RefundsGetRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("GET"), semconv.URLTemplateKey.String("/refunds"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, RefundsGetOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [1]string pathParts[0] = "/refunds" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeQueryParams" q := uri.NewQueryEncoder() { // Encode "created_at.gte" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.gte", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtGte.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.gt" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.gt", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtGt.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.lte" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.lte", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtLte.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "created_at.lt" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "created_at.lt", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.CreatedAtLt.Get(); ok { return e.EncodeValue(conv.DateTimeToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "payment_id" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "payment_id", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.PaymentID.Get(); ok { if unwrapped := string(val); true { return e.EncodeValue(conv.StringToString(unwrapped)) } return nil } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "status" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "status", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Status.Get(); ok { return e.EncodeValue(conv.StringToString(string(val))) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "limit" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "limit", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Limit.Get(); ok { return e.EncodeValue(conv.IntToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } { // Encode "cursor" parameter. cfg := uri.QueryParameterEncodingConfig{ Name: "cursor", Style: uri.QueryStyleForm, Explode: true, } if err := q.EncodeParam(cfg, func(e uri.Encoder) error { if val, ok := params.Cursor.Get(); ok { return e.EncodeValue(conv.StringToString(val)) } return nil }); err != nil { return res, errors.Wrap(err, "encode query") } } u.RawQuery = q.Values().Encode() stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "GET", u) if err != nil { return res, errors.Wrap(err, "create request") } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, RefundsGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, RefundsGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodeRefundsGetResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // RefundsPost invokes POST /refunds operation. // // Создает возврат успешного платежа на указанную сумму. // // Платеж можно вернуть только в течение трех лет с // // момента его создания: https://yookassa.ru/developers/api#create_payment. // Комиссия ЮKassa за проведение платежа не возвращается. // // POST /refunds func (c *Client) RefundsPost(ctx context.Context, request *RefundsPostReq, params RefundsPostParams) (RefundsPostRes, error) { res, err := c.sendRefundsPost(ctx, request, params) return res, err } func (c *Client) sendRefundsPost(ctx context.Context, request *RefundsPostReq, params RefundsPostParams) (res RefundsPostRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("POST"), semconv.URLTemplateKey.String("/refunds"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, RefundsPostOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [1]string pathParts[0] = "/refunds" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "POST", u) if err != nil { return res, errors.Wrap(err, "create request") } if err := encodeRefundsPostRequest(request, r); err != nil { return res, errors.Wrap(err, "encode request") } stage = "EncodeHeaderParams" h := uri.NewHeaderEncoder(r.Header) { cfg := uri.HeaderParameterEncodingConfig{ Name: "Idempotence-Key", Explode: false, } if err := h.EncodeParam(cfg, func(e uri.Encoder) error { return e.EncodeValue(conv.StringToString(params.IdempotenceKey)) }); err != nil { return res, errors.Wrap(err, "encode header") } } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, RefundsPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, RefundsPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodeRefundsPostResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // RefundsRefundIDGet invokes GET /refunds/{refund_id} operation. // // Запрос позволяет получить информацию о текущем // состоянии возврата по его уникальному // идентификатору. // // GET /refunds/{refund_id} func (c *Client) RefundsRefundIDGet(ctx context.Context, params RefundsRefundIDGetParams) (RefundsRefundIDGetRes, error) { res, err := c.sendRefundsRefundIDGet(ctx, params) return res, err } func (c *Client) sendRefundsRefundIDGet(ctx context.Context, params RefundsRefundIDGetParams) (res RefundsRefundIDGetRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("GET"), semconv.URLTemplateKey.String("/refunds/{refund_id}"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, RefundsRefundIDGetOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [2]string pathParts[0] = "/refunds/" { // Encode "refund_id" parameter. e := uri.NewPathEncoder(uri.PathEncoderConfig{ Param: "refund_id", Style: uri.PathStyleSimple, Explode: false, }) if err := func() error { return e.EncodeValue(conv.StringToString(params.RefundID)) }(); err != nil { return res, errors.Wrap(err, "encode path") } encoded, err := e.Result() if err != nil { return res, errors.Wrap(err, "encode path") } pathParts[1] = encoded } uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "GET", u) if err != nil { return res, errors.Wrap(err, "create request") } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, RefundsRefundIDGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, RefundsRefundIDGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodeRefundsRefundIDGetResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // SbpBanksGet invokes GET /sbp_banks operation. // // С помощью этого запроса вы можете получить // актуальный список всех участников СБП. Список нужно // вывести получателю выплаты, идентификатор // выбранного участника СБП необходимо использовать в // запросе на создание выплаты: https://yookassa. // ru/developers/api#create_payout. Подробнее о выплатах через СБП: // https://yookassa.ru/developers/payouts/making-payouts/sbp. // // GET /sbp_banks func (c *Client) SbpBanksGet(ctx context.Context) (SbpBanksGetRes, error) { res, err := c.sendSbpBanksGet(ctx) return res, err } func (c *Client) sendSbpBanksGet(ctx context.Context) (res SbpBanksGetRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("GET"), semconv.URLTemplateKey.String("/sbp_banks"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, SbpBanksGetOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [1]string pathParts[0] = "/sbp_banks" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "GET", u) if err != nil { return res, errors.Wrap(err, "create request") } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, SbpBanksGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, SbpBanksGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodeSbpBanksGetResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // WebhooksGet invokes GET /webhooks operation. // // Запрос позволяет узнать, какие webhook есть для // переданного OAuth-токена. // // GET /webhooks func (c *Client) WebhooksGet(ctx context.Context) (WebhooksGetRes, error) { res, err := c.sendWebhooksGet(ctx) return res, err } func (c *Client) sendWebhooksGet(ctx context.Context) (res WebhooksGetRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("GET"), semconv.URLTemplateKey.String("/webhooks"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, WebhooksGetOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [1]string pathParts[0] = "/webhooks" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "GET", u) if err != nil { return res, errors.Wrap(err, "create request") } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, WebhooksGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, WebhooksGetOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodeWebhooksGetResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // WebhooksPost invokes POST /webhooks operation. // // Запрос позволяет подписаться на уведомления о // событиях: https://yookassa.ru/developers/using-api/webhooks#events (например, // переход платежа в статус succeeded). C помощью webhook можно // подписаться только на события платежей и возвратов. // Если вы хотите получать уведомления о нескольких // событиях, вам нужно для каждого из них создать свой // webhook. Для каждого OAuth-токена нужно создавать свой // набор webhook. // // POST /webhooks func (c *Client) WebhooksPost(ctx context.Context, request *WebhooksPostReq, params WebhooksPostParams) (WebhooksPostRes, error) { res, err := c.sendWebhooksPost(ctx, request, params) return res, err } func (c *Client) sendWebhooksPost(ctx context.Context, request *WebhooksPostReq, params WebhooksPostParams) (res WebhooksPostRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("POST"), semconv.URLTemplateKey.String("/webhooks"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, WebhooksPostOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [1]string pathParts[0] = "/webhooks" uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "POST", u) if err != nil { return res, errors.Wrap(err, "create request") } if err := encodeWebhooksPostRequest(request, r); err != nil { return res, errors.Wrap(err, "encode request") } stage = "EncodeHeaderParams" h := uri.NewHeaderEncoder(r.Header) { cfg := uri.HeaderParameterEncodingConfig{ Name: "Idempotence-Key", Explode: false, } if err := h.EncodeParam(cfg, func(e uri.Encoder) error { return e.EncodeValue(conv.StringToString(params.IdempotenceKey)) }); err != nil { return res, errors.Wrap(err, "encode header") } } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, WebhooksPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, WebhooksPostOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodeWebhooksPostResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil } // WebhooksWebhookIDDelete invokes DELETE /webhooks/{webhook_id} operation. // // Запрос позволяет отписаться от уведомлений о событии // для переданного OAuth-токена. Чтобы удалить webhook, вам // нужно передать в запросе его идентификатор. // // DELETE /webhooks/{webhook_id} func (c *Client) WebhooksWebhookIDDelete(ctx context.Context, params WebhooksWebhookIDDeleteParams) (WebhooksWebhookIDDeleteRes, error) { res, err := c.sendWebhooksWebhookIDDelete(ctx, params) return res, err } func (c *Client) sendWebhooksWebhookIDDelete(ctx context.Context, params WebhooksWebhookIDDeleteParams) (res WebhooksWebhookIDDeleteRes, err error) { otelAttrs := []attribute.KeyValue{ semconv.HTTPRequestMethodKey.String("DELETE"), semconv.URLTemplateKey.String("/webhooks/{webhook_id}"), } otelAttrs = append(otelAttrs, c.cfg.Attributes...) // Run stopwatch. startTime := time.Now() defer func() { // Use floating point division here for higher precision (instead of Millisecond method). elapsedDuration := time.Since(startTime) c.duration.Record(ctx, float64(elapsedDuration)/float64(time.Millisecond), metric.WithAttributes(otelAttrs...)) }() // Increment request counter. c.requests.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) // Start a span for this request. ctx, span := c.cfg.Tracer.Start(ctx, WebhooksWebhookIDDeleteOperation, trace.WithAttributes(otelAttrs...), clientSpanKind, ) // Track stage for error reporting. var stage string defer func() { if err != nil { span.RecordError(err) span.SetStatus(codes.Error, stage) c.errors.Add(ctx, 1, metric.WithAttributes(otelAttrs...)) } span.End() }() stage = "BuildURL" u := uri.Clone(c.requestURL(ctx)) var pathParts [2]string pathParts[0] = "/webhooks/" { // Encode "webhook_id" parameter. e := uri.NewPathEncoder(uri.PathEncoderConfig{ Param: "webhook_id", Style: uri.PathStyleSimple, Explode: false, }) if err := func() error { return e.EncodeValue(conv.StringToString(params.WebhookID)) }(); err != nil { return res, errors.Wrap(err, "encode path") } encoded, err := e.Result() if err != nil { return res, errors.Wrap(err, "encode path") } pathParts[1] = encoded } uri.AddPathParts(u, pathParts[:]...) stage = "EncodeRequest" r, err := ht.NewRequest(ctx, "DELETE", u) if err != nil { return res, errors.Wrap(err, "create request") } { type bitset = [1]uint8 var satisfied bitset { stage = "Security:BasicAuth" switch err := c.securityBasicAuth(ctx, WebhooksWebhookIDDeleteOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 0 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"BasicAuth\"") } } { stage = "Security:OAuth2" switch err := c.securityOAuth2(ctx, WebhooksWebhookIDDeleteOperation, r); { case err == nil: // if NO error satisfied[0] |= 1 << 1 case errors.Is(err, ogenerrors.ErrSkipClientSecurity): // Skip this security. default: return res, errors.Wrap(err, "security \"OAuth2\"") } } 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 { return res, ogenerrors.ErrSecurityRequirementIsNotSatisfied } } stage = "SendRequest" resp, err := c.cfg.Client.Do(r) if err != nil { return res, errors.Wrap(err, "do request") } body := resp.Body defer body.Close() stage = "DecodeResponse" result, err := decodeWebhooksWebhookIDDeleteResponse(resp) if err != nil { return res, errors.Wrap(err, "decode response") } return result, nil }