企业号和订阅号服务号最大区别,千万注意消息加密和解密!!!
做企业号开发时,先明白自己想用做什么,消息交互还是其他的,最好先看看企业号开发文档,不然骚时候会来来回回查开发文档。
点击菜单时回复消息时,流程为:
先调用官方给的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.csdn.net/k8080880/article/details/40342929