首頁 >微信小程式 >小程式開發 >java實作微信小程式登入態維護

java實作微信小程式登入態維護

不言
不言原創
2018-06-23 13:39:442833瀏覽

本篇文章主要介紹了java實作微信小程式登入態維護的範例程式碼,具有一定的參考價值,有興趣的可以了解一下

相信不少喜歡開發的朋友都已經知道微信小程式是什麼物種了,樓主也是從小程式內測期間就開始關注,也寫過幾個已經上線的微信小程式。但基本上都是寫的純前端,最近樓主從後端到前端寫一個完整的小程序項目,中間碰到了一些問題,樓主會找一些個人覺得有學習價值的點不定時的拿出來跟大家分享,希望對你有一些幫助。

本次就從最基本的微信小程式登入態維護開始吧。小程式官方api文檔裡面有對登入態的一個完整的解釋,並且有相關的程式碼。想看詳情,可以出門右轉:https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html#wxloginobject 第一次看的時候沒怎麼看懂,程式碼沒有提供java版本的,這讓一個java程式設計師情何以堪,所以在努力研究了以後決定要做一個java版本的簡單的demo放出來。

作為服務端,如果想獲得到使用微信小程式的會員訊息,就需要小程式作為客戶端把會員的基本資訊傳過來。類似於手機號,openId可以作為目前小程式中使用者的唯一性標誌。然而如果把會員的openId訊息明文直接在服務端與小程式端來回傳輸的話,會有安全性的問題。萬一被別人得到這個openId,就等於得到會員的手機號碼一樣,就可以做一些其他操作了,顯然是不安全的。

為了解決這個問題微信採用了相對安全的方式。

//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)
    }
   }
  });
 }
})

微信小程式端會呼叫wx.login的api,然後會得到一個code,這個code對外人來講是沒有任何意義的,可以放心的傳給服務端。服務端得到code以後,加上你申請小程式時的appId, app secret,去調微信的介面

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

就可以得到下列參數:

  • ##openid 使用者唯一識別

  • session_key 會話金鑰

  • unionid 本欄位在滿足一定條件的情況下才回傳

其中openid 就是會員的唯一性標記,此時服務端可以保存下來。


session_key 以後解密 unionId(整個開放平台會員的唯一性識別)時有用。

服務端得到openid以後,為了後方的交互,要保存下來。一般來講有兩種方式:一種是直接入資料庫,一種是採用效率高一點的快取。樓主採用的是後者,方式是redis。

依照微信的建議此時需要產生一個不重複值作為openId的唯一性識別。這裡採用的是java的uuid。然後把這個uuid值當key,把openid以及後面會用到的session_key當value,存進redis。並且把uuid值回傳給小程式。這樣小程式就可以直接拿uuid值跟服務端互動。

也許會有人問,如果有人得到uuid值其實跟得到openid沒什麼區別啊,都相當於是會員的唯一性標誌。

所以這裡要對這個uuid值做一個處理。首先存入redis時要有時效性。 session_key在微信伺服器有效期限是30天,建議服務端快取session_key不超過30天。當小程式傳過來的uuid值過期時,認為這是過期的uuid,則重新走wx.login步驟。

為了方便redis中不僅會寸uuid與openid的對應關係。還會再存一條openid對應uuid的記錄,目的是為了下一次重新wx.login步驟時根據openid找到之前老的uuid,如果存在的話就刪掉,然後查詢一條新的uuid值,並且把openid對應的這條記錄也更新掉。這樣redis伺服器中就不會有多餘的髒數據,減輕伺服器的負擔。

以上就是我理解的整個登入態的過程,當然還有wx.checkSession這些沒有講到,其實就是發現session_key失效是再重新走一遍上述的流程就可以了。所以沒有仔細說。不知道我有沒有講清楚。我會把整個流程的關鍵程式碼貼出來,供大家參考。

@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);
          }

        }
      }
    }
  }

專案框架是我比較喜歡Jfinal,java輕量級急速開發框架,非常高效,也推薦給大家。可能有哪些遺漏的地方歡迎大家積極提出意見和批評。

以上就是本文的全部內容,希望對大家的學習有所幫助,更多相關內容請關注PHP中文網!

相關推薦:

關於微信小程式的登陸流程

#微信小程式之小豆瓣圖書的介紹

#

以上是java實作微信小程式登入態維護的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn