PHP实现微信公众平台开发---提升篇(上传素材并回复)
一、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) 回复纯文本
<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>12345678</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[你好]]></Content></xml>
b) 图片 通过素材管理中的接口上传多媒体文件,得到的MediaId
<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>12345678</CreateTime><MsgType><![CDATA[image]]></MsgType><Image><MediaId><![CDATA[media_id]]></MediaId></Image></xml>
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><![CDATA[image]]></MsgType> <Image> <MediaId><![CDATA[media_id]]></MediaId> </Image> </xml> |
c) 回复单图文
d) 回复多图文 相比单图文 多个<item>.......</item>
<ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><![CDATA[news]]></MsgType> <ArticleCount>2</ArticleCount> <Articles> <item> <Title><![CDATA[title1]]></Title> <Description><![CDATA[description1]]></Description> <PicUrl><![CDATA[picurl]]></PicUrl> <Url><![CDATA[url]]></Url> </item> <item> <Title><![CDATA[title]]></Title> <Description><![CDATA[description]]></Description> <PicUrl><![CDATA[picurl]]></PicUrl> <Url><![CDATA[url]]></Url> </item> </Articles> </xml> |
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)用户客户端 回复消息数据包(文本) <xml> <ToUserName>< ![CDATA[toUser] ]></ToUserName> <FromUserName>< ![CDATA[fromUser] ]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType>< ![CDATA[text] ]></MsgType> <Content>< ![CDATA[你好] ]></Content> </xml>*/ $type = 'text' ; $content = "欢迎加入XXX,从今天起,我们将携手共进,建议添加个人微信:dongling_shisan,经常会有霸王餐、试吃券、吃货聚会等福利哦! 回复 '吃货' 查看热门菜品, 回复 '照片'查看环境 回复图文|多图文看景 回复 南山南|还魂们看片... " ; //拼接 响应数据包模板 %s字符串类型占位 sprintf() $template = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[%s]]></MsgType><Content><![CDATA[%s]]></Content></xml>" ; //变量 依次替换字符串类型%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 = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[%s]]></Content></xml>" ; $info = sprintf($template,$toUser,$fromUser,$time,$str) ; echo $info ; break; case '照片': /* 根据MediaId 查找资源 <MediaId><![CDATA[saVsB8ck2duFJLEpOIHV-40klqwRDjUkWQiOZ8QZCXIwQaEaKfPC4csUUXiXSrjA]]></MediaId> */ $mediaId = "1ANunD9HLO7sSxQxgENwv4hbKA29wHjqhDZDZYO2i-ttZbrWgZlOAAVs58uu3jPS" ; $template = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[image]]></MsgType><Image><MediaId><![CDATA[%s]]></MediaId></Image></xml>" ; $info = sprintf($template,$toUser,$fromUser,$time,$mediaId) ; echo $info ; break ; case '图文': /* <xml><ToUserName>< ![CDATA[toUser] ]></ToUserName><FromUserName>< ![CDATA[fromUser] ]></FromUserName><CreateTime>12345678</CreateTime><MsgType>< ![CDATA[news] ]></MsgType><ArticleCount>2</ArticleCount><Articles><item><Title>< ![CDATA[title1] ]></Title> <Description>< ![CDATA[description1] ]></Description><PicUrl>< ![CDATA[picurl] ]></PicUrl><Url>< ![CDATA[url] ]></Url></item><item><Title>< ![CDATA[title] ]></Title><Description>< ![CDATA[description] ]></Description><PicUrl>< ![CDATA[picurl] ]></PicUrl><Url>< ![CDATA[url] ]></Url></item></Articles></xml> */ $title1 = "XXX图文1" ; $description1 = "远看山有色 近听水无声 春去花还在 人来鸟不惊" ; //图文链接 $picurl = "http://mmbiz.qpic.cn/mmbiz_jpg/5GRZGcUXEMITo3InTFUmicJAmZBxSzz80iaSR6lhY1YCiagNZPF2jGSqefjiacIcja109iaHj4kOCy10AtOeajPPXWg/0" ; //点击图文跳转的链接 $url = "http://www.baidu.com" ; $template = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[news]]></MsgType><ArticleCount>1</ArticleCount><Articles><item><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description><PicUrl><![CDATA[%s]]></PicUrl><Url><![CDATA[%s]]></Url></item></Articles></xml>" ; $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 = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[news]]></MsgType><ArticleCount>5</ArticleCount><Articles><item><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description><PicUrl><![CDATA[%s]]></PicUrl><Url><![CDATA[%s]]></Url></item><item><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description><PicUrl><![CDATA[%s]]></PicUrl><Url><![CDATA[%s]]></Url></item><item><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description><PicUrl><![CDATA[%s]]></PicUrl><Url><![CDATA[%s]]></Url></item><item><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description><PicUrl><![CDATA[%s]]></PicUrl><Url><![CDATA[%s]]></Url></item><item><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description><PicUrl><![CDATA[%s]]></PicUrl><Url><![CDATA[%s]]></Url></item></Articles></xml>" ; $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 '南山南': /* <xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>12345678</CreateTime><MsgType><![CDATA[video]]></MsgType><Video><MediaId><![CDATA[media_id]]></MediaId><Title><![CDATA[title]]></Title><Description><![CDATA[description]]></Description></Video> </xml> mediaId:素材管理接口上传 返回的id */ $mediaId = "6574977520480871501" ; $title = "南山南" ; $description = '马頔' ; $template = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[video]]></MsgType><Video><MediaId><![CDATA[%s]]></MediaId><Title><![CDATA[%s]]></Title><Description><![CDATA[%s]]></Description></Video></xml>" ; $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 = "<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[%s]]></Content></xml>" ; $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 media=@test.jpg "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE" |
http请求方式:POST/FORM,使用httpshttps://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE调用示例(使用curl命令,用FORM表单方式上传一个多媒体文件):curl -F media=@test.jpg "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:}
上传表单
|
接受上传文件并存储到微信服务器
|
公众号获取客户端请求并响应
|
PHP实现微信公众平台开发---提升篇(上传素材并回复)相关推荐
- java微信公众平台开发四(上传素材)
最近公司要做微信方面的开发,今天说下,如何使用微信的素材管理的接口,这里主要讲下素材的上传接口,下载之类的比较简单(就是解析json而已),今天会把所有的素材上传写道一个方法里供大家参考,关于上传的接 ...
- PHP实现微信公众平台开发---提升篇(网页授权接口)
网页授权接口(类似于浏览器通过cookie|session标识客户 微信端通过openid标识) 接口类型(通过网页授权 获取openid) snsapi_base:基本类型 静默授权并自动跳转到回调 ...
- 微信公众平台开发 - 动手篇。使用weinxinFundation开始一个微信公众平台的开发
本文主要讲解如何使用 weinxinFundation 进行二次开发. 步骤如下: 1.创建新的web项目. 在eclipse里新建一个dynamicly web project,比如本文叫weixi ...
- 微信公众平台开发——问题篇
2019独角兽企业重金招聘Python工程师标准>>> 1. 我该在哪里写开发代码: 在你url中的index.php中编写所有代码.无论是自定义菜单还是自动回复消息 ...
- PHP微信公众平台开发高级篇--群发接口
群发消息接口 订阅号:每天一条的群发权限 服务号:每月(自然月)4条群发权限 实例 <?php /*** 群发接口* PS:群发之前调用"预览接口"进行测试* PS:通过第三 ...
- 微信公众平台开发 进入篇(Web App开发入门)
WebApp与Native App有何区别呢? Native App: 1.开发成本非常大.一般使用的开发语言为Java.C++.Objective-C. 2.更新体验较差.同时也比较麻烦.每一次发布 ...
- PHP微信公众平台开发高级篇—生成二维码接口
一.说明 1.这里讲解生成二维码接口(临时二维码和永久二维码) 2.这里给出简单的实现代码,不做详细说明 3.可以参考开发手册: https://mp.weixin.qq.com/wiki?t=res ...
- PHP微信公众平台开发高级篇--生成二维码接口
临时二维码 实例 临时二维码 <?php /*** 生成二维码接口* 文档地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id= ...
- 微信公php开发视频,PHP实现微信公众平台开发 全套视频资源下载
好久没有更新东西了,今天给大家分享一份比较不错的视频学习资源吧. 主要是关于PHP实现微信公众平台开发, 不知道大家对于微信平台的开发有多少了解,那么今天就从基础开始吧,资源目录如下(PS :适各自的 ...
最新文章
- 【数据结构】顺序表的应用(3)(C语言)
- iPhone开发:Objective-c中@property声明时的参数释疑
- 第三篇——第二部分——第四文 配置SQL Server镜像——非域环境
- 微信提交表单到服务器,微信小程序页面表单如何跟图片一起上传服务器
- create react app创建的项目运行test的时候不能解析webpack的alisa配置的问题
- Tomcat(二):server.xml配置
- 删除服务中的mysql服务
- 【LOJ#2507】[CEOI2011]Matching(KMP,树状数组)
- Java高级面试题!这是一份面向Java开发者的复习指南
- 外边距的典型应用-让块级盒子水平居中(HTML、CSS)
- 大数据分析的价值体现
- 保存同一个H264视频流,第一个文件能播放,第二个播放不了。为什么
- (76) Clojure: Why would someone learn Clojure? - Quora
- Centos8[Linux]下载安装qq音乐,亲测可行
- 机器学习与模式识别期末试题回忆
- 2021Eclipse最新下载与安装教程
- linux下的etc是什么意思
- 期货模拟盘有效果吗?
- (机器学习)随机森林填补缺失值的思路和代码逐行详解
- 巨量jsvmp,扣逻辑分析