支付清结算——统一状态码

前言

图中,支付核心负责构建和发送支付指令并处理支付结果,而支付指令和支付结果的报文传输标准各个支付渠道都不一样,所以就有了渠道网关在内部系统和支付渠道之间构建起了一层适配层,对内向各个子系统提供统一的接口,对外适配不同渠道的接口,也就是负责将内部统一报文转换成各渠道要求的报文。统一渠道报文有形式和内容两方面的统一,统一状态码和统一银行编码属于内容层面的统一,形式层面的统一就是报文结构和格式方面的统一,这里我们只介绍统一状态码,报文形式的统一另外再单独介绍。统一状态码除了统一渠道响应码的标准外,还会被支付系统中很多模块和子系统依赖如重路由、监控、告警等,因为统一状态码可以为这些子系统提供更细粒度的交易状态支持:一笔资金交易从商户下单,到平台收单,再到上送渠道,形成了一条链路,这条链路的各个环节因各种原因,都可能导致交易失败;这时,如果平台内部制定的统一状态码并明确区分了不同类型的错误,那么这不仅有利于运营人员快速定位问题,而且还能辅助重路由、切流、探测、监控等服务最大限度的提升交易成功率和系统稳定性。

概念定义与分析

状态码

规范的状态码由状态、编码、消息三个要素构成,其中状态要素用于表示操作的执行结果,编码是执行结果编号通过编号可以对执行结果分类,消息是对状态的文字描述。实际中,不同支付机构制定的状态码参差不齐,风格各异,且各个要素都可能存在或不存在,这就需要对支付渠道返回给平台的响应码进行统一。

统一状态码

统一状态码是指支付平台内部制定用于表示交易状态的标准状态码。统一状态码按来源可以分成三种:内部、网络、渠道。内部状态码是支付系统内部各个子系统产生的;网络(HTTP)状态码源自于网络通讯层,其本身已经是标准状态码对所有渠道都适用,其实无所谓统一,只不过如果将其纳入统一状态码体系的话,那么编码形式上是可以统一的(本文保持了原样);渠道统一状态码源自于对各渠道响应码的标准化。

编码方式

统一状态码不仅被程序使用,还会用于日常排错,所以进行统一编码时应该尽量做到易于记忆和分辨错误,子系统不多的情况下,这里推荐采用四位数字和三级分类的方式来编码:

首位用于表示状态码的来源,它是一级分类,如用数字1、2分别表示平台状态码和渠道状态码,而HTTP状态码可以允许例外。

第二位用于表示交易状态,它是二级分类。虽然不同类型的交易的状态可能不太一样,但是数量通常是有限的,不大会超过个位数,因此用一位数字足够表示了。我们可以将收、付、退交易的状态分成四种:处理中、失败、成功、未知,分别用数字0、1、2、3来表示。其中未知状态常用于出款交易,表示因各种非明确原因导致交易无法继续进行的情况。比如,平台收到了渠道的报文,但是无法识别对方的报文(对方修改报文或者我方事前未映射对方的状态码),或者因网络中断和异常导致交易处于未知状态。对外可以将未知归入处理中,但是对内来说不能将其归入处理中,应该保持状态的语义单一。

最后两位主要用来对错误进行编码既错误码,它是三级分类。交易的错误类型理论是无限的,但常见的错误如:余额不足、达到日限额、卡号错误就那么十几二十个,没必要将那些罕见的错误都定义出来,可以将其归入大类。所谓的大类是没有明确原因的那种错误,或者渠道根本没有给出具体的错误原因,这些情况就只能将其映射到大类。通常情况将00预留给大类状态,如2100表示错误大类,2101-表示余额不足、2102表示达到日限额、2103表示卡号错误。

商户返回码

商户返回码是指平台返回给商户的交易状态码。商户返回码不是统一状态码,虽然可以将统一状态码当做商户返回码返回给商户,但是这样会暴露平台内部的一些铭感信息;安全的做法是完全重新映射或部分铭感状态码重新映射之后返回给商户,上面的表格采用的是前面的方式,下面的表格采用的是后面的方式:

渠道响应码

渠道响应码是指支付渠道或银行返回给平台的交易状态码。渠道响应码分交易响应码和HTTP响应码两种,前者是渠道明确返回用于表示交易处理结果的状态码,后者是对方服务器返回用于表示服务器之间通讯状况的状态码;HTTP响应码主要在付款、退款下单场景中使用,除此之外极少会被使用。为了将渠道响应码映射到统一状态码上,我们需要预先将响应码录入或自动收集到渠道响应码表中,并将其和统一状态码建立映射关联。渠道响应码需要区分所属的交易和接口,因为相同的状态码可能对于不同的交易和不同的接口具有不同的含义。

状态码映射

状态码映射是指将一种状态码转换成另一种状态码。在统一状态码体系下,状态码映射按所要映射的对象的不同可以分成三种:渠道响应码映射,统一状态码映射,平台内部状态码映射。渠道响应码映射是指将渠道响应码转换成统一渠道状态码,统一状态码映射是指将统一状态码转换成商户返回码,而平台内部状态码映射是平台内部子系统之间状态的互转。这里我们主要介绍渠道响应码的映射实现原理,至于其它状态码的映射原理和它是差不多的,甚至更简单一些。

渠道响应码映射

渠道响应码映射细分还可以分为渠道交易响应码映射和渠道HTTP响应码映射,两者的作用域和实现逻辑有所不一样,前者作用于特定渠道基于要素匹配实现映射,后者作用于所有渠道但适用的交易类型和接口比较有限,通常查询、回调类接口不关注网络层面的映射结果,只有付款、退款会借助HTTP响应码映射来确定交易状态。

映射配置

渠道响应码的映射,需要通过映射配置预先构建渠道响应码和统一状态码之间的关联关系,以及消息要素的匹配方式;其他两个要素无需指定默认精准匹配,只有当状态和编码两个要素无法让渠道响应码映射到统一状态码的小类且消息要素不为空时,消息要素才会被用来确定小类。审核状态和版本号两个字段是修改配置用的:当修改已审核的映射配置的时候,不应该直接在原来的数据上进行修改,而是复制原配置并增加版本号,审核通过之后删除原配置。

匹配方式

由于渠道交易响应码的不规范性,各个要素都可能存在或不存在,因此它们之间的组合就有下面八种可能:

这八种可能,基于状态、编码、消息三种匹配方式及其组合形式就能覆盖。最后一种情况比较特殊,三个要素都没有,好像无法映射;这种情况存在两种可能,第一种其实是有状态的,只不过默认就是某一种状态,比如有些渠道收款交易,只要回调都表示成功而不会给具体的状态码,这种情况可以自己填充一个固定状态来解决;另一种是因为网络故障未收到渠道的响应报文,这时候可以基于HTTP响应码进行映射。

基于状态

状态是状态码的必要要素,所有渠道的响应码都有这个要素,只要存在这个要素应该先基于状态映射确定大类。比如对方的返回报文除了交易单号,只有一个status字段来表示交易状态:pending、paid、failed,那么就基于状态将上述状态映射成平台定义的大类统一状态码如:2100,2200,2300。

基于编码

编码通常可以用来确定具体的错误类型,如果大类已经确定,那么接下来再依据编码来确定小类。但有时候,编码也表示大类,那么这个时候就需要基于消息才能映射到小类。另外,如果没有状态只有编码和消息,那么编码的映射方式应该优先于消息。

基于消息

消息的作用和编码是一样的,可以用来确定小类,但基于消息不像上面两种那样简单,他需要预先配置消息的匹配方式是精准还是模糊。精确匹配就是渠道返回码中的消息和渠道状态码中的消息一致,而模糊匹配不需要一致只需要包含事先指定的一组关键字就可以或者满足正则表达式的匹配模式。

HTTP响应码映射

只有在交易上送渠道时,渠道因服务故障没有返回具体的交易响应报文时,才会使用这种方式来确定交易状态。比如付款场景下,因对方服务故障返回504服务超时,那么这个时候交易状态是不明确的,因为对方可能处理了交易也可能没处理,需要通过主查或对方后续的回调才能明确交易当前所处的状态。在付款场景中,原则上任何渠道的网络异常,在未明确定义HTTP响应码所表示的交易状态时,都应该映射成未知状态,以免出现资损。如果明确了某个渠道的某些网络状态码都是失败,那么也不能一概而论而是只为已明确的渠道配置HTTP状态码的映射,因为虽然HTTP是标准的但是也不排除某些渠道做了个性化的改动,没按标准来。

自动收集

如果渠道响应码都需要人工录入,那么难免会有遗漏和错误,较好的方式是让系统自动收集那些未录入到渠道响应码表中的状态。自动收集还有一个好处,那就是当系统因为渠道新增状态或者事前未配置完整,无法识别渠道的状态码时,此时订单有可能处于卡单状态,无法继续推进;有了自动收集和上面的动态映射机制,运营人员明确状态码的含义后,无需研发介入,就可以自行解决问题。

ER模型

上面ER模型所表现的内容上面都一一以表格的形式展示过了,两者只是表达形式不一样,这里就不赘述相关的内容了。

映射架构


映射架构图中的构件上面也都已经单独详细的分析过了,这里只不过是从映射实现过程的角度将它们链接在一起形成一个整体,所以相关的概念不再赘述,只是简单展示一下核心组件的代码如何表现上面我们已经分析过的概念。为了表述和代码命名不那么冗长,上面的响应码特指渠道响应码。

响应码映射服务类,负责对外接受客户端的映射请求,并组织和编排内部不同构件实现响应码到统一状态码的转换,示列代码如下:


交易响应码映射器,真正实现响应码映射的类,它组织和编排要素匹配器进行响应码和响应码表中的响应码进行匹配,示列代码如下:

基于消息的响应码匹配器,示列代码如下:

结尾

统一状态码是我支付清结算的基础,支付系统中很多模块都依赖于它,构建支付系统时要先于其他的模块考虑该模块系统的设计,否则后续的渠道路由和业务监控很难设计。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前言 图中,支付核心负责构建和发送支付指令并处理支付结果,而支付指令和支付结果的报文传输标准各个支付渠道都不一样,...
    chzne阅读 4,578评论 0 2
  • 前言 大家好,这篇文章我们介绍一下《渠道路由》的第二部分——重路由。对于支付业务来说,支付成功率是衡量支付服务质量...
    chzne阅读 994评论 0 0
  • 前言 大家好,这篇文章我们介绍一下渠道路由,通常在架构设计上会将它作为渠道网关系统中的一个模块,但这里为了更清晰的...
    chzne阅读 14评论 0 0
  • PS~ 经过一段时间的忙碌与调整,终于有时间可以闲下来了,今天开始重更自己在实际工作中的产品经历与总结。第一篇就以...
    交个朋友老曾阅读 4,489评论 1 8
  • 一. 背景 我在的这家公司是做物流领域的互联网公司,周支付交易额约在亿元人民币级别,支付这块的考核指标是在降低渠道...
    栋哥哥darre_li阅读 3,624评论 0 1