1. 程式人生 > >微信小程式從入門第一講 java&&jFinal 小程式登陸功能實現以及獲取唯一標識openid和unionid

微信小程式從入門第一講 java&&jFinal 小程式登陸功能實現以及獲取唯一標識openid和unionid

在我以前的一篇部落格中講到了獲取openid的方法,這裡就不做過多的講解java獲取微信小程式openid。這裡主要講解微信小程式登陸的實現和獲取unionid。需要提醒的是我後端框架使用的是jFinal,傳值方式跟spring的那套有些許的差別。

1、首先要知道微信小程式的開發本身就是基於微信端的開發,可以算是跨域的一種操作,官方推薦的後端語言是node.js和php,這裡用到的伺服器語言是java,開始

2、這裡引用一張圖片是來自於https://blog.csdn.net/yelin042/article/details/71773636這篇博主的文章,當然我使用的登陸功能是使用redis儲存。

登陸講解圖

自認為這個登陸的講解還是比較詳細的。首先理解思路,很簡單在登陸成功了以後再java端把使用者的資訊儲存在redis然後生成的key傳到小程式端儲存起來,在下次需要使用使用者資訊的時候從小程式的快取中查詢,然後去java端查詢使用者資訊,記得是先從redis中查詢

3、首先是java端程式碼

 public void auth() {
        Cache bbs = Redis.use();
        int loginid = getParaToInt("loginid", 0);
        //根據小程式端傳過來的快取id,這個id是在java端生成的id
        BuyerUser buyerU = bbs.get(loginid);
        if (buyerU == null) {
            String grant_type = "authorization_code";
            //URL
            String requestUrl = "https://api.weixin.qq.com/sns/jscode2session?";
            String code = getPara("js_code");
            String encryptedData = getPara("encryptedData");
            String iv = getPara("iv");

            //請求引數
            String params = "appid=" + AppId + "&secret=" + AppSecret + "&js_code=" + code + "&grant_type=" + grant_type;
            //傳送請求
            String data = HttpUtils.get(requestUrl + params);
            //解析相應內容(轉換成json物件)
            JSONObject json = JSONObject.fromObject(data);
            //使用者的唯一標識(openid),這裡需要一個解密,下面會說明怎麼進行解密的
              String Openid = String.valueOf(json.get("openid"));
            com.alibaba.fastjson.JSONObject ins = WXUtils.getUserInfo(encryptedData, String.valueOf(json.get("session_key")), iv);
            System.out.println(ins + "-=-=-=-=-=-=-");
            String unionId = String.valueOf(ins.get("unionId"));

            BuyerUser user = BuyerUser.dao.findFirst("select * from " + BuyerUser.TABLE_NAME + " where unionid=?", unionId);

            if (user == null) {
				//使用者資訊儲存在資料庫中
                BuyerUser buyerUser = new BuyerUser();
                buyerUser.save();
                bbs.set(buyerUser.getId(), buyerUser);
                setAttr("loid", buyerUser.getId());

            } else {
				//更新快取
                user.setUnionid(unionId);
                user.update();
//                bbs.hset(CACHE_NAME, user.getId(), user);
                bbs.set(user.getId(), user);
                setAttr("loid", user.getId());
            }
            // index();
        } else {  
        }
        renderJson();
    }

4、上面程式碼中牽扯到union的一個解密,這裡需要提示一下union的獲取途徑,我所使用的是微信開放平臺繫結小程式,因為公司牽扯到好幾個公眾號需要使用者資訊統一所以使用開放平臺保證資訊的統一

unionid獲取方式

5、uninon解密,需要導幾個包

  <dependency>
        <groupId>net.sf.json-lib</groupId>
        <artifactId>json-lib</artifactId>
        <version>2.4</version>
            <classifier>jdk15</classifier>
        </dependency>

        <dependency>
            <groupId>org.codehaus.xfire</groupId>
            <artifactId>xfire-core</artifactId>
            <version>1.2.6</version>
        </dependency>

        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk16</artifactId>
            <version>1.46</version>
        </dependency>

程式碼

public class WXUtils {
    public static JSONObject getUserInfo(String encryptedData, String sessionKey, String iv){
        // 被加密的資料
        byte[] dataByte = Base64.decode(encryptedData);
        // 加密祕鑰
        byte[] keyByte = Base64.decode(sessionKey);
        // 偏移量
        byte[] ivByte = Base64.decode(iv);

        try {
            // 如果金鑰不足16位,那麼就補足.  這個if 中的內容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, "UTF-8");
                return JSONObject.parseObject(result);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

 

6、小程式端,只寫核心程式碼,這裡需要講解一個我裡面的ht程式碼我的域名,這裡需要自己解決 ,開個內網對映都行然後把微信開發者工具裡面的https校驗去掉就ok啦。

  // 檢視是否授權
    wx.getSetting({
      success: function(res) {
        if (res.authSetting['scope.userInfo']) {
          //使用者已經授權過,直接跳轉到主頁面就可以啦
          wx.reLaunch({
            url: '../index/index',
            success: function(res) {
             // console.log("呼叫成功")
            },
            fail: function(res) {
             // console.log("呼叫失敗")
            }
          });
          var that = this;

          //已經失效重新登入獲取
          wx.login({
            success: function (ress) {
              wx.getUserInfo({
                success: function (res) {
                  //從快取中讀取快取的key
                  wx.getStorage({
                    key: 'loginid',
                    success: function (resp) {
                     // console.log("檢視目前的loginid:" + resp.data)
                    },
                    //第一次進入小程式肯定是失敗的
                    fail: function () {
                      wx.request({
                        url: ht + '/auth.html',
                        data: {
                          encryptedData: res.encryptedData,
                          iv: res.iv,
                          js_code: ress.code,
                          loginid: 0
                        },
                        method: 'GET',
                        success: function (resd) {
                          //console.log(resd.data.loid + "登入的id")
                          // console.log(res.data.openid)
                          //把rediskey儲存在小程式的快取中
                          wx.setStorage({
                            key: 'loginid',
                            data: resd.data.loid,

                          })
                          //儲存快取以後重新重新整理頁面就可以獲取到快取中id後臺查詢資料
                          // wx.reLaunch({
                          //   url: '../index/index',
                          //   success: function (res) {
                          //     console.log("呼叫成功")
                          //   },
                          //   fail: function (res) {
                          //     console.log("呼叫失敗")
                          //   }
                          // })

                        },
                        fail: function () {
                         // console.log("拉去使用者資訊失敗")
                        }
                      })
                    }
                  })
                },
                fail: function (res) {
                //  console.log("獲取使用者資訊失敗")
                }
              });
            }
          })
        } else {
        //  console.log("還沒有授權")
        }
      }
    })