首页 > 建站‧营销

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>

本文链接:https://www.zhanque.net/cms/3136.html