import { NextRequest, NextResponse } from "next/server"; import { getResolvedProductPlanningApiConfig } from "@/lib/product-planning/server-config"; import { isProductPlanningEnabled, PRODUCT_PLANNING_DISABLED_MESSAGE, } from "@/lib/product-planning/server-feature"; import { getProductPlanningToken } from "@/lib/product-planning/server-auth"; import { normalizeJdItem } from "@/lib/product-planning/taobao"; import type { ProductPlanningTaobaoItemResponse } from "@/lib/product-planning/types"; export const runtime = "nodejs"; function jsonError(status: number, error: string) { const payload: ProductPlanningTaobaoItemResponse = { success: false, error, }; return NextResponse.json(payload, { status }); } export async function GET(request: NextRequest) { const token = await getProductPlanningToken(request); if (!token?.sub) { return jsonError(401, "未登录"); } if (!(await isProductPlanningEnabled())) { return jsonError(403, PRODUCT_PLANNING_DISABLED_MESSAGE); } const itemId = String(request.nextUrl.searchParams.get("id") || "").trim(); if (!itemId) { return jsonError(400, "缺少商品ID参数"); } const config = await getResolvedProductPlanningApiConfig(); const apiKey = config.taobaoApiKey; const apiSecret = config.taobaoApiSecret; if (!apiKey || !apiSecret) { return jsonError(500, "缺少商品策划工具淘宝 API Key / Secret,请前往系统设置配置"); } const apiUrl = `${config.oneboundBaseUrl}/jd/item_get_app/?key=${encodeURIComponent(apiKey)}` + `&secret=${encodeURIComponent(apiSecret)}&num_iid=${encodeURIComponent(itemId)}&domain_type=jd`; const descApiUrl = `${config.oneboundBaseUrl}/jd/item_get_desc/?key=${encodeURIComponent(apiKey)}` + `&secret=${encodeURIComponent(apiSecret)}&num_iid=${encodeURIComponent(itemId)}&domain_type=jd`; try { const [response, descResponse] = await Promise.all([ fetch(apiUrl, { signal: AbortSignal.timeout(15000), headers: { Accept: "application/json" }, cache: "no-store", }), fetch(descApiUrl, { signal: AbortSignal.timeout(15000), headers: { Accept: "application/json" }, cache: "no-store", }).catch(() => null), ]); if (!response.ok) { return jsonError(502, `京东商品详情接口请求失败:${response.status}`); } const data = await response.json(); if (data?.error_code && data.error_code !== "0000") { return jsonError(502, data.error || data.reason || "京东商品详情接口返回错误"); } if (!data?.item) { return jsonError(404, "未找到商品信息"); } let descHtml = ""; if (descResponse?.ok) { try { const descData = await descResponse.json(); descHtml = String(descData?.item?.desc || "").trim(); } catch (error) { console.warn("[ProductPlanning][JdItem] parse desc failed:", error); } } return NextResponse.json({ success: true, item: normalizeJdItem( { ...data.item, desc: descHtml || data.item.desc, }, itemId ), } satisfies ProductPlanningTaobaoItemResponse); } catch (error) { console.error("[ProductPlanning][JdItem] request failed:", error); return jsonError(502, "京东商品详情接口调用失败"); } }