Implement yookassa client
This commit is contained in:
@@ -3,21 +3,54 @@ package yookassa
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
resty "github.com/go-resty/resty/v2"
|
||||
|
||||
"payouts/internal/models"
|
||||
"payouts/internal/service/database/orm"
|
||||
"payouts/internal/service/yookassa/config"
|
||||
)
|
||||
|
||||
const IdempotenceHeader = "Idempotence-Key"
|
||||
|
||||
type yookassaService struct {
|
||||
conf config.YooKassa
|
||||
ctx context.Context
|
||||
|
||||
client *resty.Client
|
||||
}
|
||||
|
||||
func NewYookassaService(conf config.YooKassa) (Service, error) {
|
||||
client := resty.New()
|
||||
client.SetBaseURL(conf.BaseUrl)
|
||||
client.SetBasicAuth(conf.ApiPaymentKey, conf.ApiPaymentSecret)
|
||||
client.SetTimeout(conf.Timeout)
|
||||
|
||||
if conf.Retry.Enabled {
|
||||
client.
|
||||
SetRetryCount(conf.Retry.Count).
|
||||
SetRetryWaitTime(conf.Retry.WaitTime).
|
||||
SetRetryMaxWaitTime(conf.Retry.MaxWaitTime).
|
||||
AddRetryCondition(
|
||||
func(r *resty.Response, err error) bool {
|
||||
// Retry on network errors
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
// Retry on specific status codes
|
||||
return r.StatusCode() == 429 || // Too Many Requests
|
||||
r.StatusCode() >= 500 // Server errors
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
svc := &yookassaService{
|
||||
conf: conf,
|
||||
ctx: context.Background(),
|
||||
conf: conf,
|
||||
client: client,
|
||||
ctx: context.Background(),
|
||||
}
|
||||
return svc, nil
|
||||
}
|
||||
@@ -32,17 +65,79 @@ func (y *yookassaService) getParams(options ...Optional) *params {
|
||||
return params
|
||||
}
|
||||
|
||||
// GetSbpBanks implements [Service].
|
||||
func (y *yookassaService) GetSbpBanks(opts ...Optional) ([]models.SBPBank, error) {
|
||||
params := y.getParams(opts...)
|
||||
|
||||
yResp := &SBPBankResponse{}
|
||||
yError := &Error{}
|
||||
|
||||
restyResp, err := y.client.R().
|
||||
SetContext(params.ctx).
|
||||
SetResult(yResp).
|
||||
SetError(yError).
|
||||
Get("/sbp_banks")
|
||||
|
||||
slog.Debug(fmt.Sprintf("Got response from yookassa: %v", restyResp))
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.Join(errors.New("failed to perform yookassa api post"), err)
|
||||
}
|
||||
|
||||
if restyResp.StatusCode() != http.StatusOK {
|
||||
yError.Status = restyResp.StatusCode()
|
||||
return nil, yError
|
||||
}
|
||||
|
||||
return yResp.Items, nil
|
||||
}
|
||||
|
||||
// CreatePayout implements [Service].
|
||||
func (y *yookassaService) CreatePayout(req models.PayoutReq, userSession *orm.User, idempotenceKey string, opts ...Optional) (models.PayoutResp, error) {
|
||||
// params := y.getParams(opts...)
|
||||
func (y *yookassaService) CreatePayout(req models.PayoutReq, userSession *orm.User, idempotenceKey string, opts ...Optional) (*models.PayoutResp, error) {
|
||||
params := y.getParams(opts...)
|
||||
|
||||
yReq := &PayoutRequest{
|
||||
Amount: Amount{
|
||||
Value: fmt.Sprintf("%.2f", req.Amount),
|
||||
Currency: "RUB",
|
||||
},
|
||||
PayoutDestinationData: PayoutDestination{
|
||||
Type: req.PayoutType,
|
||||
},
|
||||
}
|
||||
yResp := &PayoutResponse{}
|
||||
yError := &Error{}
|
||||
|
||||
switch req.PayoutType {
|
||||
case models.TypeSBP:
|
||||
yReq.PayoutDestinationData.Phone = userSession.Phone
|
||||
yReq.PayoutDestinationData.BankID = req.BankID
|
||||
case models.TypeYooMoney:
|
||||
yReq.PayoutDestinationData.AccountNumber = req.AccountNumber
|
||||
default:
|
||||
return models.PayoutResp{Result: "failed", ErrorReason: "unsupported payout type"}, errors.New("unsupported payout type")
|
||||
return nil, errors.New("unsupported payout type")
|
||||
}
|
||||
return models.PayoutResp{}, nil
|
||||
|
||||
restyResp, err := y.client.R().
|
||||
SetContext(params.ctx).
|
||||
SetHeader(IdempotenceHeader, idempotenceKey).
|
||||
SetBody(yReq).
|
||||
SetResult(yResp).
|
||||
SetError(yError).
|
||||
Post("/payouts")
|
||||
|
||||
slog.Debug(fmt.Sprintf("Got response from yookassa: %v", restyResp))
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.Join(errors.New("failed to perform yookassa api post"), err)
|
||||
}
|
||||
|
||||
if restyResp.StatusCode() != http.StatusOK {
|
||||
yError.Status = restyResp.StatusCode()
|
||||
return nil, yError
|
||||
}
|
||||
|
||||
return &models.PayoutResp{ID: yResp.ID, Status: yResp.Status}, nil
|
||||
}
|
||||
|
||||
// GetConfig implements [Service].
|
||||
|
||||
Reference in New Issue
Block a user