134 lines
3.6 KiB
Go
134 lines
3.6 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) {
|
|
fmt.Println("\n\nInit payment request: ", req)
|
|
payloadBytes, err := json.Marshal(req)
|
|
if err != nil {
|
|
fmt.Println("\n\nWe are here")
|
|
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 {
|
|
fmt.Println("\n\nWe are here 2")
|
|
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 {
|
|
fmt.Println("\n\nWe are here 3")
|
|
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 {
|
|
fmt.Println("\n\nWe are here 4")
|
|
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"`
|
|
}
|
|
|
|
fmt.Printf("\n\nInit payment response body: %v\n\n", response)
|
|
|
|
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
|
|
}
|