diff --git a/veza-backend-api/internal/services/hyperswitch/client.go b/veza-backend-api/internal/services/hyperswitch/client.go index fb417d8ce..7cf7aa0d4 100644 --- a/veza-backend-api/internal/services/hyperswitch/client.go +++ b/veza-backend-api/internal/services/hyperswitch/client.go @@ -137,3 +137,53 @@ func (c *Client) GetPayment(ctx context.Context, paymentID string) (*PaymentStat } return &out, nil } + +// CreateRefundRequest is the request body for POST /refunds (v0.403 R2) +type CreateRefundRequest struct { + PaymentID string `json:"payment_id"` + Amount *int64 `json:"amount,omitempty"` // nil = full refund + Reason string `json:"reason,omitempty"` + RefundType string `json:"refund_type,omitempty"` // "instant" or "scheduled" +} + +// RefundResponse is the response from POST /refunds +type RefundResponse struct { + RefundID string `json:"refund_id"` + PaymentID string `json:"payment_id"` + Amount int64 `json:"amount"` + Currency string `json:"currency"` + Status string `json:"status"` +} + +// CreateRefund creates a refund against a payment (v0.403 R2) +func (c *Client) CreateRefund(ctx context.Context, paymentID string, amount *int64, reason string) (*RefundResponse, error) { + reqBody := CreateRefundRequest{ + PaymentID: paymentID, + Amount: amount, + Reason: reason, + RefundType: "instant", + } + body, err := json.Marshal(reqBody) + if err != nil { + return nil, fmt.Errorf("marshal refund request: %w", err) + } + req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.baseURL+"/refunds", bytes.NewReader(body)) + if err != nil { + return nil, fmt.Errorf("create request: %w", err) + } + req.Header.Set("Content-Type", "application/json") + req.Header.Set("api-key", c.apiKey) + resp, err := c.httpClient.Do(req) + if err != nil { + return nil, fmt.Errorf("http request: %w", err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("hyperswitch create refund failed: status %d", resp.StatusCode) + } + var out RefundResponse + if err := json.NewDecoder(resp.Body).Decode(&out); err != nil { + return nil, fmt.Errorf("decode response: %w", err) + } + return &out, nil +} diff --git a/veza-backend-api/internal/services/hyperswitch/provider.go b/veza-backend-api/internal/services/hyperswitch/provider.go index b15825b78..235bbe391 100644 --- a/veza-backend-api/internal/services/hyperswitch/provider.go +++ b/veza-backend-api/internal/services/hyperswitch/provider.go @@ -28,3 +28,9 @@ func (p *Provider) CreatePayment(ctx context.Context, amount int64, currency, or func (p *Provider) GetPayment(ctx context.Context, paymentID string) (string, error) { return p.client.GetPaymentStatus(ctx, paymentID) } + +// Refund creates a refund in Hyperswitch (v0.403 R2). +func (p *Provider) Refund(ctx context.Context, paymentID string, amount *int64, reason string) error { + _, err := p.client.CreateRefund(ctx, paymentID, amount, reason) + return err +}