codecamp

云开发 客服消息

在前面的章节,我们已经在小程序端将button 组件open-type 的值设置为 contact ,点击button就可以进入客服消息。不过这个客服消息使用的是官方的后台,没法进行深度的定制,我们可以使用云开发作为后台来自定义客服消息来实现快捷回复、添加常用回答等功能。

如果是使用传统的开发方式,需要填写服务器地址(URL)、令牌(Token) 和 消息加密密钥(EncodingAESKey)等信息,然后结合将token、timestamp、nonce三个参数进行字典序排序、拼接、并进行sha1加密,然后将加密后的字符串与signature对比来验证消息的确来自微信服务器,之后再来进行接收消息和事件的处理,可谓十分繁琐,而使用云开发相对简单很多。

一、客服消息的配置与说明

使用开发者工具新建一个云函数,比如customer,在config.json里,设置以下权限后部署上传到服务端。

{
  "permissions": {
    "openapi": [
      "customerServiceMessage.send",
      "customerServiceMessage.getTempMedia",
      "customerServiceMessage.setTyping",
      "customerServiceMessage.uploadTempMedia"
    ]
  }
}

然后再打开云开发控制台,点击右上角的设置,选择全局设置,开启云函数接收消息推送,添加消息推送配置。为了学习方便我们将所有的消息类型都指定推送到customer云函数里。

  • text,文本消息

  • image,图片消息

  • miniprogram,小程序卡片

  • event,事件类型user_enter_tempsession,进入客服消息时就会触发

以上有四种消息类型,但是发送客服消息的customerServiceMessage.send的msgtype属性的合法值有text、image、link(图文链接消息)、miniprogrampage四种,也就是我们还可以发图文链接消息。

二、自动回复文本消息和链接

1、自动回复文本消息

使用开发者工具新建一个页面,比如customer,然后在customer.wxml里输入以下按钮,

<button open-type="contact" >进入客服</button>

当用户通过button进入到客服消息之后,在聊天界面回复信息,就能触发设置好的customer云函数,比如下面的例子就是当用户发一条消息(包括表情)到客服消息会话界面,云函数就会给调用customerServiceMessage.send接口给用户回复两条文本消息(一次性可以回复多条),内容分别为等候您多时啦欢迎关注云开发技术训练营,一个云函数里也是可以多次调用接口的:

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: '欢迎关注云开发技术训练营'
      }
    })
    return event
  } catch (err) {
    console.log(err)
    return err
  }
}

发送文本消息时,支持插入跳小程序的文字链接的,比如我们把上面的文本消息改为以下代码:

content: '欢迎浏览<a href="http://www.qq.com" data-miniprogram-appid="你的appid" data-miniprogram-path="pages/index/index">点击跳小程序</a>' 

  • data-miniprogram-appid 项,填写小程序appid,则表示该链接跳小程序;

  • data-miniprogram-path项,填写小程序路径,路径与app.json中保持一致,可带参数;

  • 对于不支持data-miniprogram-appid 项的客户端版本,如果有herf项,则仍然保持跳href中的网页链接;

  • data-miniprogram-appid对应的小程序必须与公众号有绑定关系。

2、自动回复链接

我们还可以给用户回复链接,我们可以把customer云函数修改为以下代码,当用户向微信聊天对话界面发送一条消息时,就会回复给用户一个链接,这个链接可以是外部链接哦。

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: '快来加入云开发技术训练营',
          description: '零基础也能在10天内学会开发一个小程序',
          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
  }
}

3、根据关键词来回复用户

将上面的云函数部署之后,当用户向客服消息的聊天会话里输入内容时,不管用户发送的是什么内容,云函数都会回给用户相同的内容,这未免有点过于死板,客服消息能否根据用户发送的关键词回复用户不同的内容呢?要做到这一点我们需要能够获取到用户发送的内容。

我们可以留意云开发控制台云函数日志里看到,customer云函数返回的event对象里的Content属性就会记录用户发到聊天会话里的内容:

{   "Content":"请问怎么加入云开发训练营",
    "CreateTime":1582877109,
    "FromUserName":"oUL-mu...XbuEDsn8",
    "MsgId":22661351901594052,
    "MsgType":"text",
    "ToUserName":"gh_b2bbe22535e4",
    "userInfo":{"appId":"wxda99ae4531b57046","openId":"oUL-m5FuRmuVmxvbYOGuXbuEDsn8"}}

由于Content是字符串,那这个关键词既可以是非常精准的,比如“训练营”,或“云开发训练营”,还可以是非常模糊的“请问怎么加入云开发训练营”,我们只需要对字符串进行正则匹配处理即可,比如当用户只要发的内容包含“训练营”,就会收到链接:

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(/训练营/i)!=-1){
      const result = await cloud.openapi.customerServiceMessage.send({
        touser: wxContext.OPENID,
        msgtype: 'link',
        link: {
          title: '快来加入云开发技术训练营',
          description: '零基础也能在10天内学会开发一个小程序',
          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,

三、自动触发event事件

要触发event事件,我们可以将customer.wxml的按钮改为如下代码,这里的session-from是用户从该按钮进入客服消息会话界面时,开发者将收到带上本参数的事件推送,可用于区分用户进入客服会话的来源。

<button open-type="contact" bindcontact="onCustomerServiceButtonClick" session-from="文章详情的客服按钮">进入客服</button>

由于我们开启了event类型的客服消息,事件类型的值为user_enter_tempsession,当用户点击button进入客服时,就会触发云函数,不用用户发消息就能触发,同时我们返回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
  }
}

我们可以去云开发控制台查看返回的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"}}

在云函数端,我们是可以通过event.SessionFrom来获取到用户到底是点击了哪个按钮从而进入客服对话的,也可以根据用户进入客服会话的来源不同,给用户推送不同类型,比如我们可以给session-from的值设置为“训练营”,当用户进入客服消息会话就能推送相关的信息给到用户。

还有一点就是,bindcontact是给客服按钮绑定了了一个事件处理函数,这里为onCustomerServiceButtonClick,通过事件处理函数我们可以在小程序端做很多事情,比如记录用户点击了多少次带有标记(比如session-from的值设置为“训练营”)的客服消息的按钮等功能。

四、自动回复图片

要在客服消息里给用户回复图片,这个图片的来源只能是来源于微信服务器,我们需要先使用customerServiceMessage.uploadTempMedia,把图片文件上传到微信服务器,获取到mediaId(有点类似于微信服务器的fileID),然后才能在客服消息里使用。

在customer云函数的index.js里输入以下代码并部署上线,我们将获取到的mediaId使用cloud.openapi.customerServiceMessage.send发给用户:

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
  }
}

客服消息还能给用户回复小程序消息卡片,以及客服当前的输入状态给用户(使用customerServiceMessage.setTyping接口)。

云开发 CloudID与动态消息
云开发 微信支付
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }