package veli import ( "bytes" "context" "crypto/hmac" "crypto/sha512" "encoding/base64" "encoding/json" "fmt" "io" "net/http" "sort" "strings" "time" "github.com/SamuelTariku/FortuneBet-Backend/internal/config" "github.com/SamuelTariku/FortuneBet-Backend/internal/services/wallet" ) type Client struct { http *http.Client BaseURL string OperatorID string SecretKey string BrandID string walletSvc *wallet.Service } func NewClient(cfg *config.Config, walletSvc *wallet.Service) *Client { return &Client{ http: &http.Client{Timeout: 10 * time.Second}, BaseURL: cfg.VeliGames.BaseURL, OperatorID: cfg.VeliGames.OperatorID, SecretKey: cfg.VeliGames.SecretKey, BrandID: cfg.VeliGames.BrandID, walletSvc: walletSvc, } } // Signature generator func (c *Client) generateSignature(params map[string]any) (string, error) { keys := make([]string, 0, len(params)) for k := range params { keys = append(keys, k) } sort.Strings(keys) var b strings.Builder first := true appendKV := func(_ string, value string) { if !first { b.WriteString(";") } b.WriteString(value) first = false } for _, k := range keys { v := params[k] switch val := v.(type) { case []string: for i, item := range val { appendKV(k, fmt.Sprintf("%s:%d:%s", k, i, item)) } case []any: for i, item := range val { appendKV(k, fmt.Sprintf("%s:%d:%v", k, i, item)) } default: appendKV(k, fmt.Sprintf("%s:%v", k, val)) } } fmt.Println("String being signed:", b.String()) fmt.Println("Using secret key:", c.SecretKey) h := hmac.New(sha512.New, []byte(c.SecretKey)) h.Write([]byte(b.String())) hash := h.Sum(nil) signature := base64.StdEncoding.EncodeToString(hash) fmt.Println("Generated signature:", signature) return fmt.Sprintf("%s:%s", c.OperatorID, signature), nil } // POST helper func (c *Client) post(ctx context.Context, path string, body any, sigParams map[string]any, result any) error { data, _ := json.Marshal(body) sig, err := c.generateSignature(sigParams) if err != nil { return err } req, _ := http.NewRequestWithContext(ctx, "POST", c.BaseURL+path, bytes.NewReader(data)) req.Header.Set("Content-Type", "application/json") req.Header.Set("signature", sig) // Print request info fmt.Println("Request URL:", c.BaseURL+path) fmt.Println("Request Headers:") for k, v := range req.Header { for _, val := range v { fmt.Printf(" %s: %s\n", k, val) } } fmt.Println("Request Body:", string(data)) // Send request res, err := c.http.Do(req) if err != nil { return err } defer res.Body.Close() // Read response b, _ := io.ReadAll(res.Body) if res.StatusCode >= 400 { return fmt.Errorf("error: %s", b) } if result != nil { return json.Unmarshal(b, result) } return nil }