在前面的章節(jié),我們已經(jīng)在小程序端將button 組件open-type 的值設(shè)置為 contact ,點(diǎn)擊button就可以進(jìn)入客服消息。不過這個客服消息使用的是官方的后臺,沒法進(jìn)行深度的定制,我們可以使用云開發(fā)作為后臺來自定義客服消息來實(shí)現(xiàn)快捷回復(fù)、添加常用回答等功能。
如果是使用傳統(tǒng)的開發(fā)方式,需要填寫服務(wù)器地址(URL)、令牌(Token) 和 消息加密密鑰(EncodingAESKey)等信息,然后結(jié)合將token、timestamp、nonce三個參數(shù)進(jìn)行字典序排序、拼接、并進(jìn)行sha1加密,然后將加密后的字符串與signature對比來驗證消息的確來自微信服務(wù)器,之后再來進(jìn)行接收消息和事件的處理,可謂十分繁瑣,而使用云開發(fā)相對簡單很多。
使用開發(fā)者工具新建一個云函數(shù),比如customer,在config.json里,設(shè)置以下權(quán)限后部署上傳到服務(wù)端。
{
"permissions": {
"openapi": [
"customerServiceMessage.send",
"customerServiceMessage.getTempMedia",
"customerServiceMessage.setTyping",
"customerServiceMessage.uploadTempMedia"
]
}
}
然后再打開云開發(fā)控制臺,點(diǎn)擊右上角的設(shè)置,選擇全局設(shè)置,開啟云函數(shù)接收消息推送,添加消息推送配置。為了學(xué)習(xí)方便我們將所有的消息類型都指定推送到customer云函數(shù)里。
以上有四種消息類型,但是發(fā)送客服消息的customerServiceMessage.send的msgtype屬性的合法值有text、image、link(圖文鏈接消息)、miniprogrampage四種,也就是我們還可以發(fā)圖文鏈接消息。
使用開發(fā)者工具新建一個頁面,比如customer,然后在customer.wxml里輸入以下按鈕,
<button open-type="contact" >進(jìn)入客服</button>
當(dāng)用戶通過button進(jìn)入到客服消息之后,在聊天界面回復(fù)信息,就能觸發(fā)設(shè)置好的customer云函數(shù),比如下面的例子就是當(dāng)用戶發(fā)一條消息(包括表情)到客服消息會話界面,云函數(shù)就會給調(diào)用customerServiceMessage.send接口給用戶回復(fù)兩條文本消息(一次性可以回復(fù)多條),內(nèi)容分別為等候您多時啦
和歡迎關(guān)注云開發(fā)技術(shù)訓(xùn)練營
,一個云函數(shù)里也是可以多次調(diào)用接口的:
const cloud = require('wx-server-sdk')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV,
})
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
try {
const result = await cloud.openapi.customerServiceMessage.send({
touser: wxContext.OPENID,
msgtype: 'text',
text: {
content: '等候您多時啦'
}
})
const result2 = await cloud.openapi.customerServiceMessage.send({
touser: wxContext.OPENID,
msgtype: 'text',
text: {
content: '歡迎關(guān)注云開發(fā)技術(shù)訓(xùn)練營'
}
})
return event
} catch (err) {
console.log(err)
return err
}
}
發(fā)送文本消息時,支持插入跳小程序的文字鏈接的,比如我們把上面的文本消息改為以下代碼:
content: '歡迎瀏覽<a rel="external nofollow" target="_blank" data-miniprogram-appid="你的appid" data-miniprogram-path="pages/index/index">點(diǎn)擊跳小程序</a>'
我們還可以給用戶回復(fù)鏈接,我們可以把customer云函數(shù)修改為以下代碼,當(dāng)用戶向微信聊天對話界面發(fā)送一條消息時,就會回復(fù)給用戶一個鏈接,這個鏈接可以是外部鏈接哦。
const cloud = require('wx-server-sdk')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV,
})
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
try {
const result = await cloud.openapi.customerServiceMessage.send({
touser: wxContext.OPENID,
msgtype: 'link',
link: {
title: '快來加入云開發(fā)技術(shù)訓(xùn)練營',
description: '零基礎(chǔ)也能在10天內(nèi)學(xué)會開發(fā)一個小程序',
url: 'https://cloud.tencent.com/',
thumbUrl: 'https://tcb-1251009918.cos.ap-guangzhou.myqcloud.com/love.png'
}
})
return event
} catch (err) {
console.log(err)
return err
}
}
將上面的云函數(shù)部署之后,當(dāng)用戶向客服消息的聊天會話里輸入內(nèi)容時,不管用戶發(fā)送的是什么內(nèi)容,云函數(shù)都會回給用戶相同的內(nèi)容,這未免有點(diǎn)過于死板,客服消息能否根據(jù)用戶發(fā)送的關(guān)鍵詞回復(fù)用戶不同的內(nèi)容呢?要做到這一點(diǎn)我們需要能夠獲取到用戶發(fā)送的內(nèi)容。
我們可以留意云開發(fā)控制臺云函數(shù)日志里看到,customer云函數(shù)返回的event對象里的Content屬性就會記錄用戶發(fā)到聊天會話里的內(nèi)容:
{ "Content":"請問怎么加入云開發(fā)訓(xùn)練營",
"CreateTime":1582877109,
"FromUserName":"oUL-mu...XbuEDsn8",
"MsgId":22661351901594052,
"MsgType":"text",
"ToUserName":"gh_b2bbe22535e4",
"userInfo":{"appId":"wxda99ae4531b57046","openId":"oUL-m5FuRmuVmxvbYOGuXbuEDsn8"}}
由于Content是字符串,那這個關(guān)鍵詞既可以是非常精準(zhǔn)的,比如“訓(xùn)練營”,或“云開發(fā)訓(xùn)練營”,還可以是非常模糊的“請問怎么加入云開發(fā)訓(xùn)練營”,我們只需要對字符串進(jìn)行正則匹配處理即可,比如當(dāng)用戶只要發(fā)的內(nèi)容包含“訓(xùn)練營”,就會收到鏈接:
const cloud = require('wx-server-sdk')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV,
})
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
const keyword = event.Content
try {
if(keyword.search(/訓(xùn)練營/i)!=-1){
const result = await cloud.openapi.customerServiceMessage.send({
touser: wxContext.OPENID,
msgtype: 'link',
link: {
title: '快來加入云開發(fā)技術(shù)訓(xùn)練營',
description: '零基礎(chǔ)也能在10天內(nèi)學(xué)會開發(fā)一個小程序',
url: 'https://cloud.tencent.com/',
thumbUrl: 'https://tcb-1251009918.cos.ap-guangzhou.myqcloud.com/love.png'
}
})
}
return event
} catch (err) {
console.log(err)
return err
}
}
在前面的案例里,我們都是使用
touser: wxContext.OPENID,
,
要觸發(fā)event事件,我們可以將customer.wxml的按鈕改為如下代碼,這里的session-from是用戶從該按鈕進(jìn)入客服消息會話界面時,開發(fā)者將收到帶上本參數(shù)的事件推送,可用于區(qū)分用戶進(jìn)入客服會話的來源。
<button open-type="contact" bindcontact="onCustomerServiceButtonClick" session-from="文章詳情的客服按鈕">進(jìn)入客服</button>
由于我們開啟了event類型的客服消息,事件類型的值為user_enter_tempsession,當(dāng)用戶點(diǎn)擊button進(jìn)入客服時,就會觸發(fā)云函數(shù),不用用戶發(fā)消息就能觸發(fā),同時我們返回event對象.
const cloud = require('wx-server-sdk')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV,
})
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
try {
const result = await cloud.openapi.customerServiceMessage.send({
touser: wxContext.OPENID,
msgtype: 'text',
text: {
content: '歡迎來到等候您多時啦'
}
})
return event
} catch (err) {
console.log(err)
return err
}
}
我們可以去云開發(fā)控制臺查看返回的event對象
{ "CreateTime":1582876587,
"Event":"user_enter_tempsession",
"FromUserName":"oUL-m5F...8",
"MsgType":"event",
"SessionFrom":"文章詳情的客服按鈕",
"ToUserName":"gh_b2bbe22535e4",
"userInfo":{"appId":"wxda9...57046",
"openId":"oUL-m5FuRmuVmx...sn8"}}
在云函數(shù)端,我們是可以通過event.SessionFrom來獲取到用戶到底是點(diǎn)擊了哪個按鈕從而進(jìn)入客服對話的,也可以根據(jù)用戶進(jìn)入客服會話的來源不同,給用戶推送不同類型,比如我們可以給session-from的值設(shè)置為“訓(xùn)練營”,當(dāng)用戶進(jìn)入客服消息會話就能推送相關(guān)的信息給到用戶。
還有一點(diǎn)就是,bindcontact是給客服按鈕綁定了了一個事件處理函數(shù),這里為onCustomerServiceButtonClick,通過事件處理函數(shù)我們可以在小程序端做很多事情,比如記錄用戶點(diǎn)擊了多少次帶有標(biāo)記(比如session-from的值設(shè)置為“訓(xùn)練營”)的客服消息的按鈕等功能。
要在客服消息里給用戶回復(fù)圖片,這個圖片的來源只能是來源于微信服務(wù)器,我們需要先使用customerServiceMessage.uploadTempMedia,把圖片文件上傳到微信服務(wù)器,獲取到mediaId(有點(diǎn)類似于微信服務(wù)器的fileID),然后才能在客服消息里使用。
在customer云函數(shù)的index.js里輸入以下代碼并部署上線,我們將獲取到的mediaId使用cloud.openapi.customerServiceMessage.send發(fā)給用戶:
const cloud = require('wx-server-sdk')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV,
})
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
try {
//我們通常會將云存儲的圖片作為客服消息媒體文件的素材
const fileID = 'cloud://xly-xrlur.786c-xly-xrlur-1300446086/1572315793628-366.png'
//uploadTempMedia的圖片類型為Buffer,而從存儲下載的圖片格式也是Buffer
const res = await cloud.downloadFile({
fileID: fileID,
})
const Buffer = res.fileContent
const result = await cloud.openapi.customerServiceMessage.uploadTempMedia({
type: 'image',
media: {
contentType: 'image/png',
value: Buffer
}
})
console.log(result.mediaId)
const mediaId = result.mediaId
const wxContext = cloud.getWXContext()
const result2 = await cloud.openapi.customerServiceMessage.send({
touser: wxContext.OPENID,
msgtype: 'image',
image: {
mediaId: mediaId
}
})
return event
} catch (err) {
console.log(err)
return err
}
}
客服消息還能給用戶回復(fù)小程序消息卡片,以及客服當(dāng)前的輸入狀態(tài)給用戶(使用customerServiceMessage.setTyping接口)。
更多建議: