Skip to content

Demo

esign-helper-demo 是一个“调用方示例工程”,它的意义不是承载核心逻辑,而是演示:

  • 一个普通业务系统如何引入 esign-helper-starter
  • 如何通过 Web 接口调用 starter
  • 如何复用 starter 默认表和默认归档能力
  • 如何在本地快速验证流程创建、查询和回调链路
  • 如何把真实生产里常见的盖章/签署动作组织成可落地的请求

1. 模块定位

这个模块主要服务三类人:

  • 第一次接入 starter 的开发者
  • 想快速跑通联调链路的同学
  • 想理解“业务系统应该怎么接 starter”的维护者

它不是:

  • 生产级业务系统模板
  • 核心能力承载模块
  • 未来要持续堆复杂业务逻辑的地方

2. 一个最重要的原则

demo 当前遵循一个非常明确的原则:

尽量薄,但示例要尽量贴近生产

也就是说:

  • 核心逻辑在 starter
  • demo 只保留示例调用层
  • 不在 demo 里再复制一套领域层、编排层、持久化逻辑
  • 场景差异主要通过 requestPayload 透传表达

这里的 requestPayload 很关键:

  • demo 的 /api/esign/flows/file/api/esign/flows/template 最终会把 requestPayload 里的扩展字段透传到 e签宝请求体
  • 因此它很适合承载生产里高频出现但暂时还没有完全建模的字段
  • 比如签署方、签署顺序、通知策略、经办人信息、盖章区、关键字定位结果、抄送人、业务附加字段等

这也是 demo 能覆盖“尽可能多生产常见盖章场景”的关键原因。

补充说明:

  • 下文示例里的 requestPayload 字段名,主要用于表达常见生产编排方式
  • 真正联调时,请按你们租户所使用的 e签宝官方接口字段要求校准

3. 模块结构

text
esign-helper-demo
├─ README.md
├─ pom.xml
└─ src

它本质上是一个普通 Spring Boot 应用,只不过依赖了:

  • esign-helper-starter
  • spring-boot-starter-web
  • spring-boot-starter-validation

4. 当前 demo 暴露的接口

4.1 发起文件流程

http
POST /api/esign/flows/file

适合:

  • 已经有 fileId 的合同发起签署
  • 采购合同、销售合同、补充协议、对账单、确认函等文件类签署
  • 企业公章、法人章、经办人签字等组合签署场景

4.2 发起模板流程

http
POST /api/esign/flows/template

适合:

  • 劳动合同
  • 入职文件包
  • 标准加盟协议
  • 经常复用固定模板的签署场景

4.3 查询流程

http
GET /api/esign/flows/{signFlowId}
GET /api/esign/flows?businessId=...&tenantCode=...&systemCode=...

适合:

  • 业务单据回查
  • 流程追踪
  • 多租户隔离查询

4.4 回调入口

http
POST /esign/callback/sign-notify

适合:

  • 签署完成更新流程状态
  • 节点签署更新任务状态
  • 用回调补档签署人信息

5. demo 当前重点覆盖的生产常见盖章场景

场景推荐入口典型业务
劳动合同/入职协议标准模板签署/api/esign/flows/templateHR、共享服务中心
采购合同/销售合同/框架协议文件签署/api/esign/flows/fileERP、CRM、SRM
平台统一代发起签署流程/api/esign/flows/file中台、多租户 SaaS
企业公章 + 经办人签字/api/esign/flows/fileB2B 合同、付款协议
法人章、财务章、合同专用章等多印章编排/api/esign/flows/file财务、法务、供应链
关键字盖章、指定页盖章、骑缝章starter 直调 contractFile()法务定稿、复杂版式合同
已发起流程补章/补签/追加签署区starter 直调 appendSignFields()补签、加签、漏章修正
解约、撤销、终止协议starter 直调 createRescissionUrl()人事离职、业务终止
已签完成后申请出证报告starter 直调 contractManagement()审计、法务、归档
企业印章、成员、模板的准备与查询starter 直调 seal() / member() / enterpriseConsole()平台初始化、组织治理

6. 场景举例 + 代码

6.1 入职劳动合同模板签署

这是最典型的模板流程场景:

  • 模板固定
  • 签署方固定
  • 只替换员工、公司、入职日期、薪资等业务参数

Demo 请求示例:

json
POST /api/esign/flows/template
Content-Type: application/json

