--- title: Go Server SDK --- # Go Server SDK 公式の Go サーバーサイド SDK — `github.com/Captcha-La/captchala-go`。 SDK が引き受ける 3 つの役割: 1. **Validate** — ブラウザ SDK が返した `pt_` pass トークンを検証します。 2. **Issue** — ワンタイムの `sct_` server トークンを発行し、これから出す challenge を特定のアクション / IP / UID に紐付けます。 3. **Moderate** — テキストと画像を含むマルチモーダルのコンテンツモデレーション。ダッシュボードと同じ OpenAI 互換パイプラインを使用します。 ## インストール ```bash go get github.com/Captcha-La/captchala-go ``` 標準ライブラリのみ。外部依存はありません。 ## Validate(`pt_` トークン) エンドユーザーの IP を渡してください(`CF-Connecting-IP` / `X-Forwarded-For` から取得し、`RemoteAddr` にフォールバック)。任意ですが**指定を推奨**します — 追加のリスクチェックに使われます。 ```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 } ``` IP が手元にない場合は `client.Validate(token)` を使ってください — 検証は そのまま機能し、IP ベースの追加リスクシグナルがなくなるだけです。 元の `server_token` を `bind_uid` 付きで発行した場合は照合します。 ```go if result.UID != expectedUserID { http.Error(w, "user mismatch", http.StatusBadRequest) return } ``` 解答時のコンテキストも参考用に `result.CaptchaArgs` で返ります。 ```go ip := result.CaptchaArgs.UserIP // visitor IP recorded at solve time ``` ## server トークンの発行 ログイン・新規登録・決済などの重要フローで推奨される方式です。バックエンドがワンタイムの `sct_` トークンを発行し、ブラウザに渡し、ブラウザはそれを `serverToken` prop として使います。単回使用・アクションスコープで、必要に応じて IP / UID にバインドできます。 ```go issue, err := client.IssueServerTokenWithOptions("login", captchala.IssueOptions{ BindingIP: userIP, // 別の IP がそのトークンを使おうとするとバックエンドが拒否する TTL: 300, // 秒 MaxUses: 5, // SDK 側の再試行回数 BindUID: userID, // 検証時に ValidateResult.UID と突き合わせる }) if err != nil || !issue.OK { http.Error(w, issue.Error, http.StatusBadRequest) return } // issue.Token をブラウザに渡す ``` デフォルト設定のみのショートカット: ```go issue, err := client.IssueServerToken("login") ``` ## コンテンツモデレーション マルチモーダル — `ModerationItem`(OpenAI 互換のテキストおよび/または image_url)のスライスを受け取ります。 ```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") { // ハードブロック } } ``` プレーンテキスト向けショートカット: ```go result, err := client.ModerationText("user comment here", userID) ``` カテゴリはモデル側で定義されます。固定セットを決め打ちせず、`result.Categories` をディフェンシブに走査してください。 ## 型 | 型 | フィールド | |---|---| | `ValidateResult` | `Valid`、`Error`、`UID`、`ChallengeID`、`Action`、`Offline`、`ClientOnly`、`Warning`、`CaptchaArgs` | | `CaptchaArgs`(情報用) | `Platform`、`UserIP`、`Referer`、`Pkg`、`SolvedAt`、`RiskScore` | | `IssueResult` | `OK`、`Token`、`ExpiresIn`、`IssuedAt`、`Error`、`Message` | | `IssueOptions` | `BindingIP`、`TTL`、`MaxUses`、`BindUID` | | `ModerationItem` | `Type`、`Text`、`ImageURL`(`TextItem()` / `ImageURLItem()` ヘルパーを使用) | | `ModerationResult` | `OK`、`Flagged`、`Categories`、`ContentType`、`Raw`、`Error`、`Message`。メソッド `HasCategory(...names)` | ## リンク - [pkg.go.dev](https://pkg.go.dev/github.com/Captcha-La/captchala-go) · [GitHub](https://github.com/Captcha-La/captchala-go) - [Web SDK 概要](/ja/web-sdk) · [API リファレンス](/ja/api-reference)