随着微信的使用越来越多,更多的公司或者个人希望借助微信的平台创建自己的公众号或者服务号。对于开发人员来说,可以将微信的公众号看做一个浏览器,通过在微信端创建跳转按钮的方式来访问到你自己创建的并且已经成功部署的web项目上。不过需要注意的是,微信只接受带有域名的url访问。web创建者要先申请域名。
下面进入正题:通过wechat访问java+springMVC网站
首先附上微信用户手册,主要的流程为
1.将项目地址(带域名)配置在一个对应的微信按钮上,具体操作可访问微信用户手册。
2.通过该地址生成一个微信访问地址
/** * 微信授权 * @Title: forgetpw * @Description: TODO * @param @param request * @param @param response * @param @return 设定文件 * @return String 返回类型 * @throws */ @RequestMapping("/authority") public String authority(HttpServletRequest request, HttpServletResponse response) { String redisUrl = sendWechatMessage.<span style="color:#FF6666;">getWechatCodeURL()</span>;// request.setAttribute("redisUrl", redisUrl); System.out.println("redisUrl="+redisUrl); return "wechat/authority"; } /** * 登录授权 * @Title: getWechatCodeURL * @Description: TODO * @param @return 设定文件 * @return String 返回类型 * @throws */ public String <span style="color:#FF6666;">getWechatCodeURL ()</span> { //https://open.weixin.qq.com/connect/oauth2/authorize? //appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect String appid = getParam.getParam("appid");//自己公众号的appid,可能登录微信公众平台查看 String redirect_uri = getParam.getParam("redirect_uri");//自己项目的登录首页地址 String snsapi_base = "snsapi_base";//只能获得openid,当为<strong>snsapi_userinfo</strong>时,可通过token获取用户基本信息 StringBuffer sb = new StringBuffer(); GetWechatCode getWechatCode = new GetWechatCode(); getWechatCode.setAppid(appid); getWechatCode.setRedirect_url(redirect_uri); getWechatCode.setResponse_type("code"); getWechatCode.setScope(snsapi_base); sb.append("https://open.weixin.qq.com/connect/oauth2/authorize?"); sb.append("appid="+getWechatCode.getAppid()); sb.append("&redirect_uri="+getWechatCode.getRedirect_url()); sb.append("&response_type="+getWechatCode.getResponse_type()); sb.append("&scope="+getWechatCode.getScope()); return sb.toString(); }
3.将改地址传给客户端,并使用页面跳转将code返回给在上面设定的登录首页地址(redirect_uri)
$(document).ready(function(){ var url = "${redisUrl}"; if(url==null||url=="") { url= "<%=request.getContextPath() %>/wechat/authority"; } window.location=url; });4.服务端接收到code后,使用httpclient访问微信请求token地址,获取最新token和openid
String openid = ""; //微信获取登录用户的openId try { openid = sendWechatMessage.<span style="color:#FF6666;">getWechatOpenId</span>(wechatcode, username); } catch (ConnectException ce) { request.setAttribute("InfoMessage", "微信端连接超时:"+ce.getMessage()); logger.error(TimeHelper.getCurrentDateTime()+"------------"+username+"微信端连接超时:"+ce.getMessage()); return "wechat/login"; } catch (Exception e) { request.setAttribute("InfoMessage", "微信端https请求异常:"+e.getMessage()); logger.error(TimeHelper.getCurrentDateTime()+"------------"+username+"微信端https请求异常:"+e.getMessage()); return "wechat/login"; } /** * 获取微信的登录用户id * @Title: getWechatOpenId * @Description: TODO * @param @param code * @param @param username * @param @return * @param @throws KeyManagementException * @param @throws NoSuchAlgorithmException * @param @throws NoSuchProviderException * @param @throws MalformedURLException * @param @throws ProtocolException * @param @throws UnsupportedEncodingException * @param @throws IOException 设定文件 * @return String 返回类型 * @throws */ public String <span style="color:#FF6666;">getWechatOpenId</span>(String code,String username) throws KeyManagementException, NoSuchAlgorithmException, NoSuchProviderException, MalformedURLException, ProtocolException, UnsupportedEncodingException, IOException { //https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code String appid = getParam.getParam("appid"); String secret = getParam.getParam("secret"); String authorization_code = "authorization_code"; StringBuffer sb = new StringBuffer(); GetWechatOpenId getWechatOpenId = new GetWechatOpenId(); getWechatOpenId.setAppid(appid); getWechatOpenId.setCode(code); getWechatOpenId.setGrant_type(authorization_code); getWechatOpenId.setSecret(secret); sb.append("https://api.weixin.qq.com/sns/oauth2/access_token?"); sb.append("appid="+getWechatOpenId.getAppid()); sb.append("&secret="+getWechatOpenId.getSecret()); sb.append("&code="+getWechatOpenId.getCode()); sb.append("&grant_type="+getWechatOpenId.getGrant_type()); logger.info(TimeHelper.getCurrentDateTime()+"------------获取"+username+"微信端请求地址"+sb.toString()); JSONObject jsonObject = CommonUtil.<span style="color:#33CC00;">httpsRequestToJsonObject</span>(sb.toString(), "GET", null,username); logger.info(TimeHelper.getCurrentDateTime()+"------------获取"+username+"微信端openid接收返回值"+jsonObject.toJSONString()); String wechatOpenId = jsonObject.getString("openid"); Date currTime = TimeHelper.getCurrentDateTime(); String wechatToken =jsonObject.getString("access_token"); String expires_in =jsonObject.getString("expires_in"); String refresh_token =jsonObject.getString("refresh_token"); //在数据库记录token TWechatToken tWechatToken = new TWechatToken(); tWechatToken.setAccessToken(wechatToken); tWechatToken.setOpenId(wechatOpenId); tWechatToken.setGetTime(currTime); tWechatToken.setKeepTime(expires_in); tWechatToken.setRefreshToken(refresh_token); tWechatTokenRepository.insert(tWechatToken); return wechatOpenId; } public class CommonUtil { private static final Logger logger = LoggerFactory.getLogger(CommonUtil.class); public static JSONObject <span style="color:#33CC00;">httpsRequestToJsonObject</span>(String requestUrl, String requestMethod, String outputStr,String username) throws KeyManagementException, NoSuchAlgorithmException, NoSuchProviderException, MalformedURLException, ProtocolException, UnsupportedEncodingException, IOException { JSONObject jsonObject = null; StringBuffer buffer = httpsRequest(requestUrl, requestMethod, outputStr); jsonObject = JSONObject.parseObject(buffer.toString()); return jsonObject; } private static StringBuffer httpsRequest(String requestUrl, String requestMethod, String output) throws NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException, MalformedURLException, IOException, ProtocolException, UnsupportedEncodingException { URL url = new URL(requestUrl); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setDoInput(true); connection.setUseCaches(false); connection.setRequestMethod(requestMethod); if (null != output) { OutputStream outputStream = connection.getOutputStream(); outputStream.write(output.getBytes("utf-8")); outputStream.close(); } // 从输入流读取返回内容 InputStream inputStream = connection.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; connection.disconnect(); return buffer; }
5.每次使用token时都需要根据超时时间和获取时间判断当前token是否有效,如果有效继续使用,如果无效则要通过refresh_token重新刷新。
/** * 获取当前有效token * @Title: getaccessToken * @Description: TODO * @param @param username * @param @param openId * @param @return * @param @throws KeyManagementException * @param @throws NoSuchAlgorithmException * @param @throws NoSuchProviderException * @param @throws MalformedURLException * @param @throws ProtocolException * @param @throws UnsupportedEncodingException * @param @throws IOException 设定文件 * @return String 返回类型 * @throws */ public String getaccessToken(String username,String openId) throws KeyManagementException, NoSuchAlgorithmException, NoSuchProviderException, MalformedURLException, ProtocolException, UnsupportedEncodingException, IOException { List<TWechatToken> list = tWechatTokenRepository.getList(openId); Date getTime = list.get(0).getGetTime(); Date currTime = TimeHelper.getCurrentDateTime(); String keepTime = list.get(0).getKeepTime(); String refresh_token = list.get(0).getRefreshToken(); long l = getTime.getTime()+Integer.valueOf(keepTime); long l1 =currTime.getTime()-1000; if(l>l1) { String accessToken = list.get(0).getAccessToken(); logger.info(TimeHelper.getCurrentDateTime()+"------------"+username+"数据库获取access_token"+accessToken); return accessToken; } else { //https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET String appid = getParam.getParam("appid"); String grant_type = "refresh_token"; StringBuffer sb = new StringBuffer(); sb.append("https://api.weixin.qq.com/sns/oauth2/refresh_token?"); sb.append("&appid="+appid); sb.append("&grant_typ="+grant_type); sb.append("refresh_token="+refresh_token); logger.info(TimeHelper.getCurrentDateTime()+"------------"+username+"微信端获取access_token发送地址"+sb.toString()); JSONObject jsonObject = CommonUtil.httpsRequestToJsonObject(sb.toString(), "GET", null,username); logger.info(TimeHelper.getCurrentDateTime()+"------------"+username+"微信端获取access_token"+jsonObject.toJSONString()); String wechatToken =jsonObject.getString("access_token"); String expiresIn = jsonObject.getString("expires_in"); String refreshToken = jsonObject.getString("refresh_token"); String openIdNew = jsonObject.getString("openid"); TWechatToken tWechatToken = new TWechatToken(); tWechatToken.setAccessToken(wechatToken); tWechatToken.setGetTime(currTime); tWechatToken.setKeepTime(expiresIn ); tWechatToken.setRefreshToken(refreshToken); tWechatToken.setOpenId(openIdNew); tWechatTokenRepository.insert(tWechatToken); return wechatToken; } }
6.向对应的openid发送信息
/** * @throws IOException * @throws UnsupportedEncodingException * @throws ProtocolException * @throws MalformedURLException * @throws NoSuchProviderException * @throws NoSuchAlgorithmException * @throws KeyManagementException * 发送微信信息 * @Title: sendMessage * @Description: TODO * @param @param username * @param @return 设定文件 * @return String 返回类型 * @throws */ public void sendMessage(String openid,String username,String message) throws KeyManagementException, NoSuchAlgorithmException, NoSuchProviderException, MalformedURLException, ProtocolException, UnsupportedEncodingException, IOException { //https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN String access_token = getaccessToken(username,openid); String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token="+access_token; StringBuffer sb = new StringBuffer(); sb.append("{ "); sb.append(" \"touser\":\""+openid+"\", "); sb.append(" \"msgtype\":\"text\", "); sb.append(" \"text\": "); sb.append(" { "); sb.append(" \"content\":\""+message+"\" "); sb.append(" } "); sb.append("} "); logger.info(TimeHelper.getCurrentDateTime()+"------------"+username+"微信端发送信息发送地址"+url); JSONObject jsonObject = CommonUtil.httpsRequestToJsonObject(url, "POST", sb.toString(),username); logger.info(TimeHelper.getCurrentDateTime()+"------------"+username+"微信端向"+openid+"发送信息的返回值"+jsonObject.toJSONString()); }
最后附上token表结构
CREATE TABLE `t_wechat_token` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `access_token` varchar(400) DEFAULT NULL, `get_time` datetime DEFAULT NULL, `keep_time` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ;