Files
juzi/docs/SAE-Java-MVP-操作步骤.md
T
xsl ac0b7ca42b feat(sae): add Java MVP backend and Taobao connectivity page
Spring Boot 3.5.6 / Java 17 JAR with cloud gateway envelope and ping/whoami/echo; Taobao gateway signature verification matching the Node implementation; /pages/mvp page, splash dev entry and local transport contract test; SAE + 聚石塔 runbook and portable JDK/Maven setup; Windows 11 wmic shim for Taobao DevTools.
2026-10-31 18:35:04 +08:00

444 lines
16 KiB
Markdown
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.
# 淘宝小程序 + Java + SAE 最小 MVP 操作步骤
> 目标:先用一个最小页面,把 **淘宝小程序 → 淘宝云网关(或本地直连)→ Java 后端 → 统一 envelope 返回** 这条链路跑通。
>
> 本文不包含:真实测肤算法、Face++、账号体系、图片分片上传。这些等链路验证通过后,再按现有 Node 实现的接口契约迁到 Java。
>
> 当前时间:2026-10。淘宝开放平台在 2026-05 把聚石塔的部署运维迁到了 ACK/SAE,网上 2023 年以前的“容器部署平台”教程不要照抄。
---
## 0. 本次交付物
| 路径 | 作用 |
|---|---|
| `backend-java/` | Spring Boot 3.5.6 + Java 17 的最小后端,含 `ping/whoami/echo` |
| `backend-java/src/main/java/com/juzi/mvp/gateway/TaobaoSignatureVerifier.java` | 云网关签名校验,算法与现有 Node 实现一致 |
| `taobao/pages/mvp/` | 淘宝小程序连通性页面,直接复用现有 `utils/transport.js` |
| `taobao/config.js` | 新增 `mvpLocal` / `mvpBaseUrl`,不影响主应用原来的 18180 配置 |
| `taobao/app.json` | 注册 `pages/mvp/mvp` |
| `tools/env-java.ps1` | 一键加载 JDK 17 + Maven 3.9.9 |
| `backend-java/README.md` | 后端速查 |
| `docs/SAE-Java-MVP-操作步骤.md` | 本文 |
现有 H5、Node 后端、淘宝主流程页面均未改动;只新增 MVP 页面和两个配置字段。
---
## 1. 环境安装
本机已有:
- Node.js `v22.23.2`:`C:\Program Files\nodejs`
- JDK 17:`D:\juzi\tools\jdk17`
- Maven 3.9.9:`D:\juzi\tools\maven\apache-maven-3.9.9`
PowerShell 默认执行策略是 `Restricted`,直接运行 `.ps1` 或 `npm.ps1` 会被拦。每次新开窗口先执行:
```powershell
Set-ExecutionPolicy -Scope Process Bypass
. D:\juzi\tools\env-java.ps1
```
然后确认:
```powershell
java -version
mvn -version
node -v
npm.cmd -v
```
预期:
- `java version "17.x"`
- `Apache Maven 3.9.9`
- `v22.23.2`
- `10.9.x`
> 如果 `env-java.ps1` 报 “JDK 17 not found”,检查 `D:\juzi\tools\jdk17\<jdk目录>\bin\java.exe` 是否存在;脚本会自动向下找一层目录。
>
> 不要用系统里的 JDK 25 来跑这个 MVP;SAE 运行时选 17,编译也用 17,避免 `UnsupportedClassVersionError`。
---
## 2. 后端本地启动
```powershell
Set-ExecutionPolicy -Scope Process Bypass
. D:\juzi\tools\env-java.ps1
cd D:\juzi\backend-java
mvn -DskipTests package
java -jar target\taobao-mvp-backend-0.0.1-SNAPSHOT.jar
```
第一次 `mvn package` 会下载 Spring Boot 依赖,耐心等几分钟。看到类似日志即成功:
```text
Tomcat started on port 8080 (http)
Started MvpApplication in ...
```
想跑自动化测试(签名算法 + envelope + health):`mvn test`。
### 2.1 另开一个窗口验证
```powershell
curl.exe http://127.0.0.1:8080/actuator/health
curl.exe -X POST -H "Content-Type: application/json" -d "{}" http://127.0.0.1:8080/api/taobao/ping
Invoke-RestMethod -Method Post -Uri http://127.0.0.1:8080/api/taobao/echo -ContentType 'application/json' -Body '{"hello":"world"}' | ConvertTo-Json -Depth 5
```
> PowerShell 调原生 `curl.exe` 时,`-d` 里的双引号可能被吞掉(会看到 `{hello:world}` 解析失败);发 JSON 建议用 `Invoke-RestMethod`,或者把 body 写进文件后用 `--data-binary "@body.json"`。
预期 `ping`:
```json
{
"success": true,
"data": {
"ok": true,
"pong": true,
"server": "java",
"time": "2026-10-30T...+08:00",
"transport": "direct",
"appKey": "",
"openId": "",
"env": "",
"signVerified": false,
"signMessage": "verify-sign=false, skipped (local/direct mode)"
}
}
```
`echo` 预期能看到 `body.hello = "world"`。
> 所有 `/api/taobao/**` 返回的都是云网关要求的 envelope;`/actuator/health` 是给 SAE 健康检查用的普通 JSON,不是 envelope。
### 2.2 不装 IDE 也能跑的前端契约测试
```powershell
cd D:\juzi
node taobao\scripts\mvp-local-check.cjs
```
这个脚本用 Node 模拟 `my.request`,加载真实的 `taobao/utils/transport.js`,直连 8080,验证 `ping/echo/whoami` 和 `unwrap` 解包。预期输出 `PASS`,其中 `ping.server = "java"`。如果这里都不过,先别开 IDE。
---
## 3. 前端本地联调(淘宝 IDE)
### 3.1 安装依赖
```powershell
cd D:\juzi\taobao
npm.cmd ci
```
如果 `npm.cmd` 不在 PATH,用全路径:
```powershell
& "C:\Program Files\nodejs\npm.cmd" ci
```
`@tbmp/mp-cloud-sdk` 已经是 `1.5.10`,与当前 npm 最新版一致。
### 3.2 IDE 导入与启动页
1. 打开淘宝小程序开发者工具,导入 `D:\juzi\taobao`。
2. 填入真实小程序 AppID(`mini.project.json` 里的 `appid` 也可以留空,以 IDE 设置为准)。
3. 工具 → 构建 npm(把 `node_modules` 构建成小程序可用的包)。
4. 本地 `mvpLocal: true` 时,启动页右上角会出现「SAE MVP 连通性」入口,点它即可进入;也可以把启动页临时设为 `pages/mvp/mvp`。
5. 用**桌面模拟器**跑;手机上的 `127.0.0.1` 指向手机自己,连不到你电脑。
### 3.3 当前配置
`taobao/config.js` 新增了:
```js
mvpLocal: true,
mvpBaseUrl: 'http://127.0.0.1:8080',
```
`pages/mvp/mvp.js` 在 `onLoad` 时如果 `mvpLocal === true`,会临时把 `transport` 改成 `direct`、`baseUrl` 改成 `mvpBaseUrl`,离开页面时恢复。这样不会破坏主应用原来指向 `18180` 的 Node 后端配置。
进入页面后会自动调用一次 `/api/taobao/ping`,也可以点三个按钮:
- `POST /api/taobao/ping`
- `POST /api/taobao/whoami`
- `POST /api/taobao/echo`
预期页面显示 `server: "java"`、`pong: true`。
> 如果 IDE 拦截 localhost 请求,打开 IDE 的“不校验合法域名”/“开发环境不校验请求域名”开关(不同版本叫法不同)。桌面模拟器一般可以直接访问回环地址。
### 3.4 这一步验证了什么
- 小程序的 `utils/transport.js` 能走 `direct` 分支;
- `my.request` 能发 `POST application/json`;
- `transport.unwrap` 能正确解包 `{success,data}`;
- Java 后端端口、路径、返回结构都对。
---
## 4. 云端链路(SAE + 聚石塔云应用)
### 4.1 先理解三层关系
```text
淘宝小程序
└─ @tbmp/mp-cloud-sdk
└─ 淘宝云网关(校验 appkey/sign,注入 open_id/access_token)
└─ 聚石塔云应用(应用/环境/流量接入)
└─ SAE(真正的 Java 容器,跑 JAR)
```
- **SAE 只是算力层**,不是“建一个公网 URL 就能被小程序调用”。
- 小程序要调通,SAE 应用必须挂在**聚石塔云应用**下,或者走**空应用(不入塔)+ 域名白名单**。
- 2026-05-11 公告:原聚石塔“应用创建链路”2026-06-20 下线,部署运维迁到 ACK/SAE;聚石塔保留云应用管理、环境管理、流量接入。
- 参考:[迁移通知](https://api.alidayu.com/support/announcementDetail.htm?source=search&id=25839)、[新链路快速创建云应用](https://open.taobao.com/doc.htm?docId=122332&docType=1)、[云服务产品概述](https://miniapp.open.taobao.com/docV3.htm?docId=118541&docType=1)。
### 4.2 构建 JAR
```powershell
Set-ExecutionPolicy -Scope Process Bypass
. D:\juzi\tools\env-java.ps1
cd D:\juzi\backend-java
mvn -DskipTests clean package
```
产物:
```text
D:\juzi\backend-java\target\taobao-mvp-backend-0.0.1-SNAPSHOT.jar
```
### 4.3 SAE 创建应用
在 SAE 控制台“创建应用 → 代码包部署 → 设置代码包部署”里按下面选:
| 配置项 | 选择 |
|---|---|
| 技术栈语言 | **Java** |
| 代码包类型 | **JAR 包部署** |
| 应用运行环境 | **标准 Java 应用运行环境** |
| Java 环境 | **Open JDK 17** |
| 文件上传方式 | 上传 JAR 包 |
| 启动命令 | 默认 `java -jar` |
| 应用端口 | **8080** |
| 健康检查 | HTTP `GET /actuator/health`,期望 200 |
| 实例数 | **2**(至少 2,避免单点) |
| 时区 | **Asia/Shanghai** |
| 地域/命名空间/VPC | 用聚石塔创建云应用时分配的那套,不要自己新建默认命名空间 |
**不要选**:
- WAR 包部署
- `apache-tomcat-*`
- `EDAS-Container-*`
- Open JDK 25
原因:WAR/Tomcat 是给外置 Tomcat 的老项目;EDAS-Container 是 HSF/Pandora Boot 专用;Open JDK 25 与 Spring Boot 3.5 的兼容性没有 17 稳。
环境变量(SAE → 应用设置 → 环境变量):
```text
TAOBAO_APP_KEY=你的AppKey
TAOBAO_APP_SECRET=你的AppSecret
TAOBAO_VERIFY_SIGN=true
```
> `TAOBAO_APP_SECRET` 只能放服务端,绝不能进小程序代码或 `config.js`。
建议 JVM 参数(按实例规格调整,堆小于容器内存):
```text
-Xms512m -Xmx1024m -Duser.timezone=Asia/Shanghai
```
### 4.4 流量接入
- 云应用走**内网私网 SLB**:聚石塔“流量接入”里绑定私网 SLB,后端端口 8080。
- 不要给云应用开公网入口;公网只用于你自己调试。
- 如果后端要调 TOP/奇门/外部 API,给 SAE 配 **NAT 网关或 EIP**,否则容器只入不出,调用会超时。
- 数据库在 RDS 时,把 SAE 的网段/安全组加进 RDS 白名单。
### 4.5 聚石塔/开放平台关联
1. 聚石塔控制台 → 云应用 → 新建云应用(按 2026-05 新链路向导)。
2. 部署方式选 SAE;创建测试环境、正式环境。
3. 在 SAE 里把 JAR 部署到对应应用/环境。
4. 聚石塔 → 流量接入 → 绑定私网 SLB(测试/正式各一套,或共用一个正式 SLB)。
5. 开放平台控制台 → 云托管 → 关联云应用 → 选择你的云应用和对应 SLB。
6. 在“服务测试”里调用 `POST /api/taobao/ping`,确认返回 `success: true`。
7. 在 `taobao/config.js` 里把 `mvpLocal` 改成 `false`,并配置:
```js
transport: 'cloud',
baseUrl: 'https://你的HTTPS域名',
cloudAppId: '控制台拿到的 cloudAppId',
cloudEnv: 'test', // 先 test,验收后改 online
```
8. 进入 `pages/mvp/mvp`,点 `ping`,看到 `transport: "gateway"`、`signVerified: true` 即通。
> 账号必须一致:创建云应用的聚石塔账号,要和开放平台小程序账号一致;子账号看不到云应用。小程序上线后默认云应用不能再改,选择时确认好。
### 4.6 空应用(不入塔)作为备选
如果这个 SAE 应用不在聚石塔,不能直接“关联云应用”。只能走空应用:
1. 开放平台 → 云托管 → 云应用管理 → 新建空应用。
2. 关联一个**没有敏感数据权限**的 AppKey。
3. 设置域名白名单,提交审批(HTTPS、已备案域名)。
4. 调用时 `exts.domain` 传你的域名;现有 `transport.js` 已经会传 `domain: config.baseUrl`。
注意:现有 `transport.js` 的 cloud 分支还要求 `config.cloudAppId` 非空。如果空应用控制台没有给 cloudAppId,需要先把这行校验放宽(或暂时先用聚石塔云应用)。
空应用只适合内容/工具/轻服务;电商交易、用户敏感数据类大概率不适合,还是得入塔。
---
## 5. 云网关接口契约(Java 后端必须遵守)
现有 Node 实现已经按这个契约写了,Java 迁移时照抄:
```json
{
"success": true,
"data": {},
"errorCode": "xxxx",
"errorMessage": "xxxx"
}
```
- 只支持 **GET/POST**;POST 必须 `application/json`。
- 请求体 **≤128KB**;超时默认 3s、最大 10s。
- 平台会往 URL 追加 `app_key`、`open_id`、`access_token`、`sign`、`env`、`mini_app_id` 等系统参数;自定义参数不要重名。
- 成功时小程序 SDK 只把 `data` 返回给页面;`errorCode/errorMessage` 在失败时返回。
- 发布前把 `cloudEnv` 从 `test` 改成 `online`;默认云应用上线后不能改。
- 图片/长任务不要塞进一个请求:现有实现是 64KiB 分片上传 + 异步任务 + 轮询。
参考:[云应用调用](https://open.m.taobao.com/docs/doc.htm?treeId=622&articleId=118538&docType=1)。
---
## 6. 签名校验
Java 的 `TaobaoSignatureVerifier` 与现有 `h5/lib/taobao-auth.js` 算法一致:
1. 取全部 query 参数,排除 `sign` 和空值,按 key 升序,拼成 `key1value1key2value2...`。
2. 末尾追加**原始 JSON body**(不要重新序列化)。
3. `sign_method=md5`:`MD5(secret + content + secret)`;`sign_method` 为空:`MD5(content + secret)`;`hmac*` 用 HMAC。
4. 结果转大写十六进制,与 `sign` 比较。
本地 `TAOBAO_VERIFY_SIGN=false`,没有 `app_key/sign`,直接放行,返回 `signVerified:false`。
云端 `TAOBAO_VERIFY_SIGN=true`:
- `app_key` 必须等于 `TAOBAO_APP_KEY`;
- `open_id` 必须符合 `[A-Za-z0-9_-]{4,256}`;
- `sign` 必须是 32–64 位十六进制;
- 重复 query 参数直接拒绝;
- 校验失败返回 `success:false, errorCode:"SIGN_INVALID"`。
如果云端一直 `SIGN_INVALID`,按顺序查:
1. SAE 环境变量是否真的注入(重启后生效)。
2. `TAOBAO_APP_KEY` 是否和云应用/小程序一致。
3. 网关用的 `sign_method` 与后端是否匹配。
4. body 是否被反向代理/框架重新序列化(必须保留原始字节)。
5. 是否有重复的 `open_id`/`app_key` 参数。
---
## 7. 常见问题
| 现象 | 排查 |
|---|---|
| `UnsupportedClassVersionError` | 编译 JDK 高于 SAE 运行时;统一用 17 |
| `404` | 路径不对;云应用 path 是否带 `/api/taobao`;WAR 的 context path |
| `502/504` | SAE 端口不是 8080、健康检查失败、SLB 后端端口不对 |
| `success:false` + `SIGN_INVALID` | 见第 6 节 |
| `cloud init failed` | IDE 未登录、AppID/cloudAppId 不匹配、cloudEnv 不对 |
| `请先配置淘宝云应用和 HTTPS 服务地址` | `transport:'cloud'` 但 `baseUrl` 不是 HTTPS 或 `cloudAppId` 为空 |
| `直连接口仅用于本机联调` | `transport:'direct'` 但 `baseUrl` 不是 localhost/127.0.0.1 |
| `Cannot find module '@tbmp/mp-cloud-sdk'` | `npm.cmd ci` 后,在 IDE 里执行“构建 npm” |
| 手机真机请求失败 | 127.0.0.1 是手机自己;真机必须走云端 HTTPS |
| 请求超过 10 秒 | 云网关最大 10s;改异步任务 + 轮询 |
| 返回体超过 128KB | 分页/裁剪字段,不要把大图 base64 放进响应 |
### 7.1 淘宝 IDE 报 `install miniapp extension fail: ... wmic ...`
Windows 11 24H2 起默认移除了 `wmic.exe`,而淘宝开发者工具在安装小程序扩展时会执行:
```text
wmic path win32_VideoController get caption
```
找不到 `wmic` 就报这个错。本机已经放了一个兼容 shim:
```text
C:\Users\youmi\.local\bin\wmic.cmd
```
修复步骤:
1. 完全退出淘宝开发者工具(任务管理器里不要留 `淘宝开发者工具.exe`)。
2. 重新打开 IDE,再导入 `D:\juzi\taobao`。
如果 shim 丢了,重新运行:
```powershell
powershell -ExecutionPolicy Bypass -File D:\juzi\tools\fix-taobao-ide-wmic.ps1
```
永久方案(需要管理员 PowerShell):
```powershell
DISM /Online /Add-Capability /CapabilityName:WMIC~~~~
```
装完后 `C:\Windows\System32\wmic.exe` 会优先于 shim,shim 可以删除。如果 DISM 提示找不到这个能力,说明系统镜像没带 WMIC FoD,继续用 shim 即可。
---
## 8. 下一步(MVP 通过后)
1. 把 `h5/lib/taobao-routes.js` 的接口逐个迁到 Java:
- `POST /api/taobao/challenge`
- `POST /api/taobao/session`
- `POST /api/taobao/me`
- `POST /api/taobao/photo`(64KiB 分片)
- `POST /api/taobao/skin-analyze`(异步任务)
- `POST /api/taobao/analysis`(轮询)
- `POST /api/taobao/reports`
- `POST /api/taobao/logout`
2. 所有 `/api/taobao/**` 统一走签名校验 + envelope。
3. 账号/历史/图片存到 RDS/OSS,不要放容器本地磁盘。
4. 保留 H5 的 Node 路由不变,淘宝走 Java;两边共用同一套业务规则时,先以现有 Node 实现为契约。
5. 接 SLS 日志、Actuator 健康检查、告警,再切正式流量。
---
## 9. 命令速查
```powershell
# 每个新窗口
Set-ExecutionPolicy -Scope Process Bypass
. D:\juzi\tools\env-java.ps1
# 后端
cd D:\juzi\backend-java
mvn -DskipTests clean package
java -jar target\taobao-mvp-backend-0.0.1-SNAPSHOT.jar
# 本地验证
curl.exe http://127.0.0.1:8080/actuator/health
curl.exe -X POST -H "Content-Type: application/json" -d "{}" http://127.0.0.1:8080/api/taobao/ping
# 前端依赖
cd D:\juzi\taobao
npm.cmd ci
```