微信消息推送
微信公众平台和小程序虽然都是腾讯开发,但是其是俩个独立的平台,包括账号也是独立存在,所以小程序和公众平台不可以使用同一个账号注册使用。
因是俩个平台,所以微信公众平台的用户openId和小程序用户openId不同,当然消息推送实现方式也不同
如果本地测试接口,需要在公众平台后台配置ip白名单,否则请求不成功
公众号消息推送
模版消息通知位置:公众号详情聊天页面
推送前提:模版id、参数、接收人openId、接收人必须关注公众号。
模板跳转能力:点击查看详情可以跳转到指定的任意http链接
-
1.小程序后台配置模版消息
-
进入模版页面,点击右上角”从模版库添加“,搜索符合需求的模版消息并且配置勾选需要的参数
- 添加成功之后,模版列表页面复制该模版id,为后续接口调用模版消息使用
-
-
2.请求接口
请注意,URL置空,则在发送后,点击模版消息会进入一个空白页面(ios),或无法点击(android)。
POST请求
https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN
请求包为一个json:{ "touser":"OPENID", "template_id":"ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY", "url":"http://weixin.qq.com/download", "topcolor":"#FF0000", "data":{ "User": { "value":"黄先生", "color":"#173177" }, "Date":{ "value":"06月07日 19时24分", "color":"#173177" }, "CardNumber":{ "value":"0426", "color":"#173177" }, "Type":{ "value":"消费", "color":"#173177" }, "Money":{ "value":"人民币260.00元", "color":"#173177" }, "DeadTime":{ "value":"06月07日19时24分", "color":"#173177" }, "Left":{ "value":"6504.09", "color":"#173177" } } }
发送效果图:
返回码说明
在调用模版消息接口后,会返回JSON数据包。正常时的返回JSON数据包示例:
{ "errcode":0, "errmsg":"ok", "msgid":200228332 }
错误时的返回JSON数据,形式类似,错误返回码说明:
返回码 | 说明 |
---|---|
-1 | 系统繁忙 |
0 | 请求成功 |
40001 | 验证失败 |
40002 | 不合法的凭证类型 |
40003 | 不合法的OpenID |
40004 | 不合法的媒体文件类型 |
40005 | 不合法的文件类型 |
40006 | 不合法的文件大小 |
40007 | 不合法的媒体文件id |
40008 | 不合法的消息类型 |
40009 | 不合法的图片文件大小 |
40010 | 不合法的语音文件大小 |
40011 | 不合法的视频文件大小 |
40012 | 不合法的缩略图文件大小 |
40013 | 不合法的APPID |
41001 | 缺少access_token参数 |
41002 | 缺少appid参数 |
41003 | 缺少refresh_token参数 |
41004 | 缺少secret参数 |
41005 | 缺少多媒体文件数据 |
41006 | access_token超时 |
42001 | 需要GET请求 |
43002 | 需要POST请求 |
43003 | 需要HTTPS请求 |
44001 | 多媒体文件为空 |
44002 | POST的数据包为空 |
44003 | 图文消息内容为空 |
45001 | 多媒体文件大小超过限制 |
45002 | 消息内容超过限制 |
45003 | 标题字段超过限制 |
45004 | 描述字段超过限制 |
45005 | 链接字段超过限制 |
45006 | 图片链接字段超过限制 |
45007 | 语音播放时间超过限制 |
45008 | 图文消息超过限制 |
45009 | 接口调用超过限制 |
46001 | 不存在媒体数据 |
47001 | 解析JSON/XML内容错误 |
小程序消息推送
- 模版消息通知位置:服务通知
- 推送前提:用户有过支付行为或者提交表单操作,会生成对应的form_id,一次生成一个form_id,每次都不一样,一个form_id只可以用一次。
(1次提交表单可下发1条,多次提交下发条数独立,相互不影响) -
模板跳转能力:点击查看详情仅能跳转下发模板的该帐号的小程序各个页面
1.小程序后台配置模版消息
进入模版页面,点击右上角添加按钮,搜索符合需求的模版消息并且配置勾选需要的参数
添加成功之后,模版列表页面复制该模版id,为后续接口调用模版消息使用
2.获取access_tokenaccess_token 的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的 access_token 失效。
接口地址:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
HTTP请求方式:GET
请求参数说明
参数 | 必填 | 说明 |
---|---|---|
grant_type | 是 | 获取 access_token 填写 client_credential |
appid | 是 | 第三方用户唯一凭证 |
secret | 是 | 第三方用户唯一凭证密钥,即appsecret |
返回参数说明
正常情况下,微信会返回下述 JSON 数据包给开发者:
{"access_token": "ACCESS_TOKEN", "expires_in": 7200}
access_token:获取到的凭证
expires_in:凭证有效时间,单位:秒
错误时微信会返回错误码等信息,JSON 数据包示例如下(该示例为 AppID 无效错误):
{"errcode": 40013, "errmsg": "invalid appid"}
3.消息推送
这里需要获取到接收人的openId
-
form_id生成方式
-
页面的 form 组件,属性report-submit为true时,可以声明为需发模板消息,此时点击按钮提交表单可以获取formId,用于发送模板消息。或者当用户完成支付行为,可以获取prepay_id用于发送模板消息。
-
form例子
<form bindsubmit="formSubmit" report-submit="true"> <input name="input" class="input" placeholder="please input here" /> <button formType="submit">Submit</button> <button formType="reset">Reset</button> </form>
js获取form_id
formSubmit: function (e) { var form_id = e.detail.formId; }
-
-
开始推送
- 接口地址:(ACCESS_TOKEN 需换成上文获取到的 access_token)
https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=ACCESS_TOKEN - HTTP请求方式:POST
- 参数说明:
- 接口地址:(ACCESS_TOKEN 需换成上文获取到的 access_token)
-
参数 | 必填 | 说明 |
---|---|---|
touser | 是 | 接收者(用户)的 openid |
template_id | 是 | 所需下发的模板消息的id |
page | 否 | 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。 |
form_id | 是 | 表单提交场景下,为 submit 事件带上的 formId;支付场景下,为本次支付的 prepay_id |
data | 是 | 模板内容,不填则下发空模板 |
color | 否 | 模板内容字体的颜色,不填默认黑色 |
emphasis_keyword | 否 | 模板需要放大的关键词,不填则默认无放大 |
示例:
{
"touser": "OPENID",
"template_id": "TEMPLATE_ID",
"page": "index",
"form_id": "FORMID",
"data": {
"keyword1": {
"value": "339208499",
"color": "#173177"
},
"keyword2": {
"value": "2015年01月05日 12:30",
"color": "#173177"
},
"keyword3": {
"value": "粤海喜来登酒店",
"color": "#173177"
} ,
"keyword4": {
"value": "广州市天河区天河路208号",
"color": "#173177"
}
},
"emphasis_keyword": "keyword1.DATA"
}
返回码说明:
在调用模板消息接口后,会返回JSON数据包。
正常时的返回JSON数据包示例:
```
{
"errcode": 0,
"errmsg": "ok"
}
```
错误时会返回错误码信息,说明如下:
返回码 | 说明 |
---|---|
40037 | template_id不正确 |
41028 | form_id不正确,或者过期 |
41029 | form_id已被使用 |
41030 | page不正确 |
45009 | 接口调用超过限额(目前默认每个帐号日调用限额为100万) |
效果图如下:
事件队列发送消息
针对消息推送,当一条消息需要给很多人推送时或者同时给很多人推送消息时,为了保证服务器不会奔溃和用户请求等待时间,需要使用异步队列来推送消息,目前只有微信公众号这边的消息推送做了异步事件消息队列。
具体实现原理参照:Laravel 队列、laravel 事件监听
-
队列配置
-
配置
将.env队列驱动配置为利用数据库的异步处理
QUEUE_DRIVER=database
生成队列数据库表与失败队列数据库表
php artisan queue:table php artisan queue:failed-table php artisan migrate
-
开启队列监听进程
php artisan queue:listen
或者 开启后台监听(不影响自己输入其他命令)
php artisan queue:listen &
也能用work 后面参数是休息时间和尝试次数
php artisan queue:work connection --daemon --sleep=3 --tries=3
-
-
创建事件监听
-
手动注册监听事件
在文件“/Users/guoqing/work/LouWang/app/Providers/EventServiceProvider.php”的“$listen”数组中添加监听事件路径
eg:
protected $listen = [ 'App\Events\MessageRemind' => [// 事件 'App\Listeners\SendSmsWeChatRemind',// 监听器 ], ];
当然这个时候这个事件监听类还没创建,执行如下命令生成事件和监听器
php artisan event:generate
这个时候“/app/Events/”目录下生成了MessageRemind.php事件类,"/app/Listeners/“下生成了SendSmsWeChatRemind.php监听类
-
定义事件
在事件触发的时候,首先进入事件类,事件类接收到传来的参数,监听器再根据传来的参数做相应的处理操作,所以事件这边基本就是参数的定义和接收传递分发功能。
我们使用构造器接收必要的参数,并将其设置为当前事件属性。
-
定义监听器
监听器handle方法注入事件
eg:public function handle(MessageRemind $event)// 注入事件 { // 获取传来的参数 $remindUsers = $event->remindUsers; $rel_guid = $event->rel_guid; $type = $event->type; $weChatTemplate = $event->weChatTemplate; $smsContent = $event->smsContent; $weChatData = $event->weChatData; // 根据参数相应处理,这里做开始发送消息 }
这里有一点注意,我们怎么将处理事件操作加入到队列中异步操作呢
在开始使用监听器队列之前,请确保在你的服务器或本地开发环境中能够配置并启动 队列 监听器。
要指定监听器启动队列,只需将 ShouldQueue 接口添加到监听器类。由 Artisan 命令 event:generate 生成的监听器已经将此接口导入到当前命名空间中,因此你可以直接使用它:
<?php namespace App\Listeners; use App\Events\MessageRemind; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; class SendSmsWeChatRemind implements ShouldQueue { }
当这个监听器被事件调用时,事件调度器会自动使用 Laravel 的 队列系统。如果在队列中执行监听器时没有抛出异常,任务会在执行完成后自动从队列中删除。
-
-
手动触发监听
调用事件的时候就简单了,只需new event 传入必须的参数即可,而且不会影响后续程序的进行
eg:
event(new MessageRemind($managers, config('status.remind_log_type_find_house_help'), null, $smsContent, $weChatData, 'findHouseHelp'));