行业资讯

外呼系统和客户管理系统怎么对接?从拨号到落库要过的六个字段,线路侧最容易漏记的两项记录,以及对接后怎么当场验证

2026-10-26助销云运营团队171 次阅读

自有系统生产库的通话记录表一共 18 列。拿外呼系统对接必须过的六个字段去对——主叫号、被叫号、开始时间、通话时长、挂机原因、录音标识——能对上的只有四个:被叫号(phone)、开始时间(started_at)、时长(duration_sec)、录音标识(oss_key 与 recording_sync)。主叫号和挂机原因,这两列在表里根本不存在。

再往里看一层,1400 通记录里,已接通的 649 通六项基本齐全,只有 13 通没有录音;问题全压在未接通的 751 通上:746 通时长写 0、114 通连结束时间都没有、709 通没有任何录音。同一张表、同一个接口,接通的电话是完整的,没接通的电话是残缺的——这不是程序写错了,是对接时只按「成功那一路」设计了字段。

这篇不讲选型,只讲对接:外呼系统把话单推给客户管理系统,中间要过哪几个字段、每个字段线路侧给的是什么、系统里该存成什么、配错了当场能看出什么。文中数字全部来自自有系统生产库实测(2026-10-26),只描述字段与结构,不涉及任何真实客户信息。

一、外呼系统和客户管理系统怎么对接:先看话单落在哪张表、缺哪几列

先把「对接」这个词拆开。线路商那边产生的叫话单(CDR),它记录的是「哪个号打哪个号、什么时候开始、多久、有没有录音」。客户管理系统里要的是业务记录:这条通话属于哪个客户、哪个坐席、这次沟通有没有推进阶段、下次什么时候跟。两者不是一张表的事,中间必须有一层映射。

映射做得好不好,判据很土:把话单字段清单和你的表列清单左右排开,能不能一一对上。本库这张表 18 列,逐列点名是:id、tenant_id、employee_id、phone、direction、duration_sec、started_at、ended_at、oss_key、recording_size、recording_sync、transcript_status、client_uid、created_at、updated_at、customer_id、call_type、result_status。里面有坐席(employee_id)、有方向(direction)、有客户(customer_id)、有录音三件套(oss_key / recording_size / recording_sync)、有转写状态(transcript_status),但没有主叫号、没有挂机原因、没有呼叫流水号、没有挂机方、没有线路标识。

为什么会这样?因为这张表最初是为「坐席在 APP 里打电话」设计的:号码是坐席端的电话打出去的,主叫就是这个坐席,不需要记;挂没挂、谁挂的,客户端自己知道,也不需要从线路侧拿回来。一旦换成线路侧对接(SIP 中继、云线路 API、话机加网关),这三个「客户端自己知道」的东西就变成了「必须由外部告诉我」,而表里没有地方放。

三条接入通道拿到的东西差别很大,这是第一个要拍板的选择:

① SIP 中继直连。你自己起一套呼叫系统去注册中继,话单自己生成,字段最全(可以拿到振铃、应答、挂机三段事件和挂机方),代价是你要自己维护注册、心跳、并发和录音落盘。适合坐席规模稳定、有运维的团队。

② 云线路 API。线路商把话单 POST 给你,你只管收。字段由对方定义,通常有呼叫流水号、主叫、被叫、开始、结束、时长、状态码、录音地址,但挂机方经常不给,录音地址有时是带时效的临时链接。适合不想碰底层、按量付费的团队。

③ 话机加网关。坐席用实体话机,网关把话单转成一条 HTTP 或文件给系统。这种最容易出「只有一半字段」:网关厂商默认只推计费字段(主被叫、时长、费用),业务字段要单独开。

这一节的验收动作:向线路商要一份样例话单(不是字段文档,是一条真实记录的脱敏样例),把每个字段标成三种状态——已落、未落、落了但空。三种状态的数量,就是你对接工作量的大小。

外呼系统对接的六个字段对照:线路侧给什么、本库现状如何、缺了会怎样

二、主叫号与被叫号:两个号码口径不先对齐,后面全是脏数据

号码是话单里最基础的两个字段,也是最容易在半年后才发现有问题的地方。先说本库的现状:1400 通记录的号码字段,长度全部是 11 位(1400/1400),没有一条带星号,没有一条带 +86 或 0086 前缀。干净得出奇。

干净的原因不是设计得好,是只有一个来源。号码全部由坐席端从客户档案取出来再拨,取的时候已经是规范化的 11 位,写回去自然也是 11 位。这种「干净」在接第二条线路的那天就会破功——不同线路商给的格式不一样:有的带 +86,有的带 0086,有的中间带空格或连字符,有的把中间四位打成星号,有的对虚拟号段返回的是映射后的号码。

所以号码这一关要做四件事,顺序不能反:

第一步,剥。去掉所有非数字字符(空格、连字符、括号、加号),只留 0-9。这一步做完,长度才有可比性。

第二步,归一。把 0086 和 86 开头统一成不带前缀,只留 11 位。别在这一步做「智能判断」——比如把 10 位自动补 0,那会把真正的错误号码变成看起来正确的号码,比报错更难查。

第三步,校验。长度不等于 11 的,不要静默丢弃,要落一条「号码异常」记录:原始值、来源线路、时间。丢弃等于把问题藏起来,一个月后你只会看到「接通率突然掉了」,找不到原因。

第四步,留原样。规范化后的值存主字段,原始值另外存一列。这一列的作用是对账:当线路商账单和你的记录对不上时,能拿原始值去比,而不是拿已经被你改过的值去比。

主叫号这边还有三件事必须落,缺一件就查不清责任:

中继号(对外显示的那个号)——客户手机上看到的是它。客户投诉「你们用私人号骚扰我」,指的就是这个号。

坐席号(分机或软电话身份)——真正打电话的人。它和中继号是多对一关系,一个中继号后面可能挂十几个坐席。

号码类型(固话 / 手机 / 中间号 / 虚拟号)——这个字段决定了两件事:能不能回拨、要不要做号码保护。中间号是要过期回收的,过期后客户回拨就是空号,这类投诉在没有号码类型字段的系统里永远解释不清。

本库连主叫号都没有,所以现在只有一个 phone 字段,语义上等于「被叫」。这不影响现在的使用(坐席端拨号,主叫就是坐席登记的号),但一旦接入线路侧,同一张表里就要同时装「客户号码」和「显示号码」,不分开必然混。

这一节的验收动作:拿三家不同线路各打一通电话,然后把三条记录的号码字段抓出来比对。三条都是 11 位纯数字,才算这一关过了;只要有一条带前缀或带星号,就说明规范化那一步还没做。

三、开始时间与通话时长:114 通没有结束时间,账就算不平

时间字段看起来最没有争议,实际上是口径最多的一处。先把本库实测摊开:已接通的 649 通,开始时间和结束时间全部有值,时长也全部大于 0;未接通的 751 通里,114 通没有结束时间(占全部记录的 8.1%),746 通时长是 0。

这里有个细节值得单独拎出来:未接通 751 通里,有 746 通时长是 0,那就意味着还有 5 通「未接通」却有通话时长。5 通不多,但它暴露了一件事——「未接通」这个结论不是线路给的,是系统自己判的。继续查表结构就明白了:这张表里表示通话结果的只有 result_status 一个字段,取值只有两个(未接通 751、已接通 649),而 call_type 字段的取值 2 和 1 与它们完全一一对应(751 对 2、649 对 1)。两个字段互为镜像,说明 result_status 只是 call_type 的显示层,它不是挂机原因,也没有携带任何线路侧的状态信息。

所以时间这块要落三个时间点,不是一个:

① 发起时间 / 振铃时间。坐席点下拨打的那一秒。用它算「坐席一天按了多少次」,是产能口径。

