阅读对象:
CRM/ERP系统管理员、数据库管理员、系统实施、财务、数据分析等相关人员,希望实现两个系统之间数据同步的程序员。
适用场景:
纷享销客创建完客户以后,希望客户信息直接同步到金蝶系统客户列表里;纷享销客创建完订单,直接同步到金蝶销售订单;金蝶系统做完发货单,纷享销客同时收到发货通知等。
实现原理:
利用纷享销客开放平台Open API接口实现对纷享销客CRM对象(客户、订单、联系人、销售线索、回款……)的操作;利用金蝶云星空(K3cloud)Web API实现对金蝶云星空表单数据的操作;利用两个系统各自的API接口,结合具体的业务需求,即可实现两个系统的数据同步。

为什么现在很多平台都提供API接口?

我想引用金蝶云Web API概述里的一段话来回答这个问题。

为异构系统访问K/3Cloud系统数据提供通用的接口。

当企业规模逐渐增大时,作为支撑业务运营的IT建设也变得越来越重要,不过往往企业的IT建设过程中会发现某一家软件供应商基本不能完全覆盖企业所有的业务运营流程,这样的结果就是,企业上的IT系统很多很全,从ERP到HR、CRM、PDM、OA等,貌似所有的业务都覆盖到了,但实际上因为这些系统的不集成,而形成了企业很多新的信息孤岛,非常不利于企业的后续的管理和战略发展。K/3Cloud从现今和往后的发展趋势来看,也不可避免会遇到上述问题,毕竟企业经营的多样化,并不是所有的业务都能在K/3Cloud中完成,所以我们必须在产品架构上支持更好的与外部系统进行协同。
纷享销客把自己定义为连接型CRM,从字面意义上就能感受到这个产品互联互通的特性,它首先实现业务互联,连接企业的上下游企业;内部协作互联;以及微信生态的互联,基于Open API实现与其他系统的互联。但在这里要对号称连接型CRM纷享销客稍稍鄙视一下:使用API接口还要收费?还要开通频次调用包?自建应用访问CRM数据还要经过纷享的再次审核?对使用开放平台设置了太多门槛,并且这些都没有写在文档里,通过与客服和销售人员多次沟通才了解到的,这感觉与纷享的连接精神不符!
如何使用纷享销客开放平台?
如果熟悉微信公众平台开发的朋友,会发现纷享开放平台与微信公众平台接口非常类似,参数名几乎都一致,甚至大小写都一样,当然还有几个参数不同,比如:纷享销客API接口的每次调用都需要携带一个currentOpenUserId(当前操作人OpenUserID)的参数;CorpAccessToken有效期同为7200秒,微信平台有效期内再次访问,会生产新的AccessToken,纷享平台会返回相同的CorpAccessToken;纷享平台获取CorpAccessToken会同时获得一个corpId,这也是请求接口的必须参数之一,注意不是appId。要使用纷享销客开放平台的步骤是:

第一步:创建企业自建应用

管理员登录纷享销客网页端后进入“应用”频道“应用管理”,点击“添加应用”完成应用添加和配置,在配置过程中对应用开启“开发模式”。开启“开发模式”以后可以看到 appId、appSecret 和 permanentCode,请记录下来,第二步需要用到。详细步骤请参考:http://open.fxiaoke.com/support.html#artiId=61获取这些参数的路径并不是在纷享销客后台的应用页,而是在纷享销客的 管理=>应用管理中心=>自建应用

第二步:获取CorpAccessToken

通过第一步获取的 appId、appSecret 和permanentCode 换取 CoprAccessToken,详细请参考:http://open.fxiaoke.com/wiki.html#artiId=17API接口地址:https://open.fxiaoke.com/cgi/corpAccessToken/get/V2​JSON数据:

{    "appId": "APPID”,    "appSecret":"APPSECRET”,    "permanentCode":”PERMANENT_CODE"
}

PHP示例代码:

//获取CorpAccessTokenpublic function getcorpAccessToken() {$result = Db::name('fxtoken')->where('type', "corpAccessToken")->find();$corpId = $result['corpid'];$corpAccessToken = $result['value'];$expires_time = $result['expire'];if (time() > ($expires_time + 7200)) {$url = "https://open.fxiaoke.com/cgi/corpAccessToken/get/V2";$data = array('appId' => $this->appId,'appSecret' => $this->appSecret,'permanentCode' => $this->permanentCode,);$res = json_decode($this->http_request($url, json_encode($data)));$acctoken = array();$acctoken['corpid'] = $res->corpId;$acctoken['value'] = $res->corpAccessToken;$acctoken['expire'] = time();$corpId = $acctoken['corpid'];$corpAccessToken = $acctoken['value'];Db::name('fxtoken')->where('type', "corpAccessToken")->update($acctoken);}$AccessToken = array('corpId' => $corpId,'corpAccessToken' => $corpAccessToken);return $AccessToken;}

第三步:对CorpAccessToken做缓存处理

每个 access_token 的有效期为7200秒(2小时),有效期内重复获取返回相同结果,并自动续期。所以为了防止因为频率调用次数超出限制而影响功能正常使用的问题,建议开发者将中间生成的 CorpAccessToken 进行缓存,过期以后再重新获取。同时由于每个应用的 CorpAccessToken 是彼此独立的,所以进行缓存时需要区分应用来进行存储。上述PHP示例代码已经对CorpAccessToken写入数据库,每7200秒再次获取。
一般都会对纷享销客API接口进行封装,方便进行调用,给出部分PHP示例代码:

<?php
/*
封装纷享销客开放平台OpenAPI;
author:王志锋
email:wangzhifeng@tongdog.com.cn*/
namespace fxiaoke;
use think\Db;class fxiaoke {private $appId;private $appSecret;private $permanentCode;private $corpid;public $corpAccessToken;private $currentOpenUserId;//构造方法public function __construct($appId, $appSecret, $permanentCode, $currentOpenUserId) {$this->appId = $appId;$this->appSecret = $appSecret;$this->permanentCode = $permanentCode;$this->currentOpenUserId = $currentOpenUserId;$AccessToken = $this->getcorpAccessToken();$this->corpid = $AccessToken["corpId"];$this->corpAccessToken = $AccessToken["corpAccessToken"];}//HTTP请求(支持HTTP/HTTPS,支持GET/POST)protected function http_request($url, $data = null) {$header = array('Content-Type: application/json',);$curl = curl_init();curl_setopt($curl, CURLOPT_URL, $url);curl_setopt($curl, CURLOPT_HTTPHEADER, $header);curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);if (!empty($data)) {curl_setopt($curl, CURLOPT_POST, 1);curl_setopt($curl, CURLOPT_POSTFIELDS, $data);}curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);$output = curl_exec($curl);curl_close($curl);return $output;}
}

第二部分的getcorpAccessToken也是fxiaoke类的一个方法,其他需要封装的接口,按照开发者文档说明,进行封装即可,纷享销客开放平台开发者文档:
纷享开放平台-开发文档

open.fxiaoke.com
这里提供两个官方文档里没有的错误返回码:

errorCode: 30003
errorMessage: xxxx has no openapi quote currently!

这个错误就是我吐槽里说的,CRM系统API接口是收费的,需要开通频次调用包才能使用,客服会让你跟销售沟通。

errorCode: 20020
errorMessage: app can not access this enterprise 's data

这个错误是自建应用没有访问CRM系统数据授权的错误码,需要联系纷享客服提交给技术人员开通才能使用。

第四步:开发对接逻辑

经过了前面这些步骤,纷享销客的API就应该都可以自由调用了,根据业务需求去实现就可以了。
如何使用金蝶云星空(K3Cloud)Web API ?
金蝶K3Cloud使用Web API非常简单,只要使用管理员账号登陆,在最上方搜索:webapi,即可出来:WebSDKAPI Web API功能菜单,或者在 基础管理=>公众设置=>Web API 也能打开Web API功能。其实金蝶云星空的API接口只有15个:
登陆验证接口:
https://ServerIp/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc
查看表单数据接口:
https://ServerIp/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.View.common.kdsvc
保存表单数据接口:
https://ServerIp/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save.common.kdsvc
批量保存表单数据接口:
https://ServerIp/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.BatchSave.common.kdsvc
提交表单数据接口:
https://ServerIp/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Submit.common.kdsvc
审核表单数据接口:
https://ServerIp/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Audit.common.kdsvc
反审核表单数据接口:
https://ServerIp/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.UnAudit.common.kdsvc
删除表单数据接口:
https://ServerIp/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Delete.common.kdsvc
单据查询接口:
https://ServerIp/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery.common.kdsvc
自定义WebAPI接口:
https://ServerIp/K3Cloud/接口命名空间.接口实现类名.方法,组件名.common.kdsvc
登录验证接口带踢人功能:
https://ServerIp/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser2.common.kdsvc
暂存表单数据接口:
https://ServerIp/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Draft.common.kdsvc
分配表单数据接口:
https://ServerIp/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Allocate.common.kdsvc
下推接口:
https://ServerIp/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Push.common.kdsvc
分组保存接口:
http://ServerIp/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.GroupSave.common.kdsvc
把ServerIp替换为自己服务器的域名就是自己API接口地址了,比如:https://tongdog.kingdee.com/k3cloud/Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc
就是一个公有云的登陆接口地址。登陆接口是鉴权用的,金蝶云新版Web API已经对鉴权做了升级,改为第三方应用授权的形式,这里还是讲通用的用登陆接口做鉴权,访问其他接口都需要先通过登陆接口获取cookie,然后携带cookie去访问其他接口,关于cookie的有效期,我也没有去验证过,一个业务逻辑单元内,登陆一次,cookie肯定是有效的。

金蝶云星空的所有API接口,都是两个必要条件,一是接口URL地址,二是JSON数据包,接口地址我都已经给出了,剩下就是JSON数据包了,这个也是调用金蝶云星空API接口最关键最难的地方,主要原因是接口文档不够详细,很多参数不知道该怎么写,我们先来看下登陆接口:登陆接口API地址:https://ServerIp/K3Cloud/Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc
JSON数据包:

{"acctid": “账号ID”,//通过 WebAPI测试窗口就能看到"username": “用户名","password": "密码","lcid": 2052//语言ID
}
这

里给出PHP的示例代码:

