| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- /**
- * API 路由主入口(客户独立实例)
- * - Amazon:保留本地 SP-API 模块
- * - Sorftime / TikHub:浏览器直打公司中转;定时任务经 src/relay RelayClient
- * - 已移除:直连 sorftime / tikhub / eccang 模块
- */
- import express from 'npm:express';
- const router = express.Router();
- console.log('[API Routes] Initializing Jianhen customer instance...');
- router.use((req, res, next) => {
- console.log(`[API Router] Hit: ${req.method} ${req.url} (Original: ${req.originalUrl})`);
- next();
- });
- router.get('/ping', (req, res) => {
- res.json({ message: 'pong', instance: 'jianhen-voc' });
- });
- function isInternalRequest(req) {
- const address = String(req.socket?.remoteAddress || '');
- return !req.headers['x-external-request']
- && (address === '127.0.0.1' || address === '::1' || address.endsWith(':127.0.0.1'));
- }
- async function requireApiUser(req, res, next) {
- if (isInternalRequest(req)) return next();
- const token = String(req.headers['x-parse-session-token'] || '').trim();
- if (!token) return res.status(401).json({ success: false, message: '需要登录' });
- try {
- const Parse = globalThis.Parse;
- const query = new Parse.Query('_Session');
- query.equalTo('sessionToken', token);
- query.include('user');
- const session = await query.first({ useMasterKey: true });
- const user = session?.get('user');
- if (!user || user.get('status') === 'disabled') {
- return res.status(401).json({ success: false, message: '会话无效' });
- }
- req.currentUser = user;
- next();
- } catch {
- res.status(401).json({ success: false, message: '会话无效' });
- }
- }
- function requireAdmin(req, res, next) {
- if (isInternalRequest(req) || req.currentUser?.get?.('isAdmin') === true) return next();
- res.status(403).json({ success: false, message: '需要管理员权限' });
- }
- function requireUserExceptHealth(req, res, next) {
- if (req.path === '/health') return next();
- return requireApiUser(req, res, next);
- }
- function requireAdminExceptToken(req, res, next) {
- if (req.path === '/token') return next();
- return requireAdmin(req, res, next);
- }
- /**
- * 亚马逊相关接口
- * 必须携带店铺的 id
- */
- import { createSpApiRouter } from '../modules/fmode-amazon-sp-api/src/mod.ts';
- router.use('/amazon', requireApiUser, createSpApiRouter());
- /**
- * 公司中转密钥/余额:仅管理员
- * Sorftime / TikHub 浏览器请求不再经过本机 /forward。
- */
- import relayCredentialRouter from './relay/credential-routes.ts';
- router.use('/relay', requireApiUser, requireAdminExceptToken, relayCredentialRouter);
- console.log('[API Routes] ✅ Company relay credential routes mounted');
- // 定时任务管理路由(内部已改为 RelayClient 直打公司中转)
- import scheduleRouter from './module/schedule/routes-schedule.ts';
- try {
- router.use('/schedule', requireApiUser, requireAdmin, scheduleRouter);
- } catch (e) {
- console.warn('[API Routes] scheduleRouter 加载失败', e);
- }
- router.get('/', (req, res) => {
- res.json({
- message: 'Jianhen VOC Instance API Routes Loaded',
- version: '1.0.1-customer-relay',
- timestamp: new Date().toISOString(),
- availableRoutes: [
- '/api/amazon',
- '/api/relay/token',
- '/api/relay/status',
- '/api/relay/credential',
- '/api/schedule',
- ],
- removedModules: [
- 'fmode-sorftime-api (direct upstream)',
- 'fmode-tikhub-api (direct upstream)',
- 'fmode-tikhub-api-customize',
- 'fmode-eccang-api',
- ],
- relay: {
- companyBase: 'https://server.fmode.cn',
- sorftimeUpstream: '/api/voc-ecom/forward',
- tikhubUpstream: '/api/voc-social/*',
- },
- });
- });
- export default router;
|