微信公众平台开发接口PHP SDK完整版

官方提供的SDK只有一个文本消息功能,我们将所有消息的消息类型及事件响应都整理了进来,并且加入日志记录,代码如下:

 

更新日志:

2013-01-01 版本1.0,包含Token验证及基本消息接口的收发
2014-03-15 增加图片、视频、语音的内容回复
2014-04-09 增加菜单链接事件
2014-04-10 修改文本回复的判定方法
2014-05-20 增加高级群发消息通知事件
2014-05-26 增加多客服消息及多客服的判定方法
2014-05-27 修改自动回复判定方式
2014-06-20 修复多图文回复的Bug
2014-07-10 增加第三方接口处理样式
2014-08-02 增加Emoji表格的回复处理
2014-10-01 增加自定义菜单扫一扫、发图片、发地理位置等接口的处理
2014-10-25 增加消息体签名及加解密的支持
2014-11-07 增加该公众号暂时无法提供服务请稍后再试的兼容
2014-12-20 移除高级群发消息通知事件,必要性不大
2015-02-23 移除消息体签名及加解密的支持,必要性不大
2015-04-07 优化客服模式和自动回复模式的判定
2015-05-16 优化日志记录,兼容SAE和自有主机

 

  1 <?php
  2 /*
  3     方倍工作室 http://www.fangbei.org/
  4     CopyRight 2015 All Rights Reserved
  5 */
  6 
  7 define("TOKEN", "weixin");
  8 
  9 $wechatObj = new wechatCallbackapiTest();
 10 if (!isset($_GET['echostr'])) {
 11     $wechatObj->responseMsg();
 12 }else{
 13     $wechatObj->valid();
 14 }
 15 
 16 class wechatCallbackapiTest
 17 {
 18     //验证签名
 19     public function valid()
 20     {
 21         $echoStr = $_GET["echostr"];
 22         $signature = $_GET["signature"];
 23         $timestamp = $_GET["timestamp"];
 24         $nonce = $_GET["nonce"];
 25         $token = TOKEN;
 26         $tmpArr = array($token, $timestamp, $nonce);
 27         sort($tmpArr, SORT_STRING);
 28         $tmpStr = implode($tmpArr);
 29         $tmpStr = sha1($tmpStr);
 30         if($tmpStr == $signature){
 31             echo $echoStr;
 32             exit;
 33         }
 34     }
 35 
 36     //响应消息
 37     public function responseMsg()
 38     {
 39         $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
 40         if (!empty($postStr)){
 41             $this->logger("R \r\n".$postStr);
 42             $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
 43             $RX_TYPE = trim($postObj->MsgType);
 44 
 45             if (($postObj->MsgType == "event") && ($postObj->Event == "subscribe" || $postObj->Event == "unsubscribe")){
 46                 //过滤关注和取消关注事件
 47             }else{
 48                 
 49             }
 50             
 51             //消息类型分离
 52             switch ($RX_TYPE)
 53             {
 54                 case "event":
 55                     $result = $this->receiveEvent($postObj);
 56                     break;
 57                 case "text":
 58                    if (strstr($postObj->Content, "第三方")){
 59                         $result = $this->relayPart3("http://www.fangbei.org/test.php".'?'.$_SERVER['QUERY_STRING'], $postStr);
 60                     }else{
 61                         $result = $this->receiveText($postObj);
 62                     }
 63                     break;
 64                 case "image":
 65                     $result = $this->receiveImage($postObj);
 66                     break;
 67                 case "location":
 68                     $result = $this->receiveLocation($postObj);
 69                     break;
 70                 case "voice":
 71                     $result = $this->receiveVoice($postObj);
 72                     break;
 73                 case "video":
 74                     $result = $this->receiveVideo($postObj);
 75                     break;
 76                 case "link":
 77                     $result = $this->receiveLink($postObj);
 78                     break;
 79                 default:
 80                     $result = "unknown msg type: ".$RX_TYPE;
 81                     break;
 82             }
 83             $this->logger("T \r\n".$result);
 84             echo $result;
 85         }else {
 86             echo "";
 87             exit;
 88         }
 89     }
 90 
 91     //接收事件消息
 92     private function receiveEvent($object)
 93     {
 94         $content = "";
 95         switch ($object->Event)
 96         {
 97             case "subscribe":
 98                 $content = "欢迎关注方倍工作室 ";
 99                 $content .= (!empty($object->EventKey))?("\n来自二维码场景 ".str_replace("qrscene_","",$object->EventKey)):"";
100                 break;
101             case "unsubscribe":
102                 $content = "取消关注";
103                 break;
104             case "CLICK":
105                 switch ($object->EventKey)
106                 {
107                     case "COMPANY":
108                         $content = array();
109                         $content[] = array("Title"=>"方倍工作室", "Description"=>"", "PicUrl"=>"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958");
110                         break;
111                     default:
112                         $content = "点击菜单:".$object->EventKey;
113                         break;
114                 }
115                 break;
116             case "VIEW":
117                 $content = "跳转链接 ".$object->EventKey;
118                 break;
119             case "SCAN":
120                 $content = "扫描场景 ".$object->EventKey;
121                 break;
122             case "LOCATION":
123                 $content = "上传位置:纬度 ".$object->Latitude.";经度 ".$object->Longitude;
124                 break;
125             case "scancode_waitmsg":
126                 if ($object->ScanCodeInfo->ScanType == "qrcode"){
127                     $content = "扫码带提示:类型 二维码 结果:".$object->ScanCodeInfo->ScanResult;
128                 }else if ($object->ScanCodeInfo->ScanType == "barcode"){
129                     $codeinfo = explode(",",strval($object->ScanCodeInfo->ScanResult));
130                     $codeValue = $codeinfo[1];
131                     $content = "扫码带提示:类型 条形码 结果:".$codeValue;
132                 }else{
133                     $content = "扫码带提示:类型 ".$object->ScanCodeInfo->ScanType." 结果:".$object->ScanCodeInfo->ScanResult;
134                 }
135                 break;
136             case "scancode_push":
137                 $content = "扫码推事件";
138                 break;
139             case "pic_sysphoto":
140                 $content = "系统拍照";
141                 break;
142             case "pic_weixin":
143                 $content = "相册发图:数量 ".$object->SendPicsInfo->Count;
144                 break;
145             case "pic_photo_or_album":
146                 $content = "拍照或者相册:数量 ".$object->SendPicsInfo->Count;
147                 break;
148             case "location_select":
149                 $content = "发送位置:标签 ".$object->SendLocationInfo->Label;
150                 break;
151             default:
152                 $content = "receive a new event: ".$object->Event;
153                 break;
154         }
155 
156         if(is_array($content)){
157             if (isset($content[0]['PicUrl'])){
158                 $result = $this->transmitNews($object, $content);
159             }else if (isset($content['MusicUrl'])){
160                 $result = $this->transmitMusic($object, $content);
161             }
162         }else{
163             $result = $this->transmitText($object, $content);
164         }
165         return $result;
166     }
167 
168     //接收文本消息
169     private function receiveText($object)
170     {
171         $keyword = trim($object->Content);
172         //多客服人工回复模式
173         if (strstr($keyword, "请问在吗") || strstr($keyword, "在线客服")){
174             $result = $this->transmitService($object);
175             return $result;
176         }
177 
178         //自动回复模式
179         if (strstr($keyword, "文本")){
180             $content = "这是个文本消息";
181         }else if (strstr($keyword, "表情")){
182             $content = "中国:".$this->bytes_to_emoji(0x1F1E8).$this->bytes_to_emoji(0x1F1F3)."\n仙人掌:".$this->bytes_to_emoji(0x1F335);
183         }else if (strstr($keyword, "单图文")){
184             $content = array();
185             $content[] = array("Title"=>"单图文标题",  "Description"=>"单图文内容", "PicUrl"=>"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958");
186         }else if (strstr($keyword, "图文") || strstr($keyword, "多图文")){
187             $content = array();
188             $content[] = array("Title"=>"多图文1标题", "Description"=>"", "PicUrl"=>"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958");
189             $content[] = array("Title"=>"多图文2标题", "Description"=>"", "PicUrl"=>"http://d.hiphotos.bdimg.com/wisegame/pic/item/f3529822720e0cf3ac9f1ada0846f21fbe09aaa3.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958");
190             $content[] = array("Title"=>"多图文3标题", "Description"=>"", "PicUrl"=>"http://g.hiphotos.bdimg.com/wisegame/pic/item/18cb0a46f21fbe090d338acc6a600c338644adfd.jpg", "Url" =>"http://m.cnblogs.com/?u=txw1958");
191         }else if (strstr($keyword, "音乐")){
192             $content = array();
193             $content = array("Title"=>"最炫民族风", "Description"=>"歌手:凤凰传奇", "MusicUrl"=>"http://121.199.4.61/music/zxmzf.mp3", "HQMusicUrl"=>"http://121.199.4.61/music/zxmzf.mp3"); 
194         }else{
195             $content = date("Y-m-d H:i:s",time())."\nOpenID:".$object->FromUserName."\n技术支持 方倍工作室";
196         }
197 
198         if(is_array($content)){
199             if (isset($content[0])){
200                 $result = $this->transmitNews($object, $content);
201             }else if (isset($content['MusicUrl'])){
202                 $result = $this->transmitMusic($object, $content);
203             }
204         }else{
205             $result = $this->transmitText($object, $content);
206         }
207         return $result;
208     }
209 
210     //接收图片消息
211     private function receiveImage($object)
212     {
213         $content = array("MediaId"=>$object->MediaId);
214         $result = $this->transmitImage($object, $content);
215         return $result;
216     }
217 
218     //接收位置消息
219     private function receiveLocation($object)
220     {
221         $content = "你发送的是位置,经度为:".$object->Location_Y.";纬度为:".$object->Location_X.";缩放级别为:".$object->Scale.";位置为:".$object->Label;
222         $result = $this->transmitText($object, $content);
223         return $result;
224     }
225 
226     //接收语音消息
227     private function receiveVoice($object)
228     {
229         if (isset($object->Recognition) && !empty($object->Recognition)){
230             $content = "你刚才说的是:".$object->Recognition;
231             $result = $this->transmitText($object, $content);
232         }else{
233             $content = array("MediaId"=>$object->MediaId);
234             $result = $this->transmitVoice($object, $content);
235         }
236         return $result;
237     }
238 
239     //接收视频消息
240     private function receiveVideo($object)
241     {
242         $content = array("MediaId"=>$object->MediaId, "ThumbMediaId"=>$object->ThumbMediaId, "Title"=>"", "Description"=>"");
243         $result = $this->transmitVideo($object, $content);
244         return $result;
245     }
246 
247     //接收链接消息
248     private function receiveLink($object)
249     {
250         $content = "你发送的是链接,标题为:".$object->Title.";内容为:".$object->Description.";链接地址为:".$object->Url;
251         $result = $this->transmitText($object, $content);
252         return $result;
253     }
254 
255     //回复文本消息
256     private function transmitText($object, $content)
257     {
258         if (!isset($content) || empty($content)){
259             return "";
260         }
261 
262         $xmlTpl = "<xml>
263     <ToUserName><![CDATA[%s]]></ToUserName>
264     <FromUserName><![CDATA[%s]]></FromUserName>
265     <CreateTime>%s</CreateTime>
266     <MsgType><![CDATA[text]]></MsgType>
267     <Content><![CDATA[%s]]></Content>
268 </xml>";
269         $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time(), $content);
270 
271         return $result;
272     }
273 
274     //回复图文消息
275     private function transmitNews($object, $newsArray)
276     {
277         if(!is_array($newsArray)){
278             return "";
279         }
280         $itemTpl = "        <item>
281             <Title><![CDATA[%s]]></Title>
282             <Description><![CDATA[%s]]></Description>
283             <PicUrl><![CDATA[%s]]></PicUrl>
284             <Url><![CDATA[%s]]></Url>
285         </item>
286 ";
287         $item_str = "";
288         foreach ($newsArray as $item){
289             $item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);
290         }
291         $xmlTpl = "<xml>
292     <ToUserName><![CDATA[%s]]></ToUserName>
293     <FromUserName><![CDATA[%s]]></FromUserName>
294     <CreateTime>%s</CreateTime>
295     <MsgType><![CDATA[news]]></MsgType>
296     <ArticleCount>%s</ArticleCount>
297     <Articles>
298 $item_str    </Articles>
299 </xml>";
300 
301         $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time(), count($newsArray));
302         return $result;
303     }
304 
305     //回复音乐消息
306     private function transmitMusic($object, $musicArray)
307     {
308         if(!is_array($musicArray)){
309             return "";
310         }
311         $itemTpl = "<Music>
312         <Title><![CDATA[%s]]></Title>
313         <Description><![CDATA[%s]]></Description>
314         <MusicUrl><![CDATA[%s]]></MusicUrl>
315         <HQMusicUrl><![CDATA[%s]]></HQMusicUrl>
316     </Music>";
317 
318         $item_str = sprintf($itemTpl, $musicArray['Title'], $musicArray['Description'], $musicArray['MusicUrl'], $musicArray['HQMusicUrl']);
319 
320         $xmlTpl = "<xml>
321     <ToUserName><![CDATA[%s]]></ToUserName>
322     <FromUserName><![CDATA[%s]]></FromUserName>
323     <CreateTime>%s</CreateTime>
324     <MsgType><![CDATA[music]]></MsgType>
325     $item_str
326 </xml>";
327 
328         $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time());
329         return $result;
330     }
331 
332     //回复图片消息
333     private function transmitImage($object, $imageArray)
334     {
335         $itemTpl = "<Image>
336         <MediaId><![CDATA[%s]]></MediaId>
337     </Image>";
338 
339         $item_str = sprintf($itemTpl, $imageArray['MediaId']);
340 
341         $xmlTpl = "<xml>
342     <ToUserName><![CDATA[%s]]></ToUserName>
343     <FromUserName><![CDATA[%s]]></FromUserName>
344     <CreateTime>%s</CreateTime>
345     <MsgType><![CDATA[image]]></MsgType>
346     $item_str
347 </xml>";
348 
349         $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time());
350         return $result;
351     }
352 
353     //回复语音消息
354     private function transmitVoice($object, $voiceArray)
355     {
356         $itemTpl = "<Voice>
357         <MediaId><![CDATA[%s]]></MediaId>
358     </Voice>";
359 
360         $item_str = sprintf($itemTpl, $voiceArray['MediaId']);
361         $xmlTpl = "<xml>
362     <ToUserName><![CDATA[%s]]></ToUserName>
363     <FromUserName><![CDATA[%s]]></FromUserName>
364     <CreateTime>%s</CreateTime>
365     <MsgType><![CDATA[voice]]></MsgType>
366     $item_str
367 </xml>";
368 
369         $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time());
370         return $result;
371     }
372 
373     //回复视频消息
374     private function transmitVideo($object, $videoArray)
375     {
376         $itemTpl = "<Video>
377         <MediaId><![CDATA[%s]]></MediaId>
378         <ThumbMediaId><![CDATA[%s]]></ThumbMediaId>
379         <Title><![CDATA[%s]]></Title>
380         <Description><![CDATA[%s]]></Description>
381     </Video>";
382 
383         $item_str = sprintf($itemTpl, $videoArray['MediaId'], $videoArray['ThumbMediaId'], $videoArray['Title'], $videoArray['Description']);
384 
385         $xmlTpl = "<xml>
386     <ToUserName><![CDATA[%s]]></ToUserName>
387     <FromUserName><![CDATA[%s]]></FromUserName>
388     <CreateTime>%s</CreateTime>
389     <MsgType><![CDATA[video]]></MsgType>
390     $item_str
391 </xml>";
392 
393         $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time());
394         return $result;
395     }
396 
397     //回复多客服消息
398     private function transmitService($object)
399     {
400         $xmlTpl = "<xml>
401     <ToUserName><![CDATA[%s]]></ToUserName>
402     <FromUserName><![CDATA[%s]]></FromUserName>
403     <CreateTime>%s</CreateTime>
404     <MsgType><![CDATA[transfer_customer_service]]></MsgType>
405 </xml>";
406         $result = sprintf($xmlTpl, $object->FromUserName, $object->ToUserName, time());
407         return $result;
408     }
409 
410     //回复第三方接口消息
411     private function relayPart3($url, $rawData)
412     {
413         $headers = array("Content-Type: text/xml; charset=utf-8");
414         $ch = curl_init();
415         curl_setopt($ch, CURLOPT_URL, $url);
416         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
417         curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
418         curl_setopt($ch, CURLOPT_POST, 1);
419         curl_setopt($ch, CURLOPT_POSTFIELDS, $rawData);
420         $output = curl_exec($ch);
421         curl_close($ch);
422         return $output;
423     }
424 
425     //字节转Emoji表情
426     function bytes_to_emoji($cp)
427     {
428         if ($cp > 0x10000){       # 4 bytes
429             return chr(0xF0 | (($cp & 0x1C0000) >> 18)).chr(0x80 | (($cp & 0x3F000) >> 12)).chr(0x80 | (($cp & 0xFC0) >> 6)).chr(0x80 | ($cp & 0x3F));
430         }else if ($cp > 0x800){   # 3 bytes
431             return chr(0xE0 | (($cp & 0xF000) >> 12)).chr(0x80 | (($cp & 0xFC0) >> 6)).chr(0x80 | ($cp & 0x3F));
432         }else if ($cp > 0x80){    # 2 bytes
433             return chr(0xC0 | (($cp & 0x7C0) >> 6)).chr(0x80 | ($cp & 0x3F));
434         }else{                    # 1 byte
435             return chr($cp);
436         }
437     }
438 
439     //日志记录
440     private function logger($log_content)
441     {
442         if(isset($_SERVER['HTTP_APPNAME'])){   //SAE
443             sae_set_display_errors(false);
444             sae_debug($log_content);
445             sae_set_display_errors(true);
446         }else if($_SERVER['REMOTE_ADDR'] != "127.0.0.1"){ //LOCAL
447             $max_size = 1000000;
448             $log_filename = "log.xml";
449             if(file_exists($log_filename) and (abs(filesize($log_filename)) > $max_size)){unlink($log_filename);}
450             file_put_contents($log_filename, date('Y-m-d H:i:s')." ".$log_content."\r\n", FILE_APPEND);
451         }
452     }
453 }
454 ?>

 

