1。关于质量接口和消息接口
关于质量接口
1。订阅帐户每天可以发送一条大规模消息,服务帐户每月可以发送四个大规模消息(自然月份)。在开发人员模式下,可以通过先进的质量传输界面来实现更灵活的质量传输能力。
2。注意
对于已验证的订阅帐户,可以每天成功调用一次质量发送接口,并且可以选择发送给所有用户或某个标签的质量发送;
对于身份验证服务帐户,尽管使用高级质量发送接口的开发人员的日常呼叫限制为100次,但用户每月只能接收4封信。无论是在公共平台网站上还是使用质量发送接口,用户每月只能接收4个质量发送消息,并且超过4个质量发送将无法发送给用户;
对于具有微信付款权限的公共帐户,使用质量接口上传或发送文本消息时,他们可以使用A标签添加外部链接;
关于客户服务消息和模板消息接口
当用户和官方帐户与特定操作互动(有关特定操作列表的描述)时,微信将将消息数据推向开发人员。开发人员可以在一段时间内调用客户服务界面(目前已修改为48小时),并通过发布JSON数据包向普通用户发送消息。该界面主要用于手动消息处理链接(例如客户服务)的功能,该功能促进开发人员为用户提供更好的服务。
模板消息仅用于通过官方帐户向用户发送重要的服务通知,并且只能用于满足其要求的服务方案,例如刷卡通知,产品购买通知等。营销诸如广告和所有其他可能引起用户骚扰的消息之类的营销消息不支持。
2。背景
让我们简要描述业务的背景。目前,这是供需的官方微信。每当用户付款以发送供需信息时,我们都需要向所有用户推开此消息,以便用户可以及时接收消息,实时并保证消息的有效性。但是,质量发送接口根本无法满足我们的需求,因此我们使用模板消息和客户服务消息接口来满足我们的需求。在这里,有些人可能会问为什么客户服务消息接收要求是如此异常,仍然需要使用它。实际上,这是因为当在某些设备上收到质量发送消息时,它们就像由微信朋友发送的消息,这会更多地吸引用户的注意力。
此外,我们还需要知道,如果我们的用户使用成千上万的人,则质量发送方法非常耗时。我一直在尝试使用此现场异步通知以实现质量发送。但是,根据实际使用,这种异步IO的阈值大约6分钟。但是,实际上,发送模板的网络需要花费时间加上数据库IO仍然很长,因此我们必须使用异步多线程来实现我们的质量发送功能。在这里,我使用扩展名来完成此要求。
对于异步电子邮件质量发送的演示,您可以在我的文章 +实现异步电子邮件质量发送(SMTP方法)中参考另一篇文章。在这里,您可以更详细地了解有关服务器和客户端的构建的更多信息。
3。环境描述
.0+
TP5.0+
电子邮件发送
正时任务
4。实施4.1创建服务器
我直接在这里发布了代码。我需要注意的所有内容均在相关代码的评论中写。请看一下。
/**
* description:服务端
*/
public function asyncSend()
{
$serv = new \swoole_server('0.0.0.0', 9090);
$serv->set(array(
'task_worker_num' => 60,
'daemonize' => true,
'log_file' => '/var/www/html/myswl/tp/swoole.log'
)
);
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
$task_id = $serv->task($data);
echo "开始投递异步任务 id=$task_id\n";
});
$serv->on('task', function ($serv, $task_id, $from_id, $data) {
echo "接收异步任务[id=$task_id]" . PHP_EOL;
$data = json_decode($data,true);
//这里要特别的说明,我这里用到了数据库的远程链接,因为支付的功能在另一台window虚拟云主机上的,所以不得不利用远程访问的方式。Db::connect($conn,true);的第二个参数给给予关注,因为我们没发送一次其实都会去进行一次远程数据库连接,所以频繁的连接中,肯定会有连接失败的情况,因此我们需要做好断线重连的配置
$conn = 'mysql://用户名:数据库远程链接地址:3306/密码#utf8';
$db = Db::connect($conn,true);
$now = date('Y-m-d H:i:s');
$users = $db
->table('tp_receiver')
->field('openid')
->where("(`expire_time` > '{$now}' OR `send_status` = 1 ) AND `receive_status` = 1 ")
->limit($data['flag']*500,500)
->select();
echo $db->getLastSql();
echo 'send start--' . date('H:i:s') . PHP_EOL;
foreach ($users as $user) {
$token = $db->table('tp_accesstoken')->field('accesstoken')->find();
//这里是客服消息
$templData2 = array(
'touser' => $user['openid'],
'msgtype' => 'text',
'text' => array('content' => $data['content']."\n\n点击下方“信息查询”查看更多求购信息。"."\n回复0取消接收信息,回复1重新接收信息")
);
$res = $this->sendCustomMessage($templData2,$token['accesstoken']);
$res = json_decode($res, true);
//判断客服消息是否成功发送
if($res['errcode'] == 45047 || $res['errcode'] == 45015) {
$templData = array(
'touser' => $user['openid'],
'template_id' => '模板消息',
'url' => '',
'data' => array(
'first' => array('value' => '您好,您收到一条新的提醒', 'color' => '#173177'),
'keyword1' => array('value' => '求购信息', 'color' => '#173177'),
'keyword2' => array('value' => $data['content'], 'color' => '#173177'),
'keyword3' => array('value' => $data['phone'], 'color' => '#173177'),
'keyword4' => array('value' => date('Y-m-d H:i:s'), 'color' => '#173177'),
'remark' => array('value' => "点击下方“信息查询”查看更多求购信息。"."回复0取消接收信息,回复1重新接收信息", 'color' => '#173177')
),
);
$res = $this->sendTemplateMessage($templData, $token['accesstoken']);
Log::write('send to'.$user['openid'].$res . PHP_EOL);
}
}
echo 'send end--' . date('H:i:s') . PHP_EOL;
$serv->finish('');
});
$serv->on('finish', function ($serv, $task_id, $data) {
echo 'finish time--' . microtime(true) . PHP_EOL;
echo "异步任务[id=$task_id]完成" . PHP_EOL;
});
$serv->start();
}
然后,我们以CLI模式输入项目的根目录并执行
php public/index.php demo/wechat/asyncSend
这样,我们的服务器将继续以守护程序模式运行到我们的背景,通过ps -aux |格雷普
可以看出,已经有62个过程(睡眠等待醒来),除了60个任务过程,还使用了一个和一个工作过程。
4.2建立客户
代码如下。您需要注意的所有要点都在相关代码的评论中写成。请看一下。
/**
* description:客户端
*/
public function index()
{
//因为这个群发比较敏感,我们需要做一个token的机制,我这边就用最简单的发送方和接收方都以明文的方式来做了。
$token = $_GET['token'];
if($token != 'test'){
exit;
}
//content是发送的内容,因为不可预估里面的东西,所以进行加解密
$content = rawurldecode($_GET['content']);
$flag = $_GET['flag'];
$id = $_GET['id'];
$phone = $_GET['phone'];
$data['content'] = $content;
$data['flag'] = $flag;
$data['phone'] = $phone;
Log::write(self::json_encode($data));
$insert = [
'flag'=>$flag,
'miaomu_id'=>$id,
'status'=>1,
'createtime'=>date('Y-m-d H:i:s'),
'content'=>$content
];
Db::table('task')->insert($insert);
//异步客户端
$client = new \swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC);
$ret = $client->connect("127.0.0.1", 9090);
//当无法连接的时候,发送告警邮件
if (empty($ret)) {
SendMail::postmail('kongwentao@zuihuibao.com','警告','error!connect to swoole_server failed');
SendMail::postmail('937069176@qq.com','警告','error!connect to swoole_server failed');
Log::write('error!connect to swoole_server failed');
} else {
$client->send(self::json_encode($data));
}
}
4.3端口监视
这种质量发送已经涉及金额,因此我们需要具有关系服务运营的稳定性。在这里,我们只需使用PHP的定时任务和一些与Shell相关的功能来实现端口监视。
这次使用的时序任务
*/1 * * * * curl http://你的域名/index.php/demo/Jrmm/checkPortStatus?token=test
它是实施每分钟执行我们的PHP代码的任务。我没有直接使用Shell在这里操作。有3个原因。 1是我对Shell命令不是很熟悉,2我们对Shell命令不是很熟悉,而3是我更容易编写相关代码并使用一些现有方法,例如电子邮件发送。尽管这增加了更多的网络资源,但它仍然具有成本效益。
对于特定的监视代码,此处实施时会有许多许可问题,因此我不会说太多。遇到它们时,我将使用百度来这样做。
/**
* description:8082服务端口监控
*/
public function checkPortStatus(){
if (!isset($_GET['token']) || $_GET['token'] != 'test'){
exit();
}
$res1 = exec('sudo netstat -lpn | grep 9090');
Log::write($res1);
if($res1 == ''){
Log::write('9090stop');
SendMail::postmail('kongwentao@zuihuibao.com','警告','9090端口服务错误');
SendMail::postmail('937069176@qq.com','警告','9090端口服务错误');
//重新启动我们的服务器。您需要注意的是,我没有使用提供的平滑重新启动功能,这可能会导致数据丢失。不要注意这个额外
exec('sudo php /var/www/html/myswl/tp/public/index.php demo/jrmm/asyncSend');
$res = exec('sudo netstat -lpn | grep 8082');
if($res != ''){
Log::write('9090restart success');
SendMail::postmail('937069176@qq.com','警告解除','9090端口重启成功');
SendMail::postmail('kongwentao@zuihuibao.com','警告解除','9090端口重启成功');
}
}
}
4.4实施
我们使用PHP卷曲功能模拟付款成功后调用质量发送的功能。
$content = 'test';
for ($j=0;$j<3;$j++){
$url = 'http://你的域名/index.php/demo/Jrmm/index'.'?flag='.$j.'&id=1.'&token=test'.'&phone='110&content='.rawurlencode($content);
$this->http_post($url);
}
function http_post($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
$res= curl_exec($ch);
curl_close($ch);
return $res;
}
为什么要循环三遍?因为当我们通过测试发送1500条消息时,大约需要6分钟,但是我们项目的并发非常低,因此我们无法充分利用已经开始的60个任务过程。因此,我们将1500次分为三次。实际上,我们消耗的网络消耗几乎可以忽略不计,这将我们的发送性能提高了三倍以上。在实际项目中,发送1500多条消息实际上需要不到两分钟。当然,当并发量更大时,我们还可以使用队列方法来处理它,这要求我们团队的任务过程管理更加精通。
5。屏幕截图
收到的推消息
警报
已发送日志
6。下载完整的项目代码
扫一扫在手机端查看
我们凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求,请立即点击咨询我们或拨打咨询热线: 13761152229,我们会详细为你一一解答你心中的疑难。


客服1