微信开发 请求400

2018-05-20 22:28:08 sinat_36553913 阅读数 1590

说明

      进行微信开发,后台程序需要与微信服务器进行交互,通过调用接口来完成服务,阅读微信开发文档,发现接口的调用都是通过http请求进行的,所以必须有个HttpUtil来支撑,这里总结下以javaAPI的方式和以Apach的HttpClient的方式进行HTTP请求

正文

使用java的HttpURLConnection

一个方法实现GET,POST请求

public static String httpRequest(String requestUrl, String requestMethod, String outputStr){
        StringBuffer buffer = new StringBuffer();
        try {
            URL url = new URL(requestUrl);
            HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
            httpURLConnection.setDoInput(true);
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setUseCaches(false);
            httpURLConnection.setRequestMethod(requestMethod);

            if("GET".equalsIgnoreCase(requestMethod)){
                httpURLConnection.connect();
            }

            if(null != outputStr){
                OutputStream outputStream = httpURLConnection.getOutputStream();
                outputStream.write(outputStr.getBytes("utf-8"));
                outputStream.close();
            }

            InputStream inputStream = httpURLConnection.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            while((str = bufferedReader.readLine())!= null){
                buffer.append(str);
            }

            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            httpURLConnection.disconnect();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return buffer.toString();
    }

此方法通过指定URL,请求的方式和参数进行请求,使用流的方式发送参数和读取响应结果。该方法简单,没有设置http的请求属性等,示例代码在微信开发中可以实现功能。
在此方法中 参数outputStr是向微信服务器发送的json格式的数据或者xml结构的数据,友好性不太好,通常应该传递Map<String,Object> params 保存参数

Get请求

private static final String CHAR_SET = "UTF-8";
 public static String sendGet(String url, Map<String,Object> params){
        StringBuilder responseStr = null;
        StringBuilder paramsStr = new StringBuilder();
        if(params != null || params.size() > 0){
            for(Map.Entry<String,Object> entry : params.entrySet()){
                paramsStr.append(entry.getKey());
                paramsStr.append("=");
                try {
                    paramsStr.append(URLEncoder.encode(String.valueOf(entry.getValue()),CHAR_SET));
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                paramsStr.append("&");
            }
        }
        URL URLstr = null;
        BufferedReader bufr = null;
        HttpURLConnection httpURLConnection = null;
        try {
            if(paramsStr != null && paramsStr.length() > 0){
                url = url + "?" + paramsStr.substring(0,paramsStr.length() - 1);
            }
            URLstr = new URL(url);
            httpURLConnection = (HttpURLConnection) URLstr.openConnection();
            httpURLConnection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
            httpURLConnection.connect();
            responseStr = new StringBuilder();
            bufr = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(),CHAR_SET));
            String str = null;
            while((str = bufr.readLine()) != null){
                responseStr.append(str);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            httpURLConnection.disconnect();
            if (bufr != null){
                try {
                    bufr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return  responseStr.toString();
    }

Post请求

public static String sendPost(String url, Map<String, Object> params){
        StringBuilder responseStr = null;
        StringBuilder paramsStr = new StringBuilder();
        if(params != null || params.size() > 0){
            for(Map.Entry<String,Object> entry : params.entrySet()){
                paramsStr.append(entry.getKey());
                paramsStr.append("=");
                try {
                    paramsStr.append(URLEncoder.encode(String.valueOf(entry.getValue()),CHAR_SET));
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                paramsStr.append("&");
            }
        }
        URL URLstr = null;
        BufferedReader bufr = null;
        HttpURLConnection httpURLConnection = null;
        OutputStreamWriter osw = null;
        try {
            URLstr = new URL(url);
            httpURLConnection = (HttpURLConnection) URLstr.openConnection();
            httpURLConnection.setRequestMethod("POST");
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setDoInput(true);
            httpURLConnection.setUseCaches(false);
            if(paramsStr != null && paramsStr.length() > 0){
                osw = new OutputStreamWriter(httpURLConnection.getOutputStream(),CHAR_SET);
                osw.write(paramsStr.substring(0,paramsStr.length() - 1));
                osw.flush();
            }
            bufr = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(),CHAR_SET));
            String str = null;
            while((str = bufr.readLine()) != null){
                responseStr.append(str);
            }

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(osw != null){
                try {
                    osw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(httpURLConnection != null) {
                httpURLConnection.disconnect();
            }
            if(bufr != null){
                try {
                    bufr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
        return responseStr.toString();
    }

通过对比sendGet和sendPost两种方法,发现不同之处有:

  • 在创建URL对象时,sendGet方法的url是直接拼接了参数,而sendPost方法没有,sendPost方法通过OutputStremWriter对象将参数直接写出
  • 在创建了HttpURLConnection对象后,sendGet方法调用了connect()方法,sendPost没有调用此方法,但是显示设置了RequestMethod为POST
  • 在设置参数sendGet方法显示设置了“Content-Type”,sendPost则省略了,该参数可以不显示设置,关于“application/x-www-form-urlencoded”详细解释,为什么可以不显示设置,详见:《HTTP中application/x-www-form-urlencoded字符说明》
  • 在sendPost方法中显示设置了DoOutput和DoInput为true,UseCaches为false

使用HttpClient

Get请求

public static String httpClienOfGet(String url,Map<String,Object> params){
        String res = "";
        StringBuilder paramsStr = null;
        if(params != null && params.size() > 0){
            for(Map.Entry<String,Object> entry : params.entrySet()){
                paramsStr.append(entry.getKey());
                paramsStr.append("=");
                try {
                    paramsStr.append(URLEncoder.encode(String.valueOf(entry.getValue()),CHAR_SET));
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                paramsStr.append("&");
            }
        }

        if(paramsStr != null && paramsStr.length() > 0){
            url = url + "?" + paramsStr.substring(0,paramsStr.length() - 1);
        }
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        try {
            HttpResponse response = httpClient.execute(httpGet);
            if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                res = EntityUtils.toString(response.getEntity());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(httpClient != null){
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return res;
    }

Post请求

 public static String httpClientOfPost(String url, Map<String, Object> params){
        String res = "";
        List<NameValuePair> paramList = new ArrayList<NameValuePair>();
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpPost  httpPost = new HttpPost(url);

        if(params != null && params.size() > 0){
            for(Map.Entry<String,Object> entry : params.entrySet()){
                paramList.add(new BasicNameValuePair(entry.getKey(),String.valueOf(entry.getValue())));
            }
        }

        try {
            if(paramList.size() > 0){
                UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(paramList,CHAR_SET);
                httpPost.setEntity(urlEncodedFormEntity);
            }
            HttpResponse response = httpClient.execute(httpPost);
            if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
                res = EntityUtils.toString(response.getEntity());
            }
        } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(httpClient != null){
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return res;
    }

通过比较这两种方式,发现在创建请求方法时,对url处理不同,HttpGet的url直接拼接了参数,而HttpGet的url不做处理,参数则是通过了urlEncodedFormEntity 对象进行设置

通过Post请求发送接收json格式的数据

在微信开发时,通常要通过http发送json格式的数据,微信服务器返回的是json数据,包含了code和msg

public static String jsonOfPost(String url, String param){
        String res = "";
        DefaultHttpClient client = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Accept","application/json");
        httpPost.setHeader("Content-Type","application/json");
        String charSet = "UTF-8";
        HttpResponse response = null;

        try {
            StringEntity entity = new StringEntity(param,charSet);
            entity.setContentEncoding(charSet);
            entity.setContentType("application/json");
            httpPost.setEntity(entity);
            response = client.execute(httpPost);
            StatusLine statusLine = response.getStatusLine();
            int state = statusLine.getStatusCode();
            if(state == org.apache.http.HttpStatus.SC_OK){
                HttpEntity responseEntity = response.getEntity();
                res = EntityUtils.toString(responseEntity);
                return res;
            }else{
                System.out.println("请求出错");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return res;
    }

关于http的请求总结到这里,有关于POST和GET请求的区别,详见:
https://blog.csdn.net/yaojianyou/article/details/1720913/
http://www.nowamagic.net/librarys/veda/detail/1919

参考的优秀博文:
https://www.cnblogs.com/mengrennwpu/p/6418114.html
https://blog.csdn.net/u010197591/article/details/51441399
https://blog.csdn.net/qq9808/article/details/78320816

2014-07-15 15:02:47 zhangdaiscott 阅读数 38095

                          微信开发本地调试工具(模拟微信客户端)


开源免费微信管家系统(java)源码下载


微信部署需要依靠80端口,如何快速有效的调试本地微信开发程序,

捷微团队(jeewx-java微信开源系统),采用微信开发调试工具,

供本地开发测试;


第一个参数:http://localhost:8080/jeewx/wechatController.do?wechat

第二个参数:微信公众账号的原始ID

QQ图片20140714231105.jpg

微信开发调试功能.rar

69.42 KB, 阅读权限: 10, 下载次数: 19



体验公众号:



2015-04-22 09:49:19 ctbtcol 阅读数 5342

最近给客户做了个微信公众号,其中在菜单上配置的查询功能需要访问客户系统接口获取数据;

微信端的http请求在一定时间内(微信开发文档中写的是5s,实际开发查看报文是7s)无法得到返回的话会重发此请求。

微信的请求中会带有一个code参数用于再次请求微信服务器获取微信用户信息,重发请求发送的也是相同的code;

而这个code是一次性的,action在接到重发请求时无法通过相同的code再次获取微信用户信息。

项目会先通过code获取微信用户的OpenID,再查询客户系统接口。

但客户的系统接口查询比较慢,大约30秒左右,所以第一次的查询通过code获得了微信用户的openID并等待客户系统返回查询结果时候,微信会用相同的code发起重发请求;

而重发请求的code由于已经被使用过,是无法获得微信用户的OpenID的,所以系统会先于第一次查询返回给微信client端一个查询失败的结果页,导致查询功能不能使用。

由此,想出了以下的解决方案:

1.联系客户系统提升接口速度

——联系过客户进行优化,速度没有提升

2.联系微信客服尝试修改重发时间限制

——微信客服没有回应

3.保存code,并过滤掉相同code的重发请求

——用filter和servlet写demo测试没有能成功实现拦截请求,总是会返回一个空白页面

4.增加loading页面相应微信端请求,再异步执行查询action

——这里的实现上有很多种:

4.1在原有页面中增加loading蒙版,并使用AJAX异步请求Action查询

——原来的页面使用JSTL获取数据,改由使用AJAX传递JSON与Action进行数据交互的话,页面的获取方式和Action类的返回方式都需要重写

4.2新建loading页面

实现后发现这种办法比我想象的简单,单独的一个页面实现loading的js效果,并且在页面中加入如下的逻辑先获取微信用户的OpenID:

WeiXinClient weixin = new WeiXinClient ();
String OpenID = weixin.getOpenId(request);

并在页面中加入如下JS代码即可实现效果:

	$(document).ready(function(){
		modal_loading();
		document.location.href="/action/getInfo?OpenID=<%=OpenID%>";
	});	 


modal_loading();是页面loading的JS方法,这部分JS源码的实现方式我没看懂,网上应该有很多类似JS功能代码;

Action类中的逻辑执行完成后会直接跳转到结果展示页,这样原来的Action和展示页面都不用改。



附:WeiXinClient中的功能代码,感谢实现这部分功能的我的同事:-P:

	public static String getOpenId(HttpServletRequest req){
		String code = req.getParameter("code");//获取code
		String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+"公众号的AppId"+"&secret="+"公众号AppSecret"+"&code="+code+"&grant_type=authorization_code";
		JSONObject json = CommonUtil.httpsRequest(url, "GET", null);
		String openId = (String)json.get("openid");
		return openId;
	}





2014-09-10 19:05:58 rzg813 阅读数 17874

微信企业号请求数据基类封装:

微信开发调用接口操作,需要封装请求操作基类,方便我们完成数据读取操作,因此需要封装常用的方法。

首先封装发起http请求并获取结果的2个类:一个返回JSONObject对象,一个返回byte[]字节数组

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.SecureRandom;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import xxx.Enum.EnumMethod;
import net.sf.json.JSONObject;

public class HttpRequestUtil {
	
	/**
	 * 发起https请求并获取结果
	 * 
	 * @param requestUrl 请求地址
	 * @param requestMethod 请求方式(GET、POST)
	 * @param outputStr 提交的数据
	 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
	 */
	public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
		
		System.err.println(requestMethod+"\toutputStr="+outputStr);
		
		JSONObject jsonObject = null;
		StringBuffer buffer = new StringBuffer();
		try {
			// 创建SSLContext对象,并使用我们指定的信任管理器初始化
			TrustManager[] tm = { new MyX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			// 从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();

			URL url = new URL(requestUrl);
			HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
			httpUrlConn.setSSLSocketFactory(ssf);

			httpUrlConn.setDoOutput(true);
			httpUrlConn.setDoInput(true);
			httpUrlConn.setUseCaches(false);
			// 设置请求方式(GET/POST)
			httpUrlConn.setRequestMethod(requestMethod);

			if ("GET".equalsIgnoreCase(requestMethod))
				httpUrlConn.connect();

			// 当有数据需要提交时
			if (null != outputStr) {
				OutputStream outputStream = httpUrlConn.getOutputStream();
				// 注意编码格式,防止中文乱码
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.close();
			}

			// 将返回的输入流转换成字符串
			InputStream inputStream = httpUrlConn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

			String str = null;
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}
			bufferedReader.close();
			inputStreamReader.close();
			// 释放资源
			inputStream.close();
			inputStream = null;
			httpUrlConn.disconnect();
			jsonObject = JSONObject.fromObject(buffer.toString());
			//System.out.println("jsonObject="+jsonObject);
		} catch (ConnectException ce) {
			ce.printStackTrace();
			System.out.println("网络链接失败!");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return jsonObject;
	}
	
	/**
	 * 发起https请求并获取字节数组结果
	 * @param requestUrl
	 * @param requestMethod
	 * @param data
	 * @return
	 */
	public static byte[] httpRequest_byte(String requestUrl, String requestMethod, byte[] data) {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		try {
			if (requestMethod == EnumMethod.GET.name() && data != null && data.length > 0) {
				if (requestUrl.indexOf('?') > 0) {
					requestUrl += '&';
				} else {
					requestUrl += '?';
				}
				requestUrl += new String(data);
			}
			URL url = new URL(requestUrl);
			HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
			if (httpUrlConn instanceof HttpsURLConnection) {
				// 创建SSLContext对象,并使用我们指定的信任管理器初始化
				TrustManager[] tm = { new MyX509TrustManager() };
				SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
				sslContext.init(null, tm, new SecureRandom());
				// 从上述SSLContext对象中得到SSLSocketFactory对象
				SSLSocketFactory ssf = sslContext.getSocketFactory();
				((HttpsURLConnection) httpUrlConn).setSSLSocketFactory(ssf);
			}
			boolean truePost = requestMethod == EnumMethod.POST.name() && data != null && data.length > 0;
			httpUrlConn.setDoOutput(truePost);
			httpUrlConn.setDoInput(true);
			httpUrlConn.setUseCaches(false);
			// 设置请求方式(GET/POST)
			httpUrlConn.setRequestMethod(requestMethod);

			if (requestMethod == EnumMethod.GET.name()) {
				httpUrlConn.connect();
			} else if (truePost) {
				// 提交数据
				OutputStream outputStream = httpUrlConn.getOutputStream();
				outputStream.write(data);
				outputStream.close();
			}

			// 读取返回数据
			InputStream inputStream = httpUrlConn.getInputStream();
			byte[] buf = new byte[1024 * 2];
			int len;
			while ((len = inputStream.read(buf)) != -1) {
				out.write(buf, 0, len);
			}
			// 释放资源
			out.close();
			inputStream.close();
			inputStream = null;
			httpUrlConn.disconnect();
		} catch (ConnectException ce) {
		} catch (Exception e) {
		}
		return out.toByteArray();
	}
}


此处需要一个枚举类:

package xxx.Enum;

public enum EnumMethod {
	GET,POST;
}

以上是对httprequest 请求类的封装。


2015-12-10 20:24:26 qq_16558621 阅读数 1190

这几天做微信开发,深一脚浅一脚,总算摸出来一些门道和一些小小的感悟。

今天给大家分享一个在微信平台php发送HTTP GET请求的方法:

public function get_request($url)
		{
		$curl = curl_init();
		curl_setopt($curl, CURLOPT_URL, $url);
		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
		curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
		$data = curl_exec($curl);
		if (curl_errno($curl)) {return 'ERROR '.curl_error($curl);}
		curl_close($curl);
		return $data;
	   }