Files
suixinkan_uikit/docs/账号注销后端接口需求.md
T

25 KiB
Raw Blame History

账号注销后端接口需求

2026-08-28 已被新范围替代: 本次迭代改为使用旧 account-deregister 接口,仅注销当前 store_user 身份,不实施本文的主账号注销、新接口或恢复专用 Token 方案。当前接入情况见 门店身份注销接入说明。下文保留为历史讨论记录。

更新日期:2026-08-27 适用端:随心瞰商家版 iOS;后端账号状态应同时约束 Android、旧版本客户端及其他登录入口。 文档性质:接口需求建议稿,以下新增路径和字段尚未与后端确认,不代表线上已有接口。

1. 需要后端提供什么

需要 5 个注销接口、现有登录与鉴权流程改造,以及服务端到期处理任务。

类型 建议接口 / 能力 用途
新增 GET /api/app/account-deletion/precheck 返回真实资产、注销影响说明及阻断原因
新增 POST /api/app/account-deletion/send-sms-code 向主账号绑定手机号发送注销专用验证码
新增 POST /api/app/account-deletion/submit 校验验证码和用户确认,提交注销申请
新增 GET /api/app/account-deletion/status 查询当前账号的服务端注销状态及截止时间
新增 POST /api/app/account-deletion/cancel 冷静期内由用户明确确认后取消注销
修改 POST /api/app/v9/login 身份验证通过后区分正常登录、待注销恢复和不可恢复状态
修改 POST /api/app/v9/set-user 与统一鉴权 禁止待注销或已注销账号取得、使用业务 Token
服务端任务 到期注销、失败重试、会话失效 不依赖客户端在线或再次打开 App

如果已有等价能力,可以复用后端现有路径,但需覆盖本文的数据和行为要求,不必重复建设。

当前客户端状态

  • 已有设置入口、资产核验页、短信验证页、成功页、密码登录时的恢复确认和冷启动检查。
  • 当前为 AccountDeletionMockService:资产是固定示例,验证码固定为 123456,注销记录保存在本机 UserDefaults。
  • 目前不会发送真实短信,也不会注销后端账号或删除后端数据。
  • 接入真实接口后,服务端状态为唯一依据;本机时间、手机号输入值及本地记录不能作为注销结果或操作权限的依据。

2. 账号范围与统一约定

2.1 注销对象

当前功能意图是注销手机号登录对应的主账号及其关联业务身份,不是仅退出当前登录,也不是只停用当前选中的景区或门店身份。

  • 后端根据 Token 解析稳定的主账号 ID,并据此聚合所有关联景区、门店身份的数据。
  • 请求不接受客户端指定待注销的 user_id、username、phone、scenic_id 或 store_id;短信收件人也由后端确定。
  • 当前业务身份资料里的手机号可能与主账号绑定手机号不同,不能直接用业务身份手机号发送注销短信。
  • “解除景区、门店账号”指解除该用户的关联身份;不应删除景区、门店实体,也不能误删其他用户、门店或客户共同拥有的数据。
  • 若存在管理员、负责人或共享资产,需明确移交、保留或阻断策略,不能因为客户端勾选“放弃资产”就直接删除。

2.2 请求和响应

沿用当前 App 网络层约定:

Content-Type: application/json
Accept: application/json
token: <当前请求所需的凭证>
X-APP-VERSION: <客户端版本>
X-OS-TYPE: <客户端现有平台标识>

当前工程使用 token 请求头,不是 Authorization: Bearer ...。恢复专用凭证也建议放在同一请求头,由服务端识别凭证类型和权限。

{
  "code": 100000,
  "msg": "success",
  "data": {}
}
  • 成功业务码沿用 100000;新增失败码由后端统一分配,见第 6 节。
  • JSON 字段使用 snake_case;布尔值使用 true/false,空列表使用 []。
  • ID 建议统一返回字符串,客户端不依赖数据库自增 ID 或 UUID 的内部格式。
  • 时间统一使用带时区的 ISO 8601 字符串,例如 2026-08-27T08:00:00Z;客户端负责本地化显示。
  • 时间相关响应返回 server_time;冷静期截止、验证码到期和取消资格全部由服务端判断。

2.3 状态及七天冷静期

建议在真实服务中区分“不可再取消”和“数据已处理完成”,避免定时任务尚未完成就展示为永久删除成功。

state 含义 允许恢复 允许进入业务
none 没有注销申请 不适用 是
pending 在冷静期内,待用户取消或到期 是,且服务端当前时间必须早于截止时间 否
canceled 最近一次申请已取消 不适用;可以重新申请 是,需重新取得有效业务 Token
processing 已到截止时间,正在执行最终处理 否 否
completed 服务端已完成约定的注销处理 否 否

流转:none/canceled → pending → processing → completed;仅 pending 且未到期时允许转为 canceled。

  • 建议默认冷静期为提交成功后 7 × 24 小时,后端返回准确的 scheduled_deletion_at,客户端不自行推算。
  • 恰好到达截止时刻即不可取消;即使定时任务尚未运行,接口也必须立即按不可恢复处理。
  • 任务失败保持不可恢复状态,记录原因并重试,不能重新开放登录或重置冷静期。
  • 当前 Mock 没有 processing 状态;接入真实后端时客户端需同步扩展。

3. 五个接口的详细需求

3.1 注销前置核验

GET /api/app/account-deletion/precheck

使用有效业务 Token,无查询参数。返回整个主账号范围内的资产快照、当前绑定手机号的脱敏值、注销后果,以及是否允许提交。

成功响应示例(资产数值仅为示例):

{
  "code": 100000,
  "msg": "success",
  "data": {
    "precheck_id": "precheck_example_001",
    "expires_at": "2026-08-27T08:10:00Z",
    "server_time": "2026-08-27T08:00:00Z",
    "masked_phone": "138****0000",
    "can_submit": true,
    "blocking_reasons": [],
    "assets": [
      {"kind": "wallet", "title": "钱包余额", "value": "0.00", "unit": "CNY", "value_text": "¥0.00"},
      {"kind": "works", "title": "作品与相册", "value": "36", "unit": "item", "value_text": "36个"},
      {"kind": "projects", "title": "项目", "value": "4", "unit": "item", "value_text": "4个"},
      {"kind": "cloud_files", "title": "云盘文件", "value": "8589934592", "unit": "byte", "value_text": "8 GB"}
    ],
    "consequences": [
      "本人关联的景区与门店身份将解除",
      "个人作品和云盘文件将按已确认的规则处理",
      "提交后7天内再次登录并确认恢复,可取消注销"
    ],
    "acknowledgement_version": "account-deletion-v1"
  }
}
字段 要求
precheck_id / expires_at 后端生成的核验快照标识及有效期,绑定当前主账号,用于确认用户看到的资产和后果
masked_phone 主账号实际绑定手机号的脱敏值;不返回短信验证码
can_submit 是否满足注销条件;客户端据此禁止或允许继续
blocking_reasons 不可提交时返回 [{"reason_code":"WALLET_NOT_SETTLED","message":"请先处理钱包余额或结算中的款项"}],可有多项
assets 当前页面需要 wallet、works、projects、cloud_files 四类;零资产也返回对应项
value / unit / value_text 原始值统一为字符串;金额为元且保留两位小数,计数、字节为整数字符串;value_text 供页面直接展示
consequences 由后端按最终业务规则返回,不能宣称会删除实际需要保留的数据
acknowledgement_version 本次注销说明版本,随提交保存确认记录

要求:

  • 核验不得触发删除、资金扣除、身份解绑或短信发送。
  • 作品、相册、项目及云盘文件的统计口径和去重方式由后端明确,不能把共享资产全部算成该用户可删除的资产。
  • 余额、冻结款、提现中、未完成订单、未补缴收款等是否阻断,由产品和后端确认。在规则确认前,建议未结清资金类问题阻断注销,不直接照搬 Mock 的“放弃余额”。
  • 提交时必须再次校验条件。资产或影响范围发生需要重新确认的变化时,返回“请重新核验”,不得默默沿用旧快照。

3.2 发送注销短信验证码

POST /api/app/account-deletion/send-sms-code

使用有效业务 Token,请求体为 {}。只发送给当前主账号绑定手机号,不接受任意手机号参数。

{
  "code": 100000,
  "msg": "success",
  "data": {
    "verification_id": "verification_example_001",
    "masked_phone": "138****0000",
    "expires_in": 300,
    "retry_after": 60,
    "server_time": "2026-08-27T08:01:00Z"
  }
}
  • verification_id 是验证码会话标识,绑定主账号、当时的绑定手机号及“账号注销”用途,提交时一并携带。
  • expires_in、retry_after 单位为秒;示例为 5 分钟有效、60 秒后可重发,实际值由后端配置并返回。
  • 使用 6 位数字验证码;不在响应、日志或埋点中返回明文验证码。
  • 设置账号、手机号、IP 等维度的频率限制及错误次数限制;重发后旧验证码失效。
  • 与登录、提现、实名认证等验证码用途隔离。可复用短信基础设施,不可混用验证码。
  • 主账号换绑手机号后,旧手机号对应的验证码会话及核验快照失效,要求重新开始。
  • 缺少绑定手机号、发送失败或触发限流时返回明确错误;前端不能在失败时显示“已发送”。

3.3 提交注销申请

POST /api/app/account-deletion/submit

使用有效业务 Token。请求示例:

{
  "client_request_id": "709277cb-2085-49c1-b80f-042476c7c36b",
  "precheck_id": "precheck_example_001",
  "verification_id": "verification_example_001",
  "sms_code": "482951",
  "acknowledged_asset_kinds": ["wallet", "works", "projects", "cloud_files"],
  "acknowledgement_version": "account-deletion-v1"
}
字段 必填 说明
client_request_id 是 客户端为本次提交生成的 UUID 字符串;网络重试沿用同一个值
precheck_id 是 当前主账号的有效核验快照,不接受其他账号的快照
verification_id / sms_code 是 验证码会话及用户输入的真实短信码;示例不是固定验证码
acknowledged_asset_kinds 是 用户已确认的资产类别,须与快照中要求确认的集合一致
acknowledgement_version 是 用户确认的注销说明版本

成功响应示例:

{
  "code": 100000,
  "msg": "success",
  "data": {
    "state": "pending",
    "can_cancel": true,
    "server_time": "2026-08-27T08:02:00Z",
    "request": {
      "id": "deletion_example_001",
      "client_request_id": "709277cb-2085-49c1-b80f-042476c7c36b",
      "status": "pending",
      "submitted_at": "2026-08-27T08:02:00Z",
      "scheduled_deletion_at": "2026-09-03T08:02:00Z",
      "canceled_at": null,
      "completed_at": null,
      "acknowledged_asset_kinds": ["wallet", "works", "projects", "cloud_files"],
      "acknowledgement_version": "account-deletion-v1"
    }
  }
}

处理要求:

  1. 服务端重新校验身份、验证码、快照、确认版本以及资金和未完成业务条件。
  2. 原子保存申请及用户确认记录、消耗验证码,并使该主账号所有设备上的业务 Token、旧登录临时 Token 和刷新凭证失去业务访问权限。
  3. 冷静期内保留可恢复的身份及数据,不提前执行不可逆删除;状态必须限制新建订单、上传、提现等业务操作。
  4. 同一主账号同一时刻最多有一条有效申请。已成功的同一 client_request_id 重试应返回原申请,不因验证码已消费而重复报错;同一幂等键不能承载不同请求内容。
  5. 账号已有待处理申请时,不创建第二条,也不延长原截止时间;返回原状态或可识别的“已有申请”错误,客户端转查询状态。
  6. 成功页使用服务端返回的截止时间。客户端收到成功响应后应立即清理业务登录态;即使用户尚未点击成功页“退出”,后端也已禁止业务访问。

