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-urlencodedmultipart/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-Typeapplication/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/xmlapplication/jsonsoap,使用 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>

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>

 

 

<?php

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

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,使用https

https://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 60AMR|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 = "欢迎加入魔都的吃货小分队,从今天起,我们将携手共进,消灭每一道魔都美食同时建议添加小分队个人微信:mdchihuo009,经常会有霸王餐、试吃券、吃货聚会等福利哦! 回复 '吃货' 查看热门菜品, 回复 '照片'查看环境, 回复图文|多图文看景 ,回复 '视频' 看片,回复 '语音'听李白... " ;
               //拼接 响应数据包模板  %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 ;
        }


    


    


 

猜你喜欢

转载自blog.csdn.net/donglingjiu/article/details/81014313