package sms import ( "fmt" "io" "net/http" "net/url" "strings" "time" ) // HTTPClient sends SMS via the SMSGlobal HTTP API (api.smsglobal.com/http-api.php). // This is the PROVEN path — validated live 2026-08-05 with real credentials // (response: OK: 0; Sent queued message ID ...). Matches the 2014 WhereWoof // integration pattern: action=sendsms, user/password, from, userfield, to, text. type HTTPClient struct { user string password string from string // verified number or sender, international format without '+' http *http.Client } // NewHTTP returns an HTTP-API client. from is required (verified number or // registered sender, e.g. "61423274487"). func NewHTTP(user, password, from string) *HTTPClient { return &HTTPClient{ user: user, password: password, from: from, http: &http.Client{Timeout: 15 * time.Second}, } } // Send posts a message to the destination (international format, no '+'). func (c *HTTPClient) Send(to, body string) error { form := url.Values{} form.Set("action", "sendsms") form.Set("user", c.user) form.Set("password", c.password) form.Set("from", c.from) form.Set("userfield", fmt.Sprintf("MID%sWSIDwherewoof", time.Now().UTC().Format("20060102150405"))) form.Set("to", to) form.Set("text", body) form.Set("maxsplit", "5") resp, err := c.http.PostForm("https://api.smsglobal.com/http-api.php", form) if err != nil { return err } defer resp.Body.Close() b, _ := io.ReadAll(io.LimitReader(resp.Body, 512)) s := strings.TrimSpace(string(b)) if !strings.HasPrefix(s, "OK:") { return fmt.Errorf("smsglobal http: %s", s) } return nil }