微服务项目:尚融宝(52)(核心业务流程:充值服务(3))

一、接口幂等性原则

1、什么是接口幂等性

接口幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次调用而产生了副作用。

举个最简单的例子,那就是支付,用户购买商品后支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额返发现多扣钱了,流水记录也变成了两条...这就没有保证接口的幂等性

2、回调重试

汇付宝向尚融宝发起回调,如果没有收到正确的响应 "success",则尚融宝会发起重试

汇付宝中的相关代码如下:

@Slf4j
public class NotifyThread implements Runnable {

    private int count = 1;
    private String notifyUrl;
    private Map paramMap;

    public NotifyThread(){}

    public NotifyThread(String notifyUrl, Map paramMap) {
        this.notifyUrl = notifyUrl;
        this.paramMap = paramMap;
    }

    @Override
    public void run() {
        task();
    }

    private void task() {
        String result = SignUtil.sendRequest(paramMap,notifyUrl);
        log.info(notifyUrl + ":" + result + " count:" + count);
        if(!"success".equals(result)) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //ScheduledTask.queue.offer(new NotifyVo(notifyUrl, paramMap));
            count++;
            if(count <= 5) {
                task();
                log.info("失败重试:" + JSON.toJSONString(this));
            }
        }
    }
}

3、存在的问题

当回调重试时,金额和流水会重复增加

 微服务项目:尚融宝(52)(核心业务流程:充值服务(3))_第1张图片

二、解决方案

1、设置唯一索引

设置了唯一索引后,即使回调重复执行,遇到唯一索引,就会抛出异常,从而使事务回滚。

 微服务项目:尚融宝(52)(核心业务流程:充值服务(3))_第2张图片

2、判断流水是否存在

判断流水如果存在,则从业务方法中直接退出

接口:TransFlowService

boolean isSaveTransFlow(String agentBillNo);

实现:TransFlowServiceImpl 

@Override
public boolean isSaveTransFlow(String agentBillNo) {
    QueryWrapper queryWrapper = new QueryWrapper();
    queryWrapper.eq("trans_no", agentBillNo);
    int count = baseMapper.selectCount(queryWrapper);
    if(count > 0) {
        return true;
    }
    return false;
}

调用 :UserAccountServiceImpl 

@Transactional(rollbackFor = Exception.class)
@Override
public void notify(Map paramMap) {

    log.info("充值成功:" + JSONObject.toJSONString(paramMap));

    //判断交易流水是否存在
    String agentBillNo = (String)paramMap.get("agentBillNo"); //商户充值订单号
    boolean isSave = transFlowService.isSaveTransFlow(agentBillNo);
    if(isSave){
        log.warn("幂等性返回");
        return;
    }

   ......
       
    //增加交易流水
    //agentBillNo = (String)paramMap.get("agentBillNo"); //商户充值订单号

}

今日分享 

 1. 硬件的目的:为了运行软件给它的一些指令。我们可以优先从硬件中提取出这三个主要的东西,分别是: CPU,内存,硬盘

       2. 在现实生活中,人脑是用来计算的,在计算机中,用来计算的是什么呢?当然是CPU了。多数CPU都有两种模式,即内核态与用户态。这里的即内核态与用户态将会在下面的内容中讲到。

       3.如果我们把计算机理解为人的大脑,我们可以总结为几句话:

               CPU是人的大脑,负责运算

        内存是人的记忆,负责临时存储

        硬盘是人的笔记本,负责永久存储

        输入设备是人的耳朵或眼睛,负责接受外部的信息传给CPU

        以上所有的设备都通过总线连接,总线相当于人的神经

你可能感兴趣的:(微服务项目:尚融宝,java,开发语言,微服务,云原生,架构)