能干概述: 自己搭建一个后台,创建自己的客服工作人员,在微信公众号中实现与用户之间的沟通【注:微信公众号后台有这种功能,反正我不管,我就是要写着玩玩】
需要认证过的微信公众号一个,其他的就不说了,至于怎样开启微信的服务器配置那个我有帖子是专门讲解的,网上也有很多教程,可自行GET。
实现方法很多,可以采用用户在微信公众号里面点击按钮进行提交表单,但是这种一般用于用户需要技术支持提交工单,所以这里就选择在输入框直接输入。
开始:
接上次的开始 服务器配置代码 中的 reponseMsg 函数; 这个是接收微信的事件推送的
接收用户消息:
//接受事件推送并回复 public function reponseMsg(){ //获取到微信推送过来的数据 (xml格式的) //$postArr = $GLOBALS['HTTP_RAW_POST_DATA']; //PHP高版本没得了 $postArr = file_get_contents("php://input"); //xml转对象 $postObj = simplexml_load_string($postArr, 'SimpleXMLElement', LIBXML_NOCDATA); //$postObj->ToUserName = ''; 公众号id //$postObj->FromUserName = ''; 用户在我微信公众号上的唯一id [openid] //$postObj->CreateTime = ''; 时间 //$postObj->MsgType = ''; 事件 //$postObj->Event = ''; 事件类型 //判断该数据包是否是订阅的时间推送 if( strtolower($postObj->MsgType) == 'event'){ //如果是关注 subscribe if( strtolower($postObj->Event) == 'subscribe'){ //unsubscribe //回复用户消息 $touser = $postObj->FromUserName; $from = $postObj->ToUserName; $time = time(); $msgType = 'text'; $content = "欢迎关注我们的微信公众账号\r\n点击下面链接填写信息<a href=\"http://cqphp.cn\">测试</a>"; //友情提醒 /r/n要在双引号内使用才回有效 /* $template = "<xml> <ToUserName>< ![CDATA[".$touser."] ]></ToUserName> <FromUserName>< ![CDATA[".$from."] ]></FromUserName> <CreateTime>".$time."</CreateTime> <MsgType>< ![CDATA[".$msgType."] ]></MsgType> <Content>< ![CDATA[".$content."] ]></Content> </xml>"; */ $template = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <Content><![CDATA[%s]]></Content> </xml>"; //判断是否建立了用户 这里是要把关注的用户存储到自己的数据库中, 重点是要存储 用户的OPENID, 这个是用户在我们公众号上的卫衣标识,很多接口都要用的 $wxuser = M('wxuser'); $findresult = $wxuser->where("openid='%s'",$touser)->find(); if(!$findresult){ $data = array(); $data['openid'] = "$touser"; $addresult = $wxuser->data($data)->add(); if($addresult){ //用户存储成功后, 考虑到用户沟通是直接留言框输入的,可能后期数量量会很庞大,这里采用分表存储,每个用户一个表; 不用考虑表太多,这个mysql没得限制 $table = 'qw_wxuser_'.$addresult; //这里做了简单的存储:ID、内容、是否查看、类型(这里采用0:用户发言;1后台回复) $sql = "CREATE TABLE IF NOT EXISTS `$table` ( `id` int(11) NOT NULL AUTO_INCREMENT, `nr` varchar(200) NOT NULL, `status` tinyint(1) unsigned NOT NULL DEFAULT '0', `type` tinyint(1) unsigned, `addtime` int(11) NOT NULL, `updatetime` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;"; $result = M('', '', 'DB_CONFIG_ACTIVE')->execute($sql); //writefile($result); } } //渲染模板 就是上面 欢迎关注那个。 $resustr = sprintf($template, $touser, $from, $time, $msgType, $content); //输出模板 echo $resustr; }else if( strtolower($postObj->Event) == 'click' ){ //点击了菜单 这里不做解释了,这次用不到 if( strtolower($postObj->EventKey) == 'item1' ){ //回复用户消息 $touser = $postObj->FromUserName; $from = $postObj->ToUserName; $time = time(); $msgType = 'text'; $content = '点击菜单想干嘛?'; $template = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <Content><![CDATA[%s]]></Content> </xml>"; //渲染模板 $resustr = sprintf($template, $touser, $from, $time, $msgType, $content); //输出模板 echo $resustr; } }else if( strtolower($postObj->Event) == 'scan' ){ //关注后 扫二维码的 这里不做解释了,这次用不到 //回复用户消息 $touser = $postObj->FromUserName; $from = $postObj->ToUserName; $time = time(); $msgType = 'text'; $content = '扫描了二维码'; $template = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <Content><![CDATA[%s]]></Content> </xml>"; //渲染模板 $resustr = sprintf($template, $touser, $from, $time, $msgType, $content); //输出模板 echo $resustr; } }else if( strtolower($postObj->MsgType) == 'text' ){ //文本 这里是接收到用户在文本框里输入文字进行了发送;当然还有 图片类型、音频、视频等,这个大家自己去研究吧。 //用户输入的是你好 if( strtolower($postObj->Content) == '你好'){ //这里是简单的自定义回复,如果用户发送你好 ,自动回复你也好 //用 微信的sdk来实现 (model) 调用model实现代码的规范, 以及调用的便利 //实例化模型 我这个失败了, 只有Home才调用得到 //$indexModel = new WxHome\Model\IndexModel(); //$indexModel->responseMsg($postObj); //回复用户消息 $touser = $postObj->FromUserName; $from = $postObj->ToUserName; $time = time(); $msgType = 'text'; $content = '你也好'; $template = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <Content><![CDATA[%s]]></Content> </xml>"; //渲染模板 $resustr = sprintf($template, $touser, $from, $time, $msgType, $content); //输出模板 echo $resustr; }else{ // 这里就是开始存储用户发送的文字信息了 //得到该用户ID $user = M('wxuser')->where("openid='%s'",$postObj->FromUserName)->find(); $mes = M('wxuser_'.$user['id']); //把这个用户发送的文字信息存储到他自己的聊天表里面 数据字段可自行添加处理,这里仅做简单测试 $data['nr'] = strtolower($postObj->Content); $data['status'] = 0; $data['type'] = 1; $data['addtime'] = time(); $data['updatetime'] = time(); $mes->add($data); exit(0); } }// 文本事件 end }
后台消息列表:
public function messagelist(){ $list = M('wxuser_'.$_GET['id'])->order('addtime asc')->select(); $this->assign('list', $list); $this->display(); }
如图:
这里我是局部 3秒刷新的,可以采用ajax或者其他异步加载的技术。
后台进行回复用户实现代码:
public function chat(){ if(IS_POST){ $mes = M('wxuser_'.$_POST['id']); $data['nr'] = strtolower($_POST['nr']); $data['status'] = 0; $data['type'] = 2; $data['addtime'] = time(); $data['updatetime'] = time(); $mes->add($data); $user = M('wxuser')->where("id=".$_POST['id'])->find(); $accesstoken = getAccessToken(); $text = '{ "touser":"'.$user['openid'].'", "msgtype":"text", "text": { "content":"'.$_POST['nr'].'" } }'; $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=$accesstoken"; 调用 微信客服接口发消息 $send_result = httpPost($url, $text); $this->success('OK'); }else{ $uid = $_GET['id']; $this->assign('uid',$uid); $this->display(); } }
实现效果: