Files

76 lines
2.4 KiB
TypeScript
Raw Permalink Normal View History

import { getRuntimeEnv } from "../../../lib/runtime-env";
import {
exchangeWecomOAuthCode,
fetchWecomExternalContactName,
resolveWecomConfig,
WecomClientError,
type WecomBindings,
} from "../../../lib/wecom-client";
import { signWecomIdentityTicket } from "../../../lib/wecom-oauth-service";
import { partnerOptions, withPartnerCors } from "../../../lib/partner-cors";
const env = getRuntimeEnv();
export function OPTIONS(request: Request) {
return partnerOptions(request);
}
async function handlePost(request: Request) {
try {
const body = (await request.json().catch(() => ({}))) as { code?: string };
const code = String(body.code ?? "").trim();
const config = resolveWecomConfig(env as unknown as WecomBindings);
if (!config.corpId || !config.agentId || !config.secret) {
return Response.json(
{ error: "未配置企业微信授权(WECOM_CORP_ID / WECOM_AGENT_ID / WECOM_SECRET)" },
{ status: 501 },
);
}
if (!code) {
return Response.json({ error: "缺少授权 code" }, { status: 400 });
}
const identity = await exchangeWecomOAuthCode(config, code);
if (identity.externalUserId) {
const displayName =
(await fetchWecomExternalContactName(config, identity.externalUserId)) ??
"企微客户";
const { ticket, expiresIn } = await signWecomIdentityTicket(
identity.externalUserId,
displayName,
);
return Response.json({
userType: "external",
identityTicket: ticket,
displayName,
expiresIn,
});
}
const userId = identity.userId ?? "";
if (!userId) {
return Response.json({ error: "企业微信未返回有效身份" }, { status: 400 });
}
const { ticket, expiresIn } = await signWecomIdentityTicket("", "", {
userId,
});
return Response.json({
userType: "internal",
userId,
identityTicket: ticket,
displayName: userId,
expiresIn,
});
} catch (error) {
const status = error instanceof WecomClientError ? error.status : 500;
return Response.json(
{ error: error instanceof Error ? error.message : "授权失败" },
{ status },
);
}
}
export async function POST(request: Request) {
const response = await handlePost(request);
response.headers.set("Cache-Control", "private, no-store");
return withPartnerCors(request, response);
}