____ _ ____ _
/ ___| ___ __ _| | / ___| _ _ ___| |_ ___ _ __ ___
\___ \ / _ \/ _` | | \___ \| | | / __| __/ _ \ '_ ` _ \
___) | __/ (_| | | ___) | |_| \__ \ || __/ | | | | |
|____/ \___|\__,_|_| |____/ \__, |___/\__\___|_| |_| |_|
|___/ | 技术 | 版本 | 说明 |
|---|---|---|
| Spring Boot | 2.7.x | 基础框架 |
| MyBatis-Plus | 3.5.x | ORM 框架 |
| MySQL | 5.7+ / 8.0+ | 数据库 |
| Redis | 6.0+ | 缓存 & 短链接存储 |
| iText | 5.5.13 | PDF 处理与数字签名 |
┌─────────────────────────────────────────────────────────┐
│ 应用层 (Application) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ │
│ │ Admin UI │ │seal-core │ │mini-cont.│ │Portal │ │
│ │ (管理后台) │ │ (签署引擎) │ │(小程序/H5)│ │(PC门户) │ │
│ └──────────┘ └──────────┘ └──────────┘ └────────┘ │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 接口层 (Controller) │
│ ┌────────────┐ ┌────────────┐ ┌──────────────────┐ │
│ │ Admin API │ │ App API │ │ Portal API │ │
│ │ (管理端) │ │ (签署/认证) │ │ (PC门户端) │ │
│ └────────────┘ └────────────┘ └──────────────────┘ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Open API(第三方开放接口) │ │
│ │ 认证 → 签署任务 → Webhook 回调 │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 业务层 (Service) │
│ ┌──────────┐ ┌──────────┐ ┌────────────┐ │
│ │SealSign │ │Seal │ │Notification│ │
│ │TaskSvc │ │ConfigSvc │ │Service │ │
│ │(签署任务) │ │(配置读取) │ │(通知&短链接) │ │
│ └──────────┘ └──────────┘ └────────────┘ │
│ ┌──────────┐ ┌──────────┐ ┌────────────┐ │
│ │Signature │ │IntentVer.│ │Template │ │
│ │Service │ │Service │ │Service │ │
│ │(PDF签名) │ │(意愿验证) │ │(模板管理) │ │
│ └──────────┘ └──────────┘ └────────────┘ │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 扩展层 (SPI / Starter) │
│ ┌────────────────────┐ ┌──────────────────────────┐ │
│ │ UserInfoProvider │ │ QuotaValidator │ │
│ │ (用户信息获取) │ │ (配额校验) │ │
│ └────────────────────┘ └──────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 数据层 (DAO / Mapper) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ MySQL │ │ Redis │ │ OSS │ │
│ │ (业务数据) │ │ (短链接/缓存)│ │ (文件存储) │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────┘yudao-module-seal/
├── yudao-module-seal-api/ # 公共 API(DTO、枚举、SPI 接口)
│ └── api/
│ ├── auth/ # 认证 SPI(SealAuthProvider)
│ ├── storage/ # 存储 SPI(SealStorageProvider)
│ └── validator/ # 校验 SPI(SealQuotaValidator、SealUserValidator)
├── yudao-module-seal-biz/ # 业务实现(Controller、Service、DAL)
│ └── service/user/ # 用户信息 SPI(UserInfoProvider、UserInfoAdapter)
└── yudao-module-seal-spring-boot-starter/ # 产品化 Starter(SPI 适配、License)
├── adapter/ # SPI 适配器实现(auth、storage、user、enterprise)
└── validator/ # SPI 校验器实现(Ruoyi 适配 + NoOp 降级)| 项目 | 说明 | 路径 |
|---|---|---|
| seal-core | 签署引擎 H5(签署页面、短链接路由) | yudao-ui/seal-core |
| mini-contract | uni-app 用户端(小程序 / H5 / APP) | mini-contract/ |
| contract-portal-pc | PC 端合同管理门户 | yudao-ui/contract-portal-pc |
| yudao-ui-admin-vue3 | 管理后台 | yudao-ui/yudao-ui-admin-vue3 |
yudao-module-seal-biz/src/main/java/cn/iocoder/yudao/module/seal/
├── controller/
│ ├── admin/ # 管理端 API
│ │ ├── sealsigntask/ # 签署任务管理
│ │ └── vo/ # 管理端 VO
│ ├── app/ # App 端 API(小程序/H5 直接调用)
│ │ ├── signtask/ # 签署任务(含 auth-by-ref 认证)
│ │ ├── seal/ # 印章操作
│ │ ├── shortlink/ # 短链接信息
│ │ └── template/ # 模板操作
│ ├── portal/ # Portal 端 API(PC 门户调用)
│ └── open/ # Open API(第三方开放接口)
│ ├── OpenSealAuthController # 认证(AppKey/Secret → Token)
│ ├── OpenSignTaskController # 签署任务 CRUD
│ ├── OpenWebhookController # Webhook 回调配置
│ └── vo/ # Open API 请求/响应 VO
├── service/
│ ├── sealsigntask/ # 签署任务核心业务
│ ├── config/ # 配置服务(SealConfigService)
│ ├── notification/ # 通知 & 短链接生成
│ ├── signature/ # PDF 数字签名
│ ├── intentverification/ # 签署意愿验证
│ └── webhook/ # Webhook 回调服务
│ ├── SealWebhookService # 接口
│ └── SealWebhookServiceImpl # 实现(WebClient + 异步 + 重试)
├── dal/
│ ├── dataobject/ # 数据对象(DO)
│ │ └── webhook/ # Webhook 相关 DO
│ │ ├── SealWebhookConfigDO # 回调配置
│ │ └── SealWebhookLogDO # 回调日志
│ ├── mysql/ # Mapper
│ │ └── webhook/ # Webhook Mapper
│ └── redis/ # Redis Key 常量
├── framework/
│ └── security/ # Seal Token 认证体系
└── util/
└── jwt/ # JWT 工具┌─────────────────────────────────────────────────────────────────┐
│ seal-biz(业务层) │
│ │
│ SealSignTaskServiceImpl │
│ ├── @Resource UserInfoProvider ← 获取用户手机号等 │
│ ├── @Resource SealUserValidator ← 校验用户/实名认证 │
│ ├── @Autowired(required=false) │
│ │ SealQuotaValidator ← 配额校验(可选) │
│ └── @Autowired(required=false) │
│ EnterpriseAccessValidator ← 企业权限校验(可选) │
│ │
│ PdfDigitalSignatureService │
│ └── @Resource SealStorageProvider ← 文件上传/下载 │
│ │
│ SealTokenAdapter │
│ └── @Resource SealAuthProvider ← 用户认证 │
└────────────────────────┬────────────────────────────────────────┘
│ 接口调用(无编译依赖)
▼
┌─────────────────────────────────────────────────────────────────┐
│ seal-spring-boot-starter(适配层) │
│ │
│ ┌─────────────────┐ ┌──────────────────┐ ┌───────────────┐ │
│ │ RuoyiAuthAdapter │ │RuoyiQuotaValid. │ │UserInfoAdapter│ │
│ │ JwtAuthAdapter │ │RuoyiUserValid. │ │ Impl │ │
│ │ OAuth2AuthAdapter│ │NoOpQuotaValid. │ │NoOpUserInfo │ │
│ └─────────────────┘ │NoOpUserValid. │ │ Adapter │ │
│ └──────────────────┘ └───────────────┘ │
│ ┌──────────────────────┐ ┌──────────────────────────────┐ │
│ │ RuoyiFileClientAdapter│ │EnterpriseAccessValidatorImpl │ │
│ │ OssStorageAdapter │ │NoOpEnterpriseAccessValidator │ │
│ │ MinioStorageAdapter │ └──────────────────────────────┘ │
│ │ LocalStorageAdapter │ │
│ └──────────────────────┘ │
│ │
│ 通过 @Conditional 注解自动选择实现 │
└─────────────────────────────────────────────────────────────────┘| SPI 接口 | 所在模块 | 职责 | 是否必需 | 默认实现 |
|---|---|---|---|---|
SealAuthProvider | seal-api | 用户认证(从请求中提取用户信息) | 是 | 拒绝所有请求(需配置) |
SealStorageProvider | seal-api | 文件存储(上传/下载/删除) | 是 | 抛异常(需配置) |
SealQuotaValidator | seal-api | 配额校验与扣减 | 否(可选) | 跳过配额检查 |
SealUserValidator | seal-api | 用户存在性与实名认证校验 | 是 | RuoyiUserValidator |
UserInfoProvider | seal-biz | 获取用户手机号、昵称等详细信息 | 是 | 通过 Bridge 桥接 |
UserInfoAdapter | seal-biz | UserInfoProvider 的适配器接口 | 是 | NoOpUserInfoAdapter(降级) |
EnterpriseAccessValidator | seal-biz | 验证用户是否有企业访问权限 | 否(可选) | NoOpEnterpriseAccessValidator(放行) |
seal-api):| 实现类 | 激活条件 | 说明 |
|---|---|---|
RuoyiAuthAdapter | classpath 存在 SecurityFrameworkUtils | 从 Ruoyi 的 ThreadLocal 中获取登录用户 |
JwtAuthAdapter | yudao.seal.auth.type=jwt | 解析 JWT Token |
OAuth2AuthAdapter | yudao.seal.auth.type=oauth2 | OAuth2 Token 验证 |
seal-api):| 实现类 | 说明 |
|---|---|
RuoyiFileClientAdapter | 适配 Ruoyi 的 FileClient(推荐,复用 Ruoyi 文件配置) |
OssStorageAdapter | 阿里云 OSS |
MinioStorageAdapter | MinIO 对象存储 |
LocalStorageAdapter | 本地文件系统 |
seal-api):| 实现类 | 激活条件 | 说明 |
|---|---|---|
RuoyiQuotaValidator | yudao.seal.quota-validator=ruoyi(默认) | 读取 member_quota_account 表,使用乐观锁扣减 |
NoOpQuotaValidator | yudao.seal.quota-validator=noop | 不做任何校验,始终返回 true(测试用) |
seal-api):| 实现类 | 激活条件 | 说明 |
|---|---|---|
RuoyiUserValidator | yudao.seal.user-validator=ruoyi(默认) | 查询 system_user 和 member_user 表 |
NoOpUserValidator | yudao.seal.user-validator=noop | 始终返回成功(开发/测试用,生产会告警) |
seal-biz 定义
┌──────────────┐ ┌──────────────────┐ ┌──────────────┐
│ Service 层 │───▶│ UserInfoProvider │◀──│UserInfoPro- │
│ (业务代码调用) │ │ (接口) │ │viderBridge │
└──────────────┘ └──────────────────┘ └──────┬───────┘
│ 委托
▼
┌──────────────────┐ ┌──────────────┐
│ UserInfoAdapter │◀──│UserInfoAdap- │ seal-starter 实现
│ (接口) │ │terImpl │
└──────────────────┘ └──────────────┘UserInfoProvider:seal-biz 内部使用的标准接口,业务代码只依赖它UserInfoAdapter:供 Starter 模块实现的适配器接口,包含 getAdapterType() 等管理方法UserInfoProviderBridge:桥接器,将 Starter 的 Adapter 实现桥接为 Biz 的 Providerseal-biz):| 实现类 | 激活条件 | 说明 |
|---|---|---|
UserInfoAdapterImpl | classpath 存在 MemberUserApi | 通过反射调用 member 模块,避免编译依赖 |
NoOpUserInfoAdapter | 无其他 Adapter 实现时 | 返回 null,功能降级,日志告警 |
seal-biz):| 实现类 | 激活条件 | 说明 |
|---|---|---|
EnterpriseAccessValidatorImpl | classpath 存在 MemberEnterpriseUserService | 通过反射调用 member 模块 |
NoOpEnterpriseAccessValidator | 无其他实现时 | 始终放行,日志告警 |
@Resource):@Autowired(required = false)):META-INF/spring.factories 声明 SealAutoConfigurationyudao.seal.mode=starter 时激活自动配置@Conditional* 注解控制装配条件spring.factories
└── SealAutoConfiguration (@ConditionalOnProperty: yudao.seal.mode=starter)
├── @ComponentScan 扫描 seal.biz + seal.starter 包
├── RuoyiAuthAdapter (@ConditionalOnClass: SecurityFrameworkUtils)
├── RuoyiQuotaValidator (@ConditionalOnProperty: quota-validator=ruoyi, 默认)
├── RuoyiUserValidator (@ConditionalOnProperty: user-validator=ruoyi, 默认)
├── UserInfoAdapterImpl (@ConditionalOnClass: MemberUserApi)
├── UserInfoProviderBridge(@ConditionalOnBean: UserInfoAdapter)
├── NoOpQuotaValidator (@ConditionalOnProperty: quota-validator=noop)
├── NoOpUserValidator (@ConditionalOnProperty: user-validator=noop)
├── NoOpUserInfoAdapter (@ConditionalOnMissingBean: UserInfoAdapter)
└── NoOpEnterpriseAccess (@ConditionalOnMissingBean: EnterpriseAccessValidator)| 配置键 | 可选值 | 默认值 | 说明 |
|---|---|---|---|
yudao.seal.mode | starter / 不设置 | 不启用 | 总开关,必须设为 starter 才激活自动配置 |
yudao.seal.auth.type | ruoyi / jwt / oauth2 | ruoyi | 认证方式 |
yudao.seal.storage.type | local / oss / minio | - | 存储方式 |
yudao.seal.quota-validator | ruoyi / noop | ruoyi | 配额校验器 |
yudao.seal.user-validator | ruoyi / noop | ruoyi | 用户校验器 |
@Component 或 @Bean)application.yml 中设置对应值注意:自定义实现会自动覆盖内置的默认实现(通过 @ConditionalOnMissingBean/@ConditionalOnProperty机制)。
infra_config 表中管理,管理员通过管理后台「基础设施 - 参数配置」操作,无需修改代码或重启服务。| 配置键 | 说明 | 示 例值 |
|---|---|---|
seal.platform.h5-domain | seal-core H5 域名(签署引擎) | https://seal.example.com |
seal.platform.mini-contract-h5-domain | mini-contract H5 域名(登录签署用) | https://app.example.com |
seal.platform.miniprogram-appid | 微信小程序 AppID | wx22db0d6ebe81e2ee |
seal.platform.miniprogram-name | 小程序在引导页显示的名称 | MiniContract.Pro |
seal.platform.miniprogram-logo | 小程序在引导页显示的图标 URL | https://oss.example.com/logo.png |
infra_config 表的 visible 字段(管理后台显示为「是否可见」)控制功能开关:| visible 值 | 效果 |
|---|---|
| 是 (true) | 该配置启用,正常读取值 |
| 否 (false) | 该配置禁用,等同于未配置 |
| 小程序 AppID | Mini-Contract H5 域名 | 行为 |
|---|---|---|
| 启用 | 禁用 | 只走小程序签署 |
| 禁用 | 启用 | 只走 H5 登录签署 |
| 启用 | 启用 | 小程序优先,H5 作为回退 |
| 禁用 | 禁用 | 无法签署(异常) |
管理后台「参数配置」
↓ 写入
infra_config 表(config_key + value + visible)
↓ 读取
ConfigApi.getVisibleConfigValueByKey()
↓ visible=false 返回 null
SealConfigService.getVisibleConfig()
↓ null 或空 → 返回 ""(功能禁用)
业务代码调用(如 getSealCoreH5Domain()、isMiniprogramEnabled())ConfigApi.java / ConfigApiImpl.java - 基础配置 API(含 visible 感知方法)SealConfigService.java - 平台路由配置读取服务SealConfigChecker.java - 启动时配置检查,打印当前启用状态| 前缀 | 用途 | 场景 |
|---|---|---|
/s/{ref} | H5 签署链接 | H5 模式优先时生成 |
/m/{ref} | 小程序签署链接 | 小程序模式优先时生成 |
/p/{ref} | 预览链接 | 签署完成后查看合同 |