# ── 数字我 / Digital Me — backend env ───────────────────────────────── # Copy to `.env` and fill in. Everything optional degrades gracefully # (the product stays usable end-to-end even with no AI keys). PORT=3701 NODE_ENV=development # 系统版本(独立部署两个系统时各自锁定): # adult = 成人系统(社交/广场/群聊/专家付费/钱包) # teen = 青少年教育系统(错题/互考/排行榜/家长监护) # both = 单体平台(默认) # 两系统应各自独立部署:独立 EDITION + 独立 MONGO_DB(或 COLLECTION_PREFIX) + 独立域名。 EDITION=both # Public origin of THIS api. DashScope pulls media (photo/audio) BY URL, # so for avatar 捏脸 / 口播视频 to work this MUST be publicly reachable # (a localhost URL fails — those features degrade, chat still works). PUBLIC_URL=http://localhost:3701 # Web app origin(s), comma-separated. CORS_ORIGINS=http://localhost:5173 # Auth JWT_SECRET=change-me-in-prod JWT_EXPIRES=7d # 登录方式:邮箱密码(内置)+ 手机短信 + 微信扫码。 # 短信:设 SMS_PROVIDER=aliyun 走真实发送(需下列四项全配齐);留空=stub(验证码在 # 响应 devCode 返回,仅 dev;生产 stub 默认 fail-closed,除非 ALLOW_STUB_LOGIN=true)。 SMS_PROVIDER=stub ALIYUN_SMS_KEY_ID= # 阿里云 AccessKey ID(建议用 RAM 子账号,仅授 AliyunDysmsFullAccess) ALIYUN_SMS_KEY_SECRET= # 对应 AccessKey Secret ALIYUN_SMS_SIGN= # 短信签名(控制台「国内消息-签名管理」审核通过的签名名称) ALIYUN_SMS_TEMPLATE= # 短信模板 CODE(如 SMS_123456789,验证码类模板) # 模板正文里的验证码变量名。默认 code(对应模板 ${code});模板用别的变量名时改这里。 ALIYUN_SMS_CODE_PARAM=code # 微信【网站应用】扫码登录(open.weixin.qq.com 开放平台,scope=snsapi_login)。 # 留空=stub 二维码(本地可模拟扫码;生产 fail-closed 除非 ALLOW_STUB_LOGIN=true)。 # ⚠ 开放平台后台「网站应用 → 授权回调域」必须填 WECHAT_REDIRECT_URI 的域名(只填域名,不带路径/协议)。 # ⚠ 拿真实昵称/头像会调 sns/userinfo;unionid 需该应用已绑定到【开放平台账号】才返回(用于统一身份)。 WECHAT_APP_ID= WECHAT_APP_SECRET= # 回调地址,须公网可达。留空默认 ${PUBLIC_URL}/api/auth/wechat/callback。 WECHAT_REDIRECT_URI= # MongoDB — Digital Me owns its own DB. Never share another product's. MONGO_URI=mongodb://localhost:27017 MONGO_DB=digital_me # ── AI: 阿里云 DashScope (one key powers LLM + embeddings + 万相 + EMO + CosyVoice) ── DASHSCOPE_API_KEY= DASHSCOPE_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1 LLM_MODEL=qwen-max EMBED_MODEL=text-embedding-v3 # 通用图片生成(万相文生图)模型。复用 DASHSCOPE key,有 key 即可用(需百炼已开通万相文生图)。 # 可选:wanx2.1-t2i-turbo(快省·默认) / wanx2.1-t2i-plus(更精更贵)。经统一入口 POST /api/create(modality=image)。 WANX_T2I_MODEL=wanx2.1-t2i-turbo # ── 二创·AI 音乐生成:昆仑万维 Mureka ────────────────────────────────── # 配 MUREKA_API_KEY 即启用(经 POST /api/create type=music:词+曲风→成品歌)。缺 key → 音乐生成 503。 # ⚠ 数据出境:歌词/曲风会发往 MUREKA_BASE_URL(默认 api.mureka.ai);合规要境内就指到 Mureka 境内 API 域。 MUREKA_API_KEY= MUREKA_BASE_URL=https://api.mureka.ai MUREKA_MODEL=auto # auto / mureka-6 / V8 等 # ── 二创·AI 视频生成:字节 Seedance(火山方舟)────────────────────────── # 配 SEEDANCE_API_KEY(=火山方舟 API Key)即启用(经 POST /api/create type=drama:文/图生视频)。缺 key → 503。 # 端点走火山方舟【境内北京】域,数据不出域友好。model 需与你账号已开通的一致;若账号要求推理接入点, # 把 SEEDANCE_MODEL 设成 ep-xxxxx。 SEEDANCE_API_KEY= SEEDANCE_BASE_URL=https://ark.cn-beijing.volces.com SEEDANCE_MODEL=doubao-seedance-1-0-pro-250528 # 知识检索精排模型。gte-rerank 已于 2026-05-30 下线,默认用后继 qwen3-rerank。 RERANK_MODEL=qwen3-rerank # ── 语音合成 CosyVoice ────────────────────────────────────────────── # 新克隆音色的注册版本(默认已升 v3.5-flash;高质可用 cosyvoice-v3.5-plus)。 # ⚠ v3.5 仅北京地域,需在百炼【北京】工作空间开通 CosyVoice;旧 v2 克隆音仍按各自版本合成。 COSYVOICE_MODEL=cosyvoice-v3.5-flash # 预置音色 TTS(助手讲解 / 无克隆音兜底)的模型。预置音色名分版本、v3.5 官方未公布 → # 默认仍 v2;待 v3.5 音色公布后,改这里 + 相应 TWIN_COSY_PRESET/ASSISTANT_COSY_VOICE 音色名。 COSYVOICE_PRESET_MODEL=cosyvoice-v2 # 实时合成 WebSocket 端点。默认北京全局端点;若工作空间要求专属 MaaS 端点再填。 # COSYVOICE_WS_URL=wss://.cn-beijing.maas.aliyuncs.com/api-ws/v1/inference # 向量索引后端。留空 → memory(MongoDB 内联向量 + 内存暴力余弦,有 2000 块上限,适合小规模)。 # 配了 DASHVECTOR_ENDPOINT + DASHVECTOR_API_KEY → 自动切阿里云 DashVector(境内托管向量库,ANN 索引, # 数据不出域,去掉 2000 块上限)。首次接入或换维度后跑一次:node scripts/reindex-vectors.js # DASHVECTOR_DIM 必须与 EMBED_MODEL 维度一致(text-embedding-v3 = 1024)。 DASHVECTOR_ENDPOINT= DASHVECTOR_API_KEY= DASHVECTOR_COLLECTION=digitalme_knowledge DASHVECTOR_DIM=1024 # Optional Claude fallback when Qwen is unavailable. ANTHROPIC_API_KEY= ANTHROPIC_MODEL=claude-haiku-4-5-20251001 # 标准英文发音 (Azure Neural TTS) — 英语陪练用原生发音。留空则英文回退 # CosyVoice(克隆音色) 或浏览器 TTS。 AZURE_SPEECH_KEY= AZURE_SPEECH_REGION=eastasia AZURE_VOICE_EN=en-US-JennyNeural # Avatar 捏脸 (通义万相 wanx-style-repaint). Blank → uploaded photo used flat. # 'dashscope' reuses DASHSCOPE_API_KEY. Style: a name (3d/anime/ink/fresh) # or raw wanx style_index 0-9. For a realistic "self" twin, leaving the # uploaded photo flat (blank provider) is often the most faithful. AVATAR_PROVIDER= AVATAR_STYLE=3d # Storage: 配齐下面 OSS_* 四要素 → 自动用阿里云 OSS(推荐:公网直链、免公网穿透、 # 重部署不丢片、DashScope 直接按 URL 拉);否则回落本地磁盘 + /uploads。 STORAGE_DRIVER=local STORAGE_LOCAL_DIR=./data/uploads # ── 阿里云 OSS(媒体存储,生产推荐)────────────────────────────────── # ⚠ OSS_REGION 必须带 oss- 前缀(如 oss-cn-hangzhou),否则 SDK 拼错域名 ENOTFOUND。 # 存进 DB 的是持久直链(头像/成片长期展示)→ bucket 需「公开读」,或用 OSS_PUBLIC_BASE # 指向自定义域名/CDN。共享 bucket 靠 OSS_PREFIX 隔离(digital-me 用 digitalme)。 OSS_REGION= OSS_BUCKET= OSS_ACCESS_KEY_ID= OSS_ACCESS_KEY_SECRET= OSS_ENDPOINT= OSS_PREFIX=digitalme OSS_PUBLIC_BASE= # ── 生产级安全 (production hardening) ───────────────────────────────── # In production (NODE_ENV=production) the server REFUSES to boot unless # JWT_SECRET is set to a strong random value (not the default). # Encrypt visitor chat logs at rest (AES-256-GCM). Any string → hashed to # a 32-byte key. Strongly recommended in prod; empty = plaintext (dev only). DATA_ENC_KEY= # Emails (comma-separated) allowed to grant 蓝V verification & admin actions. SUPER_ADMIN_EMAILS= # Content moderation. Tiers (highest available wins, falls back down): # external — set MODERATION_URL (plug a pro service; POST {text} → {allowed,category?}) # llm — set MODERATION_MODE=llm to classify via DashScope (Qwen) # local — built-in regex floor (always on) MODERATION_MODE= MODERATION_URL= MODERATION_KEY= # Max length of any chat/visitor message (cost + abuse control). MAX_QUESTION_LEN=2000 # Set 'true' when behind nginx/cloudflare so client IP (rate-limit key) is # correct. Auto-on in production; set 'false' to force off. TRUST_PROXY= # ── 请求访问日志 ────────────────────────────────────────────────────── # 每个请求打一行(方法/路径/状态码/耗时/IP/请求ID)。只记元数据,不记 query/body。 LOG_REQUESTS=on # off 关闭访问日志 LOG_SLOW_MS=5000 # 超过该耗时(ms)的请求标记 ⚠slow LOG_SKIP_PATHS=/health # 不记的高频噪声路径(逗号分隔,前缀匹配) # ── 付费咨询 / 钱包 (FR-4.2) ────────────────────────────────────────── # 支付通道: # stub = 即时到账(最快开发态) # mock = 完整模拟「下单→支付→回调入账」异步链路(不涉及真钱,可本地验证) # stripe = Stripe Checkout(需 STRIPE_SECRET_KEY + STRIPE_WEBHOOK_SECRET) # wechat = 预留(在 payments.js 实现下单 + 回调) PAYMENT_PROVIDER=stub TOKENS_PER_YUAN=10 PAY_CURRENCY=cny # 用户支付后返回的前端地址(默认取 CORS_ORIGINS 第一个)。 WEB_BASE_URL= # 分享卡片 og meta(/me/:slug、/s/:token 的微信/IM 富卡片)。见 DEPLOY.md。 # 填了→读真 SPA index 注入 meta(页面仍是完整 App);空→回落 meta+跳转独立壳。 SPA_INDEX_PATH= # 可选:无头像时的兜底卡片图(绝对 URL)。 OG_FALLBACK_IMAGE= # 微信 JS-SDK(公众号「转发给朋友/朋友圈」自定义卡片)。填【公众号】appId/secret # (非开放平台扫码登录的那个)。空 → 签名接口 {configured:false}、前端休眠。见 DEPLOY.md。 # 还需在公众号后台把 digitalme.invoratec.cn 加进「JS 安全域名」。 WX_MP_APP_ID= WX_MP_APP_SECRET= # Stripe(provider=stripe 时必填)。Webhook 配到 /api/wallet/webhook/stripe。 STRIPE_SECRET_KEY= STRIPE_WEBHOOK_SECRET= # ── 产品工厂 购买通道 (商店/buy → 购买即开通) ───────────────────────── # STORE_PROVIDER:只管【stub ↔ 真实支付】总闸,与「用哪个渠道」正交(渠道见 PAY_METHODS)。 # stub = 即时开通(无真实收款,开发/演示用,默认) # live(或wechat) = 真实支付(非 stub 即视为开)。具体渠道由 PAY_METHODS 决定: # · 微信:需 WXPAY_* 配齐(微信内 JSAPI 还需 WX_MP_* + 公众号绑商户号) # · 支付宝:需 ALIPAY_* 证书三件套配齐 STORE_PROVIDER=stub # 测试收款:PAY_ENV=dev 或 test 时,所有付费订单只收 1 分钱——走真实通道验证下单→ # 收银台→回调→开通全链,但只花 1 分。免费 SKU(¥0) 不受影响。生产留空。 PAY_ENV= # 支付弹窗展示哪些收款方式 + 顺序(逗号分隔,只认 wechat/alipay)。留空默认 wechat,alipay。 # PAY_METHODS=wechat,alipay → 微信在前;=alipay → 只显示支付宝;=wechat → 只微信。 PAY_METHODS=wechat,alipay # 下单显式超时(分钟):过期后二维码/支付链接失效,渠道自动关单。前端轮询时长与之对齐。 PAY_ORDER_TIMEOUT_MIN=10 # 微信支付 v3(商户平台 → API 安全)。Webhook 配到 /api/store/webhook/wechat。 WXPAY_APP_ID= # 商户绑定的 appid(JSAPI 用 WX_MP_APP_ID 那个公众号;Native 可公众号/开放平台) WXPAY_MCH_ID= # 商户号 WXPAY_API_V3_KEY= # APIv3 密钥(必须 32 位) WXPAY_CERT_SERIAL= # 商户 API 证书序列号 # 商户私钥 PEM:二选一。直接给内容(把换行写成 \n) 或给文件路径。 WXPAY_PRIVATE_KEY= WXPAY_PRIVATE_KEY_PATH= # 微信支付【平台证书】(回调验签用公钥)。配上即启用「回调验签闸」(防伪造/重放); # 未配时回调仅靠 APIv3 GCM 鉴权放行。二选一:贴内容(\n 转义) 或给文件路径。 WECHATPAY_PLATFORM_CERT= WECHATPAY_PLATFORM_CERT_PATH= # 支付宝 · 电脑网站支付【证书模式/RSA2】。Webhook 配到 /api/store/webhook/alipay。 # 证书三件套从开放平台下载;每项二选一:贴内容(\n 转义) 或给 *_PATH 文件路径。 # ALIPAY_APP_CERT = 应用公钥证书 appCertPublicKey_2021xxx.crt # ALIPAY_CERT = 支付宝公钥证书 alipayCertPublicKey_RSA2.crt # ALIPAY_ROOT_CERT = 支付宝根证书 alipayRootCert.crt # 沙箱:ALIPAY_GATEWAY=https://openapi.alipaydev.com/gateway.do(生产留空即用默认生产网关)。 ALIPAY_APP_ID= ALIPAY_PRIVATE_KEY= ALIPAY_PRIVATE_KEY_PATH= ALIPAY_APP_CERT= ALIPAY_APP_CERT_PATH= ALIPAY_CERT= ALIPAY_CERT_PATH= ALIPAY_ROOT_CERT= ALIPAY_ROOT_CERT_PATH= ALIPAY_GATEWAY= # ── 拟人化互动合规 ──────────────────────────────────────────────────── # 《人工智能拟人化互动服务管理暂行办法》(网信办/发改委/工信部/公安部/市场监管总局 # 五部门,2026-04-10 公布,2026-07-15 施行)。本产品的「数字分身」命中第二条 # 「模拟自然人人格特征、思维模式和沟通风格」要件,故第十四/十八条的义务适用。 # # 未成年人模式(第十四条)总开关。⚠ 默认【开】——它是法定义务不是产品特性, # 不配这个变量也是开的。设 off 仅供【误伤大面积用户时先关再修】的紧急止血, # 关闭期间本站不符合第十四条,必须同步上报。 FEATURE_MINOR_MODE=on # 未成年人模式下单日累计使用时长上限(分钟)。法条只写「使用时长限制」没给数字, # 这里取《未成年人网络保护条例》的通行口径 60 分钟。调整前请过法务。 MINOR_DAILY_LIMIT_MIN=60 # 「定期现实提醒」周期(分钟):每隔这么久提醒一次"这是 AI,去看看现实里的人和事"。 MINOR_REALITY_CHECK_MIN=20 # 第十四条要求「提供相应申诉渠道」。站内申诉入口已内置(minor_appeals 集合 + 超管处理), # 但法条要的是【用户看得见、联系得上】的渠道 → 生产【应当】填一个真实邮箱或电话。 # 留空时前端只显示站内申诉,并诚实写明"仅站内受理"。 COMPLIANCE_APPEAL_CONTACT=