| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- /**
- * 取阿里云 NLS 的 token(实时语音识别用)——**走后端网关**。
- *
- * 端点是 `{VITE_NLS_TOKEN_API}`(默认 `/aly-api/proxy/verify/getALYToken`,同源路径:
- * dev 由 vite 代理到 `http://121.43.55.7:10011`,生产由 nginx 转发)。
- * 返回形态:`{ code: 200, message: "成功", content: "<32 位 token>" }`。
- *
- * **前端不签 token**:签名要 AccessKeySecret,而前端 bundle 是公开的;
- * 网关侧(或后端)做这件事,前端只拿结果。
- * 与阿里云 `CreateToken` 的差别:网关**不返回过期时间**,按官方文档的 24 小时估。
- *
- * 缓存策略:缓存到过期前 5 分钟;并发调用共用同一个在途请求
- * (说话时前端可能连着触发几次,不该打多次网关)。
- */
- import { getNlsAppkey, getNlsTokenApiUrl } from "@/utils/runtime-config";
- export interface NlsTokenResult {
- token: string;
- /** 过期时间(epoch 毫秒)—— 网关不给,按 24 小时估 */
- expireAt: number;
- }
- /** NLS token 的有效期(官方文档 24 小时;网关不返回,所以按它估) */
- const TOKEN_LIFETIME_MS = 24 * 60 * 60 * 1000;
- /** 提前多久视为过期(留出换 token + 重连的余量) */
- const REFRESH_AHEAD_MS = 5 * 60 * 1000;
- let cached: NlsTokenResult | null = null;
- let inflight: Promise<NlsTokenResult> | null = null;
- const isValid = () => !!cached && cached.expireAt - Date.now() > REFRESH_AHEAD_MS;
- export const fetchNlsToken = async (): Promise<NlsTokenResult> => {
- if (isValid()) {
- return cached as NlsTokenResult;
- }
- if (inflight) {
- return inflight;
- }
- inflight = (async () => {
- const response = await fetch(getNlsTokenApiUrl(), { method: "GET" });
- let body: any = null;
- try {
- body = await response.json();
- } catch {
- /* 非 JSON 时按状态码报错 */
- }
- if (!response.ok) {
- throw new Error(body?.message || `获取语音识别 token 失败(HTTP ${response.status})`);
- }
- // 网关用 code 表达业务结果(HTTP 200 也可能是失败)
- if (Number(body?.code) !== 200 || !body?.content) {
- throw new Error(body?.message || "获取语音识别 token 失败:响应里没有 token");
- }
- cached = {
- token: String(body.content).trim(),
- expireAt: Date.now() + TOKEN_LIFETIME_MS,
- };
- return cached;
- })();
- try {
- return await inflight;
- } finally {
- inflight = null;
- }
- };
- /** NLS 的 appkey(识别请求要带)—— 见 `getNlsAppkey` 的说明 */
- export const getNlsTokenAppkey = (): string => getNlsAppkey();
- /** 丢掉缓存(排查用:怀疑 token 失效时强制重取) */
- export const clearNlsTokenCache = (): void => {
- cached = null;
- };
|