140 lines
4.3 KiB
Go
140 lines
4.3 KiB
Go
package payments
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/gofrs/uuid/v5"
|
|
"github.com/saveinmed/backend-go/internal/domain"
|
|
)
|
|
|
|
// MockGateway provides a fictional payment gateway for testing and development.
|
|
// All payments are automatically approved after a short delay.
|
|
type MockGateway struct {
|
|
MarketplaceCommission float64
|
|
AutoApprove bool // If true, payments are auto-approved
|
|
}
|
|
|
|
func NewMockGateway(commission float64, autoApprove bool) *MockGateway {
|
|
return &MockGateway{
|
|
MarketplaceCommission: commission,
|
|
AutoApprove: autoApprove,
|
|
}
|
|
}
|
|
|
|
func (g *MockGateway) CreatePreference(ctx context.Context, order *domain.Order, payer *domain.User, sellerAcc *domain.SellerPaymentAccount) (*domain.PaymentPreference, error) {
|
|
select {
|
|
case <-ctx.Done():
|
|
return nil, ctx.Err()
|
|
default:
|
|
}
|
|
|
|
fee := int64(float64(order.TotalCents) * (g.MarketplaceCommission / 100))
|
|
|
|
// Generate a mock payment ID
|
|
mockPaymentID := uuid.Must(uuid.NewV7())
|
|
|
|
status := "pending"
|
|
if g.AutoApprove {
|
|
status = "approved"
|
|
}
|
|
|
|
pref := &domain.PaymentPreference{
|
|
OrderID: order.ID,
|
|
Gateway: "mock",
|
|
CommissionPct: g.MarketplaceCommission,
|
|
MarketplaceFee: fee,
|
|
SellerReceivable: order.TotalCents - fee,
|
|
PaymentURL: fmt.Sprintf("/mock-payment/%s?status=%s", mockPaymentID.String(), status),
|
|
}
|
|
|
|
// Simulate minimal latency
|
|
time.Sleep(5 * time.Millisecond)
|
|
return pref, nil
|
|
}
|
|
|
|
// CreatePayment simulates a direct payment.
|
|
func (g *MockGateway) CreatePayment(ctx context.Context, order *domain.Order, token, issuerID, paymentMethodID string, installments int, payer *domain.User, sellerAcc *domain.SellerPaymentAccount) (*domain.PaymentResult, error) {
|
|
return &domain.PaymentResult{
|
|
PaymentID: uuid.Must(uuid.NewV7()).String(),
|
|
Status: "approved",
|
|
Gateway: "mock",
|
|
Message: "Mock direct payment approved",
|
|
}, nil
|
|
}
|
|
|
|
// CreatePixPayment simulates a Pix payment generation.
|
|
func (g *MockGateway) CreatePixPayment(ctx context.Context, order *domain.Order) (*domain.PixPaymentResult, error) {
|
|
return &domain.PixPaymentResult{
|
|
PaymentID: uuid.Must(uuid.NewV7()).String(),
|
|
OrderID: order.ID,
|
|
Gateway: "mock",
|
|
PixKey: "mock@saveinmed.com",
|
|
QRCode: "mock_qr_code",
|
|
QRCodeBase64: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...",
|
|
CopyPasta: "mock_copy_pasta_code",
|
|
AmountCents: order.TotalCents + order.ShippingFeeCents,
|
|
Status: "pending",
|
|
ExpiresAt: time.Now().Add(30 * time.Minute),
|
|
}, nil
|
|
}
|
|
|
|
// CreateBoletoPayment simulates a Boleto generation.
|
|
func (g *MockGateway) CreateBoletoPayment(ctx context.Context, order *domain.Order, payer *domain.User) (*domain.BoletoPaymentResult, error) {
|
|
return &domain.BoletoPaymentResult{
|
|
PaymentID: uuid.Must(uuid.NewV7()).String(),
|
|
OrderID: order.ID,
|
|
Gateway: "mock",
|
|
BoletoURL: "https://example.com/mock-boleto.pdf",
|
|
BarCode: "00000000000000000000000000000000000000000000",
|
|
DigitableLine: "00000.00000 00000.000000 00000.000000 0 00000000000000",
|
|
AmountCents: order.TotalCents + order.ShippingFeeCents,
|
|
DueDate: time.Now().AddDate(0, 0, 3),
|
|
Status: "pending",
|
|
}, nil
|
|
}
|
|
|
|
// GetPaymentStatus returns a simulated payment status.
|
|
func (g *MockGateway) GetPaymentStatus(ctx context.Context, paymentID string) (*domain.PaymentWebhookEvent, error) {
|
|
return &domain.PaymentWebhookEvent{
|
|
PaymentID: paymentID,
|
|
Status: "approved",
|
|
Gateway: "mock",
|
|
}, nil
|
|
}
|
|
|
|
// ConfirmPayment simulates payment confirmation for the mock gateway.
|
|
func (g *MockGateway) ConfirmPayment(ctx context.Context, paymentID string) (*domain.PaymentResult, error) {
|
|
select {
|
|
case <-ctx.Done():
|
|
return nil, ctx.Err()
|
|
default:
|
|
}
|
|
|
|
// Always approve in mock mode
|
|
return &domain.PaymentResult{
|
|
PaymentID: paymentID,
|
|
Status: "approved",
|
|
Gateway: "mock",
|
|
Message: "Pagamento fictício aprovado automaticamente",
|
|
ConfirmedAt: time.Now(),
|
|
}, nil
|
|
}
|
|
|
|
// RefundPayment simulates a refund for the mock gateway.
|
|
func (g *MockGateway) RefundPayment(ctx context.Context, paymentID string, amountCents int64) (*domain.RefundResult, error) {
|
|
select {
|
|
case <-ctx.Done():
|
|
return nil, ctx.Err()
|
|
default:
|
|
}
|
|
|
|
return &domain.RefundResult{
|
|
RefundID: uuid.Must(uuid.NewV7()).String(),
|
|
PaymentID: paymentID,
|
|
AmountCents: amountCents,
|
|
Status: "refunded",
|
|
RefundedAt: time.Now(),
|
|
}, nil
|
|
}
|