ChatGPT API余额批量查询

    直接上代码,需要自行搭建反向代理:

    <!DOCTYPE html>
    
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>API-KEY信息查询</title>
        <style>
    
          table {
            margin: auto;
            border-collapse: collapse;
          }
          th,
          td {
            padding: 8px;
            text-align: center;
            color: #000000;
            border: 1px solid #000000;
          }
          th:first-child,
          td:first-child {
            width: 520px;
          }
          h1 {
            text-align: center;
            color: #000000;
          }
          form {
            display: flex;
            justify-content: center;
            align-items: center;
            margin-bottom: 20px;
          }
          textarea#api-key-input {
            width: 560px;
            font-size: 16px;
            padding: 10px;
            margin-right: 10px;
            border-radius: 5px;
            border: none;
            resize: vertical;
            rows: 8;
          }
          select#api-url-select,
          input#custom-url-input {
            width: 300px;
            height: 50px;
            font-size: 16px;
            background-color: #212121;
            border-radius: 5px;
            color: #ffffff;
            border: none;
            margin-right: 10px;
          }
          input#custom-url-input {
            display: none;
          }
          button {
            height: 50px;
            font-size: 16px;
            background-color: #ff8c00;
            color: #ffffff;
            border: none;
            border-radius: 5px;
            cursor: pointer;
          }
          .status-ok {
            color: #2d8d2d;
          }
          .status-error {
            color: #ed0808;
          }
          tr:nth-child(even) {
            /* 将偶数行背景色改为深蓝色 */
            background-color: #f1d39c;
          }
          tr:nth-child(odd) {
            /* 将偶数行背景色改为深蓝色 */
            background-color: #f1d39c;
          }
    
    
    
    
        </style>
    
    <style>
    body {
        background: url('/static/css/31.jpg') no-repeat center center fixed; /*自定义背景图*/
        background-size: cover;
        background-color: #f5f5f5;
        display: flex; justify-content: center; align-items: center; height: 90vh;
    }
    
    .content {
        width: 100%;
        max-width: 1100px;
        margin: auto;
        padding: 40px;
        border-radius: 8px;
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        background-color: rgba(0, 0, 0, 0.63);
    }
    
    .container {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 50vh;
    }
    
    h1 {
        text-align: center;
        font-size: 36px;
        margin-bottom: 30px;
    }
    
    form {
        display: flex;
        justify-content: center;
        align-items: center;
        flex-wrap: wrap;
    }
    
    label {
        font-size: 24px;
        color: #ff089e;
        margin-right: 10px;
    }
    
    input[type="text"] {
        border: 2px solid #ddd;
        border-radius: 6px;
        padding: 12px 16px;
        font-size: 16px;
        background-color: #f9f9f9;
        margin-right: 10px;
        flex: 1;
        transition: border-color 0.3s ease;
    }
    
    input[type="text"]:focus {
        outline: none;
        border-color: #4299e5;
    }
    
    
    button[type="submit"] {
        background-color: #4299e5;
        color: #fff;
        border: none;
        border-radius: 8px;
        font-size: 16px;
        padding: 14px 28px;
        cursor: pointer;
        transition: all 0.3s ease;
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    }
    
    button[type="submit"]:hover,
    button[type="submit"]:focus {
        background-color: #357dbf;
        outline: none;
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
    }
    
    
    
    .grid {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
        grid-gap: 20px;
        margin-top: 40px;
    }
    
    .grid-item {
        padding: 20px;
        border-radius: 8px;
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        text-align: center;
        transition: transform 0.3s ease;
        background-color:#fff;
    }
    
    .grid-item:hover {
        transform: translateY(-10px);
    }
    
    .grid-item p:nth-child(1) {
        font-size: 28px;
        font-weight: bold;
        margin-bottom: 10px;
        color: #4299e5;
        animation: pulse 1s ease-in-out infinite alternate;
    }
    
    .grid-item p:nth-child(2) {
        font-size: 16px;
        color: #666;
    }
    
    @keyframes pulse {
        from {
            opacity: 0.6;
            transform: scale(1);
        }
        to {
            opacity: 1;
            transform: scale(1.2);
        }
    }
    .text-gradient {
        background-image: linear-gradient(to right, #4299e5, #00c458);
        -webkit-background-clip: text;
        color: transparent;
    }
    
    .text-gradient {
      animation: gradient-animation 2s linear infinite;
      -webkit-background-clip: text;
      color: transparent;
    }
    
    @keyframes gradient-animation {
      from {background-image: linear-gradient(to right, #4299e5, #00c458);}
      to {background-image: linear-gradient(to right, #00c458, #4299e5);}
    }
    
    #result-table {
      border-collapse: collapse;
      width: 100%;
      margin-top: 20px;
      font-size: 14px;
    }
    
    #result-table th {
      background-color: #6fa83a;
      color: #000;
      font-weight: 400;
      height: 20px;
      /*padding: 10px 25px;*/
      text-align: center;
      border: 1px solid #090303;
    }
    
    #result-table td {
      
      height: 20px;
      
      text-align: center;
    }
    
    #result-table tbody tr:nth-child(even) {
      background-color: #f9f9f9;
    }
    
    #result-table .table-header {
      width: 25%;
    }
    
    #result-table .table-data {
      width: 25%;
      font-weight: bold;
      color: #333;
    }
    .form-group {
      margin-bottom: 1rem;
    }
    
    .form-control {
      font-family: inherit;
      font-size: 15px;
      display: block;
      width: 100%;
      height: calc(2.5rem + 2px);
      padding: 0.375rem 0.75rem;
      line-height: 1.5;
      color: #495057;
      background-color: #fff;
      border: 1px solid #ced4da;
      border-radius: 0.25rem;
      transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
    }
    
    .form-control:hover,
    .form-control:active,
    .form-control:focus {
      border-color: #80bdff;
      outline: 0;
      box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
    }
    
    .form-control::-webkit-input-placeholder {
      color: #999;
    }
    
    .form-control::-moz-placeholder {
      color: #999;
    }
    
    .form-control:-ms-input-placeholder {
      color: #999;
    }
    
    .form-control::-ms-input-placeholder {
      color: #999;
    }
    
    .form-control::placeholder {
      color: #999;
    }
    
    
    </style>
      </head>
      <body>
    <div class="content">
    <h1 class="text-3xl font-semibold text-center mb-8 text-gradient">API余额查询(批量)</h1>
        <form>
    <label for="api_key" class="w-28 mr-4 text-gradient">API密钥:</label>
          <textarea id="api-key-input" class="form-control" placeholder="每行一个秘钥"></textarea>
          <div style="display: none;">
            <select id="api-url-select">
              <option value="https://i.*.ltd">【反向代理接口】</option>
              <option value="https://api.openai.com">【官方查询接口】</option>
            </select>
          </div>
          <button type="button" style="display:inline-block; width: 100px;" onclick="sendRequest()">查询</button>
        </form>
        <table id="result-table">
          <thead>
            <tr>
              <th style="width: 40%">API KEY</th>
              <th style="width: 15%">总额度</th>
              <th style="width: 15%">已使用</th>
              <th style="width: 10%">剩余额度</th>
    		  <th style="width: 10%">开始日期</th>
    		  <th style="width: 10%">结束日期</th>
            </tr>
          </thead>
          <tbody></tbody>
        </table>
    </div>
    
    <script>
          // 定义查询过的API-KEY列表
          let queriedApiKeys = [];
    
          async function checkBilling(apiKey) {
            // 计算起始日期和结束日期
            const now = new Date();
            const startDate = new Date(now - 90 * 24 * 60 * 60 * 1000);
            const endDate = new Date(now.getTime() + 24 * 60 * 60 * 1000);
    
            // 设置API请求URL和请求头
            const urlSubscription = 'https://api.openai.com/v1/dashboard/billing/subscription'; // 查是否订阅
            const urlBalance = 'https://api.openai.com/dashboard/billing/credit_grants'; // 查普通账单
            const urlUsage = `https://api.openai.com/v1/dashboard/billing/usage?start_date=${formatDate(startDate)}&end_date=${formatDate(endDate)}`; // 查使用量
            const headers = {
              "Authorization": "Bearer " + apiKey,
              "Content-Type": "application/json"
            };
    
            try {
              // 获取API限额
              let response = await fetch(urlSubscription, {headers});
              if (!response.ok) {
                console.log("您的账户已被封禁,请登录OpenAI进行查看。");
                return;
              }
              const subscriptionData = await response.json();
              const totalAmount = subscriptionData.hard_limit_usd;
    
              // 获取已使用量
              response = await fetch(urlUsage, {headers});
              const usageData = await response.json();
              const totalUsage = usageData.total_usage / 100;
    
              // 计算剩余额度
              const remaining = totalAmount - totalUsage;
    
              // 输出总用量、总额及余额信息
              console.log(`Total Amount: ${totalAmount.toFixed(2)}`);
              console.log(`Used: ${totalUsage.toFixed(2)}`);
              console.log(`Remaining: ${remaining.toFixed(2)}`);
    
              return [totalAmount, totalUsage, remaining, startDateString, endDateString];
            } catch (error) {
              console.error(error);
              return [null, null, null];
            }
          }
    
          function formatDate(date) {
            const year = date.getFullYear();
            const month = (date.getMonth() + 1).toString().padStart(2, '0');
            const day = date.getDate().toString().padStart(2, '0');
    
            return `${year}-${month}-${day}`;
          }
    
          function sendRequest() {
            let apiKeyInput = document.getElementById("api-key-input");
            let apiUrlSelect = document.getElementById("api-url-select");
            let customUrlInput = document.getElementById("custom-url-input");
    
            if (apiKeyInput.value.trim() === "") {
              alert("请填写API KEY");
              return;
            }
    
            // 添加以下一行代码,清空之前的结果信息
            document.getElementById("result-table").getElementsByTagName('tbody')[0].innerHTML = "";
    
            let apiUrl = "";
            if (apiUrlSelect.value === "custom") {
              if (customUrlInput.value.trim() === "") {
                alert("请设置API链接");
                return;
              } else {
                apiUrl = customUrlInput.value.trim();
              }
            } else {
              apiUrl = apiUrlSelect.value;
            }
    
            let apiKeys = apiKeyInput.value.trim().split("\n");
    
            let tableBody = document.querySelector("#result-table tbody");
            for (let i = 0; i < apiKeys.length; i++) {
              let apiKey = apiKeys[i].trim();
              // 判断是否已经查询过
              if (queriedApiKeys.includes(apiKey)) {
                console.log(`API KEY ${apiKey} 已查询过,跳过此次查询`);
                continue;
              }
              queriedApiKeys.push(apiKey);
    
              checkBilling(apiKey).then((data) => {
                // update table with data
                let row = document.createElement("tr");
                // 隐藏API KEY部分信息
    			const hiddenApiKey = apiKey.substring(0, 7) + "*******************" + apiKey.substring(47);
    
                // API KEY
    			let apiKeyCell = document.createElement("td");
    			apiKeyCell.textContent = hiddenApiKey;
    			row.appendChild(apiKeyCell);
    
                if (data[0] === null) {
                  // ERROR MESSAGE
                  let errorMessageCell = document.createElement("td");
                  errorMessageCell.colSpan = "3";
                  errorMessageCell.classList.add("status-error");
                  errorMessageCell.textContent = "不正确或已失效的API-KEY";
                  row.appendChild(errorMessageCell);
                } else {
                  // TOTAL GRANTED
                  let totalGrantedCell = document.createElement("td");
                  totalGrantedCell.textContent = data[0].toFixed(2);
                  row.appendChild(totalGrantedCell);
    
                  // TOTAL USED
                  let totalUsedCell = document.createElement("td");
                  totalUsedCell.textContent = data[1].toFixed(2);
                  row.appendChild(totalUsedCell);
    
                  // TOTAL AVAILABLE
                  let totalAvailableCell = document.createElement("td");
                  totalAvailableCell.textContent = data[2].toFixed(2);
                  row.appendChild(totalAvailableCell);
    			  
                  // START DATE
                  let startDateCell = document.createElement("td");
                  startDateCell.textContent = data[3];
                  row.appendChild(startDateCell);
    			              
                  // END DATE
                  let endDateCell = document.createElement("td");
                  endDateCell.textContent = data[4];
                  row.appendChild(endDateCell);			  
                }
    			
    
                tableBody.appendChild(row);
    
                // 添加以下代码,查询完成后删除已查询的API-KEY
                if (i === apiKeys.length - 1) {
                  queriedApiKeys = [];
                }
              }).catch((error) => {
                console.error(error);
                // update table with error message
                let row = document.createElement("tr");
                let apiKeyCell = document.createElement("td");
                // 隐藏API KEY部分信息
                const hiddenApiKey = apiKey.substring(0, 7) + "*******************" + apiKey.substring(47);
                apiKeyCell.textContent = hiddenApiKey;
                row.appendChild(apiKeyCell);
    
                let errorMessageCell = document.createElement("td");
                errorMessageCell.colSpan = "3";
                errorMessageCell.style.width = "90px";
                errorMessageCell.classList.add("status-error");
                errorMessageCell.textContent =
                  "账户已被封禁,请登录OpenAI进行查看。";
                row.appendChild(errorMessageCell);
    
                tableBody.appendChild(row);
    
                // 添加以下代码,查询完成后删除已查询的API-KEY
                if (i === apiKeys.length - 1) {
                  queriedApiKeys = [];
                }
              });
            }
          }
    
          let apiUrlSelect = document.getElementById("api-url-select");
          let customUrlInput = document.getElementById("custom-url-input");
    
          apiUrlSelect.addEventListener("change", function () {
            if (apiUrlSelect.value === "custom") {
              customUrlInput.style.display = "inline-block";
              customUrlInput.style.marginTop = "5px";
            } else {
              customUrlInput.style.display = "none";
            }
          });
    </script>
    
    
    
    <script>
    
    function showLoader() {
        document.getElementById("loader").style.display = "inline-block";
    }
    
    function hideLoader() {
        document.getElementById("loader").style.display = "none";
    }
    
    function displayResult(data) {
        if (data.status === "success") {
            document.getElementById("result").innerHTML = `
                <div class="grid grid-cols-3 gap-4">
                    <div class="grid-item bg-gray-100 p-6 rounded-lg text-center">
                        <p class="text-2xl font-semibold">${data.total_granted}</p>
                        <p class="text-gray-600">总额度</p>
                    </div>
                    <div class="grid-item bg-gray-100 p-6 rounded-lg text-center">
                        <p class="text-2xl font-semibold">${parseFloat(data.total_used).toFixed(3)}</p>
                        <p class="text-gray-600">已使用额度</p>
                    </div>
                    <div class="grid-item bg-gray-100 p-6 rounded-lg text-center">
                        <p class="text-2xl font-semibold">${parseFloat(data.total_available).toFixed(3)}</p>
                        <p class="text-gray-600">剩余可用额度</p>
                    </div>
                    <div class="grid-item bg-gray-100 p-6 rounded-lg text-center">
                        <p class="text-2xl font-semibold">${data.total_startDate}</p>
                        <p class="text-gray-600">开始日期</p>
                    </div>
                    <div class="grid-item bg-gray-100 p-6 rounded-lg text-center">
                        <p class="text-2xl font-semibold">${data.total_endstartDate}</p>
                        <p class="text-gray-600">结束日期</p>
                    </div>				
                </div>
            `;
        } else {
            alert("您的账户已被封禁,请登录OpenAI进行查看。");
        }
    }
    
    function checkOpenAICredit() {
        var apiKey = document.getElementById("api_key").value;
    
        if (!apiKey.startsWith("sk-")) {
            alert("无效的API密钥,请检查您的API密钥是否正确。");
            return;
        }
    
        showLoader();
        checkBilling(apiKey)
        .then(data => {
            displayResult({
            status: "success",
            total_granted: data[0],
            total_used: data[1],
            total_available: data[2]
            });
            hideLoader();
        })
        .catch(error => {
            alert("您的账户已被封禁,请登录OpenAI进行查看。");
            hideLoader();
        });
    }
    
    async function checkBilling(apiKey) {
      // 计算起始日期和结束日期
      const now = new Date();
      const startDate = new Date(now - 90 * 24 * 60 * 60 * 1000);
      const endDate = new Date(now.getTime() + 24 * 60 * 60 * 1000);
    
      // 设置API请求URL和请求头
      const urlSubscription = 'https://i.*.ltd/v1/dashboard/billing/subscription'; // 查是否订阅
      const urlBalance = 'https://i.*.ltd/dashboard/billing/credit_grants'; // 查普通账单
      const urlUsage = `https://i.*.ltd/v1/dashboard/billing/usage?start_date=${formatDate(startDate)}&end_date=${formatDate(endDate)}`; // 查使用量
      const headers = {
        "Authorization": "Bearer " + apiKey,
        "Content-Type": "application/json"
      };
    
      try {
        // 获取API限额
        let response = await fetch(urlSubscription, {headers});
        if (!response.ok) {
          console.log("您的账户已被封禁,请登录OpenAI进行查看。");
          return;
        }
        const subscriptionData = await response.json();
        const totalAmount = subscriptionData.hard_limit_usd;
    
        // 获取已使用量
        response = await fetch(urlUsage, {headers});
        const usageData = await response.json();
        const totalUsage = usageData.total_usage / 100;
    
        // 计算剩余额度
        const remaining = totalAmount - totalUsage;
    	
    				
        // 计算开始时间和结束时间
        const endDateString = new Date(subscriptionData.access_until * 1000).toLocaleDateString();
        const startDateString = new Date(startDate).toLocaleDateString();
    
        // 输出总用量、总额及余额信息
        console.log(`Total Amount: ${totalAmount.toFixed(2)}`);
        console.log(`Used: ${totalUsage.toFixed(2)}`);
        console.log(`Remaining: ${remaining.toFixed(2)}`);
    
        return [totalAmount, totalUsage, remaining, startDateString, endDateString];
      } catch (error) {
        console.error(error);
        return [null, null, null];
      }
    }
    function formatDate(date) {
      const year = date.getFullYear();
      const month = (date.getMonth() + 1).toString().padStart(2, '0');
      const day = date.getDate().toString().padStart(2, '0');
      return `${year}-${month}-${day}`;
    }
    </script>
    
    
    </body>
    </html>