重庆小潘seo博客

当前位置:首页 > 重庆网络营销 > 小潘杂谈 >

小潘杂谈

详解微信开发模式之自定义菜单实现代码

时间:2020-09-16 09:00:10 作者:重庆seo小潘 来源:
最近有做了关于微信公众号和自己网站用户进行用户关联授权登录的一个功能,主要是用户关注该公众号,点击会员中心,则会弹出需要关联授权的网页授权:OAuth2.0网页授权,然后用户同意获取用户信息,进行用户和网站的关联,然后用户则可以使用微信进行登录。

最近有做了关于微信公众号和自己网站用户进行用户关联授权登录的一个功能,主要是用户关注该公众号,点击会员中心,则会弹出需要关联授权的网页授权:OAuth2.0网页授权,然后用户同意获取用户信息,进行用户和网站的关联,然后用户则可以使用微信进行登录。

本次做的是一个在Java的http://www.php.cn/java/java-Action.html" target="_blank">Action层处理各个返回参数获取数据。

一、 使用到的工具:

1、ngrok,将你自己的本机映射到公网,这样保证可以随时测试开发;

1、下载ngrok,网址:http://www.tunnel.mobi/

2、将文件放到Tomcat目录下,在cmd中运行ngrok -config ngrok.cfg -subdomain xinzhi 8080

3、ngrok工具为在慕课网@LAOBI 看到的

2、微信公众号测试账号,随时测试,首先保证在测试账号下没有问题后在进行公众号的移植。

二、使用到在Java中发送一个Http请求,然后返回JSON参数,获得JSON参数,然后进行处理。

首先,获取将公众号测试号放到properties文件中,以便我们进行调用或者更换,如:url请用https

Properties代码详解微信开发模式之自定义菜单实现代码AppID = wxf00**c3dd2ebfa0AppSecret = 3cb220755f****506dc35391aa5c03ecurl = https://xinzhi.tunnel.mobi这里url为我们映射到外网的地址,一会需要用到。然后需要两个工具类,该工具类作用是在Java的Action中发送http请求后获取到去返回值

启用自己有相应的改动,以适应本项目的需求:

WeixinUtil.java 和 MyX509TrustManager.java

Java代码详解微信开发模式之自定义菜单实现代码package com.zhtx.common.util;import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.ConnectException;import java.net.URL;import javax.net.ssl.HttpsURLConnection;import javax.net.ssl.SSLContext;import javax.net.ssl.SSLSocketFactory;import javax.net.ssl.TrustManager;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * 公众平台通用接口工具类 ** @author xinz * @date 2015-10-14 */public class WeixinUtil {private static Logger log = LoggerFactory.getLogger(WeixinUtil.class);/*** 发起https请求并获取结果** @param requestUrl 请求地址* @param requestMethod 请求方式(GET、POST)* @param outputStr 提交的数据* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)*/public static String httpRequest(String requestUrl, String requestMethod, String outputStr) {StringBuffer buffer = new StringBuffer();try {// 创建SSLContext对象,并使用我们指定的信任管理器初始化TrustManager[] tm = { new MyX509TrustManager() };SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");sslContext.init(null, tm, new java.security.SecureRandom());// 从上述SSLContext对象中得到SSLSocketFactory对象SSLSocketFactory ssf = sslContext.getSocketFactory();URL url = new URL(requestUrl);HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();httpUrlConn.setSSLSocketFactory(ssf);httpUrlConn.setDoOutput(true);httpUrlConn.setDoInput(true);httpUrlConn.setUseCaches(false);// 设置请求方式(GET/POST)httpUrlConn.setRequestMethod(requestMethod);if ("GET".equalsIgnoreCase(requestMethod))httpUrlConn.connect();// 当有数据需要提交时if (null != outputStr) {OutputStream outputStream = httpUrlConn.getOutputStream();// 注意编码格式,防止中文乱码outputStream.write(outputStr.getBytes("UTF-8"));outputStream.close();}// 将返回的输入流转换成字符串InputStream inputStream = httpUrlConn.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String str = null;while ((str = bufferedReader.readLine()) != null) {buffer.append(str);}bufferedReader.close();inputStreamReader.close();// 释放资源inputStream.close();inputStream = null;httpUrlConn.disconnect();} catch (ConnectException ce) {log.error("Weixin server connection timed out.");} catch (Exception e) {log.error("https request error:{}", e);}return buffer.toString();}} 对于https请求,我们需要一个证书信任管理器,这个管理器类需要自己定义,但需要实现X509TrustManager接口,代码如下:

Java代码详解微信开发模式之自定义菜单实现代码package com.zhtx.common.util;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;import javax.net.ssl.X509TrustManager;/** * 证书信任管理器(用于https请求) ** @author xinz * @date 2015-10-14 */public class MyX509TrustManager implements X509TrustManager {public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}public X509Certificate[] getAcceptedIssuers() {return null;}} 微信返回参数的一个POJO类:

Java代码详解微信开发模式之自定义菜单实现代码private Stringopenid;//用户的唯一标识 private Stringnickname;//用户昵称 private Integer sex;// 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知 private Stringprovince;//用户个人资料填写的省份 private Stringcity;//普通用户个人资料填写的城市 private Stringcountry;// 国家,如中国为CN private Stringheadimgurl;// 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。 private Stringprivilege;// 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom) private Stringunionid;// 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。详见:获取用户个人信息(UnionID机制) private String access_token; 授权凭证验证的类:

Java代码详解微信开发模式之自定义菜单实现代码private String errcode;private String errmsg; 通过code换取网页授权access_token

Java代码详解微信开发模式之自定义菜单实现代码private String access_token;private String expires_in;private String refresh_token;private String openid;private String scope;private String unionid; 关于微信头像的,获取的是一个http的url,则需要将图片下载到服务器存储,然后获得相对路径:

Java代码详解微信开发模式之自定义菜单实现代码/*** 使用url或者http存入文件* @Title: fileUpload* @param @param fileUrl文件url,可以是http* @param @param path文件存储路径* @return void* @throws xinz*/public static void fileUpload (String fileUrl,String path){//读取文件String s1 = fileUrl;java.io.InputStream is = null; //定义一个输入流。BufferedInputStream bis = null;//定义一个带缓冲的输入流 。//写到本地BufferedOutputStream bos = null; //定义一个带缓冲的输出流。try{java.net.URL url = new java.net.URL(s1);//创建一个URL对象。is = url.openStream();//打开到此 URL 的连接并返回一个用于从该连接读入的 InputStream。bis = new java.io.BufferedInputStream(is);File file = new File(path);if(!file.exists()){ //测试此抽象路径名表示的文件或目录是否存在。file.createNewFile();//创建此抽象路径名表示的文件或目录。}bos = new BufferedOutputStream(new FileOutputStream(file));;byte[] b = new byte[1024]; //创建字节数组。while(bis.read(b)!=-1){//输入流中的数据如果还有下一行(!=-1)将继续循环bos.write(b);//将字节数组写入输出流。}}catch(Exceptione){System.out.println(e.toString());}finally{try{bos.flush();//刷新此缓冲的输出流。bis.close(); //关闭此输入流 。}catch(Exceptione){System.out.println(e.toString());}}}现在是基础工作都做完了,现在开发代码的开发,然后我们按照这个步骤开发:

第一步:用户同意授权,获取code

这里的url就是前面所准备在properties中的url了。

Java代码详解微信开发模式之自定义菜单实现代码/*** 微信用户授权* @Title: wechatOauth* @param @param request* @param @param response* @param @param model* @param @return* @return String* @throws xinz*/@RequestMapping("wechatOauth")public String wechatOauth(HttpServletRequest request,HttpServletResponse response,Model model){/***1 第一步:用户同意授权,获取code*///首先拿到微信公众号的AppID、AppSecret等参数String AppID = ZhtxHelper.getApplicationResourcesProp("sendSms","AppID");String urlOpen = ZhtxHelper.getApplicationResourcesProp("sendSms","url");//如果用户授权成功则跳转到此urlString loginUrl = ""+urlOpen+"/zhtx-wap/weixin/getAccessToken";//用户授权,获取codeString url = "https://open.weixin.qq.com/connect/oauth2/authorize?"+ "appid="+AppID+""+ "&redirect_uri="+loginUrl+""+ "&response_type=code"+ "&scope=snsapi_userinfo"+ "&state=123#wechat_redirect";//forward redirectreturn "redirect:"+url+"";}第二步:通过code换取网页授权access_tokenJava代码详解微信开发模式之自定义菜单实现代码/*** 通过code换取网页授权access_token* @Title: getAccessToken* @param @param request* @param @param response* @param @param model* @param @return* @return String* @throws xinz*/@RequestMapping("getAccessToken")public String getAccessToken(HttpServletRequest request,HttpServletResponse response,Model model) {//获取到返回的参数try {//首先拿到微信公众号的AppID、AppSecret等参数String AppID = ZhtxHelper.getApplicationResourcesProp("sendSms","AppID");String AppSecret = ZhtxHelper.getApplicationResourcesProp("sendSms","AppSecret");String code = request.getParameter("code");String url = null;if(code!=null){/***2 第二步:通过code换取网页授权access_token*///用户授权,获取codeurl = "https://api.weixin.qq.com/sns/oauth2/access_token?"+ "appid="+AppID+""+ "&secret="+AppSecret+""+ "&code="+code+""+ "&grant_type=authorization_code";String requestMethod = "GET";String outputStr = "";String httpRequest = WeixinUtil.httpRequest(url, requestMethod, outputStr);System.out.println("通过code换取网页授权access_token="+httpRequest);AccessTokenModel accTok = JSON.parseObject(httpRequest, AccessTokenModel.class);/***4 第四步:拉取用户信息(需scope为 snsapi_userinfo)*///用户授权,获取codeString urlUser = "https://api.weixin.qq.com/sns/userinfo?"+ "access_token="+accTok.getAccess_token()+""+ "&openid="+accTok.getOpenid()+""+ "&lang=zh_CN";String httpUser = WeixinUtil.httpRequest(urlUser, requestMethod, outputStr);System.out.println("拉取用户信息=="+httpUser);WechatUser wechatUser = JSON.parseObject(httpUser, WechatUser.class);wechatUser.setAccess_token(accTok.getAccess_token());/***5 附:检验授权凭证(access_token)是否有效*/WechatMsg checkAccessToken = checkAccessToken(wechatUser.getAccess_token(), wechatUser.getOpenid());if(checkAccessToken.getErrcode().equals("0")){CurrentSession.setAttribute("wechatUser", wechatUser);WechatUser wechatU = new WechatUser();wechatU.setOpenid(wechatUser.getOpenid());List<WechatUser> findWechatUser = wechatUserService.findWechatUser(wechatU);if(findWechatUser.size()>0){UserRegister userRegister = userService.findUserByOpenid(wechatUser.getOpenid());CurrentSession.setAttribute("user", userRegister);return "redirect:/user/userCenter";}else{return "/jsp/wechat/wechatregister";}}else{//如果access_token失效,则再次进行调用,并存储access_token值,access_token有效期为2个小时this.wechatOauth(request, response, model);}}} catch (Exception e) {System.out.println("===拉取用户出错===");e.printStackTrace();}//forward redirectreturn "/jsp/wechat/wechatregister";}第四步:拉取用户,和自己网站用户绑定Java代码详解微信开发模式之自定义菜单实现代码/*** 微信关联用户* @Title: saveWechatUser* @param @param mobilePhone* @param @param password* @param @param validataCode* @param @return* @return String* @throws xinz*/@RequestMapping("saveWechatUser")public String saveWechatUser(HttpServletResponse response,String mobilePhone,String password,String validataCode){//使用手机号来判断该手机是否在注册UserRegister userRegister = userService.findUserByPhone(mobilePhone);WechatUser wechatUser = (WechatUser)CurrentSession.getAttribute("wechatUser");WechatUser wechatU = new WechatUser();wechatU.setOpenid(wechatUser.getOpenid());List<WechatUser> findWechatUser = wechatUserService.findWechatUser(wechatU);if(findWechatUser.size()>0 && userRegister.getOpenid()!=null){CurrentSession.setAttribute("user", userRegister);return "redirect:/user/userCenter";}else{//如果没有注册,开始注册if(userRegister==null){Result<UserRegister> saveUserInfoApp = userRegisterService.saveUserInfoApp(mobilePhone, password, validataCode,wechatUser);if(saveUserInfoApp.getState()==1){//进行微信和用户的关联wechatUserService.saveWechatUser(wechatUser);CurrentSession.setAttribute("user", userRegister);return "redirect:/user/userCenter";}}else if(userRegister.getOpenid()==null || userRegister.getOpenid().equals("")){//否则,查询出用户信息,放入session中,关联微信,跳转到用户中心UserRegister userReg = new UserRegister();userReg.setId(userRegister.getId());//存入微信openiduserReg.setOpenid(wechatUser.getOpenid());userService.upUser(userReg);UserInfo user = new UserInfo();//存入微信头像//图片类型String dateStr =DateUtil.format(DateUtil.getCurrentDate(), "yyyyMMdd")+ "/";//图片类型String imgType = "JPG";//微信头像名称String app2DBarNameAndType = UuidUtil.getUUID()+"."+imgType;//微信头像路径String path =ZhtxHelper.getApplicationResourcesProp("application","app.img.projectpath")+ SysConstant.GOODS2DBARPATH + dateStr;File file1 = new File(path);file1.mkdirs();//图片全路径String imgUrl = SysConstant.GOODS2DBARPATH + dateStr+app2DBarNameAndType;FileUtil.fileUpload(wechatUser.getHeadimgurl(), path);user.setRegisterId(userRegister.getId());user.setImageUrl(imgUrl);userInfoService.updateUserInfo(user);//存入微信用户wechatUserService.saveWechatUser(wechatUser);UserRegister userW = userService.findUserByPhone(mobilePhone);CurrentSession.setAttribute("user", userW);return "redirect:/user/userCenter";}else{CurrentSession.setAttribute("user", userRegister);return "redirect:/user/userCenter";}}return "redirect:/user/userCenter";}附:检验授权凭证(access_token)是否有效Java代码详解微信开发模式之自定义菜单实现代码/*** 检验授权凭证(access_token)是否有效* @Title: checkAccessToken* @param @param access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同* @param @param openid 用户的唯一标识* @return WechatMsg返回消息实体* @throws xinz*/public static WechatMsg checkAccessToken(String access_token,String openid){String requestMethod = "GET";String outputStr = "";String url = "https://api.weixin.qq.com/sns/auth?"+ "access_token="+access_token+""+ "&openid="+openid+"";String httpmsg = WeixinUtil.httpRequest(url, requestMethod, outputStr);System.out.println("拉取用户信息返回消息=="+httpmsg);WechatMsg msg = JSON.parseObject(httpmsg, WechatMsg.class);return msg;} 然后在网页端,则是需要编写H5页面,进行自己网站和微信用户的关联,我这里是使用手机号,用户输入手机号,进行判断,如果注册过就直接关联,如果用户没有注册则进行注册后关联,完成后跳转到会员中心。

详解微信开发模式之自定义菜单实现代码以上就是详解微信开发模式之自定义菜单实现代码的详细内容,更多请关注小潘博客其它相关文章!