云開(kāi)發(fā) CloudID與動(dòng)態(tài)消息

2020-07-22 15:32 更新

開(kāi)通了云開(kāi)發(fā)的小程序可以使用Cloud.CloudID接口返回一個(gè) CloudID(開(kāi)放數(shù)據(jù) ID)特殊對(duì)象,將該對(duì)象傳至云函數(shù)就可以獲取其對(duì)應(yīng)的開(kāi)放數(shù)據(jù),比如獲取微信運(yùn)動(dòng)的步數(shù)、手機(jī)號(hào)等開(kāi)放數(shù)據(jù),而這個(gè)功能如果是使用非云開(kāi)發(fā)的方式除了需要處理登錄的問(wèn)題,還需要進(jìn)行加解密,十分繁瑣。

一、獲取微信步數(shù)

獲取微信運(yùn)動(dòng)步數(shù)的小程序接口為wx.getWeRunData,可以獲取用戶過(guò)去三十天微信運(yùn)動(dòng)步數(shù)。使用可開(kāi)發(fā)者工具新建一個(gè)頁(yè)面頁(yè)面比如openData,然后在openData.wxml里輸入一個(gè)button按鈕:

<button bindtap="getWeRunData">獲取微信步數(shù)</button>

然后再在openData.js里輸入以下代碼,我們用事件處理函數(shù)getWeRunData來(lái)調(diào)用wx.getWeRunData接口,并打印結(jié)果。

getWeRunData(){
  wx.getWeRunData({
    success: (result) => {
      console.log(result)
    },
  })
}

編譯之后,點(diǎn)擊按鈕,我們可以在控制臺(tái)看到返回的res對(duì)象里有encryptedData包括敏感數(shù)據(jù)在內(nèi)的完整用戶信息的加密數(shù)據(jù)、iv加密算法的初始向量, cloudID敏感數(shù)據(jù)對(duì)應(yīng)的云 ID.

{errMsg: "getWeRunData:ok", 
encryptedData: "ABeBwlCHs....6PvAax", 
iv: "g8QPFXTLLD3N6Zn3YiuwEQ==", 
cloudID: "30_jVhZr_Up-8_TV...kgP8yJ8ykN0I"}

這個(gè)cloudID只有在開(kāi)通了云開(kāi)發(fā)的小程序才會(huì)返回,我們可以將cloudID傳入云函數(shù),通過(guò)云調(diào)用就可以直接獲取開(kāi)放數(shù)據(jù)。

使用開(kāi)發(fā)者工具新建云函數(shù)比如opendata,再index.js里輸入以下代碼,并部署上線,在云函數(shù)端接收到的 event 將會(huì)包含對(duì)應(yīng)開(kāi)放數(shù)據(jù)的對(duì)象。

const cloud = require('wx-server-sdk')
cloud.init({
    env: cloud.DYNAMIC_CURRENT_ENV,
})
exports.main = async (event, context) => {
    return event
}

我們?cè)賮?lái)在前面的事件處理函數(shù)getWeRunData里上傳經(jīng)過(guò)cloud.CloudID接口獲得的cloudID對(duì)象,然后調(diào)用opendata云函數(shù),并在success里打印返回來(lái)的對(duì)象,就可以看到包含微信運(yùn)動(dòng)步數(shù)的對(duì)象啦:

getWeRunData(){
  wx.getWeRunData({
    success: (result) => {
      console.log(result.cloudID)
      wx.cloud.callFunction({
        name: 'opendata',
        data: {
          weRunData: wx.cloud.CloudID(result.cloudID), 
        },
        success:(res)=>{
          console.log(res.result.weRunData.cloudID)
          console.log(res.result.weRunData.data.stepInfoList)
        }
      })
    }
  })
}

二、獲取用戶手機(jī)號(hào)

