gozero实现对接在线签名签署文件流程管理的设计与实践

在使用 **go-zero** 框架来实现对接 **签宝** 的签名与验签、待签署文件管理、电子印章、配置签署场景与签署方式、签署流程管理的相关接口时,可以按照 **go-zero** 的最佳实践进行代码设计与分层。**go-zero** 提供了强大的工具支持,能够让你高效地开发和管理服务。

下面是基于 **go-zero** 架构进行分层设计的建议,并包含如何实现相关接口。

### 1. **项目目录结构**

```
/esign
    /api                     # 表示层,处理 HTTP 请求与响应
    /logic                   # 业务逻辑层
    /model                   # 数据层,管理数据库模型和 API 请求响应模型
    /service                 # 服务层,启动服务与接口注册
    /config                  # 配置文件
    /client                  # 对接 e签宝 API 的客户端
    /utils                   # 工具类层,封装常用的功能
    main.go                  # 启动文件
```

### 2. **各层的功能职责**

- **表示层(API)**:负责接收前端的请求,调用业务逻辑层,处理请求和响应。
- **业务逻辑层(Logic)**:处理核心业务逻辑,如签名、验签、获取待签署文件等,封装业务流程。
- **数据层(Model)**:定义与数据库交互的模型,保存签署流程等信息。
- **服务层(Service)**:启动服务、注册路由等。
- **工具类层(Utils)**:封装一些常用功能,如 HTTP 请求、日志等。

### 3. **具体代码实现**

#### 3.1 **工具类层:`utils/http.go`**

工具类负责发送 HTTP 请求到 e签宝 API,处理请求响应。```go

package utils

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
)

// DoRequest 通用 HTTP 请求函数
func DoRequest(url, method string, headers map[string]string, body interface{}) ([]byte, error) {
    var reqBody []byte
    var err error

    // 如果请求体存在,则进行 JSON 序列化
    if body != nil {
        reqBody, err = json.Marshal(body)
        if err != nil {
            return nil, fmt.Errorf("failed to marshal body: %v", err)
        }
    }

    // 创建 HTTP 请求
    req, err := http.NewRequest(method, url, bytes.NewBuffer(reqBody))
    if err != nil {
        return nil, fmt.Errorf("failed to create request: %v", err)
    }

    // 设置请求头
    for key, value := range headers {
        req.Header.Set(key, value)
    }

    // 发送请求
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return nil, fmt.Errorf("failed to execute request: %v", err)
    }
    defer resp.Body.Close()

    // 读取响应体
    respBody, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, fmt.Errorf("failed to read response body: %v", err)
    }

    return respBody, nil
}


```

#### 3.2 **数据层(Model):`model/signature_model.go`**

定义与 e签宝相关的数据结构,便于与 API 交互。```go

package model

// 签署文件结构
type File struct {
    FileID   string `json:"file_id"`
    FileName string `json:"file_name"`
    FileURL  string `json:"file_url"`
}

// 签署流程结构
type SignProcess struct {
    ProcessID string `json:"process_id"`
    FileID    string `json:"file_id"`
    SignerID  string `json:"signer_id"`
    Status    string `json:"status"`
}

// API 响应结构
type APIResponse struct {
    Code    int    `json:"code"`
    Message string `json:"message"`
    Data    interface{} `json:"data"`
}


```

#### 3.3 **业务逻辑层(Logic):`logic/signature_logic.go`**

业务逻辑层负责封装业务流程,调用 e签宝 API 完成签署和验签等操作。```go

package logic

import (
    "encoding/json"
    "fmt"
    "github.com/your_project/utils"
    "github.com/your_project/model"
    "github.com/your_project/client"
    "github.com/zeromicro/go-zero/core/logx"
)

type SignatureLogic struct {
    client *client.ESignClient
}

func NewSignatureLogic(client *client.ESignClient) *SignatureLogic {
    return &SignatureLogic{client: client}
}

// 创建签署流程
func (logic *SignatureLogic) CreateSignProcess(fileID, signerID string) (*model.SignProcess, error) {
    url := fmt.Sprintf("%s/v1/sign/processes", logic.client.BaseURL)
    headers := map[string]string{
        "Authorization": logic.client.APIKey,
    }
    body := map[string]interface{}{
        "file_id":   fileID,
        "signer_id": signerID,
    }

    respData, err := utils.DoRequest(url, "POST", headers, body)
    if err != nil {
        logx.Errorf("Error creating sign process: %v", err)
        return nil, err
    }

    var response model.APIResponse
    if err := json.Unmarshal(respData, &response); err != nil {
        logx.Errorf("Failed to parse response: %v", err)
        return nil, err
    }

    if response.Code != 0 {
        return nil, fmt.Errorf("error response from eSign API: %s", response.Message)
    }

    // 返回签署流程信息
    signProcess := &model.SignProcess{
        ProcessID: response.Data["process_id"].(string),
        FileID:    fileID,
        SignerID:  signerID,
        Status:    "created",
    }
    return signProcess, nil
}


```

#### 3.4 **客户端层(Client):`client/esign_client.go`**

封装与 e签宝的 API 通信,确保与外部服务的交互简单、清晰。```go

package client

import (
    "fmt"
    "github.com/your_project/utils"
)

// ESignClient 用于与 e签宝 API 的交互
type ESignClient struct {
    BaseURL string
    APIKey  string
}

// NewESignClient 创建一个新的 eSign 客户端实例
func NewESignClient(baseURL, apiKey string) *ESignClient {
    return &ESignClient{
        BaseURL: baseURL,
        APIKey:  apiKey,
    }
}

// 上传文件
func (client *ESignClient) UploadFile(filePath string) (string, error) {
    url := fmt.Sprintf("%s/v1/files", client.BaseURL)
    headers := map[string]string{
        "Authorization": client.APIKey,
    }

    // 假设有一个工具函数处理文件上传(可以自行实现文件上传函数)
    fileData, err := utils.UploadFile(filePath)
    if err != nil {
        return "", err
    }

    respData, err := utils.DoRequest(url, "POST", headers, fileData)
    if err != nil {
        return "", err
    }

    // 假设 API 返回的文件 ID 在 response 中
    var result map[string]interface{}
    if err := json.Unmarshal(respData, &result); err != nil {
        return "", err
    }

    return result["file_id"].(string), nil
}


```

#### 3.5 **表示层(API):`api/signature_api.go`**

处理 HTTP 请求并调用相应的业务逻辑,返回结果给客户端。```go

package api

import (
    "github.com/your_project/logic"
    "github.com/your_project/model"
    "github.com/zeromicro/go-zero/rest/httpx"
    "net/http"
)

type SignatureAPI struct {
    SignatureLogic *logic.SignatureLogic
}

func NewSignatureAPI(signatureLogic *logic.SignatureLogic) *SignatureAPI {
    return &SignatureAPI{
        SignatureLogic: signatureLogic,
    }
}

func (api *SignatureAPI) CreateSignProcessHandler(w http.ResponseWriter, r *http.Request) {
    var fileID, signerID string
    // 解析请求 URL 参数等

    signProcess, err := api.SignatureLogic.CreateSignProcess(fileID, signerID)
    if err != nil {
        httpx.Error(w, err)
        return
    }

    httpx.OkJson(w, model.APIResponse{
        Code:    0,
        Message: "Success",
        Data:    signProcess,
    })
}


```

#### 3.6 **启动服务:`main.go`**

在启动文件中,初始化各个模块,启动 HTTP 服务。```go

package main

import (
    "github.com/your_project/client"
    "github.com/your_project/logic"
    "github.com/your_project/api"
    "github.com/zeromicro/go-zero/rest"
    "github.com/zeromicro/go-zero/zrpc"
)

func main() {
    // 创建 eSign 客户端
    client := client.NewESignClient("https://api.esign.com", "your_api_key")

    // 创建逻辑层
    signatureLogic := logic.NewSignatureLogic(client)

    // 创建 API 层
    signatureAPI := api.NewSignatureAPI(signatureLogic)

    // 创建并启动 HTTP 服务
    server := rest.MustNewServer(rest.RestConf{
        Host: "localhost",
        Port: 8080,
    })
    server.AddRoute(httpx.MethodPost, "/sign/{file_id}/{signer_id}", signatureAPI.CreateSignProcessHandler)

    // 启动服务
    defer server.Stop()
    server.Start()
}


```

### 4. **总结**

- 通过 **go-zero** 的分层架构,可以使得代码的模块化程度更高,职责分明。
- **工具类层**(如 HTTP 请求封装)可以复用,避免了重复的代码。
- **业务逻辑层**封装了具体的操作,如签署流程的创建、文件上传等。
- **API 层**负责与外部交互,提供用户接口,保证业务逻辑的清晰性。
- 最终通过 **服务层** 启动 Web 服务,使得整个流程更加清晰和可维护。

这种架构和设计能够有效地支持可扩展性,方便后期的维护和功能扩展。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

360-go-php

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值