THINKPHP5 微信模板消息(异步群发)推送 跨坑记录。

上次写了一篇微信模版消息推送,但是不知道怎么异步推送。导致要等它推送完几百条才能关闭网页。

然后请教了大神,和自己摸索,在此记录。

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'];//关注用户的openID

		foreach ($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;
	}

}

在网上找了很久都没有找到这样一个教程。

如果有啥问题可以留言,我还是挺活跃的。

猜你喜欢

转载自blog.csdn.net/qq_34876813/article/details/82704146