JAVA微信扫码支付模式二功能实现以及回调

来源:互联网 发布:重庆市干部网络 编辑:程序博客网 时间:2024/05/22 15:15

一、准备工作

首先吐槽一下微信关于支付这块,本身支持的支付模式就好几种,但是官方文档特别零散,连像样的Java相关的demo也没几个。本人之前没有搞过微信支付,一开始真是被它搞晕,折腾两天终于调通了,特此写下来,以享后人吧!

关于准备工作,就“微信扫码支付模式二”官方文档地址在这 https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1 可以先看看,实际上需要准备的东西有以下几个:

其中APP_ID和APP_SECRET可以在公众平台找着,MCH_ID和API_KEY则在商户平台找到,特别是API_KEY要在商户平台设置好,对于“微信扫码支付模式二”(支付与回调)实际只会用到APP_ID、MCH_ID和API_KEY,其他的都不用。

关于开发环境,我就不罗嗦了,不管你是springMVC、struts2又或者直接serverlet,都差不多,只要你能保证对应的方法能调用起来就行。关于引用第三方的jar包,我这里只用到了一个xml操作的jdom,记住是1.*的版本,不是官网上最新的2.*,两者不兼容。具体是jdom-1.1.3.jar,依赖包jaxen-1.1.6.jar,就这两个包,我没用到有些例子中使用的httpclient,感觉没必要,而且依赖包特别繁杂,当然你是maven当我没说。

二、开发实战

1、首先是接入微信接口,获取微信支付二维码。

[java] view plain copy
print?
  1. public String weixin_pay() throws Exception {  
  2.         // 账号信息  
  3.         String appid = PayConfigUtil.APP_ID;  // appid  
  4.         //String appsecret = PayConfigUtil.APP_SECRET; // appsecret  
  5.         String mch_id = PayConfigUtil.MCH_ID; // 商业号  
  6.         String key = PayConfigUtil.API_KEY; // key  
  7.   
  8.         String currTime = PayCommonUtil.getCurrTime();  
  9.         String strTime = currTime.substring(8, currTime.length());  
  10.         String strRandom = PayCommonUtil.buildRandom(4) + "";  
  11.         String nonce_str = strTime + strRandom;  
  12.           
  13.         String order_price = 1// 价格   注意:价格的单位是分  
  14.         String body = "goodssssss";   // 商品名称  
  15.         String out_trade_no = "11338"// 订单号  
  16.           
  17.         // 获取发起电脑 ip  
  18.         String spbill_create_ip = PayConfigUtil.CREATE_IP;  
  19.         // 回调接口   
  20.         String notify_url = PayConfigUtil.NOTIFY_URL;  
  21.         String trade_type = "NATIVE";  
  22.           
  23.         SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();  
  24.         packageParams.put("appid", appid);  
  25.         packageParams.put("mch_id", mch_id);  
  26.         packageParams.put("nonce_str", nonce_str);  
  27.         packageParams.put("body", body);  
  28.         packageParams.put("out_trade_no", out_trade_no);  
  29.         packageParams.put("total_fee", order_price);  
  30.         packageParams.put("spbill_create_ip", spbill_create_ip);  
  31.         packageParams.put("notify_url", notify_url);  
  32.         packageParams.put("trade_type", trade_type);  
  33.   
  34.         String sign = PayCommonUtil.createSign("UTF-8", packageParams,key);  
  35.         packageParams.put("sign", sign);  
  36.           
  37.         String requestXML = PayCommonUtil.getRequestXml(packageParams);  
  38.         System.out.println(requestXML);  
  39.    
  40.         String resXml = HttpUtil.postData(PayConfigUtil.UFDODER_URL, requestXML);  
  41.   
  42.           
  43.         Map map = XMLUtil.doXMLParse(resXml);  
  44.         //String return_code = (String) map.get("return_code");  
  45.         //String prepay_id = (String) map.get("prepay_id");  
  46.         String urlCode = (String) map.get("code_url");  
  47.           
  48.         return urlCode;  
  49. }  

如果不出意外的话,这里就从微信服务器获取了一个支付url,形如weixin://wxpay/bizpayurl?pr=pIxXXXX,之后我们就需要把这个url生成一个二维码,然后就可以使用自己手机微信端扫码支付了。关于二维码生成有很多种方法,各位各取所需吧,我这里提供一个google的二维码生成接口:

[java] view plain copy
print?
  1. public static String QRfromGoogle(String chl) throws Exception {  
  2.     int widhtHeight = 300;  
  3.     String EC_level = "L";  
  4.     int margin = 0;  
  5.     chl = UrlEncode(chl);  
  6.     String QRfromGoogle = "http://chart.apis.google.com/chart?chs=" + widhtHeight + "x" + widhtHeight  
  7.             + "&cht=qr&chld=" + EC_level + "|" + margin + "&chl=" + chl;  
  8.   
  9.     return QRfromGoogle;  
  10. }  

[java] view plain copy
print?
  1. // 特殊字符处理  
  2. public static String UrlEncode(String src)  throws UnsupportedEncodingException {  
  3.     return URLEncoder.encode(src, "UTF-8").replace("+""%20");  
  4. }  

上面代码中涉及到几个工具类:PayConfigUtil、PayCommonUtil、HttpUtil和XMLUtil,其中PayConfigUtil放的就是上面提到一些配置及路径,PayCommonUtil涉及到了获取当前事件、产生随机字符串、获取参数签名和拼接xml几个方法,代码如下:

[java] view plain copy
print?
  1. public class PayCommonUtil {  
  2.       
  3.     /** 
  4.      * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 
  5.      * @return boolean 
  6.      */  
  7.     public static boolean isTenpaySign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {  
  8.         StringBuffer sb = new StringBuffer();  
  9.         Set es = packageParams.entrySet();  
  10.         Iterator it = es.iterator();  
  11.         while(it.hasNext()) {  
  12.             Map.Entry entry = (Map.Entry)it.next();  
  13.             String k = (String)entry.getKey();  
  14.             String v = (String)entry.getValue();  
  15.             if(!"sign".equals(k) && null != v && !"".equals(v)) {  
  16.                 sb.append(k + "=" + v + "&");  
  17.             }  
  18.         }  
  19.           
  20.         sb.append("key=" + API_KEY);  
  21.           
  22.         //算出摘要  
  23.         String mysign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toLowerCase();  
  24.         String tenpaySign = ((String)packageParams.get("sign")).toLowerCase();  
  25.           
  26.         //System.out.println(tenpaySign + "    " + mysign);  
  27.         return tenpaySign.equals(mysign);  
  28.     }  
  29.   
  30.     /** 
  31.      * @author 
  32.      * @date 2016-4-22 
  33.      * @Description:sign签名 
  34.      * @param characterEncoding 
  35.      *            编码格式 
  36.      * @param parameters 
  37.      *            请求参数 
  38.      * @return 
  39.      */  
  40.     public static String createSign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) {  
  41.         StringBuffer sb = new StringBuffer();  
  42.         Set es = packageParams.entrySet();  
  43.         Iterator it = es.iterator();  
  44.         while (it.hasNext()) {  
  45.             Map.Entry entry = (Map.Entry) it.next();  
  46.             String k = (String) entry.getKey();  
  47.             String v = (String) entry.getValue();  
  48.             if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {  
  49.                 sb.append(k + "=" + v + "&");  
  50.             }  
  51.         }  
  52.         sb.append("key=" + API_KEY);  
  53.         String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();  
  54.         return sign;  
  55.     }  
  56.   
  57.     /** 
  58.      * @author 
  59.      * @date 2016-4-22 
  60.      * @Description:将请求参数转换为xml格式的string 
  61.      * @param parameters 
  62.      *            请求参数 
  63.      * @return 
  64.      */  
  65.     public static String getRequestXml(SortedMap<Object, Object> parameters) {  
  66.         StringBuffer sb = new StringBuffer();  
  67.         sb.append("<xml>");  
  68.         Set es = parameters.entrySet();  
  69.         Iterator it = es.iterator();  
  70.         while (it.hasNext()) {  
  71.             Map.Entry entry = (Map.Entry) it.next();  
  72.             String k = (String) entry.getKey();  
  73.             String v = (String) entry.getValue();  
  74.             if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {  
  75.                 sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");  
  76.             } else {  
  77.                 sb.append("<" + k + ">" + v + "</" + k + ">");  
  78.             }  
  79.         }  
  80.         sb.append("</xml>");  
  81.         return sb.toString();  
  82.     }  
  83.   
  84.     /** 
  85.      * 取出一个指定长度大小的随机正整数. 
  86.      *  
  87.      * @param length 
  88.      *            int 设定所取出随机数的长度。length小于11 
  89.      * @return int 返回生成的随机数。 
  90.      */  
  91.     public static int buildRandom(int length) {  
  92.         int num = 1;  
  93.         double random = Math.random();  
  94.         if (random < 0.1) {  
  95.             random = random + 0.1;  
  96.         }  
  97.         for (int i = 0; i < length; i++) {  
  98.             num = num * 10;  
  99.         }  
  100.         return (int) ((random * num));  
  101.     }  
  102.   
  103.     /** 
  104.      * 获取当前时间 yyyyMMddHHmmss 
  105.      *  
  106.      * @return String 
  107.      */  
  108.     public static String getCurrTime() {  
  109.         Date now = new Date();  
  110.         SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss");  
  111.         String s = outFormat.format(now);  
  112.         return s;  
  113.     }  
  114.   
  115. }  

HttpUtil和XMLUtil如下:

[java] view plain copy
print?
  1. public class HttpUtil {  
  2.   
  3.     private static final Log logger = Logs.get();  
  4.     private final static int CONNECT_TIMEOUT = 5000// in milliseconds  
  5.     private final static String DEFAULT_ENCODING = "UTF-8";  
  6.       
  7.     public static String postData(String urlStr, String data){  
  8.         return postData(urlStr, data, null);  
  9.     }  
  10.       
  11.     public static String postData(String urlStr, String data, String contentType){  
  12.         BufferedReader reader = null;  
  13.         try {  
  14.             URL url = new URL(urlStr);  
  15.             URLConnection conn = url.openConnection();  
  16.             conn.setDoOutput(true);  
  17.             conn.setConnectTimeout(CONNECT_TIMEOUT);  
  18.             conn.setReadTimeout(CONNECT_TIMEOUT);  
  19.             if(contentType != null)  
  20.                 conn.setRequestProperty("content-type", contentType);  
  21.             OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING);  
  22.             if(data == null)  
  23.                 data = "";  
  24.             writer.write(data);   
  25.             writer.flush();  
  26.             writer.close();    
  27.   
  28.             reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING));  
  29.             StringBuilder sb = new StringBuilder();  
  30.             String line = null;  
  31.             while ((line = reader.readLine()) != null) {  
  32.                 sb.append(line);  
  33.                 sb.append("\r\n");  
  34.             }  
  35.             return sb.toString();  
  36.         } catch (IOException e) {  
  37.             logger.error("Error connecting to " + urlStr + ": " + e.getMessage());  
  38.         } finally {  
  39.             try {  
  40.                 if (reader != null)  
  41.                     reader.close();  
  42.             } catch (IOException e) {  
  43.             }  
  44.         }  
  45.         return null;  
  46.     }  
  47. }  

[java] view plain copy
print?
  1. public class XMLUtil {  
  2.     /** 
  3.      * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。 
  4.      * @param strxml 
  5.      * @return 
  6.      * @throws JDOMException 
  7.      * @throws IOException 
  8.      */  
  9.     public static Map doXMLParse(String strxml) throws JDOMException, IOException {  
  10.         strxml = strxml.replaceFirst("encoding=\".*\"""encoding=\"UTF-8\"");  
  11.   
  12.         if(null == strxml || "".equals(strxml)) {  
  13.             return null;  
  14.         }  
  15.           
  16.         Map m = new HashMap();  
  17.           
  18.         InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));  
  19.         SAXBuilder builder = new SAXBuilder();  
  20.         Document doc = builder.build(in);  
  21.         Element root = doc.getRootElement();  
  22.         List list = root.getChildren();  
  23.         Iterator it = list.iterator();  
  24.         while(it.hasNext()) {  
  25.             Element e = (Element) it.next();  
  26.             String k = e.getName();  
  27.             String v = "";  
  28.             List children = e.getChildren();  
  29.             if(children.isEmpty()) {  
  30.                 v = e.getTextNormalize();  
  31.             } else {  
  32.                 v = XMLUtil.getChildrenText(children);  
  33.             }  
  34.               
  35.             m.put(k, v);  
  36.         }  
  37.           
  38.         //关闭流  
  39.         in.close();  
  40.           
  41.         return m;  
  42.     }  
  43.       
  44.     /** 
  45.      * 获取子结点的xml 
  46.      * @param children 
  47.      * @return String 
  48.      */  
  49.     public static String getChildrenText(List children) {  
  50.         StringBuffer sb = new StringBuffer();  
  51.         if(!children.isEmpty()) {  
  52.             Iterator it = children.iterator();  
  53.             while(it.hasNext()) {  
  54.                 Element e = (Element) it.next();  
  55.                 String name = e.getName();  
  56.                 String value = e.getTextNormalize();  
  57.                 List list = e.getChildren();  
  58.                 sb.append("<" + name + ">");  
  59.                 if(!list.isEmpty()) {  
  60.                     sb.append(XMLUtil.getChildrenText(list));  
  61.                 }  
  62.                 sb.append(value);  
  63.                 sb.append("</" + name + ">");  
  64.             }  
  65.         }  
  66.           
  67.         return sb.toString();  
  68.     }  
  69.       
  70. }  

当然还有一个MD5计算工具类

[java] view plain copy
print?
  1. public class MD5Util {  
  2.   
  3.     private static String byteArrayToHexString(byte b[]) {  
  4.         StringBuffer resultSb = new StringBuffer();  
  5.         for (int i = 0; i < b.length; i++)  
  6.             resultSb.append(byteToHexString(b[i]));  
  7.   
  8.         return resultSb.toString();  
  9.     }  
  10.   
  11.     private static String byteToHexString(byte b) {  
  12.         int n = b;  
  13.         if (n < 0)  
  14.             n += 256;  
  15.         int d1 = n / 16;  
  16.         int d2 = n % 16;  
  17.         return hexDigits[d1] + hexDigits[d2];  
  18.     }  
  19.   
  20.     public static String MD5Encode(String origin, String charsetname) {  
  21.         String resultString = null;  
  22.         try {  
  23.             resultString = new String(origin);  
  24.             MessageDigest md = MessageDigest.getInstance("MD5");  
  25.             if (charsetname == null || "".equals(charsetname))  
  26.                 resultString = byteArrayToHexString(md.digest(resultString  
  27.                         .getBytes()));  
  28.             else  
  29.                 resultString = byteArrayToHexString(md.digest(resultString  
  30.                         .getBytes(charsetname)));  
  31.         } catch (Exception exception) {  
  32.         }  
  33.         return resultString;  
  34.     }  
  35.   
  36.     private static final String hexDigits[] = { "0""1""2""3""4""5",  
  37.             "6""7""8""9""a""b""c""d""e""f" };  
  38.   
  39. }  

2、支付回调

支付完成后,微信会把相关支付结果和用户信息发送到我们上面指定的那个回调地址,我们需要接收处理,并返回应答。对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。 (通知频率为15/15/30/180/1800/1800/1800/1800/3600,单位:秒)

关于支付回调接口,我们首先要对于支付结果通知的内容进行签名验证,然后根据支付结果进行相应的处理流程即可。

[java] view plain copy
print?
  1. public void weixin_notify(HttpServletRequest request,HttpServletResponse response) throws Exception{  
  2.           
  3.         //读取参数  
  4.         InputStream inputStream ;  
  5.         StringBuffer sb = new StringBuffer();  
  6.         inputStream = request.getInputStream();  
  7.         String s ;  
  8.         BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));  
  9.         while ((s = in.readLine()) != null){  
  10.             sb.append(s);  
  11.         }  
  12.         in.close();  
  13.         inputStream.close();  
  14.   
  15.         //解析xml成map  
  16.         Map<String, String> m = new HashMap<String, String>();  
  17.         m = XMLUtil.doXMLParse(sb.toString());  
  18.           
  19.         //过滤空 设置 TreeMap  
  20.         SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();        
  21.         Iterator it = m.keySet().iterator();  
  22.         while (it.hasNext()) {  
  23.             String parameter = (String) it.next();  
  24.             String parameterValue = m.get(parameter);  
  25.               
  26.             String v = "";  
  27.             if(null != parameterValue) {  
  28.                 v = parameterValue.trim();  
  29.             }  
  30.             packageParams.put(parameter, v);  
  31.         }  
  32.           
  33.         // 账号信息  
  34.         String key = PayConfigUtil.API_KEY; // key  
  35.   
  36.         logger.info(packageParams);  
  37.         //判断签名是否正确  
  38.         if(PayCommonUtil.isTenpaySign("UTF-8", packageParams,key)) {  
  39.             //------------------------------  
  40.             //处理业务开始  
  41.             //------------------------------  
  42.             String resXml = "";  
  43.             if("SUCCESS".equals((String)packageParams.get("result_code"))){  
  44.                 // 这里是支付成功  
  45.                 //////////执行自己的业务逻辑////////////////  
  46.                 String mch_id = (String)packageParams.get("mch_id");  
  47.                 String openid = (String)packageParams.get("openid");  
  48.                 String is_subscribe = (String)packageParams.get("is_subscribe");  
  49.                 String out_trade_no = (String)packageParams.get("out_trade_no");  
  50.                   
  51.                 String total_fee = (String)packageParams.get("total_fee");  
  52.                   
  53.                 logger.info("mch_id:"+mch_id);  
  54.                 logger.info("openid:"+openid);  
  55.                 logger.info("is_subscribe:"+is_subscribe);  
  56.                 logger.info("out_trade_no:"+out_trade_no);  
  57.                 logger.info("total_fee:"+total_fee);  
  58.                   
  59.                 //////////执行自己的业务逻辑////////////////  
  60.                   
  61.                 logger.info("支付成功");  
  62.                 //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.  
  63.                 resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"  
  64.                         + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";  
  65.                   
  66.             } else {  
  67.                 logger.info("支付失败,错误信息:" + packageParams.get("err_code"));  
  68.                 resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"  
  69.                         + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";  
  70.             }  
  71.             //------------------------------  
  72.             //处理业务完毕  
  73.             //------------------------------  
  74.             BufferedOutputStream out = new BufferedOutputStream(  
  75.                     response.getOutputStream());  
  76.             out.write(resXml.getBytes());  
  77.             out.flush();  
  78.             out.close();  
  79.         } else{  
  80.             logger.info("通知签名验证失败");  
  81.         }  
  82.           
  83.     }  

