如何使用微信公众平台开发模式实现多客服


Posted in PHP onJanuary 06, 2016

其实微信公众平台的多客服功能已经出来好久了,并且一出来的时候我就已经为自己的公众号实现了,原本以为大家都已经会了,但是今天还是有人问起这个多客服功能怎么使用,我找了下网上也没什么好的教程,今天我就给大家发一篇比较简单易懂的教程吧!

在这篇微信公众平台开发教程中,我们将介绍如何使用开发模式实现多客服系统。

一、回复多客服消息

在新的微信协议中,开发模式也可以接入客服系统。 开发者如果需要让用户使用客服系统,需要在接收到用户发送的消息时,返回一个MsgType为transfer_customer_service的消息,微信服务器在收到这条消息时,会把用户这次发送的和以后一段时间内发送的消息转发客服系统。

返回的消息举例如下

<xml>
  <ToUserName><![CDATA[touser]]></ToUserName>
  <FromUserName><![CDATA[fromuser]]></FromUserName>
  <CreateTime>1399197672</CreateTime>
  <MsgType><![CDATA[transfer_customer_service]]></MsgType>
</xml>

该消息的实现如下(以方倍工作室的微信公众平台PHP SDK为基础)

//回复多客服消息
  private function transmitService($object)
  {
    $xmlTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[transfer_customer_service]]></MsgType>
</xml>";
    $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time());
    return $result;
  }

二、触发多客服会话

一般情况下,用户想要咨询问题是,经常会问“你好”,“在吗”,这样的问题。

我们以这些词为触发关键词,当用户发送的文本消息内容中包含这些词的时候,就返回多客服消息给用户(用户在微信端感觉不到任何内容,但微信公众账号会将用户本次及以后一段时间的消息都转发到客服)。

实现代码如下:

//接收文本消息
  private function receiveText($object)
  {
    $keyword = trim($object->Content);
    if (strstr($keyword, "投诉") || strstr($keyword, "你好") || strstr($keyword, "在吗")){
      $result = $this->transmitService($object);
    }
    return $result;
  }

三、完整代码

<?php
/*
  方倍工作室
  CopyRight 2014 All Rights Reserved
*/
define("TOKEN", "weixin");
$wechatObj = new wechatCallbackapiTest();
if (!isset($_GET['echostr'])) {
  $wechatObj->responseMsg();
}else{
  $wechatObj->valid();
}
class wechatCallbackapiTest
{
  //验证消息
  public function valid()
  {
    $echoStr = $_GET["echostr"];
    if($this->checkSignature()){
      echo $echoStr;
      exit;
    }
  }
  //检查签名
  private function checkSignature()
  {
    $signature = $_GET["signature"];
    $timestamp = $_GET["timestamp"];
    $nonce = $_GET["nonce"];
    $token = TOKEN;
    $tmpArr = array($token, $timestamp, $nonce);
    sort($tmpArr, SORT_STRING);
    $tmpStr = implode($tmpArr);
    $tmpStr = sha1($tmpStr);
    if($tmpStr == $signature){
      return true;
    }else{
      return false;
    }
  }
  //响应消息
  public function responseMsg()
  {
    $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
    if (!empty($postStr)){
      $this->logger("R ".$postStr);
      $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
      $RX_TYPE = trim($postObj->MsgType);
      switch ($RX_TYPE)
      {
        case "event":
          $result = $this->receiveEvent($postObj);
          break;
        case "text":
          $result = $this->receiveText($postObj);
          break;
      }
      $this->logger("T ".$result);
      echo $result;
    }else {
      echo "";
      exit;
    }
  }
  //接收事件消息
  private function receiveEvent($object)
  {
    switch ($object->Event)
    {
      case "subscribe":
        $content[] = array("Title" =>"欢迎关注方倍工作室", "Description" =>"使用方法:\n1.发送快递单号,例如6367532560,可查询快递详情", "PicUrl" =>"http://www.3856.cc/weixin/weixin/logo.jpg", "Url" =>"");
        break;
      default:
        $content = "receive a new event: ".$object->Event;
        break;
    }
    if(is_array($content)){
      if (isset($content[0])){
        $result = $this->transmitNews($object, $content);
      }else if (isset($content['MusicUrl'])){
        $result = $this->transmitMusic($object, $content);
      }
    }else{
      $result = $this->transmitText($object, $content);
    }
    return $result;
  }
  //接收文本消息
  private function receiveText($object)
  {
    $keyword = trim($object->Content);
    if($keyword == "时间" || $keyword == "测试"){
      $content = date("Y-m-d H:i:s",time());
      $result = $this->transmitText($object, $content);
    }
    //触发多客服模式
    else if (strstr($keyword, "您好") || strstr($keyword, "你好") || strstr($keyword, "在吗") || strstr($keyword, "有人吗")){
      $result = $this->transmitService($object);
      return $result;
    }
    return $result;
  }
  private function transmitText($object, $content)
  {
    $textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>";
    $result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(), $content);
    return $result;
  }
  private function transmitNews($object, $newsArray)
  {
    if(!is_array($newsArray)){
      return;
    }
    $itemTpl = "  <item>
    <Title><![CDATA[%s]]></Title>
    <Description><![CDATA[%s]]></Description>
    <PicUrl><![CDATA[%s]]></PicUrl>
    <Url><![CDATA[%s]]></Url>
  </item>
";
    $item_str = "";
    foreach ($newsArray as $item){
      $item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);
    }
    $newsTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<Content><![CDATA[]]></Content>
<ArticleCount>%s</ArticleCount>
<Articles>
$item_str</Articles>
</xml>";
    $result = sprintf($newsTpl, $object->FromUserName, $object->ToUserName, time(), count($newsArray));
    return $result;
  }
  private function transmitMusic($object, $musicArray)
  {
    $itemTpl = "<Music>
  <Title><![CDATA[%s]]></Title>
  <Description><![CDATA[%s]]></Description>
  <MusicUrl><![CDATA[%s]]></MusicUrl>
  <HQMusicUrl><![CDATA[%s]]></HQMusicUrl>
</Music>";
    $item_str = sprintf($itemTpl, $musicArray['Title'], $musicArray['Description'], $musicArray['MusicUrl'], $musicArray['HQMusicUrl']);
    $textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[music]]></MsgType>
$item_str
</xml>";
    $result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time());
    return $result;
  }
  //回复多客服消息
  private function transmitService($object)
  {
    $xmlTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[transfer_customer_service]]></MsgType>
</xml>";
    $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time());
    return $result;
  }
  private function logger($log_content)
  {
    if(isset($_SERVER['HTTP_APPNAME'])){  //SAE
      sae_set_display_errors(false);
      sae_debug($log_content);
      sae_set_display_errors(true);
    }else if($_SERVER['REMOTE_ADDR'] != "127.0.0.1"){ //LOCAL
      $max_size = 10000;
      $log_filename = "log.xml";
      if(file_exists($log_filename) and (abs(filesize($log_filename)) > $max_size)){unlink($log_filename);}
      file_put_contents($log_filename, date('H:i:s')." ".$log_content."\r\n", FILE_APPEND);
    }
  }
}
?>

本段代码经过测试,在自定义菜单中返回多客服消息,无法让用户进入多客服状态,使用多客服消息后,后续所有消息在一段时间内都将作为客服消息转发,原来的开发模式下的自动回复都将失效。

本文写的不好,还望海涵,有好的意见欢迎分享,大家共同学习进步。同时,感谢大家一直以来对三水点靠木网站的支持。

PHP 相关文章推荐
首页四格,首页五格For6.0(GBK)(UTF-8)[12种组合][9-18][版主安装测试通过]
Sep 24 PHP
php imagecreatetruecolor 创建高清和透明图片代码小结
May 15 PHP
修改php.ini以达到屏蔽错误信息并记录日志
Jun 16 PHP
php设计模式之单例模式使用示例
Jan 20 PHP
ThinkPHP实现ajax仿官网搜索功能实例
Dec 02 PHP
PHP性能分析工具XHProf安装使用教程
May 13 PHP
Zend Framework教程之资源(Resources)用法实例详解
Mar 14 PHP
PHP入门教程之数组用法汇总(创建,删除,遍历,排序等)
Sep 11 PHP
php使用SAE原生Mail类实现各种类型邮件发送的方法
Oct 10 PHP
thinkPHP5框架自定义验证器实现方法分析
Jun 11 PHP
PHP设计模式之工厂模式(Factory Pattern)的讲解
Mar 21 PHP
laravel 根据不同组织加载不同视图的实现
Oct 14 PHP
基于PHP技术开发客服工单系统
Jan 06 #PHP
分享php邮件管理器源码
Jan 06 #PHP
CI(Codeigniter)的Setting增强配置类实例
Jan 06 #PHP
WordPress开发中短代码的实现及相关函数使用技巧
Jan 05 #PHP
WordPress开发中用于获取近期文章的PHP函数使用解析
Jan 05 #PHP
Yii中表单用法实例详解
Jan 05 #PHP
php实现购物车功能(下)
Jan 05 #PHP
You might like
一个目录遍历函数
2006/10/09 PHP
解析使用ThinkPHP应该掌握的调试手段
2013/06/20 PHP
php中session使用示例
2014/03/29 PHP
php metaphone()函数的定义和用法
2016/05/15 PHP
ThinkPHP中create()方法自动验证表单信息
2017/04/28 PHP
Yii2.0使用阿里云OSS的SDK上传图片、下载、删除图片示例
2017/09/20 PHP
PHP数字金额转换成中文大写显示
2019/01/05 PHP
Iframe自适应高度绝对好使的代码 兼容IE,遨游,火狐
2011/01/27 Javascript
一些有用的JavaScript和jQuery的片段分享
2011/08/23 Javascript
javascript中如何处理引号编码&amp;#034;
2013/08/15 Javascript
从数组中随机取x条不重复数据的JS代码
2013/12/24 Javascript
jquery实现保存已选用户
2014/07/21 Javascript
零基础搭建Node.js、Express、Ejs、Mongodb服务器及应用开发入门
2014/12/20 Javascript
jQuery实现悬浮在右上角的网页客服效果代码
2015/10/24 Javascript
javascript性能优化之事件委托实例详解
2015/12/12 Javascript
Javascript OOP之面向对象
2016/07/31 Javascript
prototype与__proto__区别详细介绍
2017/01/09 Javascript
zTree异步加载展开第一级节点的实现方法
2017/09/05 Javascript
基于Bootstrap下拉框插件bootstrap-select使用方法详解
2018/08/07 Javascript
layer插件实现在弹出层中弹出一警告提示并关闭弹出层的方法
2019/09/24 Javascript
JavaScript鼠标悬停事件用法解析
2020/05/15 Javascript
Python使用Shelve保存对象方法总结
2019/01/28 Python
python列表生成器迭代器实例解析
2019/12/19 Python
python实现飞行棋游戏
2020/02/05 Python
Python loguru日志库之高效输出控制台日志和日志记录
2020/03/07 Python
python deque模块简单使用代码实例
2020/03/12 Python
TensorFlow2.1.0安装过程中setuptools、wrapt等相关错误指南
2020/04/08 Python
浅析NumPy 切片和索引
2020/09/02 Python
浅谈Python描述数据结构之KMP篇
2020/09/06 Python
python爬虫利用selenium实现自动翻页爬取某鱼数据的思路详解
2020/12/22 Python
什么是托管函数?托管函数有什么用?
2014/06/15 面试题
职业生涯规划怎么写
2013/12/29 职场文书
汉语言文学职业规划
2014/02/14 职场文书
社团活动总结书
2014/06/27 职场文书
告诉你一个秘密:富人致富的五大优点
2019/07/11 职场文书
Docker官方工具docker-registry案例演示
2022/04/13 Servers