Home  >  Article  >  WeChat Applet  >  Java implements WeChat applet login state maintenance

Java implements WeChat applet login state maintenance

不言
不言Original
2018-06-23 13:39:442779browse

This article mainly introduces the sample code of java to implement WeChat applet login state maintenance. It has certain reference value. Those who are interested can learn about it.

I believe that many friends who like development already know WeChat. What kind of species are mini programs? The author has been paying attention to mini programs since the internal testing period, and has also written several WeChat mini programs that have been launched. But basically they are written purely on the front-end. Recently, the poster wrote a complete small program project from the back-end to the front-end, and encountered some problems in the process. The poster will find some points that he thinks are valuable for learning and share them with everyone from time to time. , hope it will be of some help to you.

This time, let’s start with the most basic WeChat applet login state maintenance. The official API document of the mini program contains a complete explanation of the login state and relevant code. If you want to see the details, you can go out and turn right: https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html#wxloginobject I didn’t understand much the first time I looked at it, and the code There is no Java version provided, which makes a Java programmer feel embarrassed, so after hard research, I decided to make a simple demo of the Java version and release it.

As a server, if you want to obtain member information using a WeChat applet, you need the applet as a client to pass the member's basic information. Similar to a mobile phone number, openId can be used as a unique identifier for the user in the current mini program. However, if the clear text of the member's openId information is directly transmitted back and forth between the server and the applet, there will be security issues. If someone else gets this openId, it is equivalent to getting the member's mobile phone number, and you can do some other operations, which is obviously unsafe.

In order to solve this problem, WeChat has adopted a relatively safe method.

//app.js
App({
 onLaunch: function() {
  wx.login({
   success: function(res) {
    if (res.code) {
     //发起网络请求
     wx.request({
      url: 'https://test.com/onLogin',
      data: {
       code: res.code
      }
     })
    } else {
     console.log('获取用户登录态失败!' + res.errMsg)
    }
   }
  });
 }
})

The WeChat applet will call the api of wx.login, and then get a code. This code has no meaning to outsiders. You can Pass it to the server with confidence. After the server gets the code, add the appId and app secret you used when applying for the mini program to adjust the WeChat interface

https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret= SECRET&js_code=JSCODE&grant_type=authorization_code

You can get the following parameters:

  • openid User unique identification

  • session_key session Key

  • unionid This field will only return if certain conditions are met

where openid is the unique tag of the member. At this time, the service end can be saved.

session_key will be useful later when decrypting the unionId (the unique identifier of the entire open platform member).

After the server obtains the openid, it must be saved for subsequent interactions. Generally speaking, there are two ways: one is to directly enter the database, and the other is to use a more efficient cache. The poster uses the latter, using redis.

According to WeChat's suggestion, you need to generate a unique value as the unique identifier of openId. The uuid of java is used here. Then use this uuid value as key, openid and session_key that will be used later as value, and store them in redis. And return the uuid value to the applet. In this way, the applet can directly use the uuid value to interact with the server.

Some people may ask, if someone gets the uuid value, it is actually no different from getting the openid. It is equivalent to the unique identifier of the member.

So here we need to process this uuid value. First of all, it must be timely when storing in redis. The session_key is valid for 30 days on the WeChat server. It is recommended that the server cache the session_key for no more than 30 days. When the uuid value passed by the applet expires, it is considered to be an expired uuid, and the wx.login step is repeated.

In order to facilitate redis, there is not only the corresponding relationship between uuid and openid. Another record of openid corresponding to uuid will be saved. The purpose is to find the previous old uuid based on openid when re-wx.login step next time. If it exists, delete it, then query a new uuid value, and put the corresponding openid This record is also updated. In this way, there will be no redundant dirty data in the redis server, reducing the burden on the server.

The above is what I understand about the entire login process. Of course, wx.checkSession has not been mentioned. In fact, if you find that session_key is invalid, you can just go through the above process again. So I didn’t say it in detail. I don't know if I made it clear. I will post the key code of the entire process for your reference.

@ActionKey("/loginByWeixin")
  public void loginByWeixin() throws Exception {
    logger.info("Start getSessionKey");
    String json = HttpKit.readData(getRequest());
    JSONObject reqJson = JSON.parseObject(json);
    String jsCode = reqJson.getString("code");
    if (jsCode == null || "".equals(jsCode)) {
      logger.info("缺少必要参数");
      renderJson(new OutRoot().setCode("100").setMsg(SYS.PARAMETER_FAIL));
    } else {
      List<Record> record = appInfoService.selectAppInfo();
      String appId = record.get(0).get("app_id");
      String appSecret = record.get(0).getStr("app_secret");
      if (appId == null || "".equals(appId) || appSecret == null || "".equals(appSecret)) {
        logger.info("缺少必要参数");
        renderJson(new OutRoot().setCode("100").setMsg(SYS.PARAMETER_FAIL));
      } else {
        String url = "https://api.weixin.qq.com/sns/jscode2session";
        String httpUrl = url + "?appid=" + appId + "&secret=" + appSecret + "&js_code=" + jsCode
            + "&grant_type=authorization_code";
        String ret = HttpRequest.sendGetRequest(httpUrl);
        logger.info("微信返回的结果 {}", ret);
        if (ret == null || "".equals(ret)) {
          logger.info("网络超时");
          renderJson(new OutRoot().setCode("101").setMsg(SYS.CONTACT_FAIL));
        } else {
          JSONObject obj = JSONObject.parseObject(ret);
          if (obj.containsKey("errcode")) {
            String errcode = obj.get("errcode").toString();
            logger.info("微信返回的错误码{}", errcode);
            renderJson(new OutRoot().setCode("101").setMsg(SYS.CONTACT_FAIL));
          } else if (obj.containsKey("session_key")) {
            logger.info("调微信成功");
            // 开始处理userInfo
            String openId = obj.get("openid").toString();
            Record tbMember = new Record();
            tbMember.set("weixin_openid", openId);
            System.out.println("openId==" + openId);
            // 先查询openId存在不存在,存在不入库,不存在就入库
            List<Record> memberList = tbMemberService.selectMember(tbMember);
            if (memberList != null && memberList.size() > 0) {
              logger.info("openId已经存在,不需要插入");
            } else {
              JSONObject rawDataJson = reqJson.getJSONObject("userInfo");
              String nickName = rawDataJson.getString("nickName");
              String avatarUrl = rawDataJson.getString("avatarUrl");
              String gender = rawDataJson.getString("gender");
              String province = rawDataJson.getString("province");
              String city = rawDataJson.getString("city");
              String country = rawDataJson.getString("country");
              tbMember.set("gender", gender);
              tbMember.set("nick_name", nickName);
              tbMember.set("avatar_url", avatarUrl);
              Long openId2 = tbMemberService.addMember(tbMember);
              logger.info("openId不存在,插入数据库");
            }
            // (1) 获得sessionkey
            String sessionKey = obj.get("session_key").toString();
            logger.info("sessionKey==" + sessionKey);
            logger.info("openId==" + openId);
            // (2) 得到sessionkey以后存到缓存,key值采用不会重复的uuid
            String rsession = UUID.randomUUID().toString();
            Cache tokenCache = Redis.use("redis_00");
            // (3) 首先根据openId,取出来之前存的openId对应的sessionKey的值。
            String oldSeesionKey = tokenCache.getJedis().get(openId);
            if (oldSeesionKey != null && !"".equals(oldSeesionKey)) {
              logger.info("oldSeesionKey==" + oldSeesionKey);
              // (4) 删除之前openId对应的缓存
              tokenCache.getJedis().del(oldSeesionKey);
              logger.info("老的openId删除以后==" + tokenCache.getJedis().get(oldSeesionKey));
            }
            // (5) 开始缓存新的sessionKey: key --> uuid, value --> sessionObj
            JSONObject sessionObj = new JSONObject();
            sessionObj.put("openId", openId);
            sessionObj.put("sessionKey", sessionKey);
            tokenCache.getJedis().set(rsession, sessionObj.toJSONString());

            // (6) 开始缓存新的openId与session对应关系 : key --> openId , value --> rsession
            tokenCache.getJedis().set(openId, rsession);

            String newOpenId = tokenCache.getJedis().get(openId);
            String newrSession = tokenCache.getJedis().get(rsession);
            logger.info("新的openId==" + newOpenId);
            logger.info("新的newrSession==" + newrSession);
            // (7) 把新的sessionKey返回给小程序
            JSONObject objret = new JSONObject();
            objret.put("rdSessionKey", rsession);
            objret.put("errno", 0);
            renderJson(objret);
          }

        }
      }
    }
  }

The project framework is that I prefer Jfinal, a java lightweight rapid development framework, which is very efficient and recommended to everyone. If there may be any omissions, you are welcome to actively provide comments and criticisms.

The above is the entire content of this article. I hope it will be helpful to everyone's study. For more related content, please pay attention to the PHP Chinese website!

Related recommendations:

About the login process of WeChat Mini Program

Introduction to Xiaodouban Books of WeChat Mini Program

The above is the detailed content of Java implements WeChat applet login state maintenance. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn