问题

微信消息推送万级、十万百万级用传统遍历的方法就很鸡肋了,而且很容易造成内存占满和502崩溃,所以要用异步多线程处理。我们在业务中很常见,经常需要发送一些活动或者开课提醒之类的一次性推送给微信公众号粉丝。用传统方法很费人力而且操作不当容易造成重发或者漏发,这样很容易流失粉丝。而网上的一些第三方平台有这方面的服务基本上都是按照粉丝量按年收费。我之前也试用过,也只能一次性给你发一两千人。一年最低的粉丝量费用要880。所以还是自己硬着头皮给它搞出来!经过一番折腾,终于搞出来了!

环境需要

1.php安装swoole扩展。自行百度,必须是linux环境,如果是使用的宝塔直接在商店所安装的php设置里安装swoole扩展。同时放行9501端口号。

2.composer安装easywechat。很好用的一款微信相关的sdk。

3.利用thinkphp5或者以上版本自定义command来处理。方便之后做定时任务处理:at或crontab来处理任务。at是在特定时间只执行一次;crontab是每隔多久执行一次。

代码实现

namespace app\command;

use app\admin\model\WxOpenid;

use app\common\command\Base;

use Swoole\Client as SwooleClient;

use think\console\Input;

use think\console\Output;

use think\console\input\Argument;

use think\console\input\Option;

use libs\Log;

use EasyWeChat\Factory;

use Swoole\Server as SwooleServer;

class Message extends Base

{

/**

* 配置参数

*/

const TEST_OPENID = '测试openid';

const TEMPLATE_ID = '模板id';

const URL = '跳转链接';

const TEMPLATE_DATA = [

'first' => '内容1',

'keyword1' => '内容2',

'keyword2' => '全体用户',

'remark' => ['value' => '点击此条消息进入学习', 'color' => '#FF0000'],

];

const APP_ID = "微信APP_ID";

const APP_SECRET = "微信APP_SECRET";

const SWOOLE_TESK = [

'task_worker_num' => 480,

'reactor_num' => 24,

'worker_num' => 24

];

protected $app;

protected function configure()

{

$this->setName('msg')

->addOption('test', 't', Option::VALUE_NONE, '测试方法')

->addOption('client', 'c', Option::VALUE_NONE, 'swoole客户端')

->addOption('sync', 's', Option::VALUE_NONE, 'openid同步到库')

->addOption('send', 'e', Option::VALUE_NONE, '发送模板消息')

->addOption('required', null, Option::VALUE_REQUIRED, 'this is a value_required option')

->addOption('optional', null, Option::VALUE_OPTIONAL, 'this is a value_optional option')

->addArgument('optional', Argument::OPTIONAL, "argument::optional")

->setDescription('用于xxx模板消息发送');

}

protected function execute(Input $input, Output $output)

{

$options = array_filter($input->getOptions(true));

if (empty($options)) {

return $output->error('please enter options ^_^');

}

$config = [

'app_id' => self::APP_ID,

'secret' => self::APP_SECRET,

'log' => [

'default' => 'prod', // 默认使用的 channel,生产环境可以改为下面的 prod

'channels' => [

// 测试环境

'dev' => [

'driver' => 'single',

'path' => '/tmp/easywechat.log',

'level' => 'debug',

],

// 生产环境

'prod' => [

'driver' => 'daily',

'path' => '/runtime/log/easywechat.log',

'level' => 'info',

],

],

],

];

$this->app = Factory::officialAccount($config);

try {

$input->getOption('client') && $this->client();

$input->getOption('test') && $this->test();

$input->getOption('sync') && $this->sync();

$input->getOption('send') && $this->send();

} catch (\Exception $ex) {

return Log::err(__METHOD__, $options, $ex->getMessage());

}

}

protected function test()

{

// https://mp.weixin.qq.com/s/zXnuWR58oXulsrO7wLkeaw

$params = [

'touser' => self::TEST_OPENID,

'template_id' => self::TEMPLATE_ID,

'data' => self::TEMPLATE_DATA,

'url' => self::URL,

];

$res = $this->app->template_message->send($params);

dd($res);

}

protected function client()

{

$client = new SwooleClient(SWOOLE_SOCK_TCP);

if (!$client->connect('127.0.0.1', 9501, 0.5)) {

exit("connect failed. Error: {$client->errCode}\n");

}

$msg = 'Task begin...';

$this->startTime = microtime(true);

$this->output->info($msg);

//向服务器发送数据

$client->send($msg);

}

protected function send()

{

$swoole = new SwooleServer("127.0.0.1", 9501);

$swoole->set(self::SWOOLE_TESK);

$swoole->on('receive', function ($swoole, $fd, $from_id, $data) {

db('wx_openid')->where('num', 0)

->chunk(100, function ($data) use ($swoole) {

$taskId = $swoole->task($data);

$this->output->info("Task_id {$taskId} Delivering successful");

});

});

//处理异步任务

$swoole->on('task', function ($swoole, $task_id, $from_id, $data) {

foreach ($data as $item) {

$params = [

'touser' => $item['openid'],

'template_id' => self::TEMPLATE_ID,

'data' => self::TEMPLATE_DATA,

'url' => self::URL

];

$wxopenid = WxOpenid::get(['openid' => $item['openid']]);

try {

$this->app->template_message->send($params);

} catch (\Exception $ex) {

Log::err('模板消息发送错误', $params);

$wxopenid->num -= 1;

$wxopenid->save();

continue;

}

$wxopenid->num += 1;

$wxopenid->save();

}

$swoole->finish(count($data) . " -> OK");

});

//处理异步任务的结果

$swoole->on('finish', function ($swoole, $task_id, $data) {

$this->output->info("AsyncTask[$task_id] Finish: $data");

});

$swoole->start();

}

// 503289

protected function sync($nextOpenId = null)

{

$res = $this->app->user->list($nextOpenId);

$data = [];

foreach ($res['data']['openid'] as $item) {

$data[] = [

'openid' => $item,

'create_time' => NOW

];

}

WxOpenid::insertAll($data);

if ($res['next_openid']) {

$this->sync($res['next_openid']);

}

}

}

运行步骤

1.sync同步openid到数据库。因为微信每日调用用户列表等接口有次数限制,所以本着即开即食的原则,放在库里操作。

2.send起服务

3.client触发服务。

注意事项

1.必须在项目的根目录来运行php think msg命令

2.同时开始两个窗口,先执行php think msg -e,然后另一个窗口执行client。后期如果做成可视化的界面,创建定时任务的时候可以/usr/local/php/bin或(宝塔)/www/serve/php/72/bin server &&client来执行。

ps:如果有任何问题或看不懂的地方私信我,一起学习进步!

swoole php 微信推送,基于thinkphp5、swoole和easywechat微信模板消息推送相关推荐

  1. 微信小程序java后端开发记录(三):模板消息推送

    ·模板消息推送 1.1推送参数dto: 按照文档逐层次封装请求参数. 这些参数 /*** @author hanyy* @Description: 微信小程序模板消息推送参数* @date 2019/ ...

  2. 微信小程序消息推送自有服务器无法接收到信息,消息推送服务器配置次数用完的解决方式。

    问题描述:消息推送自有服务器无法接收到信息,消息推送服务器配置次数用完! 解决方向:自有服务器无法接收信息的排错,消息推送配置的次数用完的解决方式. 适合版本:微信所有版本(2020.4.16) 关于 ...

  3. php 异步请求微信模板消息_php实现微信模板消息推送

    本文实例为大家分享了php微信模板消息推送的具体代码,供大家参考,具体内容如下 1.微信公众号模板消息配置 2.PHP代码/*** 发送模板消息*/ public function send_noti ...

  4. 【微信小程序】模板消息推送(测试成功)。

    note: 这几天想做微信小程序消息推送的功能,然后在网上找了好多教程,都没解决问题,官方文档写的教程由不够详细,所以走了好多弯路. 现在问题解决了,记录一下. 我在网上找的好多教程都不详细,虽然是贴 ...

  5. springboot实现微信模板消息推送

    springboot实现微信模板消息推送 在上一篇文章我们已经知道了怎么获取openid 还不知道的可以查看我的上一篇文章springboot+微信小程序用codeid换取openid 这次我们不光要 ...

  6. 微信模板消息推送(内附工具类代码)

    文章目录 前言 一.添加模板消息 1.进入微信公众号后台 2.模板消息 3.填写信息 4.审核通过后 二.开发步骤 1.依赖坐标 2.实体类 1)AccessToken 2.WxTemplate模板消 ...

  7. java 微信模板_java开发微信模板消息推送

    概述 微信公众平台开始支持前端网页,大家可能看到很多网页上都有分享到朋友圈,关注微信等按钮,点击它们都会弹出一个窗口让你分享和关注,这个是怎么实现的呢?今天就给大家讲解下如何在微信公众平台前端网页上添 ...

  8. PHP之 微信模板消息推送 的相关代码

    温馨提示: 微信模板消息推送,得先去微信端,设置模板配置,会生成相应的消息模板id,这个是一串字符,需连同参数数据,传给微信端,切记!~ 第一部分:主体部分代码,负责业务模块,准备微信端所需参数 /* ...

  9. JAVA对接微信公众号(服务号、订阅号)实现模板消息推送功能

    最近做了个需求要求对接微信公众号,使用模板进行消息推送,今天抽时间总结一下相关的逻辑. 大概逻辑分为四个步骤: 获取微信调用接口凭证access_token. 获取微信模板列表. 使用模板进行消息推送 ...

  10. java开发微信模板消息推送

    完整demo下载 概述 微信公众平台开始支持前端网页,大家可能看到很多网页上都有分享到朋友圈,关注微信等按钮,点击它们都会弹出一个窗口让你分享和关注,这个是怎么实现的呢?今天就给大家讲解下如何在微信公 ...

最新文章

  1. 中国或将于2018年在晶圆代工支出领域位列世界第二
  2. 理解 Android Build 系统
  3. bat 安装mysql_免安装版Mysql一键部署bat文档的方法
  4. nginx php跳转url参数,NGINX 中把url中的内容当初参数处理
  5. python记录日志_5分钟内解释日志记录—使用Python演练
  6. Android之Intent深入
  7. 消息队列(2):常见的消息队列协议
  8. python3单例模式
  9. Oracle 18c新特性:Schema-Only 帐号提升应用管理安全性
  10. 外媒:美国政府官员建议阻止英飞凌收购赛普拉斯
  11. 阶段1 语言基础+高级_1-3-Java语言高级_08-JDK8新特性_第1节 常用函数接口_3_性能浪费的日志案例...
  12. 利用Samba搭建Backup Server配置文件
  13. MDK5如何生成bin文件
  14. HikariCP介绍
  15. 鹅厂假前端实习鹅的实习日志
  16. js 输入数字金额同步转换为大写金额方法
  17. WireShark基本使用(5)第 5 章 文件输入/输出及打印
  18. Kotlin 异常处理之 Option、Either、Result
  19. unbalanced enable irq
  20. Win7开自带的虚拟WIFI

热门文章

  1. EGit(Git Eclipse Plugin)使用
  2. 【填坑】Ubuntu安装vsftpd
  3. 线上不修改mysql的存储引擎对emoji标签做删除处理(PHP)
  4. 20190110-生成密码以及简易密码强度检查
  5. git push 出现 you are not allowed to upload merges 错误提示
  6. [洛谷P4720] [模板] 扩展卢卡斯
  7. expect远程登录服务器并执行命令
  8. 数据结构与算法--图的概念
  9. 不过确实setNString 也可以解决这个??问题,但是解决不了模糊匹配问题 原因不清楚...
  10. 20145324 《Java程序设计》第1周学习总结