--- title: SDK de servidor Go --- # SDK de servidor Go SDK oficial de Go para el servidor — `github.com/Captcha-La/captchala-go`. Tres tareas que el SDK gestiona por ti: 1. **Validar** — verifica un pass token `pt_` del SDK del navegador. 2. **Emitir** — genera un server token `sct_` de un solo uso para vincular el próximo desafío a una acción / IP / UID concretas. 3. **Moderar** — moderación de contenido multimodal (texto + imagen) contra la misma pipeline compatible con OpenAI que utiliza el panel. ## Instalación ```bash go get github.com/Captcha-La/captchala-go ``` Solo stdlib. Sin dependencias externas. ## Validar (token `pt_`) Pasa la IP del usuario final (desde `CF-Connecting-IP` / `X-Forwarded-For`, con respaldo en `RemoteAddr`). Es opcional, pero **recomendado**: se usa para comprobaciones de riesgo adicionales. ```go import captchala "github.com/Captcha-La/captchala-go" client := captchala.NewClient(appKey, appSecret) func handler(w http.ResponseWriter, r *http.Request) { token := r.FormValue("captcha_token") result, err := client.ValidateWithClientIP(token, false, clientIP(r)) if err != nil || !result.Valid { http.Error(w, result.Error, http.StatusBadRequest) return } // Verification passed; proceed with the request. // result.CaptchaArgs has Platform / UserIP / Referer / Pkg / SolvedAt / RiskScore } // Real end-user IP behind a CDN / proxy func clientIP(r *http.Request) string { if ip := r.Header.Get("CF-Connecting-IP"); ip != "" { return ip } if xff := r.Header.Get("X-Forwarded-For"); xff != "" { return strings.TrimSpace(strings.Split(xff, ",")[0]) } host, _, _ := net.SplitHostPort(r.RemoteAddr) return host } ``` ¿No tienes la IP a mano? Usa `client.Validate(token)`: igual verifica, solo que sin la señal de riesgo adicional basada en la IP. Si el `server_token` original se emitió con `bind_uid`, compara: ```go if result.UID != expectedUserID { http.Error(w, "user mismatch", http.StatusBadRequest) return } ``` El contexto del momento de la resolución también se devuelve en `result.CaptchaArgs` para tu referencia: ```go ip := result.CaptchaArgs.UserIP // IP del visitante registrada en el momento de la resolución ``` ## Emitir un server token Recomendado para flujos de alto valor (inicio de sesión, registro, pago): el backend genera un token `sct_` de un solo uso, lo entrega al navegador y este lo usa como prop `serverToken`. Un solo uso, acotado a una acción y vinculable opcionalmente a IP/UID. ```go issue, err := client.IssueServerTokenWithOptions("login", captchala.IssueOptions{ BindingIP: userIP, // backend rejects token if a different IP redeems it TTL: 300, // seconds MaxUses: 5, // SDK retry budget BindUID: userID, // pair with ValidateResult.UID on verify }) if err != nil || !issue.OK { http.Error(w, issue.Error, http.StatusBadRequest) return } // hand issue.Token to the browser ``` Atajo con valores por defecto: ```go issue, err := client.IssueServerToken("login") ``` ## Moderar contenido Multimodal — acepta un slice de `ModerationItem` (texto y/o image_url en formato compatible con OpenAI): ```go result, err := client.ModerationCheck([]captchala.ModerationItem{ captchala.TextItem(userComment), captchala.ImageURLItem(uploadedImageURL), }, userID) if err != nil || !result.OK { http.Error(w, result.Error, http.StatusBadRequest) return } if result.Flagged { if result.HasCategory("violence", "csam") { // hard block } } ``` Atajo de texto plano: ```go result, err := client.ModerationText("user comment here", userID) ``` Las categorías las define el modelo; recorre `result.Categories` de forma defensiva en lugar de codificar un conjunto fijo. ## Tipos | Tipo | Campos | |---|---| | `ValidateResult` | `Valid`, `Error`, `UID`, `ChallengeID`, `Action`, `Offline`, `ClientOnly`, `Warning`, `CaptchaArgs` | | `CaptchaArgs` | `Platform`, `UserIP`, `Referer`, `Pkg`, `SolvedAt`, `RiskScore` (solo informativo) | | `IssueResult` | `OK`, `Token`, `ExpiresIn`, `IssuedAt`, `Error`, `Message` | | `IssueOptions` | `BindingIP`, `TTL`, `MaxUses`, `BindUID` | | `ModerationItem` | `Type`, `Text`, `ImageURL` (usa los helpers `TextItem()` / `ImageURLItem()`) | | `ModerationResult` | `OK`, `Flagged`, `Categories`, `ContentType`, `Raw`, `Error`, `Message`; método `HasCategory(...names)` | ## Enlaces - [pkg.go.dev](https://pkg.go.dev/github.com/Captcha-La/captchala-go) · [GitHub](https://github.com/Captcha-La/captchala-go) - [Visión general del SDK Web](/es/web-sdk) · [Referencia de la API](/es/api-reference)