叶子现在公司的框架用的Laravel,众所周知,用Laravel就是为了优雅的实现需求。但是,以当下架构和需求。实在是优雅不来了。实现需求才是优先。
今天要说的是,微信发送公众号模板消息踩到的大坑之路。虽然目前也不确定是否已经排除了Bug。
首先我们来看一下环境:
框架:Laravel 5.5
后台框架:Laravel-Admin 1.7.14
PHP版本:7.3
Redis版本:6.0.9
EasyWechat:~4.0
最原始的版本,不走队列的情况下,直接强撸到底,直接在对应位置写如下代码:
open_id = 'xxxxxxxxxxxxxxxxxxx';app = app('wechat.official_account');
app->template_message->send([
'touser' =>open_id,
'template_id' => WX_TEMPLATE_ID,
'url' => 'https://xxxxx.xxx',
'data' => [
'first' => 'Title',
'keyword1' => 'ProjectTitle',
'keyword2' => '项目状态',
'keyword3' => '项目状态信息',
'keyword4' => date('Y-m-d H:i:s'),
'remark' => '进度将通过此公众号持续推送,请持续关注!',
],
]);
按照原来的这个方法,出现了一个问题,同样的代码的情况下,每次发送模板消息,腾讯回调的都是发送成功,得到如下Log:
HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: application/json;
encoding=utf-8
Date: Mon, 21 Dec 2020 07:28:30 GMT
Content-Length: 55
{"errcode":0,"errmsg":"ok","msgid":1659995462566756352}
回调是成功了,但是用户经常会出现没有收到推送消息的情况。腾讯方面回复的是:可能是发送的信息里包含了特殊字符或表情之类的,也有可能是用户多端登录导致。
但是经过叶子的几次测试,多端登录并不会影响信息的接收,从发送日志里提取没有收到的信息进行手动单独发送,也是可以正常接收信息的。那么客服的几个假设问题就都不存在了。就在没有头绪的时候,只能考虑是不是短时间内发送的次数太多,被腾讯方面给吞了请求。为了减少同一时间内发送次数太多的问题,叶子就想到了走延时队列。于是就开始了如下操作:
首先,创建Jobs,
php artisan make:job SendWechatMessage
创建后得到如下文件,并进行逻辑编写:
<?php
namespace App\Jobs;
use Exception;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Facades\Log;
class SendWechatMessage implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public params;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(params)
{
this->params =params;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
data =this->params;
if(!isset(data['url']) || empty(data['url'])){
Log::error('微信队列:缺少URL');
return false;
}
if(!isset(data['open_id']) || empty(data['open_id'])){
Log::error('微信队列:缺少OPENID');
return false;
}
if(!isset(data['first']) || empty(data['first'])){
Log::error('微信队列:缺少FIRST');
return false;
}
if(!isset(data['keyword1']) || empty(data['keyword1'])){
Log::error('微信队列:缺少keyword1');
return false;
}
if(!isset(data['keyword2']) || empty(data['keyword2'])){
Log::error('微信队列:缺少keyword2');
return false;
}
if(!isset(data['keyword3']) || empty(data['keyword3'])){
Log::error('微信队列:缺少keyword3');
return false;
}
if(!isset(data['keyword4']) || empty(data['keyword4'])){
Log::error('微信队列:缺少keyword4');
return false;
}
app = app('wechat.official_account');res = app->template_message->send([
'touser' =>data['open_id'],
'template_id' => WX_TEMPLATE_ID,
'url' => data['url'],
'data' => [
'first' =>data['first'],
'keyword1' => data['keyword1'],
'keyword2' =>data['keyword2'],
'keyword3' => data['keyword3'],
'keyword4' =>data['keyword4'],
'remark' => '进度将通过此公众号持续推送,请持续关注!',
],
]);
if(res['errcode'] == 0){
Log::info('微信队列发送成功!');
}else{
Log::info('微信队列发送失败!');
}
}
public function failed(Exceptionexception)
{
Log::error('[微信队列执行失败:'.date('Y-m-d H:i:s').']');
}
}
然后在对应位置调用dispatch进行任务分发并且delay,代码如下:
$params = [];
$params['open_id'] = $sm_open_id;
$params['url'] = 'https://xxx.com/list?status=4';
$params['first'] = '项目进度更新!';
$params['keyword1'] = '项目名称';
$params['keyword2'] = '项目状态';
$params['keyword3'] = '提示信息!';
$params['keyword4'] = '操作时间';
SendWechatMessage::dispatch($params)->onQueue('wechatmessage')->delay(now()->addSeconds(10));
delay及延迟时间,使用了carbon,now()->addSeconds(10),这个命令就是在当前时间上延迟10秒执行。当然这个延迟队列可以用在很多场景里。大家根据自己的需求去做调整。
做了如上操作后。目前为止暂未有反馈说未收到信息。就坐等测试一波吧。
P.S.:本文仅来自博主本人菜鸟记录,欢迎大神指教。