② 应答时间。客户接起来的那一秒。用它算「平均等待多久才被接」,是体验口径。没有应答时间的系统,只能拿发起时间当开始时间,于是所有「响铃 40 秒才接」的记录都会把等待时间算进通话时长里。

③ 挂机时间。通话结束的那一秒。用它算时长和工时。

本库只有 started_at 和 ended_at 两个时间点,中间缺「应答时间」,而 ended_at 在 114 通未接通的记录里是空的。这 114 通对应的业务事实是「拨了、没通、也不知道响了多久」——它们既不能算进工时,也不能算进客户等待,只能算「拨号次数」。如果你的报表把这些记录和接通记录混在一个「平均通话时长」里算分母,结论一定是错的:114 通时长按 0 处理,会把平均值往下拽。

还有两个坑要提前定,都在对接协议里写清楚:

坑一:话单延迟。云线路 API 的话单通常不是实时的,接通结束到收到话单可能有几秒到几分钟的间隔,部分线路在长时间通话结束时会延迟更久。这意味着「实时看板」上的通话数永远是偏低的,正确的做法是把看板分成两层:实时层只看「发起数」(客户端自己就能算),结算层看「话单数」(以线路为准)。两层对不上是正常的,对不上超过阈值才要报警。

坑二:时长用谁的。线路侧给的是计费时长(从应答到挂机,按整分钟向上取整的也有),客户端记的是通话时长(从接通到挂断,精确到秒)。两个值不会相等。定规则的办法很简单:算钱用线路的,算人用客户端的,并且在字段说明里写死,别让两个报表各引一个。

这一节的验收动作:随机抽 10 通电话,逐条看三件事——结束时间是否有值、时长与「结束减开始」是否相差在 2 秒以内、以及有没有「未接通却有时长」这种自相矛盾的记录。第三条最有用,它能直接告诉你 result_status 到底是线路给的还是本地判的。

四、挂机原因:线路商码表各不相同,先建一张映射表

挂机原因是外呼对接里最容易被跳过的一项,因为它在「一切正常」的时候完全没用。只有当你需要回答下面这类问题时,它才变成必需品:为什么这个坐席的接通率只有 12%、为什么这批名单打了两轮还是没人接、为什么客户说「你们天天打我」而你的记录里只打过一次。

本库没有这一列。能拿来代替的只有 result_status(接通/未接通)和 call_type(1/2),两个都是二值,连「客户挂的还是坐席挂的」都分不出来。这不是缺陷,是阶段问题:纯客户端拨打时,挂机方客户端自己知道,不需要存;对接线路后,这个信息只有线路知道。

要做这件事,先接受一个事实:没有两家线路商的挂机码表是一样的。同样是「对方无人接听」,A 家可能返回 486,B 家返回一个字符串「NO_ANSWER」,C 家返回业务码 1003。同样是「空号」,有的线路返回独立码,有的线路直接归到「呼叫失败」。所以正确做法不是「统一码表」,而是建一张映射表,把每家线路的原始码翻译成你自己的内部枚举。

映射表就三列:线路商、原始码(含原始描述)、内部枚举。内部枚举建议控制在 10 个以内,够用就行:

客户挂机(接通后客户先挂)、坐席挂机(接通后坐席先挂)、无人接听(响了没人接)、忙线、关机、停机空号、拒接、线路失败(中继不可用、并发打满、鉴权失败)、超时未应答、其他。

这 10 个值为什么要这么分?因为它们对应完全不同的管理动作。「客户挂机 + 通话 3 秒」是话术问题,要抽听;「坐席挂机 + 通话 3 秒」是态度问题,要面谈;「无人接听」是名单质量问题,要换批次;「线路失败」是技术问题,要报障。四类问题混在一个「未接通」里,管理层能做的只有一件事——全员开会。

映射表落地的两个细节:

一是「未映射」要留出口。映射表的最后一档必须是「其他」,并且带原始码原文。线路商新增一个码的时候,你的系统不能报错、不能丢话单,只能把它归到「其他」并报警。这样你能在一周内发现码表变了,而不是在季度复盘时发现「某类挂了 30% 但不知道是什么」。

二是换线路商时旧数据不能断。映射表里要存线路商标识,历史记录保留当时的原始码和当时的内部枚举。不要用「当前映射」去回算历史数据,那会让三个月前的报表在换线路那天悄悄变形。

这一节的验收动作:向线路商索取全量码表(不是常用码,是全量),逐条映射一遍,最后统计「未映射条数」。这个数必须是 0 才能上线;上线后再跑一周,看「其他」这个枚举的占比,超过 5% 说明码表没拿全。

五、录音标识:话单与录音文件靠什么配对

录音这块本库的数据是自洽的:1400 通里 678 通有 oss_key,同时有录音大小(recording_size)的也是 678 通,两者没有一条错位;没有 oss_key 的 722 通,录音大小也为空。也就是说,「有文件」和「有文件元信息」这两件事在本库是一起发生的,没有出现「有地址没大小」或「有大小没地址」的脏数据。

再看分布:已接通 649 通里 636 通有录音、13 通没有;未接通 751 通里 42 通有录音、709 通没有。已接通的录音率是 98%,未接通的是 5.6%。未接通也录了音这件事很正常——响铃阶段的声音也会被录下来,其中一部分能用来判断「是空号提示音还是真的没人接」。这 42 通是排查名单质量的好材料,别当垃圾清掉。

真正要设计的是配对:一段录音文件,怎么确定它属于哪一通电话?三种做法,只有一种可靠:

按时间配对(不可靠)。拿录音文件的创建时间去话单里找「开始时间最接近」的那条。并发一高就必错——同一秒可能有三通电话在打。

按号码配对(不可靠)。拿录音文件名里的号码去匹配。号码会重复(同一个客户被打过多次),也对不上「第几次」。本库的号码重复情况在别的篇里已经写过,这里不重复。

按呼叫流水号配对(可靠)。录音文件名里带上话单的流水号,回传时用同一个号去关联。前提是你有流水号——而本库这一列没有。这就是为什么第六节要把流水号单独拎出来讲:它不只用于去重,还是录音配对的钥匙。

录音状态也要拆开,别用一个字段表达三件事。本库用的是 recording_sync,取值 uploaded 678 / pending 722。pending 这个词是有歧义的:它既可能是「录了但还没上传」,也可能是「本来就没录」。两种情况的处理完全相反——前者要重传队列去催,后者要查为什么没录(权限没开?存储满了?坐席手动关了?)。建议拆成三个字段:

是否录音(有 / 无,由线路侧或客户端在挂机那一刻决定)、传输状态(待传 / 传输中 / 成功 / 失败,带重试次数)、可播状态(可播 / 文件缺失 / 鉴权失败)。第三个字段最实用:它对应的是「运营点开能不能听到声音」,而不是「数据库里有没有地址」。

还有一个必须提前定的技术细节:录音地址要不要存。云线路给的经常是带签名的临时链接,几小时后就失效;如果你把这个链接直接存进 oss_key,三个月后所有历史录音都点不开。正确做法是存对象键(bucket 里的路径),播放时再换签名链接。判据:把一条三个月前的记录点开,能播,就说明存对了。

这一节的验收动作:抽 10 通有录音的记录,逐条点开播放;再抽 10 通无录音的,逐条说清「为什么没有」。前者验的是可播,后者验的是状态字段有没有撒谎。两条都过,录音这一关才算完。

六、线路侧最容易漏记的两项:呼叫流水号与挂机方

前面四节讲的是「有列但可能空」,这一节讲的是「连列都没有」的两项。它们在线路侧一定有,在系统侧经常丢,丢了以后要过很久才会被发现。

第一项:呼叫流水号。一通电话在发起方生成一个号,全程不变,从拨号到挂机到回传都用它。它的作用有三个:

