開通了云開發(fā)的小程序可以使用Cloud.CloudID接口返回一個 CloudID(開放數(shù)據(jù) ID)特殊對象,將該對象傳至云函數(shù)就可以獲取其對應(yīng)的開放數(shù)據(jù),比如獲取微信運(yùn)動的步數(shù)、手機(jī)號等開放數(shù)據(jù),而這個功能如果是使用非云開發(fā)的方式除了需要處理登錄的問題,還需要進(jìn)行加解密,十分繁瑣。
獲取微信運(yùn)動步數(shù)的小程序接口為wx.getWeRunData,可以獲取用戶過去三十天微信運(yùn)動步數(shù)。使用可開發(fā)者工具新建一個頁面頁面比如openData,然后在openData.wxml里輸入一個button按鈕:
<button bindtap="getWeRunData">獲取微信步數(shù)</button>
然后再在openData.js里輸入以下代碼,我們用事件處理函數(shù)getWeRunData來調(diào)用wx.getWeRunData接口,并打印結(jié)果。
getWeRunData(){
wx.getWeRunData({
success: (result) => {
console.log(result)
},
})
}
編譯之后,點(diǎn)擊按鈕,我們可以在控制臺看到返回的res對象里有encryptedData包括敏感數(shù)據(jù)在內(nèi)的完整用戶信息的加密數(shù)據(jù)、iv加密算法的初始向量, cloudID敏感數(shù)據(jù)對應(yīng)的云 ID.
{errMsg: "getWeRunData:ok",
encryptedData: "ABeBwlCHs....6PvAax",
iv: "g8QPFXTLLD3N6Zn3YiuwEQ==",
cloudID: "30_jVhZr_Up-8_TV...kgP8yJ8ykN0I"}
這個cloudID只有在開通了云開發(fā)的小程序才會返回,我們可以將cloudID傳入云函數(shù),通過云調(diào)用就可以直接獲取開放數(shù)據(jù)。
使用開發(fā)者工具新建云函數(shù)比如opendata,再index.js里輸入以下代碼,并部署上線,在云函數(shù)端接收到的 event 將會包含對應(yīng)開放數(shù)據(jù)的對象。
const cloud = require('wx-server-sdk')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV,
})
exports.main = async (event, context) => {
return event
}
我們再來在前面的事件處理函數(shù)getWeRunData里上傳經(jīng)過cloud.CloudID接口獲得的cloudID對象,然后調(diào)用opendata云函數(shù),并在success里打印返回來的對象,就可以看到包含微信運(yùn)動步數(shù)的對象啦:
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ī)號,需要將 button 組件 open-type 的值設(shè)置為 getPhoneNumber,當(dāng)用戶點(diǎn)擊并同意之后,可以通過 bindgetphonenumber 事件回調(diào)獲取到微信服務(wù)器返回的加密數(shù)據(jù),如果開通了云開發(fā),就能在回調(diào)對象了獲取到cloudID。使用開發(fā)者工具在openData.wxml里輸入如下代碼:
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button>
然后再在openData.js里輸入以下代碼,我們打印事件處理函數(shù)getPhoneNumber返回的結(jié)果。
getPhoneNumber (result) {
console.log("result內(nèi)容",result.detail)
},
同樣我們也會獲得一個類似于微信運(yùn)動步數(shù)的返回結(jié)果
{errMsg: "getPhoneNumber:ok",
encryptedData: "Aw+W76TSvYAPS.....g==",
iv: "9wSepi6qx...=",
cloudID: "30_sSext5q.....qmLQ"}
我們?nèi)匀恢恍枰獙@取到cloudID經(jīng)過cloud.CloudID()接口處理返回的對象上傳并調(diào)用云函數(shù):
getPhoneNumber (result) {
wx.cloud.callFunction({
name: 'opendata',
data: {
getPhoneNumber: wx.cloud.CloudID(result.detail.cloudID),
},
success:(res)=>{
console.log("云函數(shù)返回的對象",res.result.getPhoneNumber)
}
})
},
在getPhoneNumber的data對象里的phoneNumber是用戶綁定的手機(jī)號(國外手機(jī)號會有區(qū)號)、purePhoneNumber是沒有區(qū)號的手機(jī)號、countryCode區(qū)號。
要獲取微信群ID和群名稱,需要經(jīng)過一系列相對比較復(fù)雜的處理,需要經(jīng)過以下步驟,具體的代碼和開發(fā)方式后面會具體介紹:
withShareTicket: true
,分享也必須分享到微信群里;shareTicket
,wx.getShareInfo
里就會得到微信群敏感數(shù)據(jù)對應(yīng)的cloudID,wx.cloud.CloudID(cloudID)
傳入到云函數(shù),云函數(shù)就可以返回微信群ID,也就是openGId
<open-data type="groupName" open-gid="{{openGId}}"></open-data>
來顯示群名
通過給 button 組件設(shè)置屬性open-type="share"
,可以在用戶點(diǎn)擊按鈕后觸發(fā)頁面的生命周期函數(shù)Page.onShareAppMessage
事件。首先我們使用開發(fā)者工具新建一個頁面,比如share,然后再在share.wxml創(chuàng)建一個button組件,比如:
<button open-type="share">轉(zhuǎn)發(fā)</button>
要獲取群聊的名稱以及群的標(biāo)識openGId,需要帶shareTicket的轉(zhuǎn)發(fā)才可以,我們在share.js頁面生命周期函數(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ù)存儲到數(shù)據(jù)庫,相當(dāng)于埋點(diǎn)
}
return {
title: '云開發(fā)技術(shù)訓(xùn)練營',
path: 'pages/share/share?openid=oUL-m5FuRmuVmxvbYOGuXbuEDsn8',
imageUrl:"cloud://xly-xrlur.786c-xly-xrlur-1300446086/share.png"http://支持云存儲的fileID
}
},
關(guān)于顯示右上角菜單的轉(zhuǎn)發(fā)按鈕可以使用
wx.showShareMenu
接口,而onShareAppMessage
除了可以監(jiān)聽用戶點(diǎn)擊頁面內(nèi)的button,也可以監(jiān)聽右上角菜單“轉(zhuǎn)發(fā)”按鈕的行為,無論是哪一種,都可以自定義菜單的title、path、imageUrl等,這里就不具體寫代碼啦。
值得注意的是,只有轉(zhuǎn)發(fā)到微信群聊中,再通過微信群聊里的小程序卡片進(jìn)入到小程序才可以獲取到shareTickets返回值,單聊沒有shareTickets;shareTicket僅在當(dāng)前小程序生命周期內(nèi)有效。但是在開發(fā)時,怎么把小程序轉(zhuǎn)發(fā)到微信群里面去呢?開發(fā)者工具提供了帶shareTickets的調(diào)試方法。
在開發(fā)者工具的模擬器里點(diǎn)擊"轉(zhuǎn)發(fā)"button,就會出現(xiàn)一個測試模擬群列表,我們可以將小程序轉(zhuǎn)發(fā)到一個群聊里面去,比如測試模擬群4
。調(diào)試時,我們要添加自定義編譯模式,在進(jìn)入場景里選擇1044: 帶 shareTicket 的小程序消息卡片
,選擇進(jìn)入的群為你轉(zhuǎn)發(fā)的群,具體可以參考如下圖:
獲取shareTicket,我們可以使用wx.getLaunchOptionsSync()
來獲取小程序啟動時的參數(shù),這個參數(shù)與App.onLaunch 的回調(diào)參數(shù)一致,而shareTicket就在這個參數(shù)對象里。我們可以在share.js的onLoad生命周期函數(shù)里來獲取它:
onLoad:function (options) {
const res = wx.getLaunchOptionsSync()
console.log('小程序啟動時的參數(shù)',res)
const {shareTicket} = res
console.log('shareTicket的值',shareTicket)
},
如果你直接使用普通編譯(不使用上面的調(diào)試方法),是獲取不到shareTicket的,shareTicket的值會為
undefined
,同時如果小程序直接加載(而不是通過點(diǎn)擊群聊里分享的小程序卡片進(jìn)入),shareTicket的值也是undefined
。
當(dāng)我們獲取到shareTicket之后,就可以調(diào)用wx.getShareInfo
接口來獲取到關(guān)于轉(zhuǎn)發(fā)的信息,尤其是cloudID。然后我們可以把獲取到的CloudID,傳入到云函數(shù),比如share云函數(shù)。
使用開發(fā)者工具新建一個share云函數(shù),在index.js里輸入以下代碼(這個其實(shí)就是返回event對象,如此簡單的云函數(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ù)寫如下代碼,先判斷shareTicket是否為空(也就是判斷是否是通過微信群聊小程序卡片進(jìn)入的),然后調(diào)用wx.getShareInfo來獲取CloudID,再將CloudID傳入到wx.cloud.CloudID()
接口,并將該對象傳至云函數(shù)share就可以返回這個CloudID對應(yīng)的開放數(shù)據(jù)了(這里的開放數(shù)據(jù)主要是openGId)。
onLoad:function (options) {
const that = this
const res = await wx.getLaunchOptionsSync()
const {shareTicket} = res
if(shareTicket!=null){ //當(dāng)shareTicket不為空時,調(diào)用wx.getShareInfo來獲取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
})
}
})
}
})
}
},
openGId為當(dāng)前群的唯一標(biāo)識,也就是每個微信群都有唯一且不變的這樣一個ID,可以用于區(qū)分不同的微信群。我們可以把微信群內(nèi)點(diǎn)擊了小程序分享卡片的群成員的用戶信息與這個openGId相關(guān)聯(lián),這樣就可以弄群排行榜等一些基于微信群的開發(fā)。
不過我們只能獲取微信群的群ID,是不能獲取微信群的名稱的,但是可以通過開放能力來顯示微信群的名稱,我們只需要把獲取到的openGId字符串傳入到open-gid
就可以了。
<open-data type="groupName" open-gid="{{openGId}}"></open-data>
可能你在調(diào)試的時候會出現(xiàn),即使你把openGId寫入到上面的組件,依然不會顯示群名,或者使用真機(jī)調(diào)試也無法顯示,這是因為測試群或者新建的群,可能會無效。
動態(tài)消息發(fā)出去之后,開發(fā)者可以通過后臺接口修改部分消息內(nèi)容,動態(tài)消息也有對應(yīng)的提醒按鈕,用戶點(diǎn)擊提醒按鈕可以訂閱提醒,開發(fā)者可以通過后臺修改消息狀態(tài)并推送一次提醒消息給訂閱了提醒的用戶。效果如下所示,這種特別適合我們做搶購、拼團(tuán)等運(yùn)營活動:
要讓轉(zhuǎn)發(fā)的小程序卡片里有動態(tài)消息,首先需要使用云調(diào)用updatableMessage.createActivityId
接口來創(chuàng)建activityId
,然后將activityId和templateInfo傳入到wx.updateShareMenu
,而要更新動態(tài)消息則需要使用到updatableMessage.setUpdatableMsg
的接口。我們可以把創(chuàng)建動態(tài)消息和更新動態(tài)消息的云函數(shù)使用tcb-router整合到一個云函數(shù)里面。
使用開發(fā)者工具新建一個云函數(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以及修改被分享的動態(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}
})
//后面我們會介紹如何更新動態(tài)消息,updatableMsg的router可以添加在這里
return app.serve();
}
和前面一樣,我們可以通過調(diào)用wx.updateShareMenu
接口,傳入isUpdatableMessage: true
,以及 templateInfo
、activityId
等參數(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ù)可以來自數(shù)據(jù)庫
}, {
name: 'room_limit',
value: '30' //這里的數(shù)據(jù)可以來自數(shù)據(jù)庫
}]
}
})
return {
title: 'HackWeek技術(shù)訓(xùn)練營',
path: 'pages/share/share?openid=oUL-m5FuRmuVmxvbYOGuXbuEDsn8',
imageUrl:"cloud://xly-xrlur.786c-xly-xrlur-1300446086/1572315793633-633.png"
}
},
動態(tài)消息發(fā)出去之后,我們可以通過這個activityId來追蹤這個動態(tài)消息,當(dāng)用戶進(jìn)入分享的小程序,報名參與了這個活動時,比如活動為拼團(tuán),30人這個團(tuán)購項目就成功啦,現(xiàn)在已經(jīng)有4個人參與了(可以從數(shù)據(jù)庫獲得),當(dāng)有新的用戶付費(fèi)參與這個拼團(tuán)時,我們可以在這個用戶付費(fèi)的回調(diào)函數(shù)里調(diào)用updatableMessage.setUpdatableMsg
這個接口來修改動態(tài)消息。比如:
wx.cloud.callFunction({
name: 'activity',
data: {
$url: "updatableMsg",
activityId: activityId, //activityId建議由前端傳入,獲取的方法如上
}
})
我們繼續(xù)在activity云函數(shù)里添加一個updatableMsg的router即可
const {activityID} = event
app.router('updatableMsg',async (ctx, next)=>{
//我們可以用從數(shù)據(jù)庫拉取現(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ù)庫拉取
}, {
name: 'room_limit',
value: '30' //從數(shù)據(jù)庫拉取
}]
}
})
})
更多建議: