微信公众号支付流程解读及支付签名验证方法

mac2026-08-05  10

 微信公众号支付大致分为以下几步:

   1.获取openID:微信公众号支付一个重要的参数就是openID,此步骤可以查阅相关文档

   2.获取支付相关参数:appid:公众账号ID,mch_id:商户号,nonce_str:随机字符串,sign_type:签名类型,out_trade_no:商户订单号,total_fee:标价金额(交易金额默认为人民币交易,接口中参数支付金额单位为【分】,参数值不能带小数),spbill_create_ip:终端IP,notify_url:通知地址,trade_type:交易类型,openid:用户标识,sign:签名

               TreeMap paramMap = new TreeMap();paramMap.put("appid", PaymentConst.WECHAT_APPID);//公众账号IDparamMap.put("mch_id", PaymentConst.WECHAT_MCHID);//商户号paramMap.put("nonce_str", Util.getRandomString(30, null));//随机字符串paramMap.put("sign_type", PaymentConst.WECHAT_SIGNTYPE);//签名类型//paramMap.put("body", "爱检查医疗套餐支付");//商品描述paramMap.put("body", "Melical Fee");//商品描述paramMap.put("out_trade_no", orderMain.getNumber());//商户订单号//交易金额默认为人民币交易,接口中参数支付金额单位为【分】,参数值不能带小数。paramMap.put("total_fee", (int)(orderMain.getTotalamount()*100));//标价金额paramMap.put("spbill_create_ip", Util.getIpAddr(request));//终端IPparamMap.put("notify_url", weChatNotifyUrl);//通知地址paramMap.put("trade_type", PaymentConst.WECHAT_TRADETYPE_JSAPI);//交易类型paramMap.put("openid", openid);//用户标识paramMap.put("sign",Signature.createSign("UTF-8", paramMap));//签名

  3.签名算法:

       public static String createSign(String characterEncoding,SortedMap<String,Object> parameters){StringBuffer sb = new StringBuffer();Set es = parameters.entrySet();Iterator it = es.iterator();while(it.hasNext()) {Map.Entry entry = (Map.Entry)it.next();String k = (String)entry.getKey();Object v = entry.getValue();if(null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {sb.append(k + "=" + v + "&");}}sb.append("key=" + PaymentConst.WECHAT_KEY);System.out.println("签名:"+sb.toString());String sign =MD5.GetMD5Code(sb.toString()).toUpperCase();return sign;}

     4.请求:

        String response = HttpClientUtil.post(PaymentConst.wechatPayUrl,new String( XMLUtils.simpleMapToXml(paramMap).getBytes(), "UTF-8"));

    5.XMLUtils.simpleMapToXml 方法:

      public static String simpleMapToXml(Map<String, Object> map){         StringBuilder xmlString = new StringBuilder();         xmlString.append("<?xml version='1.0' encoding='UTF-8'?>").append(RT);         xmlString.append("<xml>").append(RT);         for (Map.Entry<String, Object> entry : map.entrySet()){             String key = entry.getKey();             xmlString.append("<" + key + ">" + entry.getValue() + "</" + key + ">").append(RT);         }         xmlString.append("</xml>").append(RT);         return xmlString.toString();     }

  6.返回预支付结果,二次签名

  System.out.println("预支付返回结果:"+response);Map<String, String> resultParams = getWechatXmlToMap(response);         if (PaymentConst.WECHAT_STATUSCODE_FAIL.equals(resultParams.get("return_code"))){             throw new MessageException(resultParams.get("return_msg"));         }else{         if (PaymentConst.WECHAT_STATUSCODE_FAIL.equals(resultParams.get("result_code"))){         throw new MessageException(resultParams.get("return_msg"));             }else{                 String prepay_id = resultParams.get("prepay_id");                                  TreeMap paramMap1 = new TreeMap();         paramMap1.put("appId", paramMap.get("appid"));//公众账号ID         String s = String.valueOf(Util.getSecond());         paramMap1.put("timeStamp", s);         paramMap1.put("nonceStr", Util.getRandomString(30, null));         paramMap1.put("package", "prepay_id="+prepay_id);//签名类型         paramMap1.put("signType", paramMap.get("sign_type"));//签名类型         paramMap1.put("sign1",Signature.createSign("UTF-8", paramMap1));//签名         LOGGER.info("最终签名:"+paramMap1.get("sign1"));                                  //生成前台支付需要的数据                 Map<String, Object> map = new HashMap<String, Object>();                 map.put("appId", paramMap.get("appid"));                 String s1 = String.valueOf(Util.getSecond());                 map.put("timeStamp", s1);                 map.put("nonceStr", Util.getRandomString(30, null));                 map.put("package", "prepay_id="+prepay_id);                 map.put("signType", paramMap.get("sign_type"));                 map.put("paySign", paramMap1.get("sign1"));                 System.out.println("tttttttttttttttttttttttttttttt9999999999999tttttttttttttttttttttttttttttttttttttt");                 result.setT(map);             }         }

 7./**      * @Title:getWechatXmlToMap      * @Description:微信返回xml结果转为Map      * @param result      * @return      * @throws Exception Map<String,String> 返回类型      */     private Map<String, String> getWechatXmlToMap(String result) throws Exception{         SAXParserFactory factory = SAXParserFactory.newInstance();         SAXParser parser = factory.newSAXParser();         XMLHandler xmlHandler = new XMLHandler();         parser.parse(new ByteArrayInputStream(result.getBytes("UTF-8")), xmlHandler);         return xmlHandler.getParams();     }

   8.授权成功回调方法

/*** @Title:weixinPayBack* @Description:支付回调(微信支付)* @param request* @return String 返回类型*/@RequestMapping(value="/weiXinPayNotify")public String weixinPayBack(HttpServletRequest request){   try {       InputStream inStream = request.getInputStream();       ByteArrayOutputStream outSteam = new ByteArrayOutputStream();       byte[] buffer = new byte[1024];       int len = 0;       while ((len = inStream.read(buffer)) != -1) {           outSteam.write(buffer, 0, len);       }       outSteam.close();       inStream.close();       String resultStr  = new String(outSteam.toByteArray(),"utf-8");       System.out.println("微信支付的回调:"+resultStr);       Map<String, String> resultMap = getWechatXmlToMap(resultStr);       String return_code = resultMap.get("return_code");       if("SUCCESS".equals(return_code)){        //检验API返回的数据里面的签名是否合法,避免数据在传输的过程中被第三方篡改       if(!Signature.checkIsSignValidFromResponseString(resultStr)){        throw new MessageException("微信回调参数签名不合法");       }        String result_code = resultMap.get("result_code");        if("SUCCESS".equals(result_code)){        //支付成功的业务逻辑       //通知微信.异步确认成功.必写.不然微信会一直通知后台.八次之后就认为交易失败了.       return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";        }     }   } catch (Exception e) {    LOGGER.error(e.getMessage() ,e);   }   return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>";}

9.签名错误测试方法:

https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=20_1

填入如下参数

点击生成签名:出现如下xml

复制xml:

重新选择xml校验方式

生成签名出现下面的提示,校验通过,说明签名正确

其他签名错误情况检查参数是否正确

最新回复(0)