<?php
/*
封装金蝶K3cloud webapi;
author:王志锋
email:wangzhifeng@tongdog.com.cn*/
namespace kingdeeapi;class kingdeeapi {private $username;private $password;private $apiurl;private $acctID;//构造函数,初始化public function __construct($username, $password, $apiurl, $acctID) {$this->username = $username;$this->password = $password;$this->acctID = $acctID;$this->apiurl = $apiurl;$this->cookie = $this->getcookie();}//登陆接口获取cookieprivate function getcookie() {$apiurl = "https://" . $this->apiurl . "/k3cloud/Kingdee.BOS.WebApi.ServicesStub.AuthService.ValidateUser.common.kdsvc";$logindata = array("acctid" => $this->acctID,"username" => $this->username,"password" => $this->password,"lcid" => 2052,);$postdata = json_encode($logindata);$result = $this->httpRequest($apiurl, $postdata, false);}//http请求public function httpRequest($url, $post_content, $isLogin = true) {//cookie文件//$cookie_jar = tempnam('/Applications/XAMPP/xamppfiles/temp/', 'cookie');$ch = curl_init($url);$this_header = array('Content-Type: application/json','Content-Length: ' . strlen($post_content),);curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');curl_setopt($ch, CURLOPT_HTTPHEADER, $this_header);curl_setopt($ch, CURLOPT_POSTFIELDS, $post_content);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);//curl_setopt($ch, CURLOPT_HEADER,true);if ($isLogin) {curl_setopt($ch, CURLOPT_COOKIEFILE, "/Applications/XAMPP/xamppfiles/htdocs/law/simplewind/extend/kingdeeapi/cookie.txt");} else {curl_setopt($ch, CURLOPT_COOKIEJAR, "/Applications/XAMPP/xamppfiles/htdocs/law/simplewind/extend/kingdeeapi/cookie.txt");}curl_setopt($ch, CURLOPT_TIMEOUT, 30);$result = curl_exec($ch);curl_close($ch);return $result;}

在httpRequest方法里对cookie做了处理,如果是登陆接口,则把获取到的cookie写入文件,如果是调用其他接口,则送cookie.txt中读取cookie,登陆接口并不能做任何事情,只是为了获取使用其他接口的cookie。
其他接口的使用,跟登陆接口差不多,data数据包里必须包含formid,要操作表单的ID,JSON数据包里的字段多到吓人,特别是保存接口,甚至多到上百项,好在是必录的参数不是很多,根据企业要求,构建相应的JSON数据包就可以,我一般是构建一个最完整最全的数组,然后把其他的字段都对应上,如果某值不存在则赋空值,这样保证不用频繁修改数据包,字节改数组就可以,而数组可以保存在数据库里,直接调整数据库就可以,避免修改源码,这里给出一个客户的数据包示例:

$customerdata = array("formid" => "BD_Customer","data" => array(/*"Creator" => "","NeedUpDateFields" => [],"NeedReturnFields" => [],"IsDeleteEntry" => "true","SubSystemId" => "","IsVerifyBaseDataField" => "false","IsEntryBatchFill" => "true","ValidateFlag" => "true","NumberSearch" => "true","InterationFlags" => "","IsAutoSubmitAndAudit" => "false",*/"Model" => array("FCUSTID" => 0,"FCreateOrgId" => array("FNumber" => "603",),"FNumber" => $customerinfo["field_fnfcA__c"],"FUseOrgId" => array("FNumber" => "603",),"FName" => $customerinfo["name"],"FShortName" => "","FCOUNTRY" => array("FNumber" => "China",),"FPROVINCIAL" => array("FNumber" => "",),"FADDRESS" => "","FZIP" => "","FWEBSITE" => "","FTEL" => "","FFAX" => "","FCompanyClassify" => array("FNumber" => "",),"FCompanyNature" => array("FNumber" => "",),"FCompanyScale" => array("FNumber" => "",),"FINVOICETITLE" => "","FTAXREGISTERCODE" => "","FINVOICEBANKNAME" => "","FINVOICETEL" => "","FINVOICEBANKACCOUNT" => "","FINVOICEADDRESS" => "","FSUPPLIERID" => array("FNumber" => "",),"FIsDefPayer" => "false","FGROUPCUSTID" => array("FNumber" => "",),"FIsGroup" => "false","FCustTypeId" => array("FNumber" => $customerinfo["field_n5V1I__c"],),"FGroup" => array("FNumber" => $customerinfo["field_IdOci__c"],),"FTRADINGCURRID" => array("FNumber" => "PRE001",),"FCorrespondOrgId" => array("FNumber" => "",),"FDescription" => "","FSALDEPTID" => array("FNumber" => "",),"FSELLER" => array("FNumber" => "",),"FSETTLETYPEID" => array("FNumber" => "",),"FRECCONDITIONID" => array("FNumber" => "",),"FDISCOUNTLISTID" => array("FNumber" => "",),"FPRICELISTID" => array("FNumber" => "",),"FTRANSLEADTIME" => 0,"FInvoiceType" => "1","FTaxType" => array("FNumber" => "SFL02_SYS",),"FRECEIVECURRID" => array("FNumber" => "",),"FPriority" => 1,"FTaxRate" => array("FNumber" => "SL02_SYS",),"FISCREDITCHECK" => "true","FIsTrade" => "true","FT_BD_CUSTOMEREXT" => array("FEntryId" => 0,"FEnableSL" => "false","FFreezeLimit" => "","FFreezeOperator" => array("FUserID" => "",),"FFreezeDate" => "1900-01-01","FPROVINCE" => array("FNumber" => "",),"FCITY" => array("FNumber" => "",),"FDefaultConsiLoc" => array("FNUMBER" => "",),"FDefaultSettleLoc" => array("FNUMBER" => "",),"FDefaultPayerLoc" => array("FNUMBER" => "",),"FDefaultContact" => array("FNUMBER" => "",),"FMarginLevel" => 0,"FDebitCard" => "","FSettleId" => array("FNUMBER" => "",),"FChargeId" => array("FNUMBER" => "",),),"FT_BD_CUSTLOCATION" => [array("FContactId" => array("FNUMBER" => "",),"FIsDefaultConsigneeCT" => "false","FIsCopy" => "false",),],"FT_BD_CUSTBANK" => [array("FENTRYID" => 0,"FCOUNTRY1" => array("FNumber" => "",),"FBANKCODE" => "","FACCOUNTNAME" => "","FBankTypeRec" => array("FNUMBER" => "",),"FTextBankDetail" => "","FBankDetail" => array("FNUMBER" => "",),"FOpenAddressRec" => "","FOPENBANKNAME" => "","FCNAPS" => "","FCURRENCYID" => array("FNumber" => "",),"FISDEFAULT1" => "false",),],"FT_BD_CUSTCONTACT" => [array("FENTRYID" => 0,"FNUMBER1" => "","FNAME1" => $customerinfo["field_zW12m__c"],"FADDRESS1" => "","FTRANSLEADTIME1" => 0,"FMOBILE" => $customerinfo["field_G45nC__c"],"FIsDefaultConsignee" => "false","FIsDefaultSettle" => "false","FIsDefaultPayer" => "false","FIsUsed" => "false",),],"FT_BD_CUSTORDERORG" => [array("FEntryID" => 0,"FOrderOrgId" => array("FNumber" => "",),"FIsDefaultOrderOrg" => "false",),],),),);

一个小技巧,比如单据查询接口,根本没有写字段,这时候可以去保存接口里找。
本文到这里基本就已经结束了,能够熟练的使用双方API接口后,根据业务逻辑去实现就可以了。如果有类似需求,可以一起交流学习,文中若有不对之处,还望指正,谢谢阅读!
Author:王志锋
Email:wangzhifeng@tongdog.com.cn

基于纷享销客开放平台,实现纷享CRM与金蝶云星空系统数据同步相关推荐