响应丢失的处理: 提交可能已成功且原 Token 已失效。此时客户端重新完成身份验证,通过登录接口取得恢复专用凭证,再查 status;不得把网络超时直接当成提交失败,也不得为了查询结果自动取消注销。

3.4 查询注销状态

GET /api/app/account-deletion/status
  • 无查询参数,以凭证定位主账号。
  • 接受有效业务 Token、正常登录临时 Token,或第 4 节定义的恢复专用 Token;不能提供匿名按手机号查询。
  • 原业务 Token 已被注销操作撤销时,不重新赋予其查询权限,应先重新验证身份取得恢复专用 Token。
  • 用于启动检查、回到前台、多设备状态校准,以及提交/取消请求超时后的结果确认。

响应 data 与提交接口一致,包含 state、can_cancel、server_time、request。无申请时:

{
  "code": 100000,
  "msg": "success",
  "data": {
    "state": "none",
    "can_cancel": false,
    "server_time": "2026-08-27T08:00:00Z",
    "request": null
  }
}
  • canceled 返回最近取消的申请和 canceled_at;completed 返回实际完成时间 completed_at。
  • can_cancel 由后端计算,只能在状态为 pending 且未到截止时刻时为 true。
  • 查询不得取消注销或延长冷静期。到期任务尚未完成时返回 processing,不能仅凭时间到了就返回 completed。
  • 状态查询失败时,不应默认账号正常;客户端提示重试或重新登录,业务接口仍由后端鉴权保护。

3.5 取消注销申请

POST /api/app/account-deletion/cancel
token: <恢复专用 Token>

只有重新验证身份且用户点击“恢复账号并登录”后调用:

{
  "request_id": "deletion_example_001"
}

成功响应示例:

{
  "code": 100000,
  "msg": "success",
  "data": {
    "request_id": "deletion_example_001",
    "state": "canceled",
    "canceled_at": "2026-08-28T01:00:00Z",
    "server_time": "2026-08-28T01:00:00Z",
    "login": {
      "token": "new-account-selection-token",
      "scenic_users": [],
      "store_users": []
    }
  }
}
  • login 结构复用现有 v9 登录响应;示例数组省略业务内容,实际需返回恢复后当前可选的景区、门店身份。
  • 返回的 login.token 为新生成的正常账号选择临时 Token;客户端继续走原有单账号自动选择、多账号选择及 /v9/set-user 流程,不复用注销前的旧凭证。
  • request_id 必须与凭证绑定的主账号和注销申请一致,不能取消别人的申请或该账号下一次新申请。
  • 与到期任务通过事务或等效并发控制互斥;按服务端时间决定取消是否成功,不能出现既恢复又删除的结果。
  • 对同一已取消申请的重试,不重复改变状态或产生副作用。若凭证仍有效,可返回原取消结果和有效登录上下文;若凭证已撤销或过期,重新登录确认状态,不要求用户再次取消。
  • 到期、processing、completed 均拒绝恢复,返回可识别错误;不得重新启用旧 Token。

4. 登录、会话与多端配合

4.1 调整现有 /api/app/v9/login

保留现有手机号密码登录参数。必须先完成密码/验证码等身份验证,再返回该主账号的注销状态,避免泄露任意手机号是否注册或注销。

状态 登录接口行为
none / canceled 沿用当前 token、scenic_users、store_users;可附带最新注销状态
未到期的 pending 不签发正常账号选择或业务 Token;返回申请信息和恢复专用 Token,等待用户决定
processing / completed 返回明确的不可登录、不可恢复业务错误,不签发可登录凭证

待注销登录建议使用成功 Envelope 承载“验证身份成功但尚未登录”的结果:

{
  "code": 100000,
  "msg": "success",
  "data": {
    "token": "",
    "scenic_users": [],
    "store_users": [],
    "account_deletion": {
      "state": "pending",
      "request_id": "deletion_example_001",
      "submitted_at": "2026-08-27T08:02:00Z",
      "scheduled_deletion_at": "2026-09-03T08:02:00Z",
      "server_time": "2026-08-28T01:00:00Z",
      "can_cancel": true
    },
    "recovery_token": "opaque-recovery-token",
    "recovery_token_expires_at": "2026-08-28T01:10:00Z"
  }
}

