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),
|
Items: utils.ProtoItems2ReceiptItems(in.MainSettings.Items),
|
||||||
}),
|
}),
|
||||||
"save_payment_method": strconv.FormatBool(in.MainSettings.Auto),
|
"save_payment_method": strconv.FormatBool(in.MainSettings.Auto),
|
||||||
|
"recurrent": strconv.FormatBool(in.MainSettings.Recurrent),
|
||||||
}
|
}
|
||||||
link, err := provider.CreateInvoice(ctx, request)
|
link, err := provider.CreateInvoice(ctx, request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -59,6 +59,7 @@ type CreatePayment[T any] struct {
|
|||||||
ClientIP string
|
ClientIP string
|
||||||
Requisites T
|
Requisites T
|
||||||
Auto bool
|
Auto bool
|
||||||
|
Recurrent bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type BankCard struct {
|
type BankCard struct {
|
||||||
|
@ -41,3 +41,10 @@ type Customer struct {
|
|||||||
Email string `json:"email,omitempty"`
|
Email string `json:"email,omitempty"`
|
||||||
Phone string `json:"phone,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))
|
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)
|
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()
|
idempotenceKey := uuid.New().String()
|
||||||
|
|
||||||
yandexPayment, err := p.httpClient.R().
|
yandexPayment, err := p.httpClient.R().
|
||||||
@ -250,3 +255,77 @@ func (p *Provider) handleWebhook(ctx *fiber.Ctx) error {
|
|||||||
|
|
||||||
return ctx.SendStatus(http.StatusOK)
|
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)
|
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]{
|
payment := &models.CreatePayment[yandex.Receipt]{
|
||||||
Type: models.PaymentType(data["type"]),
|
Type: models.PaymentType(data["type"]),
|
||||||
@ -47,6 +54,7 @@ func MapToCreatePaymentYandexReceipt(data map[string]string) (*models.CreatePaym
|
|||||||
ClientIP: data["client_ip"],
|
ClientIP: data["client_ip"],
|
||||||
Requisites: requisites,
|
Requisites: requisites,
|
||||||
Auto: auto,
|
Auto: auto,
|
||||||
|
Recurrent: recurrent,
|
||||||
}
|
}
|
||||||
|
|
||||||
return payment, nil
|
return payment, nil
|
||||||
|
Loading…
Reference in New Issue
Block a user