  1. 纷享销客荣获“2022医疗健康行业CRM数字化最佳服务商”

    9月21日,"2022医药&医疗器械数字创新大会"在上海召开,大会以"智慧医疗 赋能健康"为主题,集结了医疗器械.生物医药等行业头部企业及专家,共同探讨 ...

  2. 如何利用开放平台把金数据采集的表单数据生成纷享销客销售线索?

    适用场景: 公司在微信公众号里发起了一个营销活动,用金数据做活动报名的表单,每一个报名的粉丝,可能都是一个潜在的客户.正常情况下,只有金数据的账号管理员能看到数据,要么导出Excel文件,这时候如果能 ...

  3. 同步纷享销客CRM合同数据至E签宝,实现全程无感完成电子合同签署!

    最新消息:纷享销客与E签宝官方已经合作,目前正在进行技术推进,纷享会以系统集成的方式使用E签宝. 一.纷享销客简介 纷享销客是连接型CRM优质服务商.纷享销客连接型CRM以开放的企业级通讯为基础架构, ...

  4. textarea实现datalist效果_同步纷享销客CRM合同数据至E签宝,实现全程无感完成电子合同签署!...

    最新消息:纷享销客与E签宝官方已经合作,目前正在进行技术推进,纷享会以系统集成的方式使用E签宝.1纷享销客简介 纷享销客是连接型CRM优质服务商.纷享销客连接型CRM以开放的企业级通讯为基础架构,以连 ...

