博客这么久没写了(因为女朋友(^__^) 嘻嘻……),今天决定把微信相关开发遇到的坑给大家分享一下,以免大家掉入坑浪费过多的时间!
我会在文章末尾上传一个开箱即用的微信公众号支付的demo,理论上来讲你只需要修改配置文件就可以支付了。
使用的技术:SpringBoot、angularJs。
使用了一个第三方的微信mavne依赖: weixin-java-mp在pom可以看见,时过境迁可能weixin-java-mp版本更新了。weixin-java-mp的API:https://github.com/chanjarster/weixin-java-tools/wiki
mavne依赖在中央仓库可以查找:http://mvnrepository.com/
微信公众号配置
access.properties文件
该文件中主要配置公众号和微信支付相关参数,里面的信息在申请公众号和申请微信支付就会得到(开箱即用也就是修改这个配置文件里面的内容)
该工具类主要映射access.properties文件键的名称
读取access.properties文件的方式为: String appId=PropertyHandler.getInstance().getValue(SampleConstants.WEIXIN_APPID)
初始化配置公众号
/**
* 初始化微信配置
*/
public class WeiXinInitConfigUtil {
public static WxMpInMemoryConfigStorage wxMpConfigStorage;
public static WxMpService wxMpService;
public static WxMpMessageRouter wxMpMessageRouter;
public static WxMpOAuth2AccessToken wxMpOAuth2AccessToken;
//注意静态块,这里使用的是weixin-java-mp的API,直接对应配置文件填上去。
static {
WxMpInMemoryConfigStorage storage=new WxMpInMemoryConfigStorage();
storage.setAppId(PropertyHandler.getInstance().getValue(SampleConstants.WEIXIN_CORPID)); storage.setSecret(PropertyHandler.getInstance().getValue(SampleConstants.WEIXIN_CORPSECRET));
storage.setToken(PropertyHandler.getInstance().getValue(SampleConstants.WEIXIN_APP_APPID_TOKEN));
storage.setAesKey(PropertyHandler.getInstance().getValue(SampleConstants.WEIXIN_APP_APPID_AESKEY));
wxMpConfigStorage=storage;
wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(storage);
wxMpMessageRouter = new WxMpMessageRouter(wxMpService);
}
}
封装当前用户
用拦截器来配置需要的校验参数 。
/**
* Created by orange on 2016/10/27.
* 获取微信用户相关信息的拦截器,该拦截器将会过滤所有请求,进行是否包含 微信登录用户的判断。
*/
@Component
public class WxCpIntercepter implements HandlerInterceptor {
private static final long serialVersionUID = 1L;
private static final Logger logger = LoggerFactory.getLogger(WxCpIntercepter.class);
//在请求处理之前进行调用(Controller方法调用之前)
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String userAgent = request.getHeader("user-agent");
//获取session里面的用户对象
WxMpUser wxUser = (WxMpUser) request.getSession().getAttribute(SampleConstants.WEIXIN_USER);
//获取request中的code
String code = request.getParameter("code");
//当request请求里面有code,但是session里面没有weixinUser(登录微信用户),将会查询的微信用户封装到session中
if (code != null && wxUser == null) {
WxCpUtil.setUserIdForSession(request);
}
//设置微信校验参数到session中
WxCpUtil.openContact(request);
return true;// 只有返回true才会继续向下执行,返回false取消当前请求
}
//请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
//在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
对拦截器进行统一配置
/**
* Created by orange on 2016/10/27.
* 拦截器集中配置类
*/
@Configuration
public class FilterConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 多个拦截器组成一个拦截器链
// addPathPatterns 用于添加拦截规则
// excludePathPatterns 用户排除拦截
//这里可添加多个拦截器
registry.addInterceptor(new WxCpIntercepter()).addPathPatterns("/**");
super.addInterceptors(registry);
}
}
拦截器使用的WxCpUtil类代码
public class WxCpUtil {
private static final Logger logger = LoggerFactory.getLogger(WxCpUtil.class);
/**
* 判断用户是否关注了公众号
* @param token
* @param openid
* @return
*/
public static boolean judgeIsFollow(String token,String openid){
int zhi=0;
InputStream is=null;
String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token="+token+"&openid="+openid+"&lang=zh_CN";
try {
URL urlGet = new URL(url);
HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
http.setRequestMethod("GET"); // 必须是get方式请求
http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
http.setDoOutput(true);
http.setDoInput(