使用客服消息实现发送多条图文消息
第一步、首先找到微擎关键字触发发送消息的PHP文件在framework->builtin->core->processor.php文件里面
二、修改respond方法
1 public function respond() { 2 $result = $this->msg_respond(); 3 return $this->respText($result); 4 }
三、写入我们自己实现发送图文的方法
msg_respond()方法
1 private function msg_respond() { 2 $rids = !is_array($this->rule) ? explode(\',\', $this->rule) : $this->rule; 3 //数据库中获取发送文字的信息 4 $reply = table(\'basic_reply\')->where(array(\'rid IN\' => $rids))->orderby(\'id\')->getAll(); 5 //图片 6 $img_reply = table(\'images_reply\')->where(array(\'rid IN\' => $rids))->orderby(\'id\')->getAll(); 7 //图文 8 //$news_reply = table(\'news_reply\')->where(array(\'rid IN\' => $rids,\'parent_id ==\' => -1))->orderby(\'id\')->getAll(); 9 $news_reply = table(\'news_reply\')->where(array(\'rid IN\' => $rids))->orderby(\'id\')->getAll(); 10 //音乐 11 $music_reply = table(\'music_reply\')->where(array(\'rid IN\' => $rids))->orderby(\'id\')->getAll(); 12 //语音 13 $voice_reply = table(\'voice_reply\')->where(array(\'rid IN\' => $rids))->orderby(\'id\')->getAll(); 14 //视频 15 $video_reply = table(\'video_reply\')->where(array(\'rid IN\' => $rids))->orderby(\'id\')->getAll(); 16 //父级找子级 17 /*foreach ($news_reply as &$value){ 18 //if ($value[\'parent\'] != -1) { 19 $value[\'parent_data\'] = table(\'news_reply\')->where([\'parent_id\' => $value[\'id\']])->orderby(\'id\')->getAll(); 20 //} 21 }*/ 22 23 //判断是否为空,如果都为空返回false 24 if (empty($reply)&&empty($img_reply)&&empty($news_reply)&&empty($music_reply)&&empty($voice_reply)&&empty($video_reply)) { 25 return false; 26 } 27 $access_token=$this->getToken(); 28 $postStr=file_get_contents(\'php://input\'); 29 $postObj = simplexml_load_string($postStr, \'SimpleXMLElement\', LIBXML_NOCDATA); 30 if (count($reply)+count($img_reply)+count($news_reply)+count($music_reply)+count($voice_reply)+count($video_reply)==1){ 31 if($reply!=null){ 32 $reply[0][\'content\'] = htmlspecialchars_decode($reply[0][\'content\']); 33 $reply[0][\'content\'] = str_replace(array(\'<br>\', \' \'), array("\n", \' \'), $reply[0][\'content\']); 34 $reply[0][\'content\'] = strip_tags($reply[0][\'content\'], \'<a>\'); 35 return $reply[0][\'content\']; 36 }elseif ($img_reply!=null){ 37 for ($y=0;$y<count($img_reply);$y++){ 38 $this->imageReply($postObj->FromUserName,$access_token,$img_reply[$y][\'mediaid\']); 39 } 40 }elseif ($news_reply!=null){ 41 //$this->judgeType(\'news\'); 42 for ($j=0;$j<count($news_reply);$j++){ 43 44 //$this->newsReply($postObj->FromUserName,$access_token,$news_reply[$j][\'url\'],$news_reply[$j][\'thumb\'],$news_reply[$j][\'title\'],$news_reply[$j][\'description\'],$news_reply[$j][\'parent_data\']); 45 $this->newsReply($postObj->FromUserName,$access_token,$news_reply[$j][\'url\'],$news_reply[$j][\'thumb\'],$news_reply[$j][\'title\'],$news_reply[$j][\'description\'],$news_reply[$j][\'media_id\']); 46 } 47 }elseif ($music_reply!=null){ 48 $result = $this->music_respond(); 49 return $this->respMusic(array( 50 \'Title\' => $result[\'title\'], 51 \'Description\' => $result[\'description\'], 52 \'MusicUrl\' => $result[\'url\'], 53 \'HQMusicUrl\' => $result[\'hqurl\'], 54 )); 55 }elseif ($voice_reply!=null){ 56 for ($s=0;$s<count($voice_reply);$s++){ 57 $this->voiceReply($postObj->FromUserName,$access_token,$voice_reply[$s][\'mediaid\']); 58 } 59 }elseif ($video_reply!=null){ 60 for ($d=0;$d<count($video_reply);$d++){ 61 $this->videoReply($postObj->FromUserName,$access_token,$video_reply[$d][\'mediaid\'],$video_reply[$d][\'title\'],$video_reply[$d][\'description\']); 62 } 63 }else{ 64 return "数据错误!!!"; 65 } 66 }else{ 67 //循环发送图片 68 for ($y=0;$y<count($img_reply);$y++){ 69 $this->imageReply($postObj->FromUserName,$access_token,$img_reply[$y][\'mediaid\']); 70 } 71 //循环发送图文 72 for ($j=0;$j<count($news_reply);$j++){ 73 $this->newsReply($postObj->FromUserName,$access_token,$news_reply[$j][\'url\'],$news_reply[$j][\'thumb\'],$news_reply[$j][\'title\'],$news_reply[$j][\'description\'],$news_reply[$j][\'media_id\']); 74 } 75 //视频 76 for ($d=0;$d<count($video_reply);$d++){ 77 $this->videoReply($postObj->FromUserName,$access_token,$video_reply[$d][\'mediaid\'],$video_reply[$d][\'title\'],$video_reply[$d][\'description\']); 78 } 79 //语音 80 for ($s=0;$s<count($voice_reply);$s++){ 81 $this->voiceReply($postObj->FromUserName,$access_token,$voice_reply[$s][\'mediaid\']); 82 } 83 //循环发送文字 84 for($i=0;$i<count($reply);$i++){ 85 if($i==count($reply)-1){ 86 return $reply[$i][\'content\']; 87 }else{ 88 $this->replymsg($postObj->FromUserName,$access_token,trim($reply[$i][\'content\'])); 89 } 90 } 91 } 92 return 0; 93 }
四、获取access token信息
我们自己写一个getToken()方法,需要修改$appid和$secret参数,修改为你自己公众号上的appid和secret
1 private function getToken(){ 2 $appid = "你自己的appid"; 3 $secret = "你自己的secret"; 4 $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$secret; 5 $ch = curl_init();//初始化 6 curl_setopt($ch, CURLOPT_URL, $url);//与url建立对话 7 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); //进行配置 8 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //进行配置 9 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//进行配置 10 $output = curl_exec($ch);//获取Access Token 11 curl_close($ch);//关闭会话 12 $jsoninfo = json_decode($output, true); 13 $access_token =$jsoninfo["access_token"]; 14 echo $access_token; 15 return $access_token; 16 }
五、写发送的方法
1 //发送文字的方法 2 private function replymsg($fromUsername,$access_token,$content){ 3 4 $data = \'{ 5 "touser":"\'.$fromUsername.\'", 6 "msgtype":"text", 7 "text": 8 { 9 "content":"\'.$content.\'" 10 } 11 }\'; 12 13 $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=".$access_token; 14 //$this->https_post($url,$data); 15 $result = $this->https_post($url,$data); 16 $final = json_decode($result); 17 return $final; 18 } 19 //发送图片的方法 20 private function imageReply($fromUsername,$access_token,$mediaId){ 21 $data=\'{ 22 "touser":"\'.$fromUsername.\'", 23 "msgtype":"image", 24 "image": 25 { 26 "media_id":"\'.$mediaId.\'" 27 } 28 }\'; 29 $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=".$access_token; 30 //$this->https_post($url,$data); 31 $result = $this->https_post($url,$data); 32 $final = json_decode($result); 33 return $final; 34 } 35 //发送图文的方法 36 private function newsReply($fromUsername,$access_token,$url,$picUrl,$title,$description,$mediaid){ 37 $data = \'{ 38 "touser":"\'.$fromUsername.\'", 39 "msgtype":"mpnews", 40 "mpnews":{ 41 "media_id":"\'.$mediaid.\'" 42 } 43 }\'; 44 $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=".$access_token; 45 //$this->https_post($url,$data); 46 $result = $this->https_post($url,$data); 47 $final = json_decode($result); 48 return $final; 49 } 50 //发送音乐的方法 51 private function musicReply($fromUsername,$access_token,$title,$description,$url,$hqurl){ 52 $data = \'{ 53 "touser":"\'.$fromUsername.\'", 54 "msgtype":"music", 55 "music": 56 { 57 "title":"\'.$title.\'", 58 "description":"\'.$description.\'", 59 "musicurl":"\'.$url.\'", 60 "hqmusicurl":"\'.$hqurl.\'" 61 } 62 }\'; 63 $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=".$access_token; 64 //$this->https_post($url,$data); 65 $result = $this->https_post($url,$data); 66 $final = json_decode($result); 67 return $final; 68 } 69 //语音 70 private function voiceReply($fromUsername,$access_token,$mediaid){ 71 $data=\' 72 { 73 "touser":"\'.$fromUsername.\'", 74 "msgtype":"voice", 75 "voice": 76 { 77 "media_id":"\'.$mediaid.\'" 78 } 79 } 80 \'; 81 $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=".$access_token; 82 //$this->https_post($url,$data); 83 $result = $this->https_post($url,$data); 84 $final = json_decode($result); 85 return $final; 86 } 87 //视频 88 private function videoReply($fromUsername,$access_token,$mediaid,$title,$description){ 89 $data = \' 90 { 91 "touser":"\'.$fromUsername.\'", 92 "msgtype":"video", 93 "video": 94 { 95 "media_id":"\'.$mediaid.\'", 96 "title":"\'.$title.\'", 97 "description":"\'.$description.\'" 98 } 99 } 100 \'; 101 $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=".$access_token; 102 //$this->https_post($url,$data); 103 $result = $this->https_post($url,$data); 104 $final = json_decode($result); 105 return $final; 106 }
六、https_post方法
1 private function https_post($url,$data) 2 { 3 $curl = curl_init(); 4 curl_setopt($curl, CURLOPT_URL, $url); 5 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); 6 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); 7 curl_setopt($curl, CURLOPT_POST, 1); 8 curl_setopt($curl, CURLOPT_POSTFIELDS, $data); 9 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 10 $result = curl_exec($curl); 11 if (curl_errno($curl)) { 12 return \'Errno\'.curl_error($curl); 13 } 14 curl_close($curl); 15 return $result; 16 }
7、展示一下效果吧
八、觉得本文章对你有帮助的麻烦动下手指点个赞呗
2020-10-29:附上优化后的全部代码。
<?php /** * [WeEngine System] Copyright (c) 2014 WE7.CC * WeEngine is NOT a free software, it under the license terms, visited http://www.we7.cc/ for more details. */ defined(\'IN_IA\') or exit(\'Access Denied\'); class CoreModuleProcessor extends WeModuleProcessor { private $data = []; //用于存入数据库获取的数据 private $newsAll=[]; //用于存入图文数据 public function weixinAccount() { static $weixinAccount; if(empty($weixinAccount))$weixinAccount = WeAccount::create($this->uniacid); return $weixinAccount; } public function respond() { $this->type_sort(); // 给$this->reply_type排序,把值为news的放在数组最后 $this->getReplyData(); // 获取数据库中的数据 if(count($this->data)==1){ return $this->oldRespond(); //按原来的方式处理 }else{ return $this->msg_respond(); //多条数据处理方法 } } public function oldRespond() { $reply_type = $this->reply_type; $key = array_rand($reply_type); $type = $reply_type[$key]; switch($type) { case \'basic\': $result = $this->basic_respond(); return $this->respText($result); break; case \'images\': $result = $this->image_respond(); return $this->respImage($result); break; case \'music\': $result = $this->music_respond(); return $this->respMusic(array( \'Title\' => $result[\'title\'], \'Description\' => $result[\'description\'], \'MusicUrl\' => $result[\'url\'], \'HQMusicUrl\' => $result[\'hqurl\'], )); break; case \'news\': $result = $this->news_respond(); return $this->respNews($result); break; case \'voice\': $result = $this->voice_respond(); return $this->respVoice($result); break; case \'video\': $result = $this->video_respond(); return $this->respVideo(array( \'MediaId\' => $result[\'mediaid\'], \'Title\' => $result[\'title\'], \'Description\' => $result[\'description\'] )); break; } } private function basic_respond() { $sql = "SELECT * FROM " . tablename(\'basic_reply\') . " WHERE `rid` IN ({$this->rule}) ORDER BY RAND() LIMIT 1"; $reply = pdo_fetch($sql); if (empty($reply)) { return false; } $reply[\'content\'] = htmlspecialchars_decode($reply[\'content\']); $reply[\'content\'] = str_replace(array(\'<br>\', \' \'), array("\n", \' \'), $reply[\'content\']); $reply[\'content\'] = strip_tags($reply[\'content\'], \'<a>\'); return $reply[\'content\']; } private function image_respond() { global $_W; $rid = $this->rule; $sql = "SELECT `mediaid` FROM " . tablename(\'images_reply\') . " WHERE `rid`=:rid ORDER BY RAND()"; $mediaid = pdo_fetchcolumn($sql, array(\':rid\' => $rid)); if (empty($mediaid)) { return false; } return $mediaid; } private function music_respond() { global $_W; $rid = $this->rule; $sql = "SELECT * FROM " . tablename(\'music_reply\') . " WHERE `rid`=:rid ORDER BY RAND()"; $item = pdo_fetch($sql, array(\':rid\' => $rid)); if (empty($item[\'id\'])) { return false; } return $item; } private function news_respond() { global $_W; load()->model(\'material\'); $rid = $this->rule; $sql = "SELECT * FROM " . tablename(\'news_reply\') . " WHERE rid = :id AND parent_id = -1 ORDER BY displayorder DESC, id ASC LIMIT 8"; $commends = pdo_fetchall($sql, array(\':id\' => $rid)); if (empty($commends)) { $sql = "SELECT * FROM " . tablename(\'news_reply\') . " WHERE rid = :id AND parent_id = 0 ORDER BY RAND()"; $main = pdo_fetch($sql, array(\':id\' => $rid)); if(empty($main[\'id\'])) { return false; } $sql = "SELECT * FROM " . tablename(\'news_reply\') . " WHERE id = :id OR parent_id = :parent_id ORDER BY displayorder ASC, id ASC LIMIT 8"; $commends = pdo_fetchall($sql, array(\':id\'=>$main[\'id\'], \':parent_id\'=>$main[\'id\'])); } if(empty($commends)) { return false; } $news = array(); if (!empty($commends[0][\'media_id\'])) { $news = material_build_reply($commends[0][\'media_id\']); } foreach($commends as $key => $commend) { $row = array(); if (!empty($commend[\'media_id\'])) { if (empty($news[$key][\'url\'])) { $news[$key][\'url\'] = $this->createMobileUrl(\'detail\', array(\'id\' => $commend[\'id\'])); } } else { $row[\'title\'] = $commend[\'title\']; $row[\'description\'] = $commend[\'description\']; !empty($commend[\'thumb\']) && $row[\'picurl\'] = tomedia($commend[\'thumb\']); $row[\'url\'] = empty($commend[\'url\']) ? $this->createMobileUrl(\'detail\', array(\'id\' => $commend[\'id\'])) : $commend[\'url\']; $news[] = $row; } } return $news; } private function voice_respond() { global $_W; $rid = $this->rule; $sql = "SELECT `mediaid` FROM " . tablename(\'voice_reply\') . " WHERE `rid`=:rid ORDER BY RAND()"; $mediaid = pdo_fetchcolumn($sql, array(\':rid\' => $rid)); if (empty($mediaid)) { return false; } return $mediaid; } private function video_respond() { global $_W; $rid = $this->rule; $sql = "SELECT * FROM " . tablename(\'video_reply\') . " WHERE `rid`=:rid ORDER BY RAND()"; $item = pdo_fetch($sql, array(\':rid\' => $rid)); if (empty($item)) { return false; } return $item; } /***************************************************微擎二次开发代码************************************************************/ /** * 多条消息发送方法 * @return int */ private function msg_respond() { $data = $this->data; if (empty($data)) return false; $open_id = $this->message[\'fromusername\']; //获取openid foreach ($this->reply_type as $type){ if ($type == "news") { for ($j = 0; $j < count($data); $j++) { $this->newsAll = $this->data[\'news\']; //直接从数据中获取 } //对id字段进行排序 $this->newsAll = iarray_sort($this->newsAll, \'id\'); if ($this->newsAll) {//发送 //组成xml $newsXml = "<xml> <ToUserName><![CDATA[{$open_id}]]></ToUserName> <FromUserName><![CDATA[{$this->message[\'tousername\']}]]></FromUserName> <CreateTime>" . time() . "</CreateTime> <MsgType><![CDATA[news]]></MsgType> <ArticleCount>" . count($this->newsAll) . "</ArticleCount> <Articles>"; foreach ($this->newsAll as $value) { $newsXml .= "<item> <Title><![CDATA[{$value[\'title\']}]]></Title> <Description><![CDATA[{$value[\'description\']}]]></Description> <PicUrl><![CDATA[{$value[\'thumb\']}]]></PicUrl> <Url><![CDATA[{$value[\'url\']}]]></Url> </item>"; } unset($this->newsAll); $newsXml .= "</Articles> </xml>"; // exit($newsXml); /*加密*/ $encryptMsg = $this->weixinAccount()->encryptMsg($newsXml); $encryptMsg = $this->weixinAccount()->xmlDetract($encryptMsg); exit($encryptMsg); } }else{ $this->Reply($type,$data[$type]); } } return 0; } /** * 获取数据库中的数据,并存入data中 */ private function getReplyData(){ foreach ($this->reply_type as $value) { $table_name = $value . "_reply"; $sql = "SELECT * FROM " . tablename($table_name) . " WHERE `rid` IN ({$this->rule})"; $this->data[$value] = pdo_fetchall($sql); } unset($sql); } /** * 功能:微信公众号构造消息发送数据方法 * 开发者:MingGyGy * 时间:2020年1月3日 * @param $type string * @param $param array * @return array */ private function typeToData($type,$param){ $data = [ "touser"=>$this->message[\'from\'], ]; switch($type) { case \'basic\': $data["msgtype"] = \'text\'; $data[\'text\'] = [ \'content\'=>urlencode($param[\'content\']) ]; break; case \'news\': $data["msgtype"] = \'link\'; $data["mpnews"] = [ \'title\'=>$param[\'title\'], \'description\' => $param[\'description\'], \'url\' => $param[\'url\'], \'thumb\' => $param[\'thumb\'] ]; break; case \'images\': $data["msgtype"] = \'image\'; $data["image"] = [ \'media_id\'=>$param[\'media_id\'] ]; break; case \'music\': $data["msgtype"] = \'music\'; $data["music"] = [ \'title\'=>$param[\'title\'], \'description\'=>$param[\'description\'], \'musicurl\'=>$param[\'musicurl\'], \'hqmusicurl\'=>$param[\'hqmusicurl\'] ]; break; case \'voice\': $data["msgtype"] = \'voice\'; $data = ["voice"=>[ \'media_id\'=>$param[\'media_id\'] ]]; break; case \'video\': $data["msgtype"] = \'video\'; $data["video"] = [ \'media_id\'=>$param[\'media_id\'], \'title\'=>$param[\'title\'], \'description\'=>$param[\'description\'] ]; break; } return $data; } /** * 功能:封装发送方法 * 开发者:MingGyGy * 时间:2020年1月3日 * @param $type */ private function Reply($type,$datas) { foreach($datas as $value) { $param = []; switch ($type) { case \'basic\': $param["content"] = $value["content"]; break; case \'images\': case \'voice\': $param[\'media_id\'] = $value["mediaid"]; break; case \'video\': $param[\'media_id\'] = $value["media_id"]; $param[\'title\'] = $value[\'title\']; $param[\'description\'] = $value[\'description\']; break; case \'news\': $param[\'title\'] = $value[\'title\']; $param[\'description\'] = $value[\'description\']; $param[\'url\'] = $value[\'url\']; $param[\'thumb\'] = $value[\'thumb\']; } $data = $this->typeToData($type, $param); $this->weixinAccount()->sendCustomNotice($data); } } /** * 功能:对$this->reply_type进行排序,把值为news放数组最后 * 开发者:MingGyGy * 时间:2020年1月3日 */ private function type_sort() { if(in_array(\'news\',$this->reply_type)){ $key = array_search(\'news\',$this->reply_type); unset($this->reply_type[$key]); $this->reply_type[] = \'news\'; } } }