Skip to content

商户入驻至平台审核激活全链路测试规范 (Spec) ​

本文档定义了携岛项目(XieLi)商户入驻申请、平台端审核、保证金支付以及激活状态控制的自动化测试用例规范。

一、 测试设计原则与数据准备 ​

  1. 测试环境要求:
    • 后端服务基于 Spring Boot 运行,直连远程数据库 xieli_dev (8.134.105.163) 和本地 Redis 缓存服务。
  2. 唯一性测试数据动态生成:
    • 由于测试数据不需要回滚且会真实落库,为了支持用例被多次重复运行而不触发唯一索引冲突(如手机号重复注册),所有用例中的关键标识均需动态生成:
      • 手机号:使用 13 加上随机 9 位数字(例如:13 + System.currentTimeMillis() % 1000000000)。
      • 商户名称:拼接时间戳,例如 自动化测试商户_1719500000。
      • 订单号:按系统规则生成唯一前缀 MCH + 毫秒级时间戳。

二、 自动化测试用例设计 ​

Case 1: 商户入驻申请字段合法性校验 (Verification & Validation) ​

  • 目的:验证入驻表单字段完整性校验及个人与企业商户的差异化拦截。
  • 输入/测试数据:
    • 用例 1A (公共必填校验):缺少联系电话/密码/业务类型。
    • 用例 1B (企业入驻差异化校验):缺少开户支行 bankBranch / 营业执照等。
    • 用例 1C (个人入驻差异化校验):个人入驻(如专车司机)缺少身份证号 idCard 等,但无需校验营业执照。
  • 预期结果:接口应正确返回状态码 500,并提示具体缺少的字段信息(例如:“开户支行不能为空”)。

Case 2: 手机号唯一性冲突拦截 ​

  • 目的:验证相同手机号不可重复申请商户。
  • 步骤:
    1. 产生一个随机手机号 phoneA 并完成第一次合法入驻申请。
    2. 使用相同的 phoneA 再次发起入驻申请。
  • 预期结果:第二次申请时接口拦截并提示 该手机号已注册商户。

Case 3: 短信验证码强制拦截 ​

  • 目的:防止绕过短信验证接口直接提交入驻表单。
  • 步骤:
    1. 产生一个随机手机号 phoneB。
    2. 不向 Redis 写入验证状态,直接调用入驻申请 /api/merchant/apply。
  • 预期结果:接口应被拒绝,返回提示:请先完成手机号验证码校验。

Case 4: 敏感数据 AES 加密落库 ​

  • 目的:保证法人身份证、手机号和对公银行卡号的隐私安全。
  • 步骤:
    1. 发起一次合法的企业商户入驻,提交明文法人身份证 110101199001011234 和银行卡号 6222020202020202020。
    2. 直接从商户表 xl_merchant 查询刚才插入的记录。
  • 预期结果:
    • 数据库中的 legal_person_id_card 和 bank_account_number 字段必须为 AES 密文(长度显著变长,非明文)。
    • 调用商户端详情接口时,能解密出正常明文供校验。

Case 5: OCR 识别与优雅降级 ​

  • 目的:当阿里云 OCR 识别发生故障时,不影响正常入驻。
  • 步骤:
    1. 模拟调用 upload-and-ocr,但由于某种原因(或人工 Mock)第三方 OCR 服务返回识别结果为 null。
    2. 验证系统能成功上传图片到 OSS 并不报错。
  • 预期结果:返回上传成功的 ossUrl,且 ocrResult 字段为 null(允许降级)。

Case 6: 平台端审核越权拦截 ​

  • 目的:确保非管理员用户无法修改商户状态。
  • 步骤:
    1. 生成测试商户并提交,状态为 1 (待审核)。
    2. 不携带任何管理员 Token,或携带普通商户的 Token 访问审核接口 /api/admin/merchants/audit。
  • 预期结果:接口应返回 403 或被 Spring Security 拦截。

Case 7: 平台审核状态机边界控制 ​

  • 目的:防止通过接口非法更改商户状态。
  • 步骤:
    1. 已经通过审核(或已经是注销状态)的商户。
    2. 管理员再次对其调用 /audit 接口尝试通过/驳回。
  • 预期结果:系统抛出异常,提示:只有待平台审核商户可以审核。

Case 8: 审核意见与驳回重提全流转 ​

  • 目的:验证审核驳回、补料重提交的完整闭环。
  • 步骤:
    1. 管理员调用审核接口驳回该商户,状态设为 2,记录 rejectReason: "营业执照模糊"。
    2. 商户端调用 /resubmit 重提资料(包含更新后的营业执照路径)。
    3. 再次查询商户状态。
  • 预期结果:
    • 重提后商户状态回滚为 1 (待审核)。
    • 原驳回意见字段 rejectReason 被重置清空(null)。
    • 敏感字段保持加密。

Case 9: 支付回调幂等性校验 ​

  • 目的:防止因微信重复回调导致多次处理订单或重复激活。
  • 步骤:
    1. 商户通过审核进入 3 (待支付) 状态,生成保证金订单。
    2. 模拟微信发起第一次支付成功通知(回调 /api/merchant/pay/notify)。
    3. 紧接着使用完全相同的报文和单号发起第二次回调。
  • 预期结果:
    • 第一次回调后,商户状态变为 4 (激活),paidAt 被记录。
    • 第二次回调接口成功返回,但不再执行更新商户表的操作,数据库内状态和时间保持一致。

Case 10: 回调丢失的主动查单兜底 ​

  • 目的:保证微信回调丢包时商户端仍能正常激活。
  • 步骤:
    1. 模拟商户已支付完成,但后端接口因为网络中断没有接收到支付成功回调。
    2. 商户端轮询查询状态,即调用 /api/merchant/status/{merchantId}。
    3. 后端触发向微信查单并返回成功。
  • 预期结果:在查询后,数据库中的商户状态自动更新为 4 (激活),且写入 paidAt。

Case 11: 未激活商户的 403 路由拦截 (White-list Enforcement) ​

  • 目的:保护核心商户接口,只有激活商户能开展业务。
  • 步骤:
    1. 创建待审核 (状态 1) 或待支付 (状态 3) 的商户,并生成对应的商户端 JWT 登录 Token。
    2. 使用此 Token 访问商户端非白名单接口(如 /api/merchant/wallet/info 或商品发布等)。
    3. 访问白名单接口 /api/merchant/status。
  • 预期结果:
    • 访问非白名单接口被拦截,返回状态码 403 或报错提示 商户审核未通过,暂无权访问该功能。
    • 访问 /status 接口正常返回。

Case 12: 注销与保证金退款流(含手动降级) ​

  • 目的:验证商户注销时的退保证金逻辑。
  • 步骤:
    1. 激活状态商户(已付保证金)发起注销。
    2. 校验商户状态变为 5 (注销中),并且创建了 xl_refund_record 退款记录。
    3. 若微信退款接口异常,管理员在微信平台手工退款后,调用平台端 /confirmDepositRefund。
  • 预期结果:商户状态成功变更为 6 (已注销)。

Case 13: 电商商城商户入驻流程 ​

  • 目的:验证 businessType 为 mall 时能够成功提交申请且 entryType 被自动判定为 merchant。
  • 步骤:
    1. 准备商户分类为 clothing (服装商城),对应业务类型 mall。
    2. 发起商户入驻申请。
  • 预期结果:申请成功,返回 entryType 为 "merchant"。

Case 14: 本地生活商户入驻流程 ​

  • 目的:验证 businessType 为 locallife 时能够成功提交申请且 entryType 判定为 merchant。
  • 步骤:
    1. 准备商户分类为 food (餐饮美食),对应业务类型 locallife。
    2. 发起商户入驻申请。
  • 预期结果:申请成功,返回 entryType 为 "merchant"。

Case 15: 合作摄影师个人入驻流程 ​

  • 目的:验证 businessType 为 delivery 且 categoryCode 为 photographer 时,系统判定为 personal(个人入驻),仅校验个人必填字段并成功插入。
  • 步骤:
    1. 准备分类为 photographer,业务类型为 delivery。
    2. 发起个人入驻申请,仅提交身份证件信息,跳过营业执照与银行对公信息。
  • 预期结果:申请成功,返回 entryType 为 "personal"。

Case 16: 合作司机个人入驻流程 ​

  • 目的:验证 businessType 为 delivery 且 categoryCode 为 driver 时,系统判定为 personal(个人入驻),仅校验个人必填字段并成功插入。
  • 步骤:
    1. 准备分类为 driver,业务类型为 delivery。
    2. 发起个人入驻申请,仅提交身份证件信息,跳过营业执照与银行对公信息。
  • 预期结果:申请成功,返回 entryType 为 "personal"。

携岛 XieDao · 内部文档