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:
- Validar — verifica un pass token
pt_del SDK del navegador. - Emitir — genera un server token
sct_de un solo uso para vincular el próximo desafío a una acción / IP / UID concretas. - Moderar — moderación de contenido multimodal (texto + imagen) contra la misma pipeline compatible con OpenAI que utiliza el panel.
Instalación
go get github.com/Captcha-La/captchala-goSolo 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.
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:
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:
ip := result.CaptchaArgs.UserIP // IP del visitante registrada en el momento de la resoluciónEmitir 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.
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 browserAtajo con valores por defecto:
issue, err := client.IssueServerToken("login")Moderar contenido
Multimodal — acepta un slice de ModerationItem (texto y/o image_url en formato compatible con OpenAI):
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:
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) |