微信支付JSAPI支付

记一次微信支付JSAPI支付功能集成。

JSAPI支付前提是必须在微信环境中(公众号、聊天界面打开链接),否则无法调起支付。小程序webview控件中也无法调起支付。

准备工作:
1.首先在微信商户号中开通JSAPI支付功能(ps:我的一打开就是开通的,可能之前的同事开通的,so开通流程无法复现)。开通方式如下图:

image.png

2.申请开通之后在开发配置中添加域名,按照提示添加即可。
3.然后登录微信公众号后台,左侧菜单栏最下方,点击接口权限,然后左侧找到网页授权,点击其右边修改,在到新页面网页授权域名栏点右边设置,添加自己的支付链接域名。步骤图示:
image.png

image.png

image.png

准备工作完成。
开发工作 使用vue写的页面

1.由于JSAPI支付时需要用户openid,所以先获取openid
1.1 在页面js中加入以下代码:

reload(){
      let redirect_uri = window.location.href;
      let state = window.location.href;
      window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+API.APPID+"&redirect_uri="+redirect_uri+"&response_type=code&scope=snsapi_base&state="+state+"#wechat_redirect"
    }

代码中的API.APPID要换成自己的公众号AppId,其他字段可继续使用。
scope参数的值有两个可选,一个是snsapi_base,另一个是snsapi_userinfo。
关于网页授权的两种scope的区别说明

1.1.1、以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)

1.1.2、以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。
这里我们只是获取用户openid,无需用户手动同意,所以用snsapi_base。

在页面打开时判断openid是否已获取,未获取时调用reload()方法。

initData(){
      let self = this
      if(self.getQueryParam("code")){
          let code = self.getQueryParam("code") //getQueryParam()方法在下方
        API.request({  //api.js 文件在下方。
            url:"自己的后台接口",
            type:'请求方式',  //get  post
            data:{
              code:code //页面通过reload()方法获取到的code 重定向后参数是拼接在页面链接上的 需要自己获取 。
            },
            success:res=>{
              if(res.errcode === 200 && res.data != undefined){
                self.$data.openID = res.data
              }else{
                self.reload();
              }
            }
        })
      }else{
        self.reload()
      }
 }
    getQueryParam(variable){
       var query = window.location.search.substring(1);
       var vars = query.split("&");
       for (var i=0;i<vars.length;i++) {
            var pair = vars[i].split("=");
            if(pair[0] == variable){
               return pair[1];
            }
       }
       return(false);
    }

后台通过前端传的code参数,获取到用户openid后返回给前端保存。
2.下单
用户点击页面支付功能后,前端调用后台接口生成预付单并返回数据,前端解析诗句获取各种参数然后入下:

pay(){
      let self = this
      API.request({
        url:"自己的下单接口",
        type:'POST',
        data:{
           //下单需要的参数
        },
        success:res=>{
          if(res.errcode === 200){
            let data = res.data
            //下面代码调起微信支付
            WeixinJSBridge.invoke(
              'getBrandWCPayRequest', {
                "appId":data .appid,     //公众号id     
                "timeStamp":data .timeStamp,         //时间戳,自1970年以来的秒数     
                "nonceStr":data .nonceStr, //随机串     
                "package":data .package,     
                "signType":"MD5",         //微信签名方式:通用参数 可不改 
                "paySign":data .paySign //微信签名 
              },
              function(res){
                  if(res.err_msg == "get_brand_wcpay_request:ok" ){
                  // 使用以上方式判断前端返回,微信团队郑重提示:
                    //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
                    //支付成功  请求接口确认 刷新页面
                  }
            }); 
          }else {
            //失败处理
          }
        }
      })
    }

前端代码完成。
后台代码:
1.获取openid

   /**
     * 网页支付 获取openid
     *
     * @param code
     * @return
     */
    @PostMapping("getOpenID")
    private String getOpenID(@RequestParam("code") String code) {
        JSONObject accessToken = getAccessToken(code);
        return accessToken.getString("openid");
    }
    public static JSONObject getAccessToken(String code){
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="公众号AppID"&secret="公众号秘钥"&code="+code+"&grant_type=authorization_code";
        String result = HttpUtils.httpGet(url);
        JSONObject data = com.alibaba.fastjson.JSON.parseObject(result);
        return data;
    }
/**
     * 发送get请求
     * @param url    路径
     * @return
     */
    public static String httpGet(String url){
        //get请求返回结果
        String strResult = null;
        try {
            DefaultHttpClient client = new DefaultHttpClient();
            //发送get请求
            HttpGet request = new HttpGet(url);
            HttpResponse response = client.execute(request);

            /**请求发送成功,并得到响应**/
            if (response.getStatusLine().getStatusCode() == org.apache.http.HttpStatus.SC_OK) {
                /**读取服务器返回过来的json字符串数据**/
                strResult = EntityUtils.toString(response.getEntity(),"UTF-8");
            } else {

            }
        } catch (IOException e) {

        }
        return strResult;
    }

获取openid完成。

  1. 调用微信支付统一下单接口
    2.1 payUtils工具类
import org.apache.commons.codec.digest.DigestUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.json.JSONObject;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

public class PayUtil {

    public static String APP_ID = "";
    
    public static JSONObject wxPay(String appID, String openid, String bodys, String orderNos, String price, String notify_url) {
        JSONObject json = new JSONObject();
        try {
            //生成的随机字符串
            String nonce_str = Utils.genNonceStr();
            //获取本机的ip地址
            String spbill_create_ip = "127.0.0.1";

            Map<String, String> packageParams = new HashMap<String, String>();
            packageParams.put("appid", appID);
            packageParams.put("mch_id", WXPayUtil.MCH_ID);
            packageParams.put("nonce_str", nonce_str);
            packageParams.put("body", bodys);//商品名称
            packageParams.put("out_trade_no", orderNos);//商户订单号
            packageParams.put("total_fee", price);
            packageParams.put("spbill_create_ip", spbill_create_ip);
            packageParams.put("notify_url", notify_url);
            packageParams.put("trade_type", "JSAPI");
            packageParams.put("openid", openid);

            // 除去数组中的空值和签名参数
            packageParams = paraFilter(packageParams);
            String prestr = createLinkString(packageParams); // 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串

            //MD5运算生成签名,这里是第一次签名,用于调用统一下单接口
            String mysign = sign(prestr, WXPayUtil.API_KEY, "utf-8").toUpperCase();
//            System.out.println("=======================第一次签名:" + mysign + "=====================");
            //拼接统一下单接口使用的xml数据,要将上一步生成的签名一起拼接进去
            String xml = "<xml version='1.0' encoding='gbk'>" + "<appid>" + appID + "</appid>"
                    + "<body><![CDATA[" + bodys + "]]></body>"
                    + "<mch_id>" + WXPayUtil.MCH_ID + "</mch_id>"
                    + "<nonce_str>" + nonce_str + "</nonce_str>"
                    + "<notify_url>" + notify_url + "</notify_url>"
                    + "<openid>" + openid + "</openid>"
                    + "<out_trade_no>" + orderNos + "</out_trade_no>"
                    + "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>"
                    + "<total_fee>" + price + "</total_fee>"
                    + "<trade_type>" + "JSAPI" + "</trade_type>"
                    + "<sign>" + mysign + "</sign>"
                    + "</xml>";


//            System.out.println("调试模式_统一下单接口 请求XML数据:" + xml);


            //调用统一下单接口,并接受返回的结果
            String result = httpRequest(pay_url, "POST", xml);

//            System.out.println("调试模式_统一下单接口 返回XML数据:" + result);


// 将解析结果存储在HashMap中
            Map map = doXMLParse(result);
//            System.out.println("map:"+map);

            String return_code = (String) map.get("return_code");//返回状态码


//返回给移动端需要的参数
            Map<String, Object> response = new HashMap<String, Object>();
            if (return_code == "SUCCESS" || return_code.equals(return_code)) {
// 业务结果
                String prepay_id = (String) map.get("prepay_id");//返回的预付单信息
//                System.out.println("prepay_id:"+prepay_id);
                response.put("nonceStr", nonce_str);
                response.put("package", "prepay_id=" + prepay_id);
                Long timeStamp = System.currentTimeMillis() / 1000;
                response.put("timeStamp", timeStamp + "");//这边要将返回的时间戳转化成字符串,不然小程序端调用wx.requestPayment方法会报签名错误

                String stringSignTemp = "appId=" + appID + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id + "&signType=" + "MD5" + "&timeStamp=" + timeStamp;
                //再次签名,这个签名用于小程序端调用wx.requesetPayment方法
                String paySign = sign(stringSignTemp, WXPayUtil.API_KEY, "utf-8").toUpperCase();
                System.out.print("=======================第二次签名:" + paySign + "=====================");
                response.put("paySign", paySign);
                //更新订单信息
                //业务逻辑代码
            }
            response.put("appid", appID);
            json.put("errMsg", "OK");
            json.put("data", response);
        } catch (Exception e) {
            e.printStackTrace();
            json.put("errMsg", "Failed");
        }
        return json;
    }