本程序在新浪云、阿里云、腾讯云、百度云 均测试通过。

不会使用,或者使用出错的朋友,请参考微信开发入门教程,地址:http://www.cnblogs.com/txw1958/p/wechat-tutorial.html

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Wechatext为非官方微信发送API * 注: 用户id为通过getMsg()方法获取的FakeId值 * 主要实现如下功能: * send($id,$content) 向某用户id发送微信文字信息 * getUserList($page,$pagesize,$group) 获取用户信息 * getGroupList($page,$pagesize) 获取群组信息 * sendNews($id,$msgid) 发送图文消息 * getNewsList($page,$pagesize) 获取图文信息列表 * uploadFile($filepath,$type) 上传附件,包括图片/音频/视频 * addPreview($title,$author,$summary,$content,$photoid,$srcurl='') 创建新的图文信息 * getFileList($type,$page,$pagesize) 获取素材库文件列表 * sendImage($id,$fid) 发送图片消息 * sendAudio($id,$fid) 发送音频消息 * sendVideo($id,$fid) 发送视频消息 * getInfo($id) 根据id获取用户资料 * getNewMsgNum($lastid) 获取从$lastid算起新消息的数目 * getTopMsg() 获取最新一条消息的数据, 此方法获取的消息id可以作为检测新消息的$lastid依据 * getMsg($lastid,$offset=0,$perpage=50,$day=0,$today=0,$star=0) 获取最新的消息列表, 列表将返回消息id, 用户id, 消息类型, 文字消息等参数 * 消息返回结构: {"id":"消息id","type":"类型号(1为文字,2为图片,3为语音)","fileId":"0","hasReply":"0","fakeId":"用户uid","nickName":"昵称","dateTime":"时间戳","content":"文字内容"} * getMsgImage($msgid,$mode='large') 若消息type类型为2, 调用此方法获取图片数据 * getMsgVoice($msgid) 若消息type类型为3, 调用此方法获取语音数据
微信公众平台 PHP 开发包,细化了微信的各项接口操作。调用官方API,具有更灵活的消息分类响应方式,支持链式调用操作 。 主要功能 接入验证 (初级权限) 自动回复(文本、图片、语音、视频、音乐、图文) (初级权限) 菜单操作(查询、创建、删除) (菜单权限) 客服消息(文本、图片、语音、视频、音乐、图文) (认证权限) 二维码(创建临时、永久二维码,获取二维码URL) (服务号、认证权限) 长链接转短链接接口 (服务号、认证权限) 分组操作(查询、创建、修改、移动用户到分组) (认证权限) 网页授权(基本授权,用户信息授权) (服务号、认证权限) 用户信息(查询用户基本信息、获取关注者列表) (认证权限) 多客服功能(客服管理、获取客服记录、客服会话管理) (认证权限) 媒体文件(上传、获取) (认证权限) 高级群发 (认证权限) 模板消息(设置所属行业、添加模板、发送模板消息) (服务号、认证权限) 卡券管理(创建、修改、删除、发放、门店管理等) (认证权限) 语义理解 (服务号、认证权限) 获取微信服务器IP列表 (初级权限) 微信JSAPI授权(获取ticket、获取签名) (初级权限) 数据统计(用户、图文、消息、接口分析数据) (认证权限) > 备注: > 初级权限:基本权限,任何正常的公众号都有此权限 > 菜单权限:正常的服务号、认证后的订阅号拥有此权限 > 认证权限:分为订阅号、服务号认证,如前缀服务号则仅认证的服务号有此权限,否则为认证后的订阅号、服务号都有此权限 > 支付权限:仅认证后的服务号可以申请此权限 初始化动作  $options = array(     'token'=>'tokenaccesskey', //填写你设定的key     'encodingaeskey'=>'encodingaeskey', //填写加密用的EncodingAESKey     'appid'=>'wxdk1234567890', //填写高级调用功能的app id, 请在微信开发模式后台查询     'appsecret'=>'xxxxxxxxxxxxxxxxxxx' //填写高级调用功能的密钥     );  $weObj = new Wechat($options); //创建实例对象  //TODO:调用$weObj各实例方法   标签:wechat

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值