用户端小程序 企业/个体商户认证 开发设计文档

  • 模块:ruoyi-user(会员业务)+ ruoyi-gateway(路由/鉴权头注入)+ hugray-admin(后台主体认证审核)+ hugray-user-miniapp(前端)
  • 日期:2026-10-13
  • 需求来源:"继续实现企业、个体商户的认证,字段只做最基础的必填校验,根据原型设计ui稿并实现"
  • 原型:4 张 UI 稿(企业信息 / 法人信息 / 收款信息 / 提交审核 四步向导)
  • 关联文档:doc/design/用户端_实名认证_20261013.md(个人实名认证,本期复用其提交/审核链路范式)
  • 数据权威源:192.168.110.111:3306/hugray-account(实际表结构优先于本文档)

一、功能概述

「我的资料」页(pages/profile/edit.vue)「企业/个体户认证」行当前点击仅弹占位 toast,本次改为**跳转到企业/个体认证四步向导页**:

  1. 新增 C 端页面 pages/profile/company-certification.vue,顶部为**四段式步骤条**(企业信息 / 法人信息 / 收款信息 / 提交审核),已完成打勾、当前高亮,底部分步表单 + 「下一步 / 提交资料」按钮(原型见 4 张 UI 稿);
  2. 页面**只做基础必填校验**(名称/代码/姓名/电话/邮箱/卡号/图片等非空),**不接入任何格式/三方核验**;
  3. 提交后落 account_certification_apply(subject_type 取 2 个体工商户 / 3 企业、audit_status='0' 待审核),并联动 account_user.company_auth_status='1'(企业认证中),使其出现在后台**主体认证审核列表**;
  4. 「我的资料」页「企业/个体户认证」徽标改为按后端新下发的 companyAuthStatus 显示真实状态(未认证 / 认证中 / 已认证 / 认证失败),与「实名认证」徽标**相互独立**;
  5. 复核进入时**回填**已提交资料与状态:审核中 → 直接进入第 4 步「资料审核中」占位页;已通过 → 展示已通过提示;已驳回 → 回到第 1 步空表单并提示驳回原因,可修改重提。

后台「审」链路(列表 / 详情 / 通过 / 驳回)**已存在**,本次做两处增强:审核结果按主体类型分流回写 auth_status / company_auth_status;审核详情页补展示企业认证新增字段。


二、现状与关键约束

2.1 数据模型已预留主体类型

account_certification_apply.subject_type(char(1))取值语义已预置:**1个人 2个体工商户 3企业**,个人实名走 '1',企业/个体走 '2'/'3',**无需改类型语义,只需补列**。

2.2 现有表缺列,需补 DDL

account_certification_apply 与 account_certification 现有企业相关列仅到「营业执照」为止(company_name、credit_code、legal_person、registered_region、company_address、register_date、license_valid_period、license_image)。原型所需的**营业执照有效期类型、法人身份证正反面、法人身份证有效期、法人身份证详细地址、负责人姓名/电话/邮箱、收款类型、银行卡照片、银行卡号、开户城市**共 13 列缺失,需补。

2.3 个人 / 企业认证状态必须隔离

account_user 当前只有一个 auth_status(个人实名认证状态),而个人中心需**两行独立徽标**(「实名认证」/「企业个体户认证」)。若企业认证复用 auth_status,提交企业认证会同时把「实名认证」徽标改成「认证中」,语义错误。故**新增 account_user.company_auth_status**,个人 / 企业互不覆盖(已确认)。

2.4 C 端状态查询需按主体类型隔离

现有 selectLatestApplyByUserId / countPendingApplyByUserId 不区分主体类型,企业认证上线后会把企业申请当作个人申请回填/防重。本次为两者都加主体类型过滤:个人限 subject_type='1',企业限 subject_type in ('2','3')。

2.5 路径规划

  • 网关注入 user_id;SecurityUtils.getUserId() 取会员身份,**C 端接口不接受前端传 userId**(防水平越权)。
  • 在既有 C 端个人中心控制器 AccountProfileController(@RequestMapping("/user"),外部 /miniapp/account/user/**)上**新增**两条企业认证接口,与个人认证接口并列。
  • 与后台 AccountCertificationApplyController(外部 /account/user/certification/**)**前缀不同域**,无冲突;网关 /miniapp/account/** 路由已存在,**无需改网关**。

2.6 主键与落库策略

account_certification_apply.id 为 bigint AUTO_INCREMENT,沿用既有 useGeneratedKeys="true" keyProperty="id";列按 <if> 动态拼,未填字段不落列。


三、接口设计

统一响应体:C 端 R<T>(成功 code=200)。

3.1 提交企业/个体认证(本次新增)

  • 外部路径:POST /miniapp/account/user/company-certification(网关 StripPrefix=2 → 服务内 POST /user/company-certification)
  • 鉴权:需登录,未登录由 AuthFilter 直接 401;会员身份取自网关注入的 user_id 头,**不接受前端传 userId**。
  • 入参:JSON(CompanyCertificationApplyDto),字段与校验见下表:
步骤 字段 类型 必填 校验 说明(对应 DB 列)
企业信息 subjectType String 是 @NotBlank + @Pattern(^[23]$) 主体类型:2个体工商户 / 3企业(subject_type)
企业信息 companyName String 是 @NotBlank+@Size(max=128) 企业/个体名称(company_name)
企业信息 licenseImage String 是 @NotBlank+@Size(max=500) 营业执照图片地址(license_image)
企业信息 creditCode String 是 @NotBlank+@Size(max=32) 统一社会信用代码(credit_code)
企业信息 licenseValidType String 是 @NotBlank+@Pattern(^[12]$) 营业执照有效期类型:1长期 / 2短期(license_valid_type)
企业信息 licenseValidPeriod String 短期必填 @Size(max=32);类型=2 时服务层必填 营业执照有效期起止(license_valid_period,存 2024-01-01~2034-01-01)
企业信息 registeredRegion String 是 @NotBlank+@Size(max=128) 营业执照注册地区(registered_region)
企业信息 companyAddress String 是 @NotBlank+@Size(max=255) 营业执照详细地址(company_address)
法人信息 legalPerson String 是 @NotBlank+@Size(max=64) 法人姓名(legal_person)
法人信息 legalIdCardFront String 是 @NotBlank+@Size(max=500) 法人身份证人像面图片(legal_id_card_front)
法人信息 legalIdCardBack String 是 @NotBlank+@Size(max=500) 法人身份证国徽面图片(legal_id_card_back)
法人信息 legalIdValidType String 是 @NotBlank+@Pattern(^[12]$) 法人身份证有效期类型(legal_id_valid_type)
法人信息 legalIdValidPeriod String 短期必填 @Size(max=32);类型=2 时服务层必填 法人身份证有效期起止(legal_id_valid_period)
法人信息 legalIdAddress String 是 @NotBlank+@Size(max=255) 法人身份证详细地址(legal_id_address)
法人信息 contactName String 是 @NotBlank+@Size(max=64) 负责人姓名(contact_name)
法人信息 contactPhone String 是 @NotBlank+@Size(max=20) 负责人联系电话(contact_phone)
法人信息 contactEmail String 是 @NotBlank+@Size(max=128) 负责人邮箱(contact_email)
收款信息 payeeType String 是 @NotBlank+@Size(max=16) 收款类型(payee_type)
收款信息 bankCardImage String 是 @NotBlank+@Size(max=500) 银行卡号码面照片(bank_card_image)
收款信息 bankCardNo String 是 @NotBlank+@Size(max=32) 银行卡号(bank_card_no)
收款信息 bankCity String 是 @NotBlank+@Size(max=128) 开户城市(bank_city)
  • 出参:R<Void>(成功即 code=200)
  • 错误提示:字段级 @NotBlank/@Pattern 提示 + 业务提示「短期有效期必须填写起止日期」/「已有企业认证申请正在审核中,请勿重复提交」/「主体类型不合法」。

3.2 查询企业/个体认证状态(本次新增)

  • 外部路径:GET /miniapp/account/user/company-certification(→ 服务内 GET /user/company-certification)
  • 取该会员**最近一次**企业/个体申请(subject_type in ('2','3'),del_flag='0',id desc limit 1),出参 CompanyCertificationStatusVo:
字段 说明
subjectType / companyName / licenseImage / creditCode / licenseValidType / licenseValidPeriod / registeredRegion / companyAddress 企业信息回填
legalPerson / legalIdCardFront / legalIdCardBack / legalIdValidType / legalIdValidPeriod / legalIdAddress 法人信息回填
contactName / contactPhone / contactEmail 负责人信息回填
payeeType / bankCardImage / bankCardNo / bankCity 收款信息回填
auditStatus 0待审核 1已通过 2已驳回;**为空表示从未提交**
auditRemark 驳回原因(audit_status='2' 时有值)

无申请时返回**空字段对象**(各字段为 null),前端按「未认证」处理,不返回 404。

3.3 查询会员信息(本次扩展)

  • 外部路径:GET /miniapp/account/user/info(既有)
  • 改动:出参 AccountUserInfoVo 新增 companyAuthStatus 字段(account_user.company_auth_status 原值 0/1/2/3),供「我的资料」页「企业/个体户认证」徽标回显。

3.4 后台审核链路(既有,增强)

GET /account/user/certification/list、GET /account/user/certification/detail/{id}、PUT /account/user/certification/audit(权限 member:certification:audit)**沿用**。企业申请同链路进入列表(subject_type='2'/'3'、待审核在前)。增强点:

  • 审核分流:通过 / 驳回时按 apply.subjectType 写回——个人写 auth_status,企业/个体写 company_auth_status(通过时同步 account_user.subject_type);
  • 详情展示:detail.vue 补展示企业/个体新增字段(见 7.3)。

四、数据库设计

库:hugray-account。新增 DDL 脚本:hugray-server/sql/hugray_account_company_certification_20261013.sql(沿用既有幂等过程 hugray_add_column 风格;与代码同一次提交)。

4.1 account_certification_apply / account_certification 各新增 13 列

列 类型 注释
license_valid_type varchar(16) 营业执照有效期类型(1长期 2短期)
legal_id_card_front varchar(500) 法人身份证人像面图片
legal_id_card_back varchar(500) 法人身份证国徽面图片
legal_id_valid_type varchar(16) 法人身份证有效期类型(1长期 2短期)
legal_id_valid_period varchar(32) 法人身份证有效期(长期/起止文本)
legal_id_address varchar(255) 法人身份证详细地址
contact_name varchar(64) 负责人姓名
contact_phone varchar(20) 负责人联系电话
contact_email varchar(128) 负责人邮箱
payee_type varchar(16) 收款类型
bank_card_image varchar(500) 银行卡号码面照片
bank_card_no varchar(32) 银行卡号
bank_city varchar(128) 开户城市

4.2 account_user 新增 1 列

列 类型 注释
company_auth_status char(1) DEFAULT '0' 企业/个体认证状态(0未认证 1审核中 2已认证 3认证失败)

license_valid_period 沿用既有 varchar(32):2024-01-01~2034-01-01 共 21 字符,够用,不改类型。


五、流程设计

5.1 前端四步向导(pages/profile/company-certification.vue)

STEP 1: onShow 校验登录态(ensureLogin),未登录跳登录页
STEP 2: 调 GET /company-certification 拉取状态与资料
STEP 3: 按 auditStatus 决定首屏:
        '' 未认证 → 停在第 1 步空表单
        '2' 已驳回 → 停在第 1 步并回填资料,展示驳回原因
        '0' 审核中 → 直接进入第 4 步「资料审核中」占位页
        '1' 已通过 → 第 4 步展示「认证已通过」
STEP 4: 第 1~3 步表单填写,点「下一步」逐级校验当前步必填项,通过则 step+1,否则 toast 首个缺失项
STEP 5: 第 3 步(收款信息)按钮为「提交资料」,点后整表单再校验一次,通过则 POST 提交
STEP 6: 成功后进入第 4 步「您的资料正在审核中,请耐心等待」;失败提示后端信息
STEP 7: 步骤条已完成的步骤打勾,可点已完成步骤回退修改(未提交前)

交互细节(对齐原型):
- 有效期类型 = 长期 时,其**起止日期行隐藏**且不参与校验;= 短期 时显示且必填(已确认)。
- 「营业执照注册地区」「开户城市」用 <picker mode="region">(沿用 pages/address/add.vue 范式);「营业执照详细地址」「法人身份证详细地址」为文本输入。
- 图片项(营业执照 / 法人身份证人像面 / 法人身份证国徽面 / 银行卡号码面)统一走 uni.chooseImage + uploadAvatarFile(/file/upload)拿到 url 后存本地表单,**均为必填**(已确认)。
- 有效期起止日期用两个 <picker mode="date">(开始 / 截止)并列在同一行内展示,回填时拼为 起~止 文本;存储为 license_valid_period / legal_id_valid_period 文本。

5.2 后端提交(submitCompanyCertification)

STEP 1: 校验 userId 非空(未登录由网关拦截,此处兜底),为空抛业务异常
STEP 2: 校验 subjectType ∈ {2 个体工商户, 3 企业};非法抛「主体类型不合法」
STEP 3: 有效期类型=短期(2) 时,对应起止日期必填(服务层兜底,防绕过 Controller)
STEP 4: 防重闸门:该会员若存在 subject_type in ('2','3') 且 audit_status='0' 的未删除申请,
        抛「已有企业认证申请正在审核中,请勿重复提交」
STEP 5: 组装申请快照:subject_type、各资料字段、audit_status='0'、create_by=登录用户名
STEP 6: insertCertificationApply 落 account_certification_apply(自增回填 id)
STEP 7: 联动 account_user.company_auth_status='1'(企业认证中,单列更新语句)
STEP 8: STEP 6/7 同事务(@Transactional),任一失败整体回滚

5.3 审核分流(auditCertificationApply 增强)

STEP 1: 既有并发闸门(where audit_status='0')+ 驳回必填意见 不变
STEP 2: 取 apply.subjectType 判断分支:
        subject_type='1'(个人)→ 写 account_user.auth_status(2 通过 / 3 失败),行为同现状
        subject_type∈{'2','3'} → 写 account_user.company_auth_status(2 通过 / 3 失败)
                                且通过时同步 account_user.subject_type = apply.subjectType
STEP 3: 通过分支继续 saveCertificationSnapshot(补全企业新增字段)

5.4 状态流转(端到端)

C 端提交 ─► account_certification_apply.audit_status='0' + account_user.company_auth_status='1'
                    │
后台「通过」─► audit_status='1' + company_auth_status='2' + subject_type 同步 + 落 account_certification
后台「驳回」─► audit_status='2' + company_auth_status='3' + 记审核意见

六、枚举与状态

名称 取值 说明
subject_type 主体类型 1 个人 / 2 个体工商户 / 3 企业 企业向导页提交 2/3(页内选择);个人页提交 1
audit_status 审核状态 0 待审核 / 1 已通过 / 2 已驳回 提交置 0,审核改 1/2
auth_status 个人认证状态 0 未认证 / 1 审核中 / 2 已认证 / 3 认证失败 个人实名专用
company_auth_status 企业认证状态 0 未认证 / 1 审核中 / 2 已认证 / 3 认证失败 企业/个体专用(本期新增)
license_valid_type / legal_id_valid_type 有效期类型 1 长期 / 2 短期 长期隐藏起止日期;短期必填

「我的资料」页徽标映射:auth_status →「实名认证」行;company_auth_status →「企业/个体户认证」行(0未认证、1认证中、2已认证、3认证失败)。


七、影响范围与文件清单

7.1 新增(ruoyi-user)

文件 说明
domain/dto/CompanyCertificationApplyDto.java 企业/个体认证提交入参(含校验注解与字段注释)
domain/vo/CompanyCertificationStatusVo.java 企业/个体认证状态与资料回填出参
src/test/.../AccountCertificationApplyServiceImplTest.java 追加提交/审核分流用例(正常、重复提交拒绝、短期缺日期、状态分流)

7.2 修改(ruoyi-user)

文件 改动
domain/AccountCertificationApply.java 新增 13 个企业/个体字段 + getter/setter + toString
domain/AccountCertification.java 同步新增 13 个字段
mapper/AccountCertificationApplyMapper.java 新增 selectLatestCompanyApplyByUserId、countPendingCompanyApplyByUserId;selectLatestApplyByUserId→selectLatestPersonalApplyByUserId(加 subject_type='1')、countPendingApplyByUserId→countPendingPersonalApplyByUserId(加 subject_type='1')
resources/mapper/user/AccountCertificationApplyMapper.xml resultMap / selectCertificationApplyVo / 列表 / insert 补新增列;主体类型过滤调整;新增企业两条查询
resources/mapper/user/AccountCertificationMapper.xml resultMap / selectCertificationVo / insert / update 补新增列
mapper/AccountUserMapper.java 新增 updateUserCompanyAuthStatus(AccountUser)
resources/mapper/user/AccountUserMapper.xml 新增 updateUserCompanyAuthStatus(只写 company_auth_status,通过时带 <if> 同步 subject_type)
service/IAccountCertificationApplyService.java 新增 submitCompanyCertification(Long, CompanyCertificationApplyDto)、getCompanyCertificationStatus(Long)
service/impl/AccountCertificationApplyServiceImpl.java 常量补 SUBJECT_INDIVIDUAL='2'/SUBJECT_COMPANY='3';实现企业提交与状态查询;auditCertificationApply 按主体类型分流;saveCertificationSnapshot 补字段
controller/AccountProfileController.java 新增 POST /user/company-certification、GET /user/company-certification
domain/vo/AccountUserInfoVo.java 新增 companyAuthStatus 字段
service/impl/AccountUserServiceImpl.java getAccountUserInfo 填充 companyAuthStatus

7.3 修改(后台 hugray-admin)

文件 改动
views/member/certification/detail.vue 「主体资料」区块补展示:主体类型、营业执照有效期类型/起止、法人身份证人像/国徽面(image-preview)、法人身份证有效期类型/起止、法人身份证详细地址、负责人姓名/电话/邮箱、收款类型、银行卡照片(image-preview)、银行卡号、开户城市

列表页 index.vue 的主体类型/主体名称列已由 subject_type 与 companyName \|\| realName 覆盖,**无需改动**。

7.4 新增(前端 hugray-user-miniapp)

文件 说明
pages/profile/company-certification.vue 企业/个体四步向导页(步骤条 + 分步表单 + 图片上传 + 地区/日期选择)

7.5 修改(前端 hugray-user-miniapp)

文件 改动
pages.json 注册 pages/profile/company-certification(navigationStyle: custom)
api/index.js 新增 getCompanyCertificationStatus()(→ GET)、submitCompanyCertification(data)(→ POST)
pages/profile/edit.vue 「企业/个体户认证」行由 handlePlaceholder 改为 uni.navigateTo 跳向导页;companyStatus 改按 /info 返回的 companyAuthStatus 映射回显

网关无需改动;无需新增菜单/权限。

7.6 新增(DDL)

文件 说明
hugray-server/sql/hugray_account_company_certification_20261013.sql 两张认证表各补 13 列 + account_user 补 company_auth_status(幂等,含回滚注释)

八、边界与异常清单

# 场景 处理
1 未登录访问 网关 AuthFilter 返回 401,前端跳登录页;后端不做分支
2 user_id 头缺失/为空 服务内兜底判空,抛业务异常(不 NPE)
3 必填项为空 / 纯空格 DTO @NotBlank 拦截,返回字段级中文提示;前端「下一步」逐级预校验并 toast 首个缺失项
4 有效期类型=长期 起止日期行隐藏且不校验;短期时必填
5 有效期类型=短期但未填日期 服务层兜底抛「短期有效期必须填写起止日期」
6 图片未上传 按必填拦截(toast「请上传XX图片」)
7 主体类型非法(非 2/3) 服务层抛「主体类型不合法」
8 已有待审核企业申请再次提交 服务层企业防重闸门提示「已有企业认证申请正在审核中,请勿重复提交」
9 个人 / 企业申请互相干扰 状态查询与防重均按 subject_type 隔离;认证状态分列 auth_status / company_auth_status
10 审核通过 / 驳回 按 subject_type 分流回写,通过时同步 subject_type 并落 account_certification
11 落库或状态联动失败 同一事务回滚,返回统一错误,不产生半更新
12 越权 会员身份取自令牌注入头,不接受前端传 userId,天然防水平越权
13 三方核验 / 格式校验 本期明确不做,仅基础必填校验
14 图片上传失败 沿用 uploadAvatarFile 错误处理,toast 提示并可重试

九、规范符合性说明

  • 分层:Controller 只取身份 + 转发;业务在 Service;SQL 在 Mapper;Controller 不直接调 Mapper。
  • 命名:submitCompanyCertification / getCompanyCertificationStatus / selectLatestCompanyApplyByUserId / countPendingCompanyApplyByUserId / updateUserCompanyAuthStatus 见名知意;DTO / VO / Entity 分离。
  • 注释:DTO / VO / Mapper / Service 方法具备 Javadoc;核心流程按 // STEP x: 分步注释;实体新增字段附列名与取值注释。
  • 魔法值:subject_type、audit_status、auth_status、company_auth_status、*_valid_type 取值抽为常量/枚举语义。
  • 事务:提交接口 insert + 状态联动 同事务;审核 更新申请 + 状态分流 + 落档 同事务。
  • 幂等/防重:以待审核企业申请为闸门,拒绝重复提交。
  • 数据库:新增列显式长度 + COMMENT;无 SELECT *;无 ${} 拼接;无循环查库;DDL 与代码同次提交。
  • 单测:覆盖企业提交正常、短期缺日期拒绝、重复提交拒绝、审核分流(企业写 company_auth_status)。
  • 文档:本文档与代码同仓库、同分支、同节奏提交。

十、已确认决策

  1. 认证状态存储:**已定** —— 新增 account_user.company_auth_status,个人 / 企业徽标各自独立,互不覆盖。
  2. 主体类型:**已定** —— 「企业信息」步骤顶部增加「主体类型」选择项(企业 / 个体工商户),subject_type 存 3 / 2(比原型多一个字段)。
  3. 有效期校验:**已定** —— 「有效期类型」选**长期**时**隐藏起止日期且不必填**;选短期时显示且必填。
  4. 图片必填:**已定** —— 营业执照、法人身份证人像面/国徽面、银行卡号码面照片**均为必填**。
  5. 校验深度:**已定** —— 仅基础必填校验,**不做格式/三方核验**。
  6. 审核入口:**已定** —— 复用后台「主体认证审核」列表/详情/通过/驳回链路,列表无需改,详情补展示新增字段。