前瞻
之前写了个通用的微信管理,领导说实用性太差,要加上群发管理,哎真是站着说话不腰疼,难为人,没办法,自己是打工的,干吧;不过个人觉得还是直接上微信后台方便的多。先看下我的目录
框架:tp3.2
思路
我这里是模拟的微信后台添加的方式,首先有个群发主题(一个栏目),然后在群发内容里在对应主题添加内容,一个主题可以对应着多个内容(多图文)。可以看下我的页面:
我的群发内容页面:
数据库字段:
-
群发主题
-
群发内容
实现群发功能需要以下几步:
- 上传群发内容的标题图到微信服务器,拿到media_id(即thumb_media_id),这是上传主题素材用的;调用接口地址http://mp.weixin.qq.com/wiki/10/78b15308b053286e2a66b33f0f0f5fb6.html (我也不知道微信公众平台有几个开发文档,我看到了3个不同版本,这个是我点击客户接口进去的)
- 上传群发内容编辑器所编辑内容所有图片,拿到对应服务器的url并替换;这个也是必须的,否则,微信不会显示图片;调用地址:http://mp.weixin.qq.com/wiki/14/0c53fac3bdec3906aaa36987b91d64ea.html
- 上传主题素材,拿到media_id,用于群发,这个和上面2的地址一样
- 利用素材的media_id,上传或者预览,地址也是2
代码:(因为我的是测试号,没权限好像是,但是我的预览接口成功了,预览和素材只是最后一步不一样)
namespace Admin\Controller;
class massController extends AuthController{
protected $MassObj;
protected $MassReturnObj;
protected $conf;
public function __construct(){
parent::__construct();
$this->MassObj = D('Mass');//主题表
$this->MassReturnObj = D('MassReturn');//主题内容表
}
/**
* [delmass 发送群发主题]
* @return [JSON] [返回成功与失败]
*/
public function sendmass(){
//这里我是异步post请求的,可以是get,看个人
if( !empty( $_POST ) ){
$id = I('post.id');
$data = $this->MassReturnObj->order('mass_order')->where(array('mass_id'=>$id))->select();//拿到主题内容数据
$access_token = $this->getWxAccessToken();//下面有函数
//循环遍历每个图文
foreach( $data as $k=>$v){
//调用基础支持的上传多媒体文件,上传标题图
$url="http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token={$access_token}&type=image";
$arr = array('media'=>'@'.$_SERVER['DOCUMENT_ROOT'].$v['pic_url'],'form-data'=>$v['pic_url']);
$res = $this->http_curl($url,'post','',$arr);
if( !$res ){
$this->ajaxReturn( array( 'code'=>1,'msg'=>'id为'.$v['id'].'的数据标题图图片上传失败!' ) );
}
$v['media_id'] = $res['media_id'];//标题图的thumb_media_id
$v['wxpic'] = $res['url'];
$content = $v['content'];
preg_match_all('//is',$content,$arr);//提取编辑内容的所有img的src
$url = "https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token={$access_token}&type=image";
//将内容里面的所有img图片上传到微信服务器,并替换新的图片地址
foreach( $arr[1] as $k1=>$vo ){
$arr = array('media'=>'@'.$_SERVER['DOCUMENT_ROOT'].$vo,'form-data'=>$vo);
//调用图片上传到微信服务器接口
$res = $this->http_curl($url,'post','',$arr);
if( !$res['url'] ){
$this->ajaxReturn( array( 'code'=>1,'msg'=>'id为'.$v['id'].'的消息内容页面的第'.($k1+1).'张图片上传失败!' ) );
}
$content = str_replace($vo,$res['url'],$content);//替换新的图片地址
}
//拼接主题素材数组,这块汉字需要用urlencode转一下,转成json再用urldecode转回,否则消息页面是乱码
$postArr['articles'][] = array(
"thumb_media_id"=>$v['media_id'],
"author"=>urlencode($v['author']),
"title"=>urlencode($v['title']),
"content_source_url"=>urlencode($v['url']),
"content"=>urlencode(htmlspecialchars(str_replace("\"","'",$content))),//需要str_replace将上引号换成单引号
"digest"=>urlencode($v['description']),
"show_cover_pic"=>"0"
);
}
//将数组转为json
$postArr = htmlspecialchars_decode(urldecode(json_encode($postArr)));
//调用上传素材接口
$url = 'https://api.weixin.qq.com/cgi-bin/media/uploadnews?access_token='.$access_token;
//上传整个素材post
$res = $this->http_curl($url,'post','json',$postArr);
$media_id = $res['media_id'];//群发素材的media_id
$url= "https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token=".$access_token;
$postArr = array(
"filter"=>[
"is_to_all"=>true,
],
"mpnews"=>[
"media_id"=>$media_id
],
"msgtype"=>"mpnews"
);
$postArr = json_encode( $postArr );
$res = $this->http_curl($url,'post','json',$postArr);
if( $res['errcode']==0 && $res['msg_data_id'] ){
$this->MassObj->setField('put_time',time());
$this->ajaxReturn( array( 'code'=>0,'msg'=>'发送成功!' ) );
}else{
$this->ajaxReturn( array( 'code'=>1,'msg'=>$res['errcode'].':'.$res['errmsg'] ) );
}
}else{
$this->ajaxReturn( array( 'code'=>1,'msg'=>'无效操作' ) );
}
}
}
预览接口
public function send(){
//Gl8DWQUSQHXlB7IBKXcyqF79PSS9Mm_rTvwJsIHx_rPs3oMgWR8tB6l5Z4CNStXo
if( !empty( $_POST ) ){
$id = I('post.id');
$data = $this->MassReturnObj->order('mass_order')->where(array('mass_id'=>$id))->select();
$access_token = $this->getWxAccessToken();
foreach( $data as $k=>$v){
//调用基础支持的上传多媒体文件
$url="http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token={$access_token}&type=image";
$arr = array('media'=>'@'.$_SERVER['DOCUMENT_ROOT'].$v['pic_url'],'form-data'=>$v['pic_url']);
$res = $this->http_curl($url,'post','',$arr);
if( !$res ){
$this->ajaxReturn( array( 'code'=>1,'msg'=>'id为'.$v['id'].'的数据标题图图片上传失败!' ) );
}
echo "1111
";var_dump($res);echo "
";
$v['media_id'] = $res['media_id'];//标题图的thumb_media_id
$v['wxpic'] = $res['url'];
$content = $v['content'];
preg_match_all('//is',$content,$arr);//提取所有img的src
$url = "https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token={$access_token}&type=image";
//将内容里面的所有img图片上传到微信服务器,并替换新的图片地址
foreach( $arr[1] as $k1=>$vo ){
$arr = array('media'=>'@'.$_SERVER['DOCUMENT_ROOT'].$vo,'form-data'=>$vo);
//调用图片上传到微信服务器接口
$res = $this->http_curl($url,'post','',$arr);
if( !$res['url'] ){
$this->ajaxReturn( array( 'code'=>1,'msg'=>'id为'.$v['id'].'的消息内容页面的第'.($k1+1).'张图片上传失败!' ) );
}
$content = str_replace($vo,$res['url'],$content);
}
//拼接数组
$postArr['articles'][] = array(
"thumb_media_id"=>$v['media_id'],
"author"=>urlencode($v['author']),
"title"=>urlencode($v['title']),
"content_source_url"=>urlencode($v['url']),
"content"=>urlencode(htmlspecialchars(str_replace("\"","'",$content))),
"digest"=>urlencode($v['description']),
"show_cover_pic"=>"0"
);
}
//将数组转为json
$postArr = htmlspecialchars_decode(urldecode(json_encode($postArr)));
//调用上传素材接口
$url = 'https://api.weixin.qq.com/cgi-bin/media/uploadnews?access_token='.$access_token;
//上传整个素材post
$res = $this->http_curl($url,'post','json',$postArr);
echo "1111
";var_dump($res);echo "
";
$media_id = $res['media_id'];//群发素材的media_id
$url= "https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token=".$access_token;
$postArr = array(
"touser"=>"oV3xFwbYr3X4sYFepGUgDNgn6cGg",
"mpnews"=>[
"media_id"=>$media_id
],
"msgtype"=>"mpnews"
);
$postArr = json_encode( $postArr );
$res = $this->http_curl($url,'post','json',$postArr);
echo "1111
";var_dump($res);
if( $res['errcode']==0 && $res['errmsg'] ){
// $this->MassObj->setField('is_send',1);
$this->ajaxReturn( array( 'code'=>0,'msg'=>'发送成功!' ) );
}else{
$this->ajaxReturn( array( 'code'=>1,'msg'=>$res['errcode'].':'.$res['errmsg'] ) );
}
}else{
$this->ajaxReturn( array( 'code'=>1,'msg'=>'无效操作' ) );
}
}
可以将上面的echo去掉,不去的话可以看返回值,调试用
用到的函数
/**
*
*获取全局access_token
* @return $access_token string
*/
function getWxAccessToken(){
//将access_token存在session中
if( $_SESSION['access_token'] && $_SESSION['expire_time']>time() ){
return $_SESSION['access_token'];
}else{
$this->conf = M('Wechat')->find(1);
//如果access_token不存在或者过期,重新获取
$appid = $this->conf['appid'];//公众号的appid
$appsecret = $this->conf['appsecret'];//公众号的appsecret
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret;
$res = $this->http_curl($url);
$access_token = $res['access_token'];
//将获取到的access_token存到session
$_SESSION['access_token'] = $access_token;
$_SESSION['expire_time'] = time()+7000;//access_token过期时间为2小时,所以把session过期时间也修改过来
return $access_token;
}
}
/**
*
*$url 接口url string
*$type 请求类型 string
*$res 返回数据类型 string
*$arr post请求参数 array
*
*/
public function http_curl($url,$type='get',$res='json',$arr=''){
//1.初始化curl
$ch = curl_init();
//2.设置curl的参数
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
if($type == 'post'){
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$arr);
}
//3.采集
$output = curl_exec($ch);
//4.关闭
curl_close($ch);
if($res == 'json'){
if( curl_error($ch) ){
return curl_error($ch);//请求失败返回错误信息
}else{
return json_decode($output,true);//请求成功返回json
}
}else{
if( curl_error($ch) ){
return curl_error($ch);//请求失败返回错误信息
}else{
return json_decode($output,true);//请求成功返回json
}
}
}