# 事件推送开发指南
# 功能介绍
七巧低码开发平台面向第三方系统提供了表单引擎数据的主动推送机制,可用于实现当表单数据新增、删除和被修改时的实时集成场景。
# 使用教程
# 配置指南
# 配置事件推送
打开API管理>>推送管理
配置URL和Token,并设置对应表单的触发类型
# 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校验通过;
# 响应规则
向对应目标服务器推送请求后,该服务器需在20秒内使用 2xx 作为响应的状态码进行响应,即认为数据推送成功。
一次推送重试最多5次,如果单次推送连续重试5次均失败,则该次推送失败。
# 开发注意点
为了保证每个对接的应用服务能够接受到推送数据时,不出现异常,所以请在接收到eventType参数的数据类型时,直接响应成功,不要响应为失败。
# 开发指南
# 推送方式
使用POST请求,在请求的内容如下:
POST
http://qiqiao.do1.com.cn/plus/cgi-bin/v1/qiqiao/hook?timestamp=1498586609
Headers:{
"Content-type":"application/json",
"X-Auth0-DeliverId":"31a2ae17-2661-4234-8d79-f62f3175fd75",
}
Body:{
"eventType":"FORM_DATA_ADD",
"applicationId":"应用Id",
"eventBusinessId":"业务模型Id",
"data": "zvmPTQAcEmxGbMoOLPjpoCPk/Oh096ZaORQ8o2iu8Cg="
}
Response: {
"msg":"执行成功",
"code": 0,
"data": {}
}
加密结构
{
"variables":{
"fieldName": "fieldValue",
"age": "22"
},
"id": "0141c3223a6e4d9dbd7c4f605fd0fb48",
"version": 1,
"formTitle": "xxx表单",
"processInstanceId": "355cfccf9bc63ce4282c0c437b71fdfb",
"processDefinitionId": "355cfccf9bc63ce4282c0c437b71fdfb",
"formDefinitionId": "105cfccf9bc63ce6a82c0c437b41fd3c",
"taskId": "64c761a7fb7f4847992466ee76efc195",
"author": "a08bcb7e67a84cb08348884688aacd02",
"authorName": "张三",
"createDate": 12324123123,
"lastModifyDate": 12312312312,
"lastModifier": "a08bcb7e67a84cb08348884688aacd02",
"lastModifierName": "张三",
"applicationId": "f58bcb7e67a84c458348884688aacd7f"
}
参数说明:
字段 | 字段类型 | 字段说明 |
---|---|---|
variables | object | 表单字段值集合 |
id | string | 表单id |
version | int | 表单数据版本号 |
formTitle | string | 表单标题 |
formDefinitionId | string | 表单定义id |
processInstanceId | string | 流程实例id |
processDefinitionId | string | 流程定义id |
taskId | string | 任务id |
author | string | 创建人id |
authorName | string | 创建人名称 |
createDate | long | 创建日期 |
lastModifyDate | long | 最后修改日期 |
lastModifier | string | 最后修改人id |
lastModifierName | string | 最后修改人名称 |
applicationId | string | 应用id |
# 请求头包含字段说明
X-Auth0-DeliverId :消息推送Id,每次推送的id是唯一的,可以通过该字段完成请求去重,防止重复请求;
# 请求包体字段说明
参数名 | 是否必须 | 字段类型 | 参数说明 | 备注 |
---|---|---|---|---|
eventType | 是 | String | 事件类型 | 类型名称(类型标识): 1.url验证 ( URL_VERIFY) 2.表单数据新增(FORM_DATA_ADD) 3.表单数据更新(FORM_DATA_MODIFY) 4.表单数据删除(FORM_DATA_DEL) |
applicationId | 是 | string | 应用Id | |
eventBusinessId | 是 | string | 业务的模型Id | 此处表示表单模型Id |
data | 是 | string | 消息内容 | 内容进行对称加密后转换为base64的字符串 |
# 加密算法
# 1.2.1 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);
}
}
1 / 0