实时交易规则

举例背景

在如今数字支付日益普及的时代,POS机的角色不可忽视。作为连接消费者与商家的纽带,POS机承载着大量的金融交易和数据传输。然而,随之而来的安全风险也日趋复杂和严峻。 本篇博客将带您踏入我们独特的世界,探索我是如何为POS机注入高强度的安全保护,提供无忧支付体验的。

早期方案

当产品提出某些需求,例如用户今日累计交易金额>10w限制出款,然后由开发编码,在交易接口里面嵌入,然后执行发版,但是这种方案对实时性的得不到保障,以及发版带来影响交易的风险。

若过几天,产品又说,某一批商户用户今日累计交易金额>20w限制出款,针对频繁的变动又该怎么办呢?

存在如下具有代表性的业务场景:

  • 限制某个城市的机器不能交易
  • 交易限额
  • 针对有问题机器禁止消费

规则引擎带来的解决方案

在复杂多变的业务场景中,单靠我们日常处理判断的能力是不够的,规则变化快,不可 控因素多,业务场景复杂,都会加快开发人员处理规则的难度,减缓项目上线的难度,看我们如何使用规则引擎解决此时遇到的一些问题!

交易接口示例

处理交易调用规则核心代码,规则客户端代码内嵌在接口内,当触发交易时,首先请求配置的规则,由规则动态判断交易逻辑。


@Slf4j
@Service
public class TradeService {

    @Resource
    private RuleEngineClient ruleEngineClient;
    @Resource
    private DemoTransactionRecordsMapper demoTransactionRecordsMapper;

    /**
     * 交易处理
     *
     * @param tradeRequest 交易请求参数
     * @return true交易成功
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean trade(TradeRequest tradeRequest) {
        // 一些其他业务处理
        // ...
        try {
            RuleSet ruleSet = this.ruleEngineClient.ruleSet();
            TradeRuleModel tradeRuleModel = new TradeRuleModel();
            // 复制参数,去请求规则引擎计算
            BeanUtil.copyProperties(tradeRequest, tradeRuleModel);
            // 调用规则引擎,并拿到返回结果
            Output execute = ruleSet.execute(tradeRuleModel);
            if (Objects.equals(execute.getClassType(), Boolean.class.getName())) {
                Boolean value = (Boolean) execute.getValue();
                if (!value) {
                    throw new RuntimeException("规则:交易失败!");
                }
            } else {
                Object value = execute.getValue();
                throw new RuntimeException("规则:" + value);
            }
        } catch (RuntimeException e) {
            // 记录交易失败流水
            // ..
            throw e;
        }
        // 一些其他业务处理
        // ...
        // 记录成功交易流水
        // ..
        return true;
    }

}

开发在不动以上稳定代码的情况下,如何保障业务正常迭代流转。规则示例如下,允许页面动态修改规则,不需要开发人员介入,提供了规则版本控制以及预览等,即能保证实时性,又能保证稳定性等

第一种需求:

判断此商户是否被限制消费,或被拉入黑名单,如果是,不可交易!

然后配置如下信息,不满足返回:已被限制消费!

none

第二种需求:

如果是优质商户,每天交易金额只能为100w其他商户50w

配置如下信息,不满足返回:额度超限!

none

模拟请求参数,请求交易接口

{
    "merNo": "M0001",
    "sn": "A0001",
    "factory": "厂商10",
    "amount": 500000
}

请求接口后控制台日志打印如下:

2023-09-03 18:51:38 c.a.druid.pool.DruidAbstractDataSource   : discard long time none received connection. , jdbcUrl : jdbc:mysql://rm-2ze27j116367ke9i93o.mysql.rds.aliyuncs.com:3306/rule_engine_v2?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8, version : 1.2.5, lastPacketReceivedIdleMillis : 1815124
2023-09-03 18:51:38 org.example.order.service.TradeService   : 开始处理交易:TradeRequest(merNo=M0001, sn=A0001, factory=厂商10, amount=500000)
2023-09-03 18:51:38 c.r.c.h.FeignInvocationHandlerFactory    : Request param is [ExecuteParam(code=tran-risk, input={factory=厂商10, amount=500000, merNo=M0001, sn=A0001})]
2023-09-03 18:51:39 c.r.c.h.FeignInvocationHandlerFactory    : Direct result is Result(code=200, data=Output(value=[额度超限!], classType=java.util.Collections$SingletonList), message=执行成功, timestamp=2023-09-03 10:51:39)
2023-09-03 18:51:39 org.example.order.service.TradeService   : 规则引擎返回结果:Output(value=[额度超限!], classType=java.util.Collections$SingletonList)
2023-09-03 18:51:39 org.example.order.service.TradeService   : 规则限制交易:规则:[额度超限!]

第三种需求:

某个POS机厂商产品出现了问题,需限制交易!

配置如下信息,不满足返回:机器限制使用!

none

请求交易接口,日志打印如下:

2023-09-03 18:21:22 org.example.order.service.TradeService   : 开始处理交易:TradeRequest(merNo=M0001, sn=A0001, factory=厂商1, amount=500000)
2023-09-03 18:21:22 c.r.c.h.FeignInvocationHandlerFactory    : Request param is [ExecuteParam(code=tran-risk, input={factory=厂商1, amount=500000, merNo=M0001, sn=A0001})]
2023-09-03 18:21:22 c.r.c.h.FeignInvocationHandlerFactory    : Direct result is Result(code=200, data=Output(value=[机器限制使用!], classType=java.util.Collections$SingletonList), message=执行成功, timestamp=2023-09-03 10:21:22)
2023-09-03 18:21:22 org.example.order.service.TradeService   : 规则引擎返回结果:Output(value=[机器限制使用!], classType=java.util.Collections$SingletonList)
2023-09-03 18:21:22 org.example.order.service.TradeService   : 规则限制交易:规则:[机器限制使用!]

处理第N个需求

....

实时风控

以上介绍了规则引擎的简单使用,但是如何做到针对某些行为以及事件实时限制商户、POS交易。以及如何预防、反洗钱等。

但是规则引擎处理的业务大部分应该是无状态的,应该如何巧妙的解决以上问题呢。

如果我们学过Flink,它是有状态的,出色的流处理、事件时间处理、低延迟和高吞吐的特性,是不是可以把二者结合起来使用呢?

下期预告:基于Flink与规则引擎的实时风控

更新日期:
作者: dingqw