Geelab Docs
Deployment

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:

ParameterDescription
lot_numberVerification event serial number
captcha_outputVerification output information
pass_tokenVerification pass identifier
gen_timeVerification pass timestamp

Generate Signature

Generate sign_token using the HMAC-SHA256 algorithm:

Generate Signature
import hmac
import hashlib

sign_token = hmac.new(
    CAPTCHA_KEY.encode(),
    lot_number.encode(),
    hashlib.sha256
).hexdigest()
Generate Signature
const crypto = require('crypto');

const sign_token = crypto
    .createHmac('sha256', CAPTCHA_KEY)
    .update(lot_number)
    .digest('hex');
Generate Signature
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);
Generate Signature
$sign_token = hash_hmac('sha256', $lot_number, $CAPTCHA_KEY);
Generate Signature
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
Request Example (Global Region)
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=xxx

Handle Response

Decide whether to allow user operations based on the response result:

Success Response
{
    "status": "success",
    "result": "success",
    "reason": ""
}
Failure Response
{
    "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:

Disaster Recovery Handling
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:

Python Quick Example
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.

Node.js Quick Example
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.

Java Quick Example
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 Quick Example
<?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.

Go Quick Example
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:

  1. Check the captcha_id used on the frontend
  2. Check the captcha_id used on the backend
  3. Confirm they are consistent

When does -50005 error occur?

Reason: Incorrect parameter transmission format.

Checklist:

  • Is gen_time a 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.