企业号和订阅号服务号最大区别,千万注意消息加密和解密!!!
做企业号开发时,先明白自己想用做什么,消息交互还是其他的,最好先看看企业号开发文档,不然骚时候会来来回回查开发文档。
点击菜单时回复消息时,流程为:
先调用官方给的VerifyURL($sMsgSignature, $sTimeStamp, $sNonce, $sEchoStr, &$sReplyEchoStr)函数进行URL验证,
其次对消息进行解密DecryptMsg($sMsgSignature, $sTimeStamp = null, $sNonce, $sPostData, &$sMsg)来检验消息的真实性,同时获取解密后的明文
接下来就是最重要的一部,调用被动响应消息,对你将要发的消息进行XML封装。(官方封装包见下)
剩下就是对封装后的消息进行加密和发送。加密函数EncryptMsg($sReplyMsg, $sTimeStamp, $sNonce, &$sEncryptMsg)
这三个函数来源WXBizMsgCrypt.php。(PHP版本下载地址:http://qydev.weixin.qq.com/download/php.zip)
图文消息是回复最复杂的一种,其官方给的封装包为:
<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
header("content-type: text/html; charset=utf-8");
include ("access_token.php");
include_once "php/WXBizMsgCrypt.php";
$encodingAesKey="JYGhEh6M5jYwW3JQHHlACNqHsoQyxzMlCRgBu9RWzzF";
$token="weixin";
$corpId="wx927b678d5dd1616e";
//公众号服务器数据
$sReqMsgSig = $_GET['msg_signature'];
$sVerifyMsgSig = $_GET['msg_signature'];//签名串,对应URL参数的msg_signature
$sReqTimeStamp = $_GET['timestamp'];
$sVerifyTimeStamp = $_GET['timestamp'];//时间戳 对应URL参数的timestamp
$sReqNonce = $_GET['nonce'];
$sVerifyNonce = $_GET['nonce'];//随机串
$sReqData = file_get_contents("php://input");
$sVerifyEchoStr = $_GET['echostr'];//随机串,对应URL参数的echostr
$wxcpt = new WXBizMsgCrypt($token, $encodingAesKey, $corpId);
global $sEncrytMsg;//xml格式的密文
if($sVerifyEchoStr){
$sEchoStr = "";//解密后的echostr
$errCode = $wxcpt->VerifyURL($sVerifyMsgSig, $sVerifyTimeStamp, $sVerifyNonce, $sVerifyEchoStr, $sEchoStr);
if ($errCode == 0) {
print($sEchoStr);
} else {
print($errCode . "\n\n");
}
exit;
}
/**
* 检验消息的真实性,并且获取解密后的明文.
* <ol>
* <li>利用收到的密文生成安全签名,进行签名验证</li>
* <li>若验证通过,则提取xml中的加密消息</li>
* <li>对消息进行解密</li>
* </ol>
*
* @param $sReqMsgSig string 签名串,对应URL参数的msg_signature
* @param $sReqTimeStamp string 时间戳 对应URL参数的timestamp
* @param $sReqNonce string 随机串,对应URL参数的nonce
* @param $sReqData string 密文,对应POST请求的数据
* @param &$sMsg string 解密后的原文,当return返回0时有效
*
*/
$sMsg="";//解析之后的明文
$errCode = $wxcpt->DecryptMsg($sReqMsgSig, $sReqTimeStamp, $sReqNonce, $sReqData, $sMsg);
if ($errCode == 0)
{
$xml = new DOMDocument();
$xml->loadXML($sMsg);
$reqToUserName = $xml->getElementsByTagName('ToUserName')->item(0)->nodeValue;
$reqFromUserName = $xml->getElementsByTagName('FromUserName')->item(0)->nodeValue;
$reqCreateTime = $xml->getElementsByTagName('CreateTime')->item(0)->nodeValue;
$reqMsgType = $xml->getElementsByTagName('MsgType')->item(0)->nodeValue;
$reqContent = $xml->getElementsByTagName('Content')->item(0)->nodeValue;
$reqEventKey = $xml->getElementsByTagName('EventKey')->item(0)->nodeValue;
$reqMsgId = $xml->getElementsByTagName('MsgId')->item(0)->nodeValue;
$reqAgentID = $xml->getElementsByTagName('AgentID')->item(0)->nodeValue;
if($reqMsgType=="event" && $reqEventKey=="ExamSystem"){
$title="考试";
$description="";
$picurl="http://120.24.47.142/picture/happy.jpg";
$url="http://120.24.47.142/phpems/index.php?content-phone";
$resultStr = "<xml>
<ToUserName><![CDATA[$reqFromUserName]]></ToUserName>
<FromUserName><![CDATA[$corpId]]></FromUserName>
<CreateTime>$sReqTimeStamp</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<ArticleCount>1</ArticleCount>
<Articles>
<item>
<Title><![CDATA[$title]]></Title>
<Description><![CDATA[$description]]></Description>
<PicUrl><![CDATA[$picurl]]></PicUrl>
<Url><![CDATA[$url]]></Url>
</item>
</Articles>
</xml>";
$sEncrytMsg="";//xml格式的密文
$errCode=$wxcpt->EncryptMsg($resultStr,$sReqTimeStamp,$sReqNonce,$sEncrytMsg);
if ($errCode == 0) {
//file_put_contents('smg_response.txt', $sEncryptMsg); //debug:查看smg
print($sEncryptMsg);
} else {
print($errCode . "\n\n");
}
}
/**
EncryptMsg($resultStr,$sReqTimeStamp,$sReqNonce,$sEncrytMsg){}
* 将公众平台回复用户的消息加密打包.
* <ol>
* <li>对要发送的消息进行AES-CBC加密</li>
* <li>生成安全签名</li>
* <li>将消息密文和安全签名打包成xml格式</li>
* </ol>
*
* @param $resultStr string 公众平台待回复用户的消息,xml格式的字符串
* @param $sReqTimeStamp string 时间戳,可以自己生成,也可以用URL参数的timestamp
* @param $sReqNonce string 随机串,可以自己生成,也可以用URL参数的nonce
* @param &$sEncrytMsg string 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串,
* 当return返回0时有效
*
*/
if($reqMsgType =="text"){
$contentStr="你好,你发的消息是".$reqContent;
$resultStr = "<xml>
<ToUserName><![CDATA[%S]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>";
$resultStr=sprintf($resultStr,$reqFromUserName,$corpId,$sReqTimeStamp,$contentStr);
}
$sEncryptMsg = ""; //xml格式的密文
$errCode = $wxcpt->EncryptMsg($resultStr, $sReqTimeStamp, $sReqNonce, $sEncryptMsg);
if ($errCode == 0) {
//file_put_contents('smg_response.txt', $sEncryptMsg); //debug:查看smg
print($sEncryptMsg);
} else {
print($errCode . "\n\n");
}
} else {
print($errCode . "\n\n");
}
?>
感谢博客:http://blog.youkuaiyun.com/k8080880/article/details/40342929