66 lines
2.1 KiB
TypeScript
66 lines
2.1 KiB
TypeScript
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,
|
||
});
|
||
}
|
||
return Response.json({
|
||
userType: "internal",
|
||
userId: identity.userId ?? "",
|
||
});
|
||
} 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);
|
||
}
|