微信接口基本类 与连接
<?php
/**
* 微信公众平台操作类
*/
class WeChat {
private $_appid;
private $_appsecret;
private $_token;// 公众平台请求开发者时需要标记
//表示QRCode的类型
const QRCODE_TYPE_TEMP = 1;
const QRCODE_TYPE_LIMIT = 2;
const QRCODE_TYPE_LIMIT_STR = 3;
private $_msg_template = array(
'text' => '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[%s]]></Content></xml>',//文本回复XML模板
'image' => '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[image]]></MsgType><Image><MediaId><![CDATA[%s]]></MediaId></Image></xml>',//图片回复XML模板
'music' => '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[music]]></MsgType><Music><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description><MusicUrl><![CDATA[%s]]></MusicUrl><HQMusicUrl><![CDATA[%s]]></HQMusicUrl><ThumbMediaId><![CDATA[%s]]></ThumbMediaId></Music></xml>',//音乐模板
'news' => '<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[news]]></MsgType><ArticleCount>%s</ArticleCount><Articles>%s</Articles></xml>',// 新闻主体
'news_item' => '<item><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description><PicUrl><![CDATA[%s]]></PicUrl><Url><![CDATA[%s]]></Url></item>',//某个新闻模板
);
public function __construct($id, $secret, $token) {
$this->_appid = $id;
$this->_appsecret = $secret;
$this->_token = $token;
}
/**
* 设置菜单
*/
public function menuSet($menu) {
$url = 'https://api.weixin.qq.com/cgi-bin/menu/create?access_token=' . $this->_getAccessToken();
$data = $menu;
$result = $this->_requestPost($url, $data);
if ($result_obj->errcode == 0) {
return true;
} else {
echo $result_obj->errmsg, '<br>';
return false;
}
}
/**
* 菜单删除
*/
public function menuDelete() {
$url = 'https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=' . $this->_getAccessToken();
$result = $this->_requestGet($url);
$result_obj = json_decode($result);
if ($result_obj->errcode == 0) {
return true;
} else {
return false;
}
}
public function responseMSG() {
// 获取请求时POST:XML字符串
// $_POST,不是key/value型因此不能使用该数组
$xml_str = $GLOBALS['HTTP_RAW_POST_DATA'];
// 如果没有post数据,则响应空字符串表示结束
if (empty($xml_str)) {
die ('');
}
// 解析该xml字符串,利用simpleXML
libxml_disable_entity_loader(true);//禁止xml实体解析,防止xml注入
$request_xml = simplexml_load_string($xml_str, 'SimpleXMLElement', LIBXML_NOCDATA);//从字符串获取simpleXML对象
// 判断该消息的类型通过元素:MsgType
switch ($request_xml->MsgType) {
case 'event': // 事件类型
// 判断具体的事件类型(关注,取消,点击)
$event = $request_xml->Event;
if ('subscribe'==$event) { // 关注事件
$this->_doSubscribe($request_xml);
}
elseif ('CLICK' == $event) { //菜单点击事件
$this->_doClick($request_xml);
}
elseif ('VIEW' == $event) { //连接跳转事件
$this->_doView($request_xml);
}
break;
case 'text': // 文本消息
$this->_doText($request_xml);
break;
case 'image': // 图片消息
$this->_doImage($request_xml);
break;
case 'voice': // 语音消息
$this->_doVoice($request_xml);
break;
case 'video': // 视频消息
$this->_doVideo($request_xml);
break;
case 'shortvideo': // 短视频消息
$this->_doShortVideo($request_xml);
break;
case 'location': // 位置消息
$this->_doLocation($request_xml);
break;
case 'link': // 连接消息
$this->_doLink($request_xml);
break;
default:
# code...
break;
}
}
private function _doClick($request_xml) {
$content = '你点击了菜单,携带的KEY为: ' . $request_xml->EventKey;
$this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $content);
}
/**
* 用于处理文本消息的方法
*/
private function _doText($request_xml) {
// 获取文本内容
$content = $request_xml->Content;
// 对内容进行判断
if ('?' == $content) {
// 显示帮助信息
$response_content = '输入对应序号或名称,获取相应资源' . "\n" . '[1]PHP'."\n". '[2]Java' . "\n" . '[3]C++';
// 将处理好的响应数据回复给用户
$this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $response_content);
} elseif ('1' == strtolower($content) || 'php'==strtolower($content)) {
$response_content = 'PHP工程师培训: ' . "\n" . 'http://php.itcast.cn/';
// 将处理好的响应数据回复给用户
$this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $response_content);
}
elseif ('2' == strtolower($content) || 'java'==strtolower($content)) {
$response_content = 'Java工程师培训: ' . "\n" . 'http://java.itcast.cn/';
// 将处理好的响应数据回复给用户
$this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $response_content);
}
elseif ('3' == strtolower($content) || 'c++'==strtolower($content)) {
$response_content = 'C++工程师培训: ' . "\n" . 'http://c.itcast.cn/';
// 将处理好的响应数据回复给用户
$this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $response_content);
}
elseif ('图片' == $content) {
$id_list = array(
'eLrmGKbhf5kS86A9bqzkLS8-45sWvqBwUv4Q7XDd-oAds44Ad9hxq9h-ShmRQLyJ',
'0Fnq-gYU8zDugqxjPNywkhW5KSHXT6DdF-NGovaPfKry8grmheEVdEkdeY8qjZ--');
$rand_index = mt_rand(0, count($id_list)-1);
// 具体那张图片,应该由业务逻辑决定
$this->_msgImage($request_xml->FromUserName, $request_xml->ToUserName, $id_list[$rand_index], true);
}
elseif ('音乐' == $content) {
$music_url = 'http://weixin.fortheday.cn/dnaw.mp3';
$ha_music_url = 'http://weixin.fortheday.cn/dnaw.mp3';
$thumb_media_id = '0Fnq-gYU8zDugqxjPNywkhW5KSHXT6DdF-NGovaPfKry8grmheEVdEkdeY8qjZ--';
$title = '等你爱我';
$desc = '等你爱我-等到地老天荒';
$this->_msgMusic($request_xml->FromUserName, $request_xml->ToUserName, $music_url, $hq_music_url, $thumb_media_id, $title, $desc);
}
elseif ('新闻' == $content) {
$item_list = array(
array('title'=>'其实你该用母亲的方式回报母亲', 'desc'=>'母亲节快乐', 'picurl'=>'http://weixin.fortheday.cn/1.jpg', 'url'=>'http://www.soso.com/'),
array('title'=>'母亲节宠爱不手软,黄金秒杀豪礼特惠值到爆', 'desc'=>'母亲节快乐', 'picurl'=>'http://weixin.fortheday.cn/2.jpg', 'url'=>'http://www.soso.com/'),
array('title'=>'浅从财富管理视角看巴菲特思想', 'desc'=>'母亲节快乐', 'picurl'=>'http://weixin.fortheday.cn/3.jpg', 'url'=>'http://www.soso.com/'),
array('title'=>'广邀好友打气,赢取万元旅游金', 'desc'=>'母亲节快乐', 'picurl'=>'http://weixin.fortheday.cn/4.jpg', 'url'=>'http://www.soso.com/'),
);
$this->_msgNews($request_xml->FromUserName, $request_xml->ToUserName, $item_list);
}
else {
// 通过小黄鸡,响应给微信用户
$url = 'http://www.xiaohuangji.com/ajax.php';
$data['para'] = $content;
$response_content = $this->_requestPost($url, $data, false);
}
}
/**
* 处理图片响应数据
*/
private function _doImage($request_xml) {
$content = '你所上传的图片的Media_ID:' . $request_xml->MediaId;
$this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $content);
}
private function _doLocation($request_xml) {
// $content = '你的坐标为,经度:'.$request_xml->Location_Y.',纬度:'.$request_xml->Location_X . "\n" . '你所在的位置为:' . $request_xml->Label;
// $this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $content);
// 利用位置获取信息
//百度LBS圆形范围查询:
$url = 'http://api.map.baidu.com/place/v2/search?query=%s&location=%s&radius=%s&output=%s&ak=%s';
$query = '银行';
$location = $request_xml->Location_X . ',' . $request_xml->Location_Y;
$radius = 2000;
$output = 'json';
$ak = 'OBDl6igKrng0V6VqT5RWIP6z';
$url = sprintf($url, urlencode($query), $location, $radius, $output, $ak);
$result = $this->_requestGet($url, false);
$result_obj = json_decode($result);
$re_list = array();
foreach($result_obj->results as $re) {
$r['name'] = $re->name;
$r['address'] = $re->address;
$re_list[] = implode('-', $r);
}
$re_str = implode("\n", $re_list);
//
$this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $re_str);
}
/**
* 用于处理关注事件的方法
* @param [type] $request_xml 事件信息对象
* @return [type] [description]
*/
private function _doSubscribe($request_xml) {
// 利用消息发送,完成向关注用户打招呼功能!
$content = '感谢你关注,会向你发送优惠信息,请查收';
$this->_msgText($request_xml->FromUserName, $request_xml->ToUserName, $content);
}
/**
* 发送文本信息
* @param [type] $to 目标用户ID
* @param [type] $from 来源用户ID
* @param [type] $content 内容
* @return [type] [description]
*/
private function _msgText($to, $from, $content) {
$response = sprintf($this->_msg_template['text'], $to, $from, time(), $content);
die($response);
}
/**
* 发送图片消息
* @param [type] $to [description]
* @param [type] $from [description]
* @param [type] $file 图片文件地址
* @return [type] [description]
*/
private function _msgImage($to, $from, $file, $is_id=false) {
if ($is_id) {
$media_id = $file;
} else {
// 上传图片到微信公众服务器,获取mediaID
$result_obj = $this->uploadTmp($file, 'image');
$media_id = $result_obj->media_id;
}
// 拼凑图像类消息xml文件
$response = sprintf($this->_msg_template['image'], $to, $from, time(), $media_id);
die($response);
}
/**
* [_msgMusic description]
* @param [type] $to [description]
* @param [type] $from [description]
* @param [type] $music_url [description]
* @param [type] $thumb_media_id [description]
* @param string $title [description]
* @param string $desc [description]
* @return [type] [description]
*/
private function _msgMusic($to, $from, $music_url, $hq_music_url, $thumb_media_id, $title='', $desc='') {
$response = sprintf($this->_msg_template['music'], $to, $from, time(), $title, $desc, $music_url, $hq_music_url, $thumb_media_id);
die($response);
}
private function _msgNews($to, $from, $item_list=array()) {
// 拼凑文章部分
$item_str = '';
foreach($item_list as $item) {
$item_str .= sprintf($this->_msg_template['news_item'], $item['title'], $item['desc'], $item['picurl'], $item['url']);
}
//拼凑整体图文部分
$response = sprintf($this->_msg_template['news'], $to, $from, time(), count($item_list), $item_str);
die($response);
}
/**
* 上传临时素材
*/
public function uploadTmp($file, $type) {
$url = 'https://api.weixin.qq.com/cgi-bin/media/upload?access_token='.$this->_getAccessToken() .'&type='.$type;
$data['media'] = '@'. $file;
$result = $this->_requestPost($url, $data);
$result_obj = json_decode($result);
return $result_obj;
}
/**
* 用于第一次验证URL合法性
*/
public function firstValid() {
// 检验签名的合法性
if ($this->_checkSignature()) {
// 签名合法,告知微信公众平台服务器
echo $_GET['echostr'];
}
}
/**
* 验证签名
* @return bool [description]
*/
private function _checkSignature() {
// 获得由微信公众平台请求的验证数据
$signature = $_GET['signature'];
$timestamp = $_GET['timestamp'];
$nonce = $_GET['nonce'];
// 将时间戳,随机字符串,token按照字母顺序排序并连接
$tmp_arr = array($this->_token, $timestamp, $nonce);
sort($tmp_arr, SORT_STRING);// 字典顺序
$tmp_str = implode($tmp_arr);//连接
$tmp_str = sha1($tmp_str);// sha1签名
if ($signature == $tmp_str) {
return true;
} else {
return false;
}
}
/**
* 获取 access_tonken
* @param string $token_file 用来存储token的临时文件
*/
private function _getAccessToken($token_file='./access_token') {
// 考虑过期问题,将获取的access_token存储到某个文件中
$life_time = 7200;
if (file_exists($token_file) && time()-filemtime($token_file)<$life_time) {
// 存在有效的access_token
return file_get_contents($token_file);
}
// 目标URL:
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->_appid}&secret={$this->_appsecret}";
//向该URL,发送GET请求
$result = $this->_requestGet($url);
if (!$result) {
return false;
}
// 存在返回响应结果
$result_obj = json_decode($result);
// 写入
file_put_contents($token_file, $result_obj->access_token);
return $result_obj->access_token;
}
/**
* [getQRCodeTicket description]
* @param $content 内容
* @param $type qr码类型
* @param $expire 有效期,如果是临时的类型则需要该参数
* @return string ticket
*/
private function _getQRCodeTicket($content, $type=2, $expire=604800) {
$access_token = $this->_getAccessToken();
$url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=$access_token";
$type_list = array(
self::QRCODE_TYPE_TEMP => 'QR_SCENE',
self::QRCODE_TYPE_LIMIT => 'QR_LIMIT_SCENE',
self::QRCODE_TYPE_LIMIT_STR => 'QR_LIMIT_STR_SCENE',
);
$action_name = $type_list[$type];
switch ($type) {
case self::QRCODE_TYPE_TEMP:
// {"expire_seconds": 604800, "action_name": "QR_SCENE", "action_info": {"scene": {"scene_id": 123}}}
$data_arr['expire_seconds'] = $expire;
$data_arr['action_name'] = $action_name;
$data_arr['action_info']['scene']['scene_id'] = $content;
break;
case self::QRCODE_TYPE_LIMIT:
case self::QRCODE_TYPE_LIMIT_STR:
$data_arr['action_name'] = $action_name;
$data_arr['action_info']['scene']['scene_id'] = $content;
break;
}
$data = json_encode($data_arr);
$result = $this->_requestPost($url, $data);
if (!$result) {
return false;
}
//处理响应数据
$result_obj = json_decode($result);
return $result_obj->ticket;
}
/**
* [getQRCode description]
* @param int|string $content qrcode内容标识
* @param [type] $file 存储为文件的地址,如果为NULL表示直接输出
* @param integer $type 类型
* @param integer $expire 如果是临时,表示其有效期
* @return [type] [description]
*/
public function getQRCode($content, $file=NULL, $type=2, $expire=604800) {
// 获取ticket
$ticket = $this->_getQRCodeTicket($content, $type=2, $expire=604800);
$url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=$ticket";
$result = $this->_requestGet($url);//此时result就是图像内容
if ($file) {
file_put_contents($file, $result);
} else {
header('Content-Type: image/jpeg');
echo $result;
}
}
private function _requestPost($url, $data, $ssl=true) {
// curl完成
$curl = curl_init();
//设置curl选项
curl_setopt($curl, CURLOPT_URL, $url);//URL
$user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0 FirePHP/0.7.4';
curl_setopt($curl, CURLOPT_USERAGENT, $user_agent);//user_agent,请求代理信息
curl_setopt($curl, CURLOPT_AUTOREFERER, true);//referer头,请求来源
curl_setopt($curl, CURLOPT_TIMEOUT, 30);//设置超时时间
//SSL相关
if ($ssl) {
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);//禁用后cURL将终止从服务端进行验证
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//检查服务器SSL证书中是否存在一个公用名(common name)。
}
// 处理post相关选项
curl_setopt($curl, CURLOPT_POST, true);// 是否为POST请求
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);// 处理请求数据
// 处理响应结果
curl_setopt($curl, CURLOPT_HEADER, false);//是否处理响应头
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);//curl_exec()是否返回响应结果
// 发出请求
$response = curl_exec($curl);
if (false === $response) {
echo '<br>', curl_error($curl), '<br>';
return false;
}
curl_close($curl);
return $response;
}
/**
* 发送GET请求的方法
* @param string $url URL
* @param bool $ssl 是否为https协议
* @return string 响应主体Content
*/
private function _requestGet($url, $ssl=true) {
// curl完成
$curl = curl_init();
//设置curl选项
curl_setopt($curl, CURLOPT_URL, $url);//URL
$user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0 FirePHP/0.7.4';
curl_setopt($curl, CURLOPT_USERAGENT, $user_agent);//user_agent,请求代理信息
curl_setopt($curl, CURLOPT_AUTOREFERER, true);//referer头,请求来源
curl_setopt($curl, CURLOPT_TIMEOUT, 30);//设置超时时间
//SSL相关
if ($ssl) {
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);//禁用后cURL将终止从服务端进行验证
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//检查服务器SSL证书中是否存在一个公用名(common name)。
}
curl_setopt($curl, CURLOPT_HEADER, false);//是否处理响应头
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);//curl_exec()是否返回响应结果
// 发出请求
$response = curl_exec($curl);
if (false === $response) {
echo '<br>', curl_error($curl), '<br>';
return false;
}
curl_close($curl);
return $response;
}
}
入口
<?php
header('Content-Type: text/html; charset=utf8');
require './WeChat.class.php';
define('APPID', 'wxe647b92b9dc39f1b');
define('APPSECRET', 'e16374d53b5b78bf25fd7e29e3d58c46');
define('TOKEN', 'itcast_php34');
$wechat = new WeChat(APPID, APPSECRET, TOKEN);
// 第一次验证:
// $wechat->firstValid();
//
// 处理威信公众平台的的消息(事件)
$wechat->responseMSG();

浙公网安备 33010602011771号