Server Integration
Server-side secondary verification integration guide
Important: Server-side secondary verification is a required security step and cannot be omitted!
Overview
After a user completes verification on the frontend, a set of verification parameters is generated. Your backend needs to submit these parameters to the Geelab verification service for secondary verification to confirm the validity of the verification.
Integration Steps
Receive Verification Parameters
Receive the following parameters from the client:
| Parameter | Description |
|---|---|
lot_number | Verification event serial number |
captcha_output | Verification output information |
pass_token | Verification pass identifier |
gen_time | Verification pass timestamp |
Generate Signature
Generate sign_token using the HMAC-SHA256 algorithm:
import hmac
import hashlib
sign_token = hmac.new(
CAPTCHA_KEY.encode(),
lot_number.encode(),
hashlib.sha256
).hexdigest()const crypto = require('crypto');
const sign_token = crypto
.createHmac('sha256', CAPTCHA_KEY)
.update(lot_number)
.digest('hex');Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(
CAPTCHA_KEY.getBytes("UTF-8"),
"HmacSHA256"
);
mac.init(secretKey);
byte[] hash = mac.doFinal(lot_number.getBytes("UTF-8"));
String sign_token = bytesToHex(hash);$sign_token = hash_hmac('sha256', $lot_number, $CAPTCHA_KEY);h := hmac.New(sha256.New, []byte(CAPTCHA_KEY))
h.Write([]byte(lot_number))
sign_token := hex.EncodeToString(h.Sum(nil))For complete signature generation documentation, please refer to Server API - Signature Generation.
Call Verification API
Send a POST request to the Geelab verification service. Please use the corresponding domain based on the region you selected when registering your ID:
- Global:
https://cap-global.geelabapi.com/validate - Europe:
https://cap-eu.geelabapi.com/validate - North America:
https://cap-na.geelabapi.com/validate
POST https://cap-global.geelabapi.com/validate?captcha_id=YOUR_CAPTCHA_ID
Content-Type: application/x-www-form-urlencoded
lot_number=xxx&captcha_output=xxx&pass_token=xxx&gen_time=xxx&sign_token=xxxHandle Response
Decide whether to allow user operations based on the response result:
{
"status": "success",
"result": "success",
"reason": ""
}{
"status": "success",
"result": "fail",
"reason": "pass_token expire"
}Implement Disaster Recovery
When the verification service encounters an exception, it's recommended to allow the request:
try:
response = requests.post(url, data=query, timeout=5)
if response.status_code != 200:
# API exception, allow request
return {'result': 'success', 'reason': 'api error, fallback'}
return response.json()
except Exception as e:
# Request exception, allow request
return {'result': 'success', 'reason': 'request fail, fallback'}Quick Start
Choose your development language to view complete examples:
import hmac
import hashlib
import requests
def validate_captcha(request_data):
# 1. Get parameters
lot_number = request_data.get('lot_number')
captcha_output = request_data.get('captcha_output')
pass_token = request_data.get('pass_token')
gen_time = request_data.get('gen_time')
# 2. Generate signature
sign_token = hmac.new(
CAPTCHA_KEY.encode(),
lot_number.encode(),
hashlib.sha256
).hexdigest()
# 3. Call verification API
try:
response = requests.post(
'https://cap-global.geelabapi.com/validate',
params={'captcha_id': CAPTCHA_ID},
data={
'lot_number': lot_number,
'captcha_output': captcha_output,
'pass_token': pass_token,
'gen_time': gen_time,
'sign_token': sign_token
},
timeout=5
)
if response.status_code != 200:
return {'result': 'success', 'reason': 'api error, fallback'}
return response.json()
except Exception as e:
return {'result': 'success', 'reason': 'request fail, fallback'}For complete Python implementation, please refer to Server API Documentation.
const crypto = require('crypto');
const axios = require('axios');
async function validateCaptcha(requestData) {
// 1. Get parameters
const { lot_number, captcha_output, pass_token, gen_time } = requestData;
// 2. Generate signature
const sign_token = crypto
.createHmac('sha256', CAPTCHA_KEY)
.update(lot_number)
.digest('hex');
// 3. Call verification API
try {
const response = await axios.post(
`https://cap-global.geelabapi.com/validate?captcha_id=${CAPTCHA_ID}`,
new URLSearchParams({
lot_number,
captcha_output,
pass_token,
gen_time,
sign_token
}),
{ timeout: 5000 }
);
if (response.status !== 200) {
return { result: 'success', reason: 'api error, fallback' };
}
return response.data;
} catch (error) {
return { result: 'success', reason: 'request fail, fallback' };
}
}For complete Node.js implementation, please refer to Server API Documentation.
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.http.*;
public ValidationResult validate(CaptchaRequest request) {
try {
// 1. Generate signature
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(
CAPTCHA_KEY.getBytes("UTF-8"),
"HmacSHA256"
);
mac.init(secretKey);
String signToken = bytesToHex(
mac.doFinal(request.getLotNumber().getBytes("UTF-8"))
);
// 2. Call verification API
HttpClient client = HttpClient.newHttpClient();
HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(URI.create(API_URL + "?captcha_id=" + CAPTCHA_ID))
.POST(HttpRequest.BodyPublishers.ofString(params))
.timeout(Duration.ofSeconds(5))
.build();
HttpResponse<String> response = client.send(
httpRequest,
HttpResponse.BodyHandlers.ofString()
);
if (response.statusCode() != 200) {
return ValidationResult.fallback();
}
return mapper.readValue(response.body(), ValidationResult.class);
} catch (Exception e) {
return ValidationResult.fallback();
}
}For complete Java implementation, please refer to Server API Documentation.
<?php
function validateCaptcha($requestData) {
// 1. Get parameters
$lot_number = $requestData['lot_number'];
$captcha_output = $requestData['captcha_output'];
$pass_token = $requestData['pass_token'];
$gen_time = $requestData['gen_time'];
// 2. Generate signature
$sign_token = hash_hmac('sha256', $lot_number, $CAPTCHA_KEY);
// 3. Call verification API
$url = 'https://cap-global.geelabapi.com/validate?captcha_id=' . $CAPTCHA_ID;
$params = http_build_query([
'lot_number' => $lot_number,
'captcha_output' => $captcha_output,
'pass_token' => $pass_token,
'gen_time' => $gen_time,
'sign_token' => $sign_token
]);
try {
$response = @file_get_contents($url, false, stream_context_create([
'http' => [
'method' => 'POST',
'header' => 'Content-Type: application/x-www-form-urlencoded',
'content' => $params,
'timeout' => 5
]
]));
if ($response === false) {
return ['result' => 'success', 'reason' => 'request fail, fallback'];
}
return json_decode($response, true);
} catch (Exception $e) {
return ['result' => 'success', 'reason' => 'exception, fallback'];
}
}
?>For complete PHP implementation, please refer to Server API Documentation.
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"net/http"
"net/url"
"strings"
"time"
)
func ValidateCaptcha(requestData map[string]string) (*ValidationResult, error) {
// 1. Get parameters
lotNumber := requestData["lot_number"]
captchaOutput := requestData["captcha_output"]
passToken := requestData["pass_token"]
genTime := requestData["gen_time"]
// 2. Generate signature
h := hmac.New(sha256.New, []byte(CAPTCHA_KEY))
h.Write([]byte(lotNumber))
signToken := hex.EncodeToString(h.Sum(nil))
// 3. Call verification API
data := url.Values{}
data.Set("lot_number", lotNumber)
data.Set("captcha_output", captchaOutput)
data.Set("pass_token", passToken)
data.Set("gen_time", genTime)
data.Set("sign_token", signToken)
client := &http.Client{Timeout: 5 * time.Second}
apiURL := API_URL + "?captcha_id=" + CAPTCHA_ID
resp, err := client.Post(
apiURL,
"application/x-www-form-urlencoded",
strings.NewReader(data.Encode()),
)
if err != nil || resp.StatusCode != 200 {
return &ValidationResult{
Result: "success",
Reason: "request fail, fallback",
}, nil
}
defer resp.Body.Close()
var result ValidationResult
json.NewDecoder(resp.Body).Decode(&result)
return &result, nil
}For complete Go implementation, please refer to Server API Documentation.
Best Practices
1. Set Reasonable Timeout
It's recommended to set a 5-second timeout to avoid long waits that affect user experience.
2. Implement Disaster Recovery
When the verification service encounters an exception, it's recommended to allow the request to avoid blocking business processes. For detailed disaster recovery strategies, please refer to Fallback Plan.
3. Log Verification Results
Record verification results and exceptions for troubleshooting:
import logging
logger.info('Verification successful', extra={
'lot_number': lot_number,
'result': result['result'],
'user_ip': request.remote_addr
})4. Protect captcha_key
Important: captcha_key is sensitive information and must:
- ✅ Be stored in environment variables or key management systems
- ✅ Not be committed to code repositories
- ✅ Not be printed in logs
- ✅ Be rotated regularly
Common Issues
When does pass_token error occur?
Reason: Inconsistent IDs configured between frontend and backend.
Solution:
- Check the
captcha_idused on the frontend - Check the
captcha_idused on the backend - Confirm they are consistent
When does -50005 error occur?
Reason: Incorrect parameter transmission format.
Checklist:
- Is
gen_timea pure numeric string - Is Content-Type set to
application/x-www-form-urlencoded - Are parameters in form data format
How to handle verification timeout?
It's recommended to set a 5-second timeout. After timeout, allow the request to avoid affecting user experience.
Related Documentation
- Server API Complete Documentation - Detailed API parameters and response formats
- Fallback Plan - Disaster recovery and exception handling
- Error Codes - Complete error code list
- FAQ - More troubleshooting