import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;

/**
 * =============================================================
 *   极验识别 Demo (Java版)
 *
 *   功能说明：
 *   提交极验验证码识别任务（支持三代/四代）
 *   极验识别为异步流程：先提交任务获取resultid，再轮询查询结果
 *
 *   使用方法：
 *   1. 将下方的配置参数替换为你自己的值
 *   2. 编译运行：javac -encoding UTF-8 RecognizeGeetest.java && java RecognizeGeetest
 * =============================================================
 */
public class RecognizeGeetest {

    // ======================== 配置区域（请替换为你自己的参数）========================
    // 用户密钥，登录平台后获取
    private static final String APPKEY = "你的appkey";

    // 极验gt值（三代为gt值，四代为captcha_id值）
    private static final String GT = "你获取到的gt值";

    // challenge值（三代必填，每次只能使用一次；四代无需传此参数，留空即可）
    private static final String CHALLENGE = "";

    // 项目类型（请参照项目价格表，不同类型对应不同的itemid）
    private static final int ITEM_ID = 0;

    // 验证码所在的页面URL（可选，部分网站需要填写）
    private static final String REFERER = "";

    // 可选参数：代理IP（格式示例：http://IP:端口，若需白名单支持请联系客服。http://账号:密码@proxy.com:8080 或 socks5://127.0.0.1:9888）
    private static final String PROXY = "";

    // 可选参数：开发者密钥（如果有的话填写）
    private static final String DEVKEY = "";

    // 可选参数：SDK版本（特殊版本为2，默认为1）
    private static final String SDK = "";

    // 可选参数：对接模式（按次计费:0，包月计费:1，默认为0。包月用户必填）
    private static final String GIVEN = "";

    // 可选参数：特殊网站极验域名（如api-na.geetest.com，不要带http://和/，只需域名）
    private static final String HOST_PARAM = "";

    // 可选参数：User-Agent（适用于某些检验UA的网站，只支持传入安卓ua）
    private static final String USER_AGENT = "";
    // ===============================================================================

    // API基础地址
    private static final String API_BASE = "http://api.ttocr.com/api";

    // 轮询配置
    private static final int POLL_INTERVAL = 2000;  // 轮询间隔（毫秒），不得低于1秒
    private static final int MAX_POLL_TIME = 60000; // 最大等待时间（毫秒）

