一、HTTP接收事件订阅与恢复响应消息
i. 接收事件推送 并回复
1. 无连接:当用户关注微信公众账号的时候 微信公众平台会向我们推送post请求 关注推送的并不是数组 而是XML
2. 接收数据包 $postArr = $GLOBALS['HTTP_RAW_POST_DATA'] ;
a) $GLOBALS["HTTP_RAW_POST_DATA"]
跟$_POST,file_get_contents('php://input') 差不多,用$GLOBALS ["HTTP_RAW_POST_DATA"]或file_get_contents('php://input')的情况大多是为了获取$_POST无法接收的数据类型(如XML数据)
b) Coentent-Type仅在取值为application/x-www-data-urlencoded和multipart/form- data两种情况下,PHP才会将http请求数据包中相应的数据填入全局变量$_POST
c) PHP不能识别的Content-Type类型的时候,会将http请求包中相应的数据填入变量$HTTP_RAW_POST_DATA
d) 只有Coentent-Type不为multipart/form-data的时候,PHP不会将http请求数据包中的相应数据填入php: //input,否则其它情况都会。填入的长度,由Coentent-Length指定。
e) 只有Content-Type为application/x-www-data-urlencoded时,php://input数据才 跟$_POST数据相一致。
f) php://input数据总是跟$HTTP_RAW_POST_DATA相同,但是php://input 比$HTTP_RAW_POST_DATA更凑效,且不需要特殊设置php.ini
g) PHP会将PATH字段的query_path部分,填入全局变量$_GET。通常情况下,GET方法提交的http请求,body为空。
h) 总结:
i. 如果是 application/x-www-form-urlencoded 和 multipart/form-data 格式 用 $_POST;
ii. 如果不能获取的时候比如 text/xml、application/json、soap,使用 file_get_contents('php://input');
在$GLOBALS ["HTTP_RAW_POST_DATA"]取不到值的情况下可以按以下方式排查:
iii. 用file_get_contents('php://input')获取数据。如果获取不到,则可能是数据传输错误,对请求进行捉包,分析数据。
iv. 如果file_get_contents('php://input')有数据。则查看php.ini配置文件。
找到如下,如果没开启则开启
注意:这种处理方式是在php版本较低的时候,在php-ini中才有的配置,当版本升级到7,或者更高的时候该机制就被废弃掉了。
3. 处理成对象 $postObj = simplexml_load_string($postArr) ;
4. 根据事件类型 判断是否是订阅
if(strtolower($postObj->Event) == 'subscribe') {}
5. 拼接串 回复数据包
6. 消息回复 订阅号主动推动送的话一天一条 被动回复的话无限制
a) 回复纯文本
12345678
|
b) 图片 通过素材管理中的接口上传多媒体文件,得到的MediaId
12345678
|
c) 回复单图文
d) 回复多图文 相比单图文 多个
|
namespace app\index\controller;
use think\Controller ;
class Index extends Controller { public function index() { /* file_get_contents("php://input") 获取微信服务器发过来的原始数据 */ $data = file_get_contents("php://input") ; file_put_contents('../app/index/controller/data.txt', $data) ;
/* simplexml_load_string(data,classname,options,ns,is_prefix); data 必需 规定形式良好的 XML 字符串。 classname 可选 规定新对象的 class。 options 可选 LIBXML_NOCDATA - 将 CDATA 设置为文本节点 ... 如果成功则返回 SimpleXMLElement 对象,如果失败则返回 FALSE。 */ $postObj = simplexml_load_string($data,'SimpleXMLElement',LIBXML_NOCDATA) ;
$toUser = $postObj->FromUserName ; $fromUser = $postObj->ToUserName ; $time = time() ; /* 判断该数据包是否是订阅的事件推送 关注取消关注的 消息类型是 event 事件类型,subscribe(订阅)、unsubscribe(取消订阅) */ if(strtolower($postObj->MsgType) == 'event') { if(strtolower($postObj->Event) == 'subscribe') {
/*说明有用户关注公众号 ToUserName 开发者微信号 服务器 FromUserName 发送方帐号(一个OpenID)用户客户端 回复消息数据包(文本)
$type = 'text' ; $content = "欢迎加入XXX,从今天起,我们将携手共进,建议添加个人微信:dongling_shisan,经常会有霸王餐、试吃券、吃货聚会等福利哦! 回复 '吃货' 查看热门菜品, 回复 '照片'查看环境 回复图文|多图文看景 回复 南山南|还魂们看片... " ; //拼接 响应数据包模板 %s字符串类型占位 sprintf() $template = " //变量 依次替换字符串类型%s占位 $info = sprintf($template,$toUser,$fromUser,$time,$type,$content) ; echo $info ; } }else if(strtolower($postObj->MsgType) == 'text') {
$content = $postObj->Content ;//用户发送的内容 原样返回
switch ($content) { case '吃货': $str = "猴头, 燕窝 ,鲨鱼翅" ; $template = " $info = sprintf($template,$toUser,$fromUser,$time,$str) ; echo $info ; break;
case '照片': /* 根据MediaId 查找资源 */ $mediaId = "1ANunD9HLO7sSxQxgENwv4hbKA29wHjqhDZDZYO2i-ttZbrWgZlOAAVs58uu3jPS" ; $template = " $info = sprintf($template,$toUser,$fromUser,$time,$mediaId) ; echo $info ; break ; case '图文': /* */ $title1 = "XXX图文1" ; $description1 = "远看山有色 近听水无声 春去花还在 人来鸟不惊" ; //图文链接 $picurl = "http://mmbiz.qpic.cn/mmbiz_jpg/5GRZGcUXEMITo3InTFUmicJAmZBxSzz80iaSR6lhY1YCiagNZPF2jGSqefjiacIcja109iaHj4kOCy10AtOeajPPXWg/0" ; //点击图文跳转的链接 $url = "http://www.baidu.com" ; $template = " $info = sprintf($template,$toUser,$fromUser,$time,$title1,$description1,$picurl,$url) ; echo $info ; break ; case '多图文': //最多八条 $title1 = "XXX图文1" ; $description1 = "远看山有色 近听水无声 春去花还在 人来鸟不惊" ; //图文链接 $picurl = "http://mmbiz.qpic.cn/mmbiz_jpg/5GRZGcUXEMITo3InTFUmicJAmZBxSzz80iaSR6lhY1YCiagNZPF2jGSqefjiacIcja109iaHj4kOCy10AtOeajPPXWg/0" ; //点击图文跳转的链接 $url = "http://www.baidu.com" ; $template = " $info = sprintf($template,$toUser,$fromUser,$time,$title1,$description1,$picurl,$url,$title1,$description1,$picurl,$url,$title1,$description1,$picurl,$url,$title1,$description1,$picurl,$url,$title1,$description1,$picurl,$url) ; echo $info ; break ; case '南山南': /* mediaId:素材管理接口上传 返回的id */ $mediaId = "6574977520480871501" ; $title = "南山南" ; $description = '马頔' ; $template = " $info = sprintf($template,$toUser,$fromUser,$time,$mediaId,$title,$description) ; echo $info ; break ; default: # code... break; } }else { // $str = "春眠不觉晓" ; $str = '春眠不觉晓 '.'MediaId:'.$postObj->MediaId.' ThumbMediaId:'.$postObj->ThumbMediaId.' MsgId:'.$postObj->MsgId ; $template = " $info = sprintf($template,$toUser,$fromUser,$time,$str) ; echo $info ; }
}
}
|
二、通过素材管理中的接口上传文件 , 返回id
i. 图片 音视频调用的时候 需要一个id 这个id是素材上传之后返回的
ii. 流程:
1. 素材(图片 音|视频 缩略图...先上传到开发者服务器 然后再调用微信的素材接口)
2. 素材分类
a) 临时素材
i. media_id可复用 有效期三天
ii. 素材格式 大小与官网要求一致
1. 图片(image) png|jpeg|jpg|gif 2M
2. 语音(voice) MP3|amr| 5M 长度60秒
3. 视频(video) MP4 10M
4. 缩略图(thumb) JPG 64K
5. 用https://调用接口
iii. 调用接口
http请求方式:POST/FORM,使用https https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE 调用示例(使用curl命令,用FORM表单方式上传一个多媒体文件): curl -F [email protected] "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE" |
http请求方式:POST/FORM,使用https
https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
调用示例(使用curl命令,用FORM表单方式上传一个多媒体文件):
curl -F [email protected] "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE"
b) 永久素材
i. 素材库保存数量有上限 图文消息|图片 5000 其他1000
ii. 素材格式 大小与官网要求一致
1. 图片(image) bmp|png|jpeg|jpg|gif 2M
2. 语音(voice) mp3|wma|wav|amr 2M|60秒
3. 视频(video) mp4 10M
4. 缩略图(thumb) JPG 64K
5. 图文消息 微信后台过滤外部的图片链接 url通过接口获取
6. 上传图文消息内的图片获取URL"接口所上传的图片,不占用公众号的素材库中图片数量的5000个的限制,图片仅支持jpg/png格式,大小必须在1MB以下
7. 图文消息支持正文中插入自己帐号和其他公众号已群发文章链接的能力。
iii. 调用接口
|
c) Form表单 上传本地文件到服务器
i. 不用框架版:
表单:
|
处理文件
|
ii. 调用接口 获取access_token
1. access_token简单了解
a) 公众号的全局唯一接口调用凭据 ;
b) 公众号调用各接口时都需使用access_token ;
c) access_token的存储至少要保留512个字符空间 ;
d) access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效 ;
e) 每天限量 2000个凭证 生产环境 建议存储在redis|memcached ;
2. 获取access_token 调用接口
https请求方式: GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET |
3. 请求上面的接口 不刷新页面返回 access_token ---curl
iii. 得到access_token 之后 调用接口上传素材 返回素材id
1. 接口
得到access_token 之后 调用上面的接口 上传素材 已经上传到自己的服务器 调用接口上传到微信服务器 http请求方式:POST/FORM,使用https https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE |
2. 参数说明
a) access_token : 传入appid appsecret 调用接口返回的
b) type 上传素材的类型
i. 图片(image)
ii. 语音(voice)
iii. 视频(video)
iv. 缩略图(thumb)
3. 用curl 返回post上传文件之后 返回的id
a) 参数
i. $url 即调用的上面的接口
ii. $fielddata 文件数据
b) php5.5+版本 和之前版本 获取文件二进制数据的时候 有区别
需要判断当前php版本
curl上传文件数据的时候 可以使用根目录下的系统 类 \CURLFILE 如果此类不存在 则说明php版本 5.5 以下
4. 调用 返回id
iv. 将返回的id存储 然后就可以根据需求 取id 返回数据
三、开通测试帐号 测试接口(高级接口[服务号|认证之后...])
i. 重新绑定服务器 上传素材
1. 基本配置->服务器配置 先停用
2. (开发者工具->公众平台测试账号)
3. 配置完成 扫码关注
ii. 重新 绑定appid appsecret 获取access_token
iii. 获取素材类型 传入access_token 和文件类型 上传文件到素材库
iv. 分别上传 音|视频|图片|图文 将返回的type media_id created_at 存入数据库(上传素材到素材库 接口需要凭证[appid appsecret接口返回的]和文件类型)
1. 数据库取出图片 随机 返回
v. 视频上传
1. 类型 video 10M mp4格式
2. FAQ:解决 nginx 出现 413 Request Entity Too Large 的问题
a) php.ini根据需要配置 upload_max_filesize = 20M|post_max_size = 20M
b) nginx /etc/nginx/sites..../XXX中 client_max_body_size 20m;
c) 重启nginx服务
3. 同理
a) 上传素材之后 取出数据库中的视频素材 ---media_id
b) 调用回复视频的模板
c) 测试
vi. 回复语音
1. 类型 voice 2M 60秒 AMR|AMRMP3
2. 上传mp3文件的时候 返回的文件类型是 audio需要 调用接口前需要手动置为 voice (调用接口的时候 语音(voice):2M,播放长度不超过60s,支持AMR\MP3格式)
3. 从数据库取出返回的media_id 返回语音
四、官方文档
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432
注意:
所有类型的素材上传(临时素材库) 都是通过access_token(凭证 【传入appid/appsecret调用接口返回的】 和文件类型【image|video...】)
返回json格式字符串 {type:,mediaId:,created_at:}
上传表单
|
接受上传文件并存储到微信服务器
|
公众号获取客户端请求并响应
|