支付之订单重复支付


layout: post title: "支付之订单重复支付" subtitle: " "如何防止订单重复支付"" date: 2018-10-17 06:00:00 author: "青乡" header-img: "img/post-bg-2015.jpg" catalog: true tags: - 支付

重复支付到底指什么?什么情况下会导致重复支付呢?

下游商家的同一笔订单,在支付系统生成了2笔订单,支付的时候就会支付2次。

所以,问题的关键在于避免支付系统生成2笔订单,或者说,要确保支付系统只生成1笔订单。这是第一点,就是只生成1笔订单。

第二点,现在要对这笔订单数据进行支付,如果商家重复点击支付按钮,支付系统这边只有1笔订单,而且取到的订单数据始终是同一笔订单数据。


总结
支付系统确保2点
1.生成订单的时候,确保只生成1笔订单数据
2.支付的时候,确保取到的始终是同一笔订单数据


流程图

如何确保支付系统只生成1笔订单数据

技术
1.缓存
2.token //UUID


步骤
1.生成订单 //把订单数据放到缓存
cache.add(token,order); //token传给商家客户端

//代码

/**
	 * 收款码参数验证网关
	 * @return
	 */
	@RequestMapping("/checkpay")
	public ModelAndView checkpay(MerchantDTO merchantDTO){
		ModelAndView mav=new ModelAndView("dopay");
		try {
			//1.校验参数
			log.info("merchantDTO info is :"+merchantDTO);
	     	ValidateHelper.asertPass(merchantDTO);
	     	
	     	payService.handleAbnormalUser(merchantDTO.getMerchantId());
	     	
//	     	//2.组装订单对象
	     	Order order = payService.bizCheckMerchant(merchantDTO); //生成订单数据
	     	
	     	String tokenId = UUIDValueGenerator.generateValue();
	     	
//			//3.存储商户信息在缓存
			cache.add(tokenId, 5*60, order); //订单数据放到缓存
			
			mav.addObject("tokenId",tokenId); //token传给客户端
			mav.addObject("siteId",merchantDTO.getSiteId());
			
		} catch (ValidateException ve) {
			log.info(ve.getMessage());
			mav.addObject("msg", ve.getMessage());
			mav.setViewName("error");
		}catch (BizException be){
			log.info(be.getMessage());
			mav.addObject("msg", be.getMessage());
			mav.setViewName("error");
		}catch (Exception e){
			log.info(e.getMessage());
			mav.addObject("msg", e.getMessage());
			mav.setViewName("error");
		}
		return mav;
	}
复制代码

2.支付 //从缓存取订单数据
cache.get(token);

/**
	 * 收款码充值支付网关
	 * @author 
	 * @param request response dopayDTO
	 */
	@RequestMapping("/dopay")
	public void dopay(HttpServletRequest request, HttpServletResponse response, @ModelAttribute DopayDTO dopayDTO ){
		ResposeDTO rseponseDTO = new ResposeDTO();
		try {
			
			//1.校验参数
			log.info("dopayDTO info is :"+dopayDTO);
	     	ValidateHelper.asertPass(dopayDTO);
			Order order = (Order) cache.get(dopayDTO.getTokenId()); //支付的时候:从缓存取订单数据
			
			if(null == order){ //缓存数据失效
				throw new BizException("订单已失效");
			}
			
			//金额校验
			if(!dopayDTO.getOrderMoney().toString().matches("^(?!(0[0-9]{0,}$))[0-9]{1,}[.]{0,}[0-9]{0,2}$")){
				rseponseDTO.setStatus(ResponseStatus.MOBILE_STATUS_INPUTYZ.getCode());
				rseponseDTO.setRemark(ResponseStatus.MOBILE_STATUS_INPUTYZ.getDesc());
				outJson(rseponseDTO, response);
				return;
				
			}
			if(Double.valueOf(dopayDTO.getOrderMoney().toString())>Double.valueOf(MAXPAYAMT)){
				rseponseDTO.setStatus(ResponseStatus.MOBILE_STATUS_MAXAMT.getCode());
				rseponseDTO.setRemark(ResponseStatus.MOBILE_STATUS_MAXAMT.getDesc());
				outJson(rseponseDTO, response);
				return;

			}
			
			if(Double.valueOf(dopayDTO.getOrderMoney().toString())return;
			}
		
			//2.处理业务
			GetPayCommandResponse getPayCommandResponse =  payService.bizDopay(dopayDTO,order); //1.保存订单到数据库 2.调用支付服务
			
			//3.返回参数
			rseponseDTO.setStatus(ResponseStatus.MOBILE_STATUS_SUCCESS.getCode());
			rseponseDTO.setPostAddress(getPayCommandResponse.getPostAddress());
			rseponseDTO.setParamsMap(getPayCommandResponse.getParams());
			outJson(rseponseDTO, response);
			
		} catch (ValidateException ve) {
			log.error(ve.getMessage(),ve);
			rseponseDTO.setStatus(ResponseStatus.MOBILE_STATUS_ERROR.getCode());
			rseponseDTO.setRemark(ResponseStatus.MOBILE_STATUS_ERROR.getDesc());
			outJson(rseponseDTO, response);
		}catch (BizException be){
			log.error(be.getMessage(),be);
			rseponseDTO.setStatus(ResponseStatus.MOBILE_STATUS_ERROR.getCode());
			rseponseDTO.setRemark(ResponseStatus.MOBILE_STATUS_ERROR.getDesc());
			outJson(rseponseDTO, response);
		}catch (Exception e) {
			log.error(e.getMessage(),e);
			rseponseDTO.setStatus(ResponseStatus.MOBILE_STATUS_ERROR.getCode());
			rseponseDTO.setRemark(ResponseStatus.MOBILE_STATUS_ERROR.getDesc());
			outJson(rseponseDTO, response);
		}
		
	}
复制代码

幂等

能解决上文提到的问题,就叫幂等。

就是同一笔数据,不能重复处理。或者说,同一笔数据,处理结果一样。


什么操作幂等?什么操作不幂等?
1.查询 //天然幂等 2.修改 //不幂等,需要解决幂等的问题

如何防止重复提交

就是如何防止重复电点击提交按钮?
前端处理,置灰按钮。

参考

tech.meituan.com/distributed…

转载于:https://juejin.im/post/5c09ffc6e51d451dc066fcc3

你可能感兴趣的:(支付之订单重复支付)