WXBizMsgCrypt.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <?php
  2. namespace WeWork\Crypt;
  3. /**
  4. * 1.第三方回复加密消息给公众平台;
  5. * 2.第三方收到公众平台发送的消息,验证消息的安全性,并对消息进行解密。
  6. */
  7. class WXBizMsgCrypt
  8. {
  9. /**
  10. * @var string
  11. */
  12. private $m_sToken;
  13. /**
  14. * @var string
  15. */
  16. private $m_sEncodingAesKey;
  17. /**
  18. * @var string
  19. */
  20. private $m_sCorpid;
  21. /**
  22. * 构造函数
  23. * @param string $token 公众平台上,开发者设置的token
  24. * @param string $encodingAesKey 公众平台上,开发者设置的EncodingAESKey
  25. * @param string $Corpid 公众平台的Corpid
  26. */
  27. public function __construct($token, $encodingAesKey, $Corpid)
  28. {
  29. $this->m_sToken = $token;
  30. $this->m_sEncodingAesKey = $encodingAesKey;
  31. $this->m_sCorpid = $Corpid;
  32. }
  33. /**
  34. * 验证URL
  35. *
  36. * @param string $sMsgSignature 签名串,对应URL参数的msg_signature
  37. * @param string $sTimeStamp 时间戳,对应URL参数的timestamp
  38. * @param string $sNonce 随机串,对应URL参数的nonce
  39. * @param string $sEchoStr 随机串,对应URL参数的echostr
  40. * @param string $sReplyEchoStr 解密之后的echostr,当return返回0时有效
  41. * @return int 成功0,失败返回对应的错误码
  42. */
  43. public function VerifyURL($sMsgSignature, $sTimeStamp, $sNonce, $sEchoStr, &$sReplyEchoStr)
  44. {
  45. if (strlen($this->m_sEncodingAesKey) != 43) {
  46. return ErrorCode::$IllegalAesKey;
  47. }
  48. $pc = new PrpCrypt($this->m_sEncodingAesKey);
  49. //verify msg_signature
  50. $sha1 = new SHA1;
  51. $array = $sha1->getSHA1($this->m_sToken, $sTimeStamp, $sNonce, $sEchoStr);
  52. $ret = $array[0];
  53. if ($ret != 0) {
  54. return $ret;
  55. }
  56. $signature = $array[1];
  57. if ($signature != $sMsgSignature) {
  58. return ErrorCode::$ValidateSignatureError;
  59. }
  60. $result = $pc->decrypt($sEchoStr, $this->m_sCorpid);
  61. if ($result[0] != 0) {
  62. return $result[0];
  63. }
  64. $sReplyEchoStr = $result[1];
  65. return ErrorCode::$OK;
  66. }
  67. /**
  68. * 将公众平台回复用户的消息加密打包.
  69. * <ol>
  70. * <li>对要发送的消息进行AES-CBC加密</li>
  71. * <li>生成安全签名</li>
  72. * <li>将消息密文和安全签名打包成xml格式</li>
  73. * </ol>
  74. *
  75. * @param string $sReplyMsg 公众平台待回复用户的消息,xml格式的字符串
  76. * @param string $sTimeStamp 时间戳,可以自己生成,也可以用URL参数的timestamp
  77. * @param string $sNonce 随机串,可以自己生成,也可以用URL参数的nonce
  78. * @param string &$sEncryptMsg 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串,
  79. * 当return返回0时有效
  80. *
  81. * @return int 成功0,失败返回对应的错误码
  82. */
  83. public function EncryptMsg($sReplyMsg, $sTimeStamp, $sNonce, &$sEncryptMsg)
  84. {
  85. $pc = new PrpCrypt($this->m_sEncodingAesKey);
  86. //加密
  87. $array = $pc->encrypt($sReplyMsg, $this->m_sCorpid);
  88. $ret = $array[0];
  89. if ($ret != 0) {
  90. return $ret;
  91. }
  92. if ($sTimeStamp == null) {
  93. $sTimeStamp = time();
  94. }
  95. $encrypt = $array[1];
  96. //生成安全签名
  97. $sha1 = new SHA1;
  98. $array = $sha1->getSHA1($this->m_sToken, $sTimeStamp, $sNonce, $encrypt);
  99. $ret = $array[0];
  100. if ($ret != 0) {
  101. return $ret;
  102. }
  103. $signature = $array[1];
  104. //生成发送的xml
  105. $xmlparse = new XMLParse;
  106. $sEncryptMsg = $xmlparse->generate($encrypt, $signature, $sTimeStamp, $sNonce);
  107. return ErrorCode::$OK;
  108. }
  109. /**
  110. * 检验消息的真实性,并且获取解密后的明文.
  111. * <ol>
  112. * <li>利用收到的密文生成安全签名,进行签名验证</li>
  113. * <li>若验证通过,则提取xml中的加密消息</li>
  114. * <li>对消息进行解密</li>
  115. * </ol>
  116. *
  117. * @param string $sMsgSignature 签名串,对应URL参数的msg_signature
  118. * @param string $sTimeStamp 时间戳 对应URL参数的timestamp
  119. * @param string $sNonce 随机串,对应URL参数的nonce
  120. * @param string $sPostData 密文,对应POST请求的数据
  121. * @param string &$sMsg 解密后的原文,当return返回0时有效
  122. *
  123. * @return int 成功0,失败返回对应的错误码
  124. */
  125. public function DecryptMsg($sMsgSignature, $sTimeStamp, $sNonce, $sPostData, &$sMsg)
  126. {
  127. if (strlen($this->m_sEncodingAesKey) != 43) {
  128. return ErrorCode::$IllegalAesKey;
  129. }
  130. $pc = new PrpCrypt($this->m_sEncodingAesKey);
  131. //提取密文
  132. $xmlparse = new XMLParse;
  133. $array = $xmlparse->extract($sPostData);
  134. $ret = $array[0];
  135. if ($ret != 0) {
  136. return $ret;
  137. }
  138. if ($sTimeStamp == null) {
  139. $sTimeStamp = time();
  140. }
  141. $encrypt = $array[1];
  142. //验证安全签名
  143. $sha1 = new SHA1;
  144. $array = $sha1->getSHA1($this->m_sToken, $sTimeStamp, $sNonce, $encrypt);
  145. $ret = $array[0];
  146. if ($ret != 0) {
  147. return $ret;
  148. }
  149. $signature = $array[1];
  150. if ($signature != $sMsgSignature) {
  151. return ErrorCode::$ValidateSignatureError;
  152. }
  153. $result = $pc->decrypt($encrypt, $this->m_sCorpid);
  154. if ($result[0] != 0) {
  155. return $result[0];
  156. }
  157. $sMsg = $result[1];
  158. return ErrorCode::$OK;
  159. }
  160. }