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

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

Jun 23, 2018 pm 01:39 PM
java微信小程式登入

本篇文章主要介紹了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

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版