这几天一直在研究微信支付回调这个问题,发现之前微信支付回调都是正常的也没怎么在意,今天在自己项目上测试的时候发现相同的代码在我这个项目上微信支付回调老是重复执行导致支付成功之后的回调逻辑一直在执行,很头疼。回调逻辑都在执行,说明回调正常执行

网上有些给的答案:

  微信没有正常接收到SUCCESS消息建议将resXml:

resXml ="<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";

修改为:resXml = "SUCCESS";

也有人反映这个方法可行,但是我自己这边没能执行成功。

也有部分人说修改成

resXml ="<xml>" + "<return_code>SUCCESS</return_code>"+ "<return_msg>OK</return_msg>" + "</xml> ";

同样部分人说可以 我修改了还是不行。

首先看下我的支付回调代码(这边只说微信支付回调,因为到这里应该都是微信支付通了的吧,我也有一篇是写微信支付的,点击这个链接)

/*** @author SpringRoot* @description 微信支付回调* @date 2020/3/4-11:17*/
@Service
public class WeiXinPayNotifyServiceImpl implements WeiXinPayNotifyService {private final static Logger LOGGER = LoggerFactory.getLogger(WeiXinPayNotifyServiceImpl.class);@Overridepublic void weixinpay_notify(HttpServletRequest request,HttpServletResponse response) {/**这些是通过微信支付,返回可以得到一些值   具体如下截图   这个代码可以不用管  下面会继续给出成功且不重复回调的代码    这边的支付都是JSAPA支付*/InputStream inputStream;StringBuffer sb = new StringBuffer();try {inputStream = request.getInputStream();String s;BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));while ((s = in.readLine()) != null) {sb.append(s);}in.close();inputStream.close();Map<String, String> m = new HashMap<String, String>();m = WXUtil.doXMLParse(sb.toString());SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();Iterator it = m.keySet().iterator();while (it.hasNext()) {String parameter = (String) it.next();String parameterValue = m.get(parameter);String v = "";if (null != parameterValue) {v = parameterValue.trim();}packageParams.put(parameter, v);}String key = WxPayPojo.MCH_KEY; // 秘钥   这个就是你的微信商户平台的秘钥if (WXUtil.isTenpaySign("UTF-8", packageParams, key)) {String resXml = "";if ("SUCCESS".equals((String) packageParams.get("result_code"))) {// 得到返回的参数String openid = (String) packageParams.get("openid");String transaction_id = (String) packageParams.get("transaction_id");String orderNumberMain = (String) packageParams.get("out_trade_no");// 这里可以写你需要的业务LOGGER.debug("我是回调函数啊!---我执行了---------------------");LOGGER.debug("openid---->" + openid);LOGGER.debug("transaction_id---->" + transaction_id);LOGGER.debug("out_trade_no---->" + orderNumberMain);resXml ="<xml>"+ "<return_code><![CDATA[SUCCESS]]></return_code>"+ "<return_msg><![CDATA[OK]]></return_msg>"+ "</xml> ";BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());out.write(resXml.getBytes());out.flush();out.close();return;} else {LOGGER.debug("回调失败");}} else {LOGGER.debug("回调失败");}} catch (IOException e) {e.printStackTrace();} catch (JDOMException e) {e.printStackTrace();}}
}

下面是微信支付回调可以调用的参数,你看你项目会用到什么,一般来说获取到订单编号  通过订单编号操作(点击这里查看微信支付回调JSAPI文档):

即上面的都可以通过packageParams.get(")  对应的到返回值。

下面是我参考一个博客之后修改的,符合我的这个要求:链接如下:https://blog.csdn.net/qq_37105358/article/details/81285779

/*** 微信小程序支付成功回调函数* @param request* @param response* @throws Exception*/@RequestMapping(value = "/weixinpay/notify")public void wxNotify(HttpServletRequest request,HttpServletResponse response) throws Exception{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为微信返回的xmlString notityXml = sb.toString();String resXml = "";System.out.println("接收到的报文:" + notityXml);Map map = PayUtil.doXMLParse(notityXml);String returnCode = (String) map.get("return_code");if("SUCCESS".equals(returnCode)){//验证签名是否正确Map<String, String> validParams = PayUtil.paraFilter(map);  //回调验签时需要去除sign和空值参数String validStr = PayUtil.createLinkString(validParams);//把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串String sign = PayUtil.sign(validStr, WxPayPojo.MCH_KEY, "utf-8").toUpperCase();//拼装生成服务器端验证的签名// 因为微信回调会有八次之多,所以当第一次回调成功了,那么我们就不再执行逻辑了//根据微信官网的介绍,此处不仅对回调的参数进行验签,还需要对返回的金额与系统订单的金额进行比对等if(sign.equals(map.get("sign"))){// 得到返回的参数//这边我上面也说过了  同理   需要什么参数  直接通过map.get获取   参数列表我上面也列举了String openid = (String) map.get("openid");String transaction_id = (String) map.get("transaction_id");String orderNumberMain = (String) map.get("out_trade_no");/**回调逻辑代码编写*///通知微信服务器已经支付成功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();}

用到的工具类:

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.SignatureException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;import org.apache.commons.codec.digest.DigestUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;public class PayUtil {/***      * 签名字符串*      * @param text 需要签名的字符串*      * @param key 密钥*      * @param input_charset 编码格式*      * @return 签名结果*      */public static String sign(String text, String key, String input_charset) {text = text + "&key=" + key;return DigestUtils.md5Hex(getContentBytes(text, input_charset));}/***      * 签名字符串*      *  @param text 需要签名的字符串*      * @param sign 签名结果*      * @param key 密钥*      * @param input_charset 编码格式*      * @return 签名结果*      */public static boolean verify(String text, String sign, String key, String input_charset) {text = text + key;String mysign = DigestUtils.md5Hex(getContentBytes(text, input_charset));if (mysign.equals(sign)) {return true;} else {return false;}}/***      * @param content*      * @param charset*      * @return*      * @throws SignatureException*      * @throws UnsupportedEncodingException*      */public static byte[] getContentBytes(String content, String charset) {if (charset == null || "".equals(charset)) {return content.getBytes();}try {return content.getBytes(charset);} catch (UnsupportedEncodingException e) {throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);}}private static boolean isValidChar(char ch) {if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))return true;if ((ch >= 0x4e00 && ch <= 0x7fff) || (ch >= 0x8000 && ch <= 0x952f))return true;// 简体中文汉字编码return false;}/***      * 除去数组中的空值和签名参数*      * @param sArray 签名参数组*      * @return 去掉空值与签名参数后的新签名参数组*      */public static Map<String, String> paraFilter(Map<String, String> sArray) {Map<String, String> result = new HashMap<String, String>();if (sArray == null || sArray.size() <= 0) {return result;}for (String key : sArray.keySet()) {String value = sArray.get(key);if (value == null || value.equals("") || key.equalsIgnoreCase("sign")|| key.equalsIgnoreCase("sign_type")) {continue;}result.put(key, value);}return result;}/***      * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串*      * @param params 需要排序并参与字符拼接的参数组*      * @return 拼接后字符串*      */public static String createLinkString(Map<String, String> params) {List<String> keys = new ArrayList<String>(params.keySet());Collections.sort(keys);String prestr = "";for (int i = 0; i < keys.size(); i++) {String key = keys.get(i);String value = params.get(key);if (i == keys.size() - 1) {// 拼接时,不包括最后一个&字符prestr = prestr + key + "=" + value;} else {prestr = prestr + key + "=" + value + "&";}}return prestr;}/***      **      * @param requestUrl 请求地址*      * @param requestMethod 请求方法*      * @param outputStr 参数*      */public static String httpRequest(String requestUrl, String requestMethod, String outputStr) {
// 创建SSLContextStringBuffer buffer = null;try {URL url = new URL(requestUrl);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod(requestMethod);conn.setDoOutput(true);conn.setDoInput(true);conn.connect();//往服务器端写内容if (null != outputStr) {OutputStream os = conn.getOutputStream();os.write(outputStr.getBytes("utf-8"));os.close();}// 读取服务器端返回的内容InputStream is = conn.getInputStream();InputStreamReader isr = new InputStreamReader(is, "utf-8");BufferedReader br = new BufferedReader(isr);buffer = new StringBuffer();String line = null;while ((line = br.readLine()) != null) {buffer.append(line);}br.close();} catch (Exception e) {e.printStackTrace();}return buffer.toString();}public static String urlEncodeUTF8(String source) {String result = source;try {result = java.net.URLEncoder.encode(source, "UTF-8");} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();}return result;}/***      * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。*      * @param strxml*      * @return*      * @throws JDOMException*      * @throws IOException*      */public static Map doXMLParse(String strxml) throws Exception {if (null == strxml || "".equals(strxml)) {return null;}Map m = new HashMap();InputStream in = String2Inputstream(strxml);SAXBuilder builder = new SAXBuilder();Document doc = builder.build(in);Element root = doc.getRootElement();List list = root.getChildren();Iterator it = list.iterator();while (it.hasNext()) {Element e = (Element) it.next();String k = e.getName();String v = "";List children = e.getChildren();if (children.isEmpty()) {v = e.getTextNormalize();} else {v = getChildrenText(children);}m.put(k, v);}//关闭流in.close();return m;}/***      * 获取子结点的xml*      * @param children*      * @return String*      */public static String getChildrenText(List children) {StringBuffer sb = new StringBuffer();if (!children.isEmpty()) {Iterator it = children.iterator();while (it.hasNext()) {Element e = (Element) it.next();String name = e.getName();String value = e.getTextNormalize();List list = e.getChildren();sb.append("<" + name + ">");if (!list.isEmpty()) {sb.append(getChildrenText(list));}sb.append(value);sb.append("</" + name + ">");}}return sb.toString();}public static InputStream String2Inputstream(String str) {return new ByteArrayInputStream(str.getBytes());}
}

微信支付重复回调,java微信支付回调问题相关推荐

  1. java微信html5上传图片代码,java微信接口之四—上传素材

    一.微信上传素材接口简介 1.请求:该请求是使用post提交地址为: https://api.weixin.qq.com/cgi-bin/media/uploadnews?access_token=A ...

  2. 微信端权限控制java,微信支付:特约子商户商户号未授权服务商的产品权限 的解决方案...

    [授权关系建立] 1. 开启"服务商API退款"功能.为保证特约商户的资金安全,服务商默认没有特约商户的退款权限.但在实际的运作中,特约商户可以将自己的退款权限授权给服务商,允许服 ...

  3. 5行代码实现微信模版消息推送,springboot实现微信推送,java微信推送

    视频讲解:https://edu.csdn.net/course/detail/23750 今天来带大家学习下微信模版消息推送. 先看效果图: 核心代码只有下面几行,即可轻松实现微信模版消息推送 // ...

  4. java 微信公众号菜单,Java 微信公众号菜单关联小程序

    最近微信公众号开发了菜单关联小程序功能,实现代码如下 /** * 自定义菜单工具类 * @author why * */ public class MenuUtil { private static ...

  5. 微信 语音转文字 java,微信语音转文字怎么操作?手把手教你,一秒钟搞定!

    原标题:微信语音转文字怎么操作?手把手教你,一秒钟搞定! ‍微信语音转文字怎么操作?相信多数人都知道微信有这样的功能,但真正操作起来不知道怎么做,也不知道能够适用于哪些场景.下面就来教大家手把手操作: ...

  6. java微信小程序毕业设计 java微信校园社团小程序系统毕业设计开题报告参考

    功能 用户注册登录:注册普通账号,然后使用注册的账号登录登录 微信授权登录:直接使用微信作为账号,授权后登录 资讯功能:用户可以任意浏览资讯列表和详细信息    活动列表:查看平台发布的所有活动列表信 ...

  7. java微信支付v3系列——5.微信支付成功回调

    目录 java微信支付v3系列--1.微信支付准备工作 java微信支付v3系列--2.微信支付基本配置 java微信支付v3系列--3.订单创建准备操作 java微信支付v3系列--4.创建订单的封 ...

  8. java微信支付v3系列——8.微信支付之退款成功回调

    目录 java微信支付v3系列--1.微信支付准备工作 java微信支付v3系列--2.微信支付基本配置 java微信支付v3系列--3.订单创建准备操作 java微信支付v3系列--4.创建订单的封 ...

  9. java微信支付v3系列——6.微信支付查询订单API

    目录 java微信支付v3系列--1.微信支付准备工作 java微信支付v3系列--2.微信支付基本配置 java微信支付v3系列--3.订单创建准备操作 java微信支付v3系列--4.创建订单的封 ...

  10. java微信支付v3系列——1.微信支付准备工作

    目录 java微信支付v3系列--1.微信支付准备工作 java微信支付v3系列--2.微信支付基本配置 java微信支付v3系列--3.订单创建准备操作 java微信支付v3系列--4.创建订单的封 ...

最新文章

  1. 重载和覆盖的区别?(overload vs override)
  2. VTK:快速傅里叶变换用法实战
  3. java中集合判空_Java中的类型安全的空集合
  4. aix linux ftp,在AIX下安装配置FTP服务器
  5. python 服务器_NeurDICOM——DICOMweb服务器端Python实现范例
  6. SHELL中的变量和参数
  7. 大巴山计算机教育中心那所学校,大巴山计算机教育中心
  8. 喵哈哈村的魔法考试 Round #14 (Div.2) 题解
  9. java.lang.ClassNotFoundException: com.mysql.jdbc.Driver,网页一直处于加载中,servlet+html+js+css项目难题解决
  10. php去掉文字空白换行,php去掉空格换行的方法
  11. Freeswitch+Sip.js实现软电话功能
  12. 基于Redis的分布式链家二手房房源数据爬虫系统 毕业设计
  13. 使用编辑器为模型批量设置 替换lod模型
  14. android 支持最低版本是多少g,手机需要多少G的运行内存,才真正够用?
  15. 面试必问---TCP连接
  16. 记录一次使用Autowired报Nullpoint空指针异常的错误
  17. [转]脑梗塞的诊治指南
  18. 北交所开通知识测评 测试题答案(海通)
  19. KVM内核文档阅读笔记
  20. 展讯的8825平台 在TP上实现距离传感器的功能

热门文章

  1. UltraISO 创建的虚拟光驱盘符 G 更改为 H
  2. labelImg启动闪退的解决方法
  3. FPGA图像处理——cameralink发送设计实现之改进版
  4. 期末学生HTML个人网页作业作品~蓝色的异清轩响应式个人博客模板源码~bootstrap响应式博客网站模板html
  5. android-x86编译
  6. 华硕A456UR7500完美黑苹果安装教程
  7. todo工具、日程管理工具、桌面日程清单app——:日历清单(mac)
  8. 亚马逊有什么技巧打造爆款?亚马逊怎样打造爆款产品?
  9. linux intel 关闭睿频
  10. 《各大IT公司薪金大曝光》(资料版)