ホームページ >WeChat アプレット >ミニプログラム開発 >Java は WeChat アプレットのログイン ステータスのメンテナンスを実装します

Java は WeChat アプレットのログイン ステータスのメンテナンスを実装します

不言
不言オリジナル
2018-06-23 13:39:442865ブラウズ

この記事では主にWeChatアプレットのログイン状態維持を実装するためのJavaのサンプルコードを紹介しますので、興味のある方はぜひ学んでみてください

WeChatアプレットがどのようなものかをすでに知っている人も多いと思います。 、元の投稿者も内部テスト期間中にミニ プログラムに注目し始め、立ち上げられたいくつかの WeChat ミニ プログラムも作成しました。しかし、基本的にこれらはフロントエンドのみで書かれており、最近、投稿者はバックエンドからフロントエンドまでの完全な小さなプログラムプロジェクトを作成しましたが、その過程でいくつかの問題に遭遇しました。学んで、時々みんなと共有してください。それがあなたのお役に立てば幸いです。

今回は、最も基本的な WeChat ミニプログラムのログイン状態のメンテナンスから始めましょう。ミニ プログラムの公式 API ドキュメントには、ログイン状態と関連コードの完全な説明が含まれています。詳細を見たい場合は、外に出て右に曲がってください: https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html#wxloginobject初めて見たとき、コード Java バージョンが提供されていないため、Java プログラマーとしては恥ずかしい思いをするでしょう。そこで、一生懸命調べた結果、Java バージョンの簡単なデモを作成してリリースすることにしました。

サーバーとしてWeChatアプレットを使用して会員情報を取得したい場合は、クライアントとしてアプレットが会員の基本情報を渡す必要があります。携帯電話番号と同様に、openId は現在のミニ プログラムでユーザーの一意の識別子として使用できます。ただし、メンバーの openId 情報の平文がサーバーとアプレットの間で直接やり取りされる場合、セキュリティ上の問題が発生します。他の人がこの openId を取得すると、メンバーの携帯電話番号を取得したことと同じになり、他の操作ができるようになりますが、これは明らかに安全ではありません。

この問題を解決するために、WeChatは比較的安全な方法を採用しました。

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

WeChat アプレットは、wx.login の API を呼び出し、コードを取得します。このコードは部外者には意味がなく、安心してサーバーに渡すことができます。サーバーがコードを取得したら、ミニ プログラムの申請時に使用した appId とアプリ シークレットを追加して、WeChat インターフェースを調整します

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

は次のパラメータを取得できます:

  • openid ユーザー固有の ID

  • session_key セッションキー

  • unionid このフィールドは、特定の条件が満たされた場合にのみ返されます

openid はどこにありますかメンバーの一意のマーク。サーバーはこの時点でそれを保存できます。

session_key は、後で UnionId (オープン プラットフォーム メンバー全体の一意の識別子) を復号​​化するときに役立ちます。

サーバーが openid を取得したら、その後の対話のために保存する必要があります。一般に、データベースに直接入力する方法と、より効率的なキャッシュを使用する方法の 2 つがあります。投稿者は後者の redis を使用しています。

WeChatの提案によると、openIdの一意の識別子として一意の値を生成する必要があります。ここではJavaのuuidを使用します。次に、この uuid 値をキーとして使用し、openid と後で値として使用する session_key を redis に保存します。そして、uuid 値をアプレットに返します。このようにして、アプレットは uuid 値を直接使用してサーバーと対話できます。

誰かが uuid 値を取得した場合、それは実際にはメンバーの一意の識別子に相当する openid を取得するのと何ら変わらないのではないかと疑問に思う人もいるかもしれません。

したがって、ここでこの uuid 値を処理する必要があります。まず、redis に保存するときはタイムリーでなければなりません。 session_key は WeChat サーバー上で 30 日間有効です。サーバーが session_key をキャッシュする期間は 30 日以内にすることをお勧めします。アプレットによって渡された uuid 値の有効期限が切れると、それは期限切れの uuid とみなされ、wx.login ステップが繰り返されます。

redisを容易にするためには、uuidとopenidの対応関係だけではありません。 uuid に対応する openid の別のレコードが保存されます。その目的は、次回 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);
          }

        }
      }
    }
  }

私は、Java 用の軽量の高速開発フレームワークである Jfinal を好みます。非常に効率的で、誰にでもお勧めします。記載漏れ等ございましたら、積極的にご意見、ご批判をいただければ幸いです。

上記がこの記事の全内容です。その他の関連コンテンツについては、PHP 中国語 Web サイトをご覧ください。

関連おすすめ:

WeChatミニプログラムのログインプロセスについて

WeChatミニプログラムのXiaodouban Booksの紹介

以上がJava は WeChat アプレットのログイン ステータスのメンテナンスを実装しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。