恢复专用 Token 要求:

  • 短时有效,并绑定主账号、当前注销申请和允许的操作;示例有效期为 10 分钟,实际由后端配置。
  • 仅可查询注销状态和取消该申请,不能调用 /v9/set-user、订单、钱包、文件下载等业务接口,也不能兑换或刷新成业务 Token。
  • 不能通过改请求参数变成其他用户的凭证;不记录到普通日志、埋点或 URL。
  • 用户选择“暂不登录”只结束本次登录,不调用取消接口;重新登录或查询本身不得自动恢复账号。
  • 取消完成后撤销该申请的恢复操作权限;新登录凭证按取消接口约定返回。

4.2 修改 /api/app/v9/set-user 和统一鉴权

  • 无论客户端是否接入新功能,待注销及不可恢复账号都不能通过旧临时 Token、刷新 Token、账号切换或其他登录入口继续使用业务。
  • 校验“凭证属于谁、凭证可做什么、账号当前是什么状态”,不能只检查签名或过期时间。
  • 提交注销需要覆盖同一主账号的全部设备和全部关联业务身份,不仅让提交申请的 iPhone 退出。
  • Android 当前有 /v9/login 的密码和短信两种登录方式;所有方式执行相同的状态检查。iOS 短信登录入口目前仍待接入,不能因此遗漏后端约束。
  • 冷静期取消后签发新凭证,不恢复旧凭证的有效性;业务身份列表以取消时的最新数据为准。

4.3 与客户端接入的关系

当前本地 loginState、cancelDeletion 是同步方法,接入网络后需改为异步;不能只替换 Mock 类名。

客户端还需扩展登录返回模型、恢复专用 Token 上下文、processing 状态、短信倒计时、阻断原因和核验快照处理。当前 Mock 使用登录输入框中的手机号取消注销,真实接口必须改用受验证的主账号/申请上下文,不能继续依赖可编辑输入值。

当前 Mock 申请 ID 使用 Swift UUID,资产枚举原始值包含 cloudFiles;本文建议接口使用字符串 ID 和 cloud_files。客户端需通过网络 DTO 显式映射,不能把本地 Mock 模型直接序列化后当作请求契约。

5. 服务端必须负责的后台处理

  • 提交成功后持久保存申请,App 卸载、退出或长期离线都不影响到期处理。
  • 冷静期内不执行不可逆清理;到期后先禁止恢复,再按最终确认的规则解除身份、处理个人资产和第三方关联。
  • 共享资产、资金账务、交易记录、客户已购买内容等分别制定处理方案;需要保留的记录与可删除的个人数据应区分,保留范围及周期由相关负责人确认。
  • 处理任务可重复执行且有重试机制;只有约定的必需处理步骤完成后才标记 completed,部分失败不能假报成功。
  • 保留可审计的申请、确认说明版本、时间、取消记录、处理进度及失败原因;审计中不保留明文验证码或 Token。
  • 到期删除与取消操作必须有统一的并发保护;业务鉴权和后台任务读取一致的主账号状态。
  • 需要测试环境的可控时间或缩短冷静期能力,以便验证到期边界及失败重试;不得在生产开放客户端任意修改截止时间的接口。

6. 错误返回要求

沿用整数 code 和可直接展示的中文 msg。以下名称是待后端分配业务码的语义清单,不是现有错误码。

错误语义 典型场景 客户端处理
ACCOUNT_IDENTITY_REQUIRED 主账号没有可用于验证的绑定手机号 提示先处理账号信息
DELETION_BLOCKED 资金未结清、订单未完成、负责人未移交等 展示阻断原因,禁止提交
PRECHECK_EXPIRED / PRECHECK_CHANGED 快照过期、资产或说明版本发生变化 重新核验并要求再次确认
ACKNOWLEDGEMENT_REQUIRED 缺少必需资产确认或确认版本不匹配 返回资产核验页
SMS_SEND_FAILED / SMS_RATE_LIMITED 短信发送失败或限流 提示重试;限流返回重试秒数
SMS_CODE_INVALID / SMS_CODE_EXPIRED / SMS_ATTEMPTS_EXCEEDED 验证码错误、过期、尝试超限 提示重输或重新发送
DELETION_ALREADY_PENDING 已有有效申请 查询原申请,不重复创建
NO_PENDING_DELETION 申请不存在或并非当前可取消申请 查询最新状态
DELETION_NOT_CANCELABLE 已到截止时间或正在最终处理 不再提供恢复入口
ACCOUNT_DELETION_COMPLETED 已完成注销 禁止登录和恢复
RECOVERY_TOKEN_INVALID / RECOVERY_TOKEN_EXPIRED 恢复凭证失效 重新验证身份,不自动取消
IDEMPOTENCY_CONFLICT 同一幂等键用于不同请求内容 停止自动重试,提示重新操作

错误响应继续采用现有 Envelope。后端如需在 data 中返回 blocking_reasons、retry_after 等结构化详情,需同时给出字段契约;当前 iOS APIClient 对失败响应只暴露 code/msg,接入时需要补充详情解析。

与现有全局登录失效处理区分: 当前 iOS 会将 HTTP 401/403 及业务码 180024、100091、100090、100060 视为登录失效。资产阻断、验证码错误、快照过期等业务问题不要复用这些码,避免误触发全局退出。真实凭证失效仍沿用项目鉴权规则。

7. 联调验收清单

  1. 主账号关联多个景区、门店时,核验范围完整;切换业务身份不会变成另一个注销对象;不能查询、提交或取消其他主账号的申请。
  2. 无手机号、无资产、存在余额/冻结款/未完成业务时,分别返回约定的正常或阻断结果。
  3. 正确验证码可提交;错误、过期、重发前旧码、其他用途码、其他账号验证码都不可提交。
  4. 资产确认不完整、核验过期、资产发生变化、说明版本不一致时,后端拒绝并要求重新确认。
  5. 成功申请返回准确截止时间;重复请求不产生新申请、不重置冷静期;请求超时后可重新验证身份并查到真实结果。
  6. 提交成功后所有设备及旧版本业务访问受限;旧 Token、账号选择、短信登录等不能绕过注销状态。
  7. 冷静期登录只显示恢复确认;点“暂不登录”保持待注销,点“恢复账号并登录”后取消并取得新的账号选择凭证。
  8. 恢复专用 Token 只能查询状态和取消绑定申请;不能访问业务或取消其他申请。
  9. 截止前可取消、恰好截止不可取消;取消与到期任务并发时只产生一个一致结果。
  10. 未运行 App 也会按期处理;任务部分失败会重试,处理期间保持不可恢复,未完成时不返回 completed。
  11. 已取消账号可再次发起新申请;旧申请和旧恢复凭证不能影响新申请。
  12. 完成注销后不能登录或恢复;共享数据、客户内容和需保留记录按确认的方案处理,没有越权删除。

8. 请后端与产品确认并回传

  • 账号及数据边界: 主账号映射、关联身份范围;作品与相册/项目的统计口径;共享资产和已售内容的处理方式。
  • 准入规则: 余额是否允许放弃;冻结资金、提现中、未完成订单、线下未补缴款及负责人身份是否阻断,如何解除阻断。
  • 时限和最终处理: 七天是否按 168 小时计算;到期处理内容、记录保留范围与周期;注销后同手机号能否重新注册,且不得恢复旧账号数据。
  • 接口契约: 最终路径、字段类型、完整正常/异常响应、业务码、短信频控、恢复凭证权限及有效期。
  • 联调交付: 测试环境地址、测试账号及各状态样例、到期和失败重试验证方式、预计可联调时间。

上述规则确认前,客户端中的“永久删除”“放弃资产”等 Mock 文案不能直接作为最终业务承诺,应随实际后端处理规则调整。