“渠道API”是一种通过流量平台直接获取用户流量的方式。传统上我们获取流量的方式有:投放广告,吸引用户下载主营APP进而使用借款服务;投放H5服务,用户通过不同渠道打开H5页面使用借款服务。
“渠道API”的方式是指用户直接在流量方的原生APP中使用我们的借款服务,这就需要将我们的系统能力按照约定的规范封装成一套API接口提供给流量方服务端调用。这里的规范可以是我方定义的,也可以是流量方定义的。这里主要讨论按照流量方标准进行接入的方式。
为了提高对接的效率,我们期望在接入一家新渠道的时候,所做的工作越简单越好,越少越好。最好每个API只需要适配请求参数,调用底层服务,封装响应结果。但要沉淀这样的底层服务何谈容易,就借款来说涉及的主要流程有:准入判断、授信申请、银行卡绑定、借款、还款。首先,单个业务流程的逻辑就很复杂,拿授信申请来说,需要完成用户注册、前置校验判断、实名认证、保存用户基础信息、联系人信息、收入信息、身份证照片认证、活体照片认证、戳额等,而且身份证照片认证、活体照片认证、戳额都是异步服务,需要等待认证结果来驱动流程进行。其次,不同流量方的流程也是不一样的,有的有单独的绑卡流程,有的绑卡是嵌入到借款流程中的;有的用户信息是在授信申请流程中提交,有的是在借款流程中提交;有的可以在借款流程中重新进行身份证照片认证,以防认证过期,有的则不可以。
若以传统方式实现各业务流程,则很难避免大量硬编码判断逻辑,导致系统可扩展性差,维护成本高。我们希望可以将一个个业务片段封装成组件,在这些组件基础上为不同流量方的不同流程编排不同的处理逻辑。因此,我们引入了LiteFlow框架。
LiteFlow是一个非常强大的现代化的规则引擎框架,融合了编排特性和规则引擎的所有特性。
LiteFlow为解耦逻辑而生,为编排而生,在使用LiteFlow之后,你会发现打造一个低耦合,灵活的系统会变得易如反掌!
利用LiteFlow,你可以将瀑布流式的代码,转变成以组件为核心概念的代码结构,这种结构的好处是可以任意编排,组件与组件之间是解耦的,组件可以用脚本来定义,组件之间的流转全靠规则来驱动。LiteFlow拥有开源规则引擎最为简单的DSL语法。十分钟就可上手。
组件可实时热更替,也可以给编排好的逻辑流里实时增加一个组件,从而改变你的业务逻辑。
LiteFlow的脚本组件,支持众多脚本语言,完全和Java打通,你可以用脚本来实现任何逻辑。
LiteFlow支持把编排规则和脚本放在数据库,注册中心中,还有可以任意扩展的接口,方便你定制。
编排语法强大到可以编排出任何你想要的逻辑流程。
LiteFlow具有如下特性:
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-spring-boot-starter</artifactId>
<version>2.11.3</version>
</dependency>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-rule-sql</artifactId>
<version>2.11.3</version>
</dependency>
@LiteflowComponent(value="A",name="A组件")
public class ACmp extends NodeComponent {
@Override
public void process() {
//业务逻辑
}
}
@LiteflowComponent(value="A",name="A组件")
public class BCmp extends NodeComponent {
@Override
public void process() {
//业务逻辑
}
}
#jdbc的连接url
liteflow.rule-source-ext-data-map.url = jdbc:mysql://{hostname}:3407/{database}?XXX=xxx
#驱动器类名
liteflow.rule-source-ext-data-map.driverClassName = com.mysql.cj.jdbc.Driver
#数据库用户名
liteflow.rule-source-ext-data-map.username = {database_username}
#数据库密码
liteflow.rule-source-ext-data-map.password = {database_password}
#以下是chain表的配置
#你的应用名称 只读取chainApplicationNameField列值为demo的规则
liteflow.rule-source-ext-data-map.applicationName = demo
#编排规则表的表名
liteflow.rule-source-ext-data-map.chainTableName = liteflow_chain
#编排规则表中应用名称存储字段名
liteflow.rule-source-ext-data-map.chainApplicationNameField = application_name
#存储规则的字段名
liteflow.rule-source-ext-data-map.chainNameField = chain_name
#EL表达式的字段(只存EL) 例如:THEN(a,b,c)
liteflow.rule-source-ext-data-map.elDataField = el_data
在数据库中,新建一张表来存储编排规则。在规则表中,一行数据就是一个规则。在脚本表中,一行数据就是一个脚本组件。
规则表:liteflow_chain
@SpringBootApplication
//把你定义的组件扫入Spring上下文中
@ComponentScan({"com.xxx.xxx.cmp"})
public class LiteflowExampleApplication {
public static void main(String[] args) {
SpringApplication.run(LiteflowExampleApplication.class, args);
}
}
然后你就可以在Springboot任意被Spring托管的类中拿到flowExecutor,进行执行链路:
@Component
public class YourClass{
@Resource
private FlowExecutor flowExecutor;
public void testConfig(){
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
}
}
对于存在多种驱动方式的业务流程,我们建议编排一个完整的处理逻辑,然后通过isAccess()方法针对特定节点进行跳过处理。这种方式可以避免逻辑分散,更加直观。
以“授信申请”流程为例,授信申请需要完成用户注册、前置校验、实名认证、保存用户信息、身份证照片认证、戳额操作。我们一般会编排如下流程:
用户主动发起授信申请的流程
收到身份证认证结果通知MQ的流程
执行状态补偿定时任务流程
但这种方式有如下缺点:由于流程的处理逻辑分散在不同的地方,导致我们无法直观地了解流程的整体处理逻辑,在需求变更的时候,就有可能考虑不周,遗漏某些修改。
建议我们可以编排一个完整的业务处理流程,无论是用户主动发起、接收到通知消息、还是定时任务都走同样的流程。这样将处理逻辑集中在一块,让我们对授信流程有个整体的把握,增加程序的可读性、可维护性。完整流程如下:
此时有一个问题,流程中有些组件应该只执行一次,怎样避免每次流程运行都执行这些组件呢?LiteFlow的组件基类NodeComponent有一个方法public boolean isAccess(),如果返回false,则跳过该组件。这样我们可以重写组件的isAccess方法并将组件的执行状态记录在数据库中,每次执行到该组件的时候,根据状态判断是否需要执行。
随风, 现任渠道对接 后端研发专家