一、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>

<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>

<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>

<?phpnamespace 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 ;}}}

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. 调用接口

http请求方式: POST,https协议
https://api.weixin.qq.com/cgi-bin/material/add_news?access_token=ACCESS_TOKEN

c)  Form表单 上传本地文件到服务器

i. 不用框架版:

表单:

<!DOCTYPE html><html><head><meta charset="utf-8"><title>素材上传</title><link rel="stylesheet" type="text/css" href="./bootstrap.min.css"></head><body><div style="width:80%;height:36%;background: #EEE;margin:auto;padding:3%;"><form method="post" enctype="multipart/form-data" action="./action.php"><div class="form-group"><label for="exampleInputFile">File input</label><input type="file"  name="pic"></div><button type="submit" class="btn btn-info">Submit</button></form></div></body></html>

处理文件

<?php/*$_FILES 是二维数组 默认多文件上传 'pic'=>[],...*/$img = $_FILES['pic'] ;// var_dump($img) ;$ext = pathinfo($img['name'])['extension'] ;//获取上传文件后缀$str = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMNOPQRSTUVWXYZ" ;str_shuffle($str) ;$fileName = substr(str_shuffle($str),26,10) . time() . '.' . $ext ;$path = './file/'.$fileName ;//判断是否是  上传文件   移动到服务器文件夹if(is_uploaded_file($img['tmp_name'])) {//执行移动临时文件  $res = move_uploaded_file($img['tmp_name'], $path) ;if($res){/*已经上传到自己的服务器  调用接口上传到微信服务器http请求方式:POST/FORM,使用httpshttps://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE需要  access_token调用接口凭证*/echo '上传成功' ;}else {echo '上传失败' ;}}

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:}

上传表单

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>素材上传</title><link rel="stylesheet" type="text/css" href="./bootstrap.min.css">
</head>
<body>
<div style="width:80%;height:36%;background: #EEE;margin:auto;padding:3%;">
<form method="post" enctype="multipart/form-data" action="./action.php"><div class="form-group"><label for="exampleInputFile">File input</label><input type="file"  name="pic"></div><button type="submit" class="btn btn-info">Submit</button>
</form>
</div>
</body>
</html>

接受上传文件并存储到微信服务器

<?php/*
$_FILES 是二维数组 默认多文件上传 'pic'=>[],...
*/
$img = $_FILES['pic'] ;
// var_dump($img) ;
$ext = pathinfo($img['name'])['extension'] ;//获取上传文件后缀$str = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMNOPQRSTUVWXYZ" ;
str_shuffle($str) ;
$fileName = substr(str_shuffle($str),26,10) . time() . '.' . $ext ;$path = './file/'.$fileName ;//获取文件类型
$type = explode('/',$img['type'])[0] ;
// var_dump($type) ;die ;
if($type == 'audio') {
//上传mp3音频返回  audio
$type = 'voice' ;
}//判断是否是  上传文件   移动到服务器文件夹
if(is_uploaded_file($img['tmp_name'])) {
//执行移动临时文件
$res = move_uploaded_file($img['tmp_name'], $path) ;
if($res){/*已经上传到自己的服务器  调用接口上传到微信服务器http请求方式:POST/FORM,使用https
https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
需要  access_token调用接口凭证
AppID  AppSecret 配置IP白名单 (个人服务器IP)*//*https请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET*/$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wxae6ea3e45f074997&secret=2cbafacadab5493a73144fd08a517f52" ;/*
请求上面接口 不刷新页面 得到access_token  并返回
curl
引入Http.class.php  调用封装好的get|post方法*/
require_once("./Http.class.php") ;
$res = Http::get($url) ;
/*$ch = curl_init($url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//将返回结果进行转换$res = curl_exec($ch);//发送请求*///json格式的字串$res转换成数组  第二个参数不传的话  $arr是对象格式
$arr = json_decode($res,true) ;/*得到access_token 之后  调用上面的接口 上传素材
已经上传到自己的服务器  调用接口上传到微信服务器http请求方式:POST/FORM,使用https
https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE access_token :  传入appid appsecret 调用接口返回的
type 上传素材的类型
图片(image)|语音(voice)|视频(video)|缩略图(thumb)
*/$url1 = 'https://api.weixin.qq.com/cgi-bin/media/upload?access_token='.$arr["access_token"].'&type='.$type ;/*
$curl  地址
$filedata 文件数据
php5.5+版本 和之前版本 获取文件二进制数据的时候 有区别
需要判断当前php版本
curl上传文件数据的时候   可以使用根目录下的系统类 \CURLFILE
如果此类不存在  则说明php版本 5.5以下
*/
if(class_exists('\CURLFILE')) {
//存在  php5.5+
$filedata = array(
//$path  要上传到微信服务器的文件
'filename' => new \CURLFILE($path)
) ;
}else {
//不存在 php5.5-
$filedata = array(
//直接赋值给 $path的话会报notice级别错误
'filename' => '@'.$path
) ;
}$res = Http::post($url1,$filedata) ;//json格式字串
// var_dump($res) ;die ;
//将返回的type ,media_id ,create_at存入数据库 weixin/sucai
try {
$pdo = new PDO("mysql:host=localhost;dbname=weixin",'root','root') ;
} catch (Exception $e) {
echo "mysql connected error!" ;
}
$sql = "INSERT INTO sucai(type,media_id,created_at) VALUES(:type,:media_id,:created_at)" ;
$stmt = $pdo->prepare($sql) ;
//$res为之前返回的json字串
$stmt->execute(json_decode($res,true)) ;echo '上传成功' ;
}else {
echo '上传失败' ;
}
}

