package monetix import ( "bytes" "context" "encoding/json" "io" "net/http" "strings" "testing" "go.uber.org/zap" ) type roundTripperFunc func(*http.Request) (*http.Response, error) func (f roundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) } func TestSendCardPayout_SignsPayload(t *testing.T) { secret := "secret" var captured CardPayoutRequest httpClient := &http.Client{ Transport: roundTripperFunc(func(r *http.Request) (*http.Response, error) { if r.URL.Path != "/v2/payment/card/payout" { t.Fatalf("expected payout path, got %q", r.URL.Path) } body, _ := io.ReadAll(r.Body) if err := json.Unmarshal(body, &captured); err != nil { t.Fatalf("failed to decode request: %v", err) } resp := APIResponse{} resp.Operation.RequestID = "req-1" payload, _ := json.Marshal(resp) return &http.Response{ StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewReader(payload)), Header: http.Header{"Content-Type": []string{"application/json"}}, }, nil }), } cfg := Config{ BaseURL: "https://monetix.test", SecretKey: secret, } client := NewClient(cfg, httpClient, zap.NewNop()) req := CardPayoutRequest{ General: General{ProjectID: 1, PaymentID: "payout-1"}, Customer: Customer{ ID: "cust-1", FirstName: "Jane", LastName: "Doe", IP: "203.0.113.10", }, Payment: Payment{Amount: 1000, Currency: "RUB"}, Card: Card{PAN: "4111111111111111", Year: 2030, Month: 12, CardHolder: "JANE DOE"}, } result, err := client.CreateCardPayout(context.Background(), req) if err != nil { t.Fatalf("expected no error, got %v", err) } if !result.Accepted { t.Fatalf("expected accepted response") } if captured.General.Signature == "" { t.Fatalf("expected signature in request") } signed := captured signed.General.Signature = "" expectedSig, err := SignPayload(signed, secret) if err != nil { t.Fatalf("failed to compute signature: %v", err) } if captured.General.Signature != expectedSig { t.Fatalf("expected signature %q, got %q", expectedSig, captured.General.Signature) } } func TestSendCardPayout_HTTPError(t *testing.T) { httpClient := &http.Client{ Transport: roundTripperFunc(func(r *http.Request) (*http.Response, error) { body := `{"code":"E100","message":"denied"}` return &http.Response{ StatusCode: http.StatusBadRequest, Body: io.NopCloser(strings.NewReader(body)), Header: http.Header{"Content-Type": []string{"application/json"}}, }, nil }), } cfg := Config{ BaseURL: "https://monetix.test", SecretKey: "secret", } client := NewClient(cfg, httpClient, zap.NewNop()) req := CardPayoutRequest{ General: General{ProjectID: 1, PaymentID: "payout-1"}, Customer: Customer{ ID: "cust-1", FirstName: "Jane", LastName: "Doe", IP: "203.0.113.10", }, Payment: Payment{Amount: 1000, Currency: "RUB"}, Card: Card{PAN: "4111111111111111", Year: 2030, Month: 12, CardHolder: "JANE DOE"}, } result, err := client.CreateCardPayout(context.Background(), req) if err != nil { t.Fatalf("expected no error, got %v", err) } if result.Accepted { t.Fatalf("expected rejected response") } if result.ErrorCode != "E100" { t.Fatalf("expected error code E100, got %q", result.ErrorCode) } if result.ErrorMessage != "denied" { t.Fatalf("expected error message denied, got %q", result.ErrorMessage) } }