这是我的第一篇博客,突然就想写一篇,写的不好要见凉呀!
 这篇主要是介绍一下“公众号微信支付”也就是JSAPI支付,用最基础的方式来实现。
 里面有的内容也是当初在一些大神博客里面借鉴的一些代码!
  其实实现不难,主要是deBug,我猜有人会不知道怎么操作,这里强烈建议Sunny-Ngrok。
  有免费的域名,不过速度不快,也可以10元买一个,这个就快了。
  下面的代码直接复制,在本地调试一下就可以实现支付,不过不建议!
  下面开始直接进入正题。
  1. 首先是基础配置:
    要写这个功能你肯定有个微信公众号的后台的登录账号,在公众号设置里面如图:

    这里还有一个要注意的地方,基本配置里的IP白名单一定不要忘了(可以设置几个)!
    紧接就是“微信商户平台”里面配置一下如图:

    这里如果域名没有设置正确,你页面里的支付控件可能只是“闪”一下就没了。
    然后开始介绍业务流程:附图一张官方流程

    这里我口水话简述一下:
    1.授权页面获取code
    2.用code获取用户的openId
    3.处理好预支付所需要的相关参数,请求接口获取预支付id(prepay_id) --第一次签名
    4.再把获取的预支付id,跟所需要的参数封装起来,异步返回到前端,调起支付控件 --第二次签名
    5.前端获取到支付成功的消息后,执行自己的业务逻辑
    下面开始贴代码跟详细表述一下:
    微信相关参数类:
public class WxPayConfig {
	//=======【基本信息设置】=====================================
	//微信公众号身份的唯一标识。审核通过后,在微信发送的邮件中查看
	public static final String APPID = "..";//
	//商户id
	public static final String MCHID = "..";//
	//商户支付密钥Key。审核通过后,在微信发送的邮件中查看,在申请支付开发的时候自己设置的
	public static final String KEY = "..";//
	//应用密匙JSAPI接口中获取openid,审核后在公众平台开启开发模式后可查看
	public static final String APPSECRET = "..";//需改
	
	//=======【异步通知url设置】===================================
	//异步通知url,回调的地址,一定是外网地址
	private static String SERVER_URL = "http://www.xxx.cn";//需改
	public static final String NOTIFY_URL = SERVER_URL + "/notifyUrl";
	//编码方式
	public static final String ENCODE = "UTF-8";
	
	//微信uri-根据code获取openid的请求地址
	public static String GET_OPENID = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code";
	
	//微信uri-请求预支付接口
	public static String UNIFIED_ORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder";
}

一 获取code(这里一般就是你公众号里面的自定义菜单中的地址,授权后再重定向到你的页面)

@WebServlet("/userWeixin")
public class UserWeixin extends HttpServlet {
	
	/**
	 * @Fields serialVersionUID : TODO
	 */
	private static final long serialVersionUID = -74398932371435346L;



	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		 // 将请求、响应的编码均设置为UTF-8(防止中文乱码)  
        request.setCharacterEncoding("UTF-8");  
        response.setCharacterEncoding("UTF-8"); 
       
        //回调地址
        String backUrl="http://www.xxxx.cn/jsp/zb/up_register.jsp";
        
        //3个参数,response_type:固定为token  。client_id=appid  。 redirect_uri:成功后回调后地址
        //授权地址
		String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+WxPayConfig.APPID
                + "&redirect_uri="+URLEncoder.encode(backUrl,"UTF-8")
                + "&response_type=token"
                + "&scope=snsapi_userinfo"
                + "&state=STATE#wechat_redirect";
		
		
        //重定向到授权页面
        response.sendRedirect(url);
		
	}

}

这个时候重定向时到你指定的地址时,链接里面或附带参数code。就像这样:delUser?code=xxx";
你有很多种方法获取:比如<span id="code" >${param.code}</span>,然后
$("#code").text(); 二、获取openId (这里就是页面中,点击 支付按钮后的一系列操作)

<script type="text/javascript">
   	$(function(){
		$("#byband").click(function(){
			 a();
			 var r=confirm("确认购买?");
			  if (r==true)
			    {
				  doPay();
			    }
		});
	});	
   	</script>
function a(){
	$.ajax({
		type: 'POST',
	    url: "http://www.xxxx.cn/getOpenId" , /*如有nginx、apache、iis等配置,根据自己的代理服务器配置填写*/
	    data: "code=" + $("#code").text(),
	    dataType: "json",
	    async:false,
	    success:function(data){
			console.log(data);
	    	if(data.status == 1){//openid获取成功
	 			orderId = data.orderId;
	    	}else{//重定向回本页面
	    		var currentUrl = window.location.href;
	    		//去掉code之后的url
	    		var redirectUrl = delQueStr(currentUrl, "code");
	    		//拼接微信授权路径
	    		var uri = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+ data.appId +"&redirect_uri="+ redirectUrl +"&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
	    		location.href = uri;//重定向
	    	}
	    },
	    error:function(){
	    	alert("获取openid错误");
	    }
	    	
	});
}
@WebServlet("/getOpenId")
public class GetOpenIdServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;


	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Object openIdObj = request.getSession().getAttribute("openId");
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("status", 0);//默认失败
		map.put("appId", WxPayConfig.APPID);//为了给前端用
		if(!StringUtil.isNullOrEmpty(openIdObj)){//已经在session存在  直接返回
			map.put("status", 1);//成功
			map.put("openId", openIdObj.toString());
		}else{//根据code获取openid
			String code = request.getParameter("code");
			if(!StringUtil.isNullOrEmpty(code)){//有code
				//请求api获取openid
				String str = HttpInvoker.sendGetRequest(StringUtil.format(WxPayConfig.GET_OPENID, new Object[]{WxPayConfig.APPID,WxPayConfig.APPSECRET,code}));
				//将json转map
				Map<String, Object> toMap = WeixinUtil.jsonStrToMap(str);
				if(!StringUtil.isNullOrEmpty(toMap.get("openid"))){//获取openid成功
					map.put("status", 1);//成功
					map.put("openId", toMap.get("openid").toString());
					//放入session
					request.getSession().setAttribute("openId", toMap.get("openid").toString());
					//设定session只存在30秒,防止冲突
					request.getSession().setMaxInactiveInterval(30);
				}
			}
		}
		//返回结果
		response.getWriter().print(JSONObject.fromObject(map).toString());
	}

}

这里把openId存入session中,如果你一个域名下有多个公众号支付,一定要注意设置session的存活时间。

三、生成自己的订单号和,获取预支付id,调起支付控件,支付成功跳转

//去支付
function doPay(){
	//先要获取orderId
	$.ajax({
		type: 'POST',
	    url: "http://www.xxxx.cn/newOrder" , 
	    data: null,
	    dataType: "json",
	    async:false,
	    success:function(data){
			console.log(data);
	    	if(data.status == 1){//openid获取成功
	    		doPrePayId(data.orderId);
	    	}else{//重定向回本页面
	    		alert("获取orderid错误");
	    	}
	    },
	    error:function(){
	    	alert("获取openid错误");
	    }
	    	
	});
}
function doPrePayId(orderId){
	//获取预支付id
	$.ajax({
		type: 'POST',//body 商品描述。tatalFee 金额(分)
	    url: "http://www.xxx.cn/BandunifiedOrder" ,
	    data: "orderId=" + orderId,
	    dataType: "json",
	    success:function(res){
	    	if(res.status == 1){//成功
	    		payParam = res.param;//赋值给微信支付参数
	    		onBridgeReady(res.param);//调起控件
	    	}else{
	    		alert(res.msg);
	    	}
	    },
	    error:function(){
	    	alert("获取预支付id错误");
	    }
	});
}
//微信提供代码
function onBridgeReady(payParam){
   WeixinJSBridge.invoke('getBrandWCPayRequest',payParam,
       function(res){
	   // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。 
           if(res.err_msg == "get_brand_wcpay_request:ok" ) {
        	   alert("支付成功!");
        	   window.location.href="http://www.xxxx.cn/updataUserByBandStatus";
           }    
       }
   ); 
}
@WebServlet("/newOrder")
public class NewOrderServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//这里应该写生成订单和支付相关的数据 
		//这里我直接写死
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("status", 1);//成功
		map.put("orderId", OrderUtil.gens("SCJYZB"));//生产订单编号
		response.getWriter().print(JSONObject.fromObject(map).toString());//返回
	}

}
@WebServlet("/unifiedOrder")
public class UnifiedOrderServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
		String orderId = request.getParameter("orderId");//订单id
		Map<String,Object> rsMap = new HashMap<String, Object>();
		PrintWriter out = response.getWriter();
		try{
			rsMap.put("status", 0);//默认出错
			//必要参数请自行判断
			if(StringUtil.isNullOrEmpty(orderId)){
				throw new Exception("订单id为空");
			}
			String openId = "";
			Object openIdObj = request.getSession().getAttribute("openId");
			if(!StringUtil.isNullOrEmpty(openIdObj)){//优先拿session
				openId = openIdObj.toString();
			}else{
				String opid = request.getParameter("openId");
				if(!StringUtil.isNullOrEmpty(opid)){
					openId = opid;
				}else{
					throw new Exception("openid为空");
				}
			}
				
			//---------获取调用预支付相关参数
			Map<String,String> paramMap = new HashMap<String, String>();
			paramMap.put("appid", WxPayConfig.APPID);//appid
			paramMap.put("mch_id", WxPayConfig.MCHID);//商户号
			paramMap.put("nonce_str", WeixinUtil.createNoncestr(32));//随机字符串
			paramMap.put("body","Zbfile");//商品描述
			//商户订单号:需唯一  (一定要注意,看自己设计,支付id和订单id关联)
			//注:我们这里用orderId,按道理是需要支付id,
			//也就是每次按支付都要生成不一样的id,防止支付错误
			paramMap.put("out_trade_no", orderId);
			paramMap.put("total_fee", "20000");//金额 -- 实际金额需除以 100
			paramMap.put("spbill_create_ip", WeixinUtil.getRemoteHost(request));//客户ip地址
			paramMap.put("notify_url", WxPayConfig.NOTIFY_URL);//回调地址
			paramMap.put("trade_type", "JSAPI");//交易类型
			paramMap.put("openid", openId);//用户openid
			paramMap.put("sign", WeixinUtil.getSign(paramMap));//签名 ,默认sign_type是MD5
			//---------------
			String unifiedStr = HttpInvoker.sendPostRequest(WxPayConfig.UNIFIED_ORDER, WeixinUtil.arrayToXml(paramMap));
			Map<String, String> preMap = WeixinUtil.xmltoMap(unifiedStr);
			
			String prepayId = preMap.get("prepay_id");
			if(StringUtil.isNullOrEmpty(prepayId)){
				throw new Exception("获取prepay_id错误:" + preMap.get("return_msg"));
			}
			//返回参数
			Map<String,String> jsApiMap = new HashMap<String,String>();
			jsApiMap.put("appId", WxPayConfig.APPID);
			jsApiMap.put("timeStamp", WeixinUtil.getTimestamp(new Date()) + "");
			jsApiMap.put("nonceStr", WeixinUtil.createNoncestr(32));
			jsApiMap.put("package", "prepay_id=" + prepayId);
			jsApiMap.put("signType", "MD5");
			jsApiMap.put("paySign", WeixinUtil.getSign(jsApiMap));
			
			rsMap.put("status", 1);//成功
			rsMap.put("param", JSONObject.fromObject(jsApiMap));
			
			String json = JSONObject.fromObject(rsMap).toString();
			out.print(json);//发送给前端
			request.getSession().removeAttribute("openId");//刷新openid,防止。公众号,与openid冲突
		}catch(Exception e){
			e.getStackTrace();
			rsMap.put("msg", e);
			out.print(rsMap);
		}finally{
			out.close();
			out = null;
		}
	}

}

所用工具类:

/**
 *	http请求类
 * ClassName: HttpInvoker 
 * date: 2017年10月24日 下午2:17:06 
 *
 */
public class HttpInvoker {

	/**
	 * 该url里面已经携带了请求参数
	 * 
	 * @param url
	 * @throws IOException
	 * @Description:
	 */
	public static String sendGetRequest(String url) {
		String lines = "";
		try {
			// 拼凑get请求的URL字串,使用URLEncoder.encode对特殊和不可见字符进行编码
			/*String getURL = url + "?username="
					+ URLEncoder.encode("fata", "utf-8");*/
			URL getUrl = new URL(url);
			// 根据拼凑的URL,打开连接,URL.openConnection()函数会根据
			// URL的类型,返回不同的URLConnection子类的对象,在这里我们的URL是一个http,因此它实际上返回的是HttpURLConnection
			HttpURLConnection connection = (HttpURLConnection) getUrl
					.openConnection();
			// 建立与服务器的连接,并未发送数据
			connection.connect();
			// 发送数据到服务器并使用Reader读取返回的数据
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					connection.getInputStream(),"UTF-8"));
			String temp = "";
			while ((temp = reader.readLine()) != null) {
				lines = lines + temp;
			}
			reader.close();
			// 断开连接
			connection.disconnect();
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return lines;
	}

	/**
	 * post提交
	 * @param url
	 * @param content
	 * @return
	 */
	public static String sendPostRequest(String url, String content) {
		String line = "";
		try {
//			content =URLEncoder.encode(content, "utf-8"); 
			// Post请求的url,与get不同的是不需要带参数
			URL postUrl = new URL(url);
			// 打开连接
			HttpURLConnection connection = (HttpURLConnection) postUrl
					.openConnection();
			// 打开读写属性,默认均为false
			connection.setDoOutput(true);
			connection.setDoInput(true);
			// 设置请求方式,默认为GET
			connection.setRequestMethod("POST");
			// Post 请求不能使用缓存
			connection.setUseCaches(false);
			//
			
		//	connection.setRequestProperty("Content-type","application/x-www-form-urlencoded");
			
			connection.setRequestProperty("Content-type","text/html");
			
			connection.setInstanceFollowRedirects(true);
//			connection.setRequestProperty(" Content-Type ",
//					" application/x-www-form-urlencoded ");
			DataOutputStream out = new DataOutputStream(
					connection.getOutputStream());
			
			out.write(content.toString().getBytes("utf-8"));  
//			out.writeBytes(content);
			out.flush();
			out.close(); // flush and close
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					connection.getInputStream()));
			System.out.println("read from server....");
			String tmp = "";
			while ((tmp = reader.readLine()) != null) {
				line = line + tmp;
			}
			reader.close();
			connection.disconnect();
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return line;
	}
	
	/**
	 * post提交
	 * @param url
	 * @param content
	 * @return
	 */
	public static String sendPostRequestUrlencoded(String url, String content) {
		String line = "";
		try {
//			content =URLEncoder.encode(content, "utf-8"); 
			// Post请求的url,与get不同的是不需要带参数
			URL postUrl = new URL(url);
			// 打开连接
			HttpURLConnection connection = (HttpURLConnection) postUrl
					.openConnection();
			// 打开读写属性,默认均为false
			connection.setDoOutput(true);
			connection.setDoInput(true);
			// 设置请求方式,默认为GET
			connection.setRequestMethod("POST");
			// Post 请求不能使用缓存
			connection.setUseCaches(false);
			//
			
			connection.setRequestProperty("Content-type","application/x-www-form-urlencoded");
			
		//	connection.setRequestProperty("Content-type","text/html");
			
			connection.setInstanceFollowRedirects(true);
//			connection.setRequestProperty(" Content-Type ",
//					" application/x-www-form-urlencoded ");
			DataOutputStream out = new DataOutputStream(
					connection.getOutputStream());
			
			out.write(content.toString().getBytes("utf-8"));  
//			out.writeBytes(content);
			out.flush();
			out.close(); // flush and close
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					connection.getInputStream()));
			System.out.println("read from server....");
			String tmp = "";
			while ((tmp = reader.readLine()) != null) {
				line = line + tmp;
			}
			reader.close();
			connection.disconnect();
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return line;
	}
	
	/**
	 * 	作用:使用证书,以post方式提交xml到对应的接口url
	 * second 超时时间
	 */
	public String postXmlSSLCurl(String url, String content,int second){
		String line = "";
		try {
//			content =URLEncoder.encode(content, "utf-8"); 
			// Post请求的url,与get不同的是不需要带参数
			URL postUrl = new URL(url);
			// 打开连接
			HttpURLConnection connection = (HttpURLConnection) postUrl
					.openConnection();
			// 打开读写属性,默认均为false
			connection.setDoOutput(true);
			connection.setDoInput(true);
			// 设置请求方式,默认为GET
			connection.setRequestMethod("POST");
			// Post 请求不能使用缓存
			connection.setUseCaches(false);
			//
			
			connection.setRequestProperty("Content-type","text/html");
			
			connection.setInstanceFollowRedirects(true);
//			connection.setRequestProperty(" Content-Type ",
//					" application/x-www-form-urlencoded ");
			DataOutputStream out = new DataOutputStream(
					connection.getOutputStream());
			
			out.write(content.toString().getBytes("utf-8"));  
//			out.writeBytes(content);
			out.flush();
			out.close(); // flush and close
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					connection.getInputStream()));
			System.out.println("read from server....");
			String tmp = "";
			while ((tmp = reader.readLine()) != null) {
				line = line + tmp;
			}
			reader.close();
			connection.disconnect();
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return line;
	}
}

字符处理等工具类

/**
 * 
 * @Title: 转型、判空、格式化操作
 * @Description:
 * @Author:fengjianshe
 * @Since:2013年8月26日
 * @Version:1.1.0
 */
public class StringUtil {

	private static Map<String, Object> dataMap = new HashMap<String, Object>();

	public static void initMap(Map<String, Object> paramMap) {
		dataMap = paramMap;
	}

	/**
	 * 判断是否为空
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isNullOrEmpty(Object obj) {

		if (null == obj || "".equals(obj.toString().trim())
				|| obj.toString().toUpperCase().equals("NULL")) {
			return true;
		}
		return false;

	}

	public static String getPercent(double d) {

		return getDouble1(d * 100) + "%";
	}

	public static byte getByte(Object obj) {
		int i = getInt(obj);
		if (-128 < i && i < 127) {
			return (byte) i;
		}
		return (byte) 0;
	}

	/**
	 * 获取整数
	 * 
	 * @param obj
	 * @return
	 */
	public static float getFloat(Object obj) {

		if (null == obj || "".equals(obj.toString().trim())
				|| obj.toString().toUpperCase().equals("NULL")) {
			return 0;
		}
		try {
			return ((int) (Float.valueOf(obj.toString()) * 100)) / (float) 100;
		} catch (Exception e) {
			return 0;
		}
	}

	/**
	 * 获取整数
	 * 
	 * @param obj
	 * @return
	 */
	public static float getFloatM(Object obj) {

		if (null == obj || "".equals(obj.toString().trim())
				|| obj.toString().toUpperCase().equals("NULL")) {
			return 0;
		}
		try {
			if (dataMap == null) {
				throw new NullPointerException("dataMap is null");
			}
			return getFloat(dataMap.get(obj));
		} catch (Exception e) {
			return 0;
		}
	}

	/**
	 * 获取浮点数: 例子: 104 / 0.7 普通计算结果为:72.7995898 ,而通过本方法处理后会得出精确的值:72.8
	 * 
	 * @param f
	 * @return
	 */
	public static float getFloat2(float f) {

		return new Float(new DecimalFormat("#.##").format(f)).floatValue();

	}

	/**
	 * 获取浮点数: 例子: 104 / 0.7 普通计算结果为:72.7495898 ,而通过本方法处理后会得出精确的值:72.8
	 * 
	 * @param f
	 * @return
	 */
	public static float getFloat1(float f) {

		return new Float(new DecimalFormat("#.#").format(f)).floatValue();

	}

	public static double getDouble1(Object obj) {

		if (obj != null && obj.toString().trim() != ""
				&& obj.toString().trim().toUpperCase() != "NULL") {
			return getDouble(Double.valueOf(obj.toString()));
		} else {
			return 0.0;
		}
	}

	/**
	 * 获取Double
	 * 
	 * @param obj
	 * @return
	 */
	public static double getDoubleM(Object obj) {

		if (obj != null && obj.toString().trim() != ""
				&& obj.toString().trim().toUpperCase() != "NULL") {
			try {
				if (dataMap == null) {
					throw new NullPointerException("dataMap is null");
				}
				return getDouble1(dataMap.get(obj));
			} catch (Exception e) {
				return 0;
			}
		} else {
			return 0.0;
		}
	}

