content: package org.wechat.common.conn;
  
  import java.io.BufferedInputStream;
  import java.io.File;
  import java.io.FileNotFoundException;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.net.HttpURLConnection;
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.net.URLDecoder;
  import java.util.Map;
  import java.util.Set;
  import java.util.TreeMap;
  import java.util.Map.Entry;
  
  import javax.net.ssl.HostnameVerifier;
  import javax.net.ssl.HttpsURLConnection;
  import javax.net.ssl.KeyManager;
  import javax.net.ssl.SSLContext;
  import javax.net.ssl.SSLSession;
  import javax.net.ssl.TrustManager;
  
  import org.wechat.common.entity.results.AccessToken;
  import org.wechat.common.entity.results.JsonResult;
  import org.wechat.common.entity.results.WechatResult;
  import org.wechat.common.utils.ConvertJsonUtils;
  import org.wechat.common.utils.WStringUtils;
  
  import com.alibaba.fastjson.JSONObject;
  
  /**
   * 连接类
   * 
   * @author Andy
   * 
   */
  public class Connection {
  	private int default_connTime = 5000;
  	private int default_readTime = 5000;
  	private int default_upload_readTime = 10 * 1000;
  	protected String default_charset = "utf-8";
  	// 获取access_token的路径
  	private String token_path = "https://api.weixin.qq.com/cgi-bin/token";
  	// 获取微信服务器ip
  	private String backIp_path = "https://api.weixin.qq.com/cgi-bin/getcallbackip";
  	// 上传多媒体的path
  	private String up_media_path = "http://file.api.weixin.qq.com/cgi-bin/media/upload";
  
  	/**
  	 * http请求
  	 * 
  	 * @param method
  	 *            请求方法GET/POST
  	 * @param path
  	 *            请求路径
  	 * @param timeout
  	 *            连接超时时间 默认为5000
  	 * @param readTimeout
  	 *            读取超时时间 默认为5000
  	 * @param data
  	 *            数据
  	 * @return
  	 */
  	public String defaultConnection(String method, String path, int timeout,
  			int readTimeout, String data) throws Exception {
  		String result = "";
  		URL url = new URL(path);
  		if (url != null) {
  			HttpURLConnection conn = getConnection(method, url);
  			conn.setConnectTimeout(timeout == 0 ? default_connTime : timeout);
  			conn.setReadTimeout(readTimeout == 0 ? default_readTime
  					: readTimeout);
  			if (data != null && !"".equals(data)) {
  				OutputStream output = conn.getOutputStream();
  				output.write(data.getBytes(default_charset));
  				output.flush();
  				output.close();
  			}
  			if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
  				InputStream input = conn.getInputStream();
  				result = inputToStr(input);
  				input.close();
  				conn.disconnect();
  			}
  		}
  		return result;
  	}
  
  	/**
  	 * 根据url的协议选择对应的请求方式 例如 http://www.baidu.com 则使用http请求,https://www.baidu.com
  	 * 则使用https请求
  	 * 
  	 * @param method
  	 *            请求的方法
  	 * @return
  	 * @throws IOException
  	 */
  	private HttpURLConnection getConnection(String method, URL url)
  			throws IOException {
  		HttpURLConnection conn = null;
  		if ("https".equals(url.getProtocol())) {
  			SSLContext context = null;
  			try {
  				context = SSLContext.getInstance("SSL", "SunJSSE");
  				context.init(new KeyManager[0],
  						new TrustManager[] { new MyX509TrustManager() },
  						new java.security.SecureRandom());
  			} catch (Exception e) {
  				throw new IOException(e);
  			}
  			HttpsURLConnection connHttps = (HttpsURLConnection) url.openConnection();
  			connHttps.setSSLSocketFactory(context.getSocketFactory());
  			connHttps.setHostnameVerifier(new HostnameVerifier() {
  
  				@Override
  				public boolean verify(String arg0, SSLSession arg1) {
  					return true;
  				}
  			});
  			conn = connHttps;
  		} else {
  			conn = (HttpURLConnection) url.openConnection();
  		}
  		conn.setRequestMethod(method);
  		conn.setUseCaches(false);
  		conn.setDoInput(true);
  		conn.setDoOutput(true);
  		return conn;
  	}
  
  	/**
  	 * 上传网络图片
  	 * 
  	 * @param method
  	 *            请求方法 GET/POST
  	 * @param path
  	 *            api的路径
  	 * @param mediaPath
  	 *            待上传的image/voide/music 的path
  	 * @param connTime
  	 *            连接时间 默认为5000
  	 * @param readTime
  	 *            读取时间 默认为5000
  	 * @param data
  	 *            POST提交的数据
  	 * @return
  	 */
  	public String HttpUploadMedia(String method, String path, String mediaPath,
  			int connTime, int readTime, String data) throws Exception {
  		String result = "";
  		URL url = new URL(path);
  		if (url != null) {
  			String boundary = "----";
  			HttpURLConnection conn = getConnection(method, url);
  			conn.setConnectTimeout(connTime == 0 ? default_connTime : connTime);
  			conn.setReadTimeout(readTime == 0 ? default_upload_readTime
  					: readTime);
  			conn.setRequestProperty("Content-Type",
  					"multipart/form-data;boundary=" + boundary);
  			OutputStream output = conn.getOutputStream();
  			URL mediaUrl = new URL(mediaPath);
  			if (mediaUrl != null) {
  				HttpURLConnection mediaConn = (HttpURLConnection) mediaUrl
  						.openConnection();
  				mediaConn.setDoOutput(true);
  				mediaConn.setRequestMethod("GET");
  				mediaConn.setConnectTimeout(connTime == 0 ? default_connTime
  						: connTime);
  				mediaConn
  						.setReadTimeout(readTime == 0 ? default_upload_readTime
  								: readTime);
  				String connType = mediaConn.getHeaderField("Content-Type");
  				// 获得文件扩展String fileExt = getFileExt(connType);
  				String fileExt = getFileExt(connType);
  				output.write(("--" + boundary + "\r\n").getBytes());
  				output.write(("Content-Disposition: form-data; name=\"media\"; filename=\""
  						+ getFileName(mediaPath) + "\"\r\n").getBytes());
  				output.write(("Content-Type: " + fileExt + "\r\n\r\n")
  						.getBytes());
  				BufferedInputStream inputStream = new BufferedInputStream(
  						mediaConn.getInputStream());
  				byte[] array = new byte[8076];
  				int size = 0;
  				while ((size = (inputStream.read(array))) != -1) {
  					output.write(array, 0, size);
  				}
  				output.write(("\r\n----" + boundary + "--\r\n").getBytes());
  				output.close();
  				inputStream.close();
  				mediaConn.disconnect();
  				// 获取输入流
  				InputStream input = conn.getInputStream();
  				result = inputToStr(input);
  			}
  		}
  		return result;
  	}
  
  	/**
  	 * 默认的下载素材方法
  	 * 
  	 * @param method
  	 *            http方法 POST/GET
  	 * @param apiPath
  	 *            api路径
  	 * @param savePath
  	 *            素材需要保存的路径
  	 * @return 是否下载成功 Reuslt.success==true 表示下载成功
  	 */
  	public WechatResult downMeaterMetod(TreeMap<String, String> params,
  			String method, String apiPath, String savePath) {
  		WechatResult result = new WechatResult();
  		try {
  			apiPath = setParmas(params, apiPath, "");
  			URL url = new URL(apiPath);
  			HttpURLConnection conn = getConnection(method, url);
  			if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
  				String contentType = conn.getContentType();
  				result = ContentType(contentType, conn, savePath);
  			} else {
  				result.setObj(conn.getResponseCode() + " "
  						+ conn.getResponseMessage());
  			}
  		} catch (MalformedURLException e) {
  			e.printStackTrace();
  		} catch (IOException e) {
  			e.printStackTrace();
  		} catch (Exception e) {
  			e.printStackTrace();
  		}
  		return result;
  	}
  
  	/**
  	 * 根据返回的头信息返回具体信息
  	 * 
  	 * @param contentType
  	 *            ContentType请求头信息
  	 * @return Result.type==1 表示文本消息,
  	 */
  	private WechatResult ContentType(String contentType, HttpURLConnection conn,
  			String savePath) {
  		WechatResult result = new WechatResult();
  		try {
  			if (conn != null) {
  				InputStream input = conn.getInputStream();
  				if (contentType.equals("image/gif")) { // gif图片
  					result = InputStreamToMedia(input, savePath, "gif");
  				} else if (contentType.equals("image/jpeg")) { // jpg图片
  					result = InputStreamToMedia(input, savePath, "jpg");
  				} else if (contentType.equals("image/jpg")) { // jpg图片
  					result = InputStreamToMedia(input, savePath, "jpg");
  				} else if (contentType.equals("image/png")) { // png图片
  					result = InputStreamToMedia(input, savePath, "png");
  				} else if (contentType.equals("image/bmp")) { // bmp图片
  					result = InputStreamToMedia(input, savePath, "bmp");
  				} else if (contentType.equals("audio/x-wav")) { // wav语音
  					result = InputStreamToMedia(input, savePath, "wav");
  				} else if (contentType.equals("audio/x-ms-wma")) { // wma语言
  					result = InputStreamToMedia(input, savePath, "wma");
  				} else if (contentType.equals("audio/mpeg")) { // mp3语言
  					result = InputStreamToMedia(input, savePath, "mp3");
  				} else if (contentType.equals("text/plain")) { // 文本信息
  					String str = inputToStr(input);
  					result.setObj(str);
  				} else if (contentType.equals("application/json")) { // 返回json格式的数据
  					String str = inputToStr(input);
  					result.setObj(str);
  				} else { // 此处有问题
  					String str = inputToStr(input);
  					result.setObj(str);
  				}
  			} else {
  				result.setObj("conn is null!");
  			}
  		} catch (Exception ex) {
  			ex.printStackTrace();
  		}
  		return result;
  	}
  
  	/**
  	 * 将字符流转换为图片文件
  	 * 
  	 * @param input
  	 *            字符流
  	 * @param savePath
  	 *            图片需要保存的路径
  	 * @param 类型
  	 *            jpg/png等
  	 * @return
  	 */
  	private WechatResult InputStreamToMedia(InputStream input, String savePath,
  			String type) {
  		WechatResult result = new WechatResult();
  		try {
  			File file = null;
  			file = new File(savePath);
  			String paramPath = file.getParent(); // 路径
  			String fileName = file.getName(); //
  			String newName = fileName.substring(0, fileName.lastIndexOf("."))
  					+ "." + type;// 根据实际返回的文件类型后缀
  			savePath = paramPath + "\\" + newName;
  			if (!file.exists()) {
  				File dirFile = new File(paramPath);
  				dirFile.mkdirs();
  			}
  			file = new File(savePath);
  			FileOutputStream output = new FileOutputStream(file);
  			int len = 0;
  			byte[] array = new byte[1024];
  			while ((len = input.read(array)) != -1) {
  				output.write(array, 0, len);
  			}
  			output.flush();
  			output.close();
  			result.setSuccess(true);
  			result.setObj("save success!");
  		} catch (FileNotFoundException e) {
  			e.printStackTrace();
  			result.setSuccess(false);
  			result.setObj(e.getMessage());
  		} catch (IOException e) {
  			e.printStackTrace();
  			result.setSuccess(false);
  			result.setObj(e.getMessage());
  		}
  		return result;
  	}
  
  	/**
  	 * 上传本地图片
  	 * 
  	 * @param method
  	 *            请求的方法 POST/GET
  	 * @param path
  	 *            api路径
  	 * @param mediaPath
  	 *            媒体的本地路径, 例如: E:\test.jpg
  	 * @param connTime
  	 *            请求连接最长时间
  	 * @param readTime
  	 *            返回数据最长时间
  	 * @param data
  	 *            post提交的数据
  	 * @return
  	 */
  	/*
  	 * public String uploadNativeImage(String method,String path,String
  	 * mediaPath,int connTime,int readTime,String data){ String result =""; try
  	 * { URL url = new URL(path); String boundary = "----"; if(url!=null){
  	 * HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  	 * conn.setDoInput(true); conn.setDoOutput(true); conn.setUseCaches(false);
  	 * conn.setRequestMethod(method);
  	 * conn.setConnectTimeout(connTime==0?default_connTime:connTime);
  	 * conn.setReadTimeout(readTime==0?default_readTime:readTime); OutputStream
  	 * output = conn.getOutputStream(); File file = new File(mediaPath);
  	 * if(file.exists()){ FileInputStream inputStrem = new
  	 * FileInputStream(file); StringBuffer buffer = new StringBuffer(); byte[]
  	 * array = new byte[1024]; int len = 0;
  	 * while((len=inputStrem.read(array))!=-1){
  	 * 
  	 * } }else{ result="file not's exist"; } } } catch (MalformedURLException e)
  	 * { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
  	 * return result; }
  	 */
  
  	/**
  	 * 默认上传媒体的方法
  	 * 
  	 * @param method
  	 *            上次方法 默认为GET
  	 * @param path
  	 *            api路径
  	 * @param mediaPath
  	 *            图片路径
  	 * @param data
  	 *            输出参数
  	 * @return
  	 */
  	public String defaultUploadImg(String urlPath, TreeMap<String, String> map,
  			String method, String mediaPath, String data) {
  		String result = "";
  		try {
  			String url = setParmas((TreeMap<String, String>) map, urlPath, "");
  			result = HttpUploadMedia(
  					(method == null || "".equals(method)) ? "GET" : method,
  					url, mediaPath, default_connTime, default_upload_readTime,
  					data);
  		} catch (Exception ex) {
  			ex.printStackTrace();
  		}
  		return result;
  	}
  
  	/**
  	 * 上传多媒体消息的基础类()
  	 * 
  	 * @param map
  	 *            参数集合
  	 * @param method
  	 *            请求的方法, GET/POST
  	 * @param mediaPath
  	 *            待上次多媒体的路径
  	 * @param data
  	 *            post传送的参数
  	 * @return
  	 */
  	public String BasicUploadImg(TreeMap<String, String> map, String method,
  			String mediaPath, String data) {
  		String result = "";
  		try {
  			String url = setParmas((TreeMap<String, String>) map,
  					up_media_path, "");
  			result = HttpUploadMedia(
  					(method == null || "".equals(method)) ? "GET" : method,
  					url, mediaPath, default_connTime, default_upload_readTime,
  					data);
  		} catch (Exception ex) {
  			ex.printStackTrace();
  		}
  		return result;
  	}
  
  	/**
  	 * 上传素材的基本方法
  	 * 
  	 * @param params
  	 *            url中的需要添加的参数集合
  	 * @param method
  	 *            请求的方法 post/get 等
  	 * @param apiPath
  	 *            api的路径,有上传临时素材,有上传永久素材,该值不一样
  	 * @param mediaPath
  	 *            多媒体上传的路径
  	 * @param data
  	 *            post需要提交的参数
  	 * @return 上传是否成功返回的json格式字符串
  	 */
  	public String uploadMediaMethod(TreeMap<String, String> params,
  			String method, String apiPath, String mediaPath, String data) {
  		String reuslt = "";
  		try {
  			String url = setParmas(params, apiPath, "");
  			method = (method == null || "".equals(method) ? "GET" : method);
  			reuslt = HttpUploadMedia(method, url, mediaPath, default_connTime,
  					default_upload_readTime, data);
  		} catch (Exception e) {
  			e.printStackTrace();
  		}
  		return reuslt;
  	}
  
  	/**
  	 * 将输入流转换为字符串
  	 * 
  	 * @param input
  	 *            输入流
  	 * @return 转换后的字符串
  	 */
  	public String inputToStr(InputStream input) {
  		String result = "";
  		if (input != null) {
  			byte[] array = new byte[1024];
  			StringBuffer buffer = new StringBuffer();
  			try {
  				for (int index; (index = (input.read(array))) > -1;) {
  					buffer.append(new String(array, 0, index, default_charset));
  				}
  				result = buffer.toString();
  			} catch (IOException e) {
  				e.printStackTrace();
  				result = "";
  			}
  		}
  		return result;
  	}
  
  	/**
  	 * 设置参数
  	 * @param map    参数map
  	 * @param path      需要赋值的path
  	 * @param charset  编码格式 默认编码为utf-8
  	 * @return 已经赋值好的url 只需要访问即可
  	 */
  	public String setParmas(Map<String, String> map, String path, String charset)
  			throws Exception {
  		String result = "";
  		boolean hasParams = false;
  		if (path != null && !"".equals(path)) {
  			if (map != null && map.size() > 0) {
  				StringBuilder builder = new StringBuilder();
  				Set<Entry<String, String>> params = map.entrySet();
  				for (Entry<String, String> entry : params) {
  					String key = entry.getKey().trim();
  					String value = entry.getValue().trim();
  					if (hasParams) {
  						builder.append("&");
  					} else {
  						hasParams = true;
  					}
  					charset = (charset != null && !"".equals(charset) ? charset: default_charset);
  					builder.append(key).append("=").append(URLDecoder.decode(value, charset));
  				}
  				result = builder.toString();
  			}
  		}
  		// 此时的url待改进
  		return doUrlPath(path, result).toString();
  	}
  
  	/**
  	 * 设置连接参数
  	 * 
  	 * @param path
  	 *            路径
  	 * @return
  	 */
  	private URL doUrlPath(String path, String query) throws Exception {
  		URL url = new URL(path);
  		if (WStringUtils.StringIsEmpty(path)) {
  			return url;
  		}
  		if (WStringUtils.StringIsEmpty(url.getQuery())) {
  			if (path.endsWith("?")) {
  				path += query;
  			} else {
  				path = path + "?" + query;
  			}
  		} else {
  			if (path.endsWith("&")) {
  				path += query;
  			} else {
  				path = path + "&" + query;
  			}
  		}
  		return new URL(path);
  	}
  
  	/**
  	 * 默认的http请求执行方法,返回
  	 * 
  	 * @param method
  	 *            请求的方法 POST/GET
  	 * @param path
  	 *            请求path 路径
  	 * @param map
  	 *            请求参数集合
  	 * @param data
  	 *            输入的数据 允许为空
  	 * @return
  	 */
  	public String HttpDefaultExecute(String method, String path,
  			Map<String, String> map, String data) {
  		String result = "";
  		try {
  			String url = setParmas((TreeMap<String, String>) map, path, "");
  			result = defaultConnection(method, url, default_connTime,
  					default_readTime, data);
  		} catch (Exception e) {
  			e.printStackTrace();
  		}
  		return result;
  	}
  
  	/**
  	 * 默认的https执行方法,返回
  	 * 
  	 * @param method
  	 *            请求的方法 POST/GET
  	 * @param path
  	 *            请求path 路径
  	 * @param map
  	 *            请求参数集合
  	 * @param data
  	 *            输入的数据 允许为空
  	 * @return
  	 */
  	public String HttpsDefaultExecute(String method, String path,
  			Map<String, String> map, String data) {
  		String result = "";
  		try {
  			String url = setParmas((TreeMap<String, String>) map, path, "");
  			result = defaultConnection(method, url, default_connTime,default_readTime, data);
  		} catch (Exception e) {
  			e.printStackTrace();
  		}
  		return result;
  	}
  
  	/**
  	 * 获取授权token
  	 * 
  	 * @param key
  	 *            应用key
  	 * @param secret
  	 *            应用密匙
  	 * @return json格式的字符串
  	 */
  	public String getAccessToken(String key, String secret) {
  		TreeMap<String, String> map = new TreeMap<String, String>();
  		map.put("grant_type", "client_credential");
  		map.put("appid", key);
  		map.put("secret", secret);
  		String result = HttpDefaultExecute("GET", token_path, map, "");
  		return result;
  	}
  
  	
  	/**
  	 * 获取授权信息
  	 * @param key	    appkey		
  	 * @param secret	secret
  	 * @return		result.success==true时,result.obj为accessToken对象  否则为 result.obj=错误提示信息 
  	 * 		        result.msg= 原始返回数据
  	 */
  	public WechatResult getAccessTokenObject(String key,String secret){
  		WechatResult result = new WechatResult();
  		String jsonData = getAccessToken(key,secret);
  		JSONObject object = JSONObject.parseObject(jsonData);
  		if(object.containsKey("access_token")){
  			AccessToken token = ConvertJsonUtils.jsonToJavaObject(jsonData,AccessToken.class);
  			result.setSuccess(true);
  			result.setObj(token);
  		}else{
  			result.setObj(jsonData);
  		}
  		result.setMsg(jsonData);
  		return result;
  	}
  
  	/**
  	 * 获取微信服务ip地址
  	 * 
  	 * @param token
  	 * @return
  	 */
  	public String getCallBackIp(String token) {
  		TreeMap<String, String> map = new TreeMap<String, String>();
  		map.put("access_token", token);
  		String result = HttpDefaultExecute("GET", backIp_path, map, "");
  		return result;
  	}
  
  	/**
  	 * 根据内容类型判断文件扩展名
  	 * 
  	 * @param ContentType
  	 *            内容类型
  	 * @return
  	 */
  	private String getFileExt(String contentType) {
  		String fileExt = "";
  		if ("image/jpeg".equals(contentType)) {
  			fileExt = ".jpg";
  		} else if ("audio/mpeg".equals(contentType)) {
  			fileExt = ".mp3";
  		} else if ("audio/amr".equals(contentType)) {
  			fileExt = ".amr";
  		} else if ("video/mp4".equals(contentType)) {
  			fileExt = ".mp4";
  		} else if ("video/mpeg4".equals(contentType)) {
  			fileExt = ".mp4";
  		} else if ("image/png".equals(contentType)) {
  			fileExt = ".png";
  		}
  
  		return fileExt;
  	}
  
  	/**
  	 * 文件路径
  	 * 
  	 * @param mediaUrl
  	 *            url 例如
  	 *            http://su.bdimg.com/static/superplus/img/logo_white_ee663702
  	 *            .png
  	 * @return logo_white_ee663702.png
  	 */
  	private String getFileName(String mediaUrl) {
  		String result = mediaUrl.substring(mediaUrl.lastIndexOf("/") + 1,
  				mediaUrl.length());
  		return result;
  	}
  
  	/**
  	 * 将json格式的字符串转换为Result	 
  	 * @param jsonResult	如果result.success=true result.obj==AccessToken 否则为错误提示信息
  	 * @return				result.msg 为最原始的json格式数据
  	 */
  	public static WechatResult ConvertToken(String jsonResult) {
  		WechatResult result = new WechatResult();
  		if (jsonResult != null && !"".equals(jsonResult)) {
  			JSONObject json = JSONObject.parseObject(jsonResult);
  			if (json.containsKey("access_token")&& json.containsKey("expires_in")) { // 表示成功!
  				AccessToken token = JSONObject.parseObject(jsonResult, AccessToken.class);
  				result.setObj(token);
  				result.setSuccess(true);
  			}else{
  				result.setObj(jsonResult);
  			}
  		}
  		result.setMsg(jsonResult);
  		return result;
  	}
  
  	/**
  	 * 将json字符串转换为JsonResult对象
  	 * 
  	 * @param jsonResult
  	 * @return
  	 */
  	public JsonResult ConvertResult(String jsonResult) {
  		JsonResult result = null;
  		if (jsonResult != null && !"".equals(jsonResult)) {
  			JSONObject jsonObj = JSONObject.parseObject(jsonResult);
  			if (jsonObj.containsKey("errcode") && jsonObj.containsKey("errmsg")) { // success
  				result = JSONObject.toJavaObject(jsonObj, JsonResult.class);
  			}
  		}
  		return result;
  	}
  }
  