1. <?php
  2. /*
  3. +----------------------------------------------------------------------
  4. + Title : 微信关注事件与取消订阅事件
  5. + Author : 小黄牛
  6. + Version : 无
  7. + Initial-Time : 2016-10-24 17:43:00
  8. + Last-time : 2016-10-25 16:41:00 + 小黄牛
  9. + Desc : 好好学习微信,这是5K迈向8K的关键技能
  10. +----------------------------------------------------------------------
  11. */
  12. # 这里是你在微信后台 -> 基本配置 -> 服务器配置中填写的Token令牌值
  13. define("TOKEN", "weixin");
  14. # 实例化示例类
  15. $wechatObj = new wechatCallbackapiTest();
  16. # 由于数字认证已经通过,valid()与checkSignature()方法删除掉,没有作用了
  17. # 只需要留下responseMsg方法,作为回调方法
  18. $wechatObj->responseMsg();
  19. class wechatCallbackapiTest {
  20. // 第一次绑定服务器地址的时候,用不到这个方法
  21. public function responseMsg() {
  22. # 获得数据包的信息
  23. $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
  24. # 如果数据包内的信息不为空
  25. if (!empty($postStr)){
  26. # XML文件的解析依赖libxml库,libxml_disable_entity_loader函数,是为了安全性,防止入侵者通过协议注入XML向服务器发起攻击
  27. libxml_disable_entity_loader(true);
  28. # 把XML编译成一个Class
  29. $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
  30. # FromUserName : 发送方帐号(一个OpenID)
  31. $fromUsername = $postObj->FromUserName;
  32. # toUsername : 开发者微信号
  33. $toUsername = $postObj->ToUserName;
  34. # keyword : 发送过来的内容
  35. $keyword = trim($postObj->Content);
  36. # rx_type : 请求类型
  37. $rx_type = trim($postObj->MsgType);
  38. # rx_event : 操作的事件
  39. $rx_event = $postObj->Event;
  40. # 服务器时间戳
  41. $time = time();
  42. # 这里的XML格式不能改变,是微信规定的格式,里面的参数使用[%s]占位符占用,到时候填充完成,再发送回给微信
  43. $textTpl = "<xml>
  44. <ToUserName><![CDATA[%s]]></ToUserName>
  45. <FromUserName><![CDATA[%s]]></FromUserName>
  46. <CreateTime>%s</CreateTime>
  47. <MsgType><![CDATA[%s]]></MsgType>
  48. <Content><![CDATA[%s]]></Content>
  49. <FuncFlag>0</FuncFlag>
  50. </xml>";
  51. # 事件类型
  52. if($rx_type == 'event'){
  53. switch ($rx_event){
  54. # 关注事件
  55. case 'subscribe':
  56. $contentStr = '感谢您关注【JunPHP】'."n".'更多内容,敬请期待...';
  57. # 返回类型
  58. $msgType = 'text';
  59. $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType,$contentStr);
  60. # 填充完成之后,输出回给微信
  61. echo $resultStr;
  62. break;
  63. # 取消关注
  64. case 'unsubscribe':
  65. # 取消关注将无法发送消息给对方,这个事件一般只能进行一些数据删除处理
  66. $resultStr = '';
  67. break;
  68. }
  69. }
  70. # 调用日志记录-方便出错则查看
  71. $this->Error_Log(array(
  72. 'OpenID' => $fromUsername,
  73. '开发者ID' => $toUsername,
  74. '发送内容' => $keyword,
  75. '请求类型' => $rx_type,
  76. '操作事件' => $rx_event,
  77. 'XML' => $resultStr
  78. ),false);
  79. }else {
  80. echo "";
  81. exit;
  82. }
  83. }
  84. /**
  85. * @Title : 记录错误信息与查看部分信息
  86. * @Author : 小黄牛
  87. * @param array : $Arr_Title 一个一维数组自定义内容
  88. * @param bool : $Arr_Error 是否插入系统错误信息
  89. * @param string : $File 日志名
  90. * @return : 无
  91. */
  92. private function Error_Log($Arr_Title,$Arr_Error=false,$File='Error_log.log'){
  93. # 不是数组中断程序
  94. if (!is_array($Arr_Title)) {return false;}
  95. # 定义一个空的变量,用于存放日志TXT实体
  96. $Error_TXT = "自定义信息如下:rn";
  97. # 解析Arr_Title 自定义日志内容
  98. foreach ($Arr_Title as $key=>$val){
  99. $Error_TXT .= $key.':'.$val."rn";
  100. }
  101. # 判断系统错误显示是否开启
  102. if ($Arr_Error === true) {
  103. # 获取刚发生的错误信息,并返回数组,无错返回null
  104. $Arr_Error = error_get_last();
  105. # 不为空则执行错误解析
  106. if (isset($Arr_Error)) {
  107. $Error_TXT .= "系统错误信息如下:rn";
  108. # 解析$Arr_Errore 系统错误信息
  109. foreach ($Arr_Title as $key=>$val){
  110. $Error_TXT .= $key.':'.$val."rn";
  111. }
  112. }
  113. }
  114. # 最后再写入两个换行符,以便追加查看
  115. $Error_TXT .= "rnrn";
  116. # 最后写入日志
  117. error_log($Error_TXT,3,$File);
  118. }
  119. }