经过最近一段时间的学习使用,我对微信的支付和分享都相当熟悉,前几天冒出个想法为什么不能将这些封装成jar包,以后在自己需要支付开发的时候这部分代码肯定不用在写了,在微信大版本不变的情况下能一直使用,好嘛,有了想法当然也就有了动力,话不多少直接开搞。

一、介绍整理出来的项目

先来个项目整体结构

一)bean包

bean包主要包含8个java类,分别是
1. BaseAccessToken(基础access_token对象),

2. JSAPIConfig(JSAPI使用的配置信息),

3. JSAPITicket(微信jsapi_ticket实体类),

4. Oauth2AccessToken(网页授权accessToken),

5. PayCallback(回调结束返回微信内容),

6. UnifiedOrder(统一下单对象),

7. WechatJSShareBean(微信分享 微信好友/朋友圈分享…模型),

8. WechatUserInfo(微信关注用户基本信息)

二)util包

1.ClassLoaderUtils:类加载起,主要在解析配置文件时使用

/** $Id: ClassLoaderUtils.java 471756 2006-11-06 15:01:43Z husted $** Licensed to the Apache Software Foundation (ASF) under one* or more contributor license agreements.  See the NOTICE file* distributed with this work for additional information* regarding copyright ownership.  The ASF licenses this file* to you under the Apache License, Version 2.0 (the* "License"); you may not use this file except in compliance* with the License.  You may obtain a copy of the License at**  http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing,* software distributed under the License is distributed on an* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY* KIND, either express or implied.  See the License for the* specific language governing permissions and limitations* under the License.*/
package com.wtp.wechat.util;import java.io.IOException;
import java.io.InputStream;
import java.net.URL;/*** This class is extremely useful for loading resources and classes in a fault tolerant manner* that works across different applications servers.* <p/>* It has come out of many months of frustrating use of multiple application servers at Atlassian,* please don't change things unless you're sure they're not going to break in one server or another!**/
public class ClassLoaderUtils {/*** Load a given resource.* <p/>* This method will try to load the resource using the following methods (in order):* <ul>* <li>From {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()}* <li>From {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()}* <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() }* </ul>** @param resourceName The name of the resource to load* @param callingClass The Class object of the calling object*/public static URL getResource(String resourceName, Class callingClass) {URL url = null;url = Thread.currentThread().getContextClassLoader().getResource(resourceName);if (url == null) {url = ClassLoaderUtils.class.getClassLoader().getResource(resourceName);}if (url == null) {url = callingClass.getClassLoader().getResource(resourceName);}return url;}/*** This is a convenience method to load a resource as a stream.* <p/>* The algorithm used to find the resource is given in getResource()** @param resourceName The name of the resource to load* @param callingClass The Class object of the calling object*/public static InputStream getResourceAsStream(String resourceName, Class callingClass) {URL url = getResource(resourceName, callingClass);try {return (url != null) ? url.openStream() : null;} catch (IOException e) {return null;}}/*** Load a class with a given name.* <p/>* It will try to load the class in the following order:* <ul>* <li>From {@link Thread#getContextClassLoader() Thread.currentThread().getContextClassLoader()}* <li>Using the basic {@link Class#forName(java.lang.String) }* <li>From {@link Class#getClassLoader() ClassLoaderUtil.class.getClassLoader()}* <li>From the {@link Class#getClassLoader() callingClass.getClassLoader() }* </ul>** @param className    The name of the class to load* @param callingClass The Class object of the calling object* @throws ClassNotFoundException If the class cannot be found anywhere.*/public static Class loadClass(String className, Class callingClass) throws ClassNotFoundException {try {return Thread.currentThread().getContextClassLoader().loadClass(className);} catch (ClassNotFoundException e) {try {return Class.forName(className);} catch (ClassNotFoundException ex) {try {return ClassLoaderUtils.class.getClassLoader().loadClass(className);} catch (ClassNotFoundException exc) {return callingClass.getClassLoader().loadClass(className);}}}}/*** Prints the current classloader hierarchy - useful for debugging.*/public static void printClassLoader() {System.out.println("ClassLoaderUtils.printClassLoader");printClassLoader(Thread.currentThread().getContextClassLoader());}/*** Prints the classloader hierarchy from a given classloader - useful for debugging.*/public static void printClassLoader(ClassLoader cl) {System.out.println("ClassLoaderUtils.printClassLoader(cl = " + cl + ")");if (cl != null) {printClassLoader(cl.getParent());}}public static void main(String s[]){System.out.println(ClassLoaderUtils.getResource("", ClassLoaderUtils.class));}
}

2.CommonUtil:工具类

package com.wtp.wechat.util;import java.io.UnsupportedEncodingException;
import java.util.UUID;/** * @ClassName: CommonUtil * @Description: 通用工具类* @author tianpengw * @date 2017年10月12日 下午5:09:46 *  */
public class CommonUtil {/*** * @Description: 字符串为null时转换为"",不为null时不作处理* @author tianpengw * @return String*/public static String filterStr(String obj){if(null == obj || obj.toLowerCase().equals("null")){return "";}return obj;}/*** * @Description: 判断字符串或者对象是否为null,或者字符串是否为""* @author tianpengw * @return String*/public static boolean isEmpty(Object obj){if(null == obj || obj.toString().isEmpty()){return true;}return false;}/***   * @Description: 获得一个UUID* @author tianpengw * @return String*/public static String getUUID(){  return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);  } /*** * @Description: 转换字符串的编码格式* @author tianpengw * @param str* @return* @throws UnsupportedEncodingException*/public static String coventToUTF8(String str) throws UnsupportedEncodingException{return new String(str.trim().getBytes("ISO-8859-1"), "UTF-8");}
}

3.HttpHelper:HTTP工具类

package com.wtp.wechat.util;import java.io.BufferedReader;import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;import javax.servlet.http.HttpServletRequest;/** * @ClassName: HttpHelper * @Description: HTTP工具类* @author tianpengw * @date 2017年10月12日 上午9:43:37 *  */
public class HttpHelper {/*** * @Description: 获取客户端地址* @author tianpengw * @param request* @return*/public static String getClientIP(HttpServletRequest request) {String ipAddress = request.getHeader("x-forwarded-for");  if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {  ipAddress = request.getHeader("Proxy-Client-IP");  }  if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {  ipAddress = request.getHeader("WL-Proxy-Client-IP");  }  if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {  ipAddress = request.getRemoteAddr();  if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){  //根据网卡取本机配置的IP  InetAddress inet=null;  try {  inet = InetAddress.getLocalHost();  } catch (UnknownHostException e) {  e.printStackTrace();  }  ipAddress= inet.getHostAddress();  }  }  //对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割  if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15  if(ipAddress.indexOf(",")>0){  ipAddress = ipAddress.substring(0,ipAddress.indexOf(","));  }  }  return ipAddress;}/*** * @Description: 发起Http请求* @author tianpengw * @param requestUrl 请求地址* @param requestMethod 请求方式 GET/POST* @param outputStr 请求参数,如果没有置 null* @return*/public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {    try {    URL url = new URL(requestUrl);    HttpURLConnection conn = (HttpURLConnection) url.openConnection();    conn.setDoOutput(true);    conn.setDoInput(true);    conn.setUseCaches(false);    // 设置请求方式(GET/POST)    conn.setRequestMethod(requestMethod);    conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");    // 当outputStr不为null时向输出流写数据    if (null != outputStr) {    OutputStream outputStream = conn.getOutputStream();    // 注意编码格式    outputStream.write(outputStr.getBytes("UTF-8"));    outputStream.close();    }    // 从输入流读取返回内容    InputStream inputStream = conn.getInputStream();    InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);    String str = null;  StringBuffer buffer = new StringBuffer();    while ((str = bufferedReader.readLine()) != null) {    buffer.append(str);    }    // 释放资源    bufferedReader.close();    inputStreamReader.close();    inputStream.close();    inputStream = null;    conn.disconnect();    return buffer.toString();    } catch (Exception e) {e.printStackTrace();}    return null;    } /*** * @Description: 根据req对象获得当前请求地址,带参数* @author tianpengw * @param req* @return*/public static String getFullRequestUrl(HttpServletRequest req){String url = req.getRequestURL().toString();String queryStr = req.getQueryString();if(CommonUtil.isEmpty(queryStr)){return url;}return url + "?" + queryStr;}/*** * @Description: 判断是否是微信浏览器发起的请求,如果是返回true,反之返回false* @author tianpengw * @param req* @return*/public static boolean isWechatBrowser(HttpServletRequest req){String ua = req.getHeader("user-agent").toLowerCase();  if (ua.indexOf("micromessenger") > 0) {// 是微信浏览器  return true;  } return false;}
}

4.PropertiesUtil:读取配置文件工具类

package com.wtp.wechat.util;import java.io.IOException;import java.io.InputStream;
import java.util.Properties;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;/** * @ClassName: PropertiesUtil * @Description: 读取配置文件工具类* @author tianpengw * @date 2017年10月12日 上午9:13:13 *  */
public class PropertiesUtil {private static Logger log = LogManager.getLogger(PropertiesUtil.class);private static Properties prop;static{try{if(null == prop){prop = new Properties();}InputStream fis = null;fis =  ClassLoaderUtils.getResourceAsStream("wechat.properties", PropertiesUtil.class);if(fis!=null){prop.load(fis);// 将属性文件流装载到Properties对象中   fis.close();// 关闭流   }}catch (Exception e) {log.error("读取配置文件出错:" + e );}}/*** * @Description: 根据key获取配置的值* @author tianpengw * @param key* @return*/public static String getProperties(String key){if(key==null) return null;return prop.getProperty(key);}/*** * @Description: * @author tianpengw * @param proper 读取配置的文件名称* @param key* @return*/public static String getPropertie(String resourceName,String key){InputStream fis =  ClassLoaderUtils.getResourceAsStream(resourceName, PropertiesUtil.class);if(fis!=null){try {prop.load(fis);fis.close();// 关闭流   } catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}   }if(key==null) return null;return prop.getProperty(key);}/*** * @Description: 根据key获取配置的值,若没有,则取传过来的默认的值* @author tianpengw * @param key* @param defaultValue 默认值* @return*/public static String getProperties(String key,String defaultValue){if(key==null) return null;return prop.getProperty(key, defaultValue);}
}

5.SignatureUtil: 加密工具类

package com.wtp.wechat.util;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;/** * @ClassName: SignatureUtil * @Description: 加密工具类* @author tianpengw * @date 2017年9月26日 下午6:22:34 *  */
public class SignatureUtil {/*** * @Description: 生成 MD5* @author tianpengw * @param data* @return*/public static String MD5(String data){StringBuilder sb = new StringBuilder();try {java.security.MessageDigest md = MessageDigest.getInstance("MD5");byte[] array = md.digest(data.getBytes("UTF-8"));sb = new StringBuilder();for (byte item : array) {sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));}} catch (Exception e) {e.printStackTrace();}return sb.toString();}/** * SHA1 安全加密算法 * @param maps 参数key=value字符串 * @return * @throws DigestException  */  public static String SHA1(String decrypt) {  StringBuffer hexString = new StringBuffer();  try {  //指定sha1算法  MessageDigest digest = MessageDigest.getInstance("SHA-1");  digest.update(decrypt.getBytes());  //获取字节数组  byte messageDigest[] = digest.digest();  // 字节数组转换为 十六进制 数  for (int i = 0; i < messageDigest.length; i++) {  String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);  if (shaHex.length() < 2) {  hexString.append(0);  }  hexString.append(shaHex);  }  } catch (NoSuchAlgorithmException e) {  e.printStackTrace();  } return hexString.toString();  }/*** * @Description: 微信签名算法 * @author tianpengw * @param params 参数格式* @param signatureType 加密类型 SHA1/MD5,默认MD5* @return*/public static String signatures(Map<String, String> params, String signatureType){String str="";try {List<String> paramsStr = new ArrayList<String>();for (String key : params.keySet()) {paramsStr.add(key);}Collections.sort(paramsStr);StringBuilder sbff = new StringBuilder();for (String kk : paramsStr) {String value = params.get(kk);if (CommonUtil.isEmpty(sbff.toString())) {sbff.append(kk + "=" + value);} else {sbff.append("&" + kk + "=" + value);}}if("SHA1".equals(signatureType)){str = SHA1(sbff.toString());}else{str = MD5(sbff.toString());}} catch (Exception e) {e.printStackTrace();}return str;}
}

6.XMLBeanUtils:xml格式解析封装工具类

package com.wtp.wechat.util;import java.io.InputStream;import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.XppDriver;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.core.util.QuickWriter;
/*** * @ClassName: XMLBeanUtils * @Description: xml格式解析封装工具类* @author tianpengw * @date 2017年10月13日 上午11:32:25 **/
public class XMLBeanUtils {private static XStream xStream = new XStream(new XppDriver(new NoNameCoder()){@Overridepublic HierarchicalStreamWriter createWriter(Writer out) {return new PrettyPrintWriter(out) {// 对所有xml节点的转换都增加CDATA标记boolean cdata = true;@Override@SuppressWarnings("rawtypes")public void startNode(String name, Class clazz) {super.startNode(name, clazz);}@Overridepublic String encodeNode(String name) {return name;}@Overrideprotected void writeText(QuickWriter writer, String text) {if (cdata) {writer.write("<![CDATA[");writer.write(text);writer.write("]]>");} else {writer.write(text);}}};}});/*** * @Description: bean转xml字符串* @author tianpengw * @param obj* @return*/public static String objectToXMLStr(Object obj){xStream.alias("xml", obj.getClass());return xStream.toXML(obj);}/** * 解析微信发来的请求(XML) *  * @param request * @return * @throws Exception */  @SuppressWarnings("unchecked")  public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {  // 将解析结果存储在HashMap中  Map<String, String> map = new HashMap<String, String>();  // 从request中取得输入流  InputStream inputStream = request.getInputStream();  // 读取输入流  SAXReader reader = new SAXReader();  Document document = reader.read(inputStream);  // 得到xml根元素  Element root = document.getRootElement();  // 得到根元素的所有子节点  List<Element> elementList = root.elements();  // 遍历所有子节点  for (Element e : elementList){map.put(e.getName(), e.getText());  }// 释放资源  inputStream.close();  inputStream = null;  return map;  }/*** @description 将xml字符串转换成map* @param xml* @return Map*/public static Map<String, String> readStringXmlOut(String xml) {Map<String, String> map = new HashMap<String, String>();Document doc = null;try {doc = DocumentHelper.parseText(xml); // 将字符串转为XMLElement rootElt = doc.getRootElement(); // 获取根节点@SuppressWarnings("unchecked")List<Element> list = rootElt.elements();// 获取根节点下所有节点for (Element element : list) { // 遍历节点map.put(element.getName(), element.getText()); // 节点的name为map的key,text为map的value}} catch (DocumentException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}return map;}}

7.【重要】WechatUtil:微信基础工具类

package com.wtp.wechat.util;import java.io.UnsupportedEncodingException;import java.util.Date;
import java.util.HashMap;
import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;import com.google.gson.Gson;
import com.wtp.wechat.bean.BaseAccessToken;
import com.wtp.wechat.bean.JSAPITicket;
import com.wtp.wechat.bean.Oauth2AccessToken;
import com.wtp.wechat.bean.WechatJSShareBean;
import com.wtp.wechat.bean.WechatUserInfo;
/** * @ClassName: WechatUtil * @Description: 微信基础工具类* @author tianpengw * @date 2017年10月12日 上午9:53:03 *  */
public class WechatUtil {private static Logger log = LogManager.getLogger(WechatUtil.class);/*** 微信公众号appid*/public static final String appid = PropertiesUtil.getProperties("wechat.appid");/*** 微信公众号appsecret*/public static final String appsecret = PropertiesUtil.getProperties("wechat.appsecret");/*** state*/public static final String state = PropertiesUtil.getProperties("wechat.state");/*** 基础token/jsApiTicket 有效时间(单位毫秒)* api中是2小时(7200s) 此处设为7190s*/private static long expiresInMillisecond = 7190000L;/*** 缓存map* 存储信息 :* accessToken         ---->   【基础 accessToken】* baseExpireMillis    ---->   【基础token存储时间】 * jsApiTicket         ---->   【jsapi_ticket】* ticketExpireMillis  ---->   【ticket存储时间】 **/private static Map<String,Object> wechatCacheMap = new HashMap<String,Object>();/*** 获取accessToken凭证请求地址*/private static final String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";/*** 授权获取code地址*/private static final String oauth2Url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";/*** 通过code换取网页授权地址*/private static final String oauth2TokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";/*** 拉取用户信息*/private static final String userinfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";/*** 获取jsApiTicket地址*/private static final String jsApiTicketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";/*** 授权方式-snsapi_base*/public static final String  scope_base = "snsapi_base";/*** 授权方式-snsapi_userinfo*/public static final String scope_userinfo = "snsapi_userinfo";/*** * @Description: 获取access_token* @author tianpengw * @return*/public static BaseAccessToken getBaseToken(){BaseAccessToken token = new BaseAccessToken();if(wechatCacheMap.containsKey("accessToken") && !CommonUtil.isEmpty(wechatCacheMap.get("accessToken"))){Long expireTime = (Long) wechatCacheMap.get("baseExpireMillis");if(new Date().getTime() <= expireTime){//accessToken 仍然有效token.setAccess_token((String)wechatCacheMap.get("accessToken"));token.setExpires_in(7200);return token;}}String url = tokenUrl.replace("APPID", appid).replace("APPSECRET", appsecret);String tokenResp = HttpHelper.httpsRequest(url, "GET", null);if(!CommonUtil.isEmpty(tokenResp)){log.info("获得基础access_token:" + tokenResp);Gson json=new Gson();token = json.fromJson(tokenResp,BaseAccessToken.class);if(!CommonUtil.isEmpty(token.getAccess_token())){wechatCacheMap.put("accessToken", token.getAccess_token());wechatCacheMap.put("baseExpireMillis", (new Date().getTime() + expiresInMillisecond));}}return token;}/*** 生成微信授权地址* @param scope* @param redirectUrl* @return*/public static String getOauth2Url(String scope,String redirectUrl){return oauth2Url.replace("APPID", appid).replace("REDIRECT_URI", redirectUrl).replace("STATE", state).replace("SCOPE", scope);}/**** 通过code换取网页授权access_token(与基础支持中的access_token不同)* @param code* @return*/public static Oauth2AccessToken getUserOpenId(String code){Oauth2AccessToken token = new Oauth2AccessToken();String url = oauth2TokenUrl.replace("APPID", appid).replace("SECRET", appsecret).replace("CODE", code);String aouth2TokenResp = HttpHelper.httpsRequest(url, "POST", null);if(!CommonUtil.isEmpty(aouth2TokenResp)){log.info("根据code获得用户aouth2Token数据:" + aouth2TokenResp);Gson json=new Gson();token = json.fromJson(aouth2TokenResp, Oauth2AccessToken.class);}return token;}/*** * @Description: 获取用户的基本信息,注意需scope为 snsapi_userinfo* @author tianpengw * @param oauth2Token* @return* @throws UnsupportedEncodingException */public static WechatUserInfo getUserInfo(Oauth2AccessToken oauth2Token) throws UnsupportedEncodingException{WechatUserInfo userInfo = new WechatUserInfo();String accessToken = oauth2Token.getAccess_token();String openId = oauth2Token.getOpenid();if(!CommonUtil.isEmpty(accessToken) && !CommonUtil.isEmpty(openId)){String url = userinfoUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);String userInfoResp = HttpHelper.httpsRequest(url, "POST", null);if(!CommonUtil.isEmpty(userInfoResp)){log.info("根据code获得用户基本信息:" + userInfoResp);Gson json=new Gson();userInfo = json.fromJson(userInfoResp, WechatUserInfo.class);}}return userInfo;}/*** * @Description: 获取微信jsapi_ticket* @author tianpengw * @return*/private static JSAPITicket getJsApiTicket(){JSAPITicket ticket = new JSAPITicket();BaseAccessToken token = getBaseToken();if(wechatCacheMap.containsKey("jsApiTicket") && null != wechatCacheMap.get("jsApiTicket")){Long expireTime = (Long) wechatCacheMap.get("ticketExpireMillis");if(new Date().getTime() <= expireTime){//ticket 仍然有效ticket.setTicket((String)wechatCacheMap.get("jsApiTicket"));ticket.setErrcode("0");ticket.setErrmsg("ok");ticket.setExpires_in(7200);return ticket;}}String url = jsApiTicketUrl.replace("ACCESS_TOKEN", token.getAccess_token());String ticketResp = HttpHelper.httpsRequest(url, "POST", null);if(!CommonUtil.isEmpty(ticketResp)){Gson json=new Gson();ticket = json.fromJson(ticketResp,JSAPITicket.class);if(!"".equals(token.getAccess_token())){wechatCacheMap.put("jsApiTicket", ticket.getTicket());wechatCacheMap.put("ticketExpireMillis", (new Date().getTime() + expiresInMillisecond));}}return ticket;}/*** * @Description: 微信自定义分享配置* @author tianpengw * @param commonShare* @param req*/public static void wechatShareConfig(WechatJSShareBean commonShare, HttpServletRequest req){String timestamp = Long.toString(System.currentTimeMillis() / 1000);commonShare.setAppId(WechatUtil.appid);commonShare.setTimestamp(timestamp);//获取时间戳commonShare.setNonceStr(CommonUtil.getUUID());//获取指定长度的随机字符串commonShare.setLink(HttpHelper.getFullRequestUrl(req));//签名用的url必须是调用JS接口页面的完整URLJSAPITicket ticket = getJsApiTicket();Map<String, String> params = new HashMap<String, String>();params.put("noncestr", commonShare.getNonceStr());params.put("timestamp", commonShare.getTimestamp());params.put("url", HttpHelper.getFullRequestUrl(req));//签名用的url必须是调用JS接口页面的完整URLparams.put("jsapi_ticket", ticket.getTicket());commonShare.setSignature(SignatureUtil.signatures(params,"SHA1"));}
}

8.【重要】WechatPayUtil:微信支付工具类

package com.wtp.wechat.util;import java.util.Map;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;import com.wtp.wechat.bean.UnifiedOrder;
/*** * @ClassName: WechatPayUtil * @Description: 微信支付工具类* @author tianpengw * @date 2017年10月12日 下午3:38:25 **/
public class WechatPayUtil {private static Logger log = LogManager.getLogger(WechatPayUtil.class);/*** 微信支付分配的商户号*/public static final String mchId = PropertiesUtil.getProperties("pay.mchid");/*** 商户平台密钥*/public static final String apiKey = PropertiesUtil.getProperties("pay.apikey");/*** 微信支付分配的商户号*/public static final String notifyUrl = PropertiesUtil.getProperties("pay.notifyUrl");/*** 终端设备号(门店号或收银设备ID),注意:PC网页或公众号内支付请传"WEB"*/public static String deviceInfo = "WEB";/*** JSAPI -- 公众号支付*/public static String tradeTypeJs = "JSAPI";/*** MWEB -- H5支付*/public static String tradeTypeH5 = "MWEB";/*** 统一订单地址*/private static String unifiedUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";/*** * @Description: 公众号支付-统一订单类型获得prepay_id* @author tianpengw * @param uo* @return*/public static String getUnifiedOrderPId(UnifiedOrder uo){String sign = createUnifiedOrderSign(uo);uo.setSign(sign);String xml = XMLBeanUtils.objectToXMLStr(uo);log.info("公账号支付统一订单请求参数:"+xml);String res = HttpHelper.httpsRequest(unifiedUrl,"POST",xml);log.info("公账号支付统一订单返回结果:"+res);Map<String, String> responseMap = XMLBeanUtils.readStringXmlOut(res);return responseMap.get("prepay_id");}/*** * @Description: 微信支付 -统一订单类型获得mweb_url* @author tianpengw * @param uo* @return*/public static String getUnifiedOrderMWebUrl(UnifiedOrder uo){String sign = createUnifiedOrderSign(uo);uo.setSign(sign);String xml = XMLBeanUtils.objectToXMLStr(uo);log.info("H5支付统一订单请求参数:"+xml);String res = HttpHelper.httpsRequest(unifiedUrl,"POST",xml);log.info("H5支付统一订单返回结果:"+res);Map<String, String> responseMap = XMLBeanUtils.readStringXmlOut(res);return responseMap.get("mweb_url");}/*** 获取统一下单签名* @param unifiedOrder* @return*/private static String createUnifiedOrderSign(UnifiedOrder unifiedOrder){StringBuffer sign = new StringBuffer();sign.append("appid=").append(unifiedOrder.getAppid());sign.append("&body=").append(unifiedOrder.getBody());sign.append("&device_info=").append(unifiedOrder.getDevice_info());sign.append("&mch_id=").append(unifiedOrder.getMch_id());sign.append("&nonce_str=").append(unifiedOrder.getNonce_str());sign.append("&notify_url=").append(unifiedOrder.getNotify_url());/*** H5支付签名时没有用户的openId*/if(!CommonUtil.isEmpty(unifiedOrder.getOpenid())){sign.append("&openid=").append(unifiedOrder.getOpenid());}sign.append("&out_trade_no=").append(unifiedOrder.getOut_trade_no());sign.append("&spbill_create_ip=").append(unifiedOrder.getSpbill_create_ip());sign.append("&total_fee=").append(unifiedOrder.getTotal_fee());sign.append("&trade_type=").append(unifiedOrder.getTrade_type());sign.append("&key=").append(apiKey);return SignatureUtil.MD5(sign.toString()).toUpperCase();}
}

三)配置文件

wechat.properties:这里配置了微信公众号和支付相关的几个关键数据,不多介绍了,贴出来自己看:

#basic wechat settings
wechat.appid=wx**************
wechat.appsecret=12d3400*********************
wechat.state=*****#basic wechat pay settings
pay.mchid=145*******
pay.apikey=ab123d******************
pay.notifyUrl=******

log4j2.xml:这个是日志配置文件

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN"><Appenders><!--输出控制台的配置--><Console name="Console" target="SYSTEM_OUT"><PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/></Console><!-- 按天每天备份一个日志 --><RollingFile name="RollingFile" fileName="d:/log/projectLog.log" filePattern="d:/log/projectLog_%d{yyyy-MM-dd}_%i.log"><PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n" /><Policies><!-- 每24小时更新一次 --><TimeBasedTriggeringPolicy modulate="true" interval="24" /></Policies><!-- 最多备份30个 --><DefaultRolloverStrategy max="30" /></RollingFile></Appenders><Loggers><Root level="trace">    <AppenderRef ref="Console"/><AppenderRef ref="RollingFile"/></Root></Loggers>
</Configuration>

最后分享下我封装的jar吧 点击进入下载页面
(如果你觉得5分太贵,自己从博客里整理也是可以的,我基本也都贴出了代码)

附上将本地包加在maven仓库的方法(默认你已经装了apache-maven工具并配好环境变量):
1) 下载jar包后扔在d盘根目录(当然也可其他目录,如果是别的下面的地址需要相应变更);
2) cmd命令行执行如下命令:

mvn install:install-file -Dfile=D:/wechat_api_20171016.jar -DgroupId=com.yytp.lib -DartifactId=wechat_api_20171016 -Dversion=1.0.0 -Dpackaging=jar

3)看到如下界面提示说明生成成功

4)在你的c:>用户>计算机名>.m2>repository>com>yytp>lib>wechat_api_20171016>1.0.0下就生成好了

然后你就能将其放在其他的仓库下了(注意要带上整个目录,如果没有就一层一层的建立)

<dependency><groupId>com.yytp.lib</groupId><artifactId>wechat_api_20171016</artifactId><version>1.0.0</version>
</dependency>

最后,代码毕竟是人写出来的,如果有什么疑问,不妥或待优化之处,希望留下你的思路和想法。
到此为止,本整理结束了,希望能给你带来收益。

微信开发整理生成jar包相关推荐

  1. maven生成jar包

    改了部分cas源码,想重新生成jar包,只好试着脱离eclipse,学了一下maven打jar包的命令,记录如下: 1.首先下载maven (请注意自己的jdk版本,如果使用maven2建议使用jdk ...

  2. 使用Gradle生成jar包

    如果你的java项目是gradle结构,并且要生成jar包的话,方法如下: 1.在build.gradle文件中添加一个新任务jar: jar {archiveFileName = 'myprojec ...

  3. 使用MATLAB如何生成jar包

    我们都知道,MATLAB在数值分析方面是很优秀的,因此我们有时候需要使用Java调用MATLAB写的一些函数.那么今天就给大家说说怎么弄. 提前声明:我的电脑系统是win10企业版,MATLAB版本为 ...

  4. Eclipse如何生成jar包

    Eclipse如何生成jar包 图1 右击项目Properites,选择Android,选择Is Library,然后会编译生成jar包在bin目录下.

  5. java 单开程序_java生成jar包并且单进程运行的实例

    java文件打包jar运行 有效步骤: 1.cmd 到当前目录(默认包主类所在目录为例) set classpath = 默认包主类所在目录 2.javac 主类名.java 3.java 主类名 4 ...

  6. Eclipse 生成 Jar 包

    第一步: 第二步: 第三步: 第四步: 最后按"完成"生成jar包.不过在测试中发现用这种方式生成jar中中文将会是乱码,此问题尚未找到解决方法. 转载于:https://www. ...

  7. linux 目录中的文件和子目录生成jar包文件的方法

    linux 目录中的文件和子目录生成jar包文件的方法 jar cvf spark-libs.jar -C //usr/cwgis/app/spark/jars/ .//注意:.点前面有一个空格 [r ...

  8. IDEA生成JAR包导出JAR包

    使用IDEA工具生成可执行的JAR包 PS:将Java项目封装成可执行到JAR包用起来及其方便,本文将介绍如果使用IDEA工具生成JAR包. 开始教程 一.在菜单栏找到-文件 选择-项目结构(快捷键- ...

  9. 创建jira plugin插件、创建jira实例生成jar包总结

    创建jira plugin插件.创建jira实例生成jar包总结 创建插件骨架: 在本地安装完Atlassian SDK后,需注意将环境变量里的maven路径更改为sdk里自带的maven仓库路径. ...

最新文章

  1. 【牛客挑战赛】我是 A 题
  2. mysql删除数据库恢复_详解MySQL数据库恢复误删除数据
  3. HDU hdu 2094 产生冠军 拓扑排序 判定环
  4. Hadoop学习之MapReduce(三)
  5. DCMTK:CT采集类型FG类的测试
  6. php计算代码运行时间与内存使用的一段代码
  7. Linux内核管理之分配掩码(三)
  8. 扇贝有道180902每日一句
  9. 极域电子教室常见问题的解决方法
  10. 计算机控制技术期中测试素材2020版
  11. 非因解读 | 单细胞空间蛋白质组学分析揭示临床显著性前列腺癌多参数相关MRI检查的异质性
  12. 单片机通过串口与电脑通信
  13. 胆固醇PEG胆固醇,CLS-PEG-CLS
  14. 像素是什么,一个像素有多大,像素和分辨率的关系
  15. 国密算法(SM2,SM3,SM4)辅助工具升级版(OTP+PBOC3.0)
  16. android动画原理,最详细的解释小白也能听懂,值得收藏!
  17. 大中华地区的商业IMAX影院(更新至2010年7月)
  18. TCP/IP协议栈Lwip的设计与实现:之一
  19. 今天腊八,请组里的人到大成Party了,很开心啊!
  20. PHP 打印0-n的所有质数,输出1到n中所有的素数 C语言编程:输出1到N中所有质数的个数...

热门文章

  1. Windows CE嵌入式系统程序开发
  2. 【复盘比赛】SDP 2021@NAACL LongSumm 科学论⽂⻓摘要生成任务 第一名
  3. Amazon Personalize 个性化效果评估,从准确性到多样性、新颖性和偶然性
  4. MTK led驱动测试 (adb)
  5. 免费数据集 人工智能训练方面
  6. 【Python语言基础】——Python 教程
  7. day82_babasport第八天
  8. 10款经典香水 怀旧十个年代-Part I
  9. 2018首届传神者大会:“语言+新技术”将推动语言产业生态化发展
  10. Python:计算两个时间相隔多少天