签名验证算法和签名生成的算法类似,在上面PayCommonUtil工具类中提供。

三、后话

感觉微信扫描支付体验效果还是挺好的,唯一缺点就是相关文档零散,官方的demo居然没有java编写的,希望之后微信官方能够逐步完善吧!


最后当然是转载声明了,转载请注明:http://blog.csdn.NET/wangqiuyun/article/details/51241064


48楼 qq_384945202017-05-09 10:06发表 [回复] [引用][举报]
楼主求 dome源码 超级急 我Q邮箱 329434396@qq.com 谢谢了
47楼 布鲁斯-斌2017-04-26 09:37发表 [回复] [引用][举报]
楼主能发分源码吗?921352158@qq.com 感谢
46楼 qq_376292262017-04-01 11:12发表 [回复] [引用][举报]
第一次测试支付成功了,但是我第二次测试的时候,urlCode为null,为什么会这样?求大神指点一下
Re: caizhenying2017-04-20 16:27发表 [回复] [引用][举报]
回复qq_37629226:请问你们是如何将urlCode转为二维码的?
45楼 qq_335286732017-03-13 13:57发表 [回复] [引用][举报]
博主 回调成功后 怎么将成功或者失败的信息传给微信后台
44楼 qq199572017-03-08 16:51发表 [回复] [引用][举报]
我现在在弄这个,有些业务逻辑没清,方便发一份源码吗?大神,谢谢了
43楼 BojonWong2017-02-24 00:21发表 [回复] [引用][举报]
您好 我想问一下 签名错误可能是什么原因
Re: 多福朗静哥2017-02-25 10:10发表 [回复] [引用][举报]
回复BojonWong:我也遇到过签名错误,现在调通了,是你微信公众号的配置信息有问题
42楼 lqqppl2017-01-11 13:29发表 [回复] [引用][举报]
多谢 !!!!菜鸟一个 , 弄了两天终于 弄成功了 模式一和 二都ok ,很激动呀 多谢多谢 赞博主的分享精神
Re: qq_335286732017-03-13 14:13发表 [回复] [引用][举报]
回复lqqppl:你好 我有个问题请教一下
41楼 yuruixin_china2017-01-10 16:50发表 [回复] [引用][举报]
先感谢!!!!!
40楼 简单_爱2017-01-06 17:31发表 [回复] [引用][举报]
很好很好很好
39楼 zhaojiawei_ok2016-12-16 13:23发表 [回复] [引用][举报]
楼主,这样定义 String order_price = 1; // 价格 注意:价格的单位是分,1不加双引号不会报错吗,我访问下单接口时,提示<return_msg><![CDATA[签名错误]]></return_msg>,,求楼主棒棒我。
38楼 zhaojiawei_ok2016-12-16 13:22发表 [回复] [引用][举报]
楼主,这样定义 String order_price = 1; // 价格 注意:价格的单位是分,1不加双引号不会报错吗,我访问下单接口时,提示<return_msg><![CDATA[签名错误]]></return_msg>,,求楼主棒棒我。
37楼 zhfonline2016-12-15 18:28发表 [回复] [引用][举报]
楼主弄得不错,值得膜拜。。。
36楼 qq_359115892016-12-08 19:34发表 [回复] [引用][举报]
第一步就返回null了。。是不是还要搞授权目录什么的
Re: qwertlkj2016-12-30 07:02发表 [回复] [引用][举报]
回复qq_35911589:我也是你解决了吗?
35楼 qq_359115892016-12-08 17:16发表 [回复] [引用][举报]
这才是好样的.
34楼 wangqiuyun2016-11-28 14:21发表 [回复] [引用][举报]
稍不留神,一堆人问这个不进回调的问题,我这再统一说一下,你要保证你在统一下单接口提交的那个nofity_url必须是公网可访问的,什么意思呢?就是微信服务器能直接访问到的,例如http://www.xxx.cn/xxx/nofity_url,我不管你后面是servlet还是struts或者springmvc,总之这url必须是外网活的,最简单的测试办法就是你用把这个地址随便发给外网的一个人,看他用浏览器能不能访问到,无数人死在用了框架例如struts却把这个地址拦截了,难道你还要求微信服务器登录再访问不成?这是最坑爹的做法,注意了!另外一点就是上面有人说道的异步,其实就是有延时的意思,注意去看一下文档,不过我测试时都还是比较及时的!我博客左侧有QQ号,还搞不懂的可以加我QQ,我在线方便时会回复!
33楼 qq_334283802016-11-28 13:38发表 [回复] [引用][举报]
你的二维码如何弄出来的
32楼 liyebing2016-11-27 11:02发表 [回复] [引用][举报]
请问楼主,生成二维码之前如果不做这个 URLEncoder.encode(src, "UTF-8").replace("+", "%20")

处理,会有什么后果吗?为什么要这么处理?
31楼 qq_348193032016-11-26 15:51发表 [回复] [引用][举报]
我来回答一下很多人遇到支付成功后进不了回调的servlet的原因吧!;看官方方案二:业务流程第10条:微信支付系统通过发送异步消息通知商户后台系统支付结果。。什么叫异步?就是不是同步,什么叫不是同步?就是用户支付完后不会立刻发送消息到回调的servlet,可以要等几分钟,几个小时都有可能,像比如说话费充值,银行转账怎么可能让客户去等!!所以告诉大家还是自己老老实实去自己想办法获取回调数据!为什么会出现这个问题?就是因为是异步,微信为什么要异步,并发量太大了。怎么解决?看官方文档,查资料。。
30楼 qq_348193032016-11-26 15:50发表 [回复] [引用][举报]
我来回答一下很多人遇到支付成功后进不了回调的servlet的原因吧!;看官方方案二:业务流程第10条:微信支付系统通过发送异步消息通知商户后台系统支付结果。。什么叫异步?就是不是同步,什么叫不是同步?就是用户支付完后不会立刻发送消息到回调的servlet,可以要等几分钟,几个小时都有可能,像比如说话费充值,银行转账怎么可能让客户去等!!所以告诉大家还是自己老老实实去自己想办法获取回调数据!为什么会出现这个问题?就是因为是异步,微信为什么要异步,并发量太大了。怎么解决?看官方文档,查资料。。
29楼 qq_348193032016-11-26 15:48发表 [回复] [引用][举报]
我来回答一下很多人遇到支付成功后进不了回调的servlet的原因吧!;看官方方案二:业务流程第10条:微信支付系统通过发送异步消息通知商户后台系统支付结果。。什么叫异步?就是不是同步,什么叫不是同步?就是用户支付完后不会立刻发送消息到回调的servlet,可以要等几分钟,几个小时都有可能,像比如说话费充值,银行转账怎么可能让客户去等!!所以告诉大家还是自己老老实实去自己想办法获取回调数据!为什么会出现这个问题?就是因为是异步,微信为什么要异步,并发量太大了。怎么解决?看官方文档,查资料。。
28楼 cczhou232016-11-23 11:33发表 [回复] [引用][举报]
大神能否加下qq,413409007,正在做微信扫码支付,也是用的模式二,但是遇到些问题
27楼 lny1292016-11-15 14:03发表 [回复] [引用][举报]
为什么我支付后没有调用回调地址呢
public static String NOTIFY_URL = "http://121.43.168.53:8080/pay/wxpay/wxpayAction!weixinNotify.action";
26楼 mengchen8882016-10-27 16:32发表 [回复] [引用][举报]
谢谢博主 这文章对我帮助很大
25楼 mengchen8882016-10-27 16:30发表 [回复] [引用][举报]
这文章写的太牛了 对我帮助很大 谢谢博主
24楼 shixiezhilong2016-10-26 11:01发表 [回复] [引用][举报]
楼主,为什么我总是回调不了..我的域名也是http://www.1001000.com/WeChatNotify/。外网可以访问的,但是微信那边都不访问.. 用的是Struts,WeChatNotify是一个action类,进去后会返回微信成功的XML信息后和修改我数据库的资料。。但是支付成功以后,数据库一直没插入数据。一直找不到原因,快愁死了。
23楼 shixiezhilong2016-10-18 16:58发表 [回复] [引用][举报]
楼主你好,就前面申请支付,返回生成二维码这一部分,可以直接在本地tomcat上调试吗? 还是说一定要在外网?
22楼 小南瓜酥2016-10-14 14:14发表 [回复] [引用][举报]
是怎么回事?谢谢大哥,能说一下吗?QQ:554564951
21楼 小南瓜酥2016-10-14 14:13发表 [回复] [引用][举报]
你好,我的回调地址是:http://117.158.178.196:9090/wenxin/notify/pay.action,能接受到服务器返回的报文,但是页面不会跳转!
20楼 JavaThinkE2016-09-01 17:44发表 [回复] [引用][举报]
问楼主一个问题 就是微信支付回调签名校验问题 在扫码完支付结束后 微信回调返回的那个签名 为什么和我支付用的那个签名不是同一个?
19楼 wangqiuyun2016-08-19 11:20发表 [回复] [引用][举报]
平时比较忙,有必要请加我QQ,在这里统一回复一下!
首先是没有回调的问题,请确保你的是公网地址,不要求https,确认你提交回调地址和你实际部署的回调地址一致(不要再坑我了),另外有可能的话请尽量用Servlet来搞,成功之后再移植到别的框架上。
然后是验签不过的问题,必须确保你接收的参数完整正确,还有编码的问题,建议尽可能用原生的api来请求网络,如URLConnection,因为我也没办法确认第三方的包会不会对数据包做别的处理。
最后我只对我上面提供的代码负责,如果你不是按我上面的来搞,我没有太多时间帮你排除问题。
Re: shixiezhilong2016-10-26 11:08发表 [回复] [引用][举报]
回复wangqiuyun:实际部署地址是我们外网的回调地址吗? 比如我外网是回调访问地址是http://www.1001000.com/WeChatNotify/,提交参数的时候写的notifyurl也是http://www.1001000.com/WeChatNotify/。。这样就可以了吗?我是这样做的,都是还是没访问,我数据库一直没插入数据啊。楼主大大请救我于水火吧。快烦死了
18楼 qq_254398612016-08-15 18:48发表 [回复] [引用][举报]
您好, 我的回调地址是公网,但是支付成功后没有回调到方法。这是怎么回事啊。
17楼 qq_254398612016-08-12 16:44发表 [回复] [引用][举报]
你好,XMLUtil 这个需要引用什么jar嘛?
16楼 qq_154332552016-07-19 10:13发表 [回复] [引用][举报]
HttpUtil中Log logger = Logs.get();引用的是哪个包
Re: qq_371450812016-12-23 11:54发表 [回复] [引用][举报]
回复qq_15433255:private static final Log logger = Logs.get(); 这个logs是哪来的
Re: qq_359115892016-12-08 18:41发表 [回复] [引用][举报]
回复qq_15433255:我也想问...Logs哪里来的,导半天都是错
15楼 wangyahuizc2016-07-16 15:33发表 [回复] [引用][举报]
请问楼主,回调地址需要启用https吗?
14楼 Simple-5202016-07-13 11:29发表 [回复] [引用][举报]
楼主,请你一个问题呀,我是自己弄的,调用统一下单接口成功,签名正常,但是回调时,验签不通过,我
dubug过,待签名字符串和之前一模一样
困扰了我快2天了,请指教
Re: JavaThinkE2016-09-01 17:46发表 [回复] [引用][举报]
回复Simple-520:我现在也遇到这个问题了 请问你解决了吗?
13楼 oyezitan2016-07-05 18:02发表 [回复] [引用][举报]
楼主,请问一下,用户支付完成后,返回商城,点击悬浮框的”已经完成支付”,网站会做什么操作?是去商城后台查询支付状态吗?
12楼 丿碎叶城丶夏天2016-06-30 16:19发表 [回复] [引用][举报]
我的问题好奇怪,刚开始可以正确返回到 回调地址,但是当时我不知道怎么 告诉微信 成功接收到了,微信回调了8次之后就不会再回调了,就算我另外再 交易一次,也不会再回调。。

感谢博主啊,找了半天的代码,终于找到 通知微信的代码了
11楼 巴达兽2016-06-22 14:11发表 [回复] [引用][举报]
终于看到二维码了,感激之情无以言表!对了,你头像真帅
10楼 oYangZhi2016-06-20 11:28发表 [回复] [引用][举报]
你好 用你的例子 提示 您没有原生支付 这个是什么解决
9楼 object-xie2016-06-18 12:01发表 [回复] [引用][举报]
同问我也遇到没有走回调的方法,各位是怎么解决的。
8楼 web神2016-06-06 13:56发表 [回复] [引用][举报]
有您的联系方式吗?我回调以后不知道做什么操作了,也就是我该怎么判断支付状态
7楼 w_xj2016-06-01 16:00发表 [回复] [引用][举报]
你好 我这个返回的post数据为空 是什么问题 ,新手求助
6楼 qq_251638892016-05-30 14:38发表 [回复] [引用][举报]
你好,我最近也在做微信支付,现在支付成功了,但是却没有调用回调地址,我设置的回调地址没有参数且在公网上,您知道什么原因可能导致这个结果吗。感谢了
5楼 wyang君2016-05-16 17:06发表 [回复] [引用][举报]
您好,请问weixin_pay方法中第40行的PayConfigUtil.UFDODER_URL中的 UFDODER_URL具体指什么?怎么配置
Re: wangqiuyun2016-05-19 08:52发表 [回复] [引用][举报]
回复wyang君:看第一张图,UFDODER_URL是微信的统一下单接口,固定的
4楼 kaka_2282016-05-12 12:09发表 [回复] [引用][举报]
您好 请问支付成功之后怎么跳转页面
Re: wangqiuyun2016-05-19 08:54发表 [回复] [引用][举报]
回复kaka_228:支付成功后转跳页面,我也没看到相关接口,估计目前没有这个功能,目前微信客户端支付成功就显示支付成功信息,你可以再找找官方文档看有没有相关功能
3楼 Zidane_20142016-05-04 14:46发表 [回复] [引用][举报]
你好,最近在弄微信扫码开发,希望能够得到一个你的联系方式,谢谢!
2楼 qq_328405572016-05-03 16:56发表 [回复] [引用][举报]
你好! 请问一下根据你的方法,二维码为什么生成不了;
Re: wangqiuyun2016-05-04 09:33发表 [回复] [引用][举报]
回复qq_32840557:我这没有搞具体的二维码生成,你只要获取到形如weixin://wxpay/bizpayurl?pr=pIxXXXX这个的code_url,就可以拿去随便用个啥二维码生成器生成就ok
Re: qq_328405572016-05-09 10:22发表 [回复] [引用][举报]
感谢,二维码用js生成的,现在项目没有部署到服务器上,回调看不到,也无法验证,我想问一下,这个nofity_url回调,是直接访问这个方法就能得到返回结果,还是要第二次签名请求,还有这么请求(小白,问的多了点!),谢谢
Re: wangqiuyun2016-05-18 10:02发表 [回复] [引用][举报]
回复qq_32840557:nofity_url就是你自己的服务器接口地址,别人扫码支付完后,微信服务器会访问你这个接口,并提交支付结果
1楼 So__Love2016-04-27 17:22发表 [回复] [引用][举报]
我支付成功后为什么回调不了那个nofity_url?
Re: wangqiuyun2016-04-28 16:07发表 [回复] [引用][举报]
回复So__Love:你回调地址设对了没?
Re: 焕听2016-05-18 11:23发表 [回复] [引用][举报]
回复wangqiuyun:我也是支付成功后不进回调url,单独执行回调url是可以进方法的,请问你们是怎么解决的呀~求博主联系方式~
Re: wangqiuyun2016-05-19 08:50发表 [回复] [引用][举报]
回复焕听:回调地址必须是公网地址哦,看你们自己搞好了没
Re: 夏漫2016-12-29 12:19发表 [回复] [引用][举报]
回复wangqiuyun:前辈:能发一份源码给我吗?麻烦您了
原创粉丝点击