要獲取用戶的手機(jī)號(hào),需要將 button 組件 open-type 的值設(shè)置為 getPhoneNumber,當(dāng)用戶點(diǎn)擊并同意之后,可以通過(guò) bindgetphonenumber 事件回調(diào)獲取到微信服務(wù)器返回的加密數(shù)據(jù),如果開(kāi)通了云開(kāi)發(fā),就能在回調(diào)對(duì)象了獲取到cloudID。使用開(kāi)發(fā)者工具在openData.wxml里輸入如下代碼:

<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button>

然后再在openData.js里輸入以下代碼,我們打印事件處理函數(shù)getPhoneNumber返回的結(jié)果。

  getPhoneNumber (result) {
    console.log("result內(nèi)容",result.detail)
  },

同樣我們也會(huì)獲得一個(gè)類似于微信運(yùn)動(dòng)步數(shù)的返回結(jié)果

{errMsg: "getPhoneNumber:ok", 
encryptedData: "Aw+W76TSvYAPS.....g==", 
iv: "9wSepi6qx...=", 
cloudID: "30_sSext5q.....qmLQ"}

我們?nèi)匀恢恍枰獙@取到cloudID經(jīng)過(guò)cloud.CloudID()接口處理返回的對(duì)象上傳并調(diào)用云函數(shù):

getPhoneNumber (result) {
  wx.cloud.callFunction({
    name: 'opendata',
    data: {
      getPhoneNumber: wx.cloud.CloudID(result.detail.cloudID), 
    },
    success:(res)=>{
      console.log("云函數(shù)返回的對(duì)象",res.result.getPhoneNumber)
    }
  })
},

在getPhoneNumber的data對(duì)象里的phoneNumber是用戶綁定的手機(jī)號(hào)(國(guó)外手機(jī)號(hào)會(huì)有區(qū)號(hào))、purePhoneNumber是沒(méi)有區(qū)號(hào)的手機(jī)號(hào)、countryCode區(qū)號(hào)。

三、獲取微信群ID和群名稱

要獲取微信群ID和群名稱,需要經(jīng)過(guò)一系列相對(duì)比較復(fù)雜的處理,需要經(jīng)過(guò)以下步驟,具體的代碼和開(kāi)發(fā)方式后面會(huì)具體介紹:

  • 首先需要小程序的分享里的withShareTicket: true,分享也必須分享到微信群里;

  • 點(diǎn)擊微信群里的小程序卡片,才能獲取到shareTicket,

  • 然后將shareTicket傳入到wx.getShareInfo里就會(huì)得到微信群敏感數(shù)據(jù)對(duì)應(yīng)的cloudID,

  • 然后我們需要將cloudID通過(guò)wx.cloud.CloudID(cloudID)傳入到云函數(shù),云函數(shù)就可以返回微信群ID,也就是openGId

  • 最后我們需要再通過(guò)<open-data type="groupName" open-gid="{{openGId}}"></open-data>來(lái)顯示群名

1、創(chuàng)建一個(gè)轉(zhuǎn)發(fā)分享

通過(guò)給 button 組件設(shè)置屬性open-type="share",可以在用戶點(diǎn)擊按鈕后觸發(fā)頁(yè)面的生命周期函數(shù)Page.onShareAppMessage事件。首先我們使用開(kāi)發(fā)者工具新建一個(gè)頁(yè)面,比如share,然后再在share.wxml創(chuàng)建一個(gè)button組件,比如:

<button open-type="share">轉(zhuǎn)發(fā)</button>

要獲取群聊的名稱以及群的標(biāo)識(shí)openGId,需要帶shareTicket的轉(zhuǎn)發(fā)才可以,我們?cè)趕hare.js頁(yè)面生命周期函數(shù)onShareAppMessage里輸入如下代碼,設(shè)置withShareTicket為true:

onShareAppMessage: function (res) {
  wx.updateShareMenu({
    withShareTicket: true,
    success(res) {
      console.log(res)
    },
    fail(err) {
      console.log(err)
    }
  })
  if (res.from === 'button') {
    console.log(res.target) //可以在這里將用戶點(diǎn)擊button的次數(shù)存儲(chǔ)到數(shù)據(jù)庫(kù),相當(dāng)于埋點(diǎn)
  }
  return {
    title: '云開(kāi)發(fā)技術(shù)訓(xùn)練營(yíng)',
    path: 'pages/share/share?openid=oUL-m5FuRmuVmxvbYOGuXbuEDsn8',
    imageUrl:"cloud://xly-xrlur.786c-xly-xrlur-1300446086/share.png"http://支持云存儲(chǔ)的fileID
  }
},

