# e签宝电子签署集成实现文档 ## 一、概述 本文档详细说明如何在贷款管理系统中集成e签宝电子签署功能,实现合同的在线电子签署。系统采用前后端分离架构,后端使用Spring Boot,前端使用uniapp开发微信小程序。 ## 二、准备工作 ### 2.1 注册e签宝账号 1. 访问e签宝官网:https://www.esign.cn 2. 注册企业账号并完成实名认证 3. 创建应用,获取以下信息: - AppId(应用ID) - AppSecret(应用密钥) - ProjectId(项目ID) - API网关地址(生产环境:https://smlopenapi.esign.cn) ### 2.2 配置回调地址 在e签宝控制台配置回调地址: - 回调URL:`https://your-domain.com/api/wechat/esign/callback` - 回调方式:HTTP POST - 回调内容:JSON格式 ## 三、后端实现 ### 3.1 依赖配置 已在`pom.xml`中添加e签宝SDK依赖: ```xml com.esign esign-sdk-java 3.6.0 ``` ### 3.2 配置文件 在`application-dev.yaml`中配置e签宝参数: ```yaml system: esign: app-id: your-app-id app-secret: your-app-secret api-url: https://smlopenapi.esign.cn project-id: your-project-id enabled: true ``` ### 3.3 核心类说明 #### 3.3.1 实体类 **EsignFlow** (`src/main/java/com/loan/system/domain/entity/EsignFlow.java`) - 存储签署流程信息 - 包含流程ID、合同ID、签署状态等字段 #### 3.3.2 服务类 **EsignService** (`src/main/java/com/loan/system/service/EsignService.java`) - 提供签署流程的创建、启动、查询等核心功能 **EsignServiceImpl** (`src/main/java/com/loan/system/service/Impl/EsignServiceImpl.java`) - 实现e签宝API调用逻辑 - 处理签署流程状态同步 #### 3.3.3 控制器 **EsignController** (`src/main/java/com/loan/system/controller/wechat/EsignController.java`) - 提供RESTful API接口 - 供前端调用 ### 3.4 数据库表结构 系统会自动创建`esign_flow`表,主要字段: ```sql CREATE TABLE `esign_flow` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `flow_id` varchar(100) NOT NULL COMMENT 'e签宝流程ID', `contract_id` bigint(20) COMMENT '合同ID', `case_id` bigint(20) COMMENT '案件ID', `flow_status` int(11) COMMENT '流程状态:0-草稿 1-签署中 2-签署完成 3-签署失败 4-已撤销 5-已过期 6-已拒签', `flow_status_desc` varchar(50) COMMENT '流程状态描述', `document_id` varchar(100) COMMENT '签署文档ID', `document_url` varchar(500) COMMENT '签署文档下载地址', `document_name` varchar(200) COMMENT '签署文档名称', `customer_account_id` varchar(100) COMMENT '客户签署人账号ID', `business_account_id` varchar(100) COMMENT '业务方签署人账号ID', `customer_sign_status` int(11) COMMENT '客户签署状态:0-待签署 1-已签署 2-已拒签 3-已过期', `business_sign_status` int(11) COMMENT '业务方签署状态', `customer_sign_time` varchar(50) COMMENT '客户签署时间', `business_sign_time` varchar(50) COMMENT '业务方签署时间', `create_time` varchar(50) COMMENT '创建时间', `update_time` varchar(50) COMMENT '更新时间', `is_delete` tinyint(1) DEFAULT 0 COMMENT '是否删除', PRIMARY KEY (`id`), UNIQUE KEY `idx_flow_id` (`flow_id`), KEY `idx_contract_id` (`contract_id`), KEY `idx_case_id` (`case_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ``` ## 四、前端实现(uniapp) ### 4.1 签署流程页面 创建签署页面 `pages/contract/sign.vue`: ```vue ``` ### 4.2 WebView页面 创建WebView页面用于显示签署页面 `pages/webview/webview.vue`: ```vue ``` ### 4.3 创建签署流程 在合同详情页面,添加创建签署流程的功能: ```javascript // 创建签署流程 async createSignFlow() { try { uni.showLoading({ title: '创建中...' }); // 获取合同信息 const contractInfo = this.contractDetail; // 获取客户信息 const customerInfo = this.customerInfo; const params = { contractId: this.contractId, caseId: this.caseId, documentUrl: contractInfo.filePath, // 合同文件URL documentName: contractInfo.contractName, customerName: customerInfo.name, customerMobile: customerInfo.mobile, customerIdNumber: customerInfo.idNumber, businessName: '业务方名称', // 从配置或用户信息获取 businessMobile: '业务方手机号', signDeadline: Date.now() + 7 * 24 * 60 * 60 * 1000 // 7天后过期 }; const res = await this.$http.post('/wechat/esign/flow/create', params); uni.hideLoading(); if (res.code === 200) { uni.showToast({ title: '创建成功', icon: 'success' }); // 启动签署流程 await this.startSignFlow(res.data); // 跳转到签署页面 uni.navigateTo({ url: `/pages/contract/sign?contractId=${this.contractId}` }); } else { uni.showToast({ title: res.msg || '创建失败', icon: 'none' }); } } catch (error) { uni.hideLoading(); console.error('创建签署流程失败', error); uni.showToast({ title: '创建失败', icon: 'none' }); } }, // 启动签署流程 async startSignFlow(flowId) { try { const res = await this.$http.post(`/wechat/esign/flow/${flowId}/start`); if (res.code !== 200) { console.error('启动签署流程失败', res); } } catch (error) { console.error('启动签署流程失败', error); } } ``` ## 五、完整签署流程 ### 5.1 流程步骤 1. **创建签署流程** - 前端调用 `/wechat/esign/flow/create` 接口 - 后端创建e签宝签署流程,返回flowId - 保存流程信息到数据库 2. **启动签署流程** - 前端调用 `/wechat/esign/flow/{flowId}/start` 接口 - 后端调用e签宝API启动流程 3. **获取签署链接** - 前端调用 `/wechat/esign/flow/{flowId}/customer/sign-url` 接口 - 后端返回签署链接 4. **打开签署页面** - 前端在WebView中打开签署链接 - 用户在e签宝页面完成签署 5. **查询签署状态** - 前端轮询调用 `/wechat/esign/flow/{flowId}/status` 接口 - 后端同步e签宝流程状态 6. **签署完成** - e签宝回调 `/wechat/esign/callback` 接口 - 后端更新流程状态 - 前端显示签署完成 7. **下载已签署文档** - 前端调用 `/wechat/esign/flow/{flowId}/download` 接口 - 后端返回文档下载地址 ### 5.2 时序图 ``` 前端 后端 e签宝 | | | |--创建流程-------->| | | |--创建流程--------->| | |<--返回flowId------| |<--返回flowId------| | | | | |--启动流程-------->| | | |--启动流程--------->| | |<--启动成功--------| |<--启动成功--------| | | | | |--获取签署链接---->| | | |--获取签署链接---->| | |<--返回签署链接----| |<--返回签署链接----| | | | | |--打开WebView-----| | | | | | |<--用户签署--------| | | | | |--回调通知--------->| | | | |--查询状态-------->| | | |--查询状态--------->| | |<--返回状态--------| |<--返回状态--------| | | | | |--下载文档-------->| | | |--获取下载地址----->| | |<--返回下载地址----| |<--返回下载地址----| | ``` ## 六、API接口说明 ### 6.1 创建签署流程 **接口地址:** `POST /wechat/esign/flow/create` **请求参数:** ```json { "contractId": 123, "caseId": 456, "documentUrl": "https://example.com/contract.pdf", "documentName": "借款合同", "customerName": "张三", "customerMobile": "13800138000", "customerIdNumber": "110101199001011234", "businessName": "业务方", "businessMobile": "13900139000", "businessIdNumber": "110101199001011235", "signDeadline": 1640995200000, "remark": "备注信息" } ``` **返回结果:** ```json { "code": 200, "msg": "创建签署流程成功", "data": "flowId123456" } ``` ### 6.2 启动签署流程 **接口地址:** `POST /wechat/esign/flow/{flowId}/start` **返回结果:** ```json { "code": 200, "msg": "启动签署流程成功" } ``` ### 6.3 获取客户签署链接 **接口地址:** `GET /wechat/esign/flow/{flowId}/customer/sign-url` **请求参数:** - `mobile`: 手机号(必填) - `name`: 姓名(必填) - `accountId`: 账号ID(可选) **返回结果:** ```json { "code": 200, "msg": "获取成功", "data": "https://esign.cn/sign/xxx" } ``` ### 6.4 查询流程状态 **接口地址:** `GET /wechat/esign/flow/{flowId}/status` **返回结果:** ```json { "code": 200, "msg": "查询成功", "data": { "flowStatus": 2, "flowStatusDesc": "签署完成", "signers": [...] } } ``` ### 6.5 下载已签署文档 **接口地址:** `GET /wechat/esign/flow/{flowId}/download` **返回结果:** ```json { "code": 200, "msg": "获取下载地址成功", "data": "https://esign.cn/download/xxx" } ``` ### 6.6 撤销签署流程 **接口地址:** `POST /wechat/esign/flow/{flowId}/revoke` **请求参数:** - `revokeReason`: 撤销原因(必填) **返回结果:** ```json { "code": 200, "msg": "撤销成功" } ``` ### 6.7 e签宝回调接口 **接口地址:** `POST /wechat/esign/callback` **请求参数(e签宝回调):** ```json { "flowId": "flowId123456", "action": "SIGN_FLOW_FINISH", "flowStatus": 2, "signerAccountId": "accountId123", "timestamp": 1640995200000 } ``` ## 七、注意事项 ### 7.1 合同文件上传 在创建签署流程前,需要先将合同文件上传到e签宝: 1. 调用e签宝文件上传接口 2. 获取文件ID(fileId) 3. 使用fileId创建签署流程 ### 7.2 签署位置配置 签署位置(坐标)需要根据实际合同模板调整: - 在`EsignServiceImpl.createSignFields()`方法中配置 - 支持多页文档,需要指定页码 - 支持多个签署区域 ### 7.3 错误处理 1. **网络错误**:实现重试机制 2. **API错误**:记录错误日志,返回友好提示 3. **签署超时**:设置合理的签署截止时间 4. **回调失败**:实现回调重试机制 ### 7.4 安全性 1. **接口鉴权**:所有接口需要JWT认证 2. **参数校验**:验证手机号、身份证号格式 3. **回调验证**:验证e签宝回调签名 4. **数据加密**:敏感信息加密存储 ### 7.5 性能优化 1. **状态轮询**:使用合理的轮询间隔(建议3-5秒) 2. **缓存机制**:缓存访问令牌,避免频繁获取 3. **异步处理**:回调处理使用异步方式 4. **数据库索引**:为flowId、contractId等字段建立索引 ## 八、测试建议 ### 8.1 单元测试 - 测试服务类方法 - 测试API接口 - 测试异常情况 ### 8.2 集成测试 - 测试完整签署流程 - 测试回调处理 - 测试并发场景 ### 8.3 沙箱环境 - 使用e签宝沙箱环境进行测试 - 验证各种签署场景 - 测试异常情况处理 ## 九、常见问题 ### 9.1 签署链接无法打开 - 检查URL是否正确编码 - 检查小程序是否配置了业务域名 - 检查网络连接 ### 9.2 签署状态不同步 - 检查回调接口是否正常 - 检查轮询逻辑是否正确 - 检查数据库更新是否成功 ### 9.3 文档下载失败 - 检查文档是否已签署完成 - 检查下载地址是否有效 - 检查文件权限 ## 十、参考资料 - [e签宝开放平台文档](https://open.esign.cn/) - [e签宝Java SDK文档](https://open.esign.cn/doc/detail?id=opendoc%2Fjava_sdk%2Fjava_sdk) - [e签宝API参考](https://open.esign.cn/doc/detail?id=opendoc%2Fapi%2Fapi) --- **文档版本:** v1.0 **最后更新:** 2024-01-01 **维护人员:** 开发团队