一:Wechat.php
<?php
define("TOKEN", "abcdefg");
/**
* 微信公众平台 PHP SDK
*
* @author NetPuter <netputer@gmail.com>
*/
/**
* 微信公众平台处理类
*/
class Wechat {
/**
* 调试模式,将错误通过文本消息回复显示
*
* @var boolean
*/
private $debug;
public $controller;
/**
* 以数组的形式保存微信服务器每次发来的请求
*
* @var array
*/
private $request;
/**
* 初始化,判断此次请求是否为验证请求,并以数组形式保存
*
* @param string $token 验证信息
* @param boolean $debug 调试模式,默认为关闭
*/
public function __construct($token,$debug) {
if (!$this->validateSignature($token)) {
exit('签名验证失败');
}
if ($this->isValid()) {
// 网址接入验证
exit($_GET['echostr']);
}
if (!isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
exit('缺少数据');
}
$this->debug = $debug;
set_error_handler(array(&$this, 'errorHandler'));
// 设置错误处理函数,将错误通过文本消息回复显示
$xml = (array) simplexml_load_string($GLOBALS['HTTP_RAW_POST_DATA'], 'SimpleXMLElement', LIBXML_NOCDATA);
$this->request = array_change_key_case($xml, CASE_LOWER);
// 将数组键名转换为小写,提高健壮性,减少因大小写不同而出现的问题
}
/**
* 判断此次请求是否为验证请求
*
* @return boolean
*/
private function isValid() {
return isset($_GET['echostr']);
}
/**
* 验证此次请求的签名信息
*
* @param string $token 验证信息
* @return boolean
*/
private function validateSignature($token) {
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
//$tmp = $signature."----".$timestamp."------". $nonce;
//file_put_contents("test.txt", $tmp);
$token = TOKEN;
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr, SORT_STRING);
$tmpStr = implode( $tmpArr );
$tmpStr = sha1( $tmpStr );
if( $tmpStr == $signature ){
return true;
}else{
return false;
}
}
/**
* 获取本次请求中的参数,不区分大小
*
* @param string $param 参数名,默认为无参
* @return mixed
*/
protected function getRequest($param = FALSE) {
if ($param === FALSE) {
return $this->request;
}
$param = strtolower($param);
if (isset($this->request[$param])) {
return $this->request[$param];
}
return NULL;
}
/**
* 用户关注时触发,用于子类重写
*
* @return void
*/
protected function onSubscribe() {}
/**
* 用户取消关注时触发,用于子类重写
*
* @return void
*/
protected function onUnsubscribe() {}
/**
* 用户点击菜单,用于子类重写
*
* @return void
*/
protected function onCLICK() {}
/**
* 收到文本消息时触发,用于子类重写
*
* @return void
*/
protected function onText() {}
/**
* 收到图片消息时触发,用于子类重写
*
* @return void
*/
protected function onImage() {}
/**
* 收到地理位置消息时触发,用于子类重写
*
* @return void
*/
protected function onLocation() {}
/**
* 收到链接消息时触发,用于子类重写
*
* @return void
*/
protected function onLink() {}
/**
* 收到未知类型消息时触发,用于子类重写
*
* @return void
*/
protected function onUnknown() {}
/**
* 回复文本消息
*
* @param string $content 消息内容
* @param integer $funcFlag 默认为0,设为1时星标刚才收到的消息
* @return void
*/
protected function responseText($content, $funcFlag = 0) {
exit(new TextResponse($this->getRequest('fromusername'), $this->getRequest('tousername'), $content, $funcFlag));
}
/**
* 回复音乐消息
*
* @param string $title 音乐标题
* @param string $description 音乐描述
* @param string $musicUrl 音乐链接
* @param string $hqMusicUrl 高质量音乐链接,Wi-Fi 环境下优先使用
* @param integer $funcFlag 默认为0,设为1时星标刚才收到的消息
* @return void
*/
protected function responseMusic($title, $description, $musicUrl, $hqMusicUrl, $funcFlag = 0) {
exit(new MusicResponse($this->getRequest('fromusername'), $this->getRequest('tousername'), $title, $description, $musicUrl, $hqMusicUrl, $funcFlag));
}
/**
* 回复图文消息
* @param array $items 由单条图文消息类型 NewsResponseItem() 组成的数组
* @param integer $funcFlag 默认为0,设为1时星标刚才收到的消息
* @return void
*/
protected function responseNews($items, $funcFlag = 0) {
exit(new NewsResponse($this->getRequest('fromusername'), $this->getRequest('tousername'), $items, $funcFlag));
}
/**
* 分析消息类型,并分发给对应的函数
*
* @return void
*/
public function run() {
switch ($this->getRequest('msgtype')) {
case 'event':
switch ($this->getRequest('event')) {
case 'subscribe':
$this->onSubscribe();
break;
case 'unsubscribe':
$this->onUnsubscribe();
break;
case 'CLICK':
$this->onCLICK();
break;
}
break;
case 'text':
$this->onText();
break;
case 'image':
$this->onImage();
break;
case 'location':
$this->onLocation();
break;
case 'link':
$this->onLink();
break;
default:
$this->onUnknown();
break;
}
}
/**
* 自定义的错误处理函数,将 PHP 错误通过文本消息回复显示
* @param int $level 错误代码
* @param string $msg 错误内容
* @param string $file 产生错误的文件
* @param int $line 产生错误的行数
* @return void
*/
protected function errorHandler($level, $msg, $file, $line) {
if ( ! $this->debug) {
return;
}
$error_type = array(
// E_ERROR => 'Error',
E_WARNING => 'Warning',
// E_PARSE => 'Parse Error',
E_NOTICE => 'Notice',
// E_CORE_ERROR => 'Core Error',
// E_CORE_WARNING => 'Core Warning',
// E_COMPILE_ERROR => 'Compile Error',
// E_COMPILE_WARNING => 'Compile Warning',
E_USER_ERROR => 'User Error',
E_USER_WARNING => 'User Warning',
E_USER_NOTICE => 'User Notice',
E_STRICT => 'Strict',
E_RECOVERABLE_ERROR => 'Recoverable Error',
E_DEPRECATED => 'Deprecated',
E_USER_DEPRECATED => 'User Deprecated',
);
$template = <<<ERR
PHP 报错啦!
%s: %s
File: %s
Line: %s
ERR;
$this->responseText(sprintf($template,
$error_type[$level],
$msg,
$file,
$line
));
}
}
/**
* 用于回复的基本消息类型
*/
abstract class WechatResponse {
protected $toUserName;
protected $fromUserName;
protected $funcFlag;
protected $template;
public function __construct($toUserName, $fromUserName, $funcFlag) {
$this->toUserName = $toUserName;
$this->fromUserName = $fromUserName;
$this->funcFlag = $funcFlag;
}
abstract public function __toString();
}
/**
* 用于回复的文本消息类型
*/
class TextResponse extends WechatResponse {
protected $content;
public function __construct($toUserName, $fromUserName, $content, $funcFlag = 0) {
parent::__construct($toUserName, $fromUserName, $funcFlag);
$this->content = $content;
$this->template = <<<XML
<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>%s<FuncFlag>
</xml>
XML;
}
public function __toString() {
return sprintf($this->template,
$this->toUserName,
$this->fromUserName,
time(),
$this->content,
$this->funcFlag
);
}
}
/**
* 用于回复的音乐消息类型
*/
class MusicResponse extends WechatResponse {
protected $title;
protected $description;
protected $musicUrl;
protected $hqMusicUrl;
public function __construct($toUserName, $fromUserName, $title, $description, $musicUrl, $hqMusicUrl, $funcFlag) {
parent::__construct($toUserName, $fromUserName, $funcFlag);
$this->title = $title;
$this->description = $description;
$this->musicUrl = $musicUrl;
$this->hqMusicUrl = $hqMusicUrl;
$this->template = <<<XML
<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>
</Music>
<FuncFlag>%s<FuncFlag>
</xml>
XML;
}
public function __toString() {
return sprintf($this->template,
$this->toUserName,
$this->fromUserName,
time(),
$this->title,
$this->description,
$this->musicUrl,
$this->hqMusicUrl,
$this->funcFlag
);
}
}
/**
* 用于回复的图文消息类型
*/
class NewsResponse extends WechatResponse {
protected $items = array();
public function __construct($toUserName, $fromUserName, $items, $funcFlag) {
parent::__construct($toUserName, $fromUserName, $funcFlag);
$this->items = $items;
$this->template = <<<XML
<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<ArticleCount>%s</ArticleCount>
<Articles>
%s
</Articles>
<FuncFlag>%s<FuncFlag>
</xml>
XML;
}
public function __toString() {
return sprintf($this->template,
$this->toUserName,
$this->fromUserName,
time(),
count($this->items),
implode($this->items),
$this->funcFlag
);
}
}
/**
* 单条图文消息类型
*/
class NewsResponseItem {
protected $title;
protected $description;
protected $picUrl;
protected $url;
protected $template;
public function __construct($title, $description, $picUrl, $url) {
$this->title = $title;
$this->description = $description;
$this->picUrl = $picUrl;
$this->url = $url;
$this->template = <<<XML
<item>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<PicUrl><![CDATA[%s]]></PicUrl>
<Url><![CDATA[%s]]></Url>
</item>
XML;
}
public function __toString() {
return sprintf($this->template,
$this->title,
$this->description,
$this->picUrl,
$this->url
);
}
}
二:home.php
<?phprequire('Wechat.php');
class MyWechat extends Wechat {
/**
* 用户关注时触发,回复「欢迎关注」
*
* @return void
*/
protected function onSubscribe() {
$this->responseText('亲mo-可爱,你怎么才来关注小天天啊!这里是天才宝贝中国专门为辣妈帅爸服务和互动的新媒体平台。回复【开始】即刻就能与小天天进行亲密互动哦~来吧~');
}
/**
* 用户取消关注时触发
*
* @return void
*/
protected function onUnsubscribe() {
$this->responseText('');
}
/**
* 收到文本消息时触发,回复收到的文本消息内容
*
* @return void
*/
protected function onText() {
//$this->responseText('系统中没有此员工编号,请确认');
}
/**
* 收到图片消息时触发,回复由收到的图片组成的图文消息
*
* @return void
*/
protected function onImage() {
}
/**
* 收到地理位置消息时触发,回复收到的地理位置
*
* @return void
*/
protected function onLocation() {
}
/**
* 收到链接消息时触发,回复收到的链接地址
*
* @return void
*/
protected function onLink() {
//$this->responseText('收到了链接:' . $this->getRequest('url'));
}
/**
* 收到未知类型消息时触发,回复收到的消息类型
*
* @return void
*/
protected function onUnknown() {
//$this->responseText('收到了未知类型消息:' . $this->getRequest('msgtype'));
}
/**
* 收到菜单点击,回复收到的消息类型
*
* @return void
*/
protected function onCLICK() {
$eventKey = $this->getRequest('EventKey');
$FromUserName = $this->getRequest('FromUserName');
$title = "";
$message = "";
if($eventKey=="bind"){
$title = '微信号绑定';
$url = "此功能的访问地址";
$this->responseText('点击链接进入'.$title.": ".$url."/".$FromUserName);
}
if($eventKey=="info"){
$title = '会员资料';
$url = "此功能的访问地址";
}
if($eventKey=="video"){
$title = '课程视频';
$url = "此功能的访问地址";
}
if($eventKey=="report"){
$title = '学科报告';
$url = "此功能的访问地址";
}
if($eventKey=="discover"){
$title = '我的发现';
$url = "此功能的访问地址";
}
$items = array(
new NewsResponseItem($title, $title, "项目图片路径".$eventKey.".png", $url."/".$FromUserName)
);
$this->responseNews($items);
}
}
$wechat = new MyWechat(TOKEN, TRUE);
$wechat->run();
// setMenu();
function setMenu(){
$wechatmenu = array();
$wechatmenu[0] = array("type"=>"view","name"=>urlencode("微官网"),"url"=>"此功能的访问地址");
$wechatmenu[1] = array("name"=>urlencode("会员专区"),"sub_button"=>array(array("type"=>"click","name"=>urlencode("微信号绑定"),"key"=>"bind"),
array("type"=>"click","name"=>urlencode("会员资料"),"key"=>"info"),
array("type"=>"click","name"=>urlencode("课程视频"),"key"=>"video"),
array("type"=>"click","name"=>urlencode("学科报告"),"key"=>"report"),
array("type"=>"click","name"=>urlencode("我的发现"),"key"=>"discover")));
$wechatmenu[2] = array("name"=>urlencode("课程预约"),"sub_button"=>array(array("type"=>"view","name"=>urlencode("课程介绍"),"url"=>"此功能的访问地址"),
array("type"=>"view","name"=>urlencode("预约体验课"),"url"=>"此功能的访问地址"),
array("type"=>"view","name"=>urlencode("CPI测试预约"),"url"=>"此功能的访问地址")));
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx641bef10d416a71b&secret=5f2b7cb171d74b966b9964bb04ffe0b7";
//echo $url;
//echo urlencode($wechatmenu);exit;
$tokenarr = json_decode(file_get_contents($url));
$token = $tokenarr->access_token;
$menudata = urldecode(json_encode(array("button"=>$wechatmenu)));
//var_dump($menudata);exit;
//$menudata = json_encode(array("button"=>$wechatmenu));
//$menudata = urldecode(json_encode(urlencode($wechatmenu)));
//$menudata = json_encode(array("button"=>$wechatmenu),JSON_UNESCAPED_UNICODE);
//echo $menudata;
//var_dump(C("WX_MENU"));
//echo $menudata;exit;
var_dump($menudata);
$retarr = createMenu($menudata,$token);
//echo 'ddd2ddd';exit;
$ret = json_decode($retarr,true);
//var_dump($wxarr);var_dump($ret);exit;
if ($ret["errcode"]!=0) {
die($ret["errmsg"]);
}else{
die("菜单已更新");
}
}
//创建菜单
function createMenu($data,$token){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$token);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$tmpInfo = curl_exec($ch);
echo $tmpInfo;exit;
if (curl_errno($ch)) {
return curl_error($ch);
}
curl_close($ch);
return $tmpInfo;
}
function get( $url, $cookie='' ) {
// 初始化一个cURL会话
$curl = curl_init($url);
// 不显示header信息
curl_setopt($curl, CURLOPT_HEADER, 0);
// 将 curl_exec()获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
// 使用自动跳转
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
if(!empty($cookie)) {
// 包含cookie数据的文件名,cookie文件的格式可以是Netscape格式,或者只是纯HTTP头部信息存入文件。
curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie);
}
// 自动设置Referer
curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
// 执行一个curl会话
$tmp = curl_exec($curl);
// 关闭curl会话
curl_close($curl);
return $tmp;
}
/*
* post 方式模拟请求指定地址
* @param string url 请求的指定地址
* @param array params 请求所带的
* #patam string cookie cookie存放地址
* @return string curl_exec()获取的信息
* @author andy
**/
function post( $url, $params, $cookie="" ) {
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_HEADER, 0);
// 对认证证书来源的检查,0表示阻止对证书的合法性的检查。
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
// 从证书中检查SSL加密算法是否存在
//curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1);
//模拟用户使用的浏览器,在HTTP请求中包含一个”user-agent”头的字符串。
curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
//发送一个常规的POST请求,类型为:application/x-www-form-urlencoded,就像表单提交的一样。
curl_setopt($curl, CURLOPT_POST, 1);
// 将 curl_exec()获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
// 使用自动跳转
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
// 自动设置Referer
curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
// Cookie地址
curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie);
// 全部数据使用HTTP协议中的"POST"操作来发送。要发送文件,
// 在文件名前面加上@前缀并使用完整路径。这个参数可以通过urlencoded后的字符串
// 类似'para1=val1¶2=val2&...'或使用一个以字段名为键值,字段数据为值的数组
// 如果value是一个数组,Content-Type头将会被设置成multipart/form-data。
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params));
$result = curl_exec($curl);
curl_close($curl);
return $result;
}
/* End of file welcome.php */
/* Location: ./application/controllers/welcome.php */