Try to use generated yookassa client (unsuccessful)

This commit is contained in:
2026-03-17 16:37:29 +03:00
parent 35f6dc6ca0
commit 2c19b9c29b
14 changed files with 867 additions and 698 deletions

View File

@@ -9,6 +9,7 @@ import (
"net/http" "net/http"
"regexp" "regexp"
"github.com/google/uuid"
"go.uber.org/fx" "go.uber.org/fx"
"payouts/internal/config" "payouts/internal/config"
@@ -124,13 +125,26 @@ func (p *payoutHandler) PayoutCreate(w http.ResponseWriter, r *http.Request) {
return return
} }
idempotenceKey := uuid.New().String()
payoutModel := &orm.Payout{
User: *userSession,
IdempotenceKey: idempotenceKey,
Type: payoutReq.PayoutType.String(),
Amount: payoutReq.Amount,
Status: orm.StatusCreated,
}
err = p.dbService.CreatePayout(payoutModel, database.WithContext(r.Context()))
slog.Debug(fmt.Sprintf("Received create payload request: %v from user %v", payoutReq, userSession)) slog.Debug(fmt.Sprintf("Received create payload request: %v from user %v", payoutReq, userSession))
err = p.yooKassa.CreatePayout(payoutReq, userSession) payoutResp, err := p.yooKassa.CreatePayout(payoutReq, userSession, idempotenceKey, yookassa.WithContext(r.Context()))
if err != nil { if err != nil {
slog.Error("Failed to create payout request", slog.String("error", err.Error())) slog.Error("Failed to create payout request", slog.String("error", err.Error()))
errResponse("failed to create payout request", err, http.StatusBadRequest) errResponse("failed to create payout request", err, http.StatusBadRequest)
return return
} }
encoder := json.NewEncoder(w)
encoder.Encode(payoutResp)
} }
// PaymentCallback implements [Handler]. // PaymentCallback implements [Handler].

View File

