iXserverLoopEnv/README.md

118 lines
8.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# iXserverLoopEnv:模拟闭环测试环境
在 FG-W11-ICON-DEV 一台机器上把五个角色跑起来,让一条 IG 消息从入站到第三方回复、再回到 IG 全程走真 HTTP。
方案与取舍见 iXserver 仓库的 `docs/构建模拟闭环测试环境.html`。
| 角色 | 端口 | 来源 |
| --- | --- | --- |
| ABP(授权 + 消息模板) | https 44332 | `C:\Projects\HKTBAbp` 发布到 `run\abp` |
| iXserver API(IIS Express) | 8081,WebSocket 33346 | `C:\Projects\iXserver` 整解决方案编译后拷到 `run\ixserver` |
| 第三方 chatbot 客户端 | 5056 | `iXserver\Tools\ThirdPartyChatbotTestClient` |
| IG 后端模拟 | 5070 | `iXserver\Tools\IgMockServer` |
| SCRM 客服系统模拟 | 5080 | `iXserver\Tools\ScrmMockServer` |
| 闭环观察台(只读,泳道时序图) | 5090 | `iXserver\Tools\LoopConsole` |
所有端口只绑本机。iXserver 的旧接口和 WebSocket **没有鉴权**,绝不能对外开放 8081 / 33346。
## 这个仓库装什么
只装「环境」:`loop.ps1`、`config\`、`db\`、`tools\`、`scenarios\`、`deployed.json`。
程序本身不在这里——两个模拟服务的代码在 iXserver 的 `Tools\`(它们模拟的是 iXserver 自己的协议,
要和协议改动同一个提交);编译产物、日志、上传文件在被忽略的 `run\`。
**以 Mac 上的 `~/projects/iXserverLoopEnv` 为准**,用 remote-dev-box 的 `sync.sh` 推到 winbox 的
`C:\Projects\iXserverLoopEnv`。提交在 Mac 上做,winbox 上只跑。
## 第一次
```powershell
.\loop.ps1 reset-abp -Init # iCONAbpFX 拷完后:换 setsail secret 与 admin 密码,留底
.\loop.ps1 deploy # 编译 iXserver 整解决方案 + 发布 ABP(慢)
.\loop.ps1 reset # 建 iXserverLoop:EDMX 建表 → FeatureTest 种子 → loop_patch,留底
.\loop.ps1 up
```
之后日常:
```powershell
.\loop.ps1 status
.\loop.ps1 deploy -Only ixserver # 改了 iXserver 代码
.\loop.ps1 deploy -Only ixserver -ConfigOnly # 只改了 config\ixserver\overrides.psd1
.\loop.ps1 reset -FromBackup # 库回到干净状态(秒级)
.\loop.ps1 logs -Only ixserver -Tail 100
.\loop.ps1 down
```
## 场景
`scenarios\` 下每个脚本独立可跑,通过退出 0、失败退出 1 并打印两侧记录。前提是 `up` 后各角色都健康。
观察台在跑时,每次跑完(通过或失败)都会生成一份**场景报告**:这次的时序图、iXserver 内部步骤、逐步断言、部署版本,
存成 `run\reports\<开始时间>-<场景>-<PASS|FAIL>.html`(单文件,离线可开,不进 git)。
`.\loop.ps1 reports` 列出最近的,观察台 <http://127.0.0.1:5090/reports/> 里也能点开。加 `-NoReport` 只断言不出报告(省几秒)。
新写场景照 S1 / S8 点源 `scenarios\_lib.ps1`:`Start-LoopRun` → 每个断言 `Add-LoopStep` → `Save-LoopReport`。
```powershell
.\scenarios\s1-ig-text-echo.ps1 # IG 文本 → iXserver → 第三方 chatbot echo → IG 收到
.\scenarios\s2-auth-ip-whitelist.ps1 # IP 白名单:token 端点 + send-txt 经真 IIS 放行 / 拒绝、可信代理的 XFF 规则;临时改 oauth_client 与 Web.config,结束还原,约 2~3 分钟
.\scenarios\s5-ig-handoff.ps1 # 机器人工单 → SCRM 开工 + 客服上线 → 下一条:echo 在前、问句在后 → 点 Yes → 新人工工单 → 客服回复 → 旧单迟到回复 409 → 下班
.\scenarios\s8-human-chain.ps1 # SCRM 开工 → 新 IG 用户 → 人工工单推送 → 指派 / 回复 → IG 收到 → 结束 → 下班
```
S5 依赖 `epro_ig_demo` 的 `DisconnectChatbotFlowSetting` 已打开(`db\ixserver\loop_patch.sql` 第 3 节;没 reset 过的库要单独执行那一段),
问句按钮标题跟 ABP 模板走,模板改过时用 `-YesTitle` 指定。
跑的时候开着观察台 <http://127.0.0.1:5090>,每一跳和状态变化会实时画成泳道时序图;`?ticket=<工单号>` 只看一张。
`epro_ig_demo` 常开条款同意(`db\ixserver\loop_patch.sql` 第 3 节的 `T_and_C_Setting`):
新 IG 用户的第一句话会被条款拦下,三个场景都先调 `_lib.ps1` 的 `Complete-LoopTnC` 走完「条款 → 同意 → 选语言 → 问候」。
staging 的 IG 条款组**缺 Agree 按钮**(漏了 Line 问候里的「Agreement Button (Line IG)」);闭环 ABP 在
`db\abp\loop_patch.sql` 第 3 节补上了,这一处与 staging 不同。改过这个补丁要 `.\loop.ps1 reset-abp -Init` 重新打并留底。
S5 / S8 结束时(失败也一样)会把服务号切回机器人、在线人数归零,所以几个场景先后跑互不影响;要停在人工状态看页面加 `-KeepShift`。
从 Mac 看几个页面用 SSH 本地端口转发:
```bash
ssh -N -L 5056:127.0.0.1:5056 -L 5070:127.0.0.1:5070 -L 5080:127.0.0.1:5080 -L 5090:127.0.0.1:5090 FG-W11-ICON-DEV
```
## 几个容易踩的点
- **库是 iXserverLoop,不是 iXsererTest。** FeatureTest 每个方法都 drop 重建 iXsererTest,
反过来闭环 API 的连接池连着它会让 FeatureTest 无限卡在删库上。
- **API 从 `run\ixserver` 跑,不从 `API\` 源码目录跑。** 编译 FeatureTest 会刷新 `API\bin` 里的模块 dll,
正在跑的站点会被回收、甚至换成依赖不全的版本。
- **`reset` 把建库与 `loop_patch.sql` 绑在一起。** 种子里有真格式的 FB token 与 api.commas.hk 等真实 webhook,
补丁把它们全换成假值 / 黑洞,并在末尾自检;不提供「只建不补」。
- **`OAuth_Authority` 必须逐字等于本地 ABP 签出 token 的 `iss`。** IdentityServer4 没设 IssuerUri,
iss 取请求的 Host,所以全链路统一用 `https://localhost:44332`,换成 127.0.0.1 就全部 401。
- **签名密钥不在库里**,在 ABP 进程工作目录的 `tempkey.jwk`。deploy 删掉仓库里那把开发密钥,
首次 `up` 时 ABP 自己生成一把,留存到 `run\abp-key\`,之后重新部署沿用同一把。
- **备份在 SQL 实例的默认备份目录**(`*.loop.bak`),不在 `run\backup\`:SQL 服务账号对 `C:\Projects` 不一定有写权限。
- **进程用 WMI(Win32_Process.Create)起**,不用 Start-Process:经 SSH 起的进程会随会话一起被杀。
pid 记在 `run\pids\`,`down` 按进程树杀。
- **VS Code 的自动端口转发会抢闭环端口。** 在 winbox 上用 VS Code Remote-SSH 连 Mac 时,它从终端输出里认
`localhost:端口`,然后在 winbox 本机占住同一个端口转发回 Mac,闭环角色就报「端口被 Code 占着」。
Mac 的 `~/.vscode-server/data/Machine/settings.json` 已设 `remote.autoForwardPorts=false`、
`remote.restoreForwardedPorts=false`;已经转发出去的要在 VS Code「端口」面板里停掉。
- **WMI 起的进程只有系统环境变量。** `TEMP` 是 `C:\Windows\TEMP`,ASP.NET 编译临时目录也会退回系统目录,
没写权限,首个请求就 500。`loop.ps1` 给每个角色设了 `TEMP`/`TMP` 指到 `run\data\temp`,
并在 Web.config 的 `<compilation>` 上写 `tempDirectory`。
- **ABP 的 HTTPS 证书用的是 IIS Express 自带的 localhost 证书**(LocalMachine\My,到 2030 年,已在当前用户受信任根里)。
winbox 的 ASP.NET dev 证书 2026-05 已过期;用 IIS Express 这张,iXserver(.NET Framework)连 ABP 不用另外信任、也不弹框。
- **ABP 的各个 DbContext 按名字找连接串,找不到退回 `Default`**,而仓库 `appsettings.json` 的 `Default` 指向公司内网的库。
`appsettings.Loop.json` 把所有连接串都盖成本机 iCONAbpFX。
- PowerShell 5.1 的两个坑已经在 `loop.ps1` 里绕开:原生命令往 stderr 写一行就抛异常(统一走 `Invoke-Native`);
`Get-Content` 默认按 GBK 读无 BOM 的 UTF-8(拷配置用 `Copy-Item`,脚本文件一律带 BOM)。
- **iXserver 的主日志在 `run\ixserver\Log\{Debug,Information,Warning,Error}\<日期>\`**(注入的 ILogger,内部步骤很全,观察台就读它)。
`run\data\API_Log` 是静态 `Logger` 写的另一份,几乎是空的,别看它下结论。排查先看 `Log\Error`。
`deploy` 的 robocopy 排除了 `Log` / `Logs`,重新部署不会清掉日志。
- `deployed.json` 记录每次部署时两个源码仓库的 commit 与未提交文件。闭环结果离开「当时部署的是哪个版本」没法解读,
跑场景的记录里引用它。注意 winbox 上 iXserver 仓库的 HEAD 不随 `sync.sh` 前进(只推文件),
`commit` 字段可能停在很久以前,以 `uncommitted` 清单和 Mac 上的提交为准。
## 闭环专用凭据(假值,可公开)
见 `config\loop.psd1` 的 `Secrets`:setsail 与 FX_App 的 client secret、ABP admin 密码、所有渠道 token 的替身。
staging 的 secret 明文不出现在这个仓库里。