    /**
     * 签名字符串
     *
     * @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 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);
        }
    }

    /**
     * 生成6位或10位随机数 param codeLength(多少位)
     *
     * @return
     */

    public static String createCode(int codeLength) {
        String code = "";
        for (int i = 0; i < codeLength; i++) {
            code += (int) (Math.random() * 9);
        }
        return code;
    }

    @SuppressWarnings("unused")
    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 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());
    }


    public static 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 = doXMLParse(notityXml);


        String returnCode = (String) map.get("return_code");
        if ("SUCCESS".equals(returnCode)) {
//验证签名是否正确
            if (verify(createLinkString(map), (String) map.get("sign"), WXPayUtil.API_KEY, "utf-8")) {
/**此处添加自己的业务逻辑代码start**/


/**此处添加自己的业务逻辑代码end**/


//通知微信服务器已经支付成功
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
            }
        } 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();
    }
}

2.2 在接口中调用方式:

//微信支付  参数说明
//APP_ID 必须是公众号appid
//openid 下单用户的openid 前端传过来的
//str  商品简单描述
//out_trade_no  商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|* 且在同一个商户号下唯一
 //"1" 商品价格 这里的价格是*100后的价格 
//NOTIFY_URL 支付回调地址

            org.json.JSONObject objects = PayUtil .wxPay(APP_ID,openid, str, out_trade_no, "1", NOTIFY_URL);//
            System.out.println(objects);
            String errMsg = objects.getString("errMsg");
            if (errMsg.equals("OK")) {
                org.json.JSONObject data = objects.getJSONObject("data");
//                  System.out.println(data);
                Map<String, Object> map = new HashMap<>();
                map.put("timeStamp", data.getString("timeStamp"));
                map.put("package", data.getString("package"));
                map.put("paySign", data.getString("paySign"));
                map.put("appid", data.getString("appid"));
                map.put("nonceStr", data.getString("nonceStr"));
                return map;
             }

2.3 支付回调

/**
     * jsApi H5广告微信支付回调
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "自定义name")
    private String 自定义name(HttpServletRequest request, HttpServletResponse response) {
        Map<String, String> return_data = new HashMap<String, String>();
        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);
            }
            String resultxml = new String(outSteam.toByteArray(), "utf-8");
//        System.out.println("resultxml:-----------------");
//        System.out.println(resultxml);
//        System.out.println("---------------------------");
            Map<String, String> params = PayCommonUtil.doXMLParse(resultxml);
            outSteam.close();
            inStream.close();

            if (!PayCommonUtil.isTenpaySign(params)) {
                // 支付失败
                System.out.println("===============信支付回调验签失败==============");
                return_data.put("return_code", "FAIL");
                return_data.put("return_msg", "return_code不正确");
                return StringUtil.GetMapToXML(return_data);
            } else {
                // ------------------------------
                // 处理业务开始
                // ------------------------------
                String total_fee = params.get("total_fee");

                double v = Double.valueOf(total_fee) / 100;

                String tradeNo = params.get("transaction_id");
                String out_trade_no = String.valueOf(Long.parseLong(params.get("out_trade_no").split("O")[0]));
              //处理业务逻辑
                    return_data.put("return_code", "SUCCESS");
                    return_data.put("return_msg", "OK");
                    return StringUtil.GetMapToXML(return_data);
                }

            }
        } catch (
                IOException e) {
            e.printStackTrace();
        } catch (
                JDOMException e) {
            e.printStackTrace();
        }
        return_data.put("return_code", "FAIL");
        return_data.put("return_msg", "out_trade_no不正确");
        return StringUtil.GetMapToXML(return_data);
    }

PayCommonUtil工具类

public class PayCommonUtil {

    //请求xml组装
    public static String getRequestXml(SortedMap<String,Object> parameters){
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String key = (String)entry.getKey();
            String value = (String)entry.getValue();
            if ("attach".equalsIgnoreCase(key)||"body".equalsIgnoreCase(key)||"sign".equalsIgnoreCase(key)) {
                sb.append("<"+key+">"+"<![CDATA["+value+"]]></"+key+">");
            }else {
                sb.append("<"+key+">"+value+"</"+key+">");
            }
        }
        sb.append("</xml>");
        return sb.toString();
    }


    /**
     * 验证回调签名
     * @return
     */
    public static boolean isTenpaySign(Map<String, String> map) {
        String characterEncoding="utf-8";
        String charset = "utf-8";
        String signFromAPIResponse = map.get("sign");
        if (signFromAPIResponse == null || signFromAPIResponse.equals("")) {
            System.out.println("API返回的数据签名数据不存在,有可能被第三方篡改!!!");
            return false;
        }
//        System.out.println("服务器回包里面的签名是:" + signFromAPIResponse);
        //过滤空 设置 TreeMap
        SortedMap<String,String> packageParams = new TreeMap();

        for (String parameter : map.keySet()) {
            String parameterValue = map.get(parameter);
            String v = "";
            if (null != parameterValue) {
                v = parameterValue.trim();
            }
            packageParams.put(parameter, v);
        }

        StringBuffer sb = new StringBuffer();
        Set es = packageParams.entrySet();
        Iterator it = es.iterator();

        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            String v = (String)entry.getValue();
            if(!"sign".equals(k) && null != v && !"".equals(v)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + API_KEY);

        //将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较
        //算出签名
        String resultSign = "";
        String tobesign = sb.toString();

        if (null == charset || "".equals(charset)) {
            resultSign = MD5Util.MD5Encode(tobesign, characterEncoding).toUpperCase();
        }else{
            try{
                resultSign = MD5Util.MD5Encode(tobesign, characterEncoding).toUpperCase();
            }catch (Exception e) {
                resultSign = MD5Util.MD5Encode(tobesign, characterEncoding).toUpperCase();
            }
        }
        String tenpaySign = ((String)packageParams.get("sign")).toUpperCase();
//        System.out.println("返回数据-tenpaySign:"+tenpaySign);
//        System.out.println("resultSign:"+resultSign);
//        System.out.println(tenpaySign.equals(resultSign));
        return tenpaySign.equals(resultSign);
    }

    //请求方法
    public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        try {

            URL url = new URL(requestUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求方式(GET/POST)
            conn.setRequestMethod(requestMethod);
            conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
            // 当outputStr不为null时向输出流写数据
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
                // 注意编码格式
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }
            // 从输入流读取返回内容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            // 释放资源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            conn.disconnect();
            return buffer.toString();
        } catch (ConnectException ce) {
            System.out.println("连接超时:{}"+ ce);
        } catch (Exception e) {
            System.out.println("https请求异常:{}"+ e);
        }
        return null;
    }

    //xml解析
    public static Map doXMLParse(String strxml) throws JDOMException, IOException {
        strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");

        if(null == strxml || "".equals(strxml)) {
            return null;
        }

        Map m = new HashMap();

        InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
        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;
    }

    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 String GetMapToXML(Map<String,String> param){
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        for (Map.Entry<String,String> entry : param.entrySet()) {
            sb.append("<"+ entry.getKey() +">");
            sb.append(entry.getValue());
            sb.append("</"+ entry.getKey() +">");
        }
        sb.append("</xml>");
        return sb.toString();
    }

}

结束!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容