Wechat paiement rappel répété, java problème de rappel de paiement Wechat

J'ai étudié la question des rappels de paiement WeChat ces jours-ci. J'ai trouvé que les rappels de paiement WeChat étaient normaux avant et je m'en fichais beaucoup. Quand je l'ai testé sur mon projet aujourd'hui, j'ai constaté que le même code était toujours exécuté à plusieurs reprises sur mon projet. La logique de rappel a été exécutée une fois le paiement effectué, ce qui est un casse-tête. La logique de rappel est en cours d'exécution, indiquant que le rappel est exécuté normalement

Quelques réponses données en ligne:

  WeChat n'a pas reçu le message SUCCESS normalement, suggérant resXml:

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

Modifier à: resXml = "SUCCESS";

 

Certaines personnes pensent également que cette méthode est faisable, mais je n'ai pas été en mesure de la mettre en œuvre avec succès.

    Certaines personnes ont dit qu'il avait été modifié pour

resXml = "<xml>" + "<return_code> SUCCÈS </return_code>" + "<return_msg> OK </return_msg>" + "</xml>";

Certaines personnes ont dit que je pouvais le modifier ou non.

Jetez d'abord un œil à mon code de rappel de paiement ( ici, seul le rappel de paiement WeChat est mentionné, car nous devrions tous passer par le paiement WeChat, j'ai également un article sur le paiement WeChat, cliquez sur ce lien )

/**
 * @author SpringRoot
 * @description 微信支付回调
 * @date 2020/3/4-11:17
 */
@Service
public class WeiXinPayNotifyServiceImpl implements WeiXinPayNotifyService {
    private final static Logger LOGGER = LoggerFactory.getLogger(WeiXinPayNotifyServiceImpl.class);

    @Override
    public 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();
        }
    }
}

Voici les paramètres qui peuvent être appelés pour les rappels de paiement WeChat. Vous voyez ce que votre projet utilisera. En règle générale, vous pouvez obtenir le numéro de commande et opérer via le numéro de commande ( cliquez ici pour afficher le document JSAPI de rappel de paiement WeChat ):

Autrement dit, ce qui précède peut être retourné à la valeur correspondante via packageParams.get (").

Ce qui suit est modifié après avoir fait référence à un blog, qui répond à mes exigences: Le lien est le suivant: 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为微信返回的xml
        String 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();
    }

Les outils utilisés:

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) {
// 创建SSLContext
        StringBuffer 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 block
            e.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());
    }
}

 

Je suppose que tu aimes

Origine blog.csdn.net/baidu_39322753/article/details/104672971
conseillé
Classement