Parcourir la source

gpt自动充值第三方对接及测试页面

chenbiao il y a 1 an
Parent
commit
a390f7f287

+ 30 - 0
netflix-service/src/main/java/com/cyksj/server/recharge/GptProxyRechargeService.java

@@ -0,0 +1,30 @@
+package com.cyksj.server.recharge;
+
+import com.cyksj.server.recharge.dto.*;
+
+/**
+ * @author chan
+ * @date 2025/7/30 18:55
+ */
+public interface GptProxyRechargeService {
+    
+    /**
+     * 验证卡密
+     */
+    CardKeyValidationResult validateCardKey(String cardKey);
+    
+    /**
+     * 验证凭证
+     */
+    TokenParseResult parseToken(String accessToken);
+    
+    /**
+     * 提交任务
+     */
+    TaskSubmitResult submitTask(String cardKey, String accessToken, String idp);
+    
+    /**
+     * 获取任务结果
+     */
+    TaskResult getTaskResult(String taskId);
+}

+ 29 - 0
netflix-service/src/main/java/com/cyksj/server/recharge/dto/CardKeyValidationResult.java

@@ -0,0 +1,29 @@
+package com.cyksj.server.recharge.dto;
+
+/**
+ * 卡密验证结果
+ */
+public class CardKeyValidationResult {
+    private Boolean available;
+
+    public CardKeyValidationResult() {}
+
+    public CardKeyValidationResult(Boolean available) {
+        this.available = available;
+    }
+
+    public Boolean getAvailable() {
+        return available;
+    }
+
+    public void setAvailable(Boolean available) {
+        this.available = available;
+    }
+
+    @Override
+    public String toString() {
+        return "CardKeyValidationResult{" +
+                "available=" + available +
+                '}';
+    }
+}

+ 40 - 0
netflix-service/src/main/java/com/cyksj/server/recharge/dto/TaskResult.java

