연동 가이드
서버 측 연동
위젯은 브라우저에 일회용 토큰을 건넵니다. 그 토큰은 당신의 서버가 Caputchin으로 확인하기 전까지 아무것도 증명하지 않습니다. 이것이 보이는 챌린지를 진짜 보호로 바꾸는 단계이며, 단 한 번의 HTTPS 호출입니다.
당신에게는 아웃바운드 요청을 할 수 있는 백엔드와, 거기서 쓸 수 있는 사이트 키의 시크릿(cpt_sec_...)이 필요하며, 절대 브라우저에는 두지 않습니다.
1. 토큰 읽기
폼이 POST하면, 당신의 핸들러는 당신 자신의 필드 옆에 추가 필드 하나를 받습니다: caputchin-token. 위젯이 방문자가 챌린지를 풀었을 때 그것을 폼에 넣었습니다.
2. /siteverify로 확인하기
토큰과 당신의 시크릿을 POST하세요. 요청과 응답은 reCAPTCHA의 siteverify와 같은 모양이라, 기존 연동을 거의 손대지 않고 옮길 수 있습니다:
POST https://caputchin.com/api/v1/siteverify
Content-Type: application/json
{ "secret": "cpt_sec_...", "response": "<caputchin-token>" }// Node 18+
const verdict = await fetch("https://caputchin.com/api/v1/siteverify", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
secret: process.env.CAPUTCHIN_SECRET,
response: token,
}),
}).then((r) => r.json());
if (!verdict.success) {
// reject the submission
}다른 언어로 된 같은 호출은 백엔드 연동 예제에 있습니다.
3. 응답 읽기
{
"success": true,
"error-codes": [],
"platform": { "game_id": "caputchin/games/leaf-memory", "score": 847, "duration_ms": 4200 }
}- **
success**가 분기할 유일한 대상입니다.true는 진짜 방문자가 챌린지를 풀었다는 뜻이니, 요청을 신뢰하세요.false는 버리라는 뜻입니다. - **
error-codes**는success가false일 때 나타나, 무엇이 잘못됐는지(없거나, 만료됐거나, 이미 사용된 토큰 등) 이름을 댑니다. - **
platform**은 클라이언트가 주장한 메타데이터입니다(어떤 게임인지, 점수, 소요 시간). 이것은 nullable이며 보안 신호가 아닙니다. 원하면 분석용으로 기록하되, 절대 점수에 신뢰를 걸지 마세요.
당신을 보호하는 규칙
- 일회용. 토큰은 한 번 검증합니다. 같은 것을 다시 제출하면
success: false가 돌아오니, 리플레이를 직접 추적할 필요가 없습니다. - 짧은 수명. 토큰은 발급 후 10분이 지나면 만료되니, 지연 작업이 아니라 제출을 처리하는 동안 검증하세요.
- 시크릿은 서버에 머뭅니다. 그것은 절대 브라우저로 가지 않으며, 호출을 인증하는 것이 바로 그것입니다.
흔한 실수
- 클라이언트 측에서 검증하기.
pass이벤트와 토큰의 존재는 UX일 뿐입니다. 모든 신뢰 결정은 여기, 서버 측에서, 당신의 시크릿으로 일어납니다. score에 게이트 걸기. 그것은 신뢰 값이 아니라 메타데이터입니다.