源码讲解:JAVA版低代码报文网关-通过简单配置快速对接银行渠道

大家好,我是隐墨星辰,前几天发布了AVA版低代码报文网关,只需要手写几个配置文件,就可以快速接入一个渠道。接入效果和详情请看《百图解码支付系统设计与实现》专栏中的文章《开源发布:JAVA版低代码报文网关-通过简单配置快速对接银行渠道》。

今天讲解报文的源码,分享设计如何落地。项目代码写得很简洁精炼,稍微有点绕的是内联函数的实现,没有写过相关代码的同学可以重点看一下,看懂后就会觉得:嗯,原来这么简单。

补一个直观的效果,一个渠道的支付接口就是一个配置文件:

1. 原理介绍

说明:

  1. 处理器引擎服务:串起全部业务处理。
  2. 引擎上下文:保存接口配置、请求参数、返回参数、加解密加验签临时变量、内联函数等。
  3. 处理器责任链工厂:组装并管理内部发外部,外部发内部责任链。
  4. 处理器责任链:处理业务数据。包括解析、参数转换、签名验签、发送等处理。
  5. 缓存服务:缓存渠道配置,密钥配置等。

详细设计参考《百图解码支付系统设计与实现》专栏文章:

《图解支付报文网关:一种低代码报文网关的设计思路与核心代码实现》

《图解支付渠道网关(一):不只是对接渠道的接口》

《图解支付渠道网关(二):不只是对接渠道的接口》

2. 工程目录说明

如下图所示。

3. 入口服务定义与实现

入口服务只有一个,是通用服务,无论支付、退款、支付查询、退款查询等全部都是这个接口

上游根据实际需求,定义一些强类型,比如支付请求模型,退款请求模型,然后使用JSON.toString序列化后传下来。返回后再反序列化强模型做内部处理。

com.demo.gateway.api.GatewayService

com.demo.gateway.api.response.GatewayResponse

com.demo.gateway.api.response.GatewayResponse

com.demo.gateway.service.GatewayServiceImpl

4. 流程引擎

流程引擎服务是最核心的服务,全部处理由流程引擎串起来。

4.1. 流程引擎服务定义与实现

流程引擎核心只做了3件事:

  1. 初始上下文
  2. 从处理器工厂找到处理器责任链
  3. 依次执行处理器

4.2. 处理器工厂

处理器工厂核心能力:

  1. 定义内部到外部,外部到内部的处理责任链。
  2. 初始化责任链。
  3. 根据方向(内部发外部,或外部发内部)返回指定的责任链。

定义责任链:

4.3. 各类型处理器

各种各样的处理器,每个处理器都非常简单,只做一件事,组合起来就是强大的网关。

4.3.1. 处理器基类

4.3.2. 参数转换

4.3.3. 签名验签名

以RSA签名示例。非RSA可以自行扩展。

4.3.4. 报文组装

4.3.5. 发送

4.3.6. 其它处理器

其它加解密等略过,主体结构都差不多。

5. 内联函数

5.1. 使用场景

大部分的参数是一一映射的,比如内部参数叫:orderNo,外部渠道参数叫merchantOrderNo,都是比较容易映射的,如下:

但是一些特殊的处理,就需要使用内联函数来解决,比如内部传的日期是时间戳,类似:1715509833656,但是外部渠道要求格式为:"yyyy-MM-dd HH:mm:ss",就不能直接做映射。

还一些情况下,比如组装复杂的结构体,或者发送前需要调用内部应用先获取一些数据,都可以使用内联函数实现。

5.2. 实现原理

主要是借助Groovy的模板引擎来实现。

先定义一个基类,方便Spring自动加载。

时间处理函数:

JSON格式化函数:

Money转换函数

先把内联函数缓存起来备用。

每次请求进来,都会初始化引荐上下文,这时把内联函数放到引擎上下文中。

com.demo.gateway.engine.impl.HandlerEngineServiceImpl#initContext

再以function开头放到runtimeContext中,这样配置文件就可以使用"${function.funcationname.method(param)}的方式调用。

com.demo.gateway.engine.context.HandlerEngineContext#initRuntimeContext

调用示例:

6. Groovy模板引擎

参数映射和内联函数的运算,依赖Groovy模板引擎。

com.demo.gateway.groovy.GroovyUtil

调用,就会把转换变量。

比如配置文件:

kotlin 复制代码
{
  "requestTime": "${function.Datetime.formatDateString(requestData.requestTime, 'yyyy-MM-dd HH:mm:ss')}"
}

转换后的报文:

json 复制代码
{
  "requestTime": "2024-05-12 18:30:33"
}

7. 配置模型

就是把渠道接口抽象出不同的配置类型,然后组装起来。

8. 配置数据

  1. 生产上可以考虑放数据库中。
  2. 生产参数和线下联调环境参数要区分开。部分敏感数据,比如apiKey建议加密后存储,提高安全性。
  3. 生产密钥保存到密钥平台,提高安全性。

9. 测试与验证

9.1. 测试代码

com.demo.gateway.DemoTest#run()

如果需要验证http外发能力,先运行:com.demo.gateway.GatewayApplication#main

com.demo.gateway.web.DemoChannelMockController#mockChannel是web服务,模拟外部渠道的http服务。

9.2. 运行日志参考

只截取了部分日志。详细输出参考:《百图解码支付系统设计与实现》专栏中的文章《开源发布:JAVA版低代码报文网关-通过简单配置快速对接银行渠道》。

  1. 内部应用调用网关的完整请求参数 (GatewayRequest)
  1. 转换后返回内部应用的参数(GatewayResponse):

10. 如何获取源码

见:gitee.com/yinmosc/gat...

11. 小结

项目代码写得很简洁精炼,如果有同学所在公司的网关想升级或准备重构,可以拿回去参考一下。说不定能为上半年的好绩效做点贡献。

这是《百图解码支付系统设计与实现》专栏系列文章中的第(33)篇。 欢迎和我一起深入解码支付系统的方方面面。

专栏系列文章PDF合集,以及电子书《图解支付系统设计与实现》(已写9万字左右)不定时更新,欢迎关注我的公众号获取:隐墨星辰。

有个小群不定时解答一些问题或知识点,有兴趣的同学可先加微信(yinmon_sc)后进入,添加微信请备注:666。

相关推荐
小李不想输啦32 分钟前
什么是微服务、微服务如何实现Eureka,网关是什么,nacos是什么
java·spring boot·微服务·eureka·架构
张铁铁是个小胖子32 分钟前
微服务学习
java·学习·微服务
ggs_and_ddu33 分钟前
Android--java实现手机亮度控制
android·java·智能手机
敲代码娶不了六花2 小时前
jsp | servlet | spring forEach读取不了对象List
java·spring·servlet·tomcat·list·jsp
Yhame.2 小时前
深入理解 Java 中的 ArrayList 和 List:泛型与动态数组
java·开发语言
是小崔啊3 小时前
开源轮子 - EasyExcel02(深入实践)
java·开源·excel
myNameGL4 小时前
linux安装idea
java·ide·intellij-idea
青春男大4 小时前
java栈--数据结构
java·开发语言·数据结构·学习·eclipse
HaiFan.5 小时前
SpringBoot 事务
java·数据库·spring boot·sql·mysql
2401_882727575 小时前
低代码配置式组态软件-BY组态
前端·后端·物联网·低代码·前端框架