added logic recurrent payment
This commit is contained in:
parent
a1f734a87d
commit
8f7f0db142
@ -97,6 +97,7 @@ func (r *PaymentController) createPayment(ctx context.Context, paymentType model
|
||||
Items: utils.ProtoItems2ReceiptItems(in.MainSettings.Items),
|
||||
}),
|
||||
"save_payment_method": strconv.FormatBool(in.MainSettings.Auto),
|
||||
"recurrent": strconv.FormatBool(in.MainSettings.Recurrent),
|
||||
}
|
||||
link, err := provider.CreateInvoice(ctx, request)
|
||||
if err != nil {
|
||||
|
@ -59,6 +59,7 @@ type CreatePayment[T any] struct {
|
||||
ClientIP string
|
||||
Requisites T
|
||||
Auto bool
|
||||
Recurrent bool
|
||||
}
|
||||
|
||||
type BankCard struct {
|
||||
|
@ -41,3 +41,10 @@ type Customer struct {
|
||||
Email string `json:"email,omitempty"`
|
||||
Phone string `json:"phone,omitempty"`
|
||||
}
|
||||
|
||||
type CreateRecurrentPayment struct {
|
||||
Amount Amount `json:"amount"`
|
||||
Capture bool `json:"capture"`
|
||||
PaymentMethodID string `json:"payment_method_id"`
|
||||
Description string `json:"description,omitempty"`
|
||||
}
|
||||
|
@ -79,6 +79,11 @@ func (p *Provider) CreateInvoice(ctx context.Context, req map[string]string) (st
|
||||
p.logger.Error("failed to create payment yandex receipt by parse map", zap.Error(err))
|
||||
return "", errors.NewWithMessage("failed to parse input request by parse map", errors.ErrInvalidArgs)
|
||||
}
|
||||
|
||||
if request.Recurrent {
|
||||
return p.CreateRecurrentPayment(ctx, request)
|
||||
}
|
||||
|
||||
idempotenceKey := uuid.New().String()
|
||||
|
||||
yandexPayment, err := p.httpClient.R().
|
||||
@ -250,3 +255,77 @@ func (p *Provider) handleWebhook(ctx *fiber.Ctx) error {
|
||||
|
||||
return ctx.SendStatus(http.StatusOK)
|
||||
}
|
||||
|
||||
func (p *Provider) CreateRecurrentPayment(ctx context.Context, request *models.CreatePayment[yandex.Receipt]) (string, errors.Error) {
|
||||
methods, err := p.paymentMethodRepository.GetByUserID(ctx, request.UserID)
|
||||
if err != nil {
|
||||
p.logger.Error("failed to get payment methods", zap.Error(err), zap.String("userId", request.UserID))
|
||||
return "", errors.NewWithError(err, errors.ErrInternalError)
|
||||
}
|
||||
|
||||
if len(methods) == 0 {
|
||||
p.logger.Warn("no saved payment methods found", zap.String("userId", request.UserID))
|
||||
return "", errors.NewWithMessage("no saved payment methods found", errors.ErrInvalidArgs)
|
||||
}
|
||||
|
||||
for _, method := range methods {
|
||||
idempotenceKey := uuid.New().String()
|
||||
|
||||
yandexPayment, err := p.httpClient.R().
|
||||
SetContext(ctx).
|
||||
SetHeader("Content-Type", "application/json").
|
||||
SetHeader("Idempotence-Key", idempotenceKey).
|
||||
SetHeader("Authorization", utils.ConvertYoomoneySercetsToAuth("Basic", p.config.StoreID, p.config.SecretKey)).
|
||||
SetBody(&yandex.CreateRecurrentPayment{
|
||||
Amount: yandex.Amount{
|
||||
Value: utils.ConvertAmountToStringFloat(request.Amount),
|
||||
Currency: request.Currency,
|
||||
},
|
||||
PaymentMethodID: method.MethodID,
|
||||
Capture: true,
|
||||
}).
|
||||
Post(p.config.PaymentsURL)
|
||||
|
||||
if err != nil {
|
||||
p.logger.Error("failed to create recurrent payment", zap.Error(err), zap.String("userId", request.UserID))
|
||||
return "", errors.NewWithError(fmt.Errorf("failed to create recurrent payment"), errors.ErrInternalError)
|
||||
}
|
||||
|
||||
if yandexPayment.StatusCode() != http.StatusOK {
|
||||
p.logger.Error("unexpected status code from yandex", zap.Int("statusCode", yandexPayment.StatusCode()), zap.String("userId", request.UserID))
|
||||
return "", errors.NewWithError(fmt.Errorf("unexpected status code: %d", yandexPayment.StatusCode()), errors.ErrInternalError)
|
||||
}
|
||||
|
||||
var payment yandex.Payment
|
||||
if err := json.Unmarshal(yandexPayment.Body(), &payment); err != nil {
|
||||
p.logger.Error("failed to unmarshal payment response", zap.Error(err), zap.String("userId", request.UserID), zap.String("methodId", method.MethodID))
|
||||
return "", errors.NewWithError(err, errors.ErrInternalError)
|
||||
}
|
||||
if payment.Status != yandex.PaymentStatusSuccessfully {
|
||||
p.logger.Error("payment not succeeded", zap.String("userId", request.UserID), zap.String("status", string(payment.Status)))
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = p.repository.Insert(ctx, &models.Payment{
|
||||
UserID: request.UserID,
|
||||
PaymentID: payment.ID,
|
||||
IdempotencePaymentID: idempotenceKey,
|
||||
ClientIP: request.ClientIP,
|
||||
Currency: request.Currency,
|
||||
Amount: request.Amount,
|
||||
Type: request.Type,
|
||||
Status: models.PaymentStatusMap[string(payment.Status)],
|
||||
Completed: false,
|
||||
RawPaymentBody: payment,
|
||||
CallbackHostGRPC: request.CallbackHostGRPC,
|
||||
})
|
||||
if err != nil {
|
||||
p.logger.Error("failed to save payment to database", zap.Error(err))
|
||||
return "", errors.NewWithError(fmt.Errorf("failed to save payment to database: %w", err), errors.ErrInternalError)
|
||||
}
|
||||
|
||||
return payment.ID, nil
|
||||
}
|
||||
|
||||
return "", errors.NewWithMessage("failed to create recurrent payment with any saved method", errors.ErrInternalError)
|
||||
}
|
||||
|
@ -36,6 +36,13 @@ func MapToCreatePaymentYandexReceipt(data map[string]string) (*models.CreatePaym
|
||||
return nil, fmt.Errorf("invalid save_payment_method field: %w", err)
|
||||
}
|
||||
}
|
||||
recurrent := false
|
||||
if val, ok := data["recurrent"]; ok && val != "" {
|
||||
recurrent, err = strconv.ParseBool(val)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid recurrent field: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
payment := &models.CreatePayment[yandex.Receipt]{
|
||||
Type: models.PaymentType(data["type"]),
|
||||
@ -47,6 +54,7 @@ func MapToCreatePaymentYandexReceipt(data map[string]string) (*models.CreatePaym
|
||||
ClientIP: data["client_ip"],
|
||||
Requisites: requisites,
|
||||
Auto: auto,
|
||||
Recurrent: recurrent,
|
||||
}
|
||||
|
||||
return payment, nil
|
||||
|
Loading…
Reference in New Issue
Block a user