115 lines
3.3 KiB
Go
115 lines
3.3 KiB
Go
package yookassa
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"log/slog"
|
|
"net/http"
|
|
"payouts/internal/models"
|
|
"payouts/internal/service/database/orm"
|
|
"payouts/internal/service/yookassa/config"
|
|
"payouts/internal/service/yookassa/gen"
|
|
|
|
"github.com/ogen-go/ogen/ogenerrors"
|
|
)
|
|
|
|
type yookassaService struct {
|
|
conf config.YooKassa
|
|
payClient *gen.Client
|
|
ctx context.Context
|
|
}
|
|
|
|
func NewYookassaService(conf config.YooKassa) (Service, error) {
|
|
|
|
svc := &yookassaService{
|
|
conf: conf,
|
|
ctx: context.Background(),
|
|
}
|
|
payClient, err := gen.NewClient(conf.BaseUrl, svc, gen.WithClient(&http.Client{
|
|
Timeout: conf.Timeout,
|
|
}))
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
svc.payClient = payClient
|
|
return svc, nil
|
|
}
|
|
|
|
func (y *yookassaService) getParams(options ...Optional) *params {
|
|
params := ¶ms{
|
|
ctx: y.ctx,
|
|
}
|
|
for _, opt := range options {
|
|
opt(params)
|
|
}
|
|
return params
|
|
}
|
|
|
|
// BasicAuth implements [gen.SecuritySource].
|
|
func (y *yookassaService) BasicAuth(ctx context.Context, operationName gen.OperationName) (gen.BasicAuth, error) {
|
|
return gen.BasicAuth{
|
|
Username: y.conf.ApiPaymentKey,
|
|
Password: y.conf.ApiPaymentSecret,
|
|
}, nil
|
|
}
|
|
|
|
// OAuth2 implements [gen.SecuritySource].
|
|
func (y *yookassaService) OAuth2(ctx context.Context, operationName gen.OperationName) (gen.OAuth2, error) {
|
|
return gen.OAuth2{}, ogenerrors.ErrSkipClientSecurity
|
|
}
|
|
|
|
// CreatePayout implements [Service].
|
|
func (y *yookassaService) CreatePayout(req models.PayoutReq, userSession *orm.User, idempotenceKey string, opts ...Optional) (models.PayoutResp, error) {
|
|
params := y.getParams(opts...)
|
|
|
|
var payoutDestination gen.PayoutRequestPayoutDestinationData
|
|
|
|
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].
|
|
func (y *yookassaService) GetConfig() config.YooKassa {
|
|
return y.conf
|
|
}
|