Skip to content

项目学习-大营销平台系统设计实现-用户行为返利结算 #22

Description

@cyjxiaozhi

一、本节诉求
上一节对用户的行为根据返利配置进行入账发送MQ消息,这一节将接收MQ消息开始结算返利。这里也就是给用户的活动账户充值。并提供一个日历签到返利的接口,用于后续对接到前端UI使用。

image

增加接收MQ消息流程,调用活动账户额度入账接口,增加用户的可抽奖次数。这里包括;总、月、日,账户额度更新。
注意 MQ 消息会有过滤,目前只处理返利是 sku 类型的返利。
最后在提供一个日历签到的接口,便于后续对接到前端页面使用

二、代码实现
@slf4j
@component
public class RebateMessageCustomer {

@Value("${spring.rabbitmq.topic.send_rebate}") // @Value 注解用于将外部配置文件(通常是 .properties 或 .yml 等格式的配置文件,在 Spring 项目中用于配置各种参数,如数据库连接信息、消息队列相关配置等)中的属性值注入到对应的类成员变量中。在这里,它的作用是将配置文件中名为 spring.rabbitmq.topic.send_rebate 的属性值注入到 topic 这个字符串变量中,从变量名和配置属性名推测,这个值代表了 RabbitMQ 中用于发送用户行为返利相关消息的主题名称,通过这种方式实现了将配置与代码分离,方便在不同环境(如开发环境、测试环境、生产环境等)下调整消息主题等配置参数,而无需改动代码本身。
private String topic;
@Resource
private IRaffleActivityAccountQuotaService raffleActivityAccountQuotaService;

@RabbitListener(queuesToDeclare = @Queue(value = "${spring.rabbitmq.topic.send_rebate}"))
public void listener(String message) {
    try {
        log.info("监听用户行为返利消息 topic: {} message: {}", topic, message);
        // 1. 转换消息
        BaseEvent.EventMessage<SendRebateMessageEvent.RebateMessage> eventMessage = JSON.parseObject(message, new TypeReference<BaseEvent.EventMessage<SendRebateMessageEvent.RebateMessage>>() {
        }.getType());
        SendRebateMessageEvent.RebateMessage rebateMessage = eventMessage.getData();
        if (!RebateTypeVO.SKU.getCode().equals(rebateMessage.getRebateType())) {
            log.info("监听用户行为返利消息 - 非sku奖励暂时不处理 topic: {} message: {}", topic, message);
            return;
        }
        // 2. 入账奖励
        SkuRechargeEntity skuRechargeEntity = new SkuRechargeEntity();
        skuRechargeEntity.setUserId(rebateMessage.getUserId());
        skuRechargeEntity.setSku(Long.valueOf(rebateMessage.getRebateConfig()));
        skuRechargeEntity.setOutBusinessNo(rebateMessage.getBizId());
        raffleActivityAccountQuotaService.createOrder(skuRechargeEntity);
    } catch (AppException e) {
        if (ResponseCode.INDEX_DUP.getCode().equals(e.getCode())) {
            log.warn("监听用户行为返利消息,消费重复 topic: {} message: {}", topic, message, e);
            return;
        }
        throw e;
    } catch (Exception e) {
        log.error("监听用户行为返利消息,消费失败 topic: {} message: {}", topic, message, e);
        throw e;
    }
}

}

接收返利MQ消息后,进行对象转换,账户调用额度账户创建充值订单操作,完成额度的变更。也就是给用户增加抽奖次数。

设计意图:该类及 listener 方法的设计意图在于利用 Spring 框架与 RabbitMQ 的集成功能,通过配置驱动(获取消息主题和监听队列配置),实现对特定主题下的用户行为返利消息的监听和处理,在消息处理过程中,通过合理的消息解析、业务规则判断以及相应的奖励入账操作,将符合要求(SKU 返利类型)的消息对应的返利奖励准确地记录到业务系统中,同时通过完善的异常处理机制,对不同类型的异常情况进行妥善处理,保证消息处理的可靠性和稳定性,为整个用户行为返利业务流程的顺利进行提供有力支持,确保用户能够按照规则获得相应的返利奖励,并且系统数据能够准确更新。
应用场景:在各类涉及用户行为激励返利的业务场景中应用广泛,比如电商平台中,当用户完成特定的购买行为、分享行为、评价行为等后,系统会根据设定的规则生成相应的返利消息(例如购买某个商品后给予一定数量的该商品库存单元作为返利),并将这些消息发布到 RabbitMQ 中名为 spring.rabbitmq.topic.send_rebate 的主题对应的队列中,此时 RebateMessageCustomer 类的 listener 方法就会监听到这些消息,经过处理后将返利奖励入账到相关的账户或者业务记录中,实现用户行为与返利奖励的关联和记录,方便后续对用户的权益管理、财务统计以及业务运营分析等操作,同时提高整个系统在处理大量用户行为返利业务时的异步处理能力和可靠性。

ActivityRepository#doSaveOrder 变更额度账户的操作增加了更新月、日个人的额度库存。
如果月、日额度存在则更新,不存在则不更新。不存在时候,在用户发起抽奖的时候是可以动态的从总账户中,创建出月和日额度账户的。

三、一些问题
1.这里如果用户签到之后 往user_behavior_rebate_order插入了数据(唯一业务id 2024-12-04) 发送完返利的mq消息之后 下游接收到消息 扣减redis的sku库存 更新数据库sku 之后给用户增加抽奖次数 但是如果“给用户增加抽奖次数这出现问题” 就会导致用户账户额度没有增加 但是sku库存扣减了 然后用户也不能继续签到了 这要怎么解决呢?

这个过程就有mq抛异常,人工介入解决

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions