zoukankan      html  css  js  c++  java
  • 微信支付(统一下单)(自己备忘)

          思路:

          ①将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+"
    ");
    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
  • 相关阅读:
    正则表达式获取远程网页
    Devexpress 常见问题
    CSS 带显示隐藏左部页面按钮
    CSS 技巧积累
    SQL 常用操作
    重置 自增字段 起始值 和 步长
    Devexpress TreeList
    Devexpress GridControl
    JS常用
    ajax跨域请求
  • 原文地址:https://www.cnblogs.com/xyt-0412/p/4953748.html
Copyright © 2011-2022 走看看