Use o SDK de Go em um handler do Gin
Use um único cliente solvethree compartilhado e passe a Solve um contexto filho de c.Request.Context() com prazo definido. Mantenha a configuração do destino e a chave de API no servidor e autentique o chamador da aplicação antes de criar uma tarefa.
Nesta página
Instale as dependências e configure o destino
- 1.
Crie o módulo Go e instale as dependências
Use Go 1.25 ou posterior para a versão atual do Gin. O SDK do solvethree exige Go 1.22+. Inicialize o módulo da sua aplicação com
go mod init, usando seu próprio caminho de módulo. Instale o Gin seguindo o guia de início rápido e usego getpara adicionarsolvethree.com/[email protected]. O SDK oficial é distribuído pelo proxy público de módulos hospedado no domínio; ele é servido a partir de solvethree.com. - 2.
Defina as credenciais do servidor
Defina
SOLVETHREE_API_KEYcom a chave de API do seu workspace eINTEGRATION_KEYcom o segredo que sua aplicação interna enviará emX-Integration-Key. São credenciais separadas: o chamador da aplicação não precisa da chave de API do solvethree. - 3.
Configure o destino fixo
Defina
CAPTCHA_SITEcom o nome do host de destino eSOLVETHREE_PROXYcom o proxy usado na resolução. Primeiro, crie um perfil de site ativo no workspace; consulte a configuração do perfil de site. O exemplo fixaActioncomologin, então altere esse valor se sua integração usar outra ação. Definir o nome do host e a ação não cria um perfil.
Adicione a rota autenticada do Gin
O cliente é criado uma única vez e é seguro para requisições simultâneas. A rota verifica a credencial da aplicação interna antes de chamar solvethree. Ela aceita um ID de requisição do chamador, mas não um destino ou proxy arbitrário.
package main
import (
"context"
"errors"
"log"
"net/http"
"os"
"time"
"github.com/gin-gonic/gin"
solvethree "solvethree.com/sdk"
)
func main() {
client,err:=solvethree.NewClient(os.Getenv("SOLVETHREE_API_KEY"),nil)
if err!=nil { log.Fatal(err) }
secret:=os.Getenv("INTEGRATION_KEY")
if secret=="" { log.Fatal("Set INTEGRATION_KEY") }
router:=gin.New()
router.Use(gin.Recovery())
router.POST("/captcha/solve",func(c *gin.Context){
if c.GetHeader("X-Integration-Key")!=secret { c.Status(http.StatusUnauthorized);return }
input:=solvethree.TaskRequest{Site:os.Getenv("CAPTCHA_SITE"),Action:"login",
Proxy:os.Getenv("SOLVETHREE_PROXY"),RequestID:c.GetHeader("X-Request-ID")}
ctx,cancel:=context.WithTimeout(c.Request.Context(),180*time.Second);defer cancel()
result,err:=client.Solve(ctx,input,solvethree.SolveOptions{})
if err!=nil {
var failed *solvethree.TaskFailedError
var recovery *solvethree.Error
if errors.As(err,&failed) { c.JSON(502,gin.H{"taskId":failed.TaskID,"errorCode":failed.ErrorCode});return }
if errors.As(err,&recovery) { c.JSON(502,gin.H{"requestId":recovery.RequestID,"taskId":recovery.TaskID});return }
c.JSON(400,gin.H{"error":"Invalid task input"});return
}
// Return private solution data only to the authorized application caller.
c.JSON(200,result)
})
log.Fatal(router.Run("127.0.0.1:3000"))
}A tarefa fornece Site, Action e um único Proxy. Ela deixa Type e URL sem definição, conforme exigido para reCAPTCHA, e usa o modo padrão Enterprise v3.
O prazo explícito do contexto limita a espera do handler a 180 segundos; a desconexão do cliente pode cancelá-la antes. O servidor HTTP e qualquer proxy reverso devem permitir essa duração de requisição. Se não puderem, use operações separadas de criação e consulta em vez de manter essa rota síncrona aberta.
O listener fica vinculado ao endereço de loopback. Integre a rota à configuração existente de autenticação interna e implantação da sua aplicação; não exponha um endpoint de resolução paga sem autenticar o chamador.
Trate erros sem expor segredos
O handler usa errors.As em vez de comparar strings de erro. Um TaskFailedError terminal produz uma resposta 502 contendo o ID da tarefa e o código de erro. Outros erros encapsulados do SDK produzem uma resposta 502 contendo IDs de recuperação. O fallback retorna uma mensagem fixa com status 400 em vez de expor erros brutos, credenciais ou URLs de proxy.
Nem todas essas respostas 502 significam que a resolução falhou. Use errors.Is para distinguir cancelamento de expiração do prazo. Para tratamento específico de HTTP, errors.As pode extrair um APIError aninhado com StatusCode e RetryAfter. Mantenha essa distinção nos diagnósticos internos, em vez de tratar cada erro como motivo para criar outra tarefa.
Não consulte novamente uma tarefa que terminou com falha. Recupere-a se precisar do texto do erro e corrija a causa antes de iniciar outra resolução. Resoluções com falha são reembolsadas.
Guarde os IDs quando a solicitação exceder o tempo limite
O cancelamento interrompe a espera, não o trabalho remoto. O exemplo retorna IDs de recuperação quando possível, mas não os persiste. Se o chamador se desconectar, essa resposta JSON talvez nunca chegue.
- 1.
Atribua o ID da solicitação antes de chamar a rota
Faça o chamador interno manter um
X-Request-IDestável para cada resolução lógica. IDs válidos contêm de 1–64 letras ASCII, números, sublinhados ou hífens. O SDK gera um ID quando ele não é fornecido, mas atribuí-lo antecipadamente permite a recuperação mesmo se a resposta se perder. - 2.
Guarde os dados de entrada exatos da tarefa
Armazene o hostname, a ação, o proxy e o ID da solicitação em um armazenamento protegido da aplicação. Uma nova tentativa após uma alteração na configuração do ambiente não deve substituir silenciosamente os dados de entrada da tarefa.
- 3.
Recupere antes de criar novo trabalho
Se o ID da tarefa for conhecido, chame
GetTaskusando um novo contexto com prazo limitado. Caso contrário, reenvie a tarefa original porCreateTaskcom o mesmo ID de solicitação e os mesmos dados de entrada. Isso retorna a tarefa existente; dados diferentes com o mesmo ID geram conflito. Continue consultando apenas enquanto a tarefa estiver pendente ou em resolução.
Solve cria uma única vez e repete apenas consultas que recebem respostas temporárias com status HTTP 429, 502, 503 ou 504, respeitando Retry-After dentro do prazo do contexto. CreateTask nunca repete POST automaticamente, portanto, um tempo limite na criação ainda exige recuperação, não um novo ID de solicitação.
Envie o token com a identidade retornada
Uma resposta bem-sucedida do handler contém dados privados da solução para o chamador autorizado da aplicação. Use Solution.Token, não o ID da tarefa, na solicitação ao destino. Use os valores retornados de UserAgent e SecChUA e obtenha o proxy bem-sucedido com SuccessfulProxy(originalTask, readyResult).
O SDK não envia nada ao destino. Uma tarefa pronta significa que uma solução foi gerada, não que o site a aceitou. Verifique a resposta do destino separadamente.
Fontes e referência da API
Execute sua primeira tarefa.
Comece com $5 em créditos no espaço de trabalho.