關(guān)于顯示右上角菜單的轉(zhuǎn)發(fā)按鈕可以使用wx.showShareMenu接口,而onShareAppMessage除了可以監(jiān)聽(tīng)用戶點(diǎn)擊頁(yè)面內(nèi)的button,也可以監(jiān)聽(tīng)右上角菜單“轉(zhuǎn)發(fā)”按鈕的行為,無(wú)論是哪一種,都可以自定義菜單的title、path、imageUrl等,這里就不具體寫(xiě)代碼啦。

2、獲取shareTickets

值得注意的是,只有轉(zhuǎn)發(fā)到微信群聊中,再通過(guò)微信群聊里的小程序卡片進(jìn)入到小程序才可以獲取到shareTickets返回值,單聊沒(méi)有shareTickets;shareTicket僅在當(dāng)前小程序生命周期內(nèi)有效。但是在開(kāi)發(fā)時(shí),怎么把小程序轉(zhuǎn)發(fā)到微信群里面去呢?開(kāi)發(fā)者工具提供了帶shareTickets的調(diào)試方法。

在開(kāi)發(fā)者工具的模擬器里點(diǎn)擊"轉(zhuǎn)發(fā)"button,就會(huì)出現(xiàn)一個(gè)測(cè)試模擬群列表,我們可以將小程序轉(zhuǎn)發(fā)到一個(gè)群聊里面去,比如測(cè)試模擬群4。調(diào)試時(shí),我們要添加自定義編譯模式,在進(jìn)入場(chǎng)景里選擇1044: 帶 shareTicket 的小程序消息卡片,選擇進(jìn)入的群為你轉(zhuǎn)發(fā)的群,具體可以參考如下圖:

獲取shareTicket,我們可以使用wx.getLaunchOptionsSync()來(lái)獲取小程序啟動(dòng)時(shí)的參數(shù),這個(gè)參數(shù)與App.onLaunch 的回調(diào)參數(shù)一致,而shareTicket就在這個(gè)參數(shù)對(duì)象里。我們可以在share.js的onLoad生命周期函數(shù)里來(lái)獲取它:

onLoad:function (options) {
  const res = wx.getLaunchOptionsSync()
  console.log('小程序啟動(dòng)時(shí)的參數(shù)',res)
  const {shareTicket} = res
  console.log('shareTicket的值',shareTicket)
},

如果你直接使用普通編譯(不使用上面的調(diào)試方法),是獲取不到shareTicket的,shareTicket的值會(huì)為undefined,同時(shí)如果小程序直接加載(而不是通過(guò)點(diǎn)擊群聊里分享的小程序卡片進(jìn)入),shareTicket的值也是undefined

3、獲取cloudID并獲取群IDopenGId

當(dāng)我們獲取到shareTicket之后,就可以調(diào)用wx.getShareInfo接口來(lái)獲取到關(guān)于轉(zhuǎn)發(fā)的信息,尤其是cloudID。然后我們可以把獲取到的CloudID,傳入到云函數(shù),比如share云函數(shù)。

使用開(kāi)發(fā)者工具新建一個(gè)share云函數(shù),在index.js里輸入以下代碼(這個(gè)其實(shí)就是返回event對(duì)象,如此簡(jiǎn)單的云函數(shù)我們可以和其他云函數(shù)合并到一起使用,比如獲取openid等):

const cloud = require('wx-server-sdk')
cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV,
})
const TcbRouter = require('tcb-router');
exports.main = async (event, context) => {
  return event
}

