微信支付(统一下单)(自己备忘)

      思路:

      ①将appid、mch_id、nonce_str、body、attach、out_trade_no、total_fee、spbill_create_ip、notify_url、trade_type 这些参数以键值对的形式拼接起来用MD5进行第一次签名

     ②拼接xml:

      例如:

 <xml>
   <appid>wx2421b1c4370ec43b</appid>
   <attach>支付测试</attach>
   <body>JSAPI支付测试</body>
   <mch_id>10000100</mch_id>
   <nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str>
   <notify_url>http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php</notify_url>
   <openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid>
   <out_trade_no>1415659990</out_trade_no>
   <spbill_create_ip>14.23.150.211</spbill_create_ip>
   <total_fee>1</total_fee>
   <trade_type>JSAPI</trade_type>
   <sign>0CB01533B8C1EF103065174F50BCA001</sign>
</xml>

,把这个xml 交个  "https://api.mch.weixin.qq.com/pay/unifiedorder"  在微信 生成一个预支付订单号prepay_id

   ③将 appid、partner、prepay_id、nonce_str、timestamp、partnerkey、key、package  通过键值对的形式拼接,然后MD5加密处理,和第一步加密方式一样进行第二次签名

    ④将appid、partnerid、prepayid、package、noncestr、timestamp、sign  传给 调起微信支付功能

 

 

注:一些用到的方法

1、MD5  将map 拼接成键值对的串,然后进行加密

 1 /**
 2      * 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
 3      */
 4     public String createSign(SortedMap<String, String> packageParams) {
 5         StringBuffer sb = new StringBuffer();
 6         Set es = packageParams.entrySet();
 7         Iterator it = es.iterator();
 8         while (it.hasNext()) {
 9             Map.Entry entry = (Map.Entry) it.next();
10             String k = (String) entry.getKey();
11             String v = (String) entry.getValue();
12             if (null != v && !"".equals(v) && !"sign".equals(k)
13                     && !"key".equals(k)) {
14                 sb.append(k + "=" + v + "&");
15             }
16         }
17         sb.append("key=" + this.getKey());
18         String sign = MD5Util.MD5Encode(sb.toString(), this.charset)
19                 .toUpperCase();
20         return sign;
21 
22     }

 

2、将xml交给 "https://api.mch.weixin.qq.com/pay/unifiedorder"  解析生成 预支付订单

    如果参数提交失败,会在try里的 if 中 返回  开发的时候建议打断点,我是存session ,然后返回错误信息msg

 1 /**
 2    *description:获取预支付id
 3    *@param urls
 4    *@param xmlParam
 5    *@return
 6    * @author ex_yangxiaoyi
 7    * @see
 8    */
 9   public static String getPayNo(String url,String xmlParam){
10       Subject currentUser = SecurityUtils.getSubject();  
11       Session session = currentUser.getSession();
12       
13       DefaultHttpClient client = new DefaultHttpClient();
14       client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
15       HttpPost httpost= HttpClientConnectionManager.getPostMethod(url);
16       String prepay_id = "";
17      try {
18          httpost.setEntity(new StringEntity(xmlParam, "UTF-8"));
19          HttpResponse response = httpclient.execute(httpost);
20          String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
21         if(jsonStr.indexOf("FAIL")!=-1){
22             session.setAttribute("error_msg", jsonStr);
23             return prepay_id;
24         }
25         Map map = doXMLParse(jsonStr);
26         prepay_id  = (String) map.get("prepay_id");
27     } catch (Exception e) {
28         // TODO Auto-generated catch block
29         e.printStackTrace();
30     }
31     return prepay_id;
32   }
33   
1     public static InputStream String2Inputstream(String str) {
2         return new ByteArrayInputStream(str.getBytes());
3     }

 

3、xml解析

 1 /**
 2      * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
 3      * @param strxml
 4      * @return
 5      * @throws JDOMException
 6      * @throws IOException
 7      */
 8     public static Map doXMLParse(String strxml) throws Exception {
 9         if(null == strxml || "".equals(strxml)) {
10             return null;
11         }
12         
13         Map m = new HashMap();
14         InputStream in = String2Inputstream(strxml);
15         SAXBuilder builder = new SAXBuilder();
16         Document doc = builder.build(in);
17         Element root = doc.getRootElement();
18         List list = root.getChildren();
19         Iterator it = list.iterator();
20         while(it.hasNext()) {
21             Element e = (Element) it.next();
22             String k = e.getName();
23             String v = "";
24             List children = e.getChildren();
25             if(children.isEmpty()) {
26                 v = e.getTextNormalize();
27             } else {
28                 v = getChildrenText(children);
29             }
30             
31             m.put(k, v);
32         }
33         
34         //关闭流
35         in.close();
36         
37         return m;
38     }
 1 /**
 2      * 获取子结点的xml
 3      * @param children
 4      * @return String
 5      */
 6     public static String getChildrenText(List children) {
 7         StringBuffer sb = new StringBuffer();
 8         if(!children.isEmpty()) {
 9             Iterator it = children.iterator();
10             while(it.hasNext()) {
11                 Element e = (Element) it.next();
12                 String name = e.getName();
13                 String value = e.getTextNormalize();
14                 List list = e.getChildren();
15                 sb.append("<" + name + ">");
16                 if(!list.isEmpty()) {
17                     sb.append(getChildrenText(list));
18                 }
19                 sb.append(value);
20                 sb.append("</" + name + ">");
21             }
22         }
23         
24         return sb.toString();
25     }

 4、微信回调函数

 1 /**
 2      * 微信支付 回调函数
 3      */
 4     @RequestMapping("/notify")
 5     @ResponseBody
 6     protected void notify(HttpServletRequest request,
 7             HttpServletResponse response) throws Exception {
 8         
 9         PageData pd=new PageData();
10         logBefore(logger, "微信支付  回调函数");
11         //把如下代码贴到的你的处理回调的servlet 或者.do 中即可明白回调操作
12         logger.info("微信支付回调数据开始");
13         //示例报文
14         //String xml = "<xml><appid><![CDATA[wxb4dc385f953b356e]]></appid><bank_type><![CDATA[CCB_CREDIT]]></bank_type><cash_fee><![CDATA[1]]></cash_fee><fee_type><![CDATA[CNY]]></fee_type><is_subscribe><![CDATA[Y]]></is_subscribe><mch_id><![CDATA[1228442802]]></mch_id><nonce_str><![CDATA[1002477130]]></nonce_str><openid><![CDATA[o-HREuJzRr3moMvv990VdfnQ8x4k]]></openid><out_trade_no><![CDATA[1000000000051249]]></out_trade_no><result_code><![CDATA[SUCCESS]]></result_code><return_code><![CDATA[SUCCESS]]></return_code><sign><![CDATA[1269E03E43F2B8C388A414EDAE185CEE]]></sign><time_end><![CDATA[20150324100405]]></time_end><total_fee>1</total_fee><trade_type><![CDATA[JSAPI]]></trade_type><transaction_id><![CDATA[1009530574201503240036299496]]></transaction_id></xml>";
15         String inputLine;
16         String notityXml = "";
17         String resXml = "";
18 
19         try {
20             while ((inputLine = request.getReader().readLine()) != null) {
21                 notityXml += inputLine;
22             }
23             request.getReader().close();
24         } catch (Exception e) {
25             e.printStackTrace();
26         }
27 
28         System.out.println("接收到的报文:" + notityXml);
29         
30         BufferedWriter writer = new BufferedWriter(new FileWriter(new File("c:\\ResultXml.txt"),true));
31          //
32          writer.write(DateUtil.getTime()+notityXml+"\r\n");
33          writer.close();
34         
35         Map m = parseXmlToList2(notityXml);
36         WxPayResult wpr = new WxPayResult();
37         wpr.setAppid(m.get("appid").toString());
38         wpr.setBankType(m.get("bank_type").toString());
39         wpr.setCashFee(m.get("cash_fee").toString());
40         wpr.setFeeType(m.get("fee_type").toString());
41         wpr.setIsSubscribe(m.get("is_subscribe").toString());
42         wpr.setMchId(m.get("mch_id").toString());
43         wpr.setNonceStr(m.get("nonce_str").toString());
44         wpr.setOpenid(m.get("openid").toString());
45         wpr.setOutTradeNo(m.get("out_trade_no").toString());
46         wpr.setResultCode(m.get("result_code").toString());
47         wpr.setReturnCode(m.get("return_code").toString());
48         wpr.setSign(m.get("sign").toString());
49         wpr.setTimeEnd(m.get("time_end").toString());
50         wpr.setTotalFee(m.get("total_fee").toString());
51         wpr.setTradeType(m.get("trade_type").toString());
52         wpr.setTransactionId(m.get("transaction_id").toString());
53         
54         if("SUCCESS".equals(wpr.getResultCode())){
55             //支付成功
56             resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
57             + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
58             //修改订单状态
59             pd.put("WX_ORDER", wpr.getOutTradeNo());
60             wxPayService.editStatusByOutId(pd);
61             //保存订单信息
62             pd.put("WX_ORDER_ID", UuidUtil.get32UUID());//微信订单主键ID
63             pd.put("OPEN_ID", wpr.getOpenid());//用户的OPEN_ID
64             pd.put("MCH_ID", wpr.getMchId());//商户号
65             pd.put("NONCE_STR", wpr.getNonceStr());//随机字符串
66             pd.put("SIGN", wpr.getSign());//SIGN
67             pd.put("CASH_FEE", wpr.getCashFee());//现金支付金额
68             pd.put("TOTAL_FEE", wpr.getTotalFee());//总金额
69             pd.put("BANK_TYPE", wpr.getBankType());//付款银行
70             pd.put("TRADE_TYPE", wpr.getTradeType());//交易类型
71             pd.put("RESULT_CODE", wpr.getResultCode());//业务结果
72             pd.put("TRANSACTION_ID", wpr.getTotalFee());//微信支付订单号
73             pd.put("TIME_END", wpr.getTimeEnd());//微信支付完成时间
74             wxPayService.saveWxOrder(pd);
75         }else{
76             resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
77             + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
78         }
79 
80         System.out.println("微信支付回调数据结束");
81 
82         BufferedOutputStream out = new BufferedOutputStream(
83                 response.getOutputStream());
84         out.write(resXml.getBytes());
85         out.flush();
86         out.close();
87 
88     }
89     
View Code

解析微信通知xml

 1 /**
 2      * description: 解析微信通知xml
 3      * 
 4      * @param xml
 5      * @return
 6      * @author ex_yangxiaoyi
 7      * @see
 8      */
 9     @SuppressWarnings({ "unused", "rawtypes", "unchecked" })
10     private static Map parseXmlToList2(String xml) {
11         Map retMap = new HashMap();
12         try {
13             StringReader read = new StringReader(xml);
14             // 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
15             InputSource source = new InputSource(read);
16             // 创建一个新的SAXBuilder
17             SAXBuilder sb = new SAXBuilder();
18             // 通过输入源构造一个Document
19             Document doc = (Document) sb.build(source);
20             Element root = doc.getRootElement();// 指向根节点
21             List<Element> es = root.getChildren();
22             if (es != null && es.size() != 0) {
23                 for (Element element : es) {
24                     retMap.put(element.getName(), element.getValue());
25                 }
26             }
27         } catch (Exception e) {
28             e.printStackTrace();
29         }
30         return retMap;
31     }
View Code

 

posted @ 2015-11-10 17:31  灰灰小菜鸟  阅读(5268)  评论(1编辑  收藏  举报