根据订单号加个锁不行嘛
服务器卡顿了15秒,导致同一笔微信支付的两次通知都被处理了,导致充值两次,请大神指点解决方案?如下方代码所示: @RequestMapping(value = "/notifysign") public void notifyUrlSign是接收微信支付通知的controller。 @Transactional public boolean notifyUrlSign是具体处理接收通知后续业务的函数 两个方法的具体代码在最下方,我先描述问题: 问题在方法public boolean notifyUrlSign中,(pltfWebpayflow.getPaysStatus().equals((short) 0))是关键标识,只有在pltfWebpayflow表的PaysStatus字段值是0时,才处理这笔支付的后续业务表。并且在if (pltfWebpayflow.getPaysStatus().equals((short) 0))判断通过之后,首先就pltfWebpayflow.setPaysStatus((short) 1);并且pltfWebpayflowJPA.saveAndFlush(pltfWebpayflow);保存了这个表,就是为了防止同一笔微信支付被重复处理。 现在的问题是,一笔微信支付的第一次通知发给我的服务器,由于访问量大等原因程序卡顿了一段时间应该有15秒,应该是卡在了if (pltfWebpayflow.getPaysStatus().equals((short) 0))的判断成功之后,然后服务器又接收到该笔支付的第二次通知,此时可能程序卡顿恢复了。 因为上一次通知还没有处理完,pltfWebpayflow表的PaysStatus字段值此时还是0,导致第二次通知又被处理了,也就是该笔支付的两次微信通知都在同时处理,也就是同一笔微信支付被处理了两次,zhxx.setYe(zhxx.getYe().add(fee));业务流水被加了两次。 服务器硬件确实不太好,偶尔会出现这种现象,我也没有升级硬件的权利,请大神从程序上给个修改解决建议,谢谢。 详细代码如下: @RequestMapping(value = "/notifysign") public void notifyUrlSign(HttpServletRequest request, HttpServletResponse response) throws Exception { String re = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>"; Map<String, String> map = WxWebXml.parseXml(request, logger); logger.debug("notimsg: " + JSON.toJSONString(map)); if (map.get("return_code").equals("SUCCESS")) { if (map.get("result_code").equals("SUCCESS")) { if (wxWebService.notifyUrlSign(map, request, response)) { re = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>"; } } } // response.getOutputStream().println(re); PrintWriter out = response.getWriter(); out.print(re); out.flush(); out.close(); // return re; } @Transactional public boolean notifyUrlSign(Map<String, String> map, HttpServletRequest request, HttpServletResponse response) { String ottrid = map.get("out_trade_no"); BigDecimal fee = new BigDecimal(map.get("total_fee")); logger.debug("notifysgstart"); PltfWebpayflow pltfWebpayflow = pltfWebpayflowJPA.findOne(ottrid); SortedMap<String, Object> sortedMap = new TreeMap<>(map); String sgin = WxPayTool.createWxPaySign(WxConstants.KEY, sortedMap, logger); logger.info("notifysign: " + sgin + " , " + JSONObject.toJSONString(pltfWebpayflow)); if (pltfWebpayflow != null && pltfWebpayflow.getTotalAmount().compareTo(fee) == 0 && sgin.equals(map.get("sign"))) { if (pltfWebpayflow.getPaysStatus().equals((short) 0)) { logger.info("notifystart567"); DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); LocalDateTime ldt = LocalDateTime.parse(map.get("time_end"), dtf); Date date = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant()); QZhxxCk qZhxxCk = QZhxxCk.zhxxCk; logger.debug("notifystart123"); Integer lshmax = queryFactory.select(qZhxxCk.lsh.max()).from(qZhxxCk).fetchFirst(); if (lshmax == null) { lshmax = 0; } logger.info("notifystart2: " + lshmax); ZhxxCk zhxxCk = new ZhxxCk(); zhxxCk.setYpaysStatus(pltfWebpayflow.getPaysStatus()); pltfWebpayflow.setFeeType(map.get("fee_type")); pltfWebpayflow.setReturnMsg(map.get("return_msg")); pltfWebpayflow.setGmtPayment(date); pltfWebpayflow.setIsnotify((short) 1); pltfWebpayflow.setPaysStatus((short) 1); pltfWebpayflow.setResultCode(map.get("result_code")); pltfWebpayflow.setReturnCode(map.get("return_code")); pltfWebpayflow.setTradeNo(map.get("transaction_id")); if (map.get("is_subscribe") != null) { pltfWebpayflow.setIssubscribe((map.get("is_subscribe"))); } pltfWebpayflowJPA.saveAndFlush(pltfWebpayflow); logger.info("notifyplwf CK: " + JSONObject.toJSONString(pltfWebpayflow)); Zhxx zhxx = zhxxJPA.findOne(pltfWebpayflow.getForeignkey()); logger.info("notifyzhxx 1 CK: " + JSONObject.toJSONString(zhxx)); if (zhxx.getYe() == null) { zhxx.setYe(new BigDecimal("0")); } fee = fee.divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP); zhxxCk.setYye(zhxx.getYe()); zhxx.setYe(zhxx.getYe().add(fee)); zhxxJPA.saveAndFlush(zhxx); logger.info("notifyzhxx 2 CK: " + JSONObject.toJSONString(zhxx)); // Date now = new Date(); zhxxCk.setId(UUID.randomUUID().toString().toUpperCase().replaceAll("-", "")); zhxxCk.setZh(zhxx.getZh()); zhxxCk.setCkrq(date); zhxxCk.setBenh(zhxx.getBenh()); zhxxCk.setYysh(zhxx.getBenh().substring(0, 2)); zhxxCk.setKh(zhxx.getKh()); zhxxCk.setXm(zhxx.getXm()); zhxxCk.setDz(zhxx.getDz()); zhxxCk.setCkje(fee); zhxxCk.setYe(zhxx.getYe()); zhxxCk.setJsry("888888"); zhxxCk.setOpName("微信支付"); DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); String str = dateFormat.format(date); zhxxCk.setRq(str); zhxxCk.setLsh(lshmax + 1); zhxxCk.setGmtPayment(pltfWebpayflow.getGmtPayment()); zhxxCk.setIsnotify(pltfWebpayflow.getIsnotify()); zhxxCk.setOutTradeNo(pltfWebpayflow.getOutTradeNo()); zhxxCk.setTradeNo(pltfWebpayflow.getTradeNo()); zhxxCk.setPaysStatus(pltfWebpayflow.getPaysStatus()); zhxxCkJPA.saveAndFlush(zhxxCk); logger.info("notify CK: " + JSONObject.toJSONString(zhxxCk)); ZhxxWxwebRec3 zhxxWxwebRec3; QZhxxWxwebRec3 qZhxxWxwebRec3 = QZhxxWxwebRec3.zhxxWxwebRec3; List<ZhxxWxwebRec3> bczxxWxwebRec3s = (List<ZhxxWxwebRec3>) zhxxWxwebRec3JPA.findAll(qZhxxWxwebRec3.openid .eq(pltfWebpayflow.getOpenid()).and(qZhxxWxwebRec3.zh.eq(zhxx.getZh()))); if (bczxxWxwebRec3s.size() > 0) { zhxxWxwebRec3 = bczxxWxwebRec3s.get(0); } else { zhxxWxwebRec3 = new ZhxxWxwebRec3(); } zhxxWxwebRec3.setOpenid(pltfWebpayflow.getOpenid()); zhxxWxwebRec3.setZh(zhxx.getZh()); zhxxWxwebRec3.setId(zhxxCk.getId()); zhxxWxwebRec3JPA.saveAndFlush(zhxxWxwebRec3); logger.info("notifyRec CK: " + JSONObject.toJSONString(zhxxWxwebRec3)); // int i=1/0; } else { logger.info("notifystartOver"); } return true; } return false; }
2023-11-29