  5. 纷享销客CRM集成用友畅捷通T+Cloud

    一.为什么要把CRM和ERP数据打通? 畅捷通是用友的龙头产品,占有ERP市场的很大规模,如果公司同时在使用纷享销客CRM和畅捷通,把两套系统数据打通,绝对是非常明智的决策!这样做的优势有以下几个方面 ...

  6. 纷享销客事件变更订阅接口到底怎么用?

    纷享事件变更订阅是一种数据事件主调的服务能力,用户可以通过在纷享侧订阅事件的方式,来监听数据的变化,从而能够以一种很轻量级的方式就能达到几乎近实时的数据同步的效果. 在纷享销客开放平台推出这个接口(2 ...

  7. 销售易和纷享销客的“生存经”

    配图来自Canva可画 数字化时代之下,企业为了进一步实现开源节流.降本增效的目标,不断加大内部运营的IT投入,促使企业销售.市场.服务等部门逐渐走向IT化.得益于此,作为专业客户关系管理的CRM软件 ...

  8. 纷享销客2019销售增长大会:连接型CRM赋能企业数字化未来

    10月24日,主题为"赋能企业数字化未来"的纷享销客2019销售增长大会在北京富力万丽酒店召开.来自全国各地制造业.高科技.快消品等行业的300余位用户嘉宾,就数字化时代企业如何利 ...

  9. 【观察】纷享销客:中国SaaS CRM市场的“破壁人”

    申耀的科技观察 读懂科技,赢取未来! 电影<斗士>中,有这么一句台词令人印象深刻:"知道路要怎么走,和走上这条路,是有区别的." 确实如此,如果以此形容中国SaaS C ...

最新文章

  1. 炸裂!微软重磅推出混合现实平台 Mesh、基于 Excel 的低代码语言 Power Fx,Ignite 2021 太精彩!...
  2. 这个Python库可以偷懒,和import说再见!
  3. C#: static关键字的作用
  4. 加密和解密.net配置节
  5. 机器学习(二)Logistic回归(Logistic regression)算法
  6. OpenVINO Inference Engine之custom Layer自定义算法(VPU版本)
  7. 西方主要管理思想简介
  8. 笔记本AutoCAD启动时闪退怎么办_cad启动时闪退怎么办
  9. spriteKit 笔记三 —— Drog 精灵
  10. 倒杨辉三角4行c语言,倒杨辉三角
  11. 期货日内交易如何判断方向
  12. 5.Lucene 基本原理(六)字典实现原理 FST(Finite State Transducer)
  13. 史上最全无线通信频率分配表
  14. CountDownLatch--等待多线程计数器
  15. 计算机等级分图表,计算机二级Office:Excel模拟分析和图表知识点讲解
  16. SSM开发笔记-尚硅谷-佟刚-Spring4.0.0
  17. python大学生信息管理系统_基于Python的高等学校社团信息管理系统
  18. Vue刷新、跳转页面的数据保存方法: sessionStorage + Object.assign()
  19. java并发编程 笔记八
  20. [Java] MVC 编写程序计算净现值 2020.2.25 Java

热门文章

  1. 幕墙LED透明屏幕哪些公司在做?玻璃幕墙LED显示屏排行榜
  2. OpenCV去除绿幕 抠图
  3. warning C318:can‘t open file `STC89C5xRC.H‘
  4. 遥感学习笔记(五)——Landsat卫星简介
  5. ktkkt的视频怎么下载
  6. STM32 W5500 HTTP Server 微型web服务实现
  7. pojo、vo、dto、entity都是什么
  8. 关于AnyChat录像解决方案的几张原理图
  9. 还在为PPT烦恼?有了这四大高质量的PPT模板网站,1秒做出精美PPT
  10. faster rcnn源码解析