本API为笔者本人所写,包括微信公众平台几乎所有的接口、接口调用方法以及错误返回码等。所有函数名称均利用接口的英文名,便于查找和使用、后期会持续优化。关于各个接口的调用的案例、会持续更新。
<?php
/**
* Author: helen
* CreateTime: 2015/12/9 20:14
* description: 微信公众平台接口API
*/
class Wechat{
/**
* @FunctionDescription:验证开发者服务器url有效性
* @Param:token(令牌 用户手动输入的配置信息)
* @Return:echostr(随机字符串)
* @Description:
* @Author:helen zheng
*/
public function valid($token){
$echostr = $_GET['echostr'];
if($this->checkSignature($token)){
echo $echostr;
exit;
}
}
/**
* @FunctionDescription:检验signature函数
* @Param:token(令牌 用户手动输入的配置信息)
* @Return:true/false
* @Description:微信服务器发送get请求将signature、timestamp、nonce、echostr四个参数发送到开发者提供的url,利用接收到的参数进行验证。
* @Author:helen zheng
*/
function checkSignature($token){
/*获取微信发送确认的参数。*/
$signature = $_GET['signature']; /*微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。*/
$timestamp = $_GET['timestamp']; /*时间戳 */
$nonce = $_GET['nonce']; /*随机数 */
$echostr = $_GET['echostr']; /*随机字符串*/
/*加密/校验流程*/
/*1. 将token、timestamp、nonce三个参数进行字典序排序*/
$array = array($token,$timestamp,$nonce);
sort($array,SORT_STRING);
/*2. 将三个参数字符串拼接成一个字符串进行sha1加密*/
$str = sha1( implode($array) );
/*3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信*/
if( $str==$signature && $echostr ){
return ture;
}else{
return false;
}
}
/**
* @FunctionDescription:获取access_token
* @Param:AppID(第三方用户唯一凭证 ),AppSecret(第三方用户唯一凭证密钥)
* @Return:access_token( string(length=117))
* @Description:access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。
* @Author:helen zheng
*/
public function getToken($appid,$appsecret){
$url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appid.'&secret='.$appsecret;
$result = $this->request_get($url);
$res = $this->resultProcess($result);
if($res==$result){ /*接口返回值*/
return($result);
}else{ /*接口调用错误信息*/
return($res);
}
}
/**
* @FunctionDescription:获取微信服务器的IP地址列表
* @Param:access_token(公众号的access_token )
* @Return:
* @Description:安全验证
* @Author:helen zheng
*/
public function getWeixinIP($access_token){
$url = 'https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token='.$access_token;
$result = $this->request_get($url);
$res = $this->resultProcess($result);
if($res==$result){ /*接口返回值*/
return($result);
}else{ /*接口调用错误信息*/
return($res);
}
}
/**
* @FunctionDescription:接收消息响应(回复)函数(可与自定义回复接口、语义理解接口、客服接口结合)
* @Param:
* @Return:接收消息类型
* @Description:?当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。
* @Author:helen zheng
*/
public function responseMsg(){
/*1,获取到微信推送过来post数据(xml格式)*/
$postArr = $GLOBALS['HTTP_RAW_POST_DATA'];
/*2,处理消息类型,并设置回复类型和内容*/
$postObj = simplexml_load_string($postArr);
/*判断用户发送消息的类型(普通消息、事件推送)*/
$MsgType = strtolower($postObj->MsgType);
$Event = strtolower($postObj->Event);
if(isset($Event)){ /*事件推送*/
switch($Event){
case 'subscribe' : /*return '订阅事件(扫描带参数二维码事件(用户未关注))';*/
$template = '<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
</xml>';
break;
case 'unsubscribe' : /*return '取消订阅事件';*/
$template ='<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[unsubscribe]]></Event>
</xml>';
break;
case 'scan' : /*return '扫描带参数二维码事件(用户已关注)';*/
$template = '<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
<EventKey><![CDATA[qrscene_123123]]></EventKey>
<Ticket><![CDATA[TICKET]]></Ticket>
</xml>';
break;
case 'location' : /*return '上报地理位置事件';*/
$template = '<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[LOCATION]]></Event>
<Latitude>23.137466</Latitude>
<Longitude>113.352425</Longitude>
<Precision>119.385040</Precision>
</xml>';
break;
case 'click' : /*return '自定义菜单事件(点击菜单拉取消息时的事件推送)';*/
$template = '<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[CLICK]]></Event>
<EventKey><![CDATA[EVENTKEY]]></EventKey>
</xml>';
break;
case 'view' : /*return '自定义菜单事件(点击菜单跳转链接时的事件推送)';*/
$template = '<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[VIEW]]></Event>
<EventKey><![CDATA[www.qq.com]]></EventKey>
</xml>';
break;
case 'scancode_push' : /*return '自定义菜单事件(扫码推事件的事件推送 )'*/
$template = '<xml>
<ToUserName><![CDATA[gh_e136c6e50636]]></ToUserName>
<FromUserName><![CDATA[oMgHVjngRipVsoxg6TuX3vz6glDg]]></FromUserName>
<CreateTime>1408090502</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[scancode_push]]></Event>
<EventKey><![CDATA[6]]></EventKey>
<ScanCodeInfo>
<ScanType><![CDATA[qrcode]]></ScanType>
<ScanResult><![CDATA[1]]></ScanResult>
</ScanCodeInfo>
</xml>';
break;
case 'scancode_waitmsg' : /*return '自定义菜单事件(扫码推事件且弹出“消息接收中”提示框的事件推送 )'*/
$template = '<xml>
<ToUserName><![CDATA[gh_e136c6e50636]]></ToUserName>
<FromUserName><![CDATA[oMgHVjngRipVsoxg6TuX3vz6glDg]]></FromUserName>
<CreateTime>1408090606</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[scancode_waitmsg]]></Event>
<EventKey><![CDATA[6]]></EventKey>
<ScanCodeInfo>
<ScanType><![CDATA[qrcode]]></ScanType>
<ScanResult><![CDATA[2]]></ScanResult>
</ScanCodeInfo>
</xml>';
break;
case 'pic_sysphoto' : /*return '自定义菜单事件(弹出系统拍照发图的事件推送 )'*/
$template = '<xml>
<ToUserName><![CDATA[gh_e136c6e50636]]></ToUserName>
<FromUserName><![CDATA[oMgHVjngRipVsoxg6TuX3vz6glDg]]></FromUserName>
<CreateTime>1408090651</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[pic_sysphoto]]></Event>
<EventKey><![CDATA[6]]></EventKey>
<SendPicsInfo>
<Count>1</Count>
<PicList>
<item>
<PicMd5Sum><![CDATA[1b5f7c23b5bf75682a53e7b6d163e185]]></PicMd5Sum>
</item>
</PicList>
</SendPicsInfo>
</xml>';
break;
case 'pic_photo_or_album' : /*return '自定义菜单事件(弹出拍照或者相册发图的事件推送 )'*/
$template = '<xml>
<ToUserName><![CDATA[gh_e136c6e50636]]></ToUserName>
<FromUserName><![CDATA[oMgHVjngRipVsoxg6TuX3vz6glDg]]></FromUserName>
<CreateTime>1408090816</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[pic_photo_or_album]]></Event>
<EventKey><![CDATA[6]]></EventKey>
<SendPicsInfo>
<Count>1</Count>
<PicList>
<item>
<PicMd5Sum><![CDATA[5a75aaca956d97be686719218f275c6b]]></PicMd5Sum>
</item>
</PicList>
</SendPicsInfo>
</xml>';
break;
case 'pic_weixin' : /*return '自定义菜单事件(弹出微信相册发图器的事件推送 )'*/
$template = '<xml>
<ToUserName><![CDATA[gh_e136c6e50636]]></ToUserName>
<FromUserName><![CDATA[oMgHVjngRipVsoxg6TuX3vz6glDg]]></FromUserName>
<CreateTime>1408090816</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[pic_weixin]]></Event>
<EventKey><![CDATA[6]]></EventKey>
<SendPicsInfo>
<Count>1</Count>
<PicList>
<item>
<PicMd5Sum><![CDATA[5a75aaca956d97be686719218f275c6b]]></PicMd5Sum>
</item>
</PicList>
</SendPicsInfo>
</xml>';
break;
case 'location_select' : /*return '自定义菜单事件(弹出地理位置选择器的事件推送)'*/
$template = '<xml>
<ToUserName><![CDATA[gh_e136c6e50636]]></ToUserName>
<FromUserName><![CDATA[oMgHVjngRipVsoxg6TuX3vz6glDg]]></FromUserName>
<CreateTime>1408091189</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[location_select]]></Event>
<EventKey><![CDATA[6]]></EventKey>
<SendLocationInfo>
<Location_X><![CDATA[23]]></Location_X>
<Location_Y><![CDATA[113]]></Location_Y>
<Scale><![CDATA[15]]></Scale>
<Label><![CDATA[ 广州市海珠区客村艺苑路 106号]]></Label>
<Poiname><![CDATA[]]></Poiname>
</SendLocationInfo>
</xml>';
break;
default : /*return '未知事件类型';*/
break;
}
}else{ /*普通消息(自动回复扩展)*/
switch($MsgType){
case 'text' : /*return '文本信息';*/
$Content = '您发送的为文本,内容为:'.$postObj->Content;
break;
case 'image' : /*return '图片消息';*/
$Content = '您发送的为图片,图片链接为:'.$postObj->PicUrl;
break;
case 'voice' : /*return '语音消息';*/
$Content = '您发送的为语音,媒体ID为:'.$postObj->MediaId;
break;
case 'video' : /*return '视频消息';*/
$Content = '您发送的为视频,媒体ID为:'.$postObj->MediaId;
break;
case 'shortvideo' : /*return '小视频消息';*/
$Content = '您发送的为小视频,媒体ID为:'.$postObj->MediaId;
break;
case 'location' : /*return '地理位置消息';*/
$Content = '您发送的为地理位置消息,位置为: '.$postObj->Label.'纬度为: '.$postObj->Location_X.'经度为: '.$postObj->Location_Y;
break;
case 'link' : /*return '链接消息';*/
$Content = '您发送的为链接消息,标题为: '.$postObj->Title.'内容为: '.$postObj->Description.'链接地址为: '.$postObj->Url;
break;
default : /*return '未知消息类型';*/
$Content = '抱歉,请重新输入!';
break;
}
}
/*响应消息*/
$FromUserName = $postObj->ToUserName;
$ToUserName = $postObj->FromUserName;
$MsgType = 'text'; /*暂时响应均利用文本消息的形式*/
$CreateTime = time();
$template = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>";
$info = sprintf($template,$ToUserName,$FromUserName,$CreateTime,$MsgType,$Content);
echo $info;
}
/**
* @FunctionDescription:发送(回复)消息
* @Param:回复消息类型(回复图文消息,需添加第二个参数 类型为array 四个字段(title、description、picUrl、url) )
* @Return:
* @Description:根据回复消息选定的类型进行特定类型的回复
* @Author:helen zheng
*/
public function transmitMsg($MsgType,$array=null){
/*1,获取到微信推送过来post数据(xml格式)*/
$postArr = $GLOBALS['HTTP_RAW_POST_DATA'];
/*2,处理消息类型,并设置回复类型和内容*/
$postObj = simplexml_load_string($postArr);
/*判断用户发送消息的类型(普通消息、事件推送)*/
/*响应消息*/
$FromUserName = $postObj->ToUserName;
$ToUserName = $postObj->FromUserName;
$CreateTime = time();
switch($MsgType){ /*回复消息*/
case 'text' : /*return '文本信息';*/
$Content = '';
$template = '<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>';
$info = sprintf($template,$ToUserName,$FromUserName,$CreateTime,$MsgType,$Content);
break;
case 'image' : /*return '图片消息';*/
$MediaId = '';
$template = '<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Image>
<MediaId><![CDATA[%s]]></MediaId>
</Image>
</xml>';
$info = sprintf($template,$ToUserName,$FromUserName,$CreateTime,$MsgType,$MediaId);
break;
case 'voice' : /*return '语音消息';*/
$MediaId = '';
$template = '<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Voice>
<MediaId><![CDATA[%s]]></MediaId>
</Voice>
</xml>';
$info = sprintf($template,$ToUserName,$FromUserName,$CreateTime,$MsgType,$MediaId);
break;
case 'video' : /*return '视频消息';*/
$MediaId = '';
$Title = '';
$Description = '';
$template = '<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Video>
<MediaId><![CDATA[%s]]></MediaId>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
</Video>
</xml>';
$info = sprintf($template,$ToUserName,$FromUserName,$CreateTime,$MsgType,$MediaId,$Title,$Description);
break;
case 'music' : /*return '音乐消息';*/
$Title = '';
$Description = '';
$MusicUrl = '';
$HQMusicUrl = '';
$ThumbMediaId = '';
$template = '<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Music>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<MusicUrl><![CDATA[%s]]></MusicUrl>
<HQMusicUrl><![CDATA[%s]]></HQMusicUrl>
<ThumbMediaId><![CDATA[%s]]></ThumbMediaId>
</Music>
</xml>';
$info = sprintf($template,$ToUserName,$FromUserName,$CreateTime,$MsgType,$Title,$Description,$MusicUrl,$HQMusicUrl,$ThumbMediaId);
case 'news' : /*return '图文消息'(根据传入的数据可发送多条图文消息);*/
$template = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<ArticleCount>".count($array)."</ArticleCount>
<Articles>";
foreach