zoukankan      html  css  js  c++  java
  • 微信小程序分享及信息追踪

    我就是个搬用工—来源:https://www.jianshu.com/p/87a75ec2fd53

    小程序分享群及信息追踪

    需求

    1. 页面分享

    ​ 小程序页面分享链接增加source参数,值为用户ID加密,分享出去的链接类似/pages/live/live?id=10109&source=1ada812s

    ​ 分享时自定义分享文案、链接、封面图

    ​ 分享完成后获取分享信息,能获取到群ID算成功,做一次上报,记录该用户分享的信息

    1. 追踪

    ​ 群用户打开分享的卡片后,获取链接中的source参数做一次上报,记录哪些用户打开小程序

    ​ 用户在此页面观看30s之后再做一次上报

    实现

    页面分布:

    • live.js 小程序某页面
    • app.js 小程序首页

    代码分析:

    由于代码中有很多不相关的部分,所以分析的过程中,尽可能的省略掉不相关的代码部分,以求更清晰的了解整个分享过程。

    第一次上报

    整个需求开发中,出现三次需要上报情况,可以将上报定义为同一个函数,根据不同的入参,做不同的事。live.js中上报函数代码如下:

    upload_share_Result(res, type, uid) {
        let share_event = apiUrl.share_event    // 获取接口
        let token = Store.getState().updateToken    // 获取登录用户token
        let params = {
            token,  // 登录用户的token
            //转发群事件 :type=1; 进入直播间事件 :type=2; 进入直播间30s事件 :type=3
            type,
            uid,    // 记录来源,如果在小程序打开,来源为空;如果从别人分享的打开,来源别人的uid
            encryptedData: res ? res.encryptedData : '',    // 分享到群的群消息
            iv: res ? res.iv : ''       // 分享到群的群消息
        }
        Request(share_event, params, 'post').then((res) => {
           //...
        }).catch((res) => {
           //...
        })
    },

    首先我们需要了解小程序转发的API,包括是否带有群标识、以及如何获取群标识、如何解密群信息等。接下来我们会一点点分析。

    live.js中实现转发分享思路和代码如下:

    首先保证live页面显示分享按钮,且能够带有ShareTicket的转发

    /*
    *  生命周期函数--监听页面加载
    */
    onLoad: function (options) {
        // 显示当前页面的转发按钮
        wx.showShareMenu({
          // 是否使用带 shareTicket 的转发
          withShareTicket: true
        })
    }

    然后在live.js中调用onShareAppMessage,来实现自定义转发的信息。然后再通过getShareInfo来获取需要的群信息。具体API可见官网onShareAppMessage & getShareInfo

    /**
    * 用户点击右上角分享
    */
    onShareAppMessage: function () {
        let _this = this
        let uid = Store.getState().updateUid        // 获取redux中的用户uid
        return {
            title: this.data.title,
            // 分享路径,房间名+用户uid
            path: `/pages/live/live?id=${this.data.roomid}&source=${uid}`,
            imageUrl: this.data.shareImage,
            // 转发成功的回调函数
            success: function (res) {
                // 分享给个人:{errMsg: 'shareAppMessage:ok'}
                // 分享给群:{errMsg: 'shareAppMessage:ok', shareTickets: Array(1)}
                /* shareTicket 数组
                 * 每一项是一个 shareTicket(是获取转发目标群信息的票据) ,对应一个转发对象
                 */
                var shareTicket = (res.shareTickets && res.shareTickets[0]) || ''
                /* 官网的Tip: 由于策略变动,小程序群相关能力进行调整,
                 * 开发者可先使用wx.getShareInfo接口中的群ID进行功能开发。
                 */
                wx.getShareInfo({
                    // 把票据带上
                    shareTicket: shareTicket,
                    success: function (res) {
                        // 如果从小程序分享没有source,如果从别人分享的再二次分享带有source
                        // 后续会讲_this.data.source的来源
                        let source = _this.data.source ? _this.data.source : '';
                        // 上报给后台,把群信息带给后台,后台会去解密得到需要的信息
                        _this.upload_share_Result(res, '1', source)
                    }
                })
            },
            fail: function (res) {
            }
        }
    }

    以上部分已经可以实现基本的分享到群,然后获取群信息,并且完成第一次上报。

    后续上报

    接下来说一下,当一个用户打开别人分享的小程序,并接受授权或者已有授权的情况下,如何完成第二次、第三次上报,代码依旧在live.js中。

    onLoad: function (options) {
        let _this = this;
        this.setData({
            // 获取小程序url中的source,记录此小程序是谁分享的;也可能不存在source
            roomid: options.id,
            source: options.source
        }, function () {
            //...
        })
    
        // 给全局添加回调函数,当用户没有已授权的状态,需要点击·授权·按钮后,此时执行回调函数
        app.getInfoCb = function () {
            if (options.source) {
                // 第二次上报,如果有options.source,则记录谁分享的
                _this.share_event_req(null, '2', options.source)
                // 第三次上报,如果有options.source,则记录谁分享的
                setTimeout(() => {
                    _this.share_event_req(null, '3', options.source)
                }, 30 * 1000)
            }
        }
        // 如果用户已授权状态,未删除小程序,直接执行
        if (Store.getState().updateUid) {
            app.getInfoCb()
        }
    }

    那么点击授权按钮后,执行回调函数又如何操作呢?此时移步至app.js

    App({
       postLogin(cdoe, iv, encryptedData) {
           let params = {
               code : cdoe,
               iv: iv,
               encryptedData: encryptedData
           }
           let _this = this;    // this指向App对象
           Request(apiUrl.postLogin, params, 'post').then(
               (res) => {
                   wx.hideLoading()
                   if(res.code === 1){
                       // ...
                       // 如果存在全局getInfoCb,则执行
                       _this.getInfoCb && _this.getInfoCb()     
                   }
               }
           )
       } 
    })

    仔细的看上面的代码会发现,全局回调中执行的方法share_event_req并不是我们最初定义的公共的upload_share_Result。如果直接调用upload_share_Result方法就可以直接上报了,那为什么还需要调用share_event_req呢?这个share_event_req方法中有做了什么处理呢?我们接着分析,代码在live.js中:

    share_event_req(res, type, uid) {
        let _this = this;
        // 如果全局存在shareTicket票据的话,重新执行getShareInfo获取票据中带有的群信息
        // 并且上报给后台,让后台去解析群信息
        // 官网:当用户将小程序转发到任一群聊之后,可以获取到此次转发的 shareTicket,此转发卡片在群聊中被其他用户打开时,可以在 App.onLaunch() 或 App.onShow 获取到另一个 shareTicket。这两步获取到的 shareTicket 均可通过 wx.getShareInfo() 接口可以获取到【相同】的转发信息。
        // 也就是说,A转发到某群,只有B从此群中打开才能算是A的二次上报;但是B再次转发到此群,C从此群打开上报,则不算B上报成功了。这样防止用户群中互相刷。
        if (app.globalData.shareTicket) {
            wx.getShareInfo({
                shareTicket: app.globalData.shareTicket,
                success: function (res) {
                    _this.upload_share_Result(res, type, uid);
                }
            })
        } else {
            // 如果全局不存在shareTicket的话,直接调用upload_share_Result上报
            self.upload_share_Result(null, type, uid);
        }
    }

    那么按照官网说的,全局的shareTicket是在App.onLaunch() 或 App.onShow() 中获取的。

    App({
        onShow: function (options) {
            // this指向App对象
            this.globalData.shareTicket = options.shareTicket
        }
    })

    总结

    • 用户A从小程序第一次分享到群,把分享的群信息和空的source传给后台上报。 ✅
    • 用户A从小程序第一次分享到个人,获取不到shareTicket,不会上报。
    • 用户B从此群打开小程序获取到全局shareTicket。
      • 如果已有授权执行全局回调,把此shareTicket信息和source=A上报给后台 ✅
      • 如果没有授权,点击授权执行全局回调,把此shareTicket信息和source=A上报给后台 ✅
    • 当用户B在此小程序停留30s,把此shareTicket信息和source=A上报给后台 ✅
    • 用户B再次分享到此群,把分享的群信息和source=A传给后台上报,群信息相同。❎
    • 用户C打开用户B分享的小程序获取到全局shareTicket。
      • 如果已有授权执行全局回调,把此shareTicket信息和source=B上报给后台。 ❎
      • 如果没有授权,点击授权执行全局回调,把此shareTicket信息和source=B上报给后台 ❎
  • 相关阅读:
    BZOJ3752 : Hack
    XIV Open Cup named after E.V. Pankratiev. GP of SPb
    XIII Open Cup named after E.V. Pankratiev. GP of Ukraine
    BZOJ2087 : [Poi2010]Sheep
    BZOJ2080 : [Poi2010]Railway
    BZOJ2082 : [Poi2010]Divine divisor
    Moscow Pre-Finals Workshop 2016. National Taiwan U Selection
    XIII Open Cup named after E.V. Pankratiev. GP of Asia and South Caucasus
    XIII Open Cup named after E.V. Pankratiev. GP of Azov Sea
    XIII Open Cup named after E.V. Pankratiev. GP of SPb
  • 原文地址:https://www.cnblogs.com/LChenglong/p/9685616.html
Copyright © 2011-2022 走看看