@@ -82,7 +82,7 @@ func (u *userHandler) UserRegister(w http.ResponseWriter, r *http.Request) {
copier.Copy(&ormUser, user) copier.Copy(&ormUser, user)
// todo: add data validation // todo: add data validation
err = u.dbService.CreateUser(ormUser, database.WithContext(r.Context())) err = u.dbService.CreateUser(&ormUser, database.WithContext(r.Context()))
if err != nil { if err != nil {
slog.Error("Failed to create user", slog.String("error", err.Error())) slog.Error("Failed to create user", slog.String("error", err.Error()))
errResponse("failed to create user", err, http.StatusBadRequest) errResponse("failed to create user", err, http.StatusBadRequest)
@@ -114,7 +114,7 @@ func (u *userHandler) UserLogin(w http.ResponseWriter, r *http.Request) {
return return
} }
ormUser, err := u.dbService.GetUser(orm.User{Phone: user.Phone}, database.WithContext(r.Context())) ormUser, err := u.dbService.GetUser(&orm.User{Phone: user.Phone}, database.WithContext(r.Context()))
if err != nil { if err != nil {
errResponse("invalid credentials", nil, http.StatusUnauthorized) errResponse("invalid credentials", nil, http.StatusUnauthorized)
return return

View File

@@ -46,6 +46,7 @@ type PayoutReq struct {
} }
type PayoutResp struct { type PayoutResp struct {
Success bool `json:"success"` Result string `json:"result"`
Reason string `json:"reason,omitempty"` PayoutID string `json:"payout_id,omitempty"`
ErrorReason string `json:"error_reason,omitempty"`
} }

View File

@@ -73,16 +73,33 @@ func (d *dbService) getParams(options ...Optional) *params {
} }
// AddUser implements [Service]. // AddUser implements [Service].
func (d *dbService) CreateUser(userModel orm.User, opts ...Optional) error { func (d *dbService) CreateUser(userModel *orm.User, opts ...Optional) error {
p := d.getParams(opts...) p := d.getParams(opts...)
return gorm.G[orm.User](d.db).Create(p.ctx, &userModel) return gorm.G[orm.User](d.db).Create(p.ctx, userModel)
} }
// GetUser implements [Service]. // GetUser implements [Service].
func (d *dbService) GetUser(userModel orm.User, opts ...Optional) (orm.User, error) { func (d *dbService) GetUser(userModel *orm.User, opts ...Optional) (orm.User, error) {
p := d.getParams(opts...)
return gorm.G[orm.User](d.db).Where(userModel).First(p.ctx)
}
// GetPayout implements [Service].
func (d *dbService) GetPayout(payoutModel *orm.Payout, opts ...Optional) (orm.Payout, error) {
p := d.getParams(opts...)
return gorm.G[orm.Payout](d.db).Where(payoutModel).First(p.ctx)
}
// CreatePayout implements [Service].
func (d *dbService) CreatePayout(payoutModel *orm.Payout, opts ...Optional) error {
p := d.getParams(opts...) p := d.getParams(opts...)
userResp, err := gorm.G[orm.User](d.db).Where(&userModel).First(p.ctx) return gorm.G[orm.Payout](d.db).Create(p.ctx, payoutModel)
return userResp, err }
// UpdatePayout implements [Service].
func (d *dbService) UpdatePayout(payoutModel *orm.Payout, opts ...Optional) error {
// p := d.getParams(opts...)
panic("unimplemented")
} }

View File

@@ -25,8 +25,11 @@ func WithContext(ctx context.Context) Optional {
} }
type Service interface { type Service interface {
CreateUser(user orm.User, opts ...Optional) error CreateUser(user *orm.User, opts ...Optional) error
GetUser(user orm.User, opts ...Optional) (orm.User, error) GetUser(user *orm.User, opts ...Optional) (orm.User, error)
GetPayout(payoutModel *orm.Payout, opts ...Optional) (orm.Payout, error)
CreatePayout(payoutModel *orm.Payout, opts ...Optional) error
UpdatePayout(payoutModel *orm.Payout, opts ...Optional) error
} }
// Params represents the module input params // Params represents the module input params

View File

@@ -1,6 +1,60 @@
package orm package orm
import "gorm.io/gorm" import (
"fmt"
"strings"
"gorm.io/gorm"
)
type PayoutStatus int64
const (
StatusCreated PayoutStatus = iota
StatusCanceled
StatusPending
StatusSucceeded
StatusFailed
)
func (r PayoutStatus) String() string {
switch r {
case StatusCreated:
return "created"
case StatusCanceled:
return "canceled"
case StatusPending:
return "pending"
case StatusSucceeded:
return "succeeded"
case StatusFailed:
return "failed"
}
return "unknown"
}
func (r PayoutStatus) MarshalText() (text []byte, err error) {
return []byte(r.String()), nil
}
func (r *PayoutStatus) UnmarshalText(text []byte) (err error) {
s := strings.ToLower(string(text))
switch s {
case "canceled":
*r = StatusCanceled
case "created":
*r = StatusCreated
case "pending":
*r = StatusPending
case "succeeded":
*r = StatusSucceeded
case "failed":
*r = StatusFailed
default:
err = fmt.Errorf("invalid payment type: %s", s)
}
return err
}
type Payout struct { type Payout struct {
gorm.Model gorm.Model
@@ -8,12 +62,13 @@ type Payout struct {
UserID uint UserID uint
User User User User
Description string Description string
PayoutID string IdempotenceKey string
Type string PayoutID string
AccountNumber string Type string
Amount float32 AccountNumber string
Currency string Amount float32
Status string Currency string
Test bool Status PayoutStatus
Test bool
} }

View File

@@ -1535,6 +1535,115 @@ func (s *BadRequestType) UnmarshalJSON(data []byte) error {
return s.Decode(d) return s.Decode(d)
} }
// Encode implements json.Marshaler.
func (s *BankCard) Encode(e *jx.Encoder) {
e.ObjStart()
s.encodeFields(e)
e.ObjEnd()
}
// encodeFields encodes fields.
func (s *BankCard) encodeFields(e *jx.Encoder) {
{
e.FieldStart("type")
s.Type.Encode(e)
}
{
e.FieldStart("card")
s.Card.Encode(e)
}
}
var jsonFieldsNameOfBankCard = [2]string{
0: "type",
1: "card",
}
// Decode decodes BankCard from json.
func (s *BankCard) Decode(d *jx.Decoder) error {
if s == nil {
return errors.New("invalid: unable to decode BankCard to nil")
}
var requiredBitSet [1]uint8
if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error {
switch string(k) {
case "type":
requiredBitSet[0] |= 1 << 0
if err := func() error {
if err := s.Type.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"type\"")
}
case "card":
requiredBitSet[0] |= 1 << 1
if err := func() error {
if err := s.Card.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"card\"")
}
default:
return d.Skip()
}
return nil
}); err != nil {
return errors.Wrap(err, "decode BankCard")
}
// Validate required fields.
var failures []validate.FieldError
for i, mask := range [1]uint8{
0b00000011,
} {
if result := (requiredBitSet[i] & mask) ^ mask; result != 0 {
// Mask only required fields and check equality to mask using XOR.
//
// If XOR result is not zero, result is not equal to expected, so some fields are missed.
// Bits of fields which would be set are actually bits of missed fields.
missed := bits.OnesCount8(result)
for bitN := 0; bitN < missed; bitN++ {
bitIdx := bits.TrailingZeros8(result)
fieldIdx := i*8 + bitIdx
var name string
if fieldIdx < len(jsonFieldsNameOfBankCard) {
name = jsonFieldsNameOfBankCard[fieldIdx]
} else {
name = strconv.Itoa(fieldIdx)
}
failures = append(failures, validate.FieldError{
Name: name,
Error: validate.ErrFieldRequired,
})
// Reset bit.
result &^= 1 << bitIdx
}
}
}
if len(failures) > 0 {
return &validate.Error{Fields: failures}
}
return nil
}
// MarshalJSON implements stdjson.Marshaler.
func (s *BankCard) MarshalJSON() ([]byte, error) {
e := jx.Encoder{}
s.Encode(&e)
return e.Bytes(), nil
}
// UnmarshalJSON implements stdjson.Unmarshaler.
func (s *BankCard) UnmarshalJSON(data []byte) error {
d := jx.DecodeBytes(data)
return s.Decode(d)
}
// Encode implements json.Marshaler. // Encode implements json.Marshaler.
func (s *BankCardData) Encode(e *jx.Encoder) { func (s *BankCardData) Encode(e *jx.Encoder) {
e.ObjStart() e.ObjStart()
@@ -28019,9 +28128,15 @@ func (s *PayoutRequest) encodeFields(e *jx.Encoder) {
s.Metadata.Encode(e) s.Metadata.Encode(e)
} }
} }
{
if s.Test.Set {
e.FieldStart("test")
s.Test.Encode(e)
}
}
} }
var jsonFieldsNameOfPayoutRequest = [8]string{ var jsonFieldsNameOfPayoutRequest = [9]string{
0: "amount", 0: "amount",
1: "payout_destination_data", 1: "payout_destination_data",
2: "payout_token", 2: "payout_token",
@@ -28030,6 +28145,7 @@ var jsonFieldsNameOfPayoutRequest = [8]string{
5: "deal", 5: "deal",
6: "personal_data", 6: "personal_data",
7: "metadata", 7: "metadata",
8: "test",
} }
// Decode decodes PayoutRequest from json. // Decode decodes PayoutRequest from json.
@@ -28037,7 +28153,7 @@ func (s *PayoutRequest) Decode(d *jx.Decoder) error {
if s == nil { if s == nil {
return errors.New("invalid: unable to decode PayoutRequest to nil") return errors.New("invalid: unable to decode PayoutRequest to nil")
} }
var requiredBitSet [1]uint8 var requiredBitSet [2]uint8
if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error { if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error {
switch string(k) { switch string(k) {
@@ -28128,6 +28244,16 @@ func (s *PayoutRequest) Decode(d *jx.Decoder) error {
}(); err != nil { }(); err != nil {
return errors.Wrap(err, "decode field \"metadata\"") return errors.Wrap(err, "decode field \"metadata\"")
} }
case "test":
if err := func() error {
s.Test.Reset()
if err := s.Test.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"test\"")
}
default: default:
return d.Skip() return d.Skip()
} }
@@ -28137,8 +28263,9 @@ func (s *PayoutRequest) Decode(d *jx.Decoder) error {
} }
// Validate required fields. // Validate required fields.
var failures []validate.FieldError var failures []validate.FieldError
for i, mask := range [1]uint8{ for i, mask := range [2]uint8{
0b00000001, 0b00000001,
0b00000000,
} { } {
if result := (requiredBitSet[i] & mask) ^ mask; result != 0 { if result := (requiredBitSet[i] & mask) ^ mask; result != 0 {
// Mask only required fields and check equality to mask using XOR. // Mask only required fields and check equality to mask using XOR.
@@ -28304,31 +28431,31 @@ func (s PayoutRequestPayoutDestinationData) Encode(e *jx.Encoder) {
func (s PayoutRequestPayoutDestinationData) encodeFields(e *jx.Encoder) { func (s PayoutRequestPayoutDestinationData) encodeFields(e *jx.Encoder) {
switch s.Type { switch s.Type {
case PayoutToYooMoneyDestinationDataPayoutRequestPayoutDestinationData: case YooMoneyPayoutRequestPayoutDestinationData:
e.FieldStart("type") e.FieldStart("type")
e.Str("PayoutToYooMoneyDestinationData") e.Str("yoo_money")
{ {
s := s.PayoutToYooMoneyDestinationData s := s.YooMoney
{ {
e.FieldStart("account_number") e.FieldStart("account_number")
e.Str(s.AccountNumber) e.Str(s.AccountNumber)
} }
} }
case PayoutToBankCardDestinationDataPayoutRequestPayoutDestinationData: case BankCardPayoutRequestPayoutDestinationData:
e.FieldStart("type") e.FieldStart("type")
e.Str("PayoutToBankCardDestinationData") e.Str("bank_card")
{ {
s := s.PayoutToBankCardDestinationData s := s.BankCard
{ {
e.FieldStart("card") e.FieldStart("card")
s.Card.Encode(e) s.Card.Encode(e)
} }
} }
case PayoutToSbpDestinationDataPayoutRequestPayoutDestinationData: case SbpPayoutRequestPayoutDestinationData:
e.FieldStart("type") e.FieldStart("type")
e.Str("PayoutToSbpDestinationData") e.Str("sbp")
{ {
s := s.PayoutToSbpDestinationData s := s.Sbp
{ {
e.FieldStart("phone") e.FieldStart("phone")
e.Str(s.Phone) e.Str(s.Phone)
@@ -28364,14 +28491,14 @@ func (s *PayoutRequestPayoutDestinationData) Decode(d *jx.Decoder) error {
return err return err
} }
switch typ { switch typ {
case "PayoutToYooMoneyDestinationData": case "yoo_money":
s.Type = PayoutToYooMoneyDestinationDataPayoutRequestPayoutDestinationData s.Type = YooMoneyPayoutRequestPayoutDestinationData
found = true found = true
case "PayoutToBankCardDestinationData": case "bank_card":
s.Type = PayoutToBankCardDestinationDataPayoutRequestPayoutDestinationData s.Type = BankCardPayoutRequestPayoutDestinationData
found = true found = true
case "PayoutToSbpDestinationData": case "sbp":
s.Type = PayoutToSbpDestinationDataPayoutRequestPayoutDestinationData s.Type = SbpPayoutRequestPayoutDestinationData
found = true found = true
default: default:
return errors.Errorf("unknown type %s", typ) return errors.Errorf("unknown type %s", typ)
@@ -28387,16 +28514,16 @@ func (s *PayoutRequestPayoutDestinationData) Decode(d *jx.Decoder) error {
return errors.New("unable to detect sum type variant") return errors.New("unable to detect sum type variant")
} }
switch s.Type { switch s.Type {
case PayoutToYooMoneyDestinationDataPayoutRequestPayoutDestinationData: case YooMoneyPayoutRequestPayoutDestinationData:
if err := s.PayoutToYooMoneyDestinationData.Decode(d); err != nil { if err := s.YooMoney.Decode(d); err != nil {
return err return err
} }
case PayoutToBankCardDestinationDataPayoutRequestPayoutDestinationData: case BankCardPayoutRequestPayoutDestinationData:
if err := s.PayoutToBankCardDestinationData.Decode(d); err != nil { if err := s.BankCard.Decode(d); err != nil {
return err return err
} }
case PayoutToSbpDestinationDataPayoutRequestPayoutDestinationData: case SbpPayoutRequestPayoutDestinationData:
if err := s.PayoutToSbpDestinationData.Decode(d); err != nil { if err := s.Sbp.Decode(d); err != nil {
return err return err
} }
default: default:
@@ -28729,115 +28856,6 @@ func (s *PayoutStatus) UnmarshalJSON(data []byte) error {
return s.Decode(d) return s.Decode(d)
} }
// Encode implements json.Marshaler.
func (s *PayoutToBankCardDestinationData) Encode(e *jx.Encoder) {
e.ObjStart()
s.encodeFields(e)
e.ObjEnd()
}
// encodeFields encodes fields.
func (s *PayoutToBankCardDestinationData) encodeFields(e *jx.Encoder) {
{
e.FieldStart("type")
s.Type.Encode(e)
}
{
e.FieldStart("card")
s.Card.Encode(e)
}
}
var jsonFieldsNameOfPayoutToBankCardDestinationData = [2]string{
0: "type",
1: "card",
}
// Decode decodes PayoutToBankCardDestinationData from json.
func (s *PayoutToBankCardDestinationData) Decode(d *jx.Decoder) error {
if s == nil {
return errors.New("invalid: unable to decode PayoutToBankCardDestinationData to nil")
}
var requiredBitSet [1]uint8
if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error {
switch string(k) {
case "type":
requiredBitSet[0] |= 1 << 0
if err := func() error {
if err := s.Type.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"type\"")
}
case "card":
requiredBitSet[0] |= 1 << 1
if err := func() error {
if err := s.Card.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"card\"")
}
default:
return d.Skip()
}
return nil
}); err != nil {
return errors.Wrap(err, "decode PayoutToBankCardDestinationData")
}
// Validate required fields.
var failures []validate.FieldError
for i, mask := range [1]uint8{
0b00000011,
} {
if result := (requiredBitSet[i] & mask) ^ mask; result != 0 {
// Mask only required fields and check equality to mask using XOR.
//
// If XOR result is not zero, result is not equal to expected, so some fields are missed.
// Bits of fields which would be set are actually bits of missed fields.
missed := bits.OnesCount8(result)
for bitN := 0; bitN < missed; bitN++ {
bitIdx := bits.TrailingZeros8(result)
fieldIdx := i*8 + bitIdx
var name string
if fieldIdx < len(jsonFieldsNameOfPayoutToBankCardDestinationData) {
name = jsonFieldsNameOfPayoutToBankCardDestinationData[fieldIdx]
} else {
name = strconv.Itoa(fieldIdx)
}
failures = append(failures, validate.FieldError{
Name: name,
Error: validate.ErrFieldRequired,
})
// Reset bit.
result &^= 1 << bitIdx
}
}
}
if len(failures) > 0 {
return &validate.Error{Fields: failures}
}
return nil
}
// MarshalJSON implements stdjson.Marshaler.
func (s *PayoutToBankCardDestinationData) MarshalJSON() ([]byte, error) {
e := jx.Encoder{}
s.Encode(&e)
return e.Bytes(), nil
}
// UnmarshalJSON implements stdjson.Unmarshaler.
func (s *PayoutToBankCardDestinationData) UnmarshalJSON(data []byte) error {
d := jx.DecodeBytes(data)
return s.Decode(d)
}
// Encode implements json.Marshaler. // Encode implements json.Marshaler.
func (s *PayoutToCardDestination) Encode(e *jx.Encoder) { func (s *PayoutToCardDestination) Encode(e *jx.Encoder) {
e.ObjStart() e.ObjStart()
@@ -29094,134 +29112,6 @@ func (s *PayoutToSbpDestination) UnmarshalJSON(data []byte) error {
return s.Decode(d) return s.Decode(d)
} }
// Encode implements json.Marshaler.
func (s *PayoutToSbpDestinationData) Encode(e *jx.Encoder) {
e.ObjStart()
s.encodeFields(e)
e.ObjEnd()
}
// encodeFields encodes fields.
func (s *PayoutToSbpDestinationData) encodeFields(e *jx.Encoder) {
{
e.FieldStart("type")
s.Type.Encode(e)
}
{
e.FieldStart("phone")
e.Str(s.Phone)
}
{
e.FieldStart("bank_id")
e.Str(s.BankID)
}
}
var jsonFieldsNameOfPayoutToSbpDestinationData = [3]string{
0: "type",
1: "phone",
2: "bank_id",
}
// Decode decodes PayoutToSbpDestinationData from json.
func (s *PayoutToSbpDestinationData) Decode(d *jx.Decoder) error {
if s == nil {
return errors.New("invalid: unable to decode PayoutToSbpDestinationData to nil")
}
var requiredBitSet [1]uint8
if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error {
switch string(k) {
case "type":
requiredBitSet[0] |= 1 << 0
if err := func() error {
if err := s.Type.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"type\"")
}
case "phone":
requiredBitSet[0] |= 1 << 1
if err := func() error {
v, err := d.Str()
s.Phone = string(v)
if err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"phone\"")
}
case "bank_id":
requiredBitSet[0] |= 1 << 2
if err := func() error {
v, err := d.Str()
s.BankID = string(v)
if err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"bank_id\"")
}
default:
return d.Skip()
}
return nil
}); err != nil {
return errors.Wrap(err, "decode PayoutToSbpDestinationData")
}
// Validate required fields.
var failures []validate.FieldError
for i, mask := range [1]uint8{
0b00000111,
} {
if result := (requiredBitSet[i] & mask) ^ mask; result != 0 {
// Mask only required fields and check equality to mask using XOR.
//
// If XOR result is not zero, result is not equal to expected, so some fields are missed.
// Bits of fields which would be set are actually bits of missed fields.
missed := bits.OnesCount8(result)
for bitN := 0; bitN < missed; bitN++ {
bitIdx := bits.TrailingZeros8(result)
fieldIdx := i*8 + bitIdx
var name string
if fieldIdx < len(jsonFieldsNameOfPayoutToSbpDestinationData) {
name = jsonFieldsNameOfPayoutToSbpDestinationData[fieldIdx]
} else {
name = strconv.Itoa(fieldIdx)
}
failures = append(failures, validate.FieldError{
Name: name,
Error: validate.ErrFieldRequired,
})
// Reset bit.
result &^= 1 << bitIdx
}
}
}
if len(failures) > 0 {
return &validate.Error{Fields: failures}
}
return nil
}
// MarshalJSON implements stdjson.Marshaler.
func (s *PayoutToSbpDestinationData) MarshalJSON() ([]byte, error) {
e := jx.Encoder{}
s.Encode(&e)
return e.Bytes(), nil
}
// UnmarshalJSON implements stdjson.Unmarshaler.
func (s *PayoutToSbpDestinationData) UnmarshalJSON(data []byte) error {
d := jx.DecodeBytes(data)
return s.Decode(d)
}
// Encode implements json.Marshaler. // Encode implements json.Marshaler.
func (s *PayoutToYooMoneyDestination) Encode(e *jx.Encoder) { func (s *PayoutToYooMoneyDestination) Encode(e *jx.Encoder) {
e.ObjStart() e.ObjStart()
@@ -29331,117 +29221,6 @@ func (s *PayoutToYooMoneyDestination) UnmarshalJSON(data []byte) error {
return s.Decode(d) return s.Decode(d)
} }
// Encode implements json.Marshaler.
func (s *PayoutToYooMoneyDestinationData) Encode(e *jx.Encoder) {
e.ObjStart()
s.encodeFields(e)
e.ObjEnd()
}
// encodeFields encodes fields.
func (s *PayoutToYooMoneyDestinationData) encodeFields(e *jx.Encoder) {
{
e.FieldStart("type")
s.Type.Encode(e)
}
{
e.FieldStart("account_number")
e.Str(s.AccountNumber)
}
}
var jsonFieldsNameOfPayoutToYooMoneyDestinationData = [2]string{
0: "type",
1: "account_number",
}
// Decode decodes PayoutToYooMoneyDestinationData from json.
func (s *PayoutToYooMoneyDestinationData) Decode(d *jx.Decoder) error {
if s == nil {
return errors.New("invalid: unable to decode PayoutToYooMoneyDestinationData to nil")
}
var requiredBitSet [1]uint8
if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error {
switch string(k) {
case "type":
requiredBitSet[0] |= 1 << 0
if err := func() error {
if err := s.Type.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"type\"")
}
case "account_number":
requiredBitSet[0] |= 1 << 1
if err := func() error {
v, err := d.Str()
s.AccountNumber = string(v)
if err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"account_number\"")
}
default:
return d.Skip()
}
return nil
}); err != nil {
return errors.Wrap(err, "decode PayoutToYooMoneyDestinationData")
}
// Validate required fields.
var failures []validate.FieldError
for i, mask := range [1]uint8{
0b00000011,
} {
if result := (requiredBitSet[i] & mask) ^ mask; result != 0 {
// Mask only required fields and check equality to mask using XOR.
//
// If XOR result is not zero, result is not equal to expected, so some fields are missed.
// Bits of fields which would be set are actually bits of missed fields.
missed := bits.OnesCount8(result)
for bitN := 0; bitN < missed; bitN++ {
bitIdx := bits.TrailingZeros8(result)
fieldIdx := i*8 + bitIdx
var name string
if fieldIdx < len(jsonFieldsNameOfPayoutToYooMoneyDestinationData) {
name = jsonFieldsNameOfPayoutToYooMoneyDestinationData[fieldIdx]
} else {
name = strconv.Itoa(fieldIdx)
}
failures = append(failures, validate.FieldError{
Name: name,
Error: validate.ErrFieldRequired,
})
// Reset bit.
result &^= 1 << bitIdx
}
}
}
if len(failures) > 0 {
return &validate.Error{Fields: failures}
}
return nil
}
// MarshalJSON implements stdjson.Marshaler.
func (s *PayoutToYooMoneyDestinationData) MarshalJSON() ([]byte, error) {
e := jx.Encoder{}
s.Encode(&e)
return e.Bytes(), nil
}
// UnmarshalJSON implements stdjson.Unmarshaler.
func (s *PayoutToYooMoneyDestinationData) UnmarshalJSON(data []byte) error {
d := jx.DecodeBytes(data)
return s.Decode(d)
}
// Encode encodes PayoutsGetInternalServerError as json. // Encode encodes PayoutsGetInternalServerError as json.
func (s *PayoutsGetInternalServerError) Encode(e *jx.Encoder) { func (s *PayoutsGetInternalServerError) Encode(e *jx.Encoder) {
unwrapped := (*TooManyRequests)(s) unwrapped := (*TooManyRequests)(s)
@@ -37969,6 +37748,134 @@ func (s *SavePaymentMethodType) UnmarshalJSON(data []byte) error {
return s.Decode(d) return s.Decode(d)
} }
// Encode implements json.Marshaler.
func (s *Sbp) Encode(e *jx.Encoder) {
e.ObjStart()
s.encodeFields(e)
e.ObjEnd()
}
// encodeFields encodes fields.
func (s *Sbp) encodeFields(e *jx.Encoder) {
{
e.FieldStart("type")
s.Type.Encode(e)
}
{
e.FieldStart("phone")
e.Str(s.Phone)
}
{
e.FieldStart("bank_id")
e.Str(s.BankID)
}
}
var jsonFieldsNameOfSbp = [3]string{
0: "type",
1: "phone",
2: "bank_id",
}
// Decode decodes Sbp from json.
func (s *Sbp) Decode(d *jx.Decoder) error {
if s == nil {
return errors.New("invalid: unable to decode Sbp to nil")
}
var requiredBitSet [1]uint8
if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error {
switch string(k) {
case "type":
requiredBitSet[0] |= 1 << 0
if err := func() error {
if err := s.Type.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"type\"")
}
case "phone":
requiredBitSet[0] |= 1 << 1
if err := func() error {
v, err := d.Str()
s.Phone = string(v)
if err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"phone\"")
}
case "bank_id":
requiredBitSet[0] |= 1 << 2
if err := func() error {
v, err := d.Str()
s.BankID = string(v)
if err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"bank_id\"")
}
default:
return d.Skip()
}
return nil
}); err != nil {
return errors.Wrap(err, "decode Sbp")
}
// Validate required fields.
var failures []validate.FieldError
for i, mask := range [1]uint8{
0b00000111,
} {
if result := (requiredBitSet[i] & mask) ^ mask; result != 0 {
// Mask only required fields and check equality to mask using XOR.
//
// If XOR result is not zero, result is not equal to expected, so some fields are missed.
// Bits of fields which would be set are actually bits of missed fields.
missed := bits.OnesCount8(result)
for bitN := 0; bitN < missed; bitN++ {
bitIdx := bits.TrailingZeros8(result)
fieldIdx := i*8 + bitIdx
var name string
if fieldIdx < len(jsonFieldsNameOfSbp) {
name = jsonFieldsNameOfSbp[fieldIdx]
} else {
name = strconv.Itoa(fieldIdx)
}
failures = append(failures, validate.FieldError{
Name: name,
Error: validate.ErrFieldRequired,
})
// Reset bit.
result &^= 1 << bitIdx
}
}
}
if len(failures) > 0 {
return &validate.Error{Fields: failures}
}
return nil
}
// MarshalJSON implements stdjson.Marshaler.
func (s *Sbp) MarshalJSON() ([]byte, error) {
e := jx.Encoder{}
s.Encode(&e)
return e.Bytes(), nil
}
// UnmarshalJSON implements stdjson.Unmarshaler.
func (s *Sbp) UnmarshalJSON(data []byte) error {
d := jx.DecodeBytes(data)
return s.Decode(d)
}
// Encode encodes SbpBankBic as json. // Encode encodes SbpBankBic as json.
func (s SbpBankBic) Encode(e *jx.Encoder) { func (s SbpBankBic) Encode(e *jx.Encoder) {
unwrapped := string(s) unwrapped := string(s)
@@ -41949,6 +41856,117 @@ func (s *WebhooksWebhookIDDeleteOK) UnmarshalJSON(data []byte) error {
return s.Decode(d) return s.Decode(d)
} }
// Encode implements json.Marshaler.
func (s *YooMoney) Encode(e *jx.Encoder) {
e.ObjStart()
s.encodeFields(e)
e.ObjEnd()
}
// encodeFields encodes fields.
func (s *YooMoney) encodeFields(e *jx.Encoder) {
{
e.FieldStart("type")
s.Type.Encode(e)
}
{
e.FieldStart("account_number")
e.Str(s.AccountNumber)
}
}
var jsonFieldsNameOfYooMoney = [2]string{
0: "type",
1: "account_number",
}
// Decode decodes YooMoney from json.
func (s *YooMoney) Decode(d *jx.Decoder) error {
if s == nil {
return errors.New("invalid: unable to decode YooMoney to nil")
}
var requiredBitSet [1]uint8
if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error {
switch string(k) {
case "type":
requiredBitSet[0] |= 1 << 0
if err := func() error {
if err := s.Type.Decode(d); err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"type\"")
}
case "account_number":
requiredBitSet[0] |= 1 << 1
if err := func() error {
v, err := d.Str()
s.AccountNumber = string(v)
if err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"account_number\"")
}
default:
return d.Skip()
}
return nil
}); err != nil {
return errors.Wrap(err, "decode YooMoney")
}
// Validate required fields.
var failures []validate.FieldError
for i, mask := range [1]uint8{
0b00000011,
} {
if result := (requiredBitSet[i] & mask) ^ mask; result != 0 {
// Mask only required fields and check equality to mask using XOR.
//
// If XOR result is not zero, result is not equal to expected, so some fields are missed.
// Bits of fields which would be set are actually bits of missed fields.
missed := bits.OnesCount8(result)
for bitN := 0; bitN < missed; bitN++ {
bitIdx := bits.TrailingZeros8(result)
fieldIdx := i*8 + bitIdx
var name string
if fieldIdx < len(jsonFieldsNameOfYooMoney) {
name = jsonFieldsNameOfYooMoney[fieldIdx]
} else {
name = strconv.Itoa(fieldIdx)
}
failures = append(failures, validate.FieldError{
Name: name,
Error: validate.ErrFieldRequired,
})
// Reset bit.
result &^= 1 << bitIdx
}
}
}
if len(failures) > 0 {
return &validate.Error{Fields: failures}
}
return nil
}
// MarshalJSON implements stdjson.Marshaler.
func (s *YooMoney) MarshalJSON() ([]byte, error) {
e := jx.Encoder{}
s.Encode(&e)
return e.Bytes(), nil
}
// UnmarshalJSON implements stdjson.Unmarshaler.
func (s *YooMoney) UnmarshalJSON(data []byte) error {
d := jx.DecodeBytes(data)
return s.Decode(d)
}
// Encode encodes YooMoneyAccountNumber as json. // Encode encodes YooMoneyAccountNumber as json.
func (s YooMoneyAccountNumber) Encode(e *jx.Encoder) { func (s YooMoneyAccountNumber) Encode(e *jx.Encoder) {
unwrapped := string(s) unwrapped := string(s)

View File

@@ -4,6 +4,7 @@ package gen
import ( import (
"bytes" "bytes"
"log/slog"
"net/http" "net/http"
"github.com/go-faster/jx" "github.com/go-faster/jx"
@@ -76,6 +77,7 @@ func encodePayoutsPostRequest(
req.Encode(e) req.Encode(e)
} }
encoded := e.Bytes() encoded := e.Bytes()
slog.Info(string(encoded))
ht.SetBody(r, bytes.NewReader(encoded), contentType) ht.SetBody(r, bytes.NewReader(encoded), contentType)
return nil return nil
} }

View File

@@ -684,6 +684,33 @@ func (s *BadRequestType) UnmarshalText(data []byte) error {
} }
} }
// Merged schema.
// Ref: #/components/schemas/bank_card
type BankCard struct {
Type PayoutDestinationDataType `json:"type"`
Card CardDataForPayoutDestination `json:"card"`
}
// GetType returns the value of Type.
func (s *BankCard) GetType() PayoutDestinationDataType {
return s.Type
}
// GetCard returns the value of Card.
func (s *BankCard) GetCard() CardDataForPayoutDestination {
return s.Card
}
// SetType sets the value of Type.
func (s *BankCard) SetType(val PayoutDestinationDataType) {
s.Type = val
}
// SetCard sets the value of Card.
func (s *BankCard) SetCard(val CardDataForPayoutDestination) {
s.Card = val
}
// Данные банковской карты. // Данные банковской карты.
// Ref: #/components/schemas/BankCardData // Ref: #/components/schemas/BankCardData
type BankCardData struct { type BankCardData struct {
@@ -18581,6 +18608,7 @@ type PayoutRequest struct {
// только для разных типов данных. // только для разных типов данных.
PersonalData []PayoutsPersonalData `json:"personal_data"` PersonalData []PayoutsPersonalData `json:"personal_data"`
Metadata OptMetadata `json:"metadata"` Metadata OptMetadata `json:"metadata"`
Test OptTest `json:"test"`
} }
// GetAmount returns the value of Amount. // GetAmount returns the value of Amount.
@@ -18623,6 +18651,11 @@ func (s *PayoutRequest) GetMetadata() OptMetadata {
return s.Metadata return s.Metadata
} }
// GetTest returns the value of Test.
func (s *PayoutRequest) GetTest() OptTest {
return s.Test
}
// SetAmount sets the value of Amount. // SetAmount sets the value of Amount.
func (s *PayoutRequest) SetAmount(val PayoutRequestAmount) { func (s *PayoutRequest) SetAmount(val PayoutRequestAmount) {
s.Amount = val s.Amount = val
@@ -18663,6 +18696,11 @@ func (s *PayoutRequest) SetMetadata(val OptMetadata) {
s.Metadata = val s.Metadata = val
} }
// SetTest sets the value of Test.
func (s *PayoutRequest) SetTest(val OptTest) {
s.Test = val
}
// Сумма в выбранной валюте. // Сумма в выбранной валюте.
type PayoutRequestAmount struct { type PayoutRequestAmount struct {
// Сумма в выбранной валюте. Всегда дробное значение. // Сумма в выбранной валюте. Всегда дробное значение.
@@ -18695,10 +18733,10 @@ func (s *PayoutRequestAmount) SetCurrency(val CurrencyCode) {
// PayoutRequestPayoutDestinationData represents sum type. // PayoutRequestPayoutDestinationData represents sum type.
type PayoutRequestPayoutDestinationData struct { type PayoutRequestPayoutDestinationData struct {
Type PayoutRequestPayoutDestinationDataType // switch on this field Type PayoutRequestPayoutDestinationDataType // switch on this field
PayoutToYooMoneyDestinationData PayoutToYooMoneyDestinationData YooMoney YooMoney
PayoutToBankCardDestinationData PayoutToBankCardDestinationData BankCard BankCard
PayoutToSbpDestinationData PayoutToSbpDestinationData Sbp Sbp
} }
// PayoutRequestPayoutDestinationDataType is oneOf type of PayoutRequestPayoutDestinationData. // PayoutRequestPayoutDestinationDataType is oneOf type of PayoutRequestPayoutDestinationData.
@@ -18706,86 +18744,86 @@ type PayoutRequestPayoutDestinationDataType string
// Possible values for PayoutRequestPayoutDestinationDataType. // Possible values for PayoutRequestPayoutDestinationDataType.
const ( const (
PayoutToYooMoneyDestinationDataPayoutRequestPayoutDestinationData PayoutRequestPayoutDestinationDataType = "PayoutToYooMoneyDestinationData" YooMoneyPayoutRequestPayoutDestinationData PayoutRequestPayoutDestinationDataType = "yoo_money"
PayoutToBankCardDestinationDataPayoutRequestPayoutDestinationData PayoutRequestPayoutDestinationDataType = "PayoutToBankCardDestinationData" BankCardPayoutRequestPayoutDestinationData PayoutRequestPayoutDestinationDataType = "bank_card"
PayoutToSbpDestinationDataPayoutRequestPayoutDestinationData PayoutRequestPayoutDestinationDataType = "PayoutToSbpDestinationData" SbpPayoutRequestPayoutDestinationData PayoutRequestPayoutDestinationDataType = "sbp"
) )
// IsPayoutToYooMoneyDestinationData reports whether PayoutRequestPayoutDestinationData is PayoutToYooMoneyDestinationData. // IsYooMoney reports whether PayoutRequestPayoutDestinationData is YooMoney.
func (s PayoutRequestPayoutDestinationData) IsPayoutToYooMoneyDestinationData() bool { func (s PayoutRequestPayoutDestinationData) IsYooMoney() bool {
return s.Type == PayoutToYooMoneyDestinationDataPayoutRequestPayoutDestinationData return s.Type == YooMoneyPayoutRequestPayoutDestinationData
} }
// IsPayoutToBankCardDestinationData reports whether PayoutRequestPayoutDestinationData is PayoutToBankCardDestinationData. // IsBankCard reports whether PayoutRequestPayoutDestinationData is BankCard.
func (s PayoutRequestPayoutDestinationData) IsPayoutToBankCardDestinationData() bool { func (s PayoutRequestPayoutDestinationData) IsBankCard() bool {
return s.Type == PayoutToBankCardDestinationDataPayoutRequestPayoutDestinationData return s.Type == BankCardPayoutRequestPayoutDestinationData
} }
// IsPayoutToSbpDestinationData reports whether PayoutRequestPayoutDestinationData is PayoutToSbpDestinationData. // IsSbp reports whether PayoutRequestPayoutDestinationData is Sbp.
func (s PayoutRequestPayoutDestinationData) IsPayoutToSbpDestinationData() bool { func (s PayoutRequestPayoutDestinationData) IsSbp() bool {
return s.Type == PayoutToSbpDestinationDataPayoutRequestPayoutDestinationData return s.Type == SbpPayoutRequestPayoutDestinationData
} }
// SetPayoutToYooMoneyDestinationData sets PayoutRequestPayoutDestinationData to PayoutToYooMoneyDestinationData. // SetYooMoney sets PayoutRequestPayoutDestinationData to YooMoney.
func (s *PayoutRequestPayoutDestinationData) SetPayoutToYooMoneyDestinationData(v PayoutToYooMoneyDestinationData) { func (s *PayoutRequestPayoutDestinationData) SetYooMoney(v YooMoney) {
s.Type = PayoutToYooMoneyDestinationDataPayoutRequestPayoutDestinationData s.Type = YooMoneyPayoutRequestPayoutDestinationData
s.PayoutToYooMoneyDestinationData = v s.YooMoney = v
} }
// GetPayoutToYooMoneyDestinationData returns PayoutToYooMoneyDestinationData and true boolean if PayoutRequestPayoutDestinationData is PayoutToYooMoneyDestinationData. // GetYooMoney returns YooMoney and true boolean if PayoutRequestPayoutDestinationData is YooMoney.
func (s PayoutRequestPayoutDestinationData) GetPayoutToYooMoneyDestinationData() (v PayoutToYooMoneyDestinationData, ok bool) { func (s PayoutRequestPayoutDestinationData) GetYooMoney() (v YooMoney, ok bool) {
if !s.IsPayoutToYooMoneyDestinationData() { if !s.IsYooMoney() {
return v, false return v, false
} }
return s.PayoutToYooMoneyDestinationData, true return s.YooMoney, true
} }
// NewPayoutToYooMoneyDestinationDataPayoutRequestPayoutDestinationData returns new PayoutRequestPayoutDestinationData from PayoutToYooMoneyDestinationData. // NewYooMoneyPayoutRequestPayoutDestinationData returns new PayoutRequestPayoutDestinationData from YooMoney.
func NewPayoutToYooMoneyDestinationDataPayoutRequestPayoutDestinationData(v PayoutToYooMoneyDestinationData) PayoutRequestPayoutDestinationData { func NewYooMoneyPayoutRequestPayoutDestinationData(v YooMoney) PayoutRequestPayoutDestinationData {
var s PayoutRequestPayoutDestinationData var s PayoutRequestPayoutDestinationData
s.SetPayoutToYooMoneyDestinationData(v) s.SetYooMoney(v)
return s return s
} }
// SetPayoutToBankCardDestinationData sets PayoutRequestPayoutDestinationData to PayoutToBankCardDestinationData. // SetBankCard sets PayoutRequestPayoutDestinationData to BankCard.
func (s *PayoutRequestPayoutDestinationData) SetPayoutToBankCardDestinationData(v PayoutToBankCardDestinationData) { func (s *PayoutRequestPayoutDestinationData) SetBankCard(v BankCard) {
s.Type = PayoutToBankCardDestinationDataPayoutRequestPayoutDestinationData s.Type = BankCardPayoutRequestPayoutDestinationData
s.PayoutToBankCardDestinationData = v s.BankCard = v
} }
// GetPayoutToBankCardDestinationData returns PayoutToBankCardDestinationData and true boolean if PayoutRequestPayoutDestinationData is PayoutToBankCardDestinationData. // GetBankCard returns BankCard and true boolean if PayoutRequestPayoutDestinationData is BankCard.
func (s PayoutRequestPayoutDestinationData) GetPayoutToBankCardDestinationData() (v PayoutToBankCardDestinationData, ok bool) { func (s PayoutRequestPayoutDestinationData) GetBankCard() (v BankCard, ok bool) {
if !s.IsPayoutToBankCardDestinationData() { if !s.IsBankCard() {
return v, false return v, false
} }
return s.PayoutToBankCardDestinationData, true return s.BankCard, true
} }
// NewPayoutToBankCardDestinationDataPayoutRequestPayoutDestinationData returns new PayoutRequestPayoutDestinationData from PayoutToBankCardDestinationData. // NewBankCardPayoutRequestPayoutDestinationData returns new PayoutRequestPayoutDestinationData from BankCard.
func NewPayoutToBankCardDestinationDataPayoutRequestPayoutDestinationData(v PayoutToBankCardDestinationData) PayoutRequestPayoutDestinationData { func NewBankCardPayoutRequestPayoutDestinationData(v BankCard) PayoutRequestPayoutDestinationData {
var s PayoutRequestPayoutDestinationData var s PayoutRequestPayoutDestinationData
s.SetPayoutToBankCardDestinationData(v) s.SetBankCard(v)
return s return s
} }
// SetPayoutToSbpDestinationData sets PayoutRequestPayoutDestinationData to PayoutToSbpDestinationData. // SetSbp sets PayoutRequestPayoutDestinationData to Sbp.
func (s *PayoutRequestPayoutDestinationData) SetPayoutToSbpDestinationData(v PayoutToSbpDestinationData) { func (s *PayoutRequestPayoutDestinationData) SetSbp(v Sbp) {
s.Type = PayoutToSbpDestinationDataPayoutRequestPayoutDestinationData s.Type = SbpPayoutRequestPayoutDestinationData
s.PayoutToSbpDestinationData = v s.Sbp = v
} }
// GetPayoutToSbpDestinationData returns PayoutToSbpDestinationData and true boolean if PayoutRequestPayoutDestinationData is PayoutToSbpDestinationData. // GetSbp returns Sbp and true boolean if PayoutRequestPayoutDestinationData is Sbp.
func (s PayoutRequestPayoutDestinationData) GetPayoutToSbpDestinationData() (v PayoutToSbpDestinationData, ok bool) { func (s PayoutRequestPayoutDestinationData) GetSbp() (v Sbp, ok bool) {
if !s.IsPayoutToSbpDestinationData() { if !s.IsSbp() {
return v, false return v, false
} }
return s.PayoutToSbpDestinationData, true return s.Sbp, true
} }
// NewPayoutToSbpDestinationDataPayoutRequestPayoutDestinationData returns new PayoutRequestPayoutDestinationData from PayoutToSbpDestinationData. // NewSbpPayoutRequestPayoutDestinationData returns new PayoutRequestPayoutDestinationData from Sbp.
func NewPayoutToSbpDestinationDataPayoutRequestPayoutDestinationData(v PayoutToSbpDestinationData) PayoutRequestPayoutDestinationData { func NewSbpPayoutRequestPayoutDestinationData(v Sbp) PayoutRequestPayoutDestinationData {
var s PayoutRequestPayoutDestinationData var s PayoutRequestPayoutDestinationData
s.SetPayoutToSbpDestinationData(v) s.SetSbp(v)
return s return s
} }
@@ -18935,33 +18973,6 @@ func (s *PayoutStatus) UnmarshalText(data []byte) error {
} }
} }
// Merged schema.
// Ref: #/components/schemas/PayoutToBankCardDestinationData
type PayoutToBankCardDestinationData struct {
Type PayoutDestinationDataType `json:"type"`
Card CardDataForPayoutDestination `json:"card"`
}
// GetType returns the value of Type.
func (s *PayoutToBankCardDestinationData) GetType() PayoutDestinationDataType {
return s.Type
}
// GetCard returns the value of Card.
func (s *PayoutToBankCardDestinationData) GetCard() CardDataForPayoutDestination {
return s.Card
}
// SetType sets the value of Type.
func (s *PayoutToBankCardDestinationData) SetType(val PayoutDestinationDataType) {
s.Type = val
}
// SetCard sets the value of Card.
func (s *PayoutToBankCardDestinationData) SetCard(val CardDataForPayoutDestination) {
s.Card = val
}
// Merged schema. // Merged schema.
// Ref: #/components/schemas/PayoutToCardDestination // Ref: #/components/schemas/PayoutToCardDestination
type PayoutToCardDestination struct { type PayoutToCardDestination struct {
@@ -19044,44 +19055,6 @@ func (s *PayoutToSbpDestination) SetRecipientChecked(val bool) {
s.RecipientChecked = val s.RecipientChecked = val
} }
// Merged schema.
// Ref: #/components/schemas/PayoutToSbpDestinationData
type PayoutToSbpDestinationData struct {
Type PayoutDestinationDataType `json:"type"`
Phone string `json:"phone"`
BankID string `json:"bank_id"`
}
// GetType returns the value of Type.
func (s *PayoutToSbpDestinationData) GetType() PayoutDestinationDataType {
return s.Type
}
// GetPhone returns the value of Phone.
func (s *PayoutToSbpDestinationData) GetPhone() string {
return s.Phone
}
// GetBankID returns the value of BankID.
func (s *PayoutToSbpDestinationData) GetBankID() string {
return s.BankID
}
// SetType sets the value of Type.
func (s *PayoutToSbpDestinationData) SetType(val PayoutDestinationDataType) {
s.Type = val
}
// SetPhone sets the value of Phone.
func (s *PayoutToSbpDestinationData) SetPhone(val string) {
s.Phone = val
}
// SetBankID sets the value of BankID.
func (s *PayoutToSbpDestinationData) SetBankID(val string) {
s.BankID = val
}
// Merged schema. // Merged schema.
// Ref: #/components/schemas/PayoutToYooMoneyDestination // Ref: #/components/schemas/PayoutToYooMoneyDestination
type PayoutToYooMoneyDestination struct { type PayoutToYooMoneyDestination struct {
@@ -19109,33 +19082,6 @@ func (s *PayoutToYooMoneyDestination) SetAccountNumber(val YooMoneyAccountNumber
s.AccountNumber = val s.AccountNumber = val
} }
// Merged schema.
// Ref: #/components/schemas/PayoutToYooMoneyDestinationData
type PayoutToYooMoneyDestinationData struct {
Type PayoutDestinationDataType `json:"type"`
AccountNumber string `json:"account_number"`
}
// GetType returns the value of Type.
func (s *PayoutToYooMoneyDestinationData) GetType() PayoutDestinationDataType {
return s.Type
}
// GetAccountNumber returns the value of AccountNumber.
func (s *PayoutToYooMoneyDestinationData) GetAccountNumber() string {
return s.AccountNumber
}
// SetType sets the value of Type.
func (s *PayoutToYooMoneyDestinationData) SetType(val PayoutDestinationDataType) {
s.Type = val
}
// SetAccountNumber sets the value of AccountNumber.
func (s *PayoutToYooMoneyDestinationData) SetAccountNumber(val string) {
s.AccountNumber = val
}
type PayoutsGetInternalServerError TooManyRequests type PayoutsGetInternalServerError TooManyRequests
func (*PayoutsGetInternalServerError) payoutsGetRes() {} func (*PayoutsGetInternalServerError) payoutsGetRes() {}
@@ -23333,6 +23279,44 @@ func (s *SavePaymentMethodType) UnmarshalText(data []byte) error {
} }
} }
// Merged schema.
// Ref: #/components/schemas/sbp
type Sbp struct {
Type PayoutDestinationDataType `json:"type"`
Phone string `json:"phone"`
BankID string `json:"bank_id"`
}
// GetType returns the value of Type.
func (s *Sbp) GetType() PayoutDestinationDataType {
return s.Type
}
// GetPhone returns the value of Phone.
func (s *Sbp) GetPhone() string {
return s.Phone
}
// GetBankID returns the value of BankID.
func (s *Sbp) GetBankID() string {
return s.BankID
}
// SetType sets the value of Type.
func (s *Sbp) SetType(val PayoutDestinationDataType) {
s.Type = val
}
// SetPhone sets the value of Phone.
func (s *Sbp) SetPhone(val string) {
s.Phone = val
}
// SetBankID sets the value of BankID.
func (s *Sbp) SetBankID(val string) {
s.BankID = val
}
type SbpBankBic string type SbpBankBic string
type SbpBankId string type SbpBankId string
@@ -24787,4 +24771,31 @@ type WebhooksWebhookIDDeleteOK struct{}
func (*WebhooksWebhookIDDeleteOK) webhooksWebhookIDDeleteRes() {} func (*WebhooksWebhookIDDeleteOK) webhooksWebhookIDDeleteRes() {}
// Merged schema.
// Ref: #/components/schemas/yoo_money
type YooMoney struct {
Type PayoutDestinationDataType `json:"type"`
AccountNumber string `json:"account_number"`
}
// GetType returns the value of Type.
func (s *YooMoney) GetType() PayoutDestinationDataType {
return s.Type
}
// GetAccountNumber returns the value of AccountNumber.
func (s *YooMoney) GetAccountNumber() string {
return s.AccountNumber
}
// SetType sets the value of Type.
func (s *YooMoney) SetType(val PayoutDestinationDataType) {
s.Type = val
}
// SetAccountNumber sets the value of AccountNumber.
func (s *YooMoney) SetAccountNumber(val string) {
s.AccountNumber = val
}
type YooMoneyAccountNumber string type YooMoneyAccountNumber string

View File

@@ -625,6 +625,40 @@ func (s BadRequestType) Validate() error {
} }
} }
func (s *BankCard) Validate() error {
if s == nil {
return validate.ErrNilPointer
}
var failures []validate.FieldError
if err := func() error {
if err := s.Type.Validate(); err != nil {
return err
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: "type",
Error: err,
})
}
if err := func() error {
if err := s.Card.Validate(); err != nil {
return err
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: "card",
Error: err,
})
}
if len(failures) > 0 {
return &validate.Error{Fields: failures}
}
return nil
}
func (s *BankCardData) Validate() error { func (s *BankCardData) Validate() error {
if s == nil { if s == nil {
return validate.ErrNilPointer return validate.ErrNilPointer
@@ -8892,18 +8926,18 @@ func (s *PayoutRequestAmount) Validate() error {
func (s PayoutRequestPayoutDestinationData) Validate() error { func (s PayoutRequestPayoutDestinationData) Validate() error {
switch s.Type { switch s.Type {
case PayoutToYooMoneyDestinationDataPayoutRequestPayoutDestinationData: case YooMoneyPayoutRequestPayoutDestinationData:
if err := s.PayoutToYooMoneyDestinationData.Validate(); err != nil { if err := s.YooMoney.Validate(); err != nil {
return err return err
} }
return nil return nil
case PayoutToBankCardDestinationDataPayoutRequestPayoutDestinationData: case BankCardPayoutRequestPayoutDestinationData:
if err := s.PayoutToBankCardDestinationData.Validate(); err != nil { if err := s.BankCard.Validate(); err != nil {
return err return err
} }
return nil return nil
case PayoutToSbpDestinationDataPayoutRequestPayoutDestinationData: case SbpPayoutRequestPayoutDestinationData:
if err := s.PayoutToSbpDestinationData.Validate(); err != nil { if err := s.Sbp.Validate(); err != nil {
return err return err
} }
return nil return nil
@@ -9029,40 +9063,6 @@ func (s PayoutStatus) Validate() error {
} }
} }
func (s *PayoutToBankCardDestinationData) Validate() error {
if s == nil {
return validate.ErrNilPointer
}
var failures []validate.FieldError
if err := func() error {
if err := s.Type.Validate(); err != nil {
return err
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: "type",
Error: err,
})
}
if err := func() error {
if err := s.Card.Validate(); err != nil {
return err
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: "card",
Error: err,
})
}
if len(failures) > 0 {
return &validate.Error{Fields: failures}
}
return nil
}
func (s *PayoutToCardDestination) Validate() error { func (s *PayoutToCardDestination) Validate() error {
if s == nil { if s == nil {
return validate.ErrNilPointer return validate.ErrNilPointer
@@ -9173,75 +9173,6 @@ func (s *PayoutToSbpDestination) Validate() error {
return nil return nil
} }
func (s *PayoutToSbpDestinationData) Validate() error {
if s == nil {
return validate.ErrNilPointer
}
var failures []validate.FieldError
if err := func() error {
if err := s.Type.Validate(); err != nil {
return err
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: "type",
Error: err,
})
}
if err := func() error {
if err := (validate.String{
MinLength: 0,
MinLengthSet: false,
MaxLength: 0,
MaxLengthSet: false,
Email: false,
Hostname: false,
Regex: regexMap["[0-9]{4,15}"],
MinNumeric: 0,
MinNumericSet: false,
MaxNumeric: 0,
MaxNumericSet: false,
}).Validate(string(s.Phone)); err != nil {
return errors.Wrap(err, "string")
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: "phone",
Error: err,
})
}
if err := func() error {
if err := (validate.String{
MinLength: 0,
MinLengthSet: false,
MaxLength: 12,
MaxLengthSet: true,
Email: false,
Hostname: false,
Regex: regexMap["[a-zA-Z0-9]{12}"],
MinNumeric: 0,
MinNumericSet: false,
MaxNumeric: 0,
MaxNumericSet: false,
}).Validate(string(s.BankID)); err != nil {
return errors.Wrap(err, "string")
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: "bank_id",
Error: err,
})
}
if len(failures) > 0 {
return &validate.Error{Fields: failures}
}
return nil
}
func (s *PayoutToYooMoneyDestination) Validate() error { func (s *PayoutToYooMoneyDestination) Validate() error {
if s == nil { if s == nil {
return validate.ErrNilPointer return validate.ErrNilPointer
@@ -9276,52 +9207,6 @@ func (s *PayoutToYooMoneyDestination) Validate() error {
return nil return nil
} }
func (s *PayoutToYooMoneyDestinationData) Validate() error {
if s == nil {
return validate.ErrNilPointer
}
var failures []validate.FieldError
if err := func() error {
if err := s.Type.Validate(); err != nil {
return err
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: "type",
Error: err,
})
}
if err := func() error {
if err := (validate.String{
MinLength: 11,
MinLengthSet: true,
MaxLength: 33,
MaxLengthSet: true,
Email: false,
Hostname: false,
Regex: nil,
MinNumeric: 0,
MinNumericSet: false,
MaxNumeric: 0,
MaxNumericSet: false,
}).Validate(string(s.AccountNumber)); err != nil {
return errors.Wrap(err, "string")
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: "account_number",
Error: err,
})
}
if len(failures) > 0 {
return &validate.Error{Fields: failures}
}
return nil
}
func (s *PayoutsGetInternalServerError) Validate() error { func (s *PayoutsGetInternalServerError) Validate() error {
alias := (*TooManyRequests)(s) alias := (*TooManyRequests)(s)
if err := alias.Validate(); err != nil { if err := alias.Validate(); err != nil {
@@ -12616,6 +12501,75 @@ func (s SavePaymentMethodType) Validate() error {
} }
} }
func (s *Sbp) Validate() error {
if s == nil {
return validate.ErrNilPointer
}
var failures []validate.FieldError
if err := func() error {
if err := s.Type.Validate(); err != nil {
return err
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: "type",
Error: err,
})
}
if err := func() error {
if err := (validate.String{
MinLength: 0,
MinLengthSet: false,
MaxLength: 0,
MaxLengthSet: false,
Email: false,
Hostname: false,
Regex: regexMap["[0-9]{4,15}"],
MinNumeric: 0,
MinNumericSet: false,
MaxNumeric: 0,
MaxNumericSet: false,
}).Validate(string(s.Phone)); err != nil {
return errors.Wrap(err, "string")
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: "phone",
Error: err,
})
}
if err := func() error {
if err := (validate.String{
MinLength: 0,
MinLengthSet: false,
MaxLength: 12,
MaxLengthSet: true,
Email: false,
Hostname: false,
Regex: regexMap["[a-zA-Z0-9]{12}"],
MinNumeric: 0,
MinNumericSet: false,
MaxNumeric: 0,
MaxNumericSet: false,
}).Validate(string(s.BankID)); err != nil {
return errors.Wrap(err, "string")
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: "bank_id",
Error: err,
})
}
if len(failures) > 0 {
return &validate.Error{Fields: failures}
}
return nil
}
func (s SbpBankBic) Validate() error { func (s SbpBankBic) Validate() error {
alias := (string)(s) alias := (string)(s)
if err := (validate.String{ if err := (validate.String{
@@ -13831,6 +13785,52 @@ func (s WebhooksPostReqEvent) Validate() error {
} }
} }
func (s *YooMoney) Validate() error {
if s == nil {
return validate.ErrNilPointer
}
var failures []validate.FieldError
if err := func() error {
if err := s.Type.Validate(); err != nil {
return err
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: "type",
Error: err,
})
}
if err := func() error {
if err := (validate.String{
MinLength: 11,
MinLengthSet: true,
MaxLength: 33,
MaxLengthSet: true,
Email: false,
Hostname: false,
Regex: nil,
MinNumeric: 0,
MinNumericSet: false,
MaxNumeric: 0,
MaxNumericSet: false,
}).Validate(string(s.AccountNumber)); err != nil {
return errors.Wrap(err, "string")
}
return nil
}(); err != nil {
failures = append(failures, validate.FieldError{
Name: "account_number",
Error: err,
})
}
if len(failures) > 0 {
return &validate.Error{Fields: failures}
}
return nil
}
func (s YooMoneyAccountNumber) Validate() error { func (s YooMoneyAccountNumber) Validate() error {
alias := (string)(s) alias := (string)(s)
if err := (validate.String{ if err := (validate.String{

View File

@@ -27,7 +27,7 @@ func WithContext(ctx context.Context) Optional {
} }
type Service interface { type Service interface {
CreatePayout(models.PayoutReq, *orm.User, ...Optional) error CreatePayout(models.PayoutReq, *orm.User, string, ...Optional) (models.PayoutResp, error)
GetConfig() yookassaConf.YooKassa GetConfig() yookassaConf.YooKassa
} }

View File

@@ -1,2 +1,11 @@
generator: generator:
ignore_not_implemented: ["all"] ignore_not_implemented: ["all"]
# features:
# enable:
# # Enables paths client generation
# - "paths/client"
# # Enables validation of client requests
# - "client/request/validation"
# # Enables validation of server responses
# - "server/response/validation"
# disable_all: true

View File

@@ -5040,7 +5040,6 @@ components:
discriminator: discriminator:
propertyName: "type" propertyName: "type"
mapping: mapping:
bank_card: "#/components/schemas/PayoutToCardDestination"
yoo_money: "#/components/schemas/PayoutToYooMoneyDestination" yoo_money: "#/components/schemas/PayoutToYooMoneyDestination"
sbp: "#/components/schemas/PayoutToSbpDestination" sbp: "#/components/schemas/PayoutToSbpDestination"
properties: properties:

View File

@@ -2,6 +2,9 @@ package yookassa
import ( import (
"context" "context"
"errors"
"fmt"
"log/slog"
"net/http" "net/http"
"payouts/internal/models" "payouts/internal/models"
"payouts/internal/service/database/orm" "payouts/internal/service/database/orm"
@@ -31,8 +34,6 @@ func NewYookassaService(conf config.YooKassa) (Service, error) {
return nil, err return nil, err
} }
svc.payClient = payClient svc.payClient = payClient
// payClient.PaymentsPost()
return svc, nil return svc, nil
} }
@@ -50,7 +51,7 @@ func (y *yookassaService) getParams(options ...Optional) *params {
func (y *yookassaService) BasicAuth(ctx context.Context, operationName gen.OperationName) (gen.BasicAuth, error) { func (y *yookassaService) BasicAuth(ctx context.Context, operationName gen.OperationName) (gen.BasicAuth, error) {
return gen.BasicAuth{ return gen.BasicAuth{
Username: y.conf.ApiPaymentKey, Username: y.conf.ApiPaymentKey,
Password: y.conf.ApiBaseSecret, Password: y.conf.ApiPaymentSecret,
}, nil }, nil
} }
@@ -60,12 +61,51 @@ func (y *yookassaService) OAuth2(ctx context.Context, operationName gen.Operatio
} }
// CreatePayout implements [Service]. // CreatePayout implements [Service].
func (y *yookassaService) CreatePayout(req models.PayoutReq, userSession *orm.User, opts ...Optional) error { func (y *yookassaService) CreatePayout(req models.PayoutReq, userSession *orm.User, idempotenceKey string, opts ...Optional) (models.PayoutResp, error) {
params := y.getParams(opts...) params := y.getParams(opts...)
y.payClient.PayoutsPost(params.ctx, &gen.PayoutRequest{}, gen.PayoutsPostParams{}) var payoutDestination gen.PayoutRequestPayoutDestinationData
return nil switch req.PayoutType {
case models.TypeSBP:
payoutDestination = gen.NewSbpPayoutRequestPayoutDestinationData(gen.Sbp{
Type: gen.PayoutDestinationDataTypeSbp,
Phone: userSession.Phone,
})
case models.TypeYooMoney:
payoutDestination = gen.NewYooMoneyPayoutRequestPayoutDestinationData(gen.YooMoney{
Type: gen.PayoutDestinationDataTypeYooMoney,
AccountNumber: req.AccountNumber,
})
default:
return models.PayoutResp{Result: "failed", ErrorReason: "unsupported payout type"}, errors.New("unsupported payout type")
}
payoutOpt := gen.NewOptPayoutRequestPayoutDestinationData(payoutDestination)
postResp, err := y.payClient.PayoutsPost(params.ctx, &gen.PayoutRequest{
Amount: gen.PayoutRequestAmount{
Value: fmt.Sprintf("%.2f", req.Amount),
Currency: gen.CurrencyCodeRUB,
},
PayoutDestinationData: payoutOpt,
Test: gen.NewOptTest(gen.Test(y.conf.Test)),
}, gen.PayoutsPostParams{
IdempotenceKey: idempotenceKey,
})
slog.Debug(fmt.Sprintf("Received from yookassa: error %v; response %v", err, postResp))
if err == nil {
switch payoutResp := postResp.(type) {
case *gen.Payout:
slog.Info(fmt.Sprintf("Succeeded payout. It's id = %s", payoutResp.ID))
return models.PayoutResp{Result: string(payoutResp.Status), PayoutID: string(payoutResp.ID)}, nil
default:
return models.PayoutResp{Result: "failed", ErrorReason: fmt.Sprintf("%T", postResp)}, nil
}
}
return models.PayoutResp{Result: "failed", ErrorReason: errors.Join(errors.New("failed to call yookassa api"), err).Error()}, err
} }
// GetConfig implements [Service]. // GetConfig implements [Service].