简介:上海五期医保接口说明文档,是一份指导 HIS 系统对接医保中心系统的技术参考,面向医院信息系统开发、实施与维护人员。文档从引言、业务分析到接口描述逐层展开,涵盖读卡、电子凭证解码、挂号收费请求与确认、登记与撤销、明细上传、住院结算、对账退款、账户及登记查询等医保业务;同时说明了卡类型、账户标志、中心流水号、就诊单元号、明细账单号等关键字段,以及 JSON 返回报文格式和接口方法的入参、出参,便于开发者快速理清对接流程。文档对读卡 ShYbV5_S000、解码 ShYbV5_SE01、挂号 ShYbV5_SH01 等接口的调用方式与返回内容也有具体说明,可直接对照学习。资源为 docx 格式,文件总数 1 个,压缩包大小约 34KB,内容紧凑,可作开发调试时直接查阅的参考。目前已有 1594 人学习浏览,适合正在开发或维护上海医保五期接口的工程师使用。
1. 上海医保五期接口:表面是一堆方法,底层是一套「有状态的账本」
上海医保五期接口对接过的人都有个直觉:方法不多,但每个方法背后都藏着状态。挂号要分请求和确认,收费之前必须先传明细,磁条卡、芯片卡、电子凭证三套身份识别路径完全不同。这套接口号称「黑匣子」,但黑匣子内部并不是无脑转发,它维护着一套严格的生命周期——计算申请序号、就诊单元号、中心流水号、明细账单号,四个号各管一段,任何一个环节没对上,整笔交易就悬在半空。
真正值得搞懂的不是某个方法怎么调,而是这套接口为什么这样设计。它把医保结算拆成「识读身份 → 挂号两阶段 → 明细上传 → 结算确认」的链式结构,每一步都有明确的输入输出和状态转移。这背后是中心系统对业务数据干净度的坚持:不想让每一笔请求都变成正式记录,不想让 HIS 拿不准一笔费用到底成没成立。读完这篇,你会理解为什么 SE01 解码要返回一个令牌、为什么 SH01 和 SH02 必须分开、为什么明细账单号要由中心系统生成——这些设计取舍才是这份文档的真正价值。
2. 从黑匣子到账本:接口方法族背后的调用次序与核心标识
文档对接口的定性是「对主程序而言类似一个黑匣子,只需按照约定调用相应方法即可」。这句话容易让人误以为方法之间彼此独立、想调哪个调哪个。实际拆开看,这套接口是一组有严格时序约束的方法族,调用顺序错了,后面每一步都会报错。
2.1 黑匣子不黑:方法族的分工与调用链
先把文档里列出的方法按职责分组看。读卡(ShYbV5_S000)和解码(ShYbV5_SE01)解决「病人是谁」;挂号请求(ShYbV5_SH01)和挂号确认(ShYbV5_SH02)解决「这次就诊怎么开始」;明细上传(ShYbV5_SN01)、收费请求和收费确认解决「钱怎么算、怎么落」;对账、退款、交易查询解决「出事了怎么追溯」。
这个分组本身就是一条完整的业务链路。以最常见的门诊收费为例,完整调用顺序是:Init → 读卡或解码 → SH01 挂号请求 → SH02 挂号确认 → 查询费用明细 → SN01 明细上传 → 收费请求 → 收费确认。每一步的输出是下一步的输入。挂号确认返回的就诊单元号(jzdyh)和中心流水号(lsh),要带进后续所有费用操作;明细上传返回的明细账单号(mxzdh),是收费请求的必需参数。这些号就是整条链路上的「接榫」,任何一个没传或者传错,链子就断了。
为什么文档开场就强调「黑匣子」?因为它想让 HIS 方不用关心中心系统内部怎么算账,但前提是 HIS 必须把约定的输入给全、给对。黑匣子只是掩盖了内部算法,并没有豁免调用方的时序责任。
2.2 卡类型与身份识别:三种卡三种路径,最后都汇聚到 cardtype + carddata
卡类型是理解整套接口的第一把钥匙,芯片卡 1、磁条卡 0、电子凭证 3。三种类型的差异不仅是读卡方式不同,而是信息获取的链路完全不同。
芯片卡插读卡机后调 ShYbV5_S000,一次拿回病人完整基本信息——卡号、姓名、性别、身份证号、联系电话、通讯地址、邮政编码、行政区域代码。因为芯片卡内部存了结构化参保数据,读卡机能一次性读出全部,HIS 不需要再拼凑信息。
磁条卡只有 28 位,刷卡直接拿卡号,拿到的只是一个身份索引,后续要换完整信息得靠这个卡号去中心系统查。注意文档里的用词:磁条卡「直接在读卡机上进行刷卡操作即可获取病人卡号」——它没提要不要调某个方法,含义是磁条卡场景下 HIS 自己拿到卡号就够了,卡号本身就是 carddata。
电子凭证(类型 3)是最特殊的路径。支付宝、微信、随申码渠道拿到二维码后,必须调 ShYbV5_SE01 解码,返回身份证信息和 ecToken。这里的关键设计是:二维码本身不是身份凭证,只是获取身份信息的「钥匙」。SE01 之后,真正在交易里使用的不是二维码,而是解码得到的 ecToken 令牌。后续 SH01 的 carddata 参数,在电子凭证场景下填的就是这个令牌。
2.3 参数传递的隐性约定:为什么电子凭证非要一个令牌
顺着电子凭证的链路往下想,会碰到一个值得琢磨的问题:SE01 已经返回了身份证号,为什么后续交易还要用一个 63 位的 ecToken,而不是直接用身份证号?
两个原因。第一,二维码是公开展示的,谁都能扫。如果拿到二维码就等于拿到交易凭证,那病人任何一次扫码都等于把医保身份公开了一回。SE01 的作用是把「码」和「人」绑定,并生成一枚有时效、可撤销、可绑定场景的会话令牌。第二,医保交易需要防重放——同一个二维码不能反复用于多次结算。ecToken 的设计让中心系统可以精确控制「这次扫码换来的身份只能在当次会话里用」,既保证身份真实,又限制了使用范围。
这带来的工程要求是:HIS 端拿到 ecToken 后要妥善保管,不能写进日志,不能进前端页面,不能随 URL 传递。这是对接电子凭证时最容易被忽视的安全边界。
3. 医保结算的核心账本:支付段、账户标志与字段边界
从支付段入手看这套接口,就会发现医保结算本质上是一个分层账户系统。文档里那句「先用当年账户,再用历年账户,再进入自负段」的描述,翻译成系统设计,就是一套五层漏斗式的资金支付模型。
3.1 支付段:五层漏斗怎么决定每个人付多少钱
门诊(普通)的规则:先用当年账户,再用历年账户,进入自负段累计,累计满后按医院级别一、二、三分别自负 10%、15%、20%,其余医保支付。这五个阶段对应五个不同的资金来源和触发条件:
| 支付段 | 资金来源 | 触发条件 |
|---|---|---|
| 当年账户段 | 个人当年账户 | 账户有余额即优先支付 |
| 历年账户段 | 个人历年账户 | 当年账户余额不足后启用 |
| 自负段 | 个人现金 / 历年账户抵充 | 自负累计未达起付线时 |
| 统筹段 | 统筹基金 | 自负段累计满后按比例分担 |
| 附加段 | 地方附加基金 | 统筹支付封顶线以上部分 |
这里的关键是「自负累计」这个概念。累计是跨次就诊的,不是每次结算清零重算。中心系统内部维护每个参保人的历史累计数据,HIS 不需要自己记账,但每次结算时中心系统会根据这个人的累计状态实时计算返回。这也是为什么挂号请求必须传 accountattr(账户标志)——中心系统靠这 16 位编码识别人员类别,查出这个人累计到哪个段了。
SH01 返回的一长串金额字段就是这五层漏斗的输出:curaccountpay(当年账户支付数)、hisaccountpay(历年账户支付数)、zfdxjzfs(自负段现金支付数)、zfdlnzhzfs(自负段历年账户支付数)、tcdzhzfs(统筹段账户支付数)、tcdxjzfs(统筹段现金支付数)、tczfs(统筹支付数)、fjdzhzfs(附加段账户支付数)、fjdxjzfs(附加段现金支付数)、fjzfs(附加支付数)。每个字段名精确对应一个支付段和一个资金来源。
3.2 字段边界:哪些由 HIS 填,哪些由中心返回,填错的代价是什么
把文档里的参数字段按角色划分,只有三类。
第一类是身份凭证类:cardtype、carddata、ecToken。chip 卡插卡后调 S000 拿卡号,磁条卡刷卡直接拿 28 位卡号,电子凭证扫码后拿身份证和令牌。这类字段填错,中心系统直接拒绝交易。
第二类是业务上下文类:deptid、yllb、dbtype、personspectag、gsrdh。这些字段描述「这次就诊属于什么场景」。最容易填错的是 dbtype。它是单字符编码:1 化疗、2 放疗、3 血透、4 腹透、6 肾移植抗排异、7 同位素治疗、8 介入治疗、9 中医药治疗、A 精神病。这个编码直接决定费用走哪条大病支付路径——血透病人漏填 dbtype,费用会按普通门诊待遇结算,个人负担比例完全不对。
第三类是金额类:totalexpense、ybjsfwfyze、fybjsfwfyze、jmbz。totalexpense 是交易费用总额,ybjsfwfyze 是医保结算范围总额,fybjsfwfyze 是非医保结算范围总额。三者关系是 totalexpense 应等于 ybjsfwfyze 加 fybjsfwfyze(非医保范围费用可能有自费部分)。如果 HIS 把医保结算范围外的金额也塞进 ybjsfwfyze,中心系统不会纠正你,它会按你报的范围计算,结果就是病人多付或少付,对账时一定出问题。
jmbz(享受社区减免标志)最容易被忽略。它只有 0 和 1 两个值。这个标志不是 HIS 能自己决定的——病人是否在社区签约、是否属于减免对象,由中心系统维护。正确的做法是 HIS 在挂号前先通过账户查询把减免状态查出来,按查询结果填 jmbz,而不是让操作员手工选择。
3.3 避坑:医保接口对接的五个常见翻车现场
这里的五条踩坑记录,基本是每次对接这套接口都会遇到的高频问题,按「现象 → 原因 → 解决」写出来。
现象一:挂号请求成功,确认时返回「计算申请序号不存在」。原因是 SH01 请求和 SH02 确认之间隔了太久,计算申请序号有有效期,超时后被中心系统作废。解决:确认必须紧接着请求,不要在两次调用之间插入人工操作或长时间等待;超时了就重新走 SH01。
现象二:电子凭证扫码后调 SE01 返回成功,但后续交易报「令牌失效」。原因是 ecToken 有效期短,HIS 端把 SE01 结果缓存太久,或者在同一就诊里重复使用了同一个令牌。解决:ecToken 只用于当次会话,用完后重新扫码取新令牌;不要把它当长期凭证缓存。
现象三:明细上传成功后收费请求报「明细账单号不存在」。原因是 SN01 返回的 mxzdh 没正确传进收费请求,或者传的时候被截断。解决:mxzdh 虽是字符串类型但可能很短,要原样传递,不要做任何拼接或格式转换。注意文档说「mxzdh 本次明细上传的明细账单号 字符串 3」,别当成数字处理丢了前导零。
现象四:住院结算金额对不上,医保支付部分比预期少。原因是住院登记的 yllb(医疗类别)传错,费用没按正确类别结算。解决:住院登记前先核对医疗类别编码,尤其是急观、家床、保健这类特殊场景有独立的登记方法,不要用普通住院流程登特殊病人。
现象五:对账时发现同一笔费用在中心系统存在两条记录。原因是 HIS 端网络超时后重发了收费确认,但第一次确认其实已成功,重复确认产生第二笔。解决:收费确认必须带原计算申请序号做幂等控制——重发时带上原序号,中心系统识别为重复请求返回原结果,不新建记录。这也解释了为什么文档里要有交易查询方法:确认前先查一次状态,比盲目重发更安全。
4. 从文档接口到工程落地:初始化、解码与明细上传的实现细节
概念理清了,落到工程层面还有几个方法特别值得细看。Init 的调用时机、SE01 的参数链路、SN01 的嵌套明细结构,这三处是实践中最容易写出 bug 的地方。
4.1 Init 不是一次性初始化:为什么每个独立操作前都要调用
Init 的参数只有三个:操作员编码(czybm)、操作员姓名(czyxm)、交易渠道(jyqd,10 线下、20 线上)。但文档里的说明才是重点:本方法需要在每个独立的操作前调用。
「每个独立的操作」怎么理解?两种错误解读很常见。第一种是程序启动时调一次 Init 就万事大吉,后面所有操作共用一份初始化。第二种是每次调医保方法前都调 Init,把 Init 当成万能前置。两种都不对。
正确的理解是:Init 的作用是绑定当前操作员和交易渠道。挂号窗口的 A 操作员调 Init 后做挂号,B 操作员接班时必须重新 Init,否则医保控件里还是 A 的操作员信息,B 做的所有交易都会记到 A 头上。同样,交易渠道区分线下和线上——线上渠道如果用了 10,中心系统会认为这是线下交易,后续风控和对账都会出问题。
所以 Init 的正确用法是:操作员身份切换或渠道切换时调用。一次挂号流程内操作员没变,不需要重复调。但为了稳妥,很多 HIS 在每笔业务开始时都强制调一次 Init,把三个参数重新写一遍。代价是一次额外初始化开销,换来操作员信息绝对不串号,属于典型的用性能换正确性。
4.2 SE01 解码链路:二维码、身份证、token 三者怎么串起来
SE01 的完整参数值得逐一看。入参是 ecQrcode(电子凭证二维码值)、ecQrChannel(获取渠道:1 支付宝、2 微信、3 随申码)、businessType(用码业务类型)、officeId(医保科室编码)、officeName(医保科室名称)。返回是 username、idno、idtype、ecToken。
这条链路的本质是「码 → 人 → 令牌」。二维码本身不包含敏感信息,它只是一个凭证索引。SE01 拿着这个码去中心系统换身份证信息和一枚临时令牌。中心系统验证二维码有效后,返回 idno 和 ecToken。之后 HIS 拿着 ecToken 当身份凭证用——SH01 的 carddata 在电子凭证场景下填的就是 ecToken,而不是二维码内容。
为什么要多这一层解码?因为电子凭证体系没有「卡号」概念,病人的医保身份绑定在身份证上。但身份证号是永久且敏感的,不能每次交易都明文传输。ecToken 作为会话凭证,有时效、可撤销、可限定用途。中心系统可以通过 ecToken 判断一笔交易是否属于同一个就诊会话,也可以在异常时单独吊销令牌,不影响病人整体医保身份。
工程上的坑是:ecToken 是 63 位字符串,很多团队把它当普通字符串打日志、写缓存,这是对接电子凭证时最危险的习惯。令牌泄露等于把病人医保身份交给别人,所有涉及 ecToken 的存储和日志输出都要做脱敏或屏蔽。
4.3 SN01 明细上传:嵌套明细结构的构造与金额精度控制
SN01 是文档里最复杂的方法。它要求 HIS 先提供一个查询病人费用明细的接口(文档建议用 webservice,返回 json 字符串),然后调 SN01 把明细上传给中心系统。整个参数结构包含一个循环体 xfmx,支持细分明细嵌套。
// detailQueryService 是 HIS 侧的明细查询服务 const detailList = await detailQueryService.query({ djh: "MZ20231001" }); const body = { djh: "MZ20231001", jzdyh: "JZ123456", jslxbz: "120", mxzdh: "", details: detailList.map(item => ({ xh: item.xh, cfh: item.cfh, deptid: item.deptid, mxxmbm: item.mxxmbm, mxxmmc: item.mxxmmc, mxxmsl: item.mxxmsl, mxxmje: item.mxxmje, bxbz: item.bxbz, xfmx: item.sfxfmx === "1" ? [{ xh: item.subXh, mxxmbmzl: item.subMxxmbm, mxxmmczl: item.subMxxmmc, mxxmslzl: item.subMxxmsl, mxxmjezl: item.subMxxmje, bxbzzl: item.subBxbz }] : [] })) }; const response = await ybGateway.uploadDetail(body); const detailBillNo = response.mxzdh;这段代码有几个关键点。xh(序号)从 1 开始,在一个明细账单内唯一,由 HIS 本地生成。中心系统依靠这个序号识别每条明细,如果明细被拆成细分明细(sfxfmx=1),父级 xh 和子级 xh 的关系靠「mxxmbmzl 对应上一层明细序号」这个字段关联。子明细有自己的编码、名称、数量、金额,父级金额应该是子级金额之和——中心系统按子级明细完成报销判断,父级只是汇总,所以父级的 mxxmje 与子级 mxxmjezl 的合计必须相等,否则对不上账。
金额精度是另一个高频踩坑点。文档里所有金额字段都是「数字格式」,但传输时按字符串处理。如果 HIS 端用浮点数计算金额,单价 0.1 元、数量 3,浮点算出 0.30000000000000004,传上去就是错的。正确做法是把金额按分来计算,四舍五入后转字符串。我一般在服务端统一一个价格计算函数,杜绝所有浮点运算。
还有一个容易犯的错:bxbz(报销标志:0 可报销、1 不可报销、2 定额)和 sftfbz(收费退费标志:1 收费、2 退费)。退费明细的报销标志和收费明细可能不同——退费项目的可报销属性必须按原收费明细一致,否则中心系统会把退费金额算进错误的报销范围里。
4.4 返回报文解析:为什么 string + JSON 能省掉一半对接工作量
文档明确说:所有返回 string 类型的方法统一用 JSON 格式。比如 S000 返回的是一段 JSON:{"kh":"Z59898D78","xm":"test","xb":"1","sfzh":"31000119500417017","lxdh":"13333333333","txdz":"上海市闵行区虹梅路","yzbm":"","xzqh":"310000"}。
这个设计的选择很聪明。传统医保接口常用定长字符串,前 2 位是返回码、3-20 位是卡号、21-30 位是金额,每次都要写按位置截取的解析器,字段顺序升级就全作废。JSON 的好处是字段名自描述、顺序无关、嵌套结构天然支持——SN01 的明细循环体在定长报文里实现起来极其痛苦,在 JSON 里只是一个数组。
工程上唯一的坑是 JSON 解析失败的排障。中心系统偶尔会返回一段「看起来像 JSON 但不是 JSON」的文本(BOM 头、单引号、或前面多了调试输出),HIS 端直接抛异常,堆栈信息还不包含报文原文。我的建议是所有医保接口的调用统一走一个封装层,这个封装层做三件事:记录原始报文、解析 JSON、解析失败时把报文前 200 个字符打进错误日志。这三件事能解决掉 80% 的对接期疑难杂症。
再想想为什么是 string 而不是直接返回某种语言对象。HIS 侧技术栈五花八门,PHP、Java、.NET 都有。返回语言特定的对象,跨语言对接就废了。string + JSON 是语言无关的中间格式,任何一种语言都能解析。设计者用一点解析开销,换来了全语言生态的兼容性。
5. 两阶段确认与幂等:请求和确认为什么要分开,流水号为什么不可缺
上海五期接口里最值得讲透的设计,是挂号请求 SH01 和挂号确认 SH02 的分离。这也是计算申请序号存在的意义。
5.1 请求与确认拆开:计算申请序号就是后悔药
SH01 返回计算申请序号(jssqxh,34 位)和记录测号(jlc,12 位)。计算申请序号是每次结算请求时中心系统返回的唯一标识,HIS 可以用它查询交易是否成功。但注意,SH01 只是请求,不是成交。挂号最终成立,要看 SH02 确认。
为什么拆成两段?从中心系统角度看,它不希望每个请求都生成正式业务。如果病人挂完号又取消、或者结算时费用算错,这些「废请求」会污染业务数据。所以 SH01 阶段只做资格校验和费用初算,生成一个临时申请序号;SH02 阶段才正式登记,生成就诊单元号和中心流水号。这是两阶段提交的简化版——先把准备工作做好、资源占住,确认后才正式提交。
对 HIS 来说,这是整个流程里最实用的后悔药。挂号请求成功后,如果操作员发现选错科室、或者病人决定不看了,只要不调 SH02,这笔请求就自然作废,不需要额外撤销。反过来,如果 SH02 已确认,就必须用撤销登记方法去撤销,不能靠「不确认」蒙混过关。
一个容易忽略的点:计算申请序号有生命周期,从 SH01 返回时诞生,到 SH02 确认时失效。如果 SH01 之后没有 SH02,这个序号会一直占着中心系统的「未完成业务」槽位。中心系统一般有超时清理,但 HIS 端不应该指望它——超时后再拿这个序号去确认,会报「计算申请序号不存在」。
再加深一层理解:计算申请序号和中心流水号的区别。计算申请序号是「这笔计算任务的临时 ID」,中心流水号是「这笔结算业务的正式 ID」。临时 ID 只在两阶段之间有意义,正式 ID 才是后续所有操作(对账、退款、查询)的锚点。SH02 确认成功后,HIS 应该把两个号都存下来,但后续业务只认中心流水号。
5.2 四个号的职责边界:谁产生、谁消费、谁作废
把文档里所有「号」放一起看,整个交易体系的分层就清楚了。
| 标识 | 产生时机 | 职责 | 生命周期 |
|---|---|---|---|
| 计算申请序号 jssqxh | 挂号请求 SH01 | 申请阶段的临时 ID,用于确认或查询 | SH01 返回时产生,SH02 确认后失效,超时自动作废 |
| 就诊单元号 jzdyh | 挂号确认 SH02 | 一次就诊的标识,从挂到结全程携带 | 挂号确认后产生,本次就诊结束后失效 |
| 明细账单号 mxzdh | 明细上传 SN01 | 一批明细的标识,收费结算时引用 | 明细上传成功后产生,结算完成后归档 |
| 中心流水号 lsh | 结算确认 | 一笔结算的正式编号,对账退款都靠它 | 结算确认后产生,作为永久业务凭据 |
就诊单元号在门诊场景对应一次挂号,在住院场景对应一次住院登记。所有费用明细、结算、退费都挂在这个号下。文档对它的解释是「将医疗服务过程按照特定参数划分为相同部分,每一部分为一个就诊单元」——换成人话就是:一个病人多次就诊,每次就诊是一个独立单元,单元之间的费用互不混叠,方便费用审核和财务核算。
明细账单号由中心系统生成且唯一。收费请求时 HIS 把明细账单号带上,中心系统按这个号取明细、逐项算报销。一次收费里可能有多个明细账单(药品一批、材料一批),每个有自己的 mxzdh,收费请求参数要带上所有账单号。中心流水号是最终的结算凭据,对账、退款、查询都以它为准。它存在的意义是让 HIS 本地流水和中心系统流水一一对应——两边对账就是逐字段比对这笔流水下的所有金额和状态。
5.3 对账、退款、查询:为什么这些「备选功能」是系统的安全网
很多 HIS 对接医保,精力全放在挂号、收费、明细这些业务方法上,对账请求和交易查询被当成上线前的边角料。这是最危险的心态。
上线后一定会遇到的问题:HIS 本地记了一笔收费 100 元,中心系统那边查不到,或金额对不上。没有交易查询方法,开发只能干瞪眼;有了它,HIS 拿中心流水号去查记录,比对状态和金额字段,定位是 HIS 丢了、中心没收到、还是两侧算得不一样。
对账请求是批量核对:把一段时期内的交易和中心系统逐笔比对。按这类系统的一般设计,它至少包含对账日期范围、交易类型、HIS 本地流水号。中心系统返回每笔交易的状态和流水号,HIS 拿本地数据逐笔匹配,匹配不上的进差异清单人工处理。
退费请求的正确姿势是:退费金额不能直接取收费时的金额,以当前中心的记录为准。病人做了部分退费后,中心系统的记录已变化,HIS 拿旧金额去退会多退或少退。正确流程是先调交易查询确认这笔交易的当前状态,再发起退款请求。顺序反了,翻车概率很高。
一句话总结:对账、退款、查询不是备选功能,是系统的安全网。只实现挂号收费的 HIS,等于走钢丝没有保险绳。
6. 身份凭证的三种形态:从卡到码的演进,以及它背后的安全设计
身份识别是这套接口的第一道关口。芯片卡、磁条卡、电子凭证三种形态,对应三个时代的读取逻辑,最后都汇聚到 cardtype + carddata 这个统一入口。
6.1 芯片卡与磁条卡:两个时代的读卡逻辑
芯片卡(类型 1,保障卡或 IC 卡)插读卡机后调 ShYbV5_S000,一次拿回病人基本信息。返回的 JSON 里有卡号(kh)、姓名(xm)、性别(xb)、身份证号(sfzh)、联系电话(lxdh)、通讯地址(txdz)、邮政编码(yzbm)、行政区域代码(xzqh)。因为芯片卡内部存储了结构化的参保数据,读卡机可以一次性读取全部信息,HIS 在挂号前就掌握了完整的病人基础档案,不需要手动录入。
磁条卡(类型 0)恰相反,它只有 28 位,刷卡只拿到一个卡号。拿到卡号后,HIS 需要拿这个卡号去中心系统换完整信息。所以磁条卡流程里没有「读卡方法」一说——卡号本身就是后续交易的身份凭证。信息获取深度的不同,背后是数据载体能力的差异:芯片卡能存结构化数据,磁条卡只能存一个索引号。
从工程角度看,三种路径的信息采集方式不同,产出是一致的:让 HIS 拿到「当前就诊的参保人身份」。后续 SH01 通过 cardtype + carddata 把这个身份传给中心系统——cardtype 的取值决定了 carddata 里填什么:磁条卡填 28 位卡号,芯片卡为空(S000 已拿全信息),电子凭证填 ecToken。
6.2 电子凭证:为什么扫码后还要再解一次码
电子凭证(类型 3)是最特别的一条链路。它通过支付宝、微信、随申码等渠道获取二维码,然后调 SE01 解码,拿到身份证信息和 ecToken。
这个「二维码 → SE01 解码 → 身份证 + 令牌」的链路多了一层专门动作,不是多此一举。二维码本身是公开展示的,谁都能扫到——如果二维码直接就是医保身份凭证,等于把身份证号贴在大街上。SE01 把「码」和「人」绑定:中心系统通过二维码查到参保人,然后返回一个有时效的 ecToken。HIS 后面的操作不直接拿二维码、也不拿身份证号,而是拿这个令牌当凭证。
token 机制是这一层最核心的安全设计。ecToken 是 63 位字符串,语义是一次就诊会话的凭证。为什么不用身份证号当凭证?因为身份证号是永久的、公开的,一旦泄露无法撤销。令牌不同——它有时效、可撤销、可绑定特定场景、可限定权限。比如 SE01 参数里的 businessType(用码业务类型)就是告诉中心系统「这次扫码用在什么场景」——挂号、结算、还是查询。不同场景拿同一个码,中心系统可以根据 businessType 决定返回的 ecToken 的权限范围。挂号场景的令牌只能用于该次挂号,拿它去结算会被拒,这就在令牌层面实现了场景隔离。
医院前台的改变也在这里。以前刷芯片卡或磁条卡,前台必须有读卡机硬件。电子凭证只需要一个二维码扫描设备,甚至手机摄像头扫一下就能解码。SE01 把「读卡」从物理动作变成逻辑动作,这是医保身份识别从卡时代到码时代的转折点。代价是 HIS 侧要多维护一种身份路径,但换来的是就诊入口的普及性和安全性的双赢。
7. 设计取舍的复盘:从这份接口说明里,我看到了一套系统的安全边界
整份接口说明最值得琢磨的,是它对「拆」的坚持。门诊结算不是一个「一键结算」的大方法包办一切,而是拆成读卡、解码、挂号请求、挂号确认、明细上传、收费确认、对账、退款这一组可以独立调用、独立失败、独立重试的小方法。这种拆法牺牲了调用方的便利,换来了系统的可诊断性和可恢复性——任何一步失败,失败边界都清清楚楚,不会波及整笔业务。
两阶段确认是这个思路的集中体现。计算申请序号的存在,让「请求」和「成交」变成两个可分离的行为。HIS 可以先试算再决定是否落地,中心系统可以在确认前不占用正式资源。这个设计的双赢之处在于:HIS 拿到了后悔药,中心系统保住了业务数据的干净。你对照自己的业务系统想想,有多少笔假数据是因为「请求即成交」的模式产生的?这个接口用两段式从根上规避了这个问题。
电子凭证的 token 设计也是同理。它没有因为「反正有身份证号」就把身份明文放行,而是引入一层临时令牌做隔离。SE01 返回的 ecToken 让后续操作不需要反复暴露身份证号。安全边界的代价是多一道解码调用,但这道调用恰恰是整条链路里最值得的投入。从卡到码的演进,表面是读取方式变了,底层是安全模型变了——从「持有即身份」变成「验证后发放会话凭证」。
从账务角度看,支付段字段的拆分也体现着取舍哲学。当年账户、历年账户、自负段、统筹段、附加段,每个段单独命名、单独返回、单独存储。对 HIS 来说,这意味着前端展示要做到「病人自负 X 元、医保统筹 Y 元、个人账户划 Z 元」这种粒度,不能只显示一个总额。系统麻烦了一点,但财务对账和医保监管恰恰需要这种粒度。为了合规,这些字段一个都不能省。
对接这类系统的经验,我习惯总结成一句话:先理清三个号(计算申请序号、就诊单元号、中心流水号),再分清三类字段(身份凭证、业务上下文、金额),最后按两阶段次序(请求-确认)落库。理清这三条线,接口的每一段报文都不再是黑匣子。
从那以后,我每次对接新的医保或社保接口,都强制自己先做一遍「号段清单」——把文档里所有带「号」的字段列出来,标清楚每个号的产生时机、生命周期、失效条件,再动手写任何一行调用代码。这个习惯帮我避开了大部分对接期的返工。希望帮到你。
本文还有配套的精品资源,点击获取