下单的二次支付的问题

简介: 下单的二次支付的问题

公众号merlinsea


  • 背景
  • 用户第一次点击下单操作的时候,会弹出支付页面等待用户支付的页面。但可能存在支付异常的情况,比如用户发现金额不够关闭了支付页面,后续通过选择其他支付方式(比如由微信支付转为支付宝支付)或者 不同的端类型(比如第一次是用电脑端支付,后面选择app支付等等)来进行支付,这个时候就会出现二次支付的场景。

  • 解决二次支付问题的思路1:
  • 由于用户支付的时候的支付页面是个html文件或者是一个支付二维码的图片,可以选择将支付页面存在数据库中,用户二次支付时通过查询数据库的支付页面,将页面返回给用户进行再次使用。【特别需要注意的是这个支付页面有没有过期!!】
  • 这种解决思路后台需要自己存储用户的支付页面或者二维码,增加了维护成本;如果支付信息超时了,那么依旧需要二次调用第三方支付。


640.jpg


  • 解决二次支付问题的思路2:


  • 用户第二次支付的时候继续调用第三方支付,让第三方根据是否超时等情况来判断是返回原来的支付页面还是生成一个新的支付页面返回。这种方案便于实现,减轻了自己后台下单的维护成本。

640.jpg


  • 注意点:用户二次支付的时候,订单微服务中是存储了用户第一次下单支付的基本信息的。因此第二次支付的时候,可以通过查询第一次支付的一些基本信息来调用第三方支付,尤其是该订单的【剩余过期时间】。
  • 剩余过期时间:后台调用第三方支付,第三方支付从收到请求信息->处理请求信息->响应请求信息是存在一定的时延的,因此一定不 能死死卡住过期时间来调用第三方支付。需要预留一些时间给第三方支付处理。比如支付过期时间是30分钟,当用户二次支付到达我们下单服务的时候是29分钟那么就拒绝支付。


  • 订单超时支付的策略
  • 策略一:前端显示订单30分钟内需要支付,后端中对第三方支付实际上是31分钟内不能支付 【预留时间给后端和第三方支付交互】
  • 策略二:前端显示订单30分钟内需要支付,后端对第三方的支付实际上是当用户支付请求在地29分钟到后端就不给支付了


  • 思路2的核心代码实现
@Override
@Transactional
public JsonData repay(RepayOrderRequest repayOrderRequest) {
    LoginUser loginUser = LoginInterceptor.threadLocal.get();
    //根据订单流水号查询第一次支付的订单信息
    ProductOrderDO productOrderDO = productOrderMapper.selectOne(new QueryWrapper<ProductOrderDO>().eq("out_trade_no",repayOrderRequest.getOutTradeNo()).eq("user_id",loginUser.getId()));
    log.info("订单状态:{}",productOrderDO);
    if(productOrderDO==null){
        return JsonData.buildResult(BizCodeEnum.PAY_ORDER_NOT_EXIST);
    }
    //订单状态不对,不是NEW状态
    if(!productOrderDO.getState().equalsIgnoreCase(ProductOrderStateEnum.NEW.name())){
        return JsonData.buildResult(BizCodeEnum.PAY_ORDER_STATE_ERROR);
    }else {
        //订单创建到现在的存活时间
        long orderLiveTime = CommonUtil.getCurrentTimestamp() - productOrderDO.getCreateTime().getTime();
        //创建订单是临界点在预留一分钟时间,比如订单实际已经存活了28分钟了,我们就对外说订单已经存活了29分钟。
        orderLiveTime = orderLiveTime + 60*1000;
        //大于订单超时时间,则失效
        if(orderLiveTime>TimeConstant.ORDER_PAY_TIMEOUT_MILLS){
            return JsonData.buildResult(BizCodeEnum.PAY_ORDER_PAY_TIMEOUT);
        }else {
            //记得更新DB订单支付参数 payType,还可以增加订单支付信息日志  TODO
            //总时间-存活的时间 = 剩下的有效时间
            long timeout = TimeConstant.ORDER_PAY_TIMEOUT_MILLS - orderLiveTime;
            //创建支付
            PayInfoVO payInfoVO = new PayInfoVO(productOrderDO.getOutTradeNo(),
                    productOrderDO.getPayAmount(),repayOrderRequest.getPayType(),
                    repayOrderRequest.getClientType(), productOrderDO.getOutTradeNo(),"",timeout);
            log.info("payInfoVO={}",payInfoVO);
            //调用第三方支付
            String payResult = payFactory.pay(payInfoVO);
            if(StringUtils.isNotBlank(payResult)){
                log.info("创建二次支付订单成功:payInfoVO={},payResult={}",payInfoVO,payResult);
                return JsonData.buildSuccess(payResult);
            }else {
                log.error("创建二次支付订单失败:payInfoVO={},payResult={}",payInfoVO,payResult);
                return JsonData.buildResult(BizCodeEnum.PAY_ORDER_FAIL);
            }
        }
    }
}
相关文章
|
前端开发 安全 数据安全/隐私保护
支付宝支付流程解读
支付宝支付流程解读
|
5月前
|
前端开发
支付系统44----支付宝支付-退款查询
支付系统44----支付宝支付-退款查询
支付系统44----支付宝支付-退款查询
支付系统43-----支付宝支付-统一收单退款,全额退款这里可以发起一笔或者两笔订单
支付系统43-----支付宝支付-统一收单退款,全额退款这里可以发起一笔或者两笔订单
支付系统42----支付宝支付-定时查单-订单已支付,如果我们在定时查单的状态中,我们明明已经支付的订单,却在本地状态中显示没有支付,这是因我们的异步通知因为种种原因没有接受到,支付宝端成功,本地失败
支付系统42----支付宝支付-定时查单-订单已支付,如果我们在定时查单的状态中,我们明明已经支付的订单,却在本地状态中显示没有支付,这是因我们的异步通知因为种种原因没有接受到,支付宝端成功,本地失败
|
7月前
|
消息中间件 Java 测试技术
支付宝支付
支付宝支付
183 1
|
数据安全/隐私保护
微信支付系列之——统一下单
微信支付系列之——统一下单
298 2
|
Java 数据安全/隐私保护
支付宝支付功能使用
支付宝支付功能使用
|
弹性计算
阿里云存在未支付订单导致无法下单解决方法
解决阿里云存在未支付订单请支付或作废后再下单,阿里云服务器或其他云资源无法立即购买,提示“您选择的资源存在未支付订单,请支付或作废后再下单!”什么原因?这是由于你的阿里云账号之前已经创建了该订单,只是订单没有支付,所以无法再次创建订单。解决方法是,要么取消之前的订单,要么支付之前的订单。阿里云百科来详细说下阿里云账号下存在未支付订单的解决方法:
1032 0
阿里云存在未支付订单导致无法下单解决方法
|
移动开发 安全 API
支付收银台初探(1)
支付收银台初探
461 0