第一版做了知乎视频保存视频到本地相册的功能。进一步我们可以做一个增强功能,支持视频查看。

用户在登录状态下载过的知乎视频,可以在我的浏览

或者查看历史记录

在线查看视频

这个功能的核心其实是用户身份标识的获取,因为我们只要拿到了用户标识,相应用户下载过的视频就可以和用户标识绑定,存储到数据库中。当用户下次再进入app,只要通过用户标识就可以去数据库中拿用户之前下载过的视频就可以了。
表结构如下:

CREATE TABLE `wx_user_zhihu_answer` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `is_delete` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '软删除标识',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `openId_md5` varchar(128) NOT NULL DEFAULT '' COMMENT 'openId md5加密',
  `answer_url` varchar(128) NOT NULL DEFAULT '' COMMENT '知乎回答url',
  PRIMARY KEY (`id`),
  KEY `idx_is_delete` (`is_delete`),
  KEY `idx_openId_md5` (`openId_md5`),
  KEY `idx_answer_url` (`answer_url`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户及知乎回答信息';

获取用户标识

我们借鉴微信的例程来设计用户登录逻辑
首先按钮上设置open-type="getUserInfo",可以让用户自主选择是否授权小程序。

<button class="login-btn" wx:if="{{!hasUserInfo}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo">
  点击登录
</button>

当用户点击并确认授权,会执行回调的getUserInfo方法

getUserInfo: function(e) {
  app.globalData.userInfo = e.detail.userInfo;
  this.setData({
    userInfo: e.detail.userInfo,
    hasUserInfo: true
  });

  // 登录
  wx.login({
    success: res => {
      const { code } = res;
      app.globalData.loginInfo.jsCode = code;
      this.fetchUserIdInfo();
      // 发送 res.code 到后台换取 openId, sessionKey, unionId
    }
  });
  // 获取用户信息
  wx.getSetting({
    success: res => {
      if (res.authSetting["scope.userInfo"]) {
        // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
        wx.getUserInfo({
          success: res => {
            const { encryptedData, iv } = res;
            // 可以将 res 发送给后台解码出 unionId
            app.globalData.loginInfo.encryptedData = encryptedData;
            app.globalData.loginInfo.iv = iv;
            this.fetchUserIdInfo();
          }
        });
      }
    }
  });
},
fetchUserIdInfo() {
  const { jsCode, encryptedData, iv } = app.globalData.loginInfo;
  if (!(jsCode && encryptedData && iv)) {
    return;
  }
  wx.request({
    url: userInfoFetchUrl,
    method: "POST",
    data: {
      jsCode,
      encryptedData,
      iv
    },
    header: {
      "Content-Type": "application/x-www-form-urlencoded"
    },
    success: res => {
      res = res.data;
      if (res.code === 1) {
        app.globalData.userIdInfo = res.data;
      }
    }
  });
},

getUserInfo可以获取用户的信息,调用wx.login能够拿到code,调用wx.getUserInfo能够拿到encryptedData和iv。

拿到code、encryptedData、iv我们就可以调用微信接口以及解码逻辑拿到用户的openId和unionId,我们这部分都放在了后端接口(userInfoFetchUrl)处理,这里我们使用openId标识用户身份,该接口返回的是openId用m5加密后的id。由于所以身份标识相关的操作都在服务器进行且返回的是md5加密后的值,所以极大提高了用户信息的安全性。

后端解析用户标识的逻辑如下

exports.infoFetch = async params => {
  const { jsCode, encryptedData, iv } = params;
  const sessionRes = await axios.get(
    `${jscode2sessionUrl}?appid=${appId}&secret=${appSecret}&js_code=${jsCode}&grant_type=authorization_code`
  );
  const sessionResData = sessionRes.data;
  const sessionKey = sessionResData.session_key;
  const openId = sessionResData.openid;
  const pc = new WXBizDataCrypt(appId, sessionKey);
  const userInfo = pc.decryptData(encryptedData, iv);
  const unionId = userInfo.unionId;
  if (unionId && openId) {
    return {
      openIdMD5: md5(openId),
      unionIdMD5: md5(unionId)
    };
  } else if (openId) {
    return {
      openIdMD5: md5(openId)
    };
  }
  return {};
};

拿到用户标识后工作基本就完成了。我们还需要做一些优化,在app.js的onLaunch回调和登录页onLoad回调中获取用户信息,使得用户再次打开app在有效登录时间内依然可以直接使用用户标识。


小番茄
67 声望5 粉丝