package com.code.web; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.math.BigDecimal; import java.net.HttpURLConnection; import java.net.URL; import java.security.KeyStore; import java.security.MessageDigest; import java.text.MessageFormat; import java.util.Arrays; import java.util.Collection; import java.util.Formatter; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.SortedMap; import java.util.TreeMap; import java.util.UUID; import javax.net.ssl.SSLContext; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.SSLContexts; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.SAXReader; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; /** * 微信开发工具类 * @author LGF * */ public class WeixinHanlder { //微信配置信息 public static Properties wxConfig; //token,ticket常量 public static String ACCESS_TOKEN = "access_token"; public static String TICKET = "ticket"; //---------------------------------------------------- //调试,日志输出 public static boolean ISDEBUG = true; //刷新token时间 public static Integer CHANGE_TOKEN_TIME = 1000*60*60*2; //公众号开发token public static String TOKEN = ""; //公众号APPID public static String APPID = ""; //公众号商户编号 public static String MCHID = ""; //公众号开发秘钥 public static String APPSECRET = ""; //商户平台 APPID public static String APP_PAY_APPID = ""; //商户平台 编号 public static String APP_MCHID = ""; //支付秘钥 public static String API_KEY = ""; //---------------------------------------------------- //获取用户信息 public static String URL_UNIONID_USER_INFO = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={0}&openid={1}"; //获取token public static String URL_ACCESS_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}"; //获取jsticket public static String URL_JS_TICKET = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi"; //授权获取openid public static String URL_BASE_GRANT_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx3d2a8457f10f2f63&redirect_uri={0}&response_type=code&scope=snsapi_base&state={1}#wechat_redirect"; //微信下单地址 public static String URL_UNIFIEDORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder"; //获取外部token,jsticket public static String URL_OTHER_TOKEN_JSTICKET = ""; //微信支付成功回调地址 public static String URL_NOTIFY_URL = ""; //加载配置文件 static{ wxConfig = new Properties(); try { wxConfig.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("weixin.properties")); APPID = wxConfig.get("app_id").toString(); MCHID = wxConfig.get("mch_id").toString(); APPSECRET = wxConfig.get("app_secret").toString(); TOKEN = wxConfig.get("token").toString(); } catch (IOException e) { e.printStackTrace(); } } /** * 检查是否是微信发送的请求 * @param signature 签名 * @param timestamp 时间戳 * @param nonce 随机数 * @return * @throws Exception */ public static boolean checkSgin(String signature,String timestamp,String nonce) throws Exception{ String[] strs = new String[]{timestamp,nonce,TOKEN}; Arrays.sort(strs); StringBuffer sb = new StringBuffer(); for (String string : strs) { sb.append(string); } String sha1 = SecurityHanlder.sha1(sb.toString()); if(sha1.equals(signature)){ return true; } return false; } /** * 获取用户信息 * 获取用户基本信息(包括UnionID机制) * 开发者可通过OpenID来获取用户基本信息。请使用https协议。 * @param req * @param openid * @return */ //{ // "subscribe": 1, // "openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", // "nickname": "Band", // "sex": 1, // "language": "zh_CN", // "city": "广州", // "province": "广东", // "country": "中国", // "headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0", // "subscribe_time": 1382694957, // "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL" // "remark": "", // "groupid": 0 //} @SuppressWarnings("unchecked") public static Map<String,String> getUserInfoByUnionId(HttpServletRequest req,String openid){ if(openid==null||openid.isEmpty()){ return null; } String accessToken = getToken(req); try { String json = URLHanlder.post(MessageFormat.format(URL_UNIONID_USER_INFO, accessToken,openid)); return JSON.parseObject(json, Map.class); } catch (IOException e) { e.printStackTrace(); return null; } } /** * 从外部获取token * @return */ @SuppressWarnings("unchecked") public static String getToken(HttpServletRequest req){ String accessToken = null; if(req==null){ try { String json = URLHanlder.post(URL_OTHER_TOKEN_JSTICKET); Map<String,String> map = JSON.parseObject(json, Map.class); accessToken = map.get(ACCESS_TOKEN); } catch (IOException e) { e.printStackTrace(); } }else{ Object temp = req.getSession().getServletContext().getAttribute(ACCESS_TOKEN); accessToken = temp==null?null:temp.toString(); } return accessToken==null?"":accessToken; } /** * 从外部获取Ticket * @return */ @SuppressWarnings("unchecked") public static String getTicket(HttpServletRequest req){ String ticket = null; if(req==null){ try { String json = URLHanlder.post(URL_OTHER_TOKEN_JSTICKET); Map<String,String> map = JSON.parseObject(json, Map.class); ticket = map.get(TICKET); } catch (IOException e) { e.printStackTrace(); } }else{ Object temp = req.getSession().getServletContext().getAttribute(TICKET); ticket = temp==null?null:temp.toString(); } return ticket==null?"":ticket; } //日志打印 public static void log(Object obj){ if(ISDEBUG){ System.out.println(obj); } } /** * 创建支付签名 * @param map * @return * @throws Exception */ public static String createSign(Map<String, String> map) throws Exception { StringBuffer sb = new StringBuffer(); Iterator<String> it = map.keySet().iterator(); while (it.hasNext()) { String k = it.next(); String v = map.get(k); if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k).append("=").append(v).append("&"); } } sb.append("key=").append(API_KEY); String sign = SecurityHanlder.md5(sb.toString()).toUpperCase(); return sign; } /** * 微信支付 * @param body * 商品信息 * @param orderid * 唯一订单号 * @param money * 价格 * @param ip * ip地址 * @param openid * 下单openid * @param notify_url * 异步通知地址 * @return */ public static Map<String, String> pay(String body,String orderid,BigDecimal money,String ip,String openid,String notify_url,String type) { Map<String, String> returnMap = null; try { //返回预支付信息 SortedMap<String, String> resultMap = new TreeMap<String, String>(); // 构造下单所需要的参数 SortedMap<String, String> map = new TreeMap<String, String>(); // 公众账号id map.put("appid", APPID); // 微信支付分配的商户号 map.put("mch_id", MCHID); //使用js api if(type==null){ map.put("trade_type", "JSAPI"); }else{ map.put("trade_type", type); } //随机字符串 map.put("nonce_str", create_nonce_str().replaceAll("-","")); // 商品描述 map.put("body", body); // 商户订单号 map.put("out_trade_no",orderid); // 总金额,单位是分 map.put("total_fee",String.valueOf(((int)(money.doubleValue()*100)))); //客户端ip map.put("spbill_create_ip",ip); // 异步通知地址 if(notify_url==null||notify_url.isEmpty()){ map.put("notify_url", URL_NOTIFY_URL); }else{ map.put("notify_url", notify_url); } // 用户openid if(openid!=null&&!openid.trim().isEmpty()){ map.put("openid", openid); } // 生成sign map.put("sign",createSign(map)); // 把参数转换为xml数据 String params = XML.toXML(map); log("\n=================== 提交预支付订单 params: \n"); log(params); // 提交数据,执行预支付 returnMap = XML.toMap(URLHanlder.post(URL_UNIFIEDORDER,params)); log("\n=================== 返回预支付订单信息 returnMap: \n"+returnMap); if ("success".equalsIgnoreCase(returnMap.get("return_code")) && "success".equalsIgnoreCase(returnMap.get("result_code"))) { // 获取返回的预支付ID String prepay_id = returnMap.get("prepay_id"); resultMap.put("appId", returnMap.get("appid")); resultMap.put("nonceStr", map.get("nonce_str")); resultMap.put("timeStamp", String.valueOf(System.currentTimeMillis())); resultMap.put("package", "prepay_id=" + prepay_id); resultMap.put("signType", "MD5"); // 第二次签名加密 String paySign = WeixinHanlder.createSign(resultMap); resultMap.put("paySign", paySign); resultMap.put("openid",openid); resultMap.put("packagestr", "prepay_id=" + prepay_id); resultMap.remove("package"); /* JS API支付所需参数 WeixinJSBridge.invoke('getBrandWCPayRequest', { "appId": w.appId, "timeStamp": w.timeStamp, "nonceStr": w.nonceStr, "package": w.packagestr, "signType": w.signType, "paySign": w.paySign } */ log("=================== 加密支付信息,返回微信端 resultMap: \n"+resultMap+"\n"); return resultMap; } }catch(Exception e){ e.printStackTrace(); } Map<String, String> m = new HashMap<String, String>(); m.put("error",returnMap.get("return_msg")); m.put("err_code_des",returnMap.get("err_code_des")); return m; } /** * APP支付参数获取 * @param body * @param orderid * @param money * @param ip * @param notify_url * @param type * @return */ public static Map<String, String> appPay(String body,String orderid,BigDecimal money,String ip,String notify_url,String type) { Map<String, String> returnMap = null; try { //返回预支付信息 SortedMap<String, String> resultMap = new TreeMap<String, String>(); // 构造下单所需要的参数 SortedMap<String, String> map = new TreeMap<String, String>(); map.put("appid", APP_PAY_APPID); // 微信支付分配的商户号 map.put("mch_id", APP_MCHID); map.put("trade_type", type); //随机字符串 map.put("nonce_str", create_nonce_str().replaceAll("-","")); // 商品描述 map.put("body", body); // 商户订单号 map.put("out_trade_no",orderid); // 总金额,单位是分 map.put("total_fee",String.valueOf(((int)(money.doubleValue()*100)))); //客户端ip map.put("spbill_create_ip",ip); // 异步通知地址 if(notify_url==null||notify_url.isEmpty()){ map.put("notify_url", URL_NOTIFY_URL); }else{ map.put("notify_url", notify_url); } // 生成sign map.put("sign",createSign(map)); // 把参数转换为xml数据 String params = XML.toXML(map); log("\n=================== APP提交预支付订单 params: \n"); log(params); // 提交数据,执行预支付 returnMap = XML.toMap(URLHanlder.post(URL_UNIFIEDORDER,params)); log("\n=================== APP返回预支付订单信息 returnMap: \n"+returnMap); if ("success".equalsIgnoreCase(returnMap.get("return_code")) && "success".equalsIgnoreCase(returnMap.get("result_code"))) { // 获取返回的预支付ID String prepay_id = returnMap.get("prepay_id"); resultMap.put("appid",APP_PAY_APPID); resultMap.put("partnerid",returnMap.get("mch_id")); resultMap.put("prepayid",prepay_id); resultMap.put("noncestr", map.get("nonce_str")); resultMap.put("timestamp", String.valueOf(System.currentTimeMillis()/1000)); resultMap.put("package", "Sign=WXPay"); // 第二次签名加密 String paySign = WeixinHanlder.createSign(resultMap); resultMap.put("sign", paySign); log("=================== APP加密支付信息,返回微信端 resultMap: \n"+resultMap+"\n"); return resultMap; } }catch(Exception e){ e.printStackTrace(); } Map<String, String> m = new HashMap<String, String>(); m.put("error",returnMap.get("return_msg")); m.put("err_code_des",returnMap.get("err_code_des")); return m; } /* 1、交易时间超过一年的订单无法提交退款; 2、微信支付退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。 一笔退款失败后重新提交,要采用原来的退款单号。总退款金额不能超过用户实际支付金额。 接口链接:https://api.mch.weixin.qq.com/secapi/pay/refund <xml> <appid>wx2421b1c4370ec43b</appid> <mch_id>10000100</mch_id> <nonce_str>6cefdb308e1e2e8aabd48cf79e546a02</nonce_str> <op_user_id>10000100</op_user_id> <out_refund_no>1415701182</out_refund_no> <out_trade_no>1415757673</out_trade_no> <refund_fee>1</refund_fee> <total_fee>1</total_fee> <transaction_id></transaction_id> <sign>FE56DD4AA85C0EECA82C35595A69E153</sign> </xml> */ public static Map<String,String> returnedorder(String orderid,String returnedno,BigDecimal money,BigDecimal returnedmoney) throws Exception{ //创建xml请求数据 SortedMap<String, String> map = new TreeMap<String, String>(); map.put("appid", APPID); map.put("mch_id", MCHID); map.put("nonce_str", create_nonce_str()); map.put("out_trade_no", orderid); map.put("out_refund_no", returnedno); map.put("total_fee", String.valueOf( (int)(money.doubleValue()*100))); map.put("refund_fee", String.valueOf( (int)(returnedmoney.doubleValue()*100))); map.put("op_user_id", MCHID); map.put("sign", createSign(map)); String params = XML.toXML(map); HttpPost post = null; CloseableHttpResponse response = null; CloseableHttpClient httpclient = null; Map<String,String> returnmap = null; try { //加载证书 KeyStore keyStore = KeyStore.getInstance("PKCS12"); InputStream instream = Thread.currentThread().getContextClassLoader().getResourceAsStream("apiclient_cert.p12"); keyStore.load(instream, MCHID.toCharArray()); SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore,MCHID.toCharArray()).build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); //发送请求 post = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund"); StringEntity es = new StringEntity(params); post.setEntity(es); response = httpclient.execute(post); HttpEntity e = response.getEntity(); if (e != null) { //获取微信返回数据 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(e.getContent(), "UTF-8")); StringBuffer sb = new StringBuffer(); String text = ""; while ((text = bufferedReader.readLine()) != null) { sb.append(text); } //转换成 map 对象 String result = sb.toString(); returnmap = XML.toMap(result); //退款成功 //result_code=SUCCESS, return_code=SUCCESS if ("SUCCESS".equalsIgnoreCase(returnmap.get("result_code"))&&"SUCCESS".equalsIgnoreCase(returnmap.get("return_code"))) { log(returnmap); return returnmap; }else{ log(returnmap); } } EntityUtils.consume(e); } catch (Exception e) { e.printStackTrace(); log(returnmap); }finally{ try {response.close();} catch (IOException e) {} try {httpclient.close();} catch (IOException e) {} } return null; } /* * 微信查询订单 * https://api.mch.weixin.qq.com/pay/orderquery * * <xml> * <appid>wx2421b1c4370ec43b</appid> * <mch_id>10000100</mch_id> * <nonce_str>ec2316275641faa3aacf3cc599e8730f</nonce_str> * <transaction_id>1008450740201411110005820873</transaction_id> * <sign>FDD167FAA73459FD921B144BAF4F4CA2</sign> * </xml> * * */ public static Map<String,String> orderquery(String orderid) throws Exception{ SortedMap<String, String> map = new TreeMap<String, String>(); // 公众账号id map.put("appid", APPID); // 微信支付分配的商户号 map.put("mch_id", MCHID); //随机字符串 map.put("nonce_str", create_nonce_str().replaceAll("-","")); map.put("transaction_id", orderid); map.put("sign",createSign(map)); String params = XML.toXML(map); Map<String,String> returnmap = XML.toMap(URLHanlder.post("https://api.mch.weixin.qq.com/pay/orderquery",params)); if ("success".equalsIgnoreCase(returnmap.get("return_code"))) { return returnmap; }else{ log(returnmap); } return null; } // <xml> // <appid>wx2421b1c4370ec43b</appid> // <mch_id>10000100</mch_id> // <nonce_str>0b9f35f484df17a732e537c37708d1d0</nonce_str> // <out_refund_no></out_refund_no> // <out_trade_no>1415757673</out_trade_no> // <refund_id></refund_id> // <transaction_id></transaction_id> // <sign>66FFB727015F450D167EF38CCC549521</sign> // </xml> public static Map<String,String> refundquery(String refundno) throws Exception{ SortedMap<String, String> map = new TreeMap<String, String>(); // 公众账号id map.put("appid", APPID); // 微信支付分配的商户号 map.put("mch_id", MCHID); //随机字符串 map.put("nonce_str", create_nonce_str().replaceAll("-","")); map.put("refund_id", refundno); map.put("out_trade_no", refundno); map.put("refund_id", refundno); map.put("sign",createSign(map)); String params = XML.toXML(map); Map<String,String> returnmap = XML.toMap(URLHanlder.post("https://api.mch.weixin.qq.com/pay/refundquery",params)); if ("success".equalsIgnoreCase(returnmap.get("return_code"))) { return returnmap; }else{ log(returnmap); } return null; } /* 订单生成后不能马上调用关单接口,最短调用时间间隔为5分钟。 接口链接:https://api.mch.weixin.qq.com/pay/closeorder <xml> <appid>wx2421b1c4370ec43b</appid> <mch_id>10000100</mch_id> <nonce_str>4ca93f17ddf3443ceabf72f26d64fe0e</nonce_str> <out_trade_no>1415983244</out_trade_no> <sign>59FF1DF214B2D279A0EA7077C54DD95D</sign> </xml> */ public Map<String,String> closeorder(String orderid) throws Exception{ SortedMap<String, String> map = new TreeMap<String, String>(); // 公众账号id map.put("appid", APPID); // 微信支付分配的商户号 map.put("mch_id", MCHID); //随机字符串 map.put("nonce_str", create_nonce_str().replaceAll("-","")); map.put("out_trade_no", orderid); map.put("sign",createSign(map)); String params = XML.toXML(map); Map<String,String> returnmap = XML.toMap(URLHanlder.post("https://api.mch.weixin.qq.com/pay/closeorder",params)); if ("success".equalsIgnoreCase(returnmap.get("return_code"))) { return returnmap; }else{ log(returnmap); } return null; } //获取用户列表 @SuppressWarnings("unchecked") public static Map<String,String> getUserList(HttpServletRequest req) throws IOException{ String access_token = getToken(req); String str = URLHanlder.post(new StringBuffer().append("https://api.weixin.qq.com/cgi-bin/user/get?access_token=").append(access_token).toString()); return JSON.parseObject(str, Map.class); } /** * JS 签名验证 * @param jsapi_ticket * @param url * @return */ public static Map<String, String> sign(String jsapi_ticket, String url) { Map<String, String> ret = new HashMap<String, String>(); String nonce_str = create_nonce_str(); String timestamp = create_timestamp(); String signature = ""; jsapi_ticket = getTicket(null); String string1; //注意这里参数名必须全部小写,且必须有序 string1 = "jsapi_ticket=" + jsapi_ticket +"&noncestr=" + nonce_str +"×tamp=" + timestamp +"&url=" + url; try { MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(string1.toString().getBytes("UTF-8")); signature = SecurityHanlder.byteToHex(crypt.digest()); } catch (Exception e) { e.printStackTrace(); } ret.put("url", url); ret.put("jsapi_ticket", jsapi_ticket); ret.put("nonceStr", nonce_str); ret.put("timestamp", timestamp); ret.put("signature", signature); return ret; } /** * 随机字符串 * @return */ private static String create_nonce_str() { return UUID.randomUUID().toString().replaceAll("-",""); } /** * 随机时间 * @return */ private static String create_timestamp() { return Long.toString(System.currentTimeMillis() / 1000); } /** * XML 文件处理,获取XML文件 * @author LGF * */ public static class XML { //输入流转换xml对象 public static String toXMLString(InputStream input) throws Exception{ try { return new SAXReader().read(input).asXML(); } finally { input.close(); } } //输入流转 map对象 @SuppressWarnings("unchecked") public static Map<String,String> toMap(InputStream input) throws Exception{ try { Document doc = new SAXReader().read(input); Element root = doc.getRootElement(); List<Element> elements = root.elements(); Map<String,String> map = new TreeMap<String,String>(); for (Element element : elements) { map.put(element.getName(), element.getText()); } return map; } finally { input.close(); } } //xml 字符串转 map @SuppressWarnings("unchecked") public static Map<String,String> toMap(String str) throws Exception{ Map<String,String> map = new HashMap<String,String>(); Document doc = DocumentHelper.parseText(str); Element root = doc.getRootElement(); List<Element> elements = root.elements(); for (Element element : elements) { map.put(element.getName(), element.getText()); } return map; } //map 转 xml @SuppressWarnings("all") public static String toXML(Map map) throws Exception{ return toXML(map,null); } @SuppressWarnings("unchecked") public static String toXML(Map<String,Object> map,Element e) throws Exception{ if(e==null){ e = DocumentHelper.createDocument().addElement("xml"); } for (String key : map.keySet()) { Object val = map.get(key); if(val!=null&&val instanceof Map){ toXML((Map<String,Object>)val,e.addElement(key)); }else if(val instanceof Collection){ Collection<Object> c = (Collection<Object>) val; Iterator<Object> it = c.iterator(); while(it.hasNext()){ toXML((Map<String,Object>)it.next(),e.addElement(key)); } }else{ e.addElement(key).setText(val!=null?val.toString():""); } } return e.asXML(); } } /** * 获取微信 access_token 线程 * @author LGF * */ public static class ThreadAccessToken implements Runnable{ private ServletContext servletContext; //实例化后启动线程 public ThreadAccessToken(ServletContext servletContext) { this.servletContext = servletContext; servletContext.setAttribute("wx_appId", APPID); servletContext.setAttribute("wx_appSecret", APPSECRET); setToken(); new Thread(this).start(); } @Override public void run() { while(true){ try { //两小时刷新一次签名 Thread.sleep(CHANGE_TOKEN_TIME); setToken(); } catch (InterruptedException e) { try { Thread.sleep(1000*20); } catch (InterruptedException e1) { e1.printStackTrace(); } e.printStackTrace(); new ThreadAccessToken(servletContext); } } } /** * 设置 access_token */ private synchronized void setToken(){ try { String input = URLHanlder.post(MessageFormat.format(URL_ACCESS_TOKEN,APPID,APPSECRET)); JSONObject json = JSONObject.parseObject(input); String wx_access_token = json.getString(ACCESS_TOKEN); String input1 = URLHanlder.post(MessageFormat.format(URL_JS_TICKET, wx_access_token)); JSONObject json1 = JSONObject.parseObject(input1); String wx_ticket = json1.get(TICKET).toString(); servletContext.setAttribute(ACCESS_TOKEN, wx_access_token); servletContext.setAttribute(TICKET, wx_ticket); } catch (Exception e) { e.printStackTrace(); } } } //格式化微信昵称 public static String formatNickName(String name,String regx){ if(regx==null){ //字母数字或汉字 regx = "([A-Za-z]|[\u4E00-\u9FA5]|[0-9])*"; } StringBuffer sb = new StringBuffer(); if(name!=null){ for (int i = 0; i < name.length(); i++) { char c = name.charAt(i); boolean is = String.valueOf(c).matches("([A-Za-z]|[\u4E00-\u9FA5]|[0-9])*"); if(is){ sb.append(c); } } } return sb.toString(); } public static class Messaeg{ //发送模板消息 public static void sendTemplate(String openid,String templateId,String url,Map<String,Object> data){ try { String token = getToken(null); Map<String, Object> map = new HashMap<String, Object>(); map.put("touser", openid); map.put("template_id", templateId); map.put("url", url); map.put("data", data); String requestbody = JSON.toJSONString(map); StringBuilder sb_url = new StringBuilder(); sb_url.append("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=").append(token); URLHanlder.post(sb_url.toString(), requestbody); } catch (Exception e) { e.printStackTrace(); } } } public static class URLHanlder { /** * 发送 HTTP 请求获取输入流 * @param url * @param params * @return */ public static InputStream postSteam(String url,Map<String,String> params){ URL uri = null; try { if(params!=null&¶ms.size()!=0){ StringBuffer sb = new StringBuffer(); int index = 0; if(url.indexOf("?")!=-1){ sb.append("&"); }else{ sb.append("?"); } for (String s : params.keySet()) { sb.append(s); sb.append("="); sb.append(params.get(s)); if(params.size()-1!=index){ sb.append("&"); } index++; } url+=sb.toString(); } uri = new URL(url); HttpURLConnection conn = (HttpURLConnection) uri.openConnection(); conn.setRequestMethod("POST"); int l = conn.getContentLength(); if(l>0){ return conn.getInputStream(); } } catch (Exception e) { e.printStackTrace(); } return null; } /** * 发送输入流数据 * @param url * @param in * @return */ public static InputStream post(String url,InputStream in){ URL uri = null; try { uri = new URL(url); HttpURLConnection conn = (HttpURLConnection) uri.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.setDoInput(true); OutputStream out = conn.getOutputStream(); byte[] bs = new byte[1024]; int len = -1; while ((len = in.read(bs))!=-1) { out.write(bs,0,len); } in.close(); out.flush(); out.close(); int l = conn.getContentLength(); if(l>0){ return conn.getInputStream(); } } catch (Exception e) { e.printStackTrace(); } return null; } /** * 发送输入流数据 * @param url * @param content * @return */ public static InputStream post(String url,String content,String charset){ URL uri = null; try { uri = new URL(url); HttpURLConnection conn = (HttpURLConnection) uri.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.setDoInput(true); OutputStream out = conn.getOutputStream(); OutputStreamWriter ow = new OutputStreamWriter(out,charset); ow.write(content); ow.flush(); ow.close(); out.flush(); out.close(); int len = conn.getContentLength(); if(len>0){ return conn.getInputStream(); } } catch (Exception e) { e.printStackTrace(); } return null; } public static InputStream post(String url,String content){ return post(url,content,"UTF-8"); } /** * 将输入流转换成字符串 * @param in 输入流 * @return string * @throws IOException */ public static String toString(InputStream in) throws IOException{ BufferedReader br = null; try { if (in != null) { StringBuffer sb = new StringBuffer(); br = new BufferedReader(new InputStreamReader( new BufferedInputStream(in), "UTF-8")); while (true) { String readLine = br.readLine(); if (readLine == null || readLine.isEmpty()) { break; } sb.append(readLine); } return sb.toString(); } } catch (Exception e) { e.printStackTrace(); }finally{ if(br!=null){br.close();} } return null; } /** * 发送 HTTP 请求获取输入流 * @param url * @return */ public static InputStream postSteam(String url){ return postSteam(url,null); } //输入流转字符 public static String post(String url,Map<String,String> params) throws IOException{ return toString(postSteam(url,params)); } //输入流转字符 public static String post(String url) throws IOException{ return toString(postSteam(url,null)); } } public static class SecurityHanlder { private static final String uuid = "4c7a37a8-b8d7-442f-b9df-31ec4bcacebc"; /** * 获取 md5 加密字符串 * @param str * @return * @throws Exception */ public static String md5(String str) throws Exception { return getSign(str,"MD5"); } /** * 获取 md5 加密字符串 * 规则 str+uuid * @param str * @return * @throws Exception */ public static String md5x(String str) throws Exception { return getSign(str+uuid,"MD5"); } /** * 获取 sha1 加密字符串 * @param str * @return * @throws Exception */ public static String sha1(String str) throws Exception { return getSign(str,"SHA-1"); } /** * 获取 sha1 加密字符串 * 二次加密 * 规则 str+uuid * @param str * @return * @throws Exception */ public static String sha1x(String str) throws Exception { return getSign(str+uuid,"SHA-1"); } /** * 获取 sha1进行加密的字符后再进行 md5 加密字符串 * 二次加密 * @param str * @return * @throws Exception */ public static String md5_sha1(String str) throws Exception { return getSign(getSign(str,"MD5"),"SHA-1"); } /** * 获取 md5 进行加密的字符后再进行 sha1加密字符串 * @param str * @return * @throws Exception */ public static String sha1_md5(String str) throws Exception { return getSign(getSign(str,"SHA-1"),"MD5"); } /** * 创建随机字符 * @return */ public static String createNonceStr() { return UUID.randomUUID().toString(); } /** * 获取加密签名 * @param str 字符 * @param type 加密类型 * @return * @throws Exception */ public static String getSign(String str, String type) throws Exception { MessageDigest crypt = MessageDigest.getInstance(type); crypt.reset(); crypt.update(str.getBytes("UTF-8")); return str = byteToHex(crypt.digest()); } /** * 创建时间戳 * @return */ public static String createTimestamp() { return Long.toString(System.currentTimeMillis() / 1000); } /** * 字节转换 16 进制 * @param hash * @return */ private static String byteToHex(final byte[] hash) { Formatter formatter = new Formatter(); for (byte b : hash) { formatter.format("%02x", b); } String result = formatter.toString(); formatter.close(); return result; } } }
相关推荐
在Java微信开发中,工具类和JAR包的使用是至关重要的,它们为开发者提供了便捷的接口和功能,简化了微信API的调用过程。这个压缩包中的"JAVA微信支付工具类"很可能是包含了处理微信支付相关逻辑的类库,方便开发者...
java版微信交互开发工具类,包含图灵机器人自动回复。微信交互处理类及网页授权功能。这是之前发布的了,把分调低了重新发布。
微信APP支付工具类是Java开发中用于实现微信支付功能的核心组件。在移动应用开发中,尤其是在电商、服务类应用中,微信支付作为一种便捷的在线支付方式,被广泛采用。本工具类集成了与微信支付服务器交互的关键逻辑...
总结来说,这些PHP工具类是构建微信支付功能的基础,它们涵盖了从数据交换、API调用、配置管理到回调处理的整个流程,大大简化了开发者的开发工作,提高了微信支付集成的效率和稳定性。在实际项目中,开发者需要按照...
这个“微信小程序工具类集合”很可能是开发者为了方便微信小程序开发而整理的一系列实用工具函数的集合,这些工具函数可以解决开发过程中遇到的各种常见问题,提高开发效率。 在JavaScript开发微信小程序的过程中,...
微信支付工具类是Java开发中用于与微信支付接口交互的核心组件,主要用于实现各种支付相关的功能。这个工具类通常封装了微信支付的API调用,使得开发者可以更方便地在自己的后台系统中集成微信支付功能。以下是对这...
Java后台微信支付工具类是开发微信App支付时不可或缺的一部分,它包含了处理支付请求、响应以及与微信支付服务器交互的关键逻辑。微信支付是一个安全且广泛使用的支付方式,它允许用户通过微信应用程序进行线上交易...
微信支付工具类是Java开发中常见的一种实用工具集,它主要负责处理与微信支付平台相关的接口调用,以便实现各种支付功能。在这个压缩包“微信支付工具类.zip”中,包含了一个名为“微信工具类”的文件,这很可能是...
微信小程序支付工具类是开发者为了简化微信支付流程而编写的代码模块,它的主要目标是提供一个易用且可定制的接口,以便在微信小...总的来说,这个工具类的存在大大降低了微信小程序支付的开发难度,提高了开发效率。
在实际开发中,Maven会根据这个文件自动下载并管理所需的第三方库,如处理XML的库、网络通信库等,以支持微信支付工具类的正常运行。 整体来看,这个整合的微信支付工具类为开发者提供了一套便捷的方式来接入微信...
总的来说,这个工具类为开发者提供了便捷的微信支付集成方式,减少了手动处理复杂支付流程的工作量。开发者只需要按照说明修改必要的参数,调用工具类的方法即可实现支付功能。同时,它也展示了如何在Android应用中...
在微信开发中,获取OpenID是一项基础且重要的任务。OpenID是微信用户在微信平台上的唯一标识,它用于区分不同的用户。本工具类主要用于帮助开发者便捷地获取微信用户的OpenID,以便实现用户登录、授权等功能。以下是...
微信支付工具类是一个Java开发的库,用于实现微信支付的全过程。这个压缩包包含的代码涵盖了从支付下单、处理订单到接收微信服务器的异步通知以及查询支付结果等多个关键环节,是开发者集成微信支付功能的重要参考...
微信红包发放工具类是微信支付接口的一个重要组成部分,主要用于实现线上活动中的红包发放功能。这个压缩包提供的代码包含了实现这一功能的关键文件,包括API接口、配置文件和DEMO示例。接下来,我们将深入探讨这些...
微信支付回调工具类是开发微信支付功能时必不可少的一部分,它主要负责处理微信支付服务器与商户服务器之间的通信。在用户成功下单并完成支付后,微信支付系统会通过回调接口将支付结果通知给商户,这时就需要一个回...
7. **开发环境与工具**:为了进行微信开发,开发者可能需要Visual Studio这样的IDE,以及NuGet包管理器来安装和管理依赖的微信SDK。同时,调试过程可能需要用到Postman或Fiddler等工具来模拟API请求和查看响应。 8....
在这个"微信小程序开发-工具类-简易计算器案例源码.zip"压缩包中,我们看到的是一个用于学习微信小程序开发的实例——一个简易计算器的源代码。这个案例将帮助开发者理解如何在微信小程序中实现基本的计算功能,包括...
对于“微信支付---工具类”的代码,应该包含签名生成、请求发送、结果处理等功能,通过查看和分析这部分代码,可以更深入地理解和解决签名错误的问题。如果在“微信支付---工具类.rar”文件中包含了具体的代码示例或...
使用Servlet实现企业微信开发通常包括以下几个步骤: 1. **注册企业微信开发者**:在企业微信管理后台完成开发者认证,获取AppID和AppSecret,这是所有后续操作的基础。 2. **创建Server配置**:在Java项目中,你...
综上所述,"android微信支付带java后台工具类"是实现微信支付功能的关键组件,它涵盖了支付流程的核心部分,包括后台订单处理、签名生成和支付结果验证,帮助开发者简化开发过程,提高支付体验。