【RabbitMq/Springboot】给跨库转账增加回访以提高安全性

 转账主动端例程下载:https://files.cnblogs.com/files/heyang78/myBank_tranfer_active_210910.rar

转账被动端例程下载:https://files.cnblogs.com/files/heyang78/myBank_transfer_passive_210910.rar

前作 中提到,如果跨库转账,对方库不存在账户,则转出账户的钱就消失了,为了解决这个问题可以增加一个队列queue02,让远程库把反馈发还回来。

比如说,本地库有个账户001,想给对方库不存在的账户009转账500,于是将“001/009/500”的消息发给queue01,对方发现不存在009,数据库更新记录为零后,就将001/500的信息发给queue02,本地库发现后将001的余额加上500,等于退回了001转出的金额,这是对方不存在的情况;而001想给对方库存在的账户002转500,于是将“001/002/500”的消息发给queue01,对方数据库更新记录为一后,将001/0的消息发给queue02,本地库发现后将001的余额加上0,等于确认了001转账的结果。整个闭环就完成了。

为完成这个闭环,RabbitMq里需要增加一个队列queue02.

转账主动方发送消息部分·:

@Component
public class AccountService {
    @Resource
    private AccountMapper amapper=null;
    
    @Autowired
    private RabbitMqMsgSender mqSender;
    
    @Transactional(rollbackFor=Exception.class) 
    public void remoteTransfer(int amount,String fromAccount,String remoteAcccount) throws TransferException{
        int count=amapper.add(-amount, fromAccount);
        if(count==0) {
            throw new TransferException("对转出账户:"+fromAccount+"操作,更新记录数为0.只有可能是该账户不存在。");
        }
        
        String msg=fromAccount+"/"+remoteAcccount+"/"+amount;
        mqSender.send(msg);
        System.out.println("已向queue01发送消息:"+msg);
    }
}

被动入账方接收消息部分: 

@Component
@RabbitListener(queues="queue01")
public class RabbitMqMsgReceiver {
    @Resource
    private AccountMapper amapper=null;
    
    @Autowired
    RabbitMqMsgSender q02Sender;
    
    @RabbitHandler
    public void QueueReceive(String receivedMsg) {
        System.out.println("T14收到来自queue01的消息:"+receivedMsg);
        
        String[] arr=receivedMsg.split("[//]");
        String fromAccount=arr[0];
        String toAccount=arr[1];
        int amount=Integer.parseInt(arr[2]);
        
        int count=amapper.add(amount, toAccount);
        String msg="";
        if(count==1) {
            msg=fromAccount+"/0";// 表示账户存在,退回金额自然为零
        }else {
            msg=fromAccount+"/"+amount;// 账户不存在,金额全部退回
        }
        
        q02Sender.send(msg);
        System.out.println("T14向queue02发送消息:"+msg);
    }
}

转账主动方获取反馈消息部分:

@Component
@RabbitListener(queues="queue02")
public class RabbitMqMsgReceiver {
    @Resource
    private AccountMapper amapper=null;
    
    @RabbitHandler
    public void QueueReceive(String receivedMsg) {
        System.out.println("T440p收到来自queue02的消息:"+receivedMsg);
        
        String[] arr=receivedMsg.split("[//]");
        String toAccount=arr[0];
        int amount=Integer.parseInt(arr[1]);
        
        amapper.add(amount, toAccount);
    }
}

当然,这个程序还没有考虑宕机的问题。

--END--

原文地址:https://www.cnblogs.com/heyang78/p/15253087.html