上次写了一篇微信模版消息推送,但是不知道怎么异步推送。导致要等它推送完几百条才能关闭网页。
然后请教了大神,和自己摸索,在此记录。
1、推送页,推送到另一个文件处理微信推送,使用fsockopen。一次性推送,不保存数据库,有需要自己改。
$data = input('post.');//前台传过来的值,组装模版使用。$host = $_SERVER['HTTP_HOST'];//域名$path = '/admin/send/index';//异步推送到这个文件,在这个文件里面处理推送。$data = http_build_query($data);//$data = json_encode($data,JSON_UNESCAPED_UNICODE);$fp = fsockopen($host, 80, $error, $errstr, 1);$http = "POST $path HTTP/1.1\r\nHost: $host\r\nContent-type: application/x-www-form-urlencoded\r\nContent-Length: " . strlen($data) . "\r\nConnection:close\r\n\r\n$data\r\n\r\n";fwrite($fp, $http);//实现异步把下面注释掉,意思是不处理返回// $receive = '';// while (!feof($fp)) {// $receive .= fgets($fp, 128);// }// echo "<br />".$receive;//连接主动断开时,线上proxy层没有及时把请求发给上游fclose($fp);return json(['code' => 1, 'msg' => '推送完成!', 'url' => url('notive/send')]);
2、异步处理页,实际上这里再一次使用fsockopen。
<?php
namespace app\admin\controller;
use think\facade\Request;
class Send
{public function index(){$data = input('post.');//这个是fscokopen推送过来的data。$value = db('wx_config')->where([ 'key' => 'SHOPWCHAT'])->value('value');$value = json_decode($value,true);$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$value['appid']."&secret=".$value['appsecret'];if (cookie('access_token')){$access_token=cookie('access_token');}else{$cont = json_decode($this->getToken($url));$access_token=$cont->access_token;setcookie('access_token',$access_token,7200);}//获取access_token$all = $this->get_allopenid($access_token);//获取关注的用户,因为只能推送关注的用户。$openids = $all['data']['openid'];//关注用户的openIDforeach ($openids as $key => $value) {if (db('users')->where('openid',$value)->value('unsub') == '1'){unset($openids[$key]);}}$openids = array_values($openids);//这里是筛选没有退订的用户,并重新排序键值对。这些推送最好是可以退订的,不然用户举报可能会封号哦。我是根据用户回复“退订”关键词来标记的。这一步是有必要的。foreach ($openids as $key => $value) {$params = json_encode($this->json_tempalte($value,$data),JSON_UNESCAPED_UNICODE);$fp = fsockopen('api.weixin.qq.com', 80, $error, $errstr, 1);$http = "POST /cgi-bin/message/template/send?access_token={$access_token} HTTP/1.1\r\nHost: api.weixin.qq.com\r\nContent-type: application/x-www-form-urlencoded\r\nContent-Length: " . strlen($params) . "\r\nConnection:close\r\n\r\n$params\r\n\r\n";fwrite($fp, $http);fclose($fp);sleep(1);}//这里就是遍历推送到各个openID了、sleep(1)是为了防止推送过快出问题。return ture;}function getToken($url) {//这个方法是获取access_token$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);curl_setopt($ch, CURLOPT_HEADER, 0);curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko)");curl_setopt($ch, CURLOPT_ENCODING, "gzip");curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);$output = curl_exec($ch);curl_close($ch);return $output;}function get_allopenid($access_token,$next_openid = ''){//这个方法是获取所有关注的用户的$url = "https://api.weixin.qq.com/cgi-bin/user/get?access_token={$access_token}&next_openid=".$next_openid;$ch = curl_init();curl_setopt($ch, CURLOPT_URL,$url);curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,0);$data = curl_exec($ch);$data = json_decode($data,true);if ($data["count"] == 10000){$newdata = $this->get_allopenid($access_token,$data["next_openid"]);$data["data"]["openid"] = array_merge_recursive($date["data"]["openid"], $newdata["data"]["openid"]);}return $data;}function json_tempalte($openid,$data,$template_id = 'DtlkLjhNf5p5P7kYorbm-6kop3zlSyct1wL70fuJ8ME'){//这里是组装模版消息的方法$template=array('touser'=>$openid,'template_id'=>$template_id,//这个是模版ID,获取方法自己看文档很详细。'url'=>$data['url'],'topcolor'=>"#7B68EE",'data'=>array('first'=>array('value'=>$data['first'],'color'=>"#000"),'keyword1'=>array('value'=>$data['keyword1'],'color'=>'#F70997'),'keyword2'=>array('value'=>$data['keyword2'],'color'=>'#248d24'),'keyword3'=>array('value'=>date("Y-m-d H:i:s"),'color'=>'#000'),'remark' =>array('value'=>$data['remark'],'color'=>'#1784e8'), ));return $template;}}
在网上找了很久都没有找到这样一个教程。
如果有啥问题可以留言,我还是挺活跃的。