    /**
     * 发送POST请求（表单数据）
     */
    private static String httpPost(String urlStr, String postData) throws Exception {
        URL url = new URL(urlStr);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        conn.setConnectTimeout(10000);
        conn.setReadTimeout(30000);
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        OutputStream os = conn.getOutputStream();
        os.write(postData.getBytes(StandardCharsets.UTF_8));
        os.flush();
        os.close();
        BufferedReader reader = new BufferedReader(
                new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        reader.close();
        conn.disconnect();
        return sb.toString();
    }

    public static void main(String[] args) {
        System.out.println("************************************************************");
        System.out.println("  极验识别 Demo (Java版)");
        System.out.println("************************************************************");

        if ("你的appkey".equals(APPKEY)) {
            System.out.println("\n[错误] 请先在代码顶部的配置区域填写你的 APPKEY");
            System.exit(1);
        }
        if ("你获取到的gt值".equals(GT)) {
            System.out.println("\n[错误] 请先在代码顶部的配置区域填写 GT 值");
            System.exit(1);
        }
        if (ITEM_ID == 0) {
            System.out.println("\n[错误] 请先在代码顶部的配置区域填写 ITEM_ID（项目类型）");
            System.exit(1);
        }

        try {
            // ========== 步骤1：提交极验识别任务 ==========
            System.out.println("==================================================");
            System.out.println("[提交任务] 正在提交极验识别任务...");
            System.out.println("==================================================");

            StringBuilder postData = new StringBuilder();
            postData.append("appkey=").append(URLEncoder.encode(APPKEY, "UTF-8"));
            postData.append("&gt=").append(URLEncoder.encode(GT, "UTF-8"));
            postData.append("&itemid=").append(ITEM_ID);
            if (CHALLENGE != null && !CHALLENGE.isEmpty()) {
                postData.append("&challenge=").append(URLEncoder.encode(CHALLENGE, "UTF-8"));
            }
            if (REFERER != null && !REFERER.isEmpty()) {
                postData.append("&referer=").append(URLEncoder.encode(REFERER, "UTF-8"));
            }
            if (PROXY != null && !PROXY.isEmpty()) {
                postData.append("&proxy=").append(URLEncoder.encode(PROXY, "UTF-8"));
            }
            if (DEVKEY != null && !DEVKEY.isEmpty()) {
                postData.append("&devkey=").append(URLEncoder.encode(DEVKEY, "UTF-8"));
            }
            if (SDK != null && !SDK.isEmpty()) {
                postData.append("&sdk=").append(URLEncoder.encode(SDK, "UTF-8"));
            }
            if (GIVEN != null && !GIVEN.isEmpty()) {
                postData.append("&given=").append(URLEncoder.encode(GIVEN, "UTF-8"));
            }
            if (HOST_PARAM != null && !HOST_PARAM.isEmpty()) {
                postData.append("&host=").append(URLEncoder.encode(HOST_PARAM, "UTF-8"));
            }
            if (USER_AGENT != null && !USER_AGENT.isEmpty()) {
                postData.append("&userAgent=").append(URLEncoder.encode(USER_AGENT, "UTF-8"));
            }

            System.out.println("[请求参数] gt=" + GT);
            System.out.println("[请求参数] itemid=" + ITEM_ID);

            String submitUrl = API_BASE + "/recognize";
            String submitResult = httpPost(submitUrl, postData.toString());
            System.out.println("[提交响应] " + submitResult);


            // 简单解析resultid（无需JSON库）
            String resultid = null;
            if (submitResult.contains("\"status\":") && submitResult.contains("\"resultid\":")) {
                // 提取status值
                if (submitResult.contains("\"status\": 1") || submitResult.contains("\"status\":1")) {
                    int ridStart = submitResult.indexOf("\"resultid\":");
                    if (ridStart >= 0) {
                        int valStart = submitResult.indexOf("\"", ridStart + 11) + 1;
                        int valEnd = submitResult.indexOf("\"", valStart);
                        resultid = submitResult.substring(valStart, valEnd);
                        System.out.println("[成功] 任务提交成功！resultid=" + resultid);
                    }
                } else {
                    System.out.println("[失败] 任务提交失败");
                }
            }

            if (resultid == null || resultid.isEmpty()) {
                System.out.println("[失败] 未获取到resultid，请检查参数配置");
                System.exit(1);
            }

            // ========== 步骤2：轮询查询识别结果 ==========
            System.out.println("\n==================================================");
            System.out.println("[查询结果] 正在轮询识别结果...");
            System.out.println("[查询结果] 轮询间隔：" + (POLL_INTERVAL / 1000) + "秒，最大等待：" + (MAX_POLL_TIME / 1000) + "秒");
            System.out.println("==================================================");

            String queryUrl = API_BASE + "/results";
            long startTime = System.currentTimeMillis();
            while (true) {
                long elapsed = System.currentTimeMillis() - startTime;
                if (elapsed > MAX_POLL_TIME) {
                    System.out.println("[超时] 已等待" + (MAX_POLL_TIME / 1000) + "秒，识别超时，请稍后重试");
                    break;
                }
                Thread.sleep(POLL_INTERVAL);
                String queryData = "appkey=" + URLEncoder.encode(APPKEY, "UTF-8")
                        + "&resultid=" + URLEncoder.encode(resultid, "UTF-8");
                String queryResult = httpPost(queryUrl, queryData);
                elapsed = System.currentTimeMillis() - startTime;
                if (queryResult.contains("\"status\": 1") || queryResult.contains("\"status\":1")) {
                    System.out.println("\n[成功] 识别成功！");
                    System.out.println("[完整响应] " + queryResult);
                    break;
                } else {
                    System.out.println("[等待中] 第" + (elapsed / 1000) + "秒 - 正在识别中...");
                }
            }
        } catch (Exception e) {
            System.out.println("[异常] 网络请求出错：" + e.getMessage());
        }

        System.out.println("\n==================================================");
        System.out.println("[完成] 识别执行完毕");
        System.out.println("==================================================");
    }
}
