최근 WeChat 공식 계정과 자체 웹 사이트 사용자 간의 사용자 연결 인증 로그인 기능을 구현했습니다. 주요 목적은 사용자가 공식 계정을 팔로우하고 회원 센터를 클릭하고 필요한 웹 페이지 인증을 수행하는 것입니다. 관련 권한이 팝업됩니다: OAuth2.0 웹 페이지 권한 부여, 그러면 사용자는 사용자 정보 획득에 동의하고 사용자를 웹사이트에 연결한 다음 사용자는 WeChat을 사용하여 로그인할 수 있습니다.
이번에는 Java 프로세스에서 Action 레이어를 수행하고 있습니다.
1. 사용된 도구:
1. ngrok, 언제든지 테스트하고 개발할 수 있도록 자신의 로컬 머신을 공용 네트워크에 매핑합니다. 🎜 >
1. http://www.tunnel.mobi/에서 ngrok를 다운로드합니다. 2. 파일을 Tomcat 디렉터리에 넣고 cmd 8080에서 ngrok -config ngrok.cfg -subdomain xinzhi를 실행합니다. 3. ngrok 도구는 MOOC.com @LAOBI에서 볼 수 있는 입니다. 2. WeChat 공개 계정 테스트 계정, 언제든지 테스트하고, 먼저 테스트 계정에 문제가 없는지 확인하기 전에 2. 를 사용하여 Java에서 Http 요청을 보낸 다음JSON 매개변수를 반환하고 JSON 매개변수를 얻은 다음 처리합니다.
먼저, 호출하거나 교체할 수 있도록 공개 계정 테스트 계정을 속성 파일에 넣습니다. 예: 에 https속성 코드를 사용하세요.
AppID = wxf00**c3dd2ebfa0 AppSecret = 3cb220755f****506dc35391aa5c03ec url = 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; } }WeChat은 매개변수의 POJO 클래스를 반환합니다:
Java 코드
private String openid; //用户的唯一标识 private String nickname;//用户昵称 private Integer sex;// 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知 private String province;//用户个人资料填写的省份 private String city;//普通用户个人资料填写的城市 private String country;// 国家,如中国为CN private String headimgurl; // 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。 private String privilege;// 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom) private String unionid;// 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。详见:获取用户个人信息(UnionID机制) private String access_token;권한 부여 자격 증명 확인 클래스:
Java 코드
private String errcode; private String errmsg;코드
Java 코드
private String access_token; private String expires_in; private String refresh_token; private String openid; private String scope; private String unionid;를 통해 웹페이지 승인 access_token을 교환합니다. WeChat 아바타의 경우 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(Exception e){ System.out.println(e.toString()); }finally{ try{ bos.flush();//刷新此缓冲的输出流。 bis.close(); //关闭此输入流 。 }catch(Exception e){ System.out.println(e.toString()); } } }이제 기본 작업이 완료되었으므로 코드를 개발하고 다음 단계에 따라 개발합니다.
1단계: 사용자가 코드 승인 및 획득에 동의합니다
여기에 있는 URL이 전면입니다. 속성에서 준비한 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"); //如果用户授权成功则跳转到此url String loginUrl = ""+urlOpen+"/zhtx-wap/weixin/getAccessToken"; //用户授权,获取code String 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 redirect return "redirect:"+url+""; }
Java代码
/** * 通过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 */ //用户授权,获取code url = "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) */ //用户授权,获取code String 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 redirect return "/jsp/wechat/wechatregister"; }</wechatuser>
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()); //存入微信openid userReg.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"; }</userregister></wechatuser>
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页面,进行自己网站和微信用户的关联,我这里是使用手机号,用户输入手机号,进行判断,如果注册过就直接关联,如果用户没有注册则进行注册后关联,完成后跳转到会员中心。
위 내용은 WeChat 개발 모델의 사용자 정의 메뉴 구현 코드에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!