diff --git a/README.md b/README.md index e0e181a..942eeaf 100644 --- a/README.md +++ b/README.md @@ -3,20 +3,34 @@ ## [English](README_EN.md) -# 7月22日更新后,需登录一次账号,F12查看sess码,使用sess码进行查询 +## 7月29日更新(点个star吧) -7月22日更新后,已删除key校验规则,需使用sess码进行查询。使用key只能查询总额度、绑卡、GPT4和组织ID。 +1. 新增GPT-3.5查询、绑卡信息(人名和地址)、组织名称、邮箱、组织ID、是否有效; +2. 使用sk查询不再整体报错,而是展示可以查询到的内容; + +### sess查询示例(120刀4.0key) + +![1690562370550.png](https://cdn-img.czl.net/2023/07/29/64c3ef5003257.png) + +### sk查询示例(120刀4.0key) + +![1690562289330.png](https://cdn-img.czl.net/2023/07/29/64c3eefec26cd.png) + +### sk查询示例(5刀未绑卡key) + +![1690562178945.png](https://cdn-img.czl.net/2023/07/29/64c3ee9070310.png) + +## 7月22日更新后,如要查看完整信息,需登录一次账号,F12查看sess码,使用sess码进行查询 + +7月22日更新后,已删除key校验规则,需使用sess码进行查询。使用key只能查询部分信息。 ![1689957580942.png](https://cdn-img.czl.net/2023/07/22/64bab4daba587.png) -# SESS ID获取方法 +## SESS ID获取方法 请见我的个人博客,提供视频教程:https://woodchen.ink/1266.html -# 查询示例图 -![1688789680187.png](https://cdn-img.czl.net/2023/07/08/64a8e2b180068.png) - -# 支持自定义反代接口 +## 支持自定义反代接口 在第361行添加自己的接口代码 ``` html @@ -25,16 +39,12 @@ ## 反代代码示例 ![image](https://github.com/woodchen-ink/openai-billing-query/assets/95951386/0bcdb51b-de08-49bc-bd01-5bf731f53d02) -# 怎么部署 -什么?这还用问?下载index.html直接打开就行,除了背景图片,没有任何外部资源。 +## 怎么部署 +下载index.html直接打开就行,除了背景图片,没有任何外部资源。 -# 开发过程 -首先感谢Github上开源的几个查询代码,是基于他们的项目使用GPT4进行改的,全程我只手动改了几个css。 -# 广告 +## 广告 - [CZL Chat](https://chat.czl.net),稳定商业版AI服务。 - [CZLOapi](https://oapi.czl.net),OPENAI代理服务,无需翻墙。 - -# 广告 -个人博客:https://woodchen.ink +- 个人博客:https://woodchen.ink diff --git a/image.png b/image.png new file mode 100644 index 0000000..ed529da Binary files /dev/null and b/image.png differ diff --git a/index.html b/index.html index d8f2314..5356337 100644 --- a/index.html +++ b/index.html @@ -5,7 +5,7 @@ OpenAIAPI 信息查询 - +

OpenAI API 信息查询

-

7月22日更新后,需使用sess码进行查询。使用key只能查询总额度、绑卡、GPT4和组织ID。

-

Oapi的余额查询

+

7月22日更新后,需使用sess码进行查询。使用key只能查询总额度、绑卡、GPT4和组织ID。 +

+ +

Oapi的余额查询

+
@@ -350,7 +358,8 @@

输入 API KEY

本站不保存 KEY 信息,查询后请自行保存

-

+

@@ -364,7 +373,7 @@ - +