{
  "tenantCode": "TENANT_HR",
  "systemCode": "HR",
  "businessId": "EMP-OFFER-20260420-001",
  "businessType": "EMPLOYMENT_CONTRACT",
  "contractName": "张三-劳动合同",
  "signTemplateId": "TPL_EMPLOYMENT_2026",
  "companyId": "COMPANY-001",
  "companyName": "示例科技有限公司",
  "initiator": "hr-admin",
  "requestPayload": {
    "autoStart": true,
    "signers": [
      {
        "signerType": "PERSON",
        "thirdPartyUserId": "EMP-10001",
        "psnAccount": "13800138000"
      },
      {
        "signerType": "ORGANIZATION",
        "orgId": "ORG-HQ-001",
        "sealId": "SEAL-COMPANY-001"
      }
    ],
    "notifyUrl": "https://hr.example.com/esign/callback/sign-notify"
  }
}

Starter 内直接调用示例:

java
Map<String, Object> payload = new LinkedHashMap<String, Object>();
payload.put("autoStart", true);
payload.put("signers", Arrays.asList(
        new LinkedHashMap<String, Object>() {{
            put("signerType", "PERSON");
            put("thirdPartyUserId", "EMP-10001");
            put("psnAccount", "13800138000");
        }},
        new LinkedHashMap<String, Object>() {{
            put("signerType", "ORGANIZATION");
            put("orgId", "ORG-HQ-001");
            put("sealId", "SEAL-COMPANY-001");
        }}
));

CreateEsignFlowCommand command = new CreateEsignFlowCommand()
        .setTenantCode("TENANT_HR")
        .setSystemCode("HR")
        .setBusinessId("EMP-OFFER-20260420-001")
        .setBusinessType("EMPLOYMENT_CONTRACT")
        .setContractName("张三-劳动合同")
        .setSignTemplateId("TPL_EMPLOYMENT_2026")
        .setCompanyId("COMPANY-001")
        .setCompanyName("示例科技有限公司")
        .setInitiator("hr-admin")
        .setRequestPayload(payload);

EsignFlowRecord record = integrationService.createTemplateFlow(command);

6.2 采购合同/销售合同文件发起签署

这是最典型的文件流程场景:

  • 合同 PDF 已由业务系统生成
  • 系统已经拿到了 fileId
  • 需要按业务单据号发起签署并做本地归档

Demo 请求示例:

json
POST /api/esign/flows/file
Content-Type: application/json

{
  "tenantCode": "TENANT_SRM",
  "systemCode": "SRM",
  "businessId": "PO-20260420-9527",
  "businessType": "PURCHASE_CONTRACT",
  "esignPactNo": "PACT-PO-9527",
  "contractName": "采购框架协议-供应商A",
  "contractCode": "PO-CONTRACT-9527",
  "initiator": "buyer-001",
  "companyId": "ORG-BUYER-001",
  "companyName": "采购中心",
  "fileId": "FILE-PO-9527",
  "requestPayload": {
    "autoStart": true,
    "deadline": "2026-04-30 23:59:59",
    "signers": [
      {
        "signerType": "ORGANIZATION",
        "orgId": "ORG-BUYER-001",
        "sealId": "SEAL-CONTRACT-001"
      },
      {
        "signerType": "ORGANIZATION",
        "orgId": "ORG-SUPPLIER-009",
        "sealId": "SEAL-SUPPLIER-009"
      }
    ]
  }
}

Starter 门面直接调用示例:

java
ContractFileModels.CreateByFileRequest request = new ContractFileModels.CreateByFileRequest()
        .setFlowName("采购框架协议-供应商A")
        .setDocs(Collections.singletonList(
                new ContractFileModels.DocumentInfo().setFileId("FILE-PO-9527")
        ))
        .putExtraField("autoStart", true)
        .putExtraField("deadline", "2026-04-30 23:59:59")
        .putExtraField("signers", Arrays.asList(
                new LinkedHashMap<String, Object>() {{
                    put("signerType", "ORGANIZATION");
                    put("orgId", "ORG-BUYER-001");
                    put("sealId", "SEAL-CONTRACT-001");
                }},
                new LinkedHashMap<String, Object>() {{
                    put("signerType", "ORGANIZATION");
                    put("orgId", "ORG-SUPPLIER-009");
                    put("sealId", "SEAL-SUPPLIER-009");
                }}
        ));

EsignResponse<ContractFileModels.SignFlowCreateData> response =
        esignApiFacade.contractFile().createByFile(request);

6.3 平台统一代发起,多租户隔离回查

这个场景在线上非常常见:

  • 一个共享平台给多个租户、多套业务系统代发起签署
  • 业务侧经常按 tenantCode + systemCode + businessId 回查

发起示例:

