Skip to content

增量/全量拉取待办数据 ​

为了解决业务方推送待办到待办中心异常情况,待办中心提供补偿轮询机制,需要业务方按照一下规则实现接口。

业务系统需要按照以下接口标准提供增量/全量同步待办数据接口 ​

接口定义 ​

接口名称url请求方式请求数据类型
获取增量/全量待办列表业务系统定义GETmultipart/form-data

请求参数 ​

参数名称参数说明是否必填数据类型备注说明
appId应用id是string分配的应用ID
startTime开始时间戳是long起始时间 这个时间的查询逻辑是数据最后更新时间 时间跨度 不大于30天
endTime结束时间戳是long结束时间 这个时间的查询逻辑是数据最后更新时间 时间跨度 不大于30天
receptionId接收人ID否String接收用户工号
deal处理状态否Integer0 待处理 1.已处理
page当前页是long当前页
size每页条数是long每页条数 (不大于500条)
sign加签校验是string业务系统根据加签规则生成值进行校验,具体生成方法如下示例
signTime加签生成时间戳是string加签生成时间戳

返回值 ​

参数名称参数说明数据类型备注说明
appId应用idstring分配的应用ID
type待办类型Integer0 审批类;1: 通知类;
deal处理状态Integer0表示未办,1表示已办
status待办状态Integer10.待审批,11.待阅,20.通过,21.已阅,30.拒绝,31.驳回,32.撤销
sourceId业务记录IDString在同一批次下的唯一标识-
batchId批次IDString批次ID-标识是同一条审批流程的编号-在同一审批中这个应该唯一,(如果新增待办的时候没有传这个参数 补偿的时候也不需要返回)
content消息内容string消息内容
title标题string标题
receptionId接收人idstring接收人id 内部员工工号,三方人员为人员组织中心中顾问工号
senderId发送人idstring内部员工工号,三方人员为人员组织中心中顾问工号 如果没有发起人 传0为系统发起
startTime流程开始时间string流程开始时间 ‘2025-04-01 10:00:00’
moduleSource模块来源string模块来源
urlpc跳转地址string用户在待办中心点击待办时跳转地址,跳转时会根据应用注册协议拼接凭证到URL后面,业务系统可根据统一认证相关接口获取用户信息
urlAppapp跳转地址string用户在待办中心点击待办时跳转地址
processStatus待办中心是否可处理Integer0-不可以处理(默认),1-可以处理 (如果设置为1 那么待办中心可以处理待办并修改待办状态,为0则不允许待办中心处理待办。设置为1需要提供回调接口 对接待办中心处理后回调同步待办状态)
sysTag系统标识string系统标识 标识子系统
json
{
  "code":200,
  "count":总数,
  "data":[{
    "appId":"注册应用返回的client_id",
    "type": "1",
	"deal": "0",
	"status":"11",
	"sourceId":"应用待办的唯一编号",
	"batchId":"标识是同一条审批流程的编号,同一流程实例不同节点批次ID相同",
	"content":"消息内容",			
	"title":"标题",	
	"receptionId":"接收人id",	
	"senderId":"发送人id",	
	"startTime":"流程开始时间",
	"asterisk":"星标",
	"moduleSource":"模块来源",
	"url":"pc跳转地址",
	"urlApp":"app跳转地址",
	"passUrl":"待办中心处理待办数据回调接口"
  }]
}

请求示例 ​

json
curl --request GET \
  --url 'http://127.0.0.1:8009/api/todo-manage/app/info/open/pullTodoData?appId=1109453752143708160&startTime=1760947769862&endTime=1761034170323&page=1&size=50&signTime=1761035753955&sign=%20vxO%2FrnUF9ltPpDt3YDIegn0aEs%3D' \
  --header 'Accept: */*' \
  --header 'Accept-Encoding: gzip, deflate, br' \
  --header 'Connection: keep-alive' \
  --header 'User-Agent: PostmanRuntime-ApipostRuntime/1.1.0'

加签验证代码 ​

java
   public static void main(String[] args) throws Exception {
   		this.validateTimeStamp(sginTime);
         Map<String, String> parameter = new HashMap<>();
            parameter.put("clientId", appId);
            parameter.put("timestamp", sginTime);// 根据传来的参sginTime 
            String sign = this.generateSign(parameter, GET, secret);
    }
 public static final String ALGORITHM = "HmacSHA1";


 public static String validateTimeStamp(String timestamp) {
        if (!org.springframework.util.StringUtils.hasText(timestamp)) {
            return "timestamp不能为空"; //"timestamp不能为空"
        }
        if (!isNumeric(timestamp)) {
            return "timestamp必须是数字";//"timestamp必须是数字"
        }
        // 时间戳验证 当前时间 - 请求时间戳
        if (Math.abs(System.currentTimeMillis() - Long.parseLong(timestamp)) > DEFAULT_TIME_STAMP_180_000) {
            return "时间戳3分钟内有效";
        }
        return "success";
    }

    /**
     * 构建签名数据
     *
     * @return 签名数据
     */
    public static String buildSigningString(Map<String, String> parameters, String httpMethod) {
        // 排序请求参数
        String[] sortedKeys = parameters.keySet().toArray(new String[]{});
        Arrays.sort(sortedKeys);
        StringBuilder stringToSign = new StringBuilder();
        if(StringUtils.isNotBlank(httpMethod)) {
            stringToSign.append(httpMethod).append(CommonConstants.Symbol.SEPARATOR);
        }
        StringBuilder canonicalizedQueryString = new StringBuilder();
        for (String key : sortedKeys) {
            if (StringUtils.isBlank(parameters.get(key))) {
                continue;
            }
            canonicalizedQueryString.append(CommonConstants.Symbol.SEPARATOR)
                    .append(percentEncode(key)).append("=")
                    .append(percentEncode(parameters.get(key)));
        }
        stringToSign.append(percentEncode(canonicalizedQueryString.substring(1)));
        return stringToSign.toString();
    }

    public static String percentEncode(String value) {
        return value != null ? URLEncoder.encode(value, StandardCharsets.UTF_8).replace("+", "%20").replace("*", "%2A").replace("%7E", "~") : null;
    }

    /**
     * 生成 HMAC-SHA1 签名
     */
    public static String generateSign(Map<String, String> parameters, String httpMethod, String secret) throws Exception {
        String data = buildSigningString(parameters, httpMethod);
        return generateSign(data, secret);
    }

    /**
     * 生成 HMAC-SHA1 签名
     */
    public static String generateSign(String data, String secret) throws Exception {
        Mac mac = Mac.getInstance(ALGORITHM);
        mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), ALGORITHM));
        byte[] hash = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(hash);
    }