@@ -373,16 +382,19 @@ 序号 - API KEY - 总额度 + API KEY + 总额度 已使用 剩余量 已用比例 到期时间 + GPT-3.5 GPT-4 32K 绑卡 - 组织ID + 绑卡信息 + 组织名称+邮箱+ID + 是否有效 @@ -398,15 +410,16 @@ let queriedApiKeys = []; let serialNumber = 1; + async function checkBilling(apiKey, apiUrl) { - // 计算起始日期和结束日期,当前为 90 天,最大不超过100天 const now = new Date(); let startDate = new Date(now - 90 * 24 * 60 * 60 * 1000); const endDate = new Date(now.getTime() + 24 * 60 * 60 * 1000); const subDate = new Date(now); subDate.setDate(1); - // 设置API请求URL和请求头 + + const headers = { "Authorization": "Bearer " + apiKey, "Content-Type": "application/json" @@ -414,62 +427,98 @@ const gpt4Check = `${apiUrl}/v1/models`; const urlSubscription = `${apiUrl}/v1/dashboard/billing/subscription`; let urlUsage = `${apiUrl}/v1/dashboard/billing/usage?start_date=${formatDate(startDate)}&end_date=${formatDate(endDate)}`; - const urlsetid = apiUrl + '/v1/organizations'; //查组织id + const urlsetid = apiUrl + '/v1/organizations'; + + + try { - // 获取API限额 + let totalAmount, totalUsage, remaining, GPT35CheckResult, GPT4CheckResult, GPT432kCheckResult, setid, isSubscrible; + let SubscribleInformation = {}; + let SubInformation; + let errors = {}; + let response = await fetch(urlSubscription, { headers }); - if (!response.ok) { - console.log("APIKEY 错误或账号被封,请登录 OpenAI 查看。"); - return; - } let currentDate = new Date(); const subscriptionData = await response.json(); - const totalAmount = subscriptionData.system_hard_limit_usd; + console.log("1:" + subscriptionData); const expiryDate = new Date(subscriptionData.access_until * 1000 + 8 * 60 * 60 * 1000); const formattedDate = `${expiryDate.getFullYear()}-${(expiryDate.getMonth() + 1).toString().padStart(2, '0')}-${expiryDate.getDate().toString().padStart(2, '0')}`; - const gpt4CheckResponse = await fetch(gpt4Check, { headers }); - const gpt4CheckData = await gpt4CheckResponse.json(); - let GPT4CheckResult = Array.isArray(gpt4CheckData.data) && gpt4CheckData.data.some(item => item.id.includes('gpt-4')) ? '✅' : '❌'; - let GPT432kCheckResult = Array.isArray(gpt4CheckData.data) && gpt4CheckData.data.some(item => item.id.includes('gpt-4-32k')) ? '✅' : '❌'; + const modelsCheckResponse = await fetch(modelsCheck, { headers }); + const modelsCheckData = await modelsCheckResponse.json(); + let GPT35CheckSuccess = GPT35CheckResult = Array.isArray(modelsCheckData.data) && modelsCheckData.data.some(item => item.id.includes('gpt-3.5-turbo')) ? '✅' : '❌'; + let GPT4CheckResult = Array.isArray(modelsCheckData.data) && modelsCheckData.data.some(item => item.id.includes('gpt-4')) ? '✅' : '❌'; + let GPT432kCheckResult = Array.isArray(modelsCheckData.data) && modelsCheckData.data.some(item => item.id.includes('gpt-4-32k')) ? '✅' : '❌'; let isSubscrible = subscriptionData.plan.id.includes('payg') ? '✅' : '❌'; - if (totalAmount > 20) { - startDate = subDate; - urlUsage = `${apiUrl}/v1/dashboard/billing/usage?start_date=${formatDate(startDate)}&end_date=${formatDate(endDate)}`; + if (totalAmount > 20) { + startDate = subDate; + urlUsage = `${apiUrl}/v1/dashboard/billing/usage?start_date=${formatDate(startDate)}&end_date=${formatDate(endDate)}`; + response = await fetch(urlUsage, { headers }); + const usageData = await response.json(); + } response = await fetch(urlUsage, { headers }); const usageData = await response.json(); + totalUsage = usageData.total_usage / 100; + remaining = currentDate > expiryDate ? "❌过期" : (totalAmount - totalUsage).toFixed(3); + } catch (error) { + console.error(error); + errors['subscription'] = error.message; + } + //获取是否绑卡 + try { + isSubscrible = subscriptionData.plan.id.includes('payg') ? '✅' : '❌'; + } catch (error) { + console.error(error); + } + //获取绑卡信息 + try { + // 从 subscriptionData 中获取 SubscribleInformation 的值... + SubscribleInformation.account_name = subscriptionData.account_name; + SubscribleInformation.po_number = subscriptionData.po_number; + SubscribleInformation.billing_email = subscriptionData.billing_email; + SubscribleInformation.tax_ids = subscriptionData.tax_ids; + + let billingAddress = subscriptionData.billing_address; // 定义并赋值 billingAddress + let businessAddress = subscriptionData.business_address; // 定义并赋值 businessAddress + + SubInformation = "Account Name: " + SubscribleInformation.account_name + "---"; + SubInformation += "PO Number: " + SubscribleInformation.po_number + "---"; + SubInformation += "Billing Email: " + SubscribleInformation.billing_email + "---"; + SubInformation += "Tax IDs: " + SubscribleInformation.tax_ids + "---"; + SubInformation += "Billing Address: " + billingAddress.line1 + ", " + billingAddress.city + ", " + billingAddress.state + ", " + billingAddress.country + ", " + billingAddress.postal_code + "---"; + SubInformation += "Business Address: " + businessAddress.line1 + ", " + businessAddress.city + ", " + businessAddress.state + ", " + businessAddress.country + ", " + businessAddress.postal_code; + } + catch (error) { + console.error(error); + } + //组织信息 + try { + response = await fetch(urlsetid, { headers }); + const setiddata = await response.json(); + setid = ''; + const emailStartIndex = setiddata.data[0].description.lastIndexOf(' ') + 1; + const email = setiddata.data[0].description.substring(emailStartIndex); + if (typeof setiddata.data[1] !== 'undefined') { + setid = setiddata.data[0].title + '----' + email + '----' + setiddata.data[0].id + '----' + setiddata.data[1].id; + } else { + setid = setiddata.data[0].title + '----' + email + '----' + setiddata.data[0].id; + } + } catch (error) { + console.error(error); + errors['setid'] = error.message; } - response = await fetch(urlUsage, { headers }); - const usageData = await response.json(); - const totalUsage = usageData.total_usage / 100; - let remaining; - if (currentDate > expiryDate) { - remaining = "❌过期"; - } else { - remaining = subscriptionData.system_hard_limit_usd - totalUsage; - } - - //查询组织id - response = await fetch(urlsetid, { headers }); - const setiddata = await response.json(); - let setid = ''; - if (typeof setiddata.data[1] !== 'undefined') { - setid = setiddata.data[0].id + '----' + setiddata.data[1].id; - } else { - setid = setiddata.data[0].id; - } - - return [totalAmount, totalUsage, remaining, formattedDate, GPT4CheckResult, GPT432kCheckResult,isSubscrible, setid]; + return [totalAmount, totalUsage, remaining, formattedDate, GPT35CheckResult, GPT4CheckResult, GPT432kCheckResult,isSubscrible, setid]; } catch (error) { - console.error(error); - return ["Error", null, null, null, null,null, null, null]; + return ["Error", null, null, null, null, null, null, null]; } } + + function formatDate(date) { const year = date.getFullYear(); const month = (date.getMonth() + 1).toString().padStart(2, '0'); @@ -478,6 +527,7 @@ return `${year}-${month}-${day}`; } + //查询函数 function sendRequest() { let apiKeyInput = document.getElementById("api-key-input"); let apiUrlSelect = document.getElementById("api-url-select"); @@ -529,6 +579,15 @@ queriedApiKeys.push(apiKey); checkBilling(apiKey, apiUrl).then((data) => { + data = data.map(item => { + if (item === undefined) { + return 'Not Found.' + } else { + return item + } + } + ) + let row = document.createElement("tr"); let serialNumberCell = document.createElement("td"); // 创建序列号单元格 @@ -536,38 +595,38 @@ row.appendChild(serialNumberCell); // 将序列号单元格添加到行中 let apiKeyCell = document.createElement("td"); - // apiKeyCell.textContent = apiKey.replace(/^(sk-[a-zA-Z0-9]{4})[a-zA-Z0-9]*(.{6})$/, "$1***$2"); apiKeyCell.textContent = apiKey.replace(/^(.{5}).*(.{4})$/, "$1***$2"); row.appendChild(apiKeyCell); - console.log(data); // 添加 console.log 以查看 data 的值 + console.log('查看查询结果', data); // 添加 console.log 以查看 data 的值 - if (data?.[0] === "Error" || data === undefined) { + if (data[0] === undefined) { let errorMessageCell = document.createElement("td"); errorMessageCell.colSpan = "8"; errorMessageCell.classList.add("status-error"); errorMessageCell.textContent = "不正确或已失效的API-KEY"; row.appendChild(errorMessageCell); } else { - let totalGrantedCell = document.createElement("td"); - totalGrantedCell.textContent = data[0].toFixed(2); - row.appendChild(totalGrantedCell); + let totalAmount = document.createElement("td"); + totalAmount.textContent = data[0]; + row.appendChild(totalAmount); let totalUsedCell = document.createElement("td"); - totalUsedCell.textContent = data[1].toFixed(2); + if (!isNaN(data[1])) { + totalUsedCell.textContent = data[1].toFixed(3); + } else { + totalUsedCell.textContent = '❌' + } row.appendChild(totalUsedCell); let totalAvailableCell = document.createElement("td"); - totalAvailableCell.textContent = typeof data[2] === 'number' ? data[2].toFixed(2) : data[2]; + totalAvailableCell.textContent = typeof data[2] === 'number' ? data[2] : data[2]; row.appendChild(totalAvailableCell); - - // 修改后的进度条单元格 let progressCell = document.createElement("td"); let progressContainer = document.createElement("div"); // 添加一个新的容器元素 progressContainer.style.width = "100%"; progressContainer.style.height = "20px"; progressContainer.style.backgroundColor = "#f3f3f3"; // 设置容器的背景色为灰白色 - let progressBar = document.createElement("div"); progressBar.style.width = (data[1] / data[0] * 100).toFixed(2) + "%"; progressBar.style.height = "20px"; @@ -577,7 +636,6 @@ progressBar.style.textAlign = "right"; // 设置文本对齐方式为右对齐 progressBar.style.paddingRight = "5px"; // 设置右边距以确保文本不超出边界 progressBar.style.color = "black"; // 设置文本颜色为白色 - progressContainer.appendChild(progressBar); // 将进度条添加到容器中 progressCell.appendChild(progressContainer); // 将容器添加到单元格中 row.appendChild(progressCell); @@ -599,11 +657,21 @@ isSubscribe.textContent = data[6]; row.appendChild(isSubscribe); - let setidCell = document.createElement("td"); - setidCell.textContent = data[7]; - row.appendChild(setidCell); - } + let SubInformation = document.createElement("td"); + SubInformation.textContent = data[8]; + row.appendChild(SubInformation); + let setidCell = document.createElement("td"); + setidCell.textContent = data[8]; + row.appendChild(setidCell); + + // 是否有效列 + let isSubscriptionValid = document.createElement("td"); + isSubscriptionValid.textContent = data[4] === '✅' ? '有效' : '无效'; // 使用 GPT35CheckResult 的值进行判断 + row.appendChild(isSubscriptionValid); + + } + console.log('查看行信息', row) tableBody.appendChild(row); if (i === apiKeys.length - 1) { @@ -612,32 +680,8 @@ serialNumber++; // 增加序列号 h2.style.display = 'block'; table.style.display = 'table'; + }) - }).catch((error) => { - console.error(error); - let row = document.createElement("tr"); - - let serialNumberCell = document.createElement("td"); // 创建序列号单元格 - serialNumberCell.textContent = serialNumber; // 设置序列号文本 - row.appendChild(serialNumberCell); // 将序列号单元格添加到行中 - let apiKeyCell = document.createElement("td"); - apiKeyCell.textContent = apiKey; - row.appendChild(apiKeyCell); - - let errorMessageCell = document.createElement("td"); - errorMessageCell.colSpan = "8"; - errorMessageCell.style.width = "90px"; - errorMessageCell.classList.add("status-error"); - errorMessageCell.textContent = "账户疑似被封禁,请登录 OpenAI 官网确认"; - row.appendChild(errorMessageCell); - - tableBody.appendChild(row); - - if (i === apiKeys.length - 1) { - queriedApiKeys = []; - } - serialNumber++; // 增加序列号 - }); } } @@ -656,4 +700,4 @@ - + \ No newline at end of file