# 流程推送开发指南
# 功能介绍
七巧低码开发平台面向第三方统一待办类产品,提供了流程引擎数据的主动推送机制,满足待办、已办、已阅等数据实时集成场景。
# 使用教程
# 流程推送配置
- 配置新增待办URL:用于新增待办、待阅;
- 配置修改待办URL:用于待办转已办,待阅转已阅,更新单据内容(例如:标题、当前节点、流程状态);
- 配置删除待办URL:用于删除待办、删除已办、删除待阅、删除已阅;
- Token:为以上3个接口的请求数据的AES的密钥;
- 流程数据推送范围:勾选流程后,对应流程的变更后将会主动推送到第三方服务;
# 流程推送接口说明
# 查询租户内流程推送数据接口说明
- 开发平台公共API管理处勾选查询租户内流程推送数据权限后,才能通过OpenApi的方式调用查询查询租户内流程推送数据接口。
- 获取OpenAPI接口的token,参考文档:「集成中心」->「OpenAPI使用指南」->「通过AccessKey获取Token」
- 调用OpenAPI调用查询租户内流程推送数据接口
功能描述
查询租户内流程推送数据
请求说明
请求方式:Get 请求URL :http://qiqiao.hbrhdl.com/plus/cgi-bin/open/third/process/todo/record (opens new window)
请求参数
参数 | 数据类型 | 必须 | 说明 |
---|---|---|---|
page | int | 是 | 页码 |
pageSize | int | 是 | 页数大小(默认10) |
workId | String | 否 | 工单id |
startTime | long | 否 | 开始时间(yyyy-MM-dd HH:mm:ss) |
endTime | long | 否 | 结束时间(yyyy-MM-dd HH:mm:ss) |
返回结果
参数 | 数据类型 | 必须 | 说明 |
---|---|---|---|
code | int | 是 | 0为成功,其他失败 |
msg | string | 是 | |
data | Object | 是 |
返回结果Data说明
参数 | 数据类型 | 必须 | 说明 |
---|---|---|---|
currPage | int | 是 | 当前页 |
pageSize | int | 是 | 每页条数 |
totalCount | int | 是 | 总数 |
totalPage | int | 是 | 总页数 |
list | Array | 是 | 数据集合 |
返回结果list说明
参数 | 数据类型 | 必须 | 说明 |
---|---|---|---|
tenantId | string | 是 | 租户id |
applicationId | string | 是 | 应用id |
processModelId | string | 是 | 流程模型id |
processDefinitionId | string | 是 | 流程定义id |
processInstanceId | string | 是 | 流程实例id |
taskId | string | 是 | 节点任务id |
userId | string | 是 | 用户id |
workId | string | 是 | 单据id |
processName | string | 是 | 流程名称 |
workTitle | string | 是 | 流程标题 |
workUrl | string | 是 | 流程跳转url |
workType | int | 是 | 单据类型:0待办、1待阅、2已办、3已阅 |
workStatus | string | 是 | 流程状态(中文) |
workCreator | string | 是 | 发起人id |
workName | string | 是 | 发起人名称 |
currentNodeId | string | 是 | 当前节点定义Id |
currentNodeName | string | 是 | 当前节点名称 |
workCreateTime | string | 是 | 工单创建时间 |
workDealTime | string | 是 | 工单处理时间 |
createTime | string | 是 | 创建时间 |
updateTime | string | 是 | 更新时间 |
{
"msg": "执行成功",
"traceId": "10ce053eb4910e9f92c4d2495da84cd8",
"code": 0,
"data": {
"currPage": 1,
"pageSize": 10,
"totalCount": 2,
"totalPage": 1,
"list": [
{
"applicationId": "60b9fdeec4a88332821818e6",
"createTime": 1659077738180,
"currentNodeId": "obj_03",
"currentNodeName": "人工任务1",
"processDefinitionId": "6691261217077854209",
"processInstanceId": "6714034989108953088",
"processModelId": "6691261217077854208",
"processName": "统一待办推送测试",
"taskId": "6714034989108953094",
"tenantId": "2efc32ee89074e919afa2219e3cace53",
"updateTime": 1658977911786,
"userId": "3534b08f0ca503a2dca7bf0ff691dff4",
"workCreateTime": 1659077737201,
"workCreator": "b2c26e0438a654765d932c510d071eb8",
"workDealTime": 1658977909708,
"workId": "6714035057828397056",
"workName": "刘言",
"workStatus": "已完成",
"workTitle": "刘言的统一待办推送测试_2022072914",
"workType": "2",
"workUrl": "http://xxxx/mruntime/?agentCode=qiqiao2dev&corp_id=ww4852f35d45307a6f#/admin/workflow/detail/6714034989108953088?applicationId=60b9fdeec4a88332821818e6&activityDefinitionId=obj_03&scope=TODO&taskId=6714034989108953094&sourceType=YBG_TODO"
},
{
"applicationId": "60b882a10cf2ab377c02a757",
"createTime": 1658989010000,
"currentNodeId": "obj_03",
"currentNodeName": "人工任务",
"processDefinitionId": "6257ebddcf588d42b3c7ed95",
"processInstanceId": "0aeb1e6cf272463dbc1e65e6b76c8db6",
"processModelId": "6257eba2cf588d42b3c7ed94",
"processName": "流程名称很长流程名称很长流程名称很长流程",
"taskId": "f68e9fadb0e24d99a8e7a4981c28efbf",
"tenantId": "2efc32ee89074e919afa2219e3cace53",
"updateTime": 1658989010000,
"userId": "56e9f9b4851dd08259fb16a271864663",
"workCreateTime": 1654753971413,
"workCreator": "baff3ca77b70b703ec28a01afee81ba6",
"workDealTime": null,
"workId": "001bd5bde0a647e1a75f8af8391be7b5",
"workName": "殷素云",
"workStatus": "审批中",
"workTitle": "殷素云的流程名称很长流程名称很长流程名称很长流程_2022060913",
"workType": "0",
"workUrl": "http://xxxx/mruntime/?agentCode=xxx2dev&corp_id=#/admin/workflow/detail/0aeb1e6cf272463dbc1e65e6b76c8db6?applicationId=60b882a10cf2ab377c02a757&activityDefinitionId=obj_03&scope=TODO&taskId=f68e9fadb0e24d99a8e7a4981c28efbf&sourceType=YBG_TODO"
}
]
}
}
# 推送方式及加密说明
新增待办推送接口、更新待办推送接口、删除待办推送接口均采用Post请求,由七巧低代码推送至第三方配置的地址
(1) AES对称加密
AES对称加密
- 加密模式:ECB
- 填充:pkcs7
- 数据块:128位
- 密钥:用户设置的token字符串
- 字符集:utf8
加密内容输出方式
将加密后的内容通过base64字符串方式输出
加密算法示例
/**添加依赖**/
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.60</version>
</dependency>
加密工具类
public final class EncryptUtils {
/**
* 加密算法
*/
private static final String ENCRY_ALGORITHM = "AES";
/**
* 加密算法/加密模式/填充类型
* 采用AES加密,ECB加密模式,PKCS7Padding填充
*/
private static final String CIPHER_MODE = "AES/ECB/PKCS7Padding";
/**
* 设置加密字符集
* 采用 UTF-8 字符集
*/
private static final String CHARACTER = "UTF-8";
private EncryptUtils() {
}
/**
* AES加密
*
* @param content 加密内容
* @param encryptKey 加密密钥
* @return
*/
private static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {
if (StringUtils.isEmpty(content)) {
log.error("The encrypted content must not be null!");
throw new EncryptContentNullException("The encrypted content must not be null!");
}
SecretKey key = getKey(encryptKey);
log.info("密钥:{}", cn.com.do1.qiqiao.webhook.encrypt.utils.Base64.encode(key.getEncoded()));
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Cipher cipher = Cipher.getInstance(CIPHER_MODE);
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(content.getBytes(CHARACTER));
}
/**
* 生成密钥
*
* @param strKey
* @return
*/
public static SecretKey getKey(String strKey) {
try {
KeyGenerator generator = KeyGenerator.getInstance(ENCRY_ALGORITHM);
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(strKey.getBytes());
generator.init(128, secureRandom);
return generator.generateKey();
} catch (Exception e) {
throw new RuntimeException(" 初始化密钥出现异常 ");
}
}
/**
* AES解密
*
* @param encryptBytes 待解密的byte[]
* @param decryptKey 解密密钥
* @return 解密后的String
* @throws Exception
*/
private static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {
SecretKey key = getKey(decryptKey);
log.info("密钥:{}", cn.com.do1.qiqiao.webhook.encrypt.utils.Base64.encode(key.getEncoded()));
// 添加加密模式
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Cipher cipher = Cipher.getInstance(CIPHER_MODE);
cipher.init(Cipher.DECRYPT_MODE, key);
return new String(cipher.doFinal(encryptBytes), CHARACTER);
}
/**
* base 64 encode
*
* @param bytes 待编码的byte[]
* @return 编码后的base 64 code
*/
private static String base64Encode(byte[] bytes) {
try {
log.info("加密后的内容:{}", bytes);
return new String(Base64.encode(bytes), CHARACTER);// new BASE64Encoder().encode(bytes);
} catch (UnsupportedEncodingException e) {
log.error(e.getMessage());
}
return null;
}
/**
* base 64 decode
*
* @param base64Code 待解码的base 64 code
* @return 解码后的byte[]
* @throws Exception
*/
private static byte[] base64Decode(String base64Code) throws Exception {
return Base64.decode(base64Code.getBytes(CHARACTER));
}
/**
* AES加密为base 64 code
*
* @param content 待加密的内容
* @param encryptKey 加密密钥
* @return 加密后的base 64 code
* @throws Exception
*/
public static String aesEncrypt(String content, String encryptKey) throws Exception {
return base64Encode(aesEncryptToBytes(content, encryptKey));
}
/**
* 将base 64 code AES解密
*
* @param encryptStr 待解密的base 64 code
* @param decryptKey 解密密钥
* @return 解密后的string
* @throws Exception
*/
public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {
return StringUtils.isBlank(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);
}
}
(2)url有效性鉴权
POST http://example.com/qiqiao/hook?timestamp=1498586609
Headers:{
"Content-type":"application/json",
"X-Auth0-DeliverId":"31a2ae17-2661-4234-8d79-f62f3175fd75",
}
Body:{
"eventType":"URL_VERIFY",
"data": "随机字符串"
}
Response: {
"msg":"执行成功",
"code": 0,
"data": {
"token" : "zvmPTQAcEmxGbMoOLPjpoCPk/Oh096ZaORQ8o2iu8Cg="
}
}
校验流程如下:
接受到body里面的一个随机字符串,使用上述设置的token进行加密并生成的Base64的签名,直接返回;当系统用同样条件生成的签名与第三方系统生成的签名一致时,表示url校验通过;
# 新增待办推送接口说明
- 接口含义:批量新增待办/待阅
- 请求方式:Post
- 请求地址:/batchAddReceiptTodo
请求参数:
参数 | 数据类型 | 说明 |
---|---|---|
addList | List | 新增待办/待阅集合 |
orgId | String | 机构id |
返回值:
无
UpdateTodoDTO详细说明:
字段 | 类型 | 允许为空 | 描述 |
---|---|---|---|
receiptDTO | object | 否 | 单据实体类DTO |
addWaitUserIds | List | 是 | 新增待办用户userId集合 |
addReadUserIds | List | 是 | 新增待阅用户userId集合 |
orgId | String | 否 | 机构id |
receiptDTO参数详细说明:
字段 | 类型 | 允许为空 | 描述 |
---|---|---|---|
workId | String | 否 | 工单id,即一张待办单据的主键 |
workTitle | String | 否 | 工单标题(流程标题) |
workUrl | String | 否 | 工单url的全路径,用于点击跳转 |
workCreateTime | String | 否 | 工单创建时间yyyy-MM-dd HH:mm:ss |
workCreator | String | 否 | 工单创建人id(发起人id) |
workName | String | 否 | 工单创建人姓名(发起人姓名) |
workStatus | String | 是 | 工单状态中文(流转状态) |
currentNodeName | String | 是 | 工单当前节点中文(当前节点名称) |
customList | MytodoCustomDTO | 是 | 自定义参数 |
MytodoCustomDTO参数
字段 | 类型 | 允许为空 | 描述 |
---|---|---|---|
customName | String | 否 | 自定义字段名 |
customValue | String | 否 | 自定义字段值 |
POST
http://第三方域名/batchAddReceiptTodo?timestamp=1498586609
Headers:{
"Content-type":"application/json",
"X-Auth0-DeliverId":"31a2ae17-2661-4234-8d79-f62f3175fd75",
}
Body:{
"eventType":"PROCESS_ADD_TODO",
"applicationId":"应用Id",
"eventBusinessId":"",
"data": "zvmPTQAcEmxGbMoOLPjpoCPk/Oh096ZaORQ8o2iu8Cg="
}
Response: {
"msg":"执行成功",
"code": 0,
"data": {}
}
加密结构:
[{
addList:[
{
"receiptDTO":{
//工单id,即第三方一张待办单据的主键
"workId":"work123",
//流程标题
"workTitle":"流程标题",
//第三方统一待办系统跳转七巧低代码流程详情的url
"workUrl":"http://qiqiao-tcb-qa.qiweioa.cn/qiqiao2/mruntime/?agentCode=qiqiao2qa&corp_id=ww4852f35d45307a6f#/admin/workflow/detail/6538414979086811136?applicationId=60c35cc2efc18e0216665c2b&activityDefinitionId=obj_02&scope=TODO&taskId=6538427486031577089&sourceType=YBG_TODO",
//待办创建时间
"workCreateTime":"2021-01-01 00:00:00",
//发起人id
"workCreator":"zhangsan",
//发起人名称
"workName":"张三",
//流转审批状态
"workStatus":"审批中",
//当前节点名称
"currentNodeName":"节点1",
"customList":[{
//当前节点定义id
"customName":"currentNodeId",
"customValue":"obj1"
},{
//流程模型id
"customName":"processModelId",
"customValue":"6538427486031577089"
},{
//流程名称
"customName":"processName",
"customValue":"流程名称"
},{
//流程实例id
"customName":"processInstanceId",
"customValue":"6538414979086811136"
},{
//应用id
"customName":"applicationId",
"customValue":"60c35cc2efc18e0216665c2b"
},{
//任务id
"customName":"taskId",
"customValue":"6538427486031577089"
}]
},
"orgId":"b17efb43-292e-4cc9-ac5d-0b46bce059c4",
//待办用户集合(一条待办对应一条待办工单)
"addWaitUserIds":[
"204dcac59b288a1731b81e6e8ac6822e"
],
"addReadUserIds":[]
}
],
orgId:"b17efb43-292e-4cc9-ac5d-0b46bce059c4"
}]
# 更新待办推送接口说明
- 接口含义:批量更新待办/待阅,待办转已办,待阅转已阅
- 请求方式:Post
- 请求地址:/batchUpdateReceiptTodo
请求参数:
参数 | 数据类型 | 说明 |
---|---|---|
updateList | List | 更新对象集合 |
orgId | String | 机构id |
返回值:
无
UpdateTodoDTO详细说明:
字段 | 类型 | 允许为空 | 描述 |
---|---|---|---|
receiptDTO | object | 否 | 单据实体类DTO |
updateWaitUserIds | List | 是 | 需要变成已办状态的用户userId集合 |
updateReadUserIds | List | 是 | 需要变成已阅状态的用户userId集合 |
updateReceipt | Boolean | 是 | 是否需要更新单据(不需要更新单据dto可只传workId)更新待办时不能为空 |
receiptDTO参数详细说明:
字段 | 类型 | 允许为空 | 描述 |
---|---|---|---|
workId | String | 否 | 工单id,即一张待办单据的主键 |
workTitle | String | 否 | 工单标题(流程标题) |
workUrl | String | 否 | 工单url的全路径,用于点击跳转 |
workCreateTime | String | 否 | 工单创建时间yyyy-MM-dd HH:mm:ss |
workCreator | String | 否 | 工单创建人id(发起人id) |
workName | String | 否 | 工单创建人姓名(发起人姓名) |
workStatus | String | 是 | 工单状态中文(流转状态) |
currentNodeName | String | 是 | 工单当前节点中文(当前节点名称) |
请求MytodoCustomDTO参数
字段 | 类型 | 允许为空 | 最大长度 | 描述 |
---|---|---|---|---|
customName | String | 否 | 自定义字段名 | |
customValue | String | 否 | 自定义字段值 |
POST
http://第三方域名/batchUpdateReceiptTodo?timestamp=1498586609
Headers:{
"Content-type":"application/json",
"X-Auth0-DeliverId":"31a2ae17-2661-4234-8d79-f62f3175fd75",
}
Body:{
"eventType":"PROCESS_UPDATE_TODO",
"applicationId":"应用Id",
"eventBusinessId":"",
"data": "zvmPTQAcEmxGbMoOLPjpoCPk/Oh096ZaORQ8o2iu8Cg="
}
Response: {
"msg":"执行成功",
"code": 0,
"data": {}
}
传参示例(加密结构):
//更新已办
[{
"updateList":[
{
"receiptDTO":{
"workId":"work123"
},
"orgId":"b17efb43-292e-4cc9-ac5d-0b46bce059c4",
//更新用户单据为已办
"updateWaitUserIds":[
"204dcac59b288a1731b81e6e8ac6822e"
],
"updateReceipt":true
}
],
"orgId":"b17efb43-292e-4cc9-ac5d-0b46bce059c4"
}]
//更新已阅
[{
"updateList":[
{
"receiptDTO":{
"workId":"work1234"
},
"orgId":"b17efb43-292e-4cc9-ac5d-0b46bce059c4",
//更新用户单据为已阅
"updateReadUserIds":[
"204dcac59b288a1731b81e6e8ac6822e"
],
"updateReceipt":true
}
],
"orgId":"b17efb43-292e-4cc9-ac5d-0b46bce059c4"
}]
//更新单据内容
[{
"updateList":[
{
"receiptDTO":{
//工单id,即第三方一张待办单据的主键
"workId":"work1234",
//流程标题
"workTitle":"流程标题",
//第三方统一待办系统跳转七巧低代码流程详情的url
"workUrl":"http://qiqiao-tcb-qa.qiweioa.cn/qiqiao2/mruntime/?agentCode=qiqiao2qa&corp_id=ww4852f35d45307a6f#/admin/workflow/detail/6538414979086811136?applicationId=60c35cc2efc18e0216665c2b&activityDefinitionId=obj_02&scope=TODO&taskId=6538427486031577089&sourceType=YBG_TODO",
//待办创建时间
"workCreateTime":"2021-01-01 00:00:00",
//发起人id
"workCreator":"lisi",
//发起人名称
"workName":"李四",
//流转审批状态
"workStatus":"完成",
//当前节点名称
"currentNodeName":"节点1",
"customList":[{
//当前节点定义id
"customName":"currentNodeId",
"customValue":"obj1"
},{
//流程模型id
"customName":"processModelId",
"customValue":"6538427486031577089"
},{
//流程名称
"customName":"processName",
"customValue":"流程名称"
},{
//流程实例id
"customName":"processInstanceId",
"customValue":"6538414979086811136"
},{
//应用id
"customName":"applicationId",
"customValue":"60c35cc2efc18e0216665c2b"
},{
//任务id
"customName":"taskId",
"customValue":"6538427486031577089"
}]
},
"orgId":"b17efb43-292e-4cc9-ac5d-0b46bce059c4",
"updateReceipt":true
}
],
"orgId":"b17efb43-292e-4cc9-ac5d-0b46bce059c4"
}]
# 删除待办推送接口说明
- 接口含义:批量删除待办或者待阅
- 请求方式:Post
- 请求地址:/batchDeleteReceiptTodo
请求参数:
参数 | 数据类型 | 说明 |
---|---|---|
deleteReceiptTodoDTO | object | 删除待办/待办对象 |
返回值:
无
deleteReceiptTodoDTO参数详细说明:
字段 | 类型 | 允许为空 | 描述 |
---|---|---|---|
orgId | String | 否 | 机构id |
workIds | List | 否 | 需要删除的工单id集合 |
POST
http://第三方域名/batchDeleteReceiptTodo?timestamp=1498586609
Headers:{
"Content-type":"application/json",
"X-Auth0-DeliverId":"31a2ae17-2661-4234-8d79-f62f3175fd75",
}
Body:{
"eventType":"PROCESS_DELETE_TODO",
"applicationId":"应用Id",
"eventBusinessId":"",
"data": "zvmPTQAcEmxGbMoOLPjpoCPk/Oh096ZaORQ8o2iu8Cg="
}
Response: {
"msg":"执行成功",
"code": 0,
"data": {}
}
//删除单据加密结构
[{
"deleteReceiptTodoDTO":{
"orgId":"b17efb43-292e-4cc9-ac5d-0b46bce059c4",
"workIds":[
"work8c10327e0c3a42a3bb1f7a92c06619ae"
]
}
}]
#
1 / 0