	/**
	 * 获取浮点数: 例子: 104 / 0.7 普通计算结果为:72.7495898 ,而通过本方法处理后会得出精确的值:72.8
	 * 
	 * @param f
	 * @return
	 */
	public static double getDouble(double f) {

		return (new Double(new DecimalFormat("#.##").format(f))).doubleValue();

	}

	/**
	 * 获取整数
	 * 
	 * @param obj
	 * @return
	 */
	public static int getInt(Object obj) {

		if (null == obj || "".equals(obj.toString().trim())
				|| obj.toString().toUpperCase().equals("NULL")) {
			return 0;
		}
		try {
			Double d = new Double(obj.toString());
			return d.intValue();
		} catch (Exception e) {
			return 0;
		}
	}

	/**
	 * 获取整数
	 * 
	 * @param obj
	 * @return
	 */
	public static int getIntM(Object obj) {

		if (null == obj || "".equals(obj.toString().trim())
				|| obj.toString().toUpperCase().equals("NULL")) {
			return 0;
		}
		try {
			if (dataMap == null) {
				throw new NullPointerException("dataMap is null");
			}
			return getInt(dataMap.get(obj));
		} catch (Exception e) {
			return 0;
		}
	}

	/**
	 * 获取整数
	 * 
	 * @param obj
	 * @return
	 */
	public static boolean getBoolean(Object obj) {
		if (null == obj || "".equals(obj.toString().trim())
				|| obj.toString().toUpperCase().equals("NULL")) {
			return false;
		}
		try {
			if (getInt(obj) == 1 || obj.toString().equalsIgnoreCase("true")) {
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 获取整数
	 * 
	 * @param obj
	 * @return
	 */
	public static boolean getBooleanM(Object obj) {
		if (null == obj || "".equals(obj.toString().trim())
				|| obj.toString().toUpperCase().equals("NULL")) {
			return false;
		}
		try {
			if (dataMap == null) {
				throw new NullPointerException("dataMap is null");
			}
			return getBoolean(dataMap.get(obj));
		} catch (Exception e) {
			return false;
		}
	}

	/**
	 * 获取字符串
	 * 
	 * @param obj
	 * @return
	 */
	public static String getString(Object obj) {
		if (null == obj || "".equals(obj.toString().trim())
				|| obj.toString().toUpperCase().equals("NULL")) {
			return "";
		}
		try {
			return obj.toString().trim();
		} catch (Exception e) {
			return "";
		}
	}

	/**
	 * 获取长整数
	 * 
	 * @param obj
	 * @return
	 */
	public static long getLong(Object obj) {

		if (null == obj || "".equals(obj.toString().trim())
				|| obj.toString().toUpperCase().equals("NULL")) {
			return 0;
		}
		try {
			return Long.valueOf(obj.toString());
		} catch (Exception e) {
			return 0;
		}
	}

	/**
	 * 获取字符串
	 * 
	 * @param obj
	 * @return
	 */
	public static String getStringM(Object obj) {
		if (null == obj || "".equals(obj.toString().trim())
				|| obj.toString().toUpperCase().equals("NULL")) {
			return "";
		}
		try {
			if (dataMap == null) {
				throw new NullPointerException("dataMap is null");
			}
			return getString(dataMap.get(obj));
		} catch (Exception e) {
			return "";
		}
	}

	/**
	 * 获取utf8编码字符串
	 * 
	 * @param s
	 * @return
	 */
	public static String toUtf8String(String s) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < s.length(); i++) {
			char c = s.charAt(i);
			if (c >= 0 && c <= 255) {
				sb.append(c);
			} else {
				byte[] b;
				try {
					b = Character.toString(c).getBytes("utf-8");
				} catch (Exception ex) {
					b = new byte[0];
				}
				for (int j = 0; j < b.length; j++) {
					int k = b[j];
					if (k < 0)
						k += 256;
					sb.append("%" + Integer.toHexString(k).toUpperCase());
				}
			}
		}
		return sb.toString();
	}

	/**
	 * Utf8URL解码
	 * 
	 * @param text
	 * @return
	 */
	public static String Utf8URLdecode(String text) {
		String result = "";
		int p = 0;
		if (text != null && text.length() > 0) {
			text = text.toLowerCase();
			p = text.indexOf("%e");
			if (p == -1)
				return text;
			while (p != -1) {
				result += text.substring(0, p);
				text = text.substring(p, text.length());
				if (text == "" || text.length() < 9)
					return result;
				result += CodeToWord(text.substring(0, 9));
				text = text.substring(9, text.length());
				p = text.indexOf("%e");
			}
		}
		return result + text;
	}

	/**
	 * 编码是否有效
	 * 
	 * @param text
	 * @return
	 */
	private static boolean Utf8codeCheck(String text) {
		String sign = "";
		if (text.startsWith("%e"))
			for (int i = 0, p = 0; p != -1; i++) {
				p = text.indexOf("%", p);
				if (p != -1)
					p++;
				sign += p;
			}
		return sign.equals("147-1");
	}

	/**
	 * 是否Utf8Url编码
	 * 
	 * @param text
	 * @return
	 */
	public boolean isUtf8Url(String text) {
		text = text.toLowerCase();
		int p = text.indexOf("%");
		if (p != -1 && text.length() - p > 9) {
			text = text.substring(p, p + 9);
		}
		return Utf8codeCheck(text);
	}

	/**
	 * utf8URL编码转字符
	 * 
	 * @param text
	 * @return
	 */
	private static String CodeToWord(String text) {
		String result;
		if (Utf8codeCheck(text)) {
			byte[] code = new byte[3];
			code[0] = (byte) (Integer.parseInt(text.substring(1, 3), 16) - 256);
			code[1] = (byte) (Integer.parseInt(text.substring(4, 6), 16) - 256);
			code[2] = (byte) (Integer.parseInt(text.substring(7, 9), 16) - 256);
			try {
				result = new String(code, "UTF-8");
			} catch (UnsupportedEncodingException ex) {
				result = null;
			}
		} else {
			result = text;
		}
		return result;
	}

	public static String format(String message, Object[] words) {
		if (words != null && words.length > 0 && message instanceof String) {
			message = MessageFormat.format((String) message, words);
		}
		return message;
	}

	/**
	 * servlet
	 * 
	 * @param str
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String toStringUTF8(String str)
			throws UnsupportedEncodingException {
		return new String(str.getBytes("ISO-8859-1"), "UTF-8");
	}

	/**
	 * 时间格式转换 <> 取得当前系统时间
	 * 
	 * @param date
	 * @return
	 */
	public static String dateToString(Date date) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String str = sdf.format(date);
		return str;
	}


	/**
	 * 判断是否是手机号码
	 * 
	 * @param mobile
	 * @return
	 * @Description:
	 */
	public static boolean isMobileNo(String mobile) {
		boolean isTrue = false;
		Pattern p = Pattern
				.compile("^((13[0-9])|(15[^4,\\D])|(17[6-8])|(18[0-9]))\\d{8}$");
		Matcher m = p.matcher(mobile);
		isTrue = m.matches();
		return isTrue;
	}

	/**
	 * 截取后几位的字符串
	 * 
	 * @param str
	 * @param lenth
	 * @return
	 * @Description:
	 */
	public static String cutBehindStr(String str, int lenth) {
		return str.substring(str.length() - lenth);
	}

	/**
	 * 生成指定位数数字随机数
	 * 
	 * @return
	 * @Description:
	 */
	public static String getRandomDigitStr(int count) {
		Random rd = new Random();
		String n = "";
		int getNum;
		do {
			getNum = Math.abs(rd.nextInt()) % 10 + 48;// 产生数字0-9的随机数
			// getNum = Math.abs(rd.nextInt())%26 + 97;//产生字母a-z的随机数
			char num1 = (char) getNum;
			String dn = Character.toString(num1);
			n += dn;
		} while (n.length() < count);
		return n;
	}

	/**
	 * (单位:米)转算成经纬度 纬度1度 = 大约111km 纬度1分 = 大约1.85km 纬度1秒 = 大约30.9m 经度xpoint =
	 * 116.34(单位:°) 纬度ypoint = 24.52(单位:°)
	 * 
	 * @return
	 * @Description:
	 */
	public static double ConvertXYpoint(Object obj) {
		if (null == obj || "".equals(obj.toString().trim())
				|| obj.toString().toUpperCase().equals("NULL")) {

			return 0;

		} else {
			Double d = new Double(obj.toString());
			return d / 111 / 1000;
		}

	}
	
	/** 
	  * 判断文件是否为图片<br> 
	  * <br> 
	  * @param pInput 文件名<br> 
	  * @param pImgeFlag 判断具体文件类型<br> 
	  * @return 检查后的结果<br> 
	  * @throws Exception 
	  */ 
	public static boolean isPicture(String  pInput) throws Exception{ 
	  // 文件名称为空的场合 
	  if(isNullOrEmpty(pInput)){ 
	   // 返回不和合法 
	   return false; 
	  } 
	  // 获得文件后缀名 
	  String tmpName = pInput.substring(pInput.lastIndexOf(".") + 1, 
	                              pInput.length()); 
	  // 声明图片后缀名数组 
	  String imgeArray [] = {"bmp","gif","jpe","jpg","jpeg","png"};
	  
	  for (int i = 0; i < imgeArray.length; i++) {
		if(tmpName.equals(imgeArray[i])){
			return true;
		}
	  }
	  
	  return false; 
	} 
	
	

	public static String removeBlankAndEnter(String content) {
		String dest = "";
		if (content != null) {
			Pattern p = Pattern.compile("\\s*|\t|\r|\n");
			Matcher m = p.matcher(content);
			dest = m.replaceAll("");
		}
		return dest;
	}
	
	public static String sub(String str,int bi,int ei) {
		
		
		
		return str.substring(bi, ei);
	}
	
	/**
     * 验证邮箱
     * @param email
     * @return
     */
    public static boolean checkEmail(String email){
        boolean flag = false;
        try{
                String check = "^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
                Pattern regex = Pattern.compile(check);
                Matcher matcher = regex.matcher(email);
                flag = matcher.matches();
            }catch(Exception e){
                flag = false;
            }
        return flag;
    }
    
    /**
     * 验证邮箱
     * @param email
     * @return
     */
    public static boolean checkAccount(String account){
        boolean flag = false;
        try{
                String check = "^[A-Za-z0-9]{6,20}$";
                Pattern regex = Pattern.compile(check);
                Matcher matcher = regex.matcher(account);
                flag = matcher.matches();
            }catch(Exception e){
                flag = false;
            }
        return flag;
    }
    
	
}

MD5 工具类 (这里我修改了一下,为了支持body中文,MD5做了编码)

public class MD5Util {
	 
	private static String byteArrayToHexString(byte b[]) {
		StringBuffer resultSb = new StringBuffer();
		for (int i = 0; i < b.length; i++)
			resultSb.append(byteToHexString(b[i]));
 
		return resultSb.toString();
	}
 
	private static String byteToHexString(byte b) {
		int n = b;
		if (n < 0)
			n += 256;
		int d1 = n / 16;
		int d2 = n % 16;
		return hexDigits[d1] + hexDigits[d2];
	}
 
	public static String MD5Encode(String origin, String charsetname) {
		String resultString = null;
		try {
			resultString = new String(origin);
			MessageDigest md = MessageDigest.getInstance("MD5");
			if (charsetname == null || "".equals(charsetname))
				resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
			else
				resultString = byteArrayToHexString(md.digest(resultString
						.getBytes(charsetname)));
		} catch (Exception exception) {
		}
		return resultString;
	}
 
	private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
			"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
 
}

订单生成

public class OrderUtil {
	
	
	private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");

    /**
     * 生成订单号
     *
     * @param pre 订单号前缀
     * @return
     */
    public static String gens(String pre) {
        //生成
        String orderNo = pre + sdf.format(new Date()) + (1 + (int) (Math.random() * 10000));
        return orderNo;
    }
	
}

Token获取

public class Token {
	
    /**
     * 获取Token
     * @param appid
     * @param secret
     * @return
     */
	public static Map getAccessTokenMap(String appid,String secret){
		String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appid+"&secret="+secret;
			String x = "";
			try {
				x = HttpInvoker.sendGetRequest(url);
			} catch (Exception e) {
				e.printStackTrace();
			}
			Map<String, Object> toMap = WeixinUtil.jsonStrToMap(x);
			return toMap;
			/*Map map = JSON.parseObject(x, HashMap.class);
			return map;*/
			}
	
	/**
	 * 刷新Token
	 */
	public void updataAccessToken() {
	   		 String appid= "";
	   		 String secret="";
	   		 Map tokenMap = Token.getAccessTokenMap(appid, secret);
	   		 String accessToken = tokenMap.get("access_token").toString();
	   		 int ex_time = 7200;
	        }
    
}

openId获取

/**
	 * 获取微信openId
	 * @param code 微信登录授权code
	 * @return
	 */
	public static String getOpenId(String code){
		String openId="";
		//请求api获取openid
		String str = HttpInvoker.sendGetRequest(StringUtil.format(WxPayConfig.GET_OPENID, new Object[]{WxPayConfig.APPID,WxPayConfig.APPSECRET,code}));
		//将json转map
		Map<String, Object> toMap = WeixinUtil.jsonStrToMap(str);
		if(!StringUtil.isNullOrEmpty(toMap.get("openid"))){//获取openid成功
			openId=(String) toMap.get("openid");
		}
		return openId;
	}

微信相关工具类

/**
 * 微信相关工具类
 * ClassName:WeixinUtil 
 * Date:     2017年10月24日 下午2:05:05 
 * @author   sqq 
 * @since    JDK 1.8 
 */
public class WeixinUtil {
	
	/** = */
	public static final String QSTRING_EQUAL = "=";

	/** & */
	public static final String QSTRING_SPLIT = "&";
	
	/**
	 * 	作用:产生随机字符串,不长于32位
	 */
	public static String createNoncestr(int length){
		
		String chars = "abcdefghijklmnopqrstuvwxyz0123456789";  
		String str ="";
		Random rand = new Random();
		for (int i = 0; i < length; i++) {
			int index = rand.nextInt(chars.length());
			str += chars.substring(index, index + 1);
		} 
		return str;
	}
		
	/**
	 * 	把请求要素按照“参数=参数值”的模式用“&”字符拼接成字符串
     * @param para 请求要素
     * @param sort 是否需要根据key值作升序排列
     * @param encode 是否需要URL编码
     * @return 拼接成的字符串
	 */
	public static String formatBizQueryParaMap(Map<String,String> para,boolean sort, boolean encode)
	{
		List<String> keys = new ArrayList<String>(para.keySet());
        
        if (sort)
        	Collections.sort(keys);

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = para.get(key);
            
            if (encode) {
				try {
					value = URLEncoder.encode(value, WxPayConfig.ENCODE);
				} catch (UnsupportedEncodingException e) {
				}
            }
            
            if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符
                sb.append(key).append(QSTRING_EQUAL).append(value);
            } else {
                sb.append(key).append(QSTRING_EQUAL).append(value).append(QSTRING_SPLIT);
            }
        }
        return sb.toString();
	}
	
	/**
	 * 	作用:生成签名
	 */
	public static String getSign(Map<String,String> paramMap)
	{
	//	System.out.println("------------------bef-----------");
		for (String key : paramMap.keySet()) {//
	//		System.out.println("-------------------------:" + key);
			//值为空不参加签名
			if(StringUtil.isNullOrEmpty(paramMap.get(key))){
	//			System.out.println("-------------------------1:" + key);
				paramMap.remove(key);
				
			}
		}
		String params = formatBizQueryParaMap(paramMap, true, false);
		//echo '【string1】'.$String.'</br>';
		//签名步骤二:在string后加入KEY
		params = params + "&key=" + WxPayConfig.KEY;//
		//echo "【string2】".$String."</br>";
		//签名步骤三:MD5加密并转大写
		params = MD5Util.MD5Encode(params,"utf-8");
		//echo "【string3】 ".$String."</br>";
		//签名步骤四:所有字符转为大写
		//echo "【result】 ".$result_."</br>";
		return params;
	}
	
	/**
	 * 	作用:map转xml
	 */
	public static String arrayToXml(Map<String,String> paramMap){
        String xml = "<xml>";
        for (String key : paramMap.keySet()) {//
			//值是否只有字母和数字
			if(paramMap.get(key).matches("^[\\da-zA-Z]*$")){
				xml += "<" + key + ">" + paramMap.get(key) + "</" + key + ">"; 
			}else{
				xml += "<" + key + "><![CDATA[" + paramMap.get(key) + "]]></" + key + ">";
			}
		}
        xml += "</xml>";
        return xml;
    }
	
	/**
	 * xml 转  map
	 * @param xml
	 * @return
	 */
	public static Map<String,String> xmltoMap(String xml) {  
        try {  
            Map<String,String> map = new HashMap<String,String>();  
            Document document = DocumentHelper.parseText(xml);  
            Element nodeElement = document.getRootElement();  
            List node = nodeElement.elements();  
            for (Iterator it = node.iterator(); it.hasNext();) {
                Element elm = (Element) it.next();  
                String val = elm.getText();
                val = val.replace("<![CDATA[", "");
                val = val.replace("]]>", "");
                map.put(elm.getName(), val);  
                elm = null;  
            }  
            node = null;
            nodeElement = null;  
            document = null;  
            return map;  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return null;  
    }
	
	/**
	 * jsonStrToMap:(json转map). 
	 * @author sqq
	 * @param jsonStr
	 * @return
	 * @since JDK 1.8
	 */
	public static Map<String, Object> jsonStrToMap(String jsonStr){  
        Map<String, Object> map = new HashMap<String, Object>();  
        //最外层解析  
        JSONObject json = JSONObject.fromObject(jsonStr); 
        for(Object k : json.keySet()){  
              Object v = json.get(k);   
              //如果内层还是数组的话,继续解析  
              if(v instanceof JSONArray){  
                    List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();  
                    Iterator<JSONObject> it = ((JSONArray)v).iterator();  
                    while(it.hasNext()){  
                      JSONObject json2 = it.next();  
                      list.add(jsonStrToMap(json2.toString()));  
                    }  
                    map.put(k.toString(), list);  
              } else {  
                  map.put(k.toString(), v);  
              }  
        }
        return map;  
    }
	/**
	 * 获取ip地址
	 * getRemoteHost
	 * @author sqq
	 * @param request
	 * @return
	 * @since JDK 1.8
	 */
	public static String getRemoteHost(javax.servlet.http.HttpServletRequest request){
	    String ip = request.getHeader("x-forwarded-for");
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
	        ip = request.getHeader("Proxy-Client-IP");
	    }
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
	        ip = request.getHeader("WL-Proxy-Client-IP");
	    }
	    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
	        ip = request.getRemoteAddr();
	    }
	    return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;
	}
	
	/** 
	 * 获取精确到秒的时间戳 
	 * @param date 
	 * @return 
	 */  
	public static int getTimestamp(Date date){  
	    if (null == date) {  
	        return 0;  
	    }  
	    String timestamp = String.valueOf(date.getTime()/1000);  
	    return Integer.valueOf(timestamp);  
	}
	
	
	
	/**
	 * 授权统一路径拼凑
	 * @param dqurl 当前访问的路径
	 * @param str 路径返回的参数
	 * @return
	 * @throws Exception
	 */
	public String doWeixinRedirectUrl(HttpServletRequest request) throws Exception{
		//特别注意:params分享会出现code过期参数  应去掉后作为回调地址
	//	String server_url_name = PropertiesUtil.getValue("SERVER_URL_NAME");//服务器地址
		String returl = request.getScheme()+"://"+ request.getServerName() + request.getRequestURI(); 
		Map<String,String[]> paramMap = request.getParameterMap();
		String params = "";
		int next = 0;
		//过滤code、state
		for (String key : paramMap.keySet()) {
			String[] strs = paramMap.get(key);
			if(!key.equals("code") && !key.equals("state")){
				if(next == 0){
					params += "?";
				}else{
					params += "&";
				}
				params += key + "=" + strs[0];
				next ++;
			}
			
		}
		System.out.println("params:" + params);
		String dqurl = returl + params;
		
		dqurl = URLEncoder.encode(dqurl, "utf-8");
		String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+ WxPayConfig.APPID +"&redirect_uri="+ dqurl +"&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect";
		return url;
	}