上期支付模块经过线上H5使用之后会出现支付回调重复调用的现象,导致我实际的业务模块流程上出现多次支付回调记录数据出现混乱。
经过代码优化之后,长时间运行环境下未出现重复回调问题,固更新一下原模块代码,具体如下:
/**
* 支付回调方法
* @param request
* @param response
* @return
* @throws Exception
*/
@RequestMapping(value = "/xxxx", produces = MediaType.APPLICATION_JSON_VALUE + ";charset=UTF-8")
@ResponseBody
public String xxxx(HttpServletRequest request, HttpServletResponse response) throws Exception {
Map<String, Object> map_return = new HashMap<String, Object>();
BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)request.getInputStream()));
String line = null;
StringBuilder sb = new StringBuilder();
while((line = br.readLine()) != null){
sb.append(line);
}
br.close();
//sb为微信返回的xml
String notityXml = sb.toString();
String resXml = "";
System.out.println("接收到的报文:" + notityXml);
Map map = PayUtil.doXMLParse(notityXml);
String returnCode = (String) map.get("return_code");
if (map.get("result_code").toString().equalsIgnoreCase("SUCCESS")) {
// 验证签名是否正确
Map<String, String> validParams = PayUtil.paraFilter(map); // 回调验签时需要去除sign和空值参数
String validStr = PayUtil.createLinkString(validParams);// 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
String sign = PayUtil.sign(validStr, WChatInfo.WX_KEY, "utf-8").toUpperCase();// 拼装生成服务器端验证的签名
// 因为微信回调会有八次之多,所以当第一次回调成功了,那么我们就不再执行逻辑了
// System.out.println("服务器验证的签名"+sign);
// System.out.println("获取到的签名"+map.get("sign"));
// 根据微信官网的介绍,此处不仅对回调的参数进行验签,还需要对返回的金额与系统订单的金额进行比对等
if (sign.equals(map.get("sign"))) {
// 得到返回的参数
// 这边我上面也说过了 同理 需要什么参数 直接通过map.get获取 参数列表我上面也列举了
String order_num = map.get("out_trade_no").toString();
/** 回调逻辑代码编写 */
// 通知微信服务器已经支付成功
request.getSession().setAttribute("message", "支付成功");
resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
} else {
System.out.println("微信支付回调失败!签名不一致");
}
} else {
resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
+ "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
}
System.out.println(resXml);
System.out.println("微信支付回调数据结束");
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
out.write(resXml.getBytes());
out.flush();
out.close();
map_return.put("resXml", resXml.getBytes());
map_return.put("type", true);
map_return.put("massage", "支付成功");
return JsonMapper.getInstance().toJson(map_return);
}
如有不明之处请私信本人,有问必答,如有优化建议也请倾囊相授。