然后再在小程序端share.js的生命周期函數(shù)里繼續(xù)寫(xiě)如下代碼,先判斷shareTicket是否為空(也就是判斷是否是通過(guò)微信群聊小程序卡片進(jìn)入的),然后調(diào)用wx.getShareInfo來(lái)獲取CloudID,再將CloudID傳入到wx.cloud.CloudID()接口,并將該對(duì)象傳至云函數(shù)share就可以返回這個(gè)CloudID對(duì)應(yīng)的開(kāi)放數(shù)據(jù)了(這里的開(kāi)放數(shù)據(jù)主要是openGId)。

onLoad:function (options) {
  const that = this
  const res = await wx.getLaunchOptionsSync()
  const {shareTicket} = res
  if(shareTicket!=null){ //當(dāng)shareTicket不為空時(shí),調(diào)用wx.getShareInfo來(lái)獲取CloudID
    wx.getShareInfo({
      shareTicket:shareTicket,
      success:function (res) {
        const cloudID = res.cloudID
        wx.cloud.callFunction({
          name: 'share',
          data: {
            groupData: wx.cloud.CloudID(cloudID)
          },
          success: function (res) {
            that.setData({
              openGId:res.result.groupData.data.openGId
            })
          }
        })
      }
    })
  }
},

4、顯示群的名稱

openGId為當(dāng)前群的唯一標(biāo)識(shí),也就是每個(gè)微信群都有唯一且不變的這樣一個(gè)ID,可以用于區(qū)分不同的微信群。我們可以把微信群內(nèi)點(diǎn)擊了小程序分享卡片的群成員的用戶信息與這個(gè)openGId相關(guān)聯(lián),這樣就可以弄群排行榜等一些基于微信群的開(kāi)發(fā)。

不過(guò)我們只能獲取微信群的群ID,是不能獲取微信群的名稱的,但是可以通過(guò)開(kāi)放能力來(lái)顯示微信群的名稱,我們只需要把獲取到的openGId字符串傳入到open-gid就可以了。

<open-data type="groupName" open-gid="{{openGId}}"></open-data>

可能你在調(diào)試的時(shí)候會(huì)出現(xiàn),即使你把openGId寫(xiě)入到上面的組件,依然不會(huì)顯示群名,或者使用真機(jī)調(diào)試也無(wú)法顯示,這是因?yàn)闇y(cè)試群或者新建的群,可能會(huì)無(wú)效。

四、動(dòng)態(tài)消息

動(dòng)態(tài)消息發(fā)出去之后,開(kāi)發(fā)者可以通過(guò)后臺(tái)接口修改部分消息內(nèi)容,動(dòng)態(tài)消息也有對(duì)應(yīng)的提醒按鈕,用戶點(diǎn)擊提醒按鈕可以訂閱提醒,開(kāi)發(fā)者可以通過(guò)后臺(tái)修改消息狀態(tài)并推送一次提醒消息給訂閱了提醒的用戶。效果如下所示,這種特別適合我們做搶購(gòu)、拼團(tuán)等運(yùn)營(yíng)活動(dòng):

要讓轉(zhuǎn)發(fā)的小程序卡片里有動(dòng)態(tài)消息,首先需要使用云調(diào)用updatableMessage.createActivityId接口來(lái)創(chuàng)建activityId,然后將activityId和templateInfo傳入到wx.updateShareMenu,而要更新動(dòng)態(tài)消息則需要使用到updatableMessage.setUpdatableMsg的接口。我們可以把創(chuàng)建動(dòng)態(tài)消息和更新動(dòng)態(tài)消息的云函數(shù)使用tcb-router整合到一個(gè)云函數(shù)里面。

1、創(chuàng)建 activityId

使用開(kāi)發(fā)者工具新建一個(gè)云函數(shù),云函數(shù)的名稱為activity,然后在package.json增加tcb-router最新版latest的依賴并用npm install安裝:

"dependencies": {
  "wx-server-sdk":"latest",
  "tcb-router": "latest"
}

以及在config.json里添加云調(diào)用的權(quán)限,用于生成ActivityId以及修改被分享的動(dòng)態(tài)消息:

{
  "permissions": {
    "openapi": [
      "updatableMessage.createActivityId",
      "updatableMessage.setUpdatableMsg"
    ]
  }
}

然后再在index.js里輸入以下代碼,使用createActivityId生成ActivityId并返回:

const cloud = require('wx-server-sdk')
cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV,
})
const TcbRouter = require('tcb-router');
exports.main = async (event, context) => {
  const app = new TcbRouter({event})
  app.use(async (ctx, next) => {
    ctx.data = {}
    await next();
  });
  app.router('getActivityId',async (ctx, next)=>{
    const result = await cloud.openapi.updatableMessage.createActivityId()
    ctx.data.activityID = result
    ctx.body = {"activityID":ctx.data.activityID}
  })
  //后面我們會(huì)介紹如何更新動(dòng)態(tài)消息,updatableMsg的router可以添加在這里
  return app.serve();
}

2、在轉(zhuǎn)發(fā)之前聲明消息類型為動(dòng)態(tài)消息

和前面一樣,我們可以通過(guò)調(diào)用wx.updateShareMenu接口,傳入isUpdatableMessage: true,以及 templateInfoactivityId等參數(shù):

async onShareAppMessage(res) {
  const activityId = (await wx.cloud.callFunction({
    name: 'activity',
    data: {
      $url: "getActivityId", 
    }
  })).result.activityID.activityId
  wx.updateShareMenu({
    withShareTicket: true,
    isUpdatableMessage: true,
    activityId: activityId, 
    templateInfo: {
      parameterList: [{
        name: 'member_count',
        value: '4' //這里的數(shù)據(jù)可以來(lái)自數(shù)據(jù)庫(kù)
      }, {
        name: 'room_limit',
        value: '30' //這里的數(shù)據(jù)可以來(lái)自數(shù)據(jù)庫(kù)
      }]
    }
  })
  return {
    title: 'HackWeek技術(shù)訓(xùn)練營(yíng)',
    path: 'pages/share/share?openid=oUL-m5FuRmuVmxvbYOGuXbuEDsn8',
    imageUrl:"cloud://xly-xrlur.786c-xly-xrlur-1300446086/1572315793633-633.png"
  }
},

3、修改動(dòng)態(tài)消息內(nèi)容

動(dòng)態(tài)消息發(fā)出去之后,我們可以通過(guò)這個(gè)activityId來(lái)追蹤這個(gè)動(dòng)態(tài)消息,當(dāng)用戶進(jìn)入分享的小程序,報(bào)名參與了這個(gè)活動(dòng)時(shí),比如活動(dòng)為拼團(tuán),30人這個(gè)團(tuán)購(gòu)項(xiàng)目就成功啦,現(xiàn)在已經(jīng)有4個(gè)人參與了(可以從數(shù)據(jù)庫(kù)獲得),當(dāng)有新的用戶付費(fèi)參與這個(gè)拼團(tuán)時(shí),我們可以在這個(gè)用戶付費(fèi)的回調(diào)函數(shù)里調(diào)用updatableMessage.setUpdatableMsg這個(gè)接口來(lái)修改動(dòng)態(tài)消息。比如:

wx.cloud.callFunction({
  name: 'activity',
  data: {
    $url: "updatableMsg",
    activityId: activityId, //activityId建議由前端傳入,獲取的方法如上
  }
})

我們繼續(xù)在activity云函數(shù)里添加一個(gè)updatableMsg的router即可

const {activityID} = event
app.router('updatableMsg',async (ctx, next)=>{
  //我們可以用從數(shù)據(jù)庫(kù)拉取現(xiàn)在拼團(tuán)的人數(shù),以及滿團(tuán)的人數(shù),從而確定targetState的狀態(tài)
  const result = await cloud.openapi.updatableMessage.setUpdatableMsg({
    activityID:activityID,
    targetState:0,
    templateInfo: {
      parameterList: [{
        name: 'member_count',
        value: '5' //從數(shù)據(jù)庫(kù)拉取
      }, {
        name: 'room_limit',
        value: '30' //從數(shù)據(jù)庫(kù)拉取
      }]
    }
  })
})

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)