@@ -0,0 +1,40 @@
+package com.cyksj.server.recharge.dto;
+
+/**
+ * 任务查询结果
+ */
+public class TaskResult {
+    private String status;
+    private String result;
+
+    public TaskResult() {}
+
+    public TaskResult(String status, String result) {
+        this.status = status;
+        this.result = result;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getResult() {
+        return result;
+    }
+
+    public void setResult(String result) {
+        this.result = result;
+    }
+
+    @Override
+    public String toString() {
+        return "TaskResult{" +
+                "status='" + status + '\'' +
+                ", result='" + result + '\'' +
+                '}';
+    }
+}

+ 40 - 0
netflix-service/src/main/java/com/cyksj/server/recharge/dto/TaskSubmitResult.java

@@ -0,0 +1,40 @@
+package com.cyksj.server.recharge.dto;
+
+/**
+ * 任务提交结果
+ */
+public class TaskSubmitResult {
+    private String taskId;
+    private Boolean success;
+
+    public TaskSubmitResult() {}
+
+    public TaskSubmitResult(String taskId, Boolean success) {
+        this.taskId = taskId;
+        this.success = success;
+    }
+
+    public String getTaskId() {
+        return taskId;
+    }
+
+    public void setTaskId(String taskId) {
+        this.taskId = taskId;
+    }
+
+    public Boolean getSuccess() {
+        return success;
+    }
+
+    public void setSuccess(Boolean success) {
+        this.success = success;
+    }
+
+    @Override
+    public String toString() {
+        return "TaskSubmitResult{" +
+                "taskId='" + taskId + '\'' +
+                ", success=" + success +
+                '}';
+    }
+}

+ 40 - 0
netflix-service/src/main/java/com/cyksj/server/recharge/dto/TokenParseResult.java

@@ -0,0 +1,40 @@
+package com.cyksj.server.recharge.dto;
+
+/**
+ * 凭证解析结果
+ */
+public class TokenParseResult {
+    private String message;
+    private Boolean success;
+
+    public TokenParseResult() {}
+
+    public TokenParseResult(String message, Boolean success) {
+        this.message = message;
+        this.success = success;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public Boolean getSuccess() {
+        return success;
+    }
+
+    public void setSuccess(Boolean success) {
+        this.success = success;
+    }
+
+    @Override
+    public String toString() {
+        return "TokenParseResult{" +
+                "message='" + message + '\'' +
+                ", success=" + success +
+                '}';
+    }
+}

+ 139 - 0
netflix-service/src/main/java/com/cyksj/server/recharge/impl/GptProxyRechargeServiceImpl.java

@@ -0,0 +1,139 @@
+package com.cyksj.server.recharge.impl;
+
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.cyksj.server.recharge.GptProxyRechargeService;
+import com.cyksj.server.recharge.dto.*;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author chan
+ * @date 2025/7/30 18:55
+ */
+@Slf4j
+@Service
+public class GptProxyRechargeServiceImpl implements GptProxyRechargeService {
+
+    private static final String BASE_URL = "https://api.ow520.com/api";
+
+    private HttpRequest createBaseRequest(String uri) {
+        return HttpRequest.get(BASE_URL + uri)
+                .header("accept", "application/json, text/plain, */*")
+                .header("accept-language", "zh-CN,zh;q=0.9,en;q=0.8")
+                .header("origin", "https://www.ow520.com")
+                .header("referer", "https://www.ow520.com/")
+                .header("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36");
+    }
+
+    public CardKeyValidationResult validateCardKey(String cardKey) {
+        log.info("开始验证卡密: {}", cardKey);
+        try {
+            HttpResponse response = createBaseRequest("/card-keys/" + cardKey)
+                    .execute();
+            String body = response.body();
+            log.info("卡密验证响应: {}", body);
+            
+            JSONObject jsonResponse = JSONUtil.parseObj(body);
+            CardKeyValidationResult result = new CardKeyValidationResult(
+                jsonResponse.getBool("available")
+            );
+            //{"available":false,"error":"卡密已被使用"}
+            log.info("卡密验证结果: {}", result);
+            return result;
+        } catch (Exception e) {
+            log.error("验证卡密失败: {}", e.getMessage(), e);
+            throw new RuntimeException("验证卡密失败: " + e.getMessage(), e);
+        }
+    }
+
+    public TokenParseResult parseToken(String accessToken) {
+        log.info("开始验证凭证: {}", accessToken.substring(0, Math.min(20, accessToken.length())) + "...");
+        try {
+            String url = BASE_URL + "/parse-token";
+            JSONObject requestBody = new JSONObject();
+            requestBody.put("access_token", accessToken);
+            
+            HttpResponse response = HttpRequest.post(url)
+                    .header("accept", "application/json, text/plain, */*")
+                    .header("accept-language", "zh-CN,zh;q=0.9,en;q=0.8")
+                    .header("content-type", "application/json")
+                    .header("origin", "https://www.ow520.com")
+                    .header("referer", "https://www.ow520.com/")
+                    .header("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36")
+                    .body(requestBody.toString())
+                    .execute();
+            String body = response.body();
+            log.info("凭证验证响应: {}", body);
+            
+            JSONObject jsonResponse = JSONUtil.parseObj(body);
+            TokenParseResult result = new TokenParseResult(
+                jsonResponse.getStr("message"),
+                jsonResponse.getBool("success")
+            );
+            log.info("凭证验证结果: {}", result);
+            return result;
+        } catch (Exception e) {
+            log.error("验证凭证失败: {}", e.getMessage(), e);
+            throw new RuntimeException("验证凭证失败: " + e.getMessage(), e);
+        }
+    }
+
+    public TaskSubmitResult submitTask(String cardKey, String accessToken, String idp) {
+        log.info("开始提交任务 - 卡密: {}, idp: {}", cardKey, idp);
+        try {
+            String url = BASE_URL + "/tasks";
+            JSONObject requestBody = new JSONObject();
+            requestBody.put("card_key", cardKey);
+            requestBody.put("access_token", accessToken);
+            requestBody.put("idp", idp);
+            
+            HttpResponse response = HttpRequest.post(url)
+                    .header("accept", "application/json, text/plain, */*")
+                    .header("accept-language", "zh-CN,zh;q=0.9,en;q=0.8")
+                    .header("content-type", "application/json")
+                    .header("origin", "https://www.ow520.com")
+                    .header("referer", "https://www.ow520.com/")
+                    .header("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36")
+                    .body(requestBody.toString())
+                    .execute();
+            String body = response.body();
+            log.info("任务提交响应: {}", body);
+            
+            JSONObject jsonResponse = JSONUtil.parseObj(body);
+            TaskSubmitResult result = new TaskSubmitResult(
+                jsonResponse.getStr("task_id"),
+                jsonResponse.getBool("success")
+            );
+            log.info("任务提交结果: {}", result);
+            return result;
+        } catch (Exception e) {
+            log.error("提交任务失败: {}", e.getMessage(), e);
+            throw new RuntimeException("提交任务失败: " + e.getMessage(), e);
+        }
+    }
+
+    public TaskResult getTaskResult(String taskId) {
+        log.info("开始查询任务结果: {}", taskId);
+        try {
+            String uri = "/tasks/" + taskId;
+            HttpResponse response = createBaseRequest(uri)
+                    .execute();
+            String body = response.body();
+            log.info("任务查询响应: {}", body);
+            
+            JSONObject jsonResponse = JSONUtil.parseObj(body);
+            TaskResult result = new TaskResult(
+                jsonResponse.getStr("status"),
+                jsonResponse.getStr("result")
+            );
+            log.info("任务查询结果: {}", result);
+            return result;
+        } catch (Exception e) {
+            log.error("获取任务结果失败: {}", e.getMessage(), e);
+            throw new RuntimeException("获取任务结果失败: " + e.getMessage(), e);
+        }
+    }
+}

+ 60 - 0
netflix-web/src/main/java/com/cyksj/web/controller/recharge/GptRechargeController.java

@@ -0,0 +1,60 @@
+package com.cyksj.web.controller.recharge;
+
+import com.cyksj.server.recharge.GptProxyRechargeService;
+import com.cyksj.server.recharge.dto.CardKeyValidationResult;
+import com.cyksj.server.recharge.dto.TaskResult;
+import com.cyksj.server.recharge.dto.TaskSubmitResult;
+import com.cyksj.server.recharge.dto.TokenParseResult;
+import com.cyksj.web.controller.recharge.req.ParseTokenRequest;
+import com.cyksj.web.controller.recharge.req.SubmitTaskRequest;
+import com.cyksj.web.controller.recharge.req.ValidateCardRequest;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * GPT代理充值控制器
+ */
+@RestController
+@RequestMapping("/api/gpt-recharge")
+@RequiredArgsConstructor
+@CrossOrigin(origins = "*")
+public class GptRechargeController {
+
+    private final GptProxyRechargeService gptProxyRechargeService;
+
+    /**
+     * 验证卡密
+     */
+    @PostMapping("/validate-card")
+    public CardKeyValidationResult validateCard(@RequestBody ValidateCardRequest request) {
+        return gptProxyRechargeService.validateCardKey(request.getCardKey());
+    }
+
+    /**
+     * 验证凭证
+     */
+    @PostMapping("/parse-token")
+    public TokenParseResult parseToken(@RequestBody ParseTokenRequest request) {
+        return gptProxyRechargeService.parseToken(request.getAccessToken());
+    }
+
+    /**
+     * 提交任务
+     */
+    @PostMapping("/submit-task")
+    public TaskSubmitResult submitTask(@RequestBody SubmitTaskRequest request) {
+        return gptProxyRechargeService.submitTask(
+            request.getCardKey(), 
+            request.getAccessToken(), 
+            request.getIdp()
+        );
+    }
+
+    /**
+     * 查询任务状态
+     */
+    @GetMapping("/task-status/{taskId}")
+    public TaskResult getTaskStatus(@PathVariable String taskId) {
+        return gptProxyRechargeService.getTaskResult(taskId);
+    }
+}

+ 14 - 0
netflix-web/src/main/java/com/cyksj/web/controller/recharge/req/ParseTokenRequest.java

@@ -0,0 +1,14 @@
+package com.cyksj.web.controller.recharge.req;
+
+import lombok.Data;
+
+/**
+ * @author chan
+ * @date 2025/7/31 10:33
+ */
+@Data
+public class ParseTokenRequest {
+
+    private String accessToken;
+
+}

+ 16 - 0
netflix-web/src/main/java/com/cyksj/web/controller/recharge/req/SubmitTaskRequest.java

@@ -0,0 +1,16 @@
+package com.cyksj.web.controller.recharge.req;
+
+import lombok.Data;
+
+/**
+ * @author chan
+ * @date 2025/7/31 10:34
+ */
+@Data
+public class SubmitTaskRequest {
+
+    private String cardKey;
+    private String accessToken;
+    private String idp = "auth0";
+
+}

+ 14 - 0
netflix-web/src/main/java/com/cyksj/web/controller/recharge/req/ValidateCardRequest.java

@@ -0,0 +1,14 @@
+package com.cyksj.web.controller.recharge.req;
+
+import lombok.Data;
+
+/**
+ * @author chan
+ * @date 2025/7/31 10:32
+ */
+@Data
+public class ValidateCardRequest {
+
+    private String cardKey;
+
+}

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 0
netflix-web/src/main/resources/application-dev.yml


+ 395 - 0
netflix-web/src/main/resources/static/gpt-recharge.html

@@ -0,0 +1,395 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>GPT账户充值</title>
+    <style>
+        * {
+            margin: 0;
+            padding: 0;
+            box-sizing: border-box;
+        }
+
+        body {
+            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+            min-height: 100vh;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            padding: 20px;
+        }
+
+        .container {
+            background: white;
+            border-radius: 16px;
+            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
+            padding: 40px;
+            width: 100%;
+            max-width: 500px;
+            text-align: center;
+        }
+
+        .title {
+            font-size: 28px;
+            font-weight: 600;
+            color: #333;
+            margin-bottom: 30px;
+        }
+
+        .step {
+            display: none;
+        }
+
+        .step.active {
+            display: block;
+        }
+
+        .input-group {
+            margin-bottom: 20px;
+            text-align: left;
+        }
+
+        .input-group label {
+            display: block;
+            margin-bottom: 8px;
+            font-weight: 500;
+            color: #555;
+        }
+
+        .input-group input, .input-group textarea {
+            width: 100%;
+            padding: 12px 16px;
+            border: 2px solid #e1e5e9;
+            border-radius: 8px;
+            font-size: 16px;
+            transition: border-color 0.3s;
+        }
+
+        .input-group input:focus, .input-group textarea:focus {
+            outline: none;
+            border-color: #667eea;
+        }
+
+        .input-group textarea {
+            height: 120px;
+            resize: vertical;
+        }
+
+        .btn {
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+            color: white;
+            border: none;
+            padding: 14px 28px;
+            border-radius: 8px;
+            font-size: 16px;
+            font-weight: 600;
+            cursor: pointer;
+            transition: transform 0.2s, box-shadow 0.2s;
+            margin: 10px;
+        }
+
+        .btn:hover {
+            transform: translateY(-2px);
+            box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
+        }
+
+        .btn:disabled {
+            background: #ccc;
+            cursor: not-allowed;
+            transform: none;
+            box-shadow: none;
+        }
+
+        .btn-secondary {
+            background: #6c757d;
+        }
+
+        .btn-secondary:hover {
+            box-shadow: 0 8px 25px rgba(108, 117, 125, 0.4);
+        }
+
+        .info-box {
+            background: #f8f9fa;
+            border: 1px solid #e9ecef;
+            border-radius: 8px;
+            padding: 20px;
+            margin: 20px 0;
+            text-align: left;
+        }
+
+        .info-box h4 {
+            color: #495057;
+            margin-bottom: 10px;
+        }
+
+        .info-box p {
+            color: #6c757d;
+            line-height: 1.5;
+        }
+
+        .status {
+            display: inline-block;
+            padding: 6px 12px;
+            border-radius: 20px;
+            font-size: 14px;
+            font-weight: 500;
+            margin: 10px 0;
+        }
+
+        .status.processing {
+            background: #fff3cd;
+            color: #856404;
+        }
+
+        .status.completed {
+            background: #d4edda;
+            color: #155724;
+        }
+
+        .loading {
+            display: inline-block;
+            width: 20px;
+            height: 20px;
+            border: 3px solid #f3f3f3;
+            border-top: 3px solid #667eea;
+            border-radius: 50%;
+            animation: spin 1s linear infinite;
+            margin-left: 10px;
+        }
+
+        @keyframes spin {
+            0% { transform: rotate(0deg); }
+            100% { transform: rotate(360deg); }
+        }
+
+        .success-message {
+            background: #d4edda;
+            color: #155724;
+            padding: 20px;
+            border-radius: 8px;
+            margin: 20px 0;
+            font-size: 18px;
+            font-weight: 600;
+        }
+
+        .error-message {
+            background: #f8d7da;
+            color: #721c24;
+            padding: 15px;
+            border-radius: 8px;
+            margin: 20px 0;
+        }
+    </style>
+</head>
+<body>
+    <div class="container">
+        <h1 class="title">GPT账户充值</h1>
+
+        <!-- 步骤1: 验证卡密 -->
+        <div id="step1" class="step active">
+            <div class="input-group">
+                <label for="cardKey">请输入卡密:</label>
+                <input type="text" id="cardKey" placeholder="输入卡密" />
+            </div>
+            <button class="btn" onclick="validateCard()">验证卡密</button>
+            <div id="cardError" class="error-message" style="display: none;"></div>
+        </div>
+
+        <!-- 步骤2: 验证凭证 -->
+        <div id="step2" class="step">
+            <div class="input-group">
+                <label for="accessToken">请输入Access Token:</label>
+                <textarea id="accessToken" placeholder="粘贴您的Access Token"></textarea>
+            </div>
+            <button class="btn" onclick="parseToken()">验证凭证</button>
+            <button class="btn btn-secondary" onclick="goBack(1)">返回</button>
+            <div id="tokenError" class="error-message" style="display: none;"></div>
+        </div>
+
+        <!-- 步骤3: 确认信息 -->
+        <div id="step3" class="step">
+            <div class="info-box">
+                <h4>账户信息</h4>
+                <p>邮箱: <span id="userEmail"></span></p>
+                <p>卡密: <span id="confirmCardKey"></span></p>
+            </div>
+            <p>请确认以上信息无误后点击确认充值</p>
+            <button class="btn" onclick="submitTask()">确认充值</button>
+            <button class="btn btn-secondary" onclick="goBack(2)">取消</button>
+            <div id="submitError" class="error-message" style="display: none;"></div>
+        </div>
+
+        <!-- 步骤4: 充值进度 -->
+        <div id="step4" class="step">
+            <h3>充值进行中...</h3>
+            <div id="taskStatus" class="status processing">处理中<span class="loading"></span></div>
+            <div id="taskResult"></div>
+        </div>
+    </div>
+
+    <script>
+        const API_BASE = '/api/gpt-recharge';
+        let currentCardKey = '';
+        let currentAccessToken = '';
+        let currentTaskId = '';
+        let pollingInterval = null;
+
+        // 显示指定步骤
+        function showStep(stepNumber) {
+            document.querySelectorAll('.step').forEach(step => {
+                step.classList.remove('active');
+            });
+            document.getElementById(`step${stepNumber}`).classList.add('active');
+        }
+
+        // 返回上一步
+        function goBack(stepNumber) {
+            showStep(stepNumber);
+            // 清理轮询
+            if (pollingInterval) {
+                clearInterval(pollingInterval);
+                pollingInterval = null;
+            }
+        }
+
+        // 显示错误信息
+        function showError(elementId, message) {
+            const errorElement = document.getElementById(elementId);
+            errorElement.textContent = message;
+            errorElement.style.display = 'block';
+            setTimeout(() => {
+                errorElement.style.display = 'none';
+            }, 5000);
+        }
+
+        // 验证卡密
+        async function validateCard() {
+            const cardKey = document.getElementById('cardKey').value.trim();
+            if (!cardKey) {
+                showError('cardError', '请输入卡密');
+                return;
+            }
+
+            try {
+                const response = await fetch(`${API_BASE}/validate-card`, {
+                    method: 'POST',
+                    headers: {
+                        'Content-Type': 'application/json',
+                    },
+                    body: JSON.stringify({ cardKey: cardKey })
+                });
+
+                const result = await response.json();
+                
+                if (result.available) {
+                    currentCardKey = cardKey;
+                    showStep(2);
+                } else {
+                    showError('cardError', '卡密无效或已使用');
+                }
+            } catch (error) {
+                showError('cardError', '验证失败,请稍后重试');
+                console.error('验证卡密失败:', error);
+            }
+        }
+
+        // 验证凭证
+        async function parseToken() {
+            const accessToken = document.getElementById('accessToken').value.trim();
+            if (!accessToken) {
+                showError('tokenError', '请输入Access Token');
+                return;
+            }
+
+            try {
+                const response = await fetch(`${API_BASE}/parse-token`, {
+                    method: 'POST',
+                    headers: {
+                        'Content-Type': 'application/json',
+                    },
+                    body: JSON.stringify({ accessToken: accessToken })
+                });
+
+                const result = await response.json();
+                
+                if (result.success) {
+                    currentAccessToken = accessToken;
+                    document.getElementById('userEmail').textContent = result.message;
+                    document.getElementById('confirmCardKey').textContent = currentCardKey;
+                    showStep(3);
+                } else {
+                    showError('tokenError', result.message || '凭证验证失败');
+                }
+            } catch (error) {
+                showError('tokenError', '验证失败,请稍后重试');
+                console.error('验证凭证失败:', error);
+            }
+        }
+
+        // 提交任务
+        async function submitTask() {
+            try {
+                const response = await fetch(`${API_BASE}/submit-task`, {
+                    method: 'POST',
+                    headers: {
+                        'Content-Type': 'application/json',
+                    },
+                    body: JSON.stringify({
+                        cardKey: currentCardKey,
+                        accessToken: currentAccessToken,
+                        idp: 'auth0'
+                    })
+                });
+
+                const result = await response.json();
+                
+                if (result.success && result.taskId) {
+                    currentTaskId = result.taskId;
+                    showStep(4);
+                    startPolling();
+                } else {
+                    showError('submitError', '提交任务失败');
+                }
+            } catch (error) {
+                showError('submitError', '提交失败,请稍后重试');
+                console.error('提交任务失败:', error);
+            }
+        }
+
+        // 开始轮询任务状态
+        function startPolling() {
+            pollingInterval = setInterval(async () => {
+                try {
+                    const response = await fetch(`${API_BASE}/task-status/${currentTaskId}`);
+                    const result = await response.json();
+                    
+                    const statusElement = document.getElementById('taskStatus');
+                    const resultElement = document.getElementById('taskResult');
+                    
+                    if (result.status === 'processing') {
+                        statusElement.className = 'status processing';
+                        statusElement.innerHTML = '处理中<span class="loading"></span>';
+                    } else if (result.status === 'completed') {
+                        statusElement.className = 'status completed';
+                        statusElement.innerHTML = '已完成';
+                        resultElement.innerHTML = '<div class="success-message">🎉 充值成功!</div>';
+                        
+                        // 停止轮询
+                        clearInterval(pollingInterval);
+                        pollingInterval = null;
+                    }
+                } catch (error) {
+                    console.error('查询任务状态失败:', error);
+                }
+            }, 5000); // 每5秒查询一次
+        }
+
+        // 页面加载完成后的初始化
+        document.addEventListener('DOMContentLoaded', function() {
+            console.log('GPT充值页面加载完成');
+        });
+    </script>
+</body>
+</html>

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff