const DEFAULT_ACK_TEXT = '已收到,正在处理,完成后发到这里。'; const DEFAULT_PROGRESS_TEXT = '还在处理,请稍等片刻。'; const DEFAULT_STATUS_TEXT = '我在这边。上一条如果还没完成,我会继续把结果发给你;你也可以直接补一句要求。'; const DEFAULT_UNSUPPORTED_TEXT = '当前先支持文字消息,你可以直接发文字给我。'; const DEFAULT_UNBOUND_TEXT = '先点这里完成绑定,再继续和专属 Agent 对话:'; const DEFAULT_PROGRESS_DELAY_MS = 8000; const DEFAULT_SESSION_IDLE_ROTATE_MS = 30 * 60 * 1000; const DEFAULT_SESSION_MESSAGE_ROTATE_COUNT = 200; const DEFAULT_WECHAT_TOKEN_URL = 'https://api.weixin.qq.com/cgi-bin/stable_token'; const DEFAULT_WECHAT_CUSTOMER_SERVICE_URL = 'https://api.weixin.qq.com/cgi-bin/message/custom/send'; const DEFAULT_WECHAT_JSAPI_TICKET_URL = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket'; function deriveWechatEndpointFromUrl(baseUrl, suffix) { const normalized = String(baseUrl ?? '').trim(); if (!normalized) return ''; try { const url = new URL(normalized); return `${url.origin}${suffix}`; } catch { return ''; } } function parseCsvList(value = '') { return String(value ?? '') .split(',') .map((item) => item.trim()) .filter(Boolean); } export function loadWechatMpConfig(env = process.env) { const appId = env.H5_WECHAT_MP_APP_ID?.trim() ?? env.H5_WECHAT_APP_ID?.trim() ?? ''; const appSecret = env.H5_WECHAT_MP_APP_SECRET?.trim() ?? env.H5_WECHAT_APP_SECRET?.trim() ?? ''; const token = env.H5_WECHAT_MP_TOKEN?.trim() ?? ''; const publicBaseUrl = env.H5_PUBLIC_BASE_URL?.trim()?.replace(/\/$/, '') ?? ''; const generatedImagePublicBaseUrls = [...new Set([ publicBaseUrl, env.IMGPROXY_BASE_URL?.trim()?.replace(/\/$/, '') ?? '', ...parseCsvList(env.H5_WECHAT_MP_GENERATED_IMAGE_BASE_URLS).map((value) => value.replace(/\/$/, '')), ].filter(Boolean))]; const enabledFlag = env.H5_WECHAT_MP_ENABLED === '1'; const bindPath = env.H5_WECHAT_MP_BIND_PATH?.trim() || '/auth/wechat/authorize?intent=login'; return { enabled: enabledFlag && Boolean(appId && appSecret && token && publicBaseUrl), appId, appSecret, token, publicBaseUrl, bindPath, ackText: env.H5_WECHAT_MP_ACK_TEXT?.trim() || DEFAULT_ACK_TEXT, ackRandomEnabled: env.H5_WECHAT_MP_ACK_RANDOM !== '0', ackNicknameEnabled: env.H5_WECHAT_MP_ACK_NICKNAME !== '0', progressText: env.H5_WECHAT_MP_PROGRESS_TEXT?.trim() || DEFAULT_PROGRESS_TEXT, progressDelayMs: Math.max( 0, Number(env.H5_WECHAT_MP_PROGRESS_DELAY_MS ?? DEFAULT_PROGRESS_DELAY_MS), ), sessionIdleRotateMs: Math.max( 0, Number(env.H5_WECHAT_MP_SESSION_IDLE_ROTATE_MS ?? DEFAULT_SESSION_IDLE_ROTATE_MS), ), sessionMessageRotateCount: Math.max( 0, Number(env.H5_WECHAT_MP_SESSION_MESSAGE_ROTATE_COUNT ?? DEFAULT_SESSION_MESSAGE_ROTATE_COUNT), ), statusText: env.H5_WECHAT_MP_STATUS_TEXT?.trim() || DEFAULT_STATUS_TEXT, unsupportedText: env.H5_WECHAT_MP_UNSUPPORTED_TEXT?.trim() || DEFAULT_UNSUPPORTED_TEXT, unboundTextPrefix: env.H5_WECHAT_MP_UNBOUND_TEXT_PREFIX?.trim() || DEFAULT_UNBOUND_TEXT, tokenUrl: env.H5_WECHAT_MP_TOKEN_URL?.trim() || DEFAULT_WECHAT_TOKEN_URL, customerServiceUrl: env.H5_WECHAT_MP_CUSTOMER_SERVICE_URL?.trim() || DEFAULT_WECHAT_CUSTOMER_SERVICE_URL, jsapiTicketUrl: env.H5_WECHAT_MP_JSAPI_TICKET_URL?.trim() || deriveWechatEndpointFromUrl(env.H5_WECHAT_MP_TOKEN_URL?.trim(), '/cgi-bin/ticket/getticket') || DEFAULT_WECHAT_JSAPI_TICKET_URL, mediaPublicBaseUrl: env.H5_WECHAT_MP_MEDIA_PUBLIC_BASE_URL?.trim()?.replace(/\/$/, '') || publicBaseUrl, generatedImagePublicBaseUrls, maxImageBytes: Math.max(1, Number(env.H5_WECHAT_MP_MAX_IMAGE_BYTES ?? 10 * 1024 * 1024)), maxFileBytes: Math.max(1, Number(env.H5_WECHAT_MP_MAX_FILE_BYTES ?? 30 * 1024 * 1024)), acceptVoice: env.H5_WECHAT_MP_ACCEPT_VOICE !== '0', acceptImage: env.H5_WECHAT_MP_ACCEPT_IMAGE !== '0', acceptFile: env.H5_WECHAT_MP_ACCEPT_FILE !== '0', acceptLocation: env.H5_WECHAT_MP_ACCEPT_LOCATION !== '0', acceptLink: env.H5_WECHAT_MP_ACCEPT_LINK !== '0', mediaAnalysisGrayUsers: parseCsvList(env.H5_WECHAT_MP_MEDIA_GRAY_USERS), reliabilityGrayUsers: parseCsvList(env.H5_WECHAT_MP_RELIABILITY_GRAY_USERS), agentReplyTimeoutMs: Math.max( 0, Number(env.H5_WECHAT_MP_AGENT_REPLY_TIMEOUT_MS ?? 15 * 60 * 1000), ), requireFreshPageThumbnail: env.H5_WECHAT_MP_FRESH_PAGE_THUMBNAILS !== '0', repairFreshPageThumbnail: env.H5_WECHAT_MP_FRESH_THUMBNAIL_REPAIR === '1', encodingAesKey: env.H5_WECHAT_MP_ENCODING_AES_KEY?.trim() ?? '', }; }