# CIP集成修改:将集成前事件代码迁移到finalListener去做安全的数据推送

# 背景&需求

目前发现有很多类客户问题,与第三方系统对接相关,在节点上配置了执行前事件,通过NC集成或者通过CIP集成,而这些前事件包含的业务往往需要和第三方系统交互。

但是前事件执行过程与正式提交过程,不在OA的同一个事务里。 就导致了可能前事件执行成功,但是正式提交因为各种原因失败;由于前事件和三方系统之间存在交互,如果操作人二次提交,又会触发前事件执行,这样就和第三方系统产生了2次交互。如果三方系统做了幂等,前事件校验就会不通过,导致整个流程无法继续提交下去,产生各种阻塞。

其中【CIP集成】【工作流】流程前事件重复执行推送三方事件失败【技术向】 https://open.seeyoncloud.com/#/faq/faq/v1/share?url=Z2JySmU+NDU0MQ== 文档对这个事件的产生进行了详细描述。

而为了解决这种常见问题,致远官方推荐:将集成前事件代码迁移到finalListener去做安全的数据推送。此篇文档也是为了解决这个问题,提供一套完整的代码迁移案例。

# 操作步骤&解决方案

# 集成前事件迁移到finalListener

# 第一步:参数传递修改

之前在CIP或者NC集成部分,可能有部分客户自己定义的参数。迁移后,后端需要在ThirdPartyListenerContext中可以获取到,因此,这里前端需要可以将这部分参数传递过来。

具体集成方式可以参考文档: https://open.seeyoncloud.com/v5devCTP/1842/1878/1879.html 动态注入js/css资源

以下为注入js的样例:

//强阻塞
$.ctp.bind('thirdPartyHandle',(args)=>{
    alert(args.data.errorMsg);
    args.error();
});
//弱阻塞,带确认
$.ctp.bind('thirdPartyHandle',(args)=>{
    console.log('12313',args)
    var confirmation = confirm(args.data.errorMsg);
    if(confirmation){
        args.thirdPartyContext['weekBlock12345']={
            confirm:true//后端发现此key匹配的true无需再校验
        }
    args.success(); 
    }else{
       args.error();  
    }
});

# 第二步:后端对对应的finalListener进行监听处理自己业务

后端提供了三套扩展抽象类:

业务类型 className
发送 CollaborationThirdPartySendListener
处理 CollaborationThirdPartyDealListener
终止/回退/指定回退 CollaborationThirdPartyOperateListener

这里依照CollaborationThirdPartyDealListener为样例: /** * 完成后的事件处理 */ public class ExampleFinalDealListener extends CollaborationThirdPartyDealListener implements FinalListener { @Override public ServiceResult doHandle(ThirdPartyListenerContext thirdPartyListenerContext) throws BusinessException { //从上下文信息获取业务需要的数据 ThirdpartParamData thirdpartParamData = thirdPartyListenerContext.getThirdpartParamData(); Object confirm = thirdpartParamData.getThirdPartyContext().get("your parame"); if (confirm instanceof Map){ Map<String, Boolean> stringObjectMap = (Map<String, Boolean>) confirm; if (stringObjectMap.getOrDefault("confirm",false)){ return ServiceResult.ok(); } } //处理自己业务:成功返回样例 if (Objects.nonNull(thirdPartyListenerContext.getFormAppId())){ return ServiceResult.ok(); }else { //失败返回样例 return ServiceResult.fail(Collections.singletonMap("errorMsg","发送拦截不通过")); }

    }

    /**
     * 这里决定执行顺序,值越小越先执行
     * @return
     */
    @Override
    public int getOrder() {
        return 100;
    }
}
编撰人:yanghaiw