公众号获取客户端请求并响应

<?php/*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() ;try {$pdo = new PDO("mysql:host=localhost;dbname=weixin",'root','root') ;} catch (Exception $e) {echo "mysql connected error!" ;}// 查询所有media_id  图片的 $sql = "SELECT * FROM sucai WHERE type='image' ORDER BY id DESC" ;$stmt = $pdo->query($sql) ;$arr = $stmt->fetchAll(PDO::FETCH_ASSOC) ;//查询所有  二维数组/*判断该数据包是否是订阅的事件推送关注取消关注的消息类型是   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 = "欢迎加入吃货小分队,从今天起,我们将携手共进,建议添加小分队个人微信: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 = "mRgMr3wHDQlHXA843dmE1sfZ8tWPslz4ekaZZdU0ASsaSlKpDbUdmaWsDnAxDVlM" ;shuffle($arr);//打乱数组$mediaId = $arr[2]['media_id'] ;$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 = "图文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 = "图文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 '视频'://视频的try {$pdo1 = new PDO("mysql:host=localhost;dbname=weixin",'root','root') ;} catch (Exception $e) {echo "mysql connected error!" ;}$sql1 = "SELECT * FROM sucai WHERE type='video' ORDER BY id DESC " ;$stmt = $pdo1->query($sql1) ;$arr1 = $stmt->fetchAll(PDO::FETCH_ASSOC) ;$mediaId = $arr1[0]['media_id'] ;$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 = printf($template,$toUser,$fromUser,$time,$mediaId,$title,$description) ;break ;case '语音':/*数据库取出所需音频*/try {$pdo = new PDO("mysql:host=localhost;dbname=weixin",'root','root') ;} catch (Exception $e) {echo "MySQL connected error!" ;}$sql = "SELECT * FROM sucai WHERE type='voice' ORDER BY id DESC" ;$stmt = $pdo->query($sql) ;$arr = $stmt->fetchAll(PDO::FETCH_ASSOC) ;$mediaId = $arr[0]['media_id'] ;$template="<xml><ToUserName><![CDATA[%s]]></ToUserName><FromUserName><![CDATA[%s]]></FromUserName><CreateTime>%s</CreateTime><MsgType><![CDATA[voice]]></MsgType><Voice><MediaId><![CDATA[%s]]></MediaId></Voice></xml>" ;$info = printf($template,$toUser,$fromUser,$time,$mediaId) ;file_put_contents('data.txt', $info) ;echo $info ;break;default:$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 ;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 ;}
 

PHP实现微信公众平台开发---提升篇(上传素材并回复)相关推荐

  1. java微信公众平台开发四(上传素材)

    最近公司要做微信方面的开发,今天说下,如何使用微信的素材管理的接口,这里主要讲下素材的上传接口,下载之类的比较简单(就是解析json而已),今天会把所有的素材上传写道一个方法里供大家参考,关于上传的接 ...

  2. PHP实现微信公众平台开发---提升篇(网页授权接口)

    网页授权接口(类似于浏览器通过cookie|session标识客户 微信端通过openid标识) 接口类型(通过网页授权 获取openid) snsapi_base:基本类型 静默授权并自动跳转到回调 ...

  3. 微信公众平台开发 - 动手篇。使用weinxinFundation开始一个微信公众平台的开发

    本文主要讲解如何使用 weinxinFundation 进行二次开发. 步骤如下: 1.创建新的web项目. 在eclipse里新建一个dynamicly web project,比如本文叫weixi ...

  4. 微信公众平台开发——问题篇

    2019独角兽企业重金招聘Python工程师标准>>> 1. 我该在哪里写开发代码:      在你url中的index.php中编写所有代码.无论是自定义菜单还是自动回复消息    ...

  5. PHP微信公众平台开发高级篇--群发接口

    群发消息接口 订阅号:每天一条的群发权限 服务号:每月(自然月)4条群发权限 实例 <?php /*** 群发接口* PS:群发之前调用"预览接口"进行测试* PS:通过第三 ...

  6. 微信公众平台开发 进入篇(Web App开发入门)

    WebApp与Native App有何区别呢? Native App: 1.开发成本非常大.一般使用的开发语言为Java.C++.Objective-C. 2.更新体验较差.同时也比较麻烦.每一次发布 ...

  7. PHP微信公众平台开发高级篇—生成二维码接口

    一.说明 1.这里讲解生成二维码接口(临时二维码和永久二维码) 2.这里给出简单的实现代码,不做详细说明 3.可以参考开发手册: https://mp.weixin.qq.com/wiki?t=res ...

  8. PHP微信公众平台开发高级篇--生成二维码接口

    临时二维码 实例 临时二维码 <?php /*** 生成二维码接口* 文档地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id= ...

  9. 微信公php开发视频,PHP实现微信公众平台开发 全套视频资源下载

    好久没有更新东西了,今天给大家分享一份比较不错的视频学习资源吧. 主要是关于PHP实现微信公众平台开发, 不知道大家对于微信平台的开发有多少了解,那么今天就从基础开始吧,资源目录如下(PS :适各自的 ...

最新文章

  1. 【数据结构】顺序表的应用(3)(C语言)
  2. iPhone开发:Objective-c中@property声明时的参数释疑
  3. 第三篇——第二部分——第四文 配置SQL Server镜像——非域环境
  4. 微信提交表单到服务器,微信小程序页面表单如何跟图片一起上传服务器
  5. create react app创建的项目运行test的时候不能解析webpack的alisa配置的问题
  6. Tomcat(二):server.xml配置
  7. 删除服务中的mysql服务
  8. 【LOJ#2507】[CEOI2011]Matching(KMP,树状数组)
  9. Java高级面试题!这是一份面向Java开发者的复习指南
  10. 外边距的典型应用-让块级盒子水平居中(HTML、CSS)
  11. 大数据分析的价值体现
  12. 保存同一个H264视频流,第一个文件能播放,第二个播放不了。为什么
  13. (76) Clojure: Why would someone learn Clojure? - Quora
  14. Centos8[Linux]下载安装qq音乐,亲测可行
  15. 机器学习与模式识别期末试题回忆
  16. 2021Eclipse最新下载与安装教程
  17. linux下的etc是什么意思
  18. 期货模拟盘有效果吗?
  19. (机器学习)随机森林填补缺失值的思路和代码逐行详解
  20. 巨量jsvmp,扣逻辑分析

热门文章

  1. nodejs 面试题(个人总结)
  2. 初级会计实务(2020年)——第一章 会计概述
  3. 给apk加system权限
  4. 统计物理中“无用”的过渡量
  5. memory cache 和 disk cache
  6. 互联网架构(一)总体架构设计
  7. python中的面向对象、类
  8. 属性和方法的区别是什么_痤疮和痘痘有什么区别?长痘痘之后3种护肤方法,痤疮3种治疗方式...
  9. python 编码规范-命名规范
  10. YouTube多语种视频营销,低成本也能带来高收益