json
POST /api/esign/flows/file
Content-Type: application/json

{
  "tenantCode": "TENANT_B",
  "systemCode": "CRM",
  "businessId": "OPPORTUNITY-20260420-08",
  "businessType": "SALES_CONTRACT",
  "contractName": "华东区销售合同",
  "fileId": "FILE-SALES-008"
}

回查示例:

http
GET /api/esign/flows?businessId=OPPORTUNITY-20260420-08&tenantCode=TENANT_B&systemCode=CRM

这种写法可以直接复用 starter 默认归档表,不需要业务系统自己再维护一套签署流程索引。

6.4 企业公章 + 经办人签字

很多生产合同不是“单纯盖一个章”,而是:

  • 企业盖章
  • 再由经办人签字
  • 或者先经办人签字,再企业盖章

Demo 请求示例:

json
POST /api/esign/flows/file
Content-Type: application/json

{
  "tenantCode": "TENANT_FINANCE",
  "systemCode": "FIN",
  "businessId": "PAY-AGREEMENT-20260420-11",
  "businessType": "PAYMENT_AGREEMENT",
  "contractName": "付款协议-四月批次",
  "fileId": "FILE-PAY-011",
  "requestPayload": {
    "autoStart": true,
    "signOrder": true,
    "signers": [
      {
        "signerType": "ORGANIZATION",
        "orgId": "ORG-PAYER-001",
        "sealId": "SEAL-FINANCE-001",
        "transactor": {
          "psnId": "PSN-TRANS-001",
          "psnAccount": "13900000001"
        }
      },
      {
        "signerType": "PERSON",
        "psnId": "PSN-VENDOR-002",
        "psnAccount": "13900000002"
      }
    ]
  }
}

这个模式尤其适合:

  • B2B 合同
  • 对账确认单
  • 付款确认函
  • 供应商承诺书

6.5 关键字盖章、指定页盖章、骑缝章

这是法务场景里非常高频的一类动作,通常做法是:

  1. 先查关键字坐标
  2. 再按坐标追加签署区
  3. 必要时再配置骑缝章、多页章

Starter 直调示例:

java
ContractFileModels.KeywordPositionQueryRequest keywordRequest =
        new ContractFileModels.KeywordPositionQueryRequest()
                .putExtraField("keyword", "甲方盖章");

EsignResponse<ContractFileModels.KeywordPositionData> keywordResponse =
        esignApiFacade.contractFile().queryKeywordPositions("FILE-PO-9527", keywordRequest);

ContractFileModels.AppendSignFieldsRequest appendRequest =
        new ContractFileModels.AppendSignFieldsRequest()
                .putExtraField("signFields", Arrays.asList(
                        new LinkedHashMap<String, Object>() {{
                            put("sealId", "SEAL-CONTRACT-001");
                            put("pageNum", 3);
                            put("posX", 420);
                            put("posY", 580);
                        }}
                ))
                .putExtraField("acrossPageSeal", true);

esignApiFacade.contractFile().appendSignFields("FLOW-PO-9527", appendRequest);

适合:

  • 关键字“甲方盖章”“乙方签字”
  • 每页盖章
  • 首页盖章 + 尾页签字
  • 骑缝章

6.6 已发起流程补章、补签、加签

生产环境里经常出现:

  • 合同定稿后新增一个审批节点
  • 原来漏了一个盖章位置
  • 需要给经办人补签

Starter 直调示例:

java
ContractFileModels.AppendSignFieldsRequest request =
        new ContractFileModels.AppendSignFieldsRequest()
                .putExtraField("signFields", Arrays.asList(
                        new LinkedHashMap<String, Object>() {{
                            put("signerType", "PERSON");
                            put("psnId", "PSN-LEGAL-009");
                            put("pageNum", 5);
                            put("posX", 180);
                            put("posY", 680);
                        }}
                ));

esignApiFacade.contractFile().appendSignFields("FLOW-LEGAL-20260420-09", request);

这个场景是很多“上线后才发现还要多加一个章/签字”的救火动作。

6.7 解约、撤销、终止协议

生产里常见于:

  • 劳动合同解除
  • 渠道协议终止
  • 供应商合作解约

Starter 直调示例:

java
ContractFileModels.RescissionUrlRequest request =
        new ContractFileModels.RescissionUrlRequest()
                .putExtraField("initiatorType", "ORG")
                .putExtraField("operatorId", "hr-admin")
                .putExtraField("reason", "试用期不通过,发起解约");

EsignResponse<ContractFileModels.SignUrlData> response =
        esignApiFacade.contractFile().createRescissionUrl("FLOW-EMP-0008", request);

如果是“续签/补充协议”,通常还是重新走:

  • 模板流程:/api/esign/flows/template
  • 文件流程:/api/esign/flows/file

6.8 已签完成后申请出证报告

适合:

  • 法务归档
  • 争议留证
  • 审计留痕

Starter 直调示例:

java
EvidenceModels.ApplyReportRequest request =
        new EvidenceModels.ApplyReportRequest().setSignFlowId("FLOW-PO-9527");

EsignResponse<EvidenceModels.ApplyReportData> response =
        esignApiFacade.contractManagement().applyEvidenceReport(request);

6.9 回调更新流程、任务和本地档案

demo 已经把这条链路串起来了。

回调示例:

json
POST /esign/callback/sign-notify
Content-Type: application/json

{
  "action": "SIGN_FLOW_COMPLETE",
  "signFlowId": "FLOW002",
  "signOrderId": "TASK-001",
  "operatorId": "PSN-001",
  "operatorName": "张三",
  "operatorMobile": "13800138000",
  "signResult": "2"
}

回调后可直接查询:

http
GET /api/esign/flows/FLOW002

这条链路适合做:

  • 业务状态回写
  • 回调补档
  • 签署节点审计

6.10 企业印章、成员、模板准备

很多系统在正式“发合同”前,先要把企业侧基础资源准备好。

Starter 直调示例:

java
esignApiFacade.seal().createOrganizationTemplateSeal(
        new SealModels.CreateOrganizationTemplateSealRequest()
                .setOrgId("ORG-HQ-001")
                .setSealName("合同专用章")
);

esignApiFacade.seal().listOrganizationOwnSeals("ORG-HQ-001", 1, 20);
esignApiFacade.member().listMembers("ORG-HQ-001", 1, 20);
esignApiFacade.flowTemplate().listTemplates("ORG-HQ-001", 1, 20, null);
esignApiFacade.enterpriseConsole().workspace("ORG-HQ-001", 1, 20);

这类场景在线上常见于:

  • 新租户开通
  • 新公司主体接入
  • 印章治理
  • 模板和经办人初始化

7. 怎么运行

7.1 运行命令

bash
mvn -q -f esign-helper-starter/pom.xml install
mvn -q -f esign-helper-demo/pom.xml spring-boot:run

7.2 测试命令

bash
mvn -q -f esign-helper-starter/pom.xml install
mvn -q -f esign-helper-demo/pom.xml test

补充说明:

  • demostarter 在同一个仓库里维护,但不是 Maven 父子 module 关系
  • 运行、测试和打包都应直接基于 esign-helper-demo/pom.xml 执行
  • 如果本地还没有安装 starter,需要先把 esign-helper-starter 安装到本地 Maven 仓库

8. 你应该从 demo 学到什么

你真正要学的是:

  • 怎么引 starter
  • 怎么配置 starter
  • 怎么调 starter 暴露的服务
  • 怎么复用 starter 默认表
  • 怎么把常见盖章动作组织成 requestPayload

而不是把 demo 当成未来生产系统的模板直接复制。

适合:

  • 新同学 onboarding
  • 接入预演
  • Mock 联调
  • 回归验证
  • 梳理常见盖章动作的请求组织方式

不适合:

  • 继续往里堆复杂业务
  • 再造一套 starter 能力
  • 当正式平台服务发布

9. 和 starter 的关系

demostarter 的关系是:

  • starter 是产品核心
  • demo 是接入范例

所以遇到任何设计问题,优先原则永远是:

能力应该下沉到 starter,而不是堆在 demo


10. 推荐阅读顺序

建议按下面顺序看:

  1. 先看 esign-helper-starter/README.md
  2. 再看本 README 的“场景举例 + 代码”
  3. 再运行 demo
  4. 再看 Controller 和测试

关键代码:


11. 产品化视角下 demo 的价值

从产品化角度看,demo 不是“给仓库凑一个示例模块”,而是:

  • 降低新接入方的理解成本
  • 降低 starter 的学习门槛
  • 让团队内部能快速验证 starter 的升级是否破坏接入方式
  • 把生产环境里最常见的盖章动作沉淀成可讨论、可复用的示例

所以它更像 starter 的“开发者体验层”和“接入教学层”。


12. 结论

如果一句话概括:

esign-helper-demo 不是生产系统本身,而是一套尽量贴近生产常见盖章操作的接入样例,用来证明 starter 在真实业务系统里的使用姿势。

最近更新

EsignHelper Portal powered by VitePress Theme Teek