一. 概述
纷享集成平台是用来做CRM和其它IT系统间对接的支撑平台。具有如下特点:
-
支持CRM和其它IT系统(不限于ERP)之间数据同步。
-
用于数据对接,而不是流程对接。比如CRM的审批流和外部OA的审批流要交替审批,这种场景是不支持的。
外部的数据源,用外部对象元数据管理(对应的菜单是 连接器管理->连接对象)抽象为对象。所有的对接,都变成CRM对象和外部对象的对接,外部对象可以是ERP,可以是文件,可以是数据库。
二. 集成平台开通
按照连接器在fs租户下,购买集成平台销售订单,就能在 管理 频道下看到集成平台入口了。
三. 连接器和集成流
连接器负责调用外部IT系统读写接口。连接器是按照系统划分的,云星空是一个连接器,SAP是一个连接器,CRM也是一个连接器。
集成流负责把源系统数据"加工"成目标系统的数据。
集成实施步骤:确定好对接需求->配置连接器->配置集成流->启用集成流->日程运维。
1. 连接器说明
外部对象管理
-
主键
相当于CRM的_id字段。每条数据必须有唯一的主键,主键必须具有唯一性。两条不同的数据,主键必须是不同的。主键的作用,用来识别调用更新接口的时候,找到待更新数据。
-
主属性
默认是name字段。
-
单选option和label
option是代码使用,label用来帮助人眼阅读。选项映射的时候,option一定要对齐。
-
引用字段
如果引用的是单选字段,对接会有问题。因为CRM默认查到的是字段的label, 查不到option。
-
虚拟字段
crm和erp上的非真实字段,集成平台为了方便对接而自动添加上去的字段。比如K3C上的是否开启批次和序列号。
-
虚拟复合字段
多个字段拼接在一起的虚拟字段,比如k3c上销售订单使用ID+编码作为主键, 那么 回款明细要关联订单,就使用 ID+编码拼成的虚拟复合字段 查找关联订单。
读写外部接口说明
账套管理
通常一个连接器,连接一个外部系统。如果有多套外部系统要对接,需要创建多个连接器。
比如一个企业对接云星空的2个数据中心,和一套SAP,那么需要3个连接器。
系统字段管理
这里处理的是CRM和外部都不是对象,又需要转换的字段。这类数据无法通过对接对象来完成。主要是以下数据
- 国家
- 省市区
- 乡镇
部门和人员,产品分类在CRM已经做了对象化,最好是使用 对象对接的方式。
账户绑定
主要是CRM和外部的人员绑定。
CRM如果使用人员对象对接的话,这里的数据由集成平台自动维护,无需再手工导入。
标准API说明
2. 集成流说明
执行顺序
在集成流配置页面看到的图,就是一条数据经过集成流处理时的执行顺序
上图中,一条数据从金蝶K3C读回来,先经过数据范围过滤,然后做字段转换,最后写入目标系统。
读写外部数据的方式
- PAAS事件。CRM数据变化(页面编辑和PAAS后台计算)时,触发CRM->ERP数据同步。
- 轮询。集成平台定时调用queryMasterBatch获取外部数据。
- 推送。外部系统通过asyncpush接口往集成平台推送数据。
erp->CRM如果不是对时效性要求很高的话,尽量用轮询而不是推送。因为使用轮询,重试或者刷历史数据这类操作可以自助完成,不需要客户方IT人员配合。
什么时候触发同步
ERP->CRM方向,只要轮询到主数据就会触发发生数据同步。
CRM->ERP方向,(1)只要CRM上数据的字段内容发生变化就会触发数据同步。(2)从数据发生变化,则主数据也会触发同步。
以下情况会阻断数据同步。
1.同步策略没有开启,数据不会做同步。
2.不符合数据范围的数据,同步过程会被阻断。
3.对于新增到目标系统:变化的字段既没有做过字段映射,又没有配置过数据范围,则该条数据的同步会被阻断。
4.对于更新到目标系统:变化的字段没有做过字段映射,则该条数据的同步会被阻断。
事件转换说明
源事件到目标事件的转换逻辑如下表
事件过滤说明
-
目标事件如果不在已勾选的执行动作中,则丢弃改事件,数据不做同步。比如下图中目标系统不允许调用编辑接口,那么对于目标事件是编辑的,则丢弃事件。
-
CRM数据风暴规避。只针对CRM->ERP。
(1)源事件更新,目标事件是新增的。变化的字段如果不在数据范围中也不在字段映射中,则丢弃本次事件。
(2)目标事件是更新的。如果变化的字段不在字段映射中,则丢弃本次事件。如果变化的字段在映射字段中,但它是个引用字段且实际的值没有变化,也会丢弃事件。
补充背景:原来有同事在CRM中增加一个计算字段,导致CRM全量数据的计算字段都发生字段变化,然后触发CRM->ERP同步。
实际上计算字段如果不做字段映射,是不需要同步的。
数据范围说明
-
主从对象独立设置过滤条件。主数据使用主对象的数据范围条件做检查,从数据使用从对象的数据范围条件做检查。
-
主对象数据还会检查从数据。如果从数据全部不满足数据范围且设置了 "没有从数据则不同步主数据",则主数据也会被阻挡。
最常见的情况是:一主多从,部分从被过滤掉,则满足条件的主数据和满足条件的部分从数据会继续同步。
从对象事件转为主对象事件
如果主数据还没有中间表映射关系,则该从事件丢弃,发出一个主数据同步的事件。
从触发主 这个逻辑,是导致偶发的页面操作一次,CRM->ERP发生多次写的根源。但是为什么还要保留这个逻辑呢?
请查阅 引申阅读:
字段转换说明
- 引用字段。源数据中把引用字段替换为真实的值再进行其它转换。
- 查找关联类型的,自动替换。比如erp订单数据查找关联erp客户id, 则字段转换时,自动把erp客户id转为crm客户id。
- 主从类型的,自动替换。比如erp订单明细上有erp订单主id, 则字段转换时,自动把erp订单主id转为crm订单主id。
- 设置为固定值的,塞入固定值。
- 国家省市区通过系统字段中的映射关系自动替换。
- 人员id通过人员绑定关系表自动替换。
- 单选字段类型的,把源option替换为目标系统option。
- 默认直接拷贝。
四.自定义函数说明
同步前、中、后函数入参和返回值类型都是Map,参数名为syncArg。
同步前函数
场景:复杂的数据过滤条件在数据范围表达不出来,可以用同步前函数实现。
即函中返回结果中包含"isExec":"false",即该次同步将不再往后执行,目标数据将不会做出相应的更改。
同步中函数
场景:在目标数据调用写接口之前,修改目标数据。
同步后函数
场景:调用目标系统写接口之后,添加后动作。比如CRM->ERP同步了一个订单,把ERP接口调用成功或失败的状态写入CRM的字段。业务人员就能看到这条数据是否同步成功了。
回填状态的功能现在可以通过回写组件配置完成。其它更复杂的后动作可以通过同步后函数完成。
触发CRM——>ERP数据同步
使用场景:在CRM列表、详情页配置按钮,触发数据同步。可用于解决CRM数据不方便修改或刷数据需求。
//必填,CRM对象apiName
def crmObjApiName = context.data.object_describe_api_name;
//必填,CRM数据Id
def crmDataId = context.data._id
//选填,ERP中间对象apiName,不指定会同步所有策略,填写则只同步到指定目标ERP对象的策略
def erpObjApiName = null //"BD_Customer.BillHead"
def type = "manualSyncCrm2Erp"
def params = ["crmObjectApiName":crmObjApiName,
"crmDataId":crmDataId,
"erpObjectApiName":erpObjApiName]
def arg = ["type":type,
"params":Fx.json.toJson(params)]
def ret = Fx.proxy.callAPI("erp.syncData.executeCustomFunction", [:], arg)
//同步结果处理逻辑:
log.info(ret)
触发ERP——>CRM数据同步
//必填,CRM对象apiName
def crmObjApiName = context.data.object_describe_api_name;
//必填,CRM数据Id
def crmDataId = context.data._id
//必填,ERP中间对象apiName
def erpObjApiName = "BD_Customer.BillHead"
//该类型用于触发ERP往CRM数据同步,使用crm数据id
def type = "manualSyncErpDataByCrmDataId"
def params = ["crmObjectApiName":crmObjApiName,
"crmDataId":crmDataId,
"erpObjectApiName":erpObjApiName]
def arg = ["type":type,
"params":Fx.json.toJson(params)]
def ret = Fx.proxy.callAPI("erp.syncData.executeCustomFunction", [:], arg)
//同步结果处理逻辑:
log.info(ret)
操作集成平台中间表
Map header=[:]
//创建数据映射
Map param1=["ployDetailId":"155bd981457343f291e0edc13776217f",//策略明细id(见下图),如果策略被删除重新建了,这里需要改动
"sourceObjectApiName":"AccountObj",//源对象apiName,如果对象apiName变了,这里要改动
"destObjectApiName":"BD_Customer.BillHead",//目标对象apiName,如果对象apiName变了,这里要改动
"sourceDataId":"sourceDataId123",//源对象数据id
"destDataId":"destDataId123666",//目标对象数据id
"sourceDataName":"sourceDataName3666",//源对象数据name属性
"destDataName":"destDataName66",//目标对象数据name属性
"remark":"remark1341"];//备注
def result1=Fx.proxy.callAPI("erp.syncData.createSyncDataMapping",header,param1);
//[false, HttpResult(statusCode=200, content={"errCode":"s106240000","errMsg":"成功"}, bytes=null), ] s106240000成功,其他失败
log.info(result1)
//根据源对象数据id更新目标对象数据id
Map param2=["sourceObjectApiName":"AccountObj",//源对象apiName,如果对象apiName变了,这里要改动
"destObjectApiName":"BD_Customer.BillHead",//目标对象apiName,如果对象apiName变了,这里要改动
"sourceDataId":"sourceDataId123",//源对象数据id
"destDataId":"destDataId123666"]//目标对象数据id
def result2=Fx.proxy.callAPI("erp.syncData.updateSyncDataMapping",header,param2);
//[false, HttpResult(statusCode=200, content={"errCode":"s106240000","errMsg":"成功"}, bytes=null), ] s106240000成功,其他失败
log.info(result2)
//查询源对象数据id是否存在映射关系
Map param3=["sourceObjectApiName":"AccountObj",//源对象apiName,如果对象apiName变了,这里要改动
"destObjectApiName":"BD_Customer.BillHead",//目标对象apiName,如果对象apiName变了,这里要改动
"sourceDataId":["sourceDataId123"]]//源对象数据ids,List
def result3=Fx.proxy.callAPI("erp.syncData.getSyncDataMappingBySourceDataId",header,param3);
// [false, HttpResult(statusCode=200, content={"data":{"sourceDataId123":{"sourceDataId":"sourceDataId123","isCreated":true,"destDataId":"destDataId123666","sourceDataName":"sourceDataName1233","updateTime":1611047455451,"lastSyncStatus":6,"destDataName":"destDataName123","destTenantId":"81138","sourceObjectApiName":"AccountObj","destObjectApiName":"BD_Customer.BillHead","sourceTenantId":"81138","statusName":"新增成功","id":"aa46ed320312476485e932a1ca4b4263","lastSyncDataId":"92c86fb175254e54b990bd86b6ce1145","status":1}},"errCode":"s106240000","errMsg":"成功"}, bytes=null), ]
//s106240000成功,其他失败
//data是一个Map,存储着存在映射关系的数据,key是源数据id,value是已存在的对应关系,
log.info(result3)
五.运维相关
告警
熔断
熔断有两种:
集成流的熔断。错误数据超过阈值,集成流被强制停止了。
getbyid接口的熔断。集成流不会停止,只是不会再调用getbyid接口了,依赖getbyid接口的功能都被禁止了。
监控
六.问题排查
日志存储说明
一个租户能存储的日志量,是通过资源包控制的。
下完销售订单以后,会根据连接器的类型,自动赠送一个资源包。如果日志量超过资源包的值,就会把最老的日志滚掉。
资源包控制的日志包括:
-
详情页快照。
-
访问ERP接口的日志
-
全流程日志。全流程的日志,一部分是复用了详情页快照的日志。
排查和解决问题方法
- 数据维护查看详情,报错提示
- 接口调用参数和返回结果说明
- FAQ
- 跳转各渠道排查方法(K3webapi、第三方系统接口,函数)
正确的提问方法
- 提问之前:先自查。非配置导致的接口问题需要找接口提供方解决。
- 在哪或者向谁提问:如何提系统对接的问题
- 怎么提问题:提供完整信息,企业、ERP中间对象apiName、CRM中间对象apiName和数据ID、尽量具体(到秒)的发生时间、报错信息、问题现象和描述、自己排查的结果