fix: 修复资源点余额查询一直返回0的问题
- 改为直接调用 StrangeLoop /api/credit/balance 接口 - 携带 JWT token 认证,绕开 Gateway 缺少接口的问题 - 使用 availableCredits 作为余额值 - 固定 5s 超时,避免阻塞发送前检查 - 401/403 单独提示登录过期 - 补充 json.msg 错误消息兜底
This commit is contained in:
@ -3,7 +3,11 @@
|
|||||||
* 负责缓存余额、主动查询、发送前检测
|
* 负责缓存余额、主动查询、发送前检测
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getCreditBalance } from './apiClient';
|
import * as vscode from 'vscode';
|
||||||
|
import * as https from 'https';
|
||||||
|
import * as http from 'http';
|
||||||
|
import { URL } from 'url';
|
||||||
|
import { getStrangeLoopApiUrl } from '../config/settings';
|
||||||
import { getCachedUserInfo } from './userService';
|
import { getCachedUserInfo } from './userService';
|
||||||
|
|
||||||
/** 低余额阈值 */
|
/** 低余额阈值 */
|
||||||
@ -43,22 +47,41 @@ function isCacheValid(): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 主动查询余额
|
* StrangeLoop 余额响应类型
|
||||||
|
*/
|
||||||
|
interface StrangeLoopBalanceResponse {
|
||||||
|
userId?: number;
|
||||||
|
availableCredits?: number;
|
||||||
|
totalCredits?: number;
|
||||||
|
error?: string;
|
||||||
|
message?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主动查询余额(直接调用 StrangeLoop 接口)
|
||||||
*/
|
*/
|
||||||
export async function fetchBalance(): Promise<number | null> {
|
export async function fetchBalance(): Promise<number | null> {
|
||||||
const userInfo = getCachedUserInfo();
|
|
||||||
if (!userInfo?.userId) {
|
|
||||||
console.warn('[CreditsService] 无法查询余额:未登录');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await getCreditBalance(userInfo.userId);
|
// 获取 JWT token
|
||||||
if (response.success && response.balance !== undefined) {
|
const session = await vscode.authentication.getSession('iccoder', [], { silent: true });
|
||||||
updateCachedBalance(response.balance);
|
if (!session?.accessToken) {
|
||||||
return response.balance;
|
console.warn('[CreditsService] 无法查询余额:未登录');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = session.accessToken;
|
||||||
|
console.log('[CreditsService] 开始查询余额,token 长度:', token.length);
|
||||||
|
|
||||||
|
// 直接调用 StrangeLoop 的 /api/credit/balance 接口
|
||||||
|
const response = await callStrangeLoopBalance(token);
|
||||||
|
|
||||||
|
if (response.availableCredits !== undefined) {
|
||||||
|
const balance = response.availableCredits;
|
||||||
|
updateCachedBalance(balance);
|
||||||
|
console.log('[CreditsService] 余额查询成功:', balance);
|
||||||
|
return balance;
|
||||||
} else {
|
} else {
|
||||||
console.warn('[CreditsService] 查询余额失败:', response.error);
|
console.warn('[CreditsService] 查询余额失败:', response.error || response.message);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -67,6 +90,72 @@ export async function fetchBalance(): Promise<number | null> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用 StrangeLoop 余额接口
|
||||||
|
*/
|
||||||
|
async function callStrangeLoopBalance(token: string): Promise<StrangeLoopBalanceResponse> {
|
||||||
|
const urlStr = getStrangeLoopApiUrl('/api/credit/balance');
|
||||||
|
const url = new URL(urlStr);
|
||||||
|
|
||||||
|
const isHttps = url.protocol === 'https:';
|
||||||
|
const httpModule = isHttps ? https : http;
|
||||||
|
|
||||||
|
// 余额查询使用固定短超时,避免阻塞发送前检查
|
||||||
|
const BALANCE_TIMEOUT_MS = 5000;
|
||||||
|
|
||||||
|
const requestOptions: http.RequestOptions = {
|
||||||
|
hostname: url.hostname,
|
||||||
|
port: url.port || (isHttps ? 443 : 80),
|
||||||
|
path: url.pathname + url.search,
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': `Bearer ${token}`
|
||||||
|
},
|
||||||
|
timeout: BALANCE_TIMEOUT_MS
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const req = httpModule.request(requestOptions, (res) => {
|
||||||
|
let data = '';
|
||||||
|
|
||||||
|
res.on('data', (chunk) => {
|
||||||
|
data += chunk;
|
||||||
|
});
|
||||||
|
|
||||||
|
res.on('end', () => {
|
||||||
|
console.log('[CreditsService] 响应状态码:', res.statusCode);
|
||||||
|
console.log('[CreditsService] 响应内容:', data);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const json = JSON.parse(data);
|
||||||
|
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
|
||||||
|
resolve(json as StrangeLoopBalanceResponse);
|
||||||
|
} else if (res.statusCode === 401 || res.statusCode === 403) {
|
||||||
|
// 登录过期或无权限
|
||||||
|
resolve({ error: '登录已过期,请重新登录' });
|
||||||
|
} else {
|
||||||
|
resolve({ error: json.error || json.message || json.msg || `HTTP ${res.statusCode}` });
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
resolve({ error: `解析响应失败: ${data}` });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
req.on('error', (error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
req.on('timeout', () => {
|
||||||
|
req.destroy();
|
||||||
|
reject(new Error('请求超时'));
|
||||||
|
});
|
||||||
|
|
||||||
|
req.end();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前余额(优先使用缓存,过期则主动查询)
|
* 获取当前余额(优先使用缓存,过期则主动查询)
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user