3. 支付渠道接入与网关设计

医疗支付平台面对的是高度碎片化的渠道生态:微信支付、支付宝、银联云闪付、医保移动支付,以及部分医院自有的 POS、聚合码、银行直连通道。每个渠道在接口协议、签名方式、报文格式、异步通知机制、退款规则、对账文件结构上都不一致。如果让业务系统直接对接每一个渠道,任何一次渠道升级、证书轮换或限额调整都会引发大范围改造。统一支付网关的核心价值,就是把“渠道差异”收敛到网关内部,向上暴露一套稳定的支付能力接口。

一、网关的分层结构与职责边界

统一支付网关通常分为四层:接入层、能力层、渠道路由层、渠道适配层。接入层负责鉴权、限流、幂等校验与参数规范化;能力层把业务语义(下单、支付、退款、查询、关单、对账)翻译成内部统一指令;渠道路由层根据支付方式、金额、医院、医保类型、渠道健康度选择具体通道;渠道适配层则封装各渠道 SDK 与协议细节,完成签名、加密、报文组装与响应解析。

关键设计原则是:业务系统只感知“支付方式 + 金额 + 订单号”,不感知“走哪个渠道的哪个接口”。渠道选择、重试、降级全部在网关内部完成。这样新增一个医保移动支付渠道时,只需在适配层增加一个实现类并注册路由规则,上层业务零改动。

业务系统 HIS / 互联网医院 接入层 鉴权 · 限流 · 幂等 参数规范化 能力层 下单 · 支付 · 退款 查询 · 关单 · 对账 渠道路由层 支付方式 · 金额 医院 · 医保 · 健康度 渠道适配层(统一接口 IChannelAdapter) 签名/验签 · 报文组装 · 响应解析 · 异常映射 · 证书管理 微信支付 JSAPI / Native / 小程序 支付宝 当面付 / APP / 小程序 银联云闪付 二维码 / 无跳转 / 网关 医保移动支付 医保电子凭证 / 混合支付 路由决策输入: 支付方式(微信/支付宝/银联/医保) · 订单金额 · 医院ID · 医保类型 · 渠道实时健康度 · 限额余量 · 降级开关 输出:目标渠道编码 + 适配器实例 + 超时/重试策略 + 降级备选通道

二、渠道抽象:统一接口与差异封装

渠道适配层的关键是定义一套稳定的内部契约。以支付下单为例,内部统一请求对象包含:商户订单号、支付金额(分)、支付方式、用户标识(openid/医保电子凭证)、回调地址、超时时间、扩展参数。适配器负责把这些字段映射到各渠道的真实字段,并处理差异。

典型差异包括:微信支付 v3 使用 SHA256-RSA 签名与 AES-GCM 解密回调;支付宝使用 RSA2 签名,回调为 form 表单;银联全渠道使用证书签名与 XML/JSON 混合报文;医保移动支付则涉及医保局下发的动态令牌与医院端密钥协商。适配器需要把这些差异全部吸收,向上只返回统一结果:SUCCESS / FAIL / UNKNOWN / PROCESSING,并附带渠道流水号与原始响应。

下面是一个适配器接口的示例定义:

public interface IChannelAdapter {
    // 渠道编码:WECHAT / ALIPAY / UNIONPAY / MI
    String channelCode();

    // 统一下单
    ChannelPayResult pay(ChannelPayRequest request);

    // 统一退款
    ChannelRefundResult refund(ChannelRefundRequest request);

    // 统一查询
    ChannelQueryResult query(String outTradeNo, String channelTradeNo);

    // 异步通知验签与解析
    ChannelNotifyResult parseNotify(Map<String, String> headers, String body);

    // 渠道健康检查
    ChannelHealth health();
}

注意 UNKNOWN 状态的处理:当网关调用渠道超时或网络中断时,不能简单判定为失败,而应标记为未知,进入主动查询补偿流程。这是医疗支付场景中避免“用户已扣款但订单显示未支付”的关键。

三、渠道路由策略

路由不是简单的 if-else,而应设计为可配置的规则链。路由输入包括:支付方式、金额、医院、医保类型、渠道健康度、限额余量、降级开关。输出是目标渠道编码与适配器实例。

常见的路由规则优先级如下:

  • 强制指定:医保移动支付必须走医保通道,不可降级到普通支付。
  • 限额过滤:单笔金额超过微信单笔限额(示例:5万元)时,自动切换到银联或银行直连。
  • 健康度过滤:渠道连续失败率超过阈值(示例:5分钟内失败率 > 30%)时,临时摘除该渠道。
  • 成本与优先级:在多个可用渠道中,按费率、到账时间、医院协议优先级排序。
  • 降级备选:主通道不可用时,按预设顺序切换到备选通道,并记录降级事件。

路由规则建议存储在配置中心,支持热更新。每次路由决策输出一条结构化日志,包含:订单号、命中规则、候选渠道列表、最终选择、决策耗时。这样在排障时可以快速回答“这笔订单为什么走了银联而不是微信”。

四、限额控制与降级策略

限额控制分为三个层次:渠道级限额、医院级限额、单用户级限额。渠道级限额来自各支付机构,例如微信单笔、单日限额;医院级限额是平台为控制风险设置的业务上限;单用户级限额用于防止异常高频支付。网关在路由前先做限额预检,超限则直接拒绝或切换通道。

降级策略需要区分“渠道降级”和“功能降级”。渠道降级是指主通道不可用时切换到备选通道;功能降级是指某些非核心能力(如营销立减、分期)在异常时暂时关闭,保证主支付链路可用。降级开关应支持手动与自动两种触发方式,并设置恢复条件,避免渠道恢复后仍长期处于降级状态。

实践建议:降级决策应设置“熔断—半开—恢复”三态。熔断后经过冷却期(示例:60秒)进入半开,放行少量试探流量;若试探成功率达到阈值(示例:90%),则恢复全量;否则重新熔断。这样既能快速止损,又不会因一次抖动永久摘除渠道。

五、幂等、重试与对账闭环

支付网关必须保证幂等:同一商户订单号重复请求下单,应返回首次结果而非重复创建。实现方式通常是以商户订单号 + 渠道编码作为唯一键,在数据库中做唯一约束,并在接入层做分布式锁或状态机校验。

重试策略要区分“可重试”与“不可重试”。网络超时、渠道系统繁忙可重试;参数错误、签名失败、余额不足不可重试。重试必须使用相同的商户订单号,避免重复扣款。对于 UNKNOWN 状态,应进入主动查询队列,按指数退避策略查询渠道最终状态。

对账是最后一道防线。网关每日拉取各渠道对账文件,与平台交易流水逐笔比对,输出差异明细:长款、短款、状态不一致、金额不一致。差异记录进入人工处理工单,并触发告警。只有对账闭环完成,才能确认当日资金与订单真正一致。

控制点 关键动作 判断依据
幂等校验 商户订单号唯一约束 + 状态机 重复请求返回首次结果
限额预检 渠道/医院/用户三级限额比对 超限则拒绝或切换通道
路由决策 规则链匹配 + 健康度过滤 输出渠道编码与备选通道
降级熔断 失败率阈值触发,半开试探恢复 试探成功率达标则恢复
对账闭环 渠道对账文件与平台流水逐笔比对 差异为零或差异已处理

综上,统一支付网关的设计本质是“收敛差异、稳定契约、可控降级”。把渠道差异封装在适配层,把路由与限额做成可配置规则,把异常与降级做成可观测、可恢复的状态机,再以对账闭环兜底,才能在医疗支付这种高可用、强合规的场景中稳定运行。