移动端开发(微信开发)day1
一、微信公众平台概述
1、历史起源
- 2011年1月21日,腾讯推出微信(张小龙)
- 2011年8月,用户达到1500万 。到2011年底,微信用户已超过5000万
- 2012年8月20日,腾讯推出微信公众平台功能,同年11月开放第三方接口
- 2013年1月微信突破3亿,海外版wechat用户也达到7000万
- 2013年10月24日,腾讯微信的用户数量已经超过了6亿,每日活跃用户1亿
2、微信公众平台
- 微信公众平台:给个人、企业和组织提供业务服务与用户管理能力的服务平台,如:
查看关注用户,回复用户消息,推送文章消息给用户等
3、微信与微信公众平台区别(★)
- 微信:是一款跨平台的通讯工具。支持单人、多人参与。通过手机网络发送语音、
图片、视频和文字。
- 微信公众平台:管理公众号的系统/平台,可以查看关注用户,推送消息给用户
4、微信公众号
二、概念
1、微信公众号:订阅号与服务号的区别
- 订阅号:针对的是个人和媒体,每天只能发送一条信息,默认有自定义菜单(不可
以自定义跳转地址),不支持微信认证(注:目前订阅号不支持升级服务号)
- 服务号:针对的是企业或组织,每月只能发送4条信息,默认有自定义的菜单,认
证(300/年),认证完成可以使用高级接口(如:微信支付,用户管理等)
微信平台的两种运营模式(★)
- 说明:在微信公众平台注册成功后可以获得一个微信公众号(订阅/服务
等),该公众号可以分享给用户关注,并且后期登录公众平台可以进去管
理(如:查看关注用户,回复关注用户消息,推送消息给关注用户等)
- 编辑模式运营:通过之前注册的公众平台管理公众号
- 开发模式运营:不用原来注册的平台管理公众号,而是自己独立开发
脚下留心:开发者模式和编辑模式相互排斥
编辑模式适用场景
- 不具备开发能力的运营者
- 主要是进行品牌宣传、新闻媒体、自助客服的公众帐号
- 运营初期,不需要特别多的功能
- 开发模式系统升级、故障等特殊情况
三、公众平台注册
1、打开官网
2、填写基本资料
3、验证邮箱,选择账号类型
4、选择【订阅号】后,信息录入
填写身份证姓名和身份证卡号
5、公众号信息
6、注册成功页
通过网址【https://mp.weixin.qq.com/】登录,也可以进入该页面
四、编辑模式运营(了解)
1、编辑模式和开发模式切换
脚下留心:切换开发模式后编辑模式将禁用
2、编辑模式功能
1)群发功能
2)回复功能 – 被关注添加自动回复
关注公共账号,平台发送的关注信息或欢迎语,我们通常称之为订阅回复或关注回复。
3)回复功能 – 关键词自动回复
当我们设定的关键词与用户发送的关键词相匹配时,系统自动回复执行消息。
未全匹配:当用户发送的内容包含当前关键词,系统自动回复。
已全匹配:当用户发送的内容与当前关键词完全匹配,系统自动回复
︴思考:如何修改已经存在的规则
4)回复功能 – 消息自动回复
当用户发送的关键词与我们设定的关键词不匹配时,系统自动回复此信息。
温馨提示:
1、消息自动回复:1个小时内回复1—2条内容;
2、暂不支持设置图文、网页地址消息回复;
3、消息自动回复只能设置一条信息回复。
︴案例:简单号码薄
1)功能需求和效果
用户关注后或输【?】自动弹出自定义回复文本信息如下:
回复1特种服务号码
回复2通讯服务号码
回复3银行服务号码
回复4用户反馈
2)回复1
常用特种服务号码:
匪警:110
火警:119
急救中心:120
3)回复2
常用通讯服务号码:
中移动:10086
中电信:10000
中联通:10010
4)回复3
银行服务号码
建设银行:95533
工商银行:99588
农业银行:95599
5)回复4
尊敬的用户,为了更好的为您服务,请将系统的不足之处反馈给我们。
反馈格式:@+建议内容
例如:@希望增加***号码
回复:感谢您的宝贵建议,我们会努力为您提供更好的服务!
5)关注:
欢迎关注简易号码簿!
在这里,我们为您提供常用号码查询服务。您可以通过文本菜单交互或关键字搜索的方式查找号码。
快回复?开始体验吧!
︴案例:自定义菜单
1)说明
- 自定义菜单一级菜单3个二级菜单5个(共15个菜单)
- 微信自定义菜单,默认是有24小时的缓冲期,所以无法实时预览(注:可以通过取消关注并再次关注,解决此问题)
2)需求:精仿传智播客官方微信
3)步骤
五、开发者模式运营(重要)
1、概念
1)编辑模式原理图
当用户发送消息时,直接发送到微信服务器上,经过微信服务器的处理,则返回给客户端.
2)开发者模式原理图
请求:用户发送消息 ->(XML报文)-> 微信服务器 ->(XML报文)-> 自定义服务器
响应:用户发送消息 <-(XML报文)<- 微信服务器 <-(XML报文)<- 自定义服务器
2、准备自定义服务器(SAE云 或者 阿里云)
1)SAE云(默认有PHP环境)
- 步骤1:打开官网注册进入用户中心
- 步骤2:创建应用(相当于创建虚拟主机)
- 步骤3:服务器代码管理(svn版本控制软件)
脚下留心:仓库目录下必须有以1命名的文件下
- 步骤4:浏览器代码
#常看创建应用设置的二级域名是什么,每个人填写的不一样)
http://php0225.applinzi.com/test.php
2)创建阿里云服务器(需要自己安装PHP环境)
- 步骤1:打开官网注册并点击顶部控制台,进入控制台页点击左侧菜单购买服务器
- 步骤2:选择购买指定节点服务器
- 步骤3:选择计费方式(ps. 该方式需要账号有100元)
- 步骤4:服务器购买清单
- 步骤5:获取服务器公网IP地址
配置阿里云(LAMP环境)
- 安装apache服务
步骤1:安装
步骤2:启动(注:第一次需要修改下配置文件)
步骤3:输入ip访问
步骤4:修改网页访问
- 安装php
步骤1:安装
yum -y install php php-mysql
yum -y install gd php-gd gd-devel php-xml php-common php-curl php-mbstring php-ldap php-pear php-xmlrpc php-imap
步骤2:重启apache,创建php文件测试
- 安装MySQL
步骤1:安装
yum -y install mysql mysql-server mysql-devel
步骤2:启动服务(service mysqld start)
步骤3:登录,更改密码(注:默认密码为空)
update mysql.user set password=password(‘admin888′) where User=’root’;
flush privileges;
3、微信接口开发
1)下载微信PHP SDK
下载地址:
http://mp.weixin.qq.com/mpres/htmledition/res/wx_sample.20140819.zip
2)微信接口初体验
- 步骤1:下载微信官方SDK
http://mp.weixin.qq.com/mpres/htmledition/res/wx_sample.20140819.zip
SDK就是别人开发好的功能或者接口,一般工作中下载第三方SDK输入APPID和APPKEY即可完
成对应功能。
- 步骤2:更改微信SDK,上传服务器(代码如下)
wx.php
<?php
/**
* wechat php test
*/
//define your token
define(“TOKEN”, “itcast”); //脚下留心:token必须和微信公众平台保持一致
$wechatObj = new wechatCallbackapiTest();
$wechatObj->valid();
class wechatCallbackapiTest
{
public function valid()
{
$echoStr = $_GET[“echostr”];
//valid signature , option
if($this->checkSignature()){
echo $echoStr;
exit;
}
}
public function responseMsg()
{
//get post data, May be due to the different environments
$postStr = $GLOBALS[“HTTP_RAW_POST_DATA”];
//extract post data
if (!empty($postStr)){
/* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection,
the best way is to check the validity of xml by yourself */
libxml_disable_entity_loader(true);
$postObj = simplexml_load_string($postStr, ‘SimpleXMLElement’, LIBXML_NOCDATA);
$fromUsername = $postObj->FromUserName;
$toUsername = $postObj->ToUserName;
$keyword = trim($postObj->Content);
$time = time();
$textTpl = “<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>0</FuncFlag>
</xml>”;
if(!empty( $keyword ))
{
$msgType = “text”;
$contentStr = “滚!”;
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
}else{
echo “Input something…”;
}
}else {
echo “”;
exit;
}
}
private function checkSignature()
{
// you must define TOKEN by yourself
if (!defined(“TOKEN”)) {
throw new Exception(‘TOKEN is not defined!’);
}
$signature = $_GET[“signature”];
$timestamp = $_GET[“timestamp”];
$nonce = $_GET[“nonce”];
$token = TOKEN;
$tmpArr = array($token, $timestamp, $nonce);
// use SORT_STRING rule
sort($tmpArr, SORT_STRING);
$tmpStr = implode( $tmpArr );
$tmpStr = sha1( $tmpStr );
if( $tmpStr == $signature ){
return true;
}else{
return false;
}
}
}
?>
- 步骤3:开启开发者模式(校验token)
打开微信公众号管理平台 -> 点击左侧菜单(开发->基本配置) -> 开启开发者模式
- 步骤4:修改SDK(关闭校验,开启响应用户请求)
wx.php
<?php
/**
* wechat php test
*/
//define your token
define(“TOKEN”, “itcast”); //脚下留心:token必须和微信公众平台保持一致
$wechatObj = new wechatCallbackapiTest();
//$wechatObj->valid();
$wechatObj->responseMsg();
class wechatCallbackapiTest
{
public function valid()
{
$echoStr = $_GET[“echostr”];
//valid signature , option
if($this->checkSignature()){
echo $echoStr;
exit;
}
}
public function responseMsg()
{
//get post data, May be due to the different environments
$postStr = $GLOBALS[“HTTP_RAW_POST_DATA”];
//extract post data
if (!empty($postStr)){
/* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection,
the best way is to check the validity of xml by yourself */
libxml_disable_entity_loader(true);
$postObj = simplexml_load_string($postStr, ‘SimpleXMLElement’, LIBXML_NOCDATA);
$fromUsername = $postObj->FromUserName;
$toUsername = $postObj->ToUserName;
$keyword = trim($postObj->Content);
$time = time();
$textTpl = “<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>0</FuncFlag>
</xml>”;
if(!empty( $keyword ))
{
$msgType = “text”;
$contentStr = “滚!”;
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
}else{
echo “Input something…”;
}
}else {
echo “”;
exit;
}
}
private function checkSignature()
{
// you must define TOKEN by yourself
if (!defined(“TOKEN”)) {
throw new Exception(‘TOKEN is not defined!’);
}
$signature = $_GET[“signature”];
$timestamp = $_GET[“timestamp”];
$nonce = $_GET[“nonce”];
$token = TOKEN;
$tmpArr = array($token, $timestamp, $nonce);
// use SORT_STRING rule
sort($tmpArr, SORT_STRING);
$tmpStr = implode( $tmpArr );
$tmpStr = sha1( $tmpStr );
if( $tmpStr == $signature ){
return true;
}else{
return false;
}
}
}
?>
4、微信接口分析
函数认识
- 函数:simplexml_load_string
- 作用:将xml字符串载入到对象中
- 函数:sprintf()
- 作用:将字符串中的百分号替换成变量
接口代码注释
<?php
/**
* wechat php test
*/
//define your token
//定义TOKEN秘钥,用于微信服务器和自定义服务器之间的校验
define(“TOKEN”, “itcast”);
//创建一个wechatObj对象
$wechatObj = new wechatCallbackapiTest();
//调用valid方法,用于微信开发验证和回复
//$wechatObj->valid();
//
$wechatObj->responseMsg();
class wechatCallbackapiTest
{
public function valid()
{
// 接受随机字符串
$echoStr = $_GET[“echostr”];
//valid signature , option
if($this->checkSignature()){
echo $echoStr;
exit;
}
}
public function responseMsg()
{
//get post data, May be due to the different environments
//$GLOBALS[“HTTP_RAW_POST_DATA”]功能与$_POST功能类似,主要用于接收HTTP中的POST请求
//但是$GLOBALS[“HTTP_RAW_POST_DATA”]可以接收XML数据
$postStr = $GLOBALS[“HTTP_RAW_POST_DATA”];
//extract post data
if (!empty($postStr)){
/* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection,
the best way is to check the validity of xml by yourself */
//安全处理:禁止引用外部xml实体, 防止XXE漏洞
// http://www.thinkphp.cn/topic/37740.html
libxml_disable_entity_loader(true);
// simplexml_load_string() 函数把 XML 字符串载入对象中
$postObj = simplexml_load_string($postStr, ‘SimpleXMLElement’, LIBXML_NOCDATA);
$fromUsername = $postObj->FromUserName; // 发送方帐号(一个OpenID)
$toUsername = $postObj->ToUserName; // 开发者微信号
$keyword = trim($postObj->Content); // 文本消息内容
$time = time();
// 文本消息XML模板
$textTpl = “<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>0</FuncFlag>
</xml>”;
if(!empty( $keyword ))
{
$msgType = “text”;
$contentStr = “Welcome to wechat world!”;
// 给XML模板填充数据
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $toUsername.’__’.$fromUsername);
echo $resultStr;
}else{
echo “Input something…”;
}
}else {
echo “”;
exit;
}
}
// 验证数字签名
private function checkSignature()
{
// you must define TOKEN by yourself
// 校验TOKEN秘钥
if (!defined(“TOKEN”)) {
throw new Exception(‘TOKEN is not defined!’);
}
// 接受数字签名
$signature = $_GET[“signature”];
// 接受时间戳
$timestamp = $_GET[“timestamp”];
// 接受随机数
$nonce = $_GET[“nonce”];
// 定义$token 获取TOKEN秘钥
$token = TOKEN;
// token、timestamp、nonce组成数组
$tmpArr = array($token, $timestamp, $nonce);
// use SORT_STRING rule
//数组排序
sort($tmpArr, SORT_STRING);
// 划分成字符串
$tmpStr = implode( $tmpArr );
// 通过哈希算法进行加密
$tmpStr = sha1( $tmpStr );
// 与当前发送过来的数字签名进行比对,成功返回true,否则返回false
if( $tmpStr == $signature ){
return true;
}else{
return false;
}
}
}
?>
六、微信的6大接收接口
︴思考:如何区分数据类型(文本、图片、语音、视频、地理、链接消息)
2、使用php代码判断代码判断用户发送的消息类型
需求:用户发送图片则响应图片消息,视频响应视频消息,文本响应文本消息
发现:通过xml报文中的msgTtype可以判断类型
<?php
/**
* wechat php test
*/
//定义token
define(“TOKEN”, “itcast”);
//创建wechatObj对象
$wechatObj = new wechatCallbackapiTest();
//校验token
//$wechatObj->valid(); 仅开启开发者模式使用一下后期不需要使用
//调用方法响应用户数据
$wechatObj->responseMsg();
class wechatCallbackapiTest
{
public function valid()
{
//随机字符串
$echoStr = $_GET[“echostr”];
//校验token
if($this->checkSignature()){
echo $echoStr;
exit;
}
}
public function responseMsg()
{
//get post data, May be due to the different environments
//和POST一样获取数据,只不过他可以获取xml数据
//接受微信服务器提交过来的xml报文
$postStr = $GLOBALS[“HTTP_RAW_POST_DATA”];
//extract post data
if (!empty($postStr)) {
/* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection,
the best way is to check the validity of xml by yourself */
//安全处理:禁止引用外部xml实体, 防止XXE漏洞
// http://www.thinkphp.cn/topic/37740.html
libxml_disable_entity_loader(true);
//将xml数据转化为对象
$postObj = simplexml_load_string($postStr, ‘SimpleXMLElement’, LIBXML_NOCDATA);
$fromUsername = $postObj->FromUserName; //那个用户发送的
$toUsername = $postObj->ToUserName; //发送给那个用户
$keyword = trim($postObj->Content); //发送的内容(可能是图片、文字、视频等)
$time = time();
$textTpl = “<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>0</FuncFlag>
</xml>”; //被动回复文本xml报文
//根据消息xml报文的MsgType参数判断请求文件类型
switch ($postObj->MsgType) {
case ‘text’:
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, “text”, ‘文本消息’);
break;
case ‘image’:
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, “text”, ‘图片消息’);
break;
case ‘voice’:
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, “text”, ‘语法消息’);
break;
case ‘video’:
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, “text”, ‘视频消息’);
break;
case ‘shortvideo’:
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, “text”, ‘小视频消息’);
break;
case ‘location’:
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, “text”, ‘位置消息’);
break;
case ‘link’:
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, “text”, ‘链接消息’);
break;
default:
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, “text”, ‘滚!’);
break;
}
echo $resultStr;
}else {
echo “”;
exit;
}
}
private function checkSignature()
{
//检测token是否定义
if (!defined(“TOKEN”)) {
throw new Exception(‘TOKEN is not defined!’);
}
//微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
$signature = $_GET[“signature”];
//时间戳
$timestamp = $_GET[“timestamp”];
//随机数
$nonce = $_GET[“nonce”];
//将一个常量的值赋给$token变量
$token = TOKEN;
//将token、时间戳、随机数放到一个数组中
$tmpArr = array($token, $timestamp, $nonce);
//给数组排序
sort($tmpArr, SORT_STRING);
//将数组转化为字符串
$tmpStr = implode( $tmpArr );
//哈希加密
$tmpStr = sha1( $tmpStr );
if( $tmpStr == $signature ){
return true;
}else{
return false;
}
}
}
?>
■ 代码(封装优化)
<?php
/**
* wechat php test
*/
//定义token
define(“TOKEN”, “itcast”);
//创建wechatObj对象
$wechatObj = new wechatCallbackapiTest();
//校验token
//$wechatObj->valid(); 仅开启开发者模式使用一下后期不需要使用
//调用方法响应用户数据
$wechatObj->responseMsg();
class wechatCallbackapiTest
{
public function valid()
{
//随机字符串
$echoStr = $_GET[“echostr”];
//校验token
if($this->checkSignature()){
echo $echoStr;
exit;
}
}
public function responseMsg()
{
//get post data, May be due to the different environments
//和POST一样获取数据,只不过他可以获取xml数据
//接受微信服务器提交过来的xml报文
$postStr = $GLOBALS[“HTTP_RAW_POST_DATA”];
//extract post data
if (!empty($postStr)) {
/* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection,
the best way is to check the validity of xml by yourself */
//安全处理:禁止引用外部xml实体, 防止XXE漏洞
// http://www.thinkphp.cn/topic/37740.html
libxml_disable_entity_loader(true);
//将xml数据转化为对象
$postObj = simplexml_load_string($postStr, ‘SimpleXMLElement’, LIBXML_NOCDATA);
$fromUsername = $postObj->FromUserName; //发送者:那个用户发送的
$toUsername = $postObj->ToUserName; //接受者:发送给那个用户
$keyword = trim($postObj->Content); //发送的内容(可能是图片、文字、视频等)
//根据消息xml报文的MsgType参数判断请求文件类型
switch ($postObj->MsgType) {
case ‘text’:
$this->sendText($fromUsername, $toUsername, ‘文本消息’);
break;
case ‘image’:
$this->sendText($fromUsername, $toUsername, ‘图片消息’);
break;
case ‘voice’:
$this->sendText($fromUsername, $toUsername, ‘语音消息’);
break;
case ‘video’:
$this->sendText($fromUsername, $toUsername, ‘视频消息’);
break;
case ‘shortvideo’:
$this->sendText($fromUsername, $toUsername, ‘小视频消息’);
break;
case ‘location’:
$this->sendText($fromUsername, $toUsername, ‘位置消息’);
break;
case ‘link’:
$this->sendText($fromUsername, $toUsername, ‘链接消息’);
break;
default:
$this->sendText($fromUsername, $toUsername, ‘滚!’);
break;
}
}else {
echo “”;
exit;
}
}
/**
* @param stirng $fromUsername 接受消息的用户
* @param stirng $toUsername 发送消息的用户
* @param stirng $content 内容
*/
private function sendText($fromUsername, $toUsername, $content)
{
$time = time();
$textTpl = “<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>0</FuncFlag>
</xml>”; //被动回复文本xml报文
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, “text”, $content);
echo $resultStr;
}
private function checkSignature()
{
//检测token是否定义
if (!defined(“TOKEN”)) {
throw new Exception(‘TOKEN is not defined!’);
}
//微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
$signature = $_GET[“signature”];
//时间戳
$timestamp = $_GET[“timestamp”];
//随机数
$nonce = $_GET[“nonce”];
//将一个常量的值赋给$token变量
$token = TOKEN;
//将token、时间戳、随机数放到一个数组中
$tmpArr = array($token, $timestamp, $nonce);
//给数组排序
sort($tmpArr, SORT_STRING);
//将数组转化为字符串
$tmpStr = implode( $tmpArr );
//哈希加密
$tmpStr = sha1( $tmpStr );
if( $tmpStr == $signature ){
return true;
}else{
return false;
}
}
}
?>
七、微信订阅回复接口
1、订阅回复接口(关注回复接口)
2、编写PHP代码判断订阅回复
<?php
/**
* wechat php test
*/
//定义token
define(“TOKEN”, “itcast”);
//创建wechatObj对象
$wechatObj = new wechatCallbackapiTest();
//校验token
//$wechatObj->valid(); 仅开启开发者模式使用一下后期不需要使用
//调用方法响应用户数据
$wechatObj->responseMsg();
class wechatCallbackapiTest
{
public function valid()
{
//随机字符串
$echoStr = $_GET[“echostr”];
//校验token
if($this->checkSignature()){
echo $echoStr;
exit;
}
}
public function responseMsg()
{
//get post data, May be due to the different environments
//和POST一样获取数据,只不过他可以获取xml数据
//接受微信服务器提交过来的xml报文
$postStr = $GLOBALS[“HTTP_RAW_POST_DATA”];
//extract post data
if (!empty($postStr)) {
/* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection,
the best way is to check the validity of xml by yourself */
//安全处理:禁止引用外部xml实体, 防止XXE漏洞
// http://www.thinkphp.cn/topic/37740.html
libxml_disable_entity_loader(true);
//将xml数据转化为对象
$postObj = simplexml_load_string($postStr, ‘SimpleXMLElement’, LIBXML_NOCDATA);
$fromUsername = $postObj->FromUserName; //发送者:那个用户发送的
$toUsername = $postObj->ToUserName; //接受者:发送给那个用户
$keyword = trim($postObj->Content); //发送的内容(可能是图片、文字、视频等)
//根据消息xml报文的MsgType参数判断请求文件类型
switch ($postObj->MsgType) {
case ‘event’:
//Event 事件类型,subscribe(订阅)、unsubscribe(取消订阅)
if ($postObj->Event == ‘subscribe’) {
$this->sendText($fromUsername, $toUsername, ‘感谢老板关注,需要xx请服务1’);
} else {
//后期项目封装可能需要修改数据库
}
break;
case ‘text’:
$this->sendText($fromUsername, $toUsername, ‘文本消息’);
break;
case ‘image’:
$this->sendText($fromUsername, $toUsername, ‘图片消息’);
break;
case ‘voice’:
$this->sendText($fromUsername, $toUsername, ‘语音消息’);
break;
case ‘video’:
$this->sendText($fromUsername, $toUsername, ‘视频消息’);
break;
case ‘shortvideo’:
$this->sendText($fromUsername, $toUsername, ‘小视频消息’);
break;
case ‘location’:
$this->sendText($fromUsername, $toUsername, ‘位置消息’);
break;
case ‘link’:
$this->sendText($fromUsername, $toUsername, ‘链接消息’);
break;
default:
$this->sendText($fromUsername, $toUsername, ‘滚!’);
break;
}
}else {
echo “”;
exit;
}
}
/**
* @param stirng $fromUsername 接受消息的用户
* @param stirng $toUsername 发送消息的用户
* @param stirng $content 内容
*/
private function sendText($fromUsername, $toUsername, $content)
{
$time = time();
$textTpl = “<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>0</FuncFlag>
</xml>”; //被动回复文本xml报文
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, “text”, $content);
echo $resultStr;
}
private function checkSignature()
{
//检测token是否定义
if (!defined(“TOKEN”)) {
throw new Exception(‘TOKEN is not defined!’);
}
//微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
$signature = $_GET[“signature”];
//时间戳
$timestamp = $_GET[“timestamp”];
//随机数
$nonce = $_GET[“nonce”];
//将一个常量的值赋给$token变量
$token = TOKEN;
//将token、时间戳、随机数放到一个数组中
$tmpArr = array($token, $timestamp, $nonce);
//给数组排序
sort($tmpArr, SORT_STRING);
//将数组转化为字符串
$tmpStr = implode( $tmpArr );
//哈希加密
$tmpStr = sha1( $tmpStr );
if( $tmpStr == $signature ){
return true;
}else{
return false;
}
}
}
?>
八、微信消息的6大回复接口
1、回复文本接口
1)xml报文
2)代码
/**
* @param stirng $fromUsername 接受消息的用户
* @param stirng $toUsername 发送消息的用户
* @param stirng $content 内容
*/
private function sendText($fromUsername, $toUsername, $content)
{
$time = time();
$textTpl = “<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>0</FuncFlag>
</xml>”; //被动回复文本xml报文
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, “text”, $content);
echo $resultStr;
}
2、回复图片、语音、视频消息
1)图片xml报文
—————————-
【获取Mediald】
步骤1:
https://mp.weixin.qq.com/debug/cgi-bin/apiinfo?t=index&type=基础支持
2)代码
Eg2F6ND63LqjRvlOdaEV_lxGjgO9KIRDZm8e54hcTYH-P-FyBZA55FNad8a8pQMA
视频xml报文
代码
3、音乐回复接口
1)xml报文
2)代码
4、图文回复接口(重点重点)
1)xml报文
2)代码
/**
* 响应图文(优化版)
* @param stirng $fromUsername 接受消息的用户
* @param stirng $toUsername 发送消息的用户
* @param array $arr 图文消息二位数组(注;第二层数组字段 title,desc,picurl,url)
*/
private function sendImgArticle($fromUsername, $toUsername, $arr)
{
$textTpl = “<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<ArticleCount>%s</ArticleCount>
<Articles>”;
foreach ($arr as $img) {
$textTpl .= “<item>
<Title><![CDATA[{$img[‘title’]}]]></Title>
<Description><![CDATA[{$img[‘desc’]}]]></Description>
<PicUrl><![CDATA[{$img[‘picurl’]}]]></PicUrl>
<Url><![CDATA[{$img[‘url’]}]]></Url>
</item>”;
}
$textTpl .= “</Articles>
</xml>”;
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, time(), count($arr));
echo $resultStr;
}
/**
* 响应单图文
* @param stirng $fromUsername 接受消息的用户
* @param stirng $toUsername 发送消息的用户
*/
private function sendImgArticle1($fromUsername, $toUsername)
{
$textTpl = “<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<ArticleCount>%s</ArticleCount>
<Articles>
<item>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<PicUrl><![CDATA[%s]]></PicUrl>
<Url><![CDATA[%s]]></Url>
</item>
</Articles>
</xml>”;
$imgCount = 1;
$title = ‘单图文’;
$desc = ‘xxx’;
$picurl = ‘http://47.52.95.83/zhaoxiaokang/img/b1.jpg’;
$url = ‘http://baidu.com’;
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, time(), $imgCount, $title, $desc, $picurl, $url);
echo $resultStr;
}
/**
* 响应多图文
* @param stirng $fromUsername 接受消息的用户
* @param stirng $toUsername 发送消息的用户
*/
private function sendImgArticleN($fromUsername, $toUsername)
{
$textTpl = “<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<ArticleCount>3</ArticleCount>
<Articles>
<item>
<Title><![CDATA[大图]]></Title>
<Description><![CDATA[bigimg]]></Description>
<PicUrl><![CDATA[http://47.52.95.83/zhaoxiaokang/img/b1.jpg]]></PicUrl>
<Url><![CDATA[http://baidu.com]]></Url>
</item>
<item>
<Title><![CDATA[小图1]]></Title>
<Description><![CDATA[one]]></Description>
<PicUrl><![CDATA[http://47.52.95.83/zhaoxiaokang/img/one.png]]></PicUrl>
<Url><![CDATA[http://baidu.com]]></Url>
</item>
<item>
<Title><![CDATA[小图2]]></Title>
<Description><![CDATA[two]]></Description>
<PicUrl><![CDATA[http://47.52.95.83/zhaoxiaokang/img/two.png]]></PicUrl>
<Url><![CDATA[http://baidu.com]]></Url>
</item>
</Articles>
</xml>”;
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, time());
echo $resultStr;
}
︴自觉练习