在CI中国论坛里,Hex老大很早就写了一个微信开发的类库,原文地址: http://codeigniter.org.cn/forums/forum.php?mod=viewthread&tid=16665
这个类库很简洁,符合CI开发模式,不过功能过于简单,所以要使用一些高级的微信开发接口,推荐使用这个比较收欢迎的微信开发类库: https://github.com/dodgepudding/wechat-php-sdk
不过这个类库不是CI的,需要封装一下,下面讲讲我的封装,封装的有点过度,你可以按照自己的意愿稍加改造。
1.首先git clone https://github.com/dodgepudding/wechat-php-sdk.git 源代码wechat.php,放到CI的library文件夹下;
2.然后我们扩展一下wechat.php,为它加入一些事件委托,防止你每次写具体逻辑时要写一堆的switch或者if/else语句,这里就看你是否习惯我这种写法了。新建类库wechatex.php放到library下,源代码如下:
<?php
include APPPATH.'libraries/wechat.php';
class WechatEx extends Wechat {
const EVENT_SUBSCRIBE = 'SUBSCRIBE'; // 没关注时扫描:订阅公共号
const EVENT_UNSUBSCRIBE = 'UNSUBSCRIBE';// 已关注后,手动取消订阅号时触发
const EVENT_SCAN = 'SCAN'; //关注后再次扫描
const EVENT_CLICK = 'CLICK'; //点击推事件
const EVENT_VIEW = 'VIEW'; //跳转URL
const EVENT_LOCATION = 'LOCATION'; //用户同意上传位置信息后,服务器每5秒钟推送触发
const EVENT_SCANCODE_PUSH = 'SCANCODE_PUSH';//用户点击自定义扫描按钮,扫码推事件
const EVENT_SCANCODE_WAITMSG = 'SCANCODE_WAITMSG';//扫码推事件且弹出消息接收中提示框
const EVENT_PIC_SYSPHOTO = 'PIC_SYSPHOTO';//弹出系统拍照发图
const EVENT_PIC_PHOTO_OR_ALBUM = 'PIC_PHOTO_OR_ALBUM'; //弹出拍照或者相册发图
const EVENT_PIC_WEIXIN = 'PIC_WEIXIN'; //弹出微信相册发图器
const EVENT_LOCATION_SELECT = 'LOCATION_SELECT';//弹出地理位置选择器
function __construct($options)
{
parent::__construct($options);
}
public function run()
{
$this->valid();
$type = $this->getRev()->getRevType();
switch($type) {
case Wechat::MSGTYPE_TEXT:
$this->onText();
break;
case Wechat::MSGTYPE_EVENT:
$info = $this->getRevEvent(); //event, key
if (isset($info['event'])){
switch(strtoupper($info['event'])){
case self::EVENT_SUBSCRIBE:
$this->onSubscribe();
break;
case self::EVENT_UNSUBSCRIBE:
$this->onUnsubscribe();
break;
//关注后再次扫描
case self::EVENT_SCAN:
$this->onScan();
break;
case self::EVENT_LOCATION:
$this->onLocation();
break;
//点击菜单时:CLICK
case self::EVENT_CLICK:
//EventKey:与自定义菜单接口中KEY值对应
$this->onClick();
break;
//点击菜单跳转链接时的事件推送
case self::EVENT_VIEW:
//EventKey:设置的跳转URL
$this->onView();
break;
case self::EVENT_SCANCODE_PUSH:
$this->onScanCodePush();
break;
case self::EVENT_SCANCODE_WAITMSG:
$this->onScanCodeWaitMsg();
break;
case self::EVENT_PIC_SYSPHOTO:
$this->onPicSysPhoto();
break;
case self::EVENT_PIC_PHOTO_OR_ALBUM:
$this->onPicPhotoOrAlbum();
break;
case self::EVENT_PIC_WEIXIN:
$this->onPicWeixin();
break;
case self::EVENT_LOCATION_SELECT:
$this->onLocationSelect();
break;
default:
$this->onUnknown();
}
}
break;
case Wechat::MSGTYPE_IMAGE:
$this->onImage();
break;
case Wechat::MSGTYPE_LOCATION:
$this->onLocation();
break;
case Wechat::MSGTYPE_LINK:
$this->onLink();
break;
case Wechat::MSGTYPE_VOICE:
$this->onVoice();
break;
case Wechat::MSGTYPE_VIDEO:
$this->onVideo();
break;
default:
$this->onUnknown();
}
}
protected function onScanCodePush(){$this->defaultReply();}
protected function onScanCodeWaitMsg(){$this->defaultReply();}
protected function onPicWeixin(){$this->defaultReply();}
protected function onPicSysPhoto(){$this->defaultReply();}
protected function onPicPhotoOrAlbum(){$this->defaultReply();}
protected function onLocationSelect(){$this->defaultReply();}
/**
* 用户关注时触发,用于子类重写
*
* @return void
*/
protected function onSubscribe() {
$this->defaultReply();
}
protected function onUnsubscribe() {
$this->defaultReply();
}
protected function onClick(){
$this->defaultReply();
}
protected function onView() {
$this->defaultReply();
}
protected function onScan(){
$this->defaultReply();
}
/*
1 文本消息
2 图片消息
3 语音消息
4 视频消息
5 地理位置消息
6 链接消息
*/
protected function onText() {
$this->defaultReply();
}
protected function onImage() {
$this->defaultReply();
}
protected function onVoice(){
$this->defaultReply();
}
protected function onVideo(){
$this->defaultReply();
}
protected function onLocation(){
$this->defaultReply();
}
protected function onLink() {
$this->defaultReply();
}
protected function onUnknown() {
$this->defaultReply();
}
protected function defaultReply(){
$this->text('')->reply();
}
}
3.再次扩展wechatex.php,新建mywechat.php放到library下,这里就要写具体的实现逻辑了:
<?php
include APPPATH.'libraries/wechatex.php';
class MyWechat extends WechatEx {
private $_ci;
function __construct($options){
parent::__construct($options);
if (function_exists("get_instance") && defined("APPPATH")){
$this->_ci =& get_instance();
$this->_ci->load->model('product_model', 'product');
//$this->_ci->load->model('post_model', 'post');
}
}
protected function onSubscribe() {
$this->text('终于等到你。感谢你关注……')->reply();
}
protected function onUnsubscribe() {
$this->text('悄悄地我走了,正如我悄悄地来。')->reply();
}
protected function onText(){}
protected function onLocation() {
$info = $this->getRevGeo();
$this->text("收到了位置消息:({$info['x']},{$info['y']})")->reply();
}
protected function onLink() {
$info = $this->getRevLink();
$url = $info['url'];
$this->text("收到链接消息:({$info['url']},{$info['title']},{$info['description']})")->reply();
}
protected function onVoice() {
$info = $this->getRevVoice();
$this->text("收到链接消息:({$info['mediaid']},{$info['format']})")->reply();
}
protected function onUnknown() {
$this->text('收到未知消息')->reply();
}
//以下是cache的保存,按照具体情形保存你的token,因为微信服务器规定token的获取次数是有限制的,不要请求太多次数。
protected function setCache($cachename, $value, $expired){
$this->_ci->load->model('setting_model', 'setting');
$this->_ci->setting->set($cachename, array(
'value' => $value,
'expire_time'=> time() + $expired)
);
}
protected function getCache($cachename){
$this->_ci->load->model('setting_model', 'setting');
$data = $this->_ci->setting->get($cachename);
if(empty($data) || time() > $data['expire_time'])
return false;
return $data['value'];
}
protected function removeCache($cachename){
$this->_ci->load->model('setting_model', 'setting');
$this->_ci->setting->remove($cachename);
}
//真实微信号里只要有的事件,具体逻辑就可以写到这里。
}
4.最后,你需要一个控制器,在控制器之前,我们来一个配置文件,wechat.php放到config下:
<?php
$config['wechat'] = array(
'token'=>'CodeIgniter', //填写你设定的key
'appid'=>'wx1357312bf6f6f5df', //填写高级调用功能的app id
'appsecret'=>'0bf5ef023cd0318808b52232e3fc2315', //
'partnerid'=>'88888888', //财付通商户身份标识
'partnerkey'=>'', //财付通商户权限密钥Key
'paysignkey'=>'', //商户签名密钥Key
'debug'=>true
);
$config['wechat_menu'] = array(
"button"=>array(
array(
"type"=>"pic_photo_or_album",
"name"=>"我卖",
"key"=>"upload_pics"
),
array(
"type"=>"view",
"name"=>"逛逛",
"url"=> site_url('product/discovery')
),
array(
"name"=>"我的",
"sub_button"=>array(
array(
"type"=>"view",
"name"=>"正在出售",
"url"=>site_url('user/product/index')
),
array(
"type"=>"view",
"name"=>"个人中心",
"url"=>site_url('user/home/index')
),
array(
"type"=>"view",
"name"=>"帮助",
"url"=>site_url('home/weixin_help')
)
)
)
)
);
最后的最后,实现一个简单的微信控制器, weixin.php。这里不要命名成wechat.php,因为CI中已经含有wechat对象了,那就是那个类库,如果再把控制器也命名为wechat.php就会出错,简单地说,CI中类库的名字和控制器的名字不能重复,否则出错。不要跳坑。代码如下:
class Weixin extends MY_Controller{
function __construct(){
parent::__construct();
$this->config->load('wechat');
$options = $this->config->item('wechat');
$options['logcallback'] = 'logdebug';
$this->load->library('mywechat', $options);
}
public function api(){
$this->mywechat->run();
}
public function menu(){
$menus = $this->config->item('wechat_menu');
$flag = $this->mywechat->createMenu($menus);
echo !$flag ? 'FALSE' : json_encode($menus);
}
//其他的一些逻辑……
}
function logdebug($text){
file_put_contents('./upload/log.txt',$text."\n",FILE_APPEND);
}
在微信开发者模式下,填入以下API: http://www.abc.com/weixin/api即可。如果需要更改菜单,可以使用: http://www.abc.com/weixin/menu 刷新,当然你可以自己做个菜单系统,不像我这样把菜单写死。欢迎大家批评指正。
文章来源:http://www.tuicool.com/articles/eIvYna