docs: add development-machine handoff and server deploy configs
换开发机继续开发。新机器只需要拉仓库 + 自备工具链 + 单独拷贝两个机密文件, 服务器/聚石塔/SAE 全部沿用,不需要重建。 - docs/HANDOFF-2026-11-02.md:开发机交接(环境、仓库地图、三套测试、 本地怎么跑、云端资源清单、上线方式、11 条关键结论、9 项待办、故障对照表) - deploy/:服务器侧配置入库(原先只存在于机器上) - systemd/juzi-taobao.service(18081,独立数据目录与凭据文件) - nginx/tb-location.conf(/tb/ 反代 + 只放行聚石塔 NAT EIP) - add-tb-nginx.sh(幂等插入,先备份,nginx -t 通过才 reload) - README.md(重建与回滚步骤) - tools/env-java.ps1:优先用仓库内便携工具链,缺失时回退 JAVA_HOME/PATH, 换机器不用再下便携 JDK/Maven - README.md:交接文档入口更新
This commit is contained in:
@@ -5,7 +5,9 @@
|
||||
- `h5/`:现有浏览器/微信公众号 H5、管理后台,以及共享后端 `server.js`。
|
||||
- `taobao/`:淘宝原生小程序。开发、联调、测试说明见 [taobao/README.md](taobao/README.md)。
|
||||
- `backend-java/`:SAE + 淘宝云网关的 Java 最小连通性 MVP;操作步骤见 [docs/SAE-Java-MVP-操作步骤.md](docs/SAE-Java-MVP-操作步骤.md)。
|
||||
- 当前交接:[docs/HANDOFF-2026-11-01.md](docs/HANDOFF-2026-11-01.md)。
|
||||
- 当前交接(**换开发机先读这份**):[docs/HANDOFF-2026-11-02.md](docs/HANDOFF-2026-11-02.md)。
|
||||
- 上一轮交接:[docs/HANDOFF-2026-11-01.md](docs/HANDOFF-2026-11-01.md)。
|
||||
- 服务器侧配置(systemd / nginx `/tb/` 白名单 / 安装脚本):[deploy/README.md](deploy/README.md)。
|
||||
- `rednote/`:复用 H5 的持久浏览器身份入口,独立运行和存储。说明见 [rednote/README.md](rednote/README.md)。
|
||||
- `h5/js/skin-score.js`、`report-ui.js`、`report-copy.js`:业务规则的源文件。小程序内的副本由同步脚本生成并检查哈希。
|
||||
- `h5/lib/taobao-*.js`:淘宝网关验签、短期上传/异步任务和独立 API 路由。
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
# deploy —— 1me.xajuzi.com 上的「淘宝专用」Node 实例
|
||||
|
||||
这份目录存放**不在 git 里自动生效**的服务器侧配置:systemd unit、nginx 片段、安装脚本。
|
||||
换机器/换人接手时,按本文重建即可。
|
||||
|
||||
## 拓扑
|
||||
|
||||
```
|
||||
淘宝小程序(taobao/,AppKey 35486228)
|
||||
→ 淘宝云网关(注入 app_key / open_id / sign,单请求 10s / 128KB 上限)
|
||||
→ 聚石塔云应用 1me-net(62829) → 私网 CLB 192.168.65.185:80
|
||||
→ SAE 应用 nnn(taobao-mvp-backend-0.0.4-forward.jar,mode=forward,纯透传)
|
||||
→ 聚石塔 NAT 网关出网(EIP 47.92.113.176)
|
||||
→ https://1me.xajuzi.com/tb/ (nginx 白名单只放行上面这个 EIP)
|
||||
→ juzi-taobao.service(Node,127.0.0.1:18081,本文档这套配置)
|
||||
→ 旷视 Face++ skinanalyze_pro
|
||||
```
|
||||
|
||||
生产 H5(`/state/`)和红书渠道(`/rednote/`)跑在同机另外两个 systemd 服务上,**8080/8081 端口,和本实例完全隔离**。
|
||||
|
||||
## 三个服务的分工
|
||||
|
||||
| 服务 | 端口 | 代码目录 | 用途 |
|
||||
|---|---|---|---|
|
||||
| `juzi-h5.service` | 8080 | `/home/ubuntu/juzi/h5` | 生产 H5(微信登录、报告、后台) |
|
||||
| `juzi-rednote.service` | 8081 | `/home/ubuntu/juzi-rednote/current/h5` | 小红书渠道隔离实例 |
|
||||
| `juzi-taobao.service` | 18081 | `/home/ubuntu/juzi-tb/h5` | **本目录新增**:淘宝小程序专用 |
|
||||
|
||||
## 重建步骤
|
||||
|
||||
### 1. 代码
|
||||
|
||||
`/home/ubuntu/juzi-tb` 是**独立的一份 h5 代码**(不是生产目录的软链),来自本仓库的 `h5/`。
|
||||
部署方式(本地执行,把仓库里的 h5 打包传上去):
|
||||
|
||||
```powershell
|
||||
# 本地仓库根目录
|
||||
tar -czf temp/juzi-h5.tgz --exclude=h5/data --exclude=h5/test --exclude=h5/scripts -C . h5
|
||||
scp temp/juzi-h5.tgz ubuntu@1me.xajuzi.com:/tmp/
|
||||
```
|
||||
|
||||
```bash
|
||||
# 服务器上
|
||||
sudo mkdir -p /home/ubuntu/juzi-tb /home/ubuntu/juzi-tb-data
|
||||
sudo chown -R ubuntu:ubuntu /home/ubuntu/juzi-tb /home/ubuntu/juzi-tb-data
|
||||
chmod 700 /home/ubuntu/juzi-tb-data
|
||||
tar -xzf /tmp/juzi-h5.tgz -C /home/ubuntu/juzi-tb
|
||||
|
||||
# 旷视凭据复用生产那份(gitignored,不随仓库走)
|
||||
mkdir -p /home/ubuntu/juzi-tb/reference/facepp-skinanalyze
|
||||
cp /home/ubuntu/juzi/reference/facepp-skinanalyze/credentials.env \
|
||||
/home/ubuntu/juzi-tb/reference/facepp-skinanalyze/credentials.env
|
||||
chmod 600 /home/ubuntu/juzi-tb/reference/facepp-skinanalyze/credentials.env
|
||||
```
|
||||
|
||||
> `h5/server.js` 启动时如果找不到旷视 key 会直接 `exit(1)`,所以这一步不能漏。
|
||||
|
||||
### 2. 淘宝凭据
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /etc/juzi
|
||||
sudo tee /etc/juzi/taobao.env >/dev/null <<'EOF'
|
||||
TAOBAO_APP_KEY=35486228
|
||||
TAOBAO_APP_SECRET=<35486228 的 AppSecret,向项目负责人索取>
|
||||
EOF
|
||||
sudo chmod 600 /etc/juzi/taobao.env && sudo chown root:root /etc/juzi/taobao.env
|
||||
```
|
||||
|
||||
这个文件被 `h5/lib/taobao-auth.js` 读取,用于校验云网关签名。**没有它,`/session` 一律 401。**
|
||||
|
||||
### 3. systemd
|
||||
|
||||
```bash
|
||||
scp deploy/systemd/juzi-taobao.service ubuntu@1me.xajuzi.com:/tmp/
|
||||
ssh ubuntu@1me.xajuzi.com "sudo install -m 644 -o root -g root /tmp/juzi-taobao.service /etc/systemd/system/ \
|
||||
&& sudo systemctl daemon-reload && sudo systemctl enable --now juzi-taobao && systemctl is-active juzi-taobao"
|
||||
```
|
||||
|
||||
### 4. nginx
|
||||
|
||||
```bash
|
||||
# 本地
|
||||
scp deploy/add-tb-nginx.sh deploy/nginx/tb-location.conf ubuntu@1me.xajuzi.com:/tmp/
|
||||
|
||||
# 服务器
|
||||
ssh ubuntu@1me.xajuzi.com "sed -i 's/\r\$//' /tmp/add-tb-nginx.sh && bash /tmp/add-tb-nginx.sh /tmp/tb-location.conf"
|
||||
```
|
||||
|
||||
脚本是幂等的(检测到 `location /tb/` 就跳过),会先备份成 `juzi.bak-tb-<时间戳>`。
|
||||
|
||||
### 5. 验收
|
||||
|
||||
```bash
|
||||
# 服务器本机(127.0.0.1 在白名单里)
|
||||
curl -sk -H 'Host: 1me.xajuzi.com' https://127.0.0.1/tb/api/health
|
||||
# 期望 {"ok":true}
|
||||
|
||||
# 公网(应被白名单挡掉)
|
||||
curl -s -o /dev/null -w '%{http_code}\n' https://1me.xajuzi.com/tb/api/health
|
||||
# 期望 403
|
||||
|
||||
# 生产 H5 不受影响
|
||||
curl -s -o /dev/null -w '%{http_code}\n' https://1me.xajuzi.com/state/api/health
|
||||
# 期望 200
|
||||
```
|
||||
|
||||
最后在聚石塔 SAE 容器里再验一次(这是唯一走 NAT 的路径):
|
||||
|
||||
```bash
|
||||
curl -s https://1me.xajuzi.com/tb/api/health # 期望 {"ok":true}
|
||||
```
|
||||
|
||||
## 回滚
|
||||
|
||||
```bash
|
||||
sudo systemctl disable --now juzi-taobao
|
||||
sudo cp /etc/nginx/sites-available/juzi.bak-tb-<时间戳> /etc/nginx/sites-available/juzi
|
||||
sudo nginx -t && sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
生产两个服务完全不受影响(端口、目录、数据都是独立的)。
|
||||
|
||||
## 数据
|
||||
|
||||
- 运行数据:`/home/ubuntu/juzi-tb-data`(700)—— 照片 `photos/`、原始返回 `results/`、记录 `records.jsonl`、账号 `accounts/`
|
||||
- 与生产的 `/home/ubuntu/juzi/h5/data` 完全分开,两边用户/报告不互通
|
||||
- **没有任何自动清理**:每次检测约 10–12MB 常驻磁盘,长期要换 OSS + RDS
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/bin/bash
|
||||
# 幂等地把 deploy/nginx/tb-location.conf 插入 /etc/nginx/sites-available/juzi。
|
||||
# 只做「插入一段 location」,不改动任何已有 location;先备份,nginx -t 通过才 reload。
|
||||
#
|
||||
# 用法(在 1me.xajuzi.com 上):
|
||||
# scp deploy/add-tb-nginx.sh deploy/nginx/tb-location.conf ubuntu@1me.xajuzi.com:/tmp/
|
||||
# ssh ubuntu@1me.xajuzi.com "sed -i 's/\r$//' /tmp/add-tb-nginx.sh && bash /tmp/add-tb-nginx.sh"
|
||||
set -euo pipefail
|
||||
|
||||
CONF=/etc/nginx/sites-available/juzi
|
||||
SNIPPET=${1:-/tmp/tb-location.conf}
|
||||
STAMP=$(date +%Y%m%d%H%M%S)
|
||||
BACKUP="$CONF.bak-tb-$STAMP"
|
||||
|
||||
if grep -q 'location /tb/' "$CONF"; then
|
||||
echo "SKIP: /tb/ 已存在,不重复插入"
|
||||
exit 0
|
||||
fi
|
||||
if [ ! -f "$SNIPPET" ]; then
|
||||
echo "缺少片段文件: $SNIPPET" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sudo cp "$CONF" "$BACKUP"
|
||||
echo "BACKUP: $BACKUP"
|
||||
|
||||
sudo python3 - "$CONF" "$SNIPPET" <<'PY'
|
||||
import sys
|
||||
|
||||
conf_path, snippet_path = sys.argv[1], sys.argv[2]
|
||||
text = open(conf_path, encoding='utf-8').read()
|
||||
snippet = open(snippet_path, encoding='utf-8').read()
|
||||
|
||||
block = "# BEGIN taobao-debug 2026-11-01\n" + snippet + "# END taobao-debug 2026-11-01\n\n"
|
||||
marker = " location / {\n"
|
||||
if marker not in text:
|
||||
sys.exit("marker 'location / {' not found")
|
||||
text = text.replace(marker, block + marker, 1)
|
||||
open(conf_path, 'w', encoding='utf-8').write(text)
|
||||
print("INSERTED")
|
||||
PY
|
||||
|
||||
echo "--- nginx -t ---"
|
||||
sudo nginx -t
|
||||
echo "--- reload ---"
|
||||
sudo systemctl reload nginx
|
||||
echo "RELOADED"
|
||||
@@ -0,0 +1,25 @@
|
||||
# 插入到 /etc/nginx/sites-available/juzi 的 HTTPS server { } 块内。
|
||||
# 作用:给淘宝小程序云网关一个专用入口 /tb/,反代到 juzi-taobao.service(127.0.0.1:18081)。
|
||||
#
|
||||
# 为什么要 allow 白名单:/tb/ 暴露在公网,后面是真实旷视计费调用。
|
||||
# 只允许聚石塔 NAT 的出口 EIP(以及本机自测)访问,其余一律 403。
|
||||
#
|
||||
# 注意:nginx 会剥掉 /tb/ 前缀,所以 /tb/api/taobao/session → Node 收到 /api/taobao/session,
|
||||
# 与 h5/server.js 的路由完全一致。
|
||||
location = /tb {
|
||||
return 301 /tb/;
|
||||
}
|
||||
location /tb/ {
|
||||
# 聚石塔 NAT 网关绑定的 EIP。换环境时改这一行。
|
||||
allow 47.92.113.176;
|
||||
# 本机自测(curl -H 'Host: 1me.xajuzi.com' https://127.0.0.1/tb/api/health)
|
||||
allow 127.0.0.1;
|
||||
deny all;
|
||||
|
||||
proxy_pass http://127.0.0.1:18081/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 150s;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
[Unit]
|
||||
Description=1me taobao mini program backend (Node, /tb/ debug instance)
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=ubuntu
|
||||
WorkingDirectory=/home/ubuntu/juzi-tb/h5
|
||||
# 独立于生产 juzi-h5(8080)/juzi-rednote(8081):独立端口、独立数据目录、独立凭据文件
|
||||
Environment=JUZI_ENTRY_MODE=state
|
||||
Environment=NODE_ENV=production
|
||||
Environment=HOST=127.0.0.1
|
||||
Environment=PORT=18081
|
||||
Environment=JUZI_DATA_ROOT=/home/ubuntu/juzi-tb-data
|
||||
Environment=TRUST_LOOPBACK_PROXY=1
|
||||
# 内容格式:
|
||||
# TAOBAO_APP_KEY=35486228
|
||||
# TAOBAO_APP_SECRET=<35486228 的 AppSecret>
|
||||
# 权限 600 root,绝不入库。
|
||||
EnvironmentFile=/etc/juzi/taobao.env
|
||||
ExecStart=/usr/bin/node /home/ubuntu/juzi-tb/h5/server.js
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
UMask=0077
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,301 @@
|
||||
# 开发交接 —— 换一台开发机继续做(2026-11-02)
|
||||
|
||||
> **写给**:在新 Windows 机器上接手的人(或未来的 agent)
|
||||
> **不涉及**:服务器 / 聚石塔 / SAE 都不用重建,云端资源全部现成可用
|
||||
> **上一份**:[HANDOFF-2026-11-01.md](HANDOFF-2026-11-01.md)(那一轮只到「链路打通 + Java MVP」,UI 和真机测肤是这一轮做的)
|
||||
|
||||
---
|
||||
|
||||
## 0. 一句话状态
|
||||
|
||||
**真机全链路已跑通**:淘宝小程序 → 云网关(AppKey 35486228)→ 聚石塔云应用 1me-net → 私网 CLB → SAE `nnn`(只做透传)→ 聚石塔 NAT 出网(EIP `47.92.113.176`)→ `https://1me.xajuzi.com/tb/` → 现有 H5 的 Node 服务 → 旷视 Face++,**三视图拍摄后报告正常返回**。
|
||||
|
||||
小程序五个页面的 UI 已按 H5 重做(像素级对齐,见下)。剩下的是相机组件验证和一批工程化工作,清单在第 8 节。
|
||||
|
||||
---
|
||||
|
||||
## 1. 新机器准备
|
||||
|
||||
### 1.1 必装
|
||||
|
||||
| 工具 | 版本 | 用途 |
|
||||
|---|---|---|
|
||||
| Git | 任意近期版本 | 拉代码 |
|
||||
| Node.js | **18+(推荐 20/22)** | `taobao/` 测试、`h5/` 本地跑、零依赖 |
|
||||
| JDK | **17** | `backend-java/` 编译与测试 |
|
||||
| Maven | 3.9.x | 同上 |
|
||||
| 淘宝小程序开发者工具 | 最新 | 真机预览(**模拟器不支持云应用 SDK**) |
|
||||
| PowerShell 7(可选) | 7.x | 仓库里的脚本按 pwsh 语法写 |
|
||||
|
||||
### 1.2 拉代码
|
||||
|
||||
```powershell
|
||||
git clone https://git.xiangsilian.com/xsl/juzi.git
|
||||
cd juzi
|
||||
```
|
||||
|
||||
> 远端证书有效期到 2027-01-29;凭据失效时重新配置 Git 凭据管理器。
|
||||
|
||||
### 1.3 小程序依赖(必做,否则真机报 `Cannot find module`)
|
||||
|
||||
```powershell
|
||||
cd taobao
|
||||
npm ci
|
||||
```
|
||||
|
||||
`@tbmp/mp-cloud-sdk` 固定 1.5.10,只有这一个运行期依赖。
|
||||
|
||||
### 1.4 工具链
|
||||
|
||||
仓库自带 `tools/env-java.ps1`,查找顺序:仓库内便携工具链 → 环境变量 → PATH。
|
||||
|
||||
```powershell
|
||||
Set-ExecutionPolicy -Scope Process Bypass
|
||||
. .\tools\env-java.ps1 # 输出 JAVA_HOME / MAVEN_HOME / java -version
|
||||
```
|
||||
|
||||
- 用系统安装的 JDK 17 + Maven 即可,**不需要**再下便携版
|
||||
- 想复原老机器的布局:把 JDK 放 `tools/jdk17/`、Maven 放 `tools/maven/apache-maven-3.9.9/`(这两个目录 gitignore)
|
||||
|
||||
### 1.5 必须单独拷贝的机密文件(**不在 git 里**)
|
||||
|
||||
| 文件 | 内容 | 没有会怎样 |
|
||||
|---|---|---|
|
||||
| `backend-java/src/main/resources/application-local.yml` | 淘宝 AppKey/AppSecret + `mode: forward` + `forward-base` | JAR 里没有 AppKey/Secret,`/session` 一定 401 |
|
||||
| `reference/facepp-skinanalyze/credentials.env` | 旷视 `FACEPP_API_KEY/SECRET` | `h5/server.js` 启动即 `exit(1)` |
|
||||
| SSH 私钥 | 免密登录 `ubuntu@1me.xajuzi.com` | 无法部署 Node 侧 / 看日志 |
|
||||
|
||||
```powershell
|
||||
# 从老机器拷(示例)
|
||||
scp <老机器>:D:/juzi/backend-java/src/main/resources/application-local.yml .\backend-java\src\main\resources\
|
||||
scp <老机器>:D:/juzi/reference/facepp-skinanalyze/credentials.env .\reference\facepp-skinanalyze\
|
||||
```
|
||||
|
||||
新机器要能 ssh 服务器的话:`ssh-keygen -t ed25519` 后把公钥追加到服务器 `~/.ssh/authorized_keys`。
|
||||
|
||||
> 老机器若已不可用:AppSecret / 旷视 key 找项目负责人索取,或在开放平台重置(重置后记得同步更新服务器 `/etc/juzi/taobao.env` 与 JAR)。
|
||||
|
||||
### 1.6 淘宝 IDE 的一个已知坑(Windows)
|
||||
|
||||
老机器上 IDE 曾因 `wmic` 缺失打不开,用 `tools/fix-taobao-ide-wmic.ps1` 生成过一个 shim(`C:\Users\<你>\.local\bin\wmic.cmd`)。新机器如果 IDE 报 `install miniapp extension fail: ... wmic ...`,跑这个脚本。
|
||||
|
||||
---
|
||||
|
||||
## 2. 仓库地图
|
||||
|
||||
```
|
||||
juzi/
|
||||
├── taobao/ 淘宝小程序(当前主战场)
|
||||
│ ├── config.js ★ 环境/传输配置(cloud+tower+test、assetBase)
|
||||
│ ├── app.acss ★ 全局设计 token(对齐 H5 的 .btn-primary/.card/.chev/.popup)
|
||||
│ ├── pages/
|
||||
│ │ ├── splash/ 启动页(登录、隐私弹窗、开发版入口)
|
||||
│ │ ├── profile/ 档案填写(出生/性别/地区/肤质轮播)
|
||||
│ │ ├── camera/ 拍照页(蒙版取景 or 系统相机兜底)
|
||||
│ │ ├── report/ 报告页(环形分、7 视角、叠加层、标记点)
|
||||
│ │ ├── history/ 历史报告
|
||||
│ │ ├── mvp/ 连通性调试页(ping/whoami/echo)
|
||||
│ │ └── camtest/ ★ 相机组件冒烟页(只放 <camera>,判断组件是否可用)
|
||||
│ ├── utils/
|
||||
│ │ ├── transport.js 云网关/direct 两种传输 + 信封解包
|
||||
│ │ ├── api.js 9 个接口封装(challenge/session/me/photo/skin-analyze/…)
|
||||
│ │ ├── permissions.js ★ 权限(scope 前缀、诊断 diagnose())
|
||||
│ │ ├── image.js 1280 长边 + JPEG q0.88 压缩
|
||||
│ │ ├── voice.js 语音播报(异常静默)
|
||||
│ │ └── report-model.js payload → 报告页 data
|
||||
│ └── test/ 20 个 node:test 用例
|
||||
├── h5/ ★ 真正的测肤后端(Node,零依赖)
|
||||
│ ├── server.js 入口:Face++ 调用、评分、报告、admin
|
||||
│ ├── lib/taobao-*.js ★ 淘宝云网关路由/验签/会话(关键算法在这里)
|
||||
│ ├── js/skin-score.js 评分引擎(6 类 → 3 维,4:3:3 加权)
|
||||
│ └── test/ 一堆独立测试脚本(没有统一 runner)
|
||||
├── backend-java/ SAE 上的透传层(Spring Boot 3.5.6 / Java 17)
|
||||
│ ├── src/main/java/com/juzi/mvp/api/
|
||||
│ │ ├── TaobaoForwardController.java ★ mode=forward 时字节级透传
|
||||
│ │ ├── TaobaoEnvelope.java 客户端要的 data.ok + data.http_status
|
||||
│ │ ├── TaobaoAuthController.java native 模式的登录接口(当前未启用)
|
||||
│ │ └── TaobaoSessionService.java challenge + Bearer token
|
||||
│ └── src/main/java/com/juzi/mvp/gateway/TaobaoSignatureVerifier.java 验签算法
|
||||
├── deploy/ ★ 服务器侧配置(systemd / nginx / 安装脚本)
|
||||
├── docs/ 交接与实施文档(本文件所在)
|
||||
└── tools/ 构建与素材脚本
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 三套测试
|
||||
|
||||
```powershell
|
||||
# 1) 小程序:20 个用例
|
||||
cd taobao ; npm test
|
||||
|
||||
# 2) Java:11 个用例(含验签向量的回归测试)
|
||||
cd backend-java ; mvn test
|
||||
|
||||
# 3) H5 单测(独立脚本,逐个跑)
|
||||
node h5/test/taobao-auth.js # 网关签名,必须 PASS
|
||||
```
|
||||
|
||||
**改动提交前请保证**:`taobao` 20/20 + `backend-java` 11/11。老机器最后一次全绿是在 `fed5293`。
|
||||
|
||||
> `taobao/test/frontend.test.cjs` 会用 vm 真跑页面 JS,页面 data 字段改名要同步改测试。
|
||||
|
||||
---
|
||||
|
||||
## 4. 本地怎么跑
|
||||
|
||||
### 4.1 H5 后端(Node,测肤真正的实现)
|
||||
|
||||
```powershell
|
||||
cd h5
|
||||
$env:PORT=8099 ; $env:HOST='127.0.0.1' ; $env:JUZI_ENTRY_MODE='state'
|
||||
$env:JUZI_DATA_ROOT='..\temp\h5-data'
|
||||
node server.js
|
||||
# http://127.0.0.1:8099/api/health → {"ok":true}
|
||||
```
|
||||
|
||||
启动时缺旷视 key 会直接退出。只想调 UI/接口时给假值即可(真实检测会失败,但路由可用):
|
||||
|
||||
```powershell
|
||||
$env:SKIN_API_KEY='dummy' ; $env:SKIN_API_SECRET='dummy'
|
||||
```
|
||||
|
||||
### 4.2 Java(SAE 那一层)
|
||||
|
||||
```powershell
|
||||
. .\tools\env-java.ps1
|
||||
cd backend-java
|
||||
mvn spring-boot:run # 或 mvn -DskipTests package 后 java -jar target\*.jar
|
||||
curl.exe -X POST -H "Content-Type: application/json" -d "{}" http://127.0.0.1:8080/api/taobao/ping
|
||||
```
|
||||
|
||||
- 默认 `mode: native`(Java 自己实现登录,便于单独调接口)
|
||||
- 部署用的 `application-local.yml` 里写的是 `mode: forward`
|
||||
- 本地想看透传:`$env:TAOBAO_MODE='forward'` + `$env:TAOBAO_FORWARD_BASE='http://127.0.0.1:8099'`
|
||||
|
||||
### 4.3 小程序
|
||||
|
||||
1. 淘宝 IDE 导入仓库里的 `taobao/`(`mini.project.json` 的 `appid` 留空,以 IDE 账号为准)
|
||||
2. **确认 IDE 当前小程序是 35486228(`1me 肌肤状态检测`)**
|
||||
3. `config.js` 保持 `transport: 'cloud'` / `cloudType: 'tower'` / `cloudEnv: 'test'`
|
||||
4. 顶部「预览」→ **手机淘宝扫码**(模拟器不支持 `cloud.application.httpRequest`)
|
||||
5. 启动页右上角有三个**开发版入口**(`environment !== 'production'` 时才显示):
|
||||
|
||||
| 入口 | 作用 |
|
||||
|---|---|
|
||||
| 权限诊断 | 打印 `my.canIUse`、`getSetting` 的 authSetting、`authorize` 的原始返回(真机上唯一能看到这些的地方) |
|
||||
| 相机组件测试 | 整页只有一个 `<camera>`,用来判断组件是否可用 |
|
||||
| SAE MVP 连通性 | `ping/whoami/echo`,看 `transport:"gateway"`、`server:"java"` |
|
||||
|
||||
---
|
||||
|
||||
## 5. 云端资源(只读,无需重建)
|
||||
|
||||
| 资源 | 值 |
|
||||
|---|---|
|
||||
| 开放平台应用 | `1me 肌肤状态检测`,AppKey **35486228** |
|
||||
| 旧应用(废弃) | `1me肌肤检测` 35479221 —— **不要再用它的 Secret** |
|
||||
| 聚石塔云应用 | `1me-net`,ID **62829**,默认应用 |
|
||||
| 私网 CLB | `lb-k2j324dwux1svaf2akwqx` / `192.168.65.185:80` |
|
||||
| SAE 应用 | `nnn`,`cn-zhangjiakou:my-namespace` |
|
||||
| 代码包 | `taobao-mvp-backend-0.0.4-forward.jar`(**环境变量全空**,配置都在包里) |
|
||||
| VPC / vSwitch | `vpc-8vb5mcvenp8jwa1roqcsa` / `vsw-8vbna5zb2rq03gaeiymch`(可用区 A) |
|
||||
| NAT 出口 EIP | **47.92.113.176**(nginx `/tb/` 白名单按它放行) |
|
||||
| 服务器 | `ubuntu@1me.xajuzi.com`,Node v20.20.2 |
|
||||
| 生产 H5 | `https://1me.xajuzi.com/state/` → `juzi-h5.service`(8080) |
|
||||
| 红书渠道 | `https://1me.xajuzi.com/rednote/` → `juzi-rednote.service`(8081) |
|
||||
| 淘宝专用 | `https://1me.xajuzi.com/tb/` → `juzi-taobao.service`(18081) |
|
||||
|
||||
---
|
||||
|
||||
## 6. 改完怎么上线
|
||||
|
||||
### 6.1 小程序
|
||||
IDE 编译 → 预览(自测)→ 「上传」发版本。**不需要碰服务器。**
|
||||
|
||||
### 6.2 Java(SAE)
|
||||
```powershell
|
||||
. .\tools\env-java.ps1 ; cd backend-java
|
||||
mvn clean package # 测试会自动跑
|
||||
# 产物 target\taobao-mvp-backend-0.0.4-forward.jar
|
||||
```
|
||||
SAE 控制台 → `nnn` → 部署应用 → 代码包部署 → 上传 JAR(**版本号要和上次不同**,否则会被当成同一个版本)→ 环境变量保持全空。
|
||||
|
||||
### 6.3 Node(`/tb` 实例)
|
||||
见 [deploy/README.md](../deploy/README.md) 第 1 节。核心三步:
|
||||
|
||||
```powershell
|
||||
tar -czf temp/juzi-h5.tgz --exclude=h5/data --exclude=h5/test -C . h5
|
||||
scp temp/juzi-h5.tgz ubuntu@1me.xajuzi.com:/tmp/
|
||||
```
|
||||
```bash
|
||||
ssh ubuntu@1me.xajuzi.com "tar -xzf /tmp/juzi-h5.tgz -C /home/ubuntu/juzi-tb && sudo systemctl restart juzi-taobao"
|
||||
```
|
||||
|
||||
> ⚠️ **不要动** `/home/ubuntu/juzi`(生产 H5)和 `/home/ubuntu/juzi-rednote`。我们那份是独立拷贝 `/home/ubuntu/juzi-tb`。
|
||||
|
||||
---
|
||||
|
||||
## 7. 这一轮的关键结论(踩过的坑,别重复踩)
|
||||
|
||||
1. **云网关签名算法**:真实请求**不带 `sign_method`**,缺省等价于 `MD5(secret + content + secret)`(`content` = 排序后的 `key+value` 拼接 + **原始 body 字节**)。之前按 `MD5(content + secret)` 实现,是 10 月底那个「signature mismatch」的真因。改在 [h5/lib/taobao-auth.js](../h5/lib/taobao-auth.js)。
|
||||
2. **淘宝的 scope 是带前缀的** `scope.camera` / `scope.album`;传裸名 `camera` 返回 `{"errorCode":"5022","errorMessage":"Scope:camera信息不存在"}`。
|
||||
3. **`<camera>` 组件在真机上会让整页崩溃**,且 `my.canIUse('camera')` 返回 `yes` 是**假阳性**。当前默认走系统相机(`config.nativeCamera = false`)。怀疑原因是相机里嵌了**微信专有的 `<cover-view>`**,已改成兄弟节点 + 普通 view 覆盖,并加了 `pages/camtest` 冒烟页——**这个还没在真机验证,是新机器的第一件事**。
|
||||
4. **网关限制**:单请求 **10 秒 / 128KB**。所以 `skin-analyze` 必须 **202 + 1 秒轮询(最长 90 秒)**,不能同步等旷视。
|
||||
5. **旷视 Face++**:正式 key 有并发窗口,必须**串行 + 4 秒间隔**;60 秒超时,失败/5xx/并发超限重试 1 次;返回值含 `face_maps`,4000px 素材时约 3.2MB(真实链路客户端压到 1280,约 200–300KB)。
|
||||
6. **`/api/taobao/reports` 详情带 3 张 base64 照片**,历史报告页有超时风险(网关大响应未验证)。
|
||||
7. **会话/任务全在内存**:SAE 只能单副本;`juzi-taobao` 重启后登录态与进行中的任务都会丢。
|
||||
8. **没有任何清理策略**:每次检测在磁盘留 10–12MB,长期必须换 OSS。
|
||||
9. **转发必须字节级透传**:签名覆盖原始 body 和 query,Java 一旦重新序列化 JSON 就会 401。
|
||||
10. **生产那台 Node 是旧代码**,没有 `/api/taobao/*`;我们另外起 `/home/ubuntu/juzi-tb`(18081)跑新代码,用 nginx `/tb/` 分流。
|
||||
11. **图片资源**走 `https://1me.xajuzi.com/state/assets/`(`config.assetBase`)。之前是 `127.0.0.1:18180`,真机上全部加载失败。
|
||||
|
||||
---
|
||||
|
||||
## 8. 待办(建议顺序)
|
||||
|
||||
| # | 事项 | 说明 |
|
||||
|---|---|---|
|
||||
| 1 | **真机验证 `pages/camtest`** | 能出实时画面 → 把 `config.nativeCamera` 改 `true`,拍照页立刻有蒙版取景;仍然崩 → 维持系统相机 |
|
||||
| 2 | `/reports` 详情瘦身 | 现在透传 3 张 base64 原图(约 0.5MB+),改缩略图或 OSS URL |
|
||||
| 3 | 存储工程化 | 照片/原始 JSON/记录 → OSS + RDS;现在全在容器/单机磁盘,无清理 |
|
||||
| 4 | 旷视请求裁剪 | `return_maps` 请求 10 层但报告只用 6 层,可少传 4 层省带宽与落盘 |
|
||||
| 5 | WebP 转码(可选) | 实测:6 层图 WebP q80 省 54%,叠 50% 缩放省 84%;**先真机验证 `<image>` 支持 WebP data URL** |
|
||||
| 6 | 密钥治理 | `application-local.yml` / `/etc/juzi/taobao.env` 里的 AppSecret、JAR 内嵌 Secret → 改 KMS/保密字典,并**重置一次 AppSecret** |
|
||||
| 7 | Java 端可选迁移 | `mode=native` 的登录接口已写好并测过(4 个用例),可把 auth 从 Node 搬到 Java;测肤仍留在 Node |
|
||||
| 8 | 仓库收拾 | `sdk-java-35479221/`、三个 `.pptx`、`tools/build_taobao_proposal_*.py` 仍未跟踪,建议加 ignore 或删除 |
|
||||
| 9 | 启用签名校验(Java 侧) | 当前 forward 模式下由 Node 验签;若切 `native` 或要 `/ping` 也验签,把 `verify-sign` 打开即可(算法已修复) |
|
||||
|
||||
---
|
||||
|
||||
## 9. 故障对照表
|
||||
|
||||
| 现象 | 原因 | 处理 |
|
||||
|---|---|---|
|
||||
| 真机 `cloud init failed` | IDE 当前 app 不是 35486228 / 云应用没设默认 | 确认 IDE 账号与 AppKey |
|
||||
| `淘宝身份校验失败,请重新授权登录` | 云网关签名不匹配 | 检查服务器 `/etc/juzi/taobao.env` 的 AppSecret;算法见第 7 节第 1 条 |
|
||||
| `请先配置淘宝云应用和 HTTPS 服务地址` | `cloudType` 不是 `tower` 或 `transport` 不是 `cloud` | 看 `config.js` |
|
||||
| 页面一片灰没有图 | `assetBase` 指向 127.0.0.1 | 应为 `https://1me.xajuzi.com/state/assets/` |
|
||||
| 点拍照整页崩(「系统遇到一点问题」) | `<camera>` 组件 | 保持 `nativeCamera: false`,用系统相机/相册 |
|
||||
| 报告页白屏 | `payload` 为空或 `report-model` 抛错 | 看启动页「SAE MVP 连通性」是否 `server:"java"` |
|
||||
| SAE 侧 `上游 403` | 容器出口 IP 不在 nginx `/tb/` 白名单 | `curl -s https://myip.ipip.net` 取新 IP,改 nginx 后 reload |
|
||||
| `Cannot find module '@tbmp/mp-cloud-sdk'` | 没装依赖 / IDE 没构建 npm | `npm ci`,IDE「工具 → 构建 npm」 |
|
||||
| Java 打包报找不到 `application-local.yml` | 机密文件没拷过来 | 见 1.5 |
|
||||
|
||||
---
|
||||
|
||||
## 10. 交接检查清单
|
||||
|
||||
- [ ] `npm ci`(taobao)跑过
|
||||
- [ ] `tools/env-java.ps1` 能加载出 JDK17 + Maven
|
||||
- [ ] `application-local.yml` 与 `credentials.env` 已从老机器拷来
|
||||
- [ ] `taobao` 20/20、`backend-java` 11/11、`node h5/test/taobao-auth.js` PASS
|
||||
- [ ] IDE 打开 `taobao/` 并确认 AppKey 是 35486228
|
||||
- [ ] 真机预览能看到图片(说明资产域名通)
|
||||
- [ ] 真机点「权限诊断」→ `authorize(scope.camera)=ok`
|
||||
- [ ] 真机点「相机组件测试」→ 记录结果,决定 `nativeCamera` 开关
|
||||
- [ ] 能 `ssh ubuntu@1me.xajuzi.com`,`systemctl is-active juzi-taobao` 为 active
|
||||
|
||||
---
|
||||
|
||||
**给接手者的第一句话**:先按第 1 节把机器装好、把两个机密文件拷过来,跑通三套测试;然后去真机验 `camtest`——那是唯一还悬着的技术问题,也决定拍照页最终形态。
|
||||
+32
-14
@@ -1,26 +1,42 @@
|
||||
# 在当前 PowerShell 会话中加载 JDK 17 + Maven 3.9.9
|
||||
# 用法:. D:\juzi\tools\env-java.ps1
|
||||
# 在当前 PowerShell 会话中加载 JDK 17 + Maven
|
||||
# 用法:. <仓库根>\tools\env-java.ps1
|
||||
#
|
||||
# 查找顺序:
|
||||
# 1) 仓库内便携工具链 tools\jdk17\* + tools\maven\apache-maven-3.9.9(不入库,换机器需自备)
|
||||
# 2) 已导出的环境变量 $env:JAVA_HOME / $env:MAVEN_HOME
|
||||
# 3) PATH 上的 java / mvn(例:scoop/choco/winget 安装的)
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$projectRoot = Split-Path -Parent $PSScriptRoot
|
||||
$jdkRoot = Join-Path $projectRoot 'tools\jdk17'
|
||||
$jdkCandidates = @($jdkRoot)
|
||||
if (Test-Path $jdkRoot) {
|
||||
$jdkCandidates += Get-ChildItem $jdkRoot -Directory -ErrorAction SilentlyContinue |
|
||||
ForEach-Object { $_.FullName }
|
||||
|
||||
function Find-Jdk {
|
||||
$root = Join-Path $projectRoot 'tools\jdk17'
|
||||
$candidates = @()
|
||||
if (Test-Path $root) {
|
||||
$candidates += $root
|
||||
$candidates += Get-ChildItem $root -Directory -ErrorAction SilentlyContinue | ForEach-Object { $_.FullName }
|
||||
}
|
||||
if ($env:JAVA_HOME) { $candidates += $env:JAVA_HOME }
|
||||
return $candidates | Where-Object { $_ -and (Test-Path (Join-Path $_ 'bin\java.exe')) } | Select-Object -First 1
|
||||
}
|
||||
|
||||
$jdkHome = $jdkCandidates |
|
||||
Where-Object { Test-Path (Join-Path $_ 'bin\java.exe') } |
|
||||
Select-Object -First 1
|
||||
function Find-Maven {
|
||||
$portable = Join-Path $projectRoot 'tools\maven\apache-maven-3.9.9'
|
||||
if (Test-Path (Join-Path $portable 'bin\mvn.cmd')) { return $portable }
|
||||
if ($env:MAVEN_HOME -and (Test-Path (Join-Path $env:MAVEN_HOME 'bin\mvn.cmd'))) { return $env:MAVEN_HOME }
|
||||
$onPath = Get-Command mvn -ErrorAction SilentlyContinue
|
||||
if ($onPath) { return Split-Path -Parent (Split-Path -Parent $onPath.Source) }
|
||||
return $null
|
||||
}
|
||||
|
||||
$jdkHome = Find-Jdk
|
||||
if (-not $jdkHome) {
|
||||
throw "JDK 17 not found under $jdkRoot. Run the portable JDK setup first."
|
||||
throw "找不到 JDK 17:请安装 JDK 17 并设置 JAVA_HOME,或把便携版放到 tools\jdk17\"
|
||||
}
|
||||
|
||||
$mavenHome = Join-Path $projectRoot 'tools\maven\apache-maven-3.9.9'
|
||||
if (-not (Test-Path (Join-Path $mavenHome 'bin\mvn.cmd'))) {
|
||||
throw "Maven not found at $mavenHome. Run the portable Maven setup first."
|
||||
$mavenHome = Find-Maven
|
||||
if (-not $mavenHome) {
|
||||
throw "找不到 Maven:请安装 Maven 3.9+ 并放到 PATH,或放便携版到 tools\maven\apache-maven-3.9.9"
|
||||
}
|
||||
|
||||
$env:JAVA_HOME = $jdkHome
|
||||
@@ -29,5 +45,7 @@ $env:PATH = "$jdkHome\bin;$mavenHome\bin;$env:PATH"
|
||||
|
||||
Write-Host "JAVA_HOME=$env:JAVA_HOME"
|
||||
Write-Host "MAVEN_HOME=$env:MAVEN_HOME"
|
||||
# java/mvn 往 stderr 写版本信息,在 ErrorActionPreference=Stop 下会被当成终止错误,这里放宽
|
||||
$ErrorActionPreference = 'Continue'
|
||||
java -version
|
||||
mvn -version
|
||||
|
||||
Reference in New Issue
Block a user