一是去重。网络抖动、对方重试、或者你同时配了「实时回调」和「定时拉取」两条通路,同一通电话会来两次。没有流水号,第二次就会落成一条新记录,坐席的通话量凭空多一倍。本库没有这一列,现在靠通话记录主键兜底——在「只有一个客户端回传」的时候够用,接第二条线路的那天就会出问题。

二是对账。月底和线路商结账,你按条数、对方按分钟,两边对不上时,唯一能逐条比的就是流水号。

三是录音配对(上一节说过)。

字段设计建议:varchar(64),建普通索引,不做业务主键(不同线路商的号可能撞车,加上线路标识做联合索引更稳)。落库时先按「流水号 + 线路标识」查一次,存在就更新、不存在才插入,这一条规则写进对接文档,能省掉以后 90% 的重复数据排查。

第二项:挂机方。谁先挂的电话。它在四个地方有用:

接通的电话里,客户先挂说明话术没接住(要抽听)、坐席先挂说明在赶量(要看人均日呼上限是不是定太高);未接通的电话里,「客户响一声就挂」和「坐席看没人接就挂」在名单质量判断上完全相反——前者是名单有问题,后者是坐席在刷拨号量。

本库没有这一列,能间接看出来的只有时长:时长极短(比如 3 秒以内)的记录,大概率是某一方秒挂,但是谁秒挂,查不出来。这就是「字段缺失导致归因失效」的典型——数据不缺,结论缺。

字段设计建议:varchar(16),取值 CALLER(客户)/ CALLEE(坐席)/ SYSTEM(系统超时或线路中断)。注意一个反直觉的地方:这里的 CALLER/CALLEE 是站在线路侧视角的,主叫是被叫出去的那个号(客户),所以「客户挂机」对应 CALLER。字段注释里一定要写清视角,否则三个月后没人敢改这段代码。

两项都缺的后果可以叠在一起看:没有流水号 → 重复话单进库 → 通话量虚高;没有挂机方 → 秒挂归因不了 → 只能靠人工抽听。两个问题在规模小的时候都不明显,坐席过 20 人、日呼过 3000 通之后,会同时爆发。

这一节的验收动作:让技术同事做一次「重复回传」测试——同一通电话的回调故意发两次,看库里是一条还是两条。一条就说明幂等做对了;两条就说明既没有流水号也没有幂等键,先补字段再谈别的。

七、对接后怎么当场验证:十通电话与一张对账表

前面六节讲的都是「该有什么字段」,这一节讲「怎么证明它真的在」。方法是设计十通电话,把这十通跑完,字段齐不齐、绑定对不对、录音能不能播,一次全暴露。

十通这么设计,覆盖六种情形:

3 通接通且超过 60 秒——验正常路径,同时能验转写(本库的转写门槛是 60 秒,短于这个不会触发)。

2 通客户秒挂(3 秒内)——验挂机方字段。如果两条记录的挂机方都是空,说明这个字段没接。

2 通无人接听——验挂机原因。这两条应该归到「无人接听」,而不是笼统的「未接通」。

1 通空号或停机——验异常码。这条最容易暴露码表没拿全:线路返回的码如果落在「其他」里,说明映射缺项。

1 通坐席主动挂断——验「坐席挂机」这个枚举能不能出来,同时也是挂机方字段的第二个验证点。

1 通呼入(客户回拨)——验方向字段。本库 1400 通里呼入只有 25 通,比例低但绝不能丢:呼入的客户意向通常比外呼高,落不进系统就是白丢。

十通打完,做一张五列的对账表,逐行填:

第一列,呼叫流水号——有值吗?十通十个号吗?(这一列现在还是空的,填表的过程就是补字段的过程)

第二列,六字段齐全度——主叫号、被叫号、开始时间、时长、挂机原因、录音标识,六项打勾。判据是十通全部六项齐全,不是平均。

第三列,客户绑定——这通电话挂到客户档案上了吗?用客户 ID 绑的,还是用号码回填的?回填的要单独标记,因为号码重复时它会绑错。

第四列,录音可播——点开能听到声音吗?不能播的,原因是什么(文件缺失 / 链接过期 / 权限)?

第五列,与线路商后台一致——登录线路商的管理后台,找到这十通,逐条比:开始时间差多少秒、时长差多少秒、状态一致吗。这一列是唯一能证明「你没记错」的证据。

这张表不是一次性动作。上线首周建议每天抽 10 通、连续跑 5 天;稳定后改成每周抽 10 通。理由很简单:线路侧的字段会变(升级、换供应商、改码表),而你的系统不会主动告诉你它变了——它只会安静地把新字段丢掉。

三个判据,达到才算对接完成:六字段齐全率 100%(十通十齐全)、客户绑定率不低于 98%(允许极少数确实无档案的陌生号)、录音可播数等于有录音的记录数(不能出现「有地址点不开」)。

最后补一句关于顺序的建议:这套字段不要等系统重构再补。补字段是加列,成本很低;补历史数据才是真花钱——已经落库的 1400 通没有流水号,以后永远补不回来,能做的只有「从某一天起新数据是完整的」。所以越早加越好,加完在报表上标一条分界线,比假装历史数据一样干净要诚实得多。

三条接入通道分别能拿到哪些字段:SIP 中继直连、云线路 API、话机加网关

八、外呼系统对接常见问题

外呼系统和客户管理系统对接,一般要多久能跑通?

取决于你选哪条通道,以及要不要补字段。只做「话单能进库、号码能对上」这一层,一两天就够;要做到六个字段齐全、挂机原因归一、录音可播、重复回传不出错,通常要一到两周,其中大部分时间花在向线路商索要码表和样例话单上。真正拖时间的不是写代码,是对方文档里没写的那些默认行为。

能不能不做挂机原因,只用「接通 / 未接通」?

坐席少于 10 人、日呼少于 500 通时可以先将就,因为你能靠人工听出来。超过这个规模就必须做:一是抽听跟不上,二是「未接通」这一档里混着名单质量、话术、线路故障三类完全不同的原因,管理层拿着一个笼统的未接通率做不出任何决定。做映射表的成本其实很低,三列一张表,一次性半天。

线路商说他们有呼叫流水号,但我们系统里没有这一列,怎么补?

加一列 varchar(64) 就行,不要动现有主键。补的时候注意两点:一是新列允许为空(历史数据补不上),二是插入前按「流水号 + 线路标识」查重。历史数据不用回填,回填只能靠猜,猜出来的号会让以后的对账更乱。

录音存在线路商那边,我们只存链接,行不行?

要看链接的性质。带签名的临时链接不行——几小时后就失效,三个月后历史记录全部点不开。正确做法是把录音文件转存到你自己的对象存储,库里只存对象键,播放时再换签名链接。转存还有一个附带好处:线路商换供应商、停服务的时候,历史录音还在你手上。

回到开头那张 18 列的表。它现在能支撑「坐席打电话、系统记一笔」这个用法,但支撑不了「线路侧对接、按通话归因、按通话对账」这个用法。差别不在于代码写得好不好,而在于六个字段里有两个连位置都没有——字段是容器,容器不在,数据来了也只能丢。要查这条链路上还有哪些地方会丢数据,可以顺着看电销助手和客户管理系统怎么打通里客户端那一侧的五步,或者看助贷外呼系统有哪些呼叫方式里三种呼叫方式的差异;如果关心的是录音拿到之后怎么用,通话录音分析怎么做和电销智能质检怎么做接着往下走;名单和拒呼那一层,见助贷AI外呼合规吗;号码重复导致的绑定错误,见助贷线索去重怎么做;客户档案这一侧的整体搭法,见贷款中介客户管理系统怎么搭。版本与接口能力对照可以看价格与版本说明。

十通测试电话的验收单:六种情形各自要核对的字段与合格信号
—— END ——|本文由助销云运营团队发布,禁止转载
外呼系统和客户管理系统怎么对接?从拨号到落库要过的六个字段,线路侧最容易漏记的两项记录,以及对接后怎么当场验证