Files
digital-me-history/digital-me-backend/.env.example
T
admin 0593ff7e62
nginx serve /uploads direct (audio speed) / patch-nginx (push) Failing after 1m34s
数字我 Digital Me:全量入库(大文件走 Git LFS)
2026-10-10 16:24:43 +08:00

251 lines
14 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ── 数字我 / 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://<WorkspaceId>.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=