如下方代码所示:
@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;
}
根据订单号加个锁不行嘛
然后把在写入这个表的订单id的同一个事务去修改账户充值。
然后第一条可以正常充值,第二笔就充值失败了