RealDoc异步任务Webhook使用指南
功能说明
RealDoc Webhook用于通知异步文档处理任务的最终状态。当您通过异步文档处理API提交任务后,任务进入Success或Failure状态时,ZOLOZ会向您配置的回调地址发送HTTP POST请求。
Webhook仅通知任务状态,不包含完整处理结果。收到通知后,请使用transactionId调用异步任务状态或结果查询接口获取详细结果。
开通说明
Webhook按商户和环境开通。如需开通,请联系ZOLOZ客户经理或技术支持,并提供目标环境和商户信息。
使用流程
前提条件
- 开通Webhook功能和Portal权限:请联系ZOLOZ开通。
- Portal权限开通后,请退出并重新登录。
- 当前Webhook管理功能面向Administrator、Operator及具备相关权限的自定义角色开放。
- 准备接收地址:准备一个可以从公网访问的HTTPS回调地址。
配置步骤
- 登录ZOLOZ Portal。
- 在左侧导航栏,选择Integration > Webhook,进入Webhook Configuration页面。
- 创建Webhook并选择RealDoc Async。
- 填写配置信息,包括HTTPS回调地址、Secret、摘要算法等,保存后执行测试验证连通性。
- 测试成功后启用该配置。
- 通过RealDoc异步API提交任务后,ZOLOZ将在任务完成时发送Webhook通知。收到通知后,请使用
transactionId查询完整结果。
回调协议
请求概览
项目 | 内容 |
Method |
|
Content-Type |
|
回调地址 | Portal中配置的公网HTTPS地址 |
发送时机 | 异步任务进入 |
请求Header
HTTP Header名称不区分大小写。
Header | 说明 |
| 使用Portal中配置的Secret对原始请求Body计算得到的HMAC签名(十六进制字符串)。 |
| 签名算法,支持 |
请求Body
示例:
copy
{
"transactionId": "R000000202607211713541766****",
"status": "Success",
"productType": "REALDOC_DOCUMENT_EXTRACTION"
}字段说明:
字段 | 说明 |
| 异步任务的唯一标识,与异步上传接口响应中的任务标识一致,用于幂等处理和结果查询。 |
| 任务的最终状态, |
| RealDoc产品类型。支持以下取值:
|
Java接收与验签示例
本示例适用于Java 8和Spring Boot。验签时需注意:
- 算法支持:验签支持
HMAC_SHA256_HEX和HMAC_SHA512_HEX两种签名算法。 - 关键要求:验签时必须使用HTTP收到的原始Body,请勿对Body进行格式化、反序列化或重新序列化,否则会导致签名不一致。
copy
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.EnumMap;
import java.util.Map;
import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/webhooks")
public class RealDocWebhookController {
private static final Logger log = LoggerFactory.getLogger(RealDocWebhookController.class);
private static final String HEADER_DIGEST = "X-Payload-Digest";
private static final String HEADER_DIGEST_ALG = "X-Payload-Digest-Alg";
private static final String ALG_HMAC_SHA256_HEX = "HMAC_SHA256_HEX";
private static final String ALG_HMAC_SHA512_HEX = "HMAC_SHA512_HEX";
private final Map<HmacAlgorithms, HmacUtils> hmacUtilsMap = new EnumMap<>(HmacAlgorithms.class);
public RealDocWebhookController(@Value("${realdoc.webhook.secret:}") String secret) {
hmacUtilsMap.put(HmacAlgorithms.HMAC_SHA_256, new HmacUtils(HmacAlgorithms.HMAC_SHA_256, secret));
hmacUtilsMap.put(HmacAlgorithms.HMAC_SHA_512, new HmacUtils(HmacAlgorithms.HMAC_SHA_512, secret));
}
@PostMapping(value = "/realdoc", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Void> receive(@RequestBody String rawBody, @RequestHeader(HEADER_DIGEST) String digest,
@RequestHeader(HEADER_DIGEST_ALG) String algorithm) {
HmacAlgorithms hmacAlg = resolveAlgorithm(algorithm);
if (hmacAlg == null) {
log.warn("Unsupported digest algorithm: {}", algorithm);
return ResponseEntity.badRequest().build();
}
String expected = hmacUtilsMap.get(hmacAlg).hmacHex(rawBody);
boolean valid = MessageDigest.isEqual(expected.getBytes(StandardCharsets.UTF_8), digest.getBytes(StandardCharsets.UTF_8));
if (!valid) {
log.warn("Webhook signature verification failed, algorithm={}", algorithm);
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
// Process the event idempotently by transactionId.
return ResponseEntity.ok().build();
}
private HmacAlgorithms resolveAlgorithm(String algorithm) {
switch (algorithm) {
case ALG_HMAC_SHA256_HEX:
return HmacAlgorithms.HMAC_SHA_256;
case ALG_HMAC_SHA512_HEX:
return HmacAlgorithms.HMAC_SHA_512;
default:
return null;
}
}
}注意事项
- 接收成功后,请尽快向ZOLOZ返回HTTP 2xx状态码。如果业务处理耗时较长,建议将耗时的业务逻辑转移至内部队列异步处理。
- 当ZOLOZ未收到2xx响应或发生超时、网络异常时,可能触发重试,同一通知可能多次送达。请使用
transactionId幂等处理。 - Webhook投递失败不影响RealDoc任务结果,您仍可以定期调用状态查询和结果查询接口获取任务最终结果。
- Webhook仅由客户通过异步API提交的任务触发,Portal体验中心发起的任务不会触发Webhook通知。
- 未开通或未配置Webhook不影响原有异步API的正常使用,您仍可通过状态查询和结果查询接口进行轮询。
- Secret应保存在Portal和您的密钥管理系统中,不要记录到日志中,也不要提交到代码仓库。