328 lines
8.5 KiB
Markdown
328 lines
8.5 KiB
Markdown
|
|
# e签宝集成使用指南
|
|||
|
|
|
|||
|
|
## 概述
|
|||
|
|
|
|||
|
|
本项目已集成e签宝电子签名服务,用于企业认证流程中的合同签署。e签宝服务提供了完整的电子签名功能,包括合同生成、签署流程管理、文件下载等。
|
|||
|
|
|
|||
|
|
## 架构设计
|
|||
|
|
|
|||
|
|
### 服务结构
|
|||
|
|
- **EQService**: 统一的e签宝服务,提供底层API封装和业务集成方法
|
|||
|
|
- **配置管理**: 在主配置文件中统一管理e签宝配置
|
|||
|
|
- **应用服务**: 直接调用EQService的业务方法
|
|||
|
|
|
|||
|
|
### 核心功能
|
|||
|
|
1. **合同生成**: 使用模板生成合同文件
|
|||
|
|
2. **签署流程**: 创建和管理签署流程
|
|||
|
|
3. **签署链接**: 获取签署页面链接
|
|||
|
|
4. **状态查询**: 查询签署流程状态
|
|||
|
|
5. **文件下载**: 下载已签署的文件
|
|||
|
|
|
|||
|
|
## 配置说明
|
|||
|
|
|
|||
|
|
### 主配置文件 (config.go)
|
|||
|
|
```go
|
|||
|
|
type Config struct {
|
|||
|
|
// ... 其他配置 ...
|
|||
|
|
|
|||
|
|
// e签宝配置
|
|||
|
|
Esign EsignConfig `yaml:"esign"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
type EsignConfig struct {
|
|||
|
|
AppID string `yaml:"app_id"` // e签宝应用ID
|
|||
|
|
AppSecret string `yaml:"app_secret"` // e签宝应用密钥
|
|||
|
|
ServerURL string `yaml:"server_url"` // e签宝服务器地址
|
|||
|
|
TemplateID string `yaml:"template_id"` // 合同模板ID
|
|||
|
|
EnableDebug bool `yaml:"enable_debug"` // 是否启用调试模式
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 环境配置文件
|
|||
|
|
```yaml
|
|||
|
|
# configs/env.development.yaml
|
|||
|
|
esign:
|
|||
|
|
app_id: "your_app_id"
|
|||
|
|
app_secret: "your_app_secret"
|
|||
|
|
server_url: "https://esign-api.antfin.com"
|
|||
|
|
template_id: "your_template_id"
|
|||
|
|
enable_debug: true
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 使用方法
|
|||
|
|
|
|||
|
|
### 1. 在应用服务中使用
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 注入e签宝服务
|
|||
|
|
type CertificationApplicationServiceImpl struct {
|
|||
|
|
// ... 其他依赖 ...
|
|||
|
|
esignService *esign_service.EQService
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 生成合同
|
|||
|
|
func (s *CertificationApplicationServiceImpl) ApplyContract(ctx context.Context, userID string) (*responses.CertificationResponse, error) {
|
|||
|
|
// 1. 获取企业信息
|
|||
|
|
enterpriseInfo, err := s.enterpriseService.GetEnterpriseInfo(ctx, userID)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2. 准备合同签署请求
|
|||
|
|
contractReq := &esign_service.ContractSignRequest{
|
|||
|
|
CertificationID: certification.ID,
|
|||
|
|
UserID: userID,
|
|||
|
|
CompanyName: enterpriseInfo.CompanyName,
|
|||
|
|
UnifiedSocialCode: enterpriseInfo.UnifiedSocialCode,
|
|||
|
|
LegalPersonName: enterpriseInfo.LegalPersonName,
|
|||
|
|
LegalPersonIDCard: enterpriseInfo.LegalPersonID,
|
|||
|
|
LegalPersonPhone: user.Phone,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 3. 生成合同
|
|||
|
|
contractResp, err := s.esignService.GenerateContract(contractReq)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, fmt.Errorf("生成合同失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 4. 创建合同记录
|
|||
|
|
contractRecord := entities.NewEsignContractGenerateRecord(
|
|||
|
|
certification.ID,
|
|||
|
|
userID,
|
|||
|
|
"企业认证服务协议",
|
|||
|
|
"certification_agreement",
|
|||
|
|
)
|
|||
|
|
contractRecord.MarkAsSuccess(
|
|||
|
|
contractResp.SignFlowID,
|
|||
|
|
contractResp.FileID,
|
|||
|
|
contractResp.SignURL,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// 5. 保存记录到数据库
|
|||
|
|
// ... 保存逻辑 ...
|
|||
|
|
|
|||
|
|
return response, nil
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 获取签署链接
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 获取签署链接
|
|||
|
|
func (s *CertificationApplicationServiceImpl) GetContractSignURL(ctx context.Context, cmd *commands.GetContractSignURLCommand) (*responses.ContractSignURLResponse, error) {
|
|||
|
|
// 1. 从数据库获取签署流程ID
|
|||
|
|
signFlowID := "从数据库获取的流程ID"
|
|||
|
|
|
|||
|
|
// 2. 获取签署链接
|
|||
|
|
signURL, shortURL, err := s.esignService.GetContractSignURL(signFlowID, user.Phone, enterpriseInfo.LegalPersonName)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, fmt.Errorf("获取签署链接失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
response := &responses.ContractSignURLResponse{
|
|||
|
|
SignURL: signURL,
|
|||
|
|
ShortURL: shortURL,
|
|||
|
|
SignFlowID: signFlowID,
|
|||
|
|
ContractName: "企业认证服务协议",
|
|||
|
|
ExpireAt: time.Now().AddDate(0, 0, 7).Format(time.RFC3339),
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return response, nil
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 检查签署状态
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
// 检查签署是否完成
|
|||
|
|
func (s *CertificationApplicationServiceImpl) CheckSignStatus(ctx context.Context, signFlowID string) (bool, error) {
|
|||
|
|
completed, err := s.esignService.IsSignFlowCompleted(signFlowID)
|
|||
|
|
if err != nil {
|
|||
|
|
return false, fmt.Errorf("检查签署状态失败: %w", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return completed, nil
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## API接口
|
|||
|
|
|
|||
|
|
### 1. 申请合同
|
|||
|
|
```http
|
|||
|
|
POST /api/certification/apply-contract
|
|||
|
|
Authorization: Bearer {token}
|
|||
|
|
|
|||
|
|
Response:
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"message": "合同申请成功",
|
|||
|
|
"data": {
|
|||
|
|
"id": "certification_id",
|
|||
|
|
"user_id": "user_id",
|
|||
|
|
"status": "contract_applied",
|
|||
|
|
"status_name": "已申请合同",
|
|||
|
|
"progress": 60,
|
|||
|
|
"contract_applied_at": "2024-01-01T12:00:00Z"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 获取签署链接
|
|||
|
|
```http
|
|||
|
|
GET /api/certification/contract-sign-url
|
|||
|
|
Authorization: Bearer {token}
|
|||
|
|
|
|||
|
|
Response:
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"message": "获取签署链接成功",
|
|||
|
|
"data": {
|
|||
|
|
"sign_url": "https://esign.antfin.com/sign/...",
|
|||
|
|
"short_url": "https://short.url/...",
|
|||
|
|
"sign_flow_id": "flow_id",
|
|||
|
|
"contract_name": "企业认证服务协议",
|
|||
|
|
"expire_at": "2024-01-08T12:00:00Z"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 完成合同签署
|
|||
|
|
```http
|
|||
|
|
POST /api/certification/complete-contract-sign
|
|||
|
|
Authorization: Bearer {token}
|
|||
|
|
Content-Type: application/json
|
|||
|
|
|
|||
|
|
{
|
|||
|
|
"contract_url": "https://esign.antfin.com/sign/..."
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Response:
|
|||
|
|
{
|
|||
|
|
"code": 200,
|
|||
|
|
"message": "合同签署完成",
|
|||
|
|
"data": null
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 数据库表结构
|
|||
|
|
|
|||
|
|
### esign_contract_generate_records (合同生成记录表)
|
|||
|
|
```sql
|
|||
|
|
CREATE TABLE esign_contract_generate_records (
|
|||
|
|
id VARCHAR(36) PRIMARY KEY,
|
|||
|
|
certification_id VARCHAR(36) NOT NULL,
|
|||
|
|
user_id VARCHAR(36) NOT NULL,
|
|||
|
|
esign_flow_id VARCHAR(100),
|
|||
|
|
contract_file_id VARCHAR(100),
|
|||
|
|
contract_url VARCHAR(500),
|
|||
|
|
contract_name VARCHAR(200) NOT NULL,
|
|||
|
|
contract_type VARCHAR(50) NOT NULL,
|
|||
|
|
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
|||
|
|
request_at TIMESTAMP NOT NULL,
|
|||
|
|
generated_at TIMESTAMP NULL,
|
|||
|
|
failed_at TIMESTAMP NULL,
|
|||
|
|
failure_reason TEXT,
|
|||
|
|
retry_count INT DEFAULT 0,
|
|||
|
|
max_retries INT DEFAULT 3,
|
|||
|
|
created_at TIMESTAMP NOT NULL,
|
|||
|
|
updated_at TIMESTAMP NOT NULL,
|
|||
|
|
deleted_at TIMESTAMP NULL,
|
|||
|
|
INDEX idx_certification_id (certification_id),
|
|||
|
|
INDEX idx_user_id (user_id),
|
|||
|
|
INDEX idx_esign_flow_id (esign_flow_id),
|
|||
|
|
INDEX idx_contract_file_id (contract_file_id)
|
|||
|
|
);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### esign_contract_sign_records (合同签署记录表)
|
|||
|
|
```sql
|
|||
|
|
CREATE TABLE esign_contract_sign_records (
|
|||
|
|
id VARCHAR(36) PRIMARY KEY,
|
|||
|
|
certification_id VARCHAR(36) NOT NULL,
|
|||
|
|
user_id VARCHAR(36) NOT NULL,
|
|||
|
|
esign_flow_id VARCHAR(100) NOT NULL,
|
|||
|
|
sign_url VARCHAR(500),
|
|||
|
|
short_url VARCHAR(500),
|
|||
|
|
sign_status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
|||
|
|
signed_at TIMESTAMP NULL,
|
|||
|
|
expire_at TIMESTAMP NULL,
|
|||
|
|
created_at TIMESTAMP NOT NULL,
|
|||
|
|
updated_at TIMESTAMP NOT NULL,
|
|||
|
|
deleted_at TIMESTAMP NULL,
|
|||
|
|
INDEX idx_certification_id (certification_id),
|
|||
|
|
INDEX idx_user_id (user_id),
|
|||
|
|
INDEX idx_esign_flow_id (esign_flow_id)
|
|||
|
|
);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 错误处理
|
|||
|
|
|
|||
|
|
### 常见错误
|
|||
|
|
1. **配置错误**: 检查e签宝配置是否正确
|
|||
|
|
2. **网络错误**: 检查网络连接和e签宝服务状态
|
|||
|
|
3. **参数错误**: 检查请求参数是否完整
|
|||
|
|
4. **权限错误**: 检查e签宝应用权限
|
|||
|
|
|
|||
|
|
### 错误响应格式
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"code": 500,
|
|||
|
|
"message": "生成合同失败: 网络连接超时",
|
|||
|
|
"data": null
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 最佳实践
|
|||
|
|
|
|||
|
|
### 1. 配置管理
|
|||
|
|
- 使用环境变量管理敏感配置
|
|||
|
|
- 不同环境使用不同的配置
|
|||
|
|
- 定期更新e签宝应用密钥
|
|||
|
|
|
|||
|
|
### 2. 错误处理
|
|||
|
|
- 实现重试机制
|
|||
|
|
- 记录详细的错误日志
|
|||
|
|
- 提供友好的错误提示
|
|||
|
|
|
|||
|
|
### 3. 性能优化
|
|||
|
|
- 使用缓存减少API调用
|
|||
|
|
- 异步处理长时间操作
|
|||
|
|
- 合理设置超时时间
|
|||
|
|
|
|||
|
|
### 4. 安全考虑
|
|||
|
|
- 验证用户权限
|
|||
|
|
- 加密敏感数据
|
|||
|
|
- 记录操作日志
|
|||
|
|
|
|||
|
|
## 开发调试
|
|||
|
|
|
|||
|
|
### 启用调试模式
|
|||
|
|
```yaml
|
|||
|
|
esign:
|
|||
|
|
enable_debug: true
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 查看日志
|
|||
|
|
```bash
|
|||
|
|
# 查看应用日志
|
|||
|
|
tail -f logs/app.log | grep esign
|
|||
|
|
|
|||
|
|
# 查看e签宝API调用日志
|
|||
|
|
tail -f logs/app.log | grep "e签宝"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 测试流程
|
|||
|
|
1. 配置测试环境
|
|||
|
|
2. 创建测试用户
|
|||
|
|
3. 提交企业信息
|
|||
|
|
4. 申请合同
|
|||
|
|
5. 获取签署链接
|
|||
|
|
6. 完成签署流程
|
|||
|
|
|
|||
|
|
## 注意事项
|
|||
|
|
|
|||
|
|
1. **模板配置**: 确保e签宝模板配置正确
|
|||
|
|
2. **字段映射**: 注意模板字段与业务数据的映射关系
|
|||
|
|
3. **状态同步**: 及时同步e签宝状态到本地数据库
|
|||
|
|
4. **数据备份**: 定期备份合同相关数据
|
|||
|
|
5. **合规要求**: 确保符合电子签名相关法规要求
|