Yimaru-BackEnd/internal/services/chapa/client.go

127 lines
3.3 KiB
Go

package chapa
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"github.com/SamuelTariku/FortuneBet-Backend/internal/domain"
)
type ChapaClient interface {
IssuePayment(ctx context.Context, payload domain.ChapaTransferPayload) (bool, error)
InitPayment(ctx context.Context, req domain.InitPaymentRequest) (string, error)
FetchBanks() ([]domain.ChapaSupportedBank, error)
}
type Client struct {
BaseURL string
SecretKey string
HTTPClient *http.Client
UserAgent string
}
func NewClient(baseURL, secretKey string) *Client {
return &Client{
BaseURL: baseURL,
SecretKey: secretKey,
HTTPClient: http.DefaultClient,
UserAgent: "FortuneBet/1.0",
}
}
func (c *Client) IssuePayment(ctx context.Context, payload domain.ChapaTransferPayload) (bool, error) {
payloadBytes, err := json.Marshal(payload)
if err != nil {
return false, fmt.Errorf("failed to serialize payload: %w", err)
}
req, err := http.NewRequestWithContext(ctx, "POST", c.BaseURL+"/transfers", bytes.NewBuffer(payloadBytes))
if err != nil {
return false, fmt.Errorf("failed to create HTTP request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+c.SecretKey)
req.Header.Set("Content-Type", "application/json")
resp, err := c.HTTPClient.Do(req)
if err != nil {
return false, fmt.Errorf("chapa HTTP request failed: %w", err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
return true, nil
}
return false, fmt.Errorf("chapa error: status %d, body: %s", resp.StatusCode, string(body))
}
// service/chapa_service.go
func (c *Client) InitPayment(ctx context.Context, req domain.InitPaymentRequest) (string, error) {
payloadBytes, err := json.Marshal(req)
if err != nil {
return "", fmt.Errorf("failed to serialize payload: %w", err)
}
httpReq, err := http.NewRequestWithContext(ctx, "POST", c.BaseURL+"/transaction/initialize", bytes.NewBuffer(payloadBytes))
if err != nil {
return "", fmt.Errorf("failed to create HTTP request: %w", err)
}
httpReq.Header.Set("Authorization", "Bearer "+c.SecretKey)
httpReq.Header.Set("Content-Type", "application/json")
resp, err := c.HTTPClient.Do(httpReq)
if err != nil {
return "", fmt.Errorf("chapa HTTP request failed: %w", err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return "", fmt.Errorf("chapa error: status %d, body: %s", resp.StatusCode, string(body))
}
var response struct {
Data struct {
CheckoutURL string `json:"checkout_url"`
} `json:"data"`
}
if err := json.Unmarshal(body, &response); err != nil {
return "", fmt.Errorf("failed to parse chapa response: %w", err)
}
return response.Data.CheckoutURL, nil
}
func (c *Client) FetchBanks() ([]domain.ChapaSupportedBank, error) {
req, _ := http.NewRequest("GET", c.BaseURL+"/banks", nil)
req.Header.Set("Authorization", "Bearer "+c.SecretKey)
fmt.Printf("\n\nbase URL is: %s\n\n", c.BaseURL)
res, err := c.HTTPClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
var resp struct {
Message string `json:"message"`
Data []domain.ChapaSupportedBank `json:"data"`
}
if err := json.NewDecoder(res.Body).Decode(&resp); err != nil {
return nil, err
}
fmt.Printf("\n\nclient fetched banks: %+v\n\n", resp.Data)
return resp.Data, nil
}