Files
suixinkan_uikit/docs/门店身份注销接口实测.md
T

343 lines
19 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.
# 门店身份注销接口实测
实测时间:2026-08-28 11:39;追加 13:45–13:46 零资产确认(服务端响应时间)。
环境:`https://api-test.zhifly.cn`。首次 11:39 使用用户明确授权的 iPhone 当前 `store_user` 登录 Token,仅执行 `GET /eligibility` 与 `GET /status`,当时未调用修改接口。后续额外授权的两项零资产确认见第 5 节。请求头与当前 Debug App 一致:`token`、`X-APP-VERSION: 1.3.1`、`X-OS-TYPE: iOS`、JSON Accept/Content-Type。
以下为真实响应;仅 `store_user_id`、`finance_identity_id` 统一替换为数值 `0` 脱敏,不能把该值用作有效身份。没有保存 Token。
## 1. 注销条件
`GET /api/yf-handset-app/account-deregister/eligibility`
HTTP 200,业务码 `100000`:
```json
{
"code": 100000,
"msg": "success",
"data": {
"can_apply": false,
"store_user_id": 0,
"finance_identity_id": 0,
"wallet_balance_fen": 0,
"wallet_balance": "0.00",
"points_balance": 0,
"wallet_waived": false,
"points_waived": false,
"unfulfilled_count": 37,
"fulfillment_in_progress_count": 0,
"risk_end_at": "2026-08-27 15:47:32",
"eligible_at": "2026-09-03 15:47:32",
"risk_window_hours": 168,
"blockers": [
{
"code": "ORDER_UNFULFILLED",
"message": "账户仍有未履约订单或带单",
"action": "complete_orders"
},
{
"code": "RISK_WINDOW_NOT_EXPIRED",
"message": "最后一笔业务的风险结束时间尚未超过7天",
"action": "wait_risk_window"
},
{
"code": "WALLET_WAIVER_MISSING",
"message": "请先确认放弃现金余额",
"action": "confirm_wallet_waiver"
},
{
"code": "POINTS_WAIVER_MISSING",
"message": "请先确认放弃积分",
"action": "confirm_points_waiver"
}
],
"deregister": null
},
"time": "2026-08-28 11:39:51"
}
```
本次观测到的类型:
| 字段 | JSON 类型 / 含义 |
| --- | --- |
| `can_apply` | 布尔值,服务端是否允许申请 |
| `store_user_id`、`finance_identity_id` | 整数 |
| `wallet_balance_fen` | 整数,现金余额(分) |
| `wallet_balance` | 字符串,金额展示值;本次为 `"0.00"` |
| `points_balance` | 整数,积分余额 |
| `wallet_waived`、`points_waived` | 独立布尔值,是否已确认放弃 |
| `unfulfilled_count`、`fulfillment_in_progress_count` | 整数 |
| `risk_end_at`、`eligible_at` | 时间字符串,格式 `yyyy-MM-dd HH:mm:ss`;时区及无历史业务时的空值形式尚未确认 |
| `risk_window_hours` | 整数,本次为 `168` |
| `blockers` | 对象数组,每项有字符串 `code`、`message`、`action` |
| `deregister` | 本次为 `null`,尚未观测非空结构 |
本次余额与积分均为零,服务端仍返回两项放弃确认缺失。客户端不能因为资产为零就省略确认。当前还有 37 项未履约订单或带单,且风险等待期未结束,不能提交注销。`eligible_at` 是业务风险期截止时间,不是提交申请后的冷静期截止时间;达到该时间也不代表其他条件自动满足。
## 2. 注销状态
`GET /api/yf-handset-app/account-deregister/status`
HTTP 200,业务码 `100000`:
```json
{
"code": 100000,
"msg": "success",
"data": {
"deregister": null
},
"time": "2026-08-28 11:39:51"
}
```
当前查询没有返回注销申请。不能据此推断非空申请的字段名称、状态枚举或是否可撤销。
## 3. 首次只读探测后尚缺的信息(后续进展见第 5、6 节)
- 草稿、冷静期、阻断、撤销、完成时 `data.deregister` 的非空结构、状态字段和值。
- `cooling_until`、`remaining_seconds` 的实际位置及类型。
- 无历史业务时风险时间的空值形式、时间字符串所用时区。
- 重新登录或选择身份自动撤销的具体接口时机,以及受限 Token 是否允许切换其他身份。
这些情况需要现有后端响应样例/源码,或在获得明确授权的专用测试身份上验证。本次授权仅限只读查询,不为采样创建、撤销注销申请或确认资产放弃。
## 4. 后续零资产确认授权(2026-08-28 13:42)
用户随后明确允许:在测试环境重新核实现金余额与积分均为 0 后,分别调用两项资产放弃确认接口,并查询是否产生草稿。此授权不包含发送短信、提交或撤销注销申请,也不允许非零资产确认。
已确认 iPhone 11 连接,并读取本 App 的当前会话:没有登录 Token,保存的账号类型为 `photog`,不是旧注销接口要求的 `store_user`。因此此次没有发出任何接口请求或资产确认,设备偏好未修改,本地临时偏好副本已删除。需在测试版 App 登录门店身份后继续;不要为采样登录已有未完成注销申请的身份,以免触发自动撤销。
## 5. 已完成两项真实零资产确认(2026-08-28 13:45–13:46)
用户重新登录后,核实当前为有效 `store_user`。每项确认前均重新查询:身份与设备会话一致、现金余额(分和展示金额)与积分均为 0;只访问测试环境,禁止重定向,不自动重试修改请求。仅执行了已授权的 `POST /waivers/wallet`、`POST /waivers/points` 各一次,没有发送短信、提交或撤销注销申请。
本次身份初始没有未履约/交付处理中记录,`risk_end_at`、`eligible_at` 均为 JSON `null`,阻断仅为两项确认缺失。与第 1 节较早查询的身份情况不同,不能沿用之前的 37 项未履约记录。
| 阶段 | `wallet_waived` | `points_waived` | `can_apply` | `deregister` |
| --- | --- | --- | --- | --- |
| 确认前 | false | false | false | null |
| 现金确认后 | true | false | false | `status: 0` 草稿 |
| 积分确认后 | true | true | true | 同一未提交草稿 |
两个确认请求均 HTTP 200、`code: 100000`,`data` 返回 `asset_type`(分别为 `"wallet"`、`"points"`)、`wallet_balance_fen: 0`、`wallet_balance: "0.00"`、`points_balance: 0` 及两项确认时间。现金确认后 `wallet_waived_at: "2026-08-28 13:45:57"`、`points_waived_at: null`;积分确认后后者变为 `"2026-08-28 13:46:42"`。
两个 GET 中的 `data.deregister` 都返回以下结构;仅 `id` 脱敏为 0,实际是正整数:
```json
{
"id": 0,
"status": 0,
"status_label": "待确认",
"reason": "",
"apply_time": null,
"cooling_until": null,
"remaining_seconds": 0,
"cancel_time": null,
"blocked_code": "",
"blocked_reason": "",
"completed_at": null
}
```
**确认结论:第一次资产确认即产生非空草稿;`status` 为数字,0 对应“待确认”。非空记录不等于已提交,不能一律限制普通业务或后续资产确认。两项确认后即使仍有草稿,`can_apply` 也会变为 true。** `remaining_seconds: 0` 在草稿中存在,不能单独据此认定冷静期已结束或注销已完成。
已据此修正客户端草稿判断、继续确认/验证和启动核验,并补充 Mock 测试。只将完整且无提交、撤销、阻断或完成字段冲突的 `status: 0` 识别为草稿;未知状态仍不推断。所有本地会话临时副本已删除,未写回设备偏好,未保存 Token。
仍缺:冷静期、撤销、阻断、完成的实际状态值及对应时间数据;确认过期响应;登录/切换自动撤销的具体时机。继续真实验证需要另行授权短信、提交与撤销操作,当前授权不包含这些操作。
## 6. 短信、申请与立即撤销(2026-08-28 14:16–14:24)
用户另外授权在切换后的专用测试身份上发送短信、提交申请,获取状态后立即撤销。真机页面核实:现金/积分为0、两项确认已完成、无未履约及风险等待阻断。通过 iPhone 镜像发送短信,用户提供验证码后提交;未将验证码写入源码或文档。短信和申请的原始 POST 响应体没有保存,不能把后续 GET 当作 POST 原文。
- 申请原因:`API test; cancel immediately`。
- 申请时间:`2026-08-28 14:23:40`。
- 查询确认:`status: 1`、`status_label: "冷静期中"`,冷静期截止 `2026-09-04 14:23:40`。
- 核对当前身份、同一申请及原因后只调用一次 `/cancel`,不自动重试。
- 撤销成功时间:`2026-08-28 14:24:04`,返回 `status: 9`、`status_label: "已撤销"`。
- `14:24:05` 再次 GET `/status` 与 `/eligibility` 确认已撤销;未留下待注销申请,未执行最终注销。
- 本地临时会话副本已删除,未编辑设备偏好,未在文档中保存 Token、手机号或真实身份 ID。
### 冷静期状态
```json
{
"code": 100000,
"msg": "success",
"data": {
"deregister": {
"id": 0,
"status": 1,
"status_label": "冷静期中",
"reason": "API test; cancel immediately",
"apply_time": "2026-08-28 14:23:40",
"cooling_until": "2026-09-04 14:23:40",
"remaining_seconds": 604776,
"cancel_time": null,
"blocked_code": "",
"blocked_reason": "",
"completed_at": null
}
},
"time": "2026-08-28 14:24:03"
}
```
### 撤销响应
```json
{
"code": 100000,
"msg": "注销申请已撤销",
"data": {
"deregister": {
"id": 0,
"status": 9,
"status_label": "已撤销",
"reason": "API test; cancel immediately",
"apply_time": "2026-08-28 14:23:40",
"cooling_until": "2026-09-04 14:23:40",
"remaining_seconds": 0,
"cancel_time": "2026-08-28 14:24:04",
"blocked_code": "CANCELLED_BY_USER",
"blocked_reason": "用户主动撤销注销",
"completed_at": null
}
},
"time": "2026-08-28 14:24:04"
}
```
### 撤销后的条件
```json
{
"code": 100000,
"msg": "success",
"data": {
"can_apply": false,
"store_user_id": 0,
"finance_identity_id": 0,
"wallet_balance_fen": 0,
"wallet_balance": "0.00",
"points_balance": 0,
"wallet_waived": false,
"points_waived": false,
"unfulfilled_count": 0,
"fulfillment_in_progress_count": 0,
"risk_end_at": null,
"eligible_at": null,
"risk_window_hours": 168,
"blockers": [
{
"code": "WALLET_WAIVER_MISSING",
"message": "请先确认放弃现金余额",
"action": "confirm_wallet_waiver"
},
{
"code": "POINTS_WAIVER_MISSING",
"message": "请先确认放弃积分",
"action": "confirm_points_waiver"
}
],
"deregister": {
"id": 0,
"status": 9,
"status_label": "已撤销",
"reason": "API test; cancel immediately",
"apply_time": "2026-08-28 14:23:40",
"cooling_until": "2026-09-04 14:23:40",
"remaining_seconds": 0,
"cancel_time": "2026-08-28 14:24:04",
"blocked_code": "CANCELLED_BY_USER",
"blocked_reason": "用户主动撤销注销",
"completed_at": null
}
},
"time": "2026-08-28 14:24:05"
}
```
冷静期 GET `/eligibility` 已返回两项确认 false 和缺少确认的两个阻断,撤销后也是如此;冷静期不能因此重新确认资产。撤销记录保留旧冷静期时间;remaining_seconds 为0不等于注销完成。正式完成与终审阻断的状态值、自动撤销和所有身份注销后的登录响应仍未验证。此次授权操作已结束,不继续发送短信或创建申请。
## 2026-08-28:补查终态契约及新申请准备
用户随后允许继续申请注销,以尝试获取缺失的终态响应。本节是新的调查记录,不代表已经创建新的申请。
| 查找范围 | 结果 |
| --- | --- |
| 本机 iOS、Android 参考工程及桌面相关文件 | 未找到旧注销后端的 Controller、Resource、状态枚举或 migration 源码 |
| 测试 API 的 `/docs`、`/api/documentation`、`/openapi.json`、`/swagger.json` | HTTP 200,但业务体均为路由不存在,不能当作可用接口文档 |
| Gitea 匿名仓库搜索 | 没有返回匹配仓库;不代表私有仓库不存在 |
| Chrome 中已有登录的 Gitea 会话 | 可访问当前用户的仓库列表;代码搜索 `StoreUserDeregister`、`deregister` 均未匹配,未取得注销后端源码 |
| 已打开的飞书原始文档 | 页面显示最近修改为8月21日;相关规则与本地文档一致,未给出终态数字枚举、完整 JSON 或完成后的鉴权响应 |
| 真机当前 App 会话 | 无有效门店登录态,因此没有发起认证查询、短信、资产确认、申请或撤销 |
当前仍需先在真机登录一个允许最终注销的专用测试门店身份,再读取该身份的条件。若保留申请等待正式完成,需经过服务端7天冷静期;不能修改本机时间来替代服务端等待,也不能为制造终审阻断而擅自修改订单、资产或数据库。按旧文档,重新登录或选中申请中的同一身份会自动撤销申请,等待期间应避免这种操作。
“终审阻断”需要到期复核发现条件变化,单纯提交并等待不能保证得到该状态。此次只读查找未新增任何终态实测结论。
## 2026-08-28 15:23:按用户要求改在模拟器准备新申请
- 用户明确要求操作其已登录的 iPhone Air 模拟器。本次是人工界面操作,不是模拟器单元测试;不改变此前真机测试结论。
- 页面当前身份为北大科技园,显示现金0元、积分0;初始只有两项资产确认阻断,上次申请已撤销。
- 用户授权分别确认两项零资产并发送验证码。继续操作时,现金已显示确认完成,因此没有重复提交现金确认;随后单独确认零积分。
- 页面显示两项资产均已确认、当前条件满足;仍为未提交草稿。
- 15:23通过页面发送一次注销验证码,界面提示已发送至当前身份绑定手机号。未保存短信 POST 原始响应,不能把界面提示当作完整接口 JSON。
- 停留在验证码输入页,等待用户提供本次验证码;此时尚未提交新申请,也未进入新的冷静期。
## 2026-08-28 15:27—15:29:新申请已提交并保留
- 用户提供本次验证码,并在最终弹窗前明确确认:只注销北大科技园身份,保留申请至服务端7天后复核,正式完成不可恢复,不像上次立即撤销。
- 15:27:24在模拟器点击一次“确认提交申请”。原因为 `Test account deregistration`;验证码不写入文档或代码。
- 页面进入冷静期核验页,显示截止时间 `2026-09-04 15:27:24`(服务端时间)。
- 15:28:27只读 GET `/status`、`/eligibility` 均确认 `deregister.status: 1`,`cancel_time`、`completed_at` 均为 null。
- 15:29:22以同一现有 Token GET `/api/yf-handset-app/userinfo`,返回 HTTP 200、业务码150015、`data.status: "cooling"`、相同冷静期截止时间;响应没有 `time` 字段。前后 GET `/status` 均成功且仍是同一冷静期记录。
- 未重复发送短信、未重复申请、未执行撤销、登录或身份选择。未保留 Token 副本或修改模拟器偏好设置。
**此时申请仍待注销,与14:24已撤销的旧申请不同;后续已于15:55:36因重新登录自动撤销,见文末15:56记录。** 终审阻断/正式完成未发生;不能把冷静期截止当作已经注销。查询样例已加入[旧接口返回数据说明](门店身份注销旧接口返回数据说明.md)。短信和申请 POST 原始响应体仍未捕获,不能用 GET 代替。
本轮脱敏证据:
- `/private/tmp/suixinkan-contract-discovery-20260828/152826-simulator-status-redacted.json`
- `/private/tmp/suixinkan-contract-discovery-20260828/152826-simulator-eligibility-redacted.json`
- `/private/tmp/suixinkan-contract-discovery-20260828/152921-simulator-userinfo-cooling-redacted.json`
- `/private/tmp/suixinkan-contract-discovery-20260828/152921-simulator-status-before-auth-redacted.json`
- `/private/tmp/suixinkan-contract-discovery-20260828/152921-simulator-status-after-auth-redacted.json`
## 2026-08-28 15:45:真实响应回归与源码补查
- 将本轮150015及对应status响应整理为Swift测试夹具;逐字段对比采样JSON,仅注销记录ID替换为测试值301。
- 在iPhone 11上完成全量792项测试:782通过、10项既有失败,无跳过;失败用例集合与原始基线一致。注销相关73项全部通过,包括真实userinfo限制响应经API、通知和路由进入冷静期页面的新增Mock集成测试。
- 本轮仅更新测试与文档,未操作模拟器中的真实申请;未变更工程配置、版本号或依赖。
- 补查已保存项目列表,未发现相关后端工程;Android工程现有Git主机的HTTP网页根返回空响应,未取得源码。未猜测后端仓库路径、修改服务器或扩展访问权限。
- 结果:`/private/tmp/suixinkan-deregister-real-contract-20260828.xcresult`。终态样例仍缺,不能将测试通过作为正式注销完成的证据。
## 2026-08-28 15:48—15:50:最终只读复核与冷启动尝试
- 15:48:04查询仍为申请时间15:27:24的冷静期1。
- 仅终止并重启iPhone Air中的App进程;未卸载、清空数据、登录或选择身份。工具未能切换至正确模拟器窗口,故冷启动UI没有验证完成。
- 15:50:51用原会话再次GET `/status`、`/eligibility`,均返回同一申请的冷静期1,截止时间不变,`remaining_seconds: 603392`,撤销时间与完成时间均为null。
- 证据:`/private/tmp/suixinkan-contract-discovery-20260828/155050-simulator-status-redacted.json`及同前缀的`eligibility-redacted.json`。
- 未产生新的终态依据,不继续重复轮询或制造业务变化;待服务端到期状态或已有源码可用后再推进。
## 2026-08-28 15:56:重新登录自动撤销
用户告知已进入后,只读查询发现15:27:24申请已于15:55:36自动撤销。两次GET均返回status9、CANCELLED_BY_LOGIN、用户重新登录自动撤销的说明,completed_at仍为null。没有调用cancel或重新申请;未采集触发撤销的具体登录请求,因此不能断言具体接口时机。
证据:/private/tmp/suixinkan-contract-discovery-20260828/155633-simulator-status-redacted.json及同前缀eligibility文件。此前待注销记录的截止时间已失效,不再等待该申请于9月4日完成。用户随后要求UI简化,本轮仅使用Mock测试,不再操作真实注销。
## 2026-08-28 17:01:验证资产确认接口的false参数
用户单独授权尝试现金、积分接口传`accepted: false`。使用iPhone 11当前已登录门店身份和测试环境,先只读确认两项标记均为true、金额均为0、状态为未提交草稿0,再分别调用一次两个确认接口。
- 现金:17:01:14返回HTTP 200、业务码100099、`msg: 请明确确认自愿放弃对应资产`、`data: []`。
- 积分:17:01:32返回同样结果。
- 每次调用后重新GET查询:`wallet_waived`和`points_waived`仍为true,草稿仍为0,金额未变化,没有进入冷静期。
- 结论:当前接口不接受false作为撤回确认;本轮没有调用true、短信、申请、撤销或登录接口。未重试POST。
完整返回及前后状态见[旧接口返回数据说明4.4节](门店身份注销旧接口返回数据说明.md)。脱敏证据目录:`/private/tmp/suixinkan-waiver-false-20260828/`。