CheckWechatForbidden.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. <?php
  2. /*
  3. * 检测公众号是否被封
  4. */
  5. namespace app\admin\command;
  6. use app\common\library\Redis;
  7. use app\common\model\Admin;
  8. use app\common\library\WeChatObject;
  9. use EasyWeChat\Factory;
  10. use Symfony\Component\Cache\Simple\RedisCache;
  11. use think\Config;
  12. use think\console\Command;
  13. use think\console\input\Option;
  14. use think\console\Input;
  15. use think\console\Output;
  16. use app\common\model\AdminConfig;
  17. use app\common\model\Config as dbconfig;
  18. use think\Log;
  19. use think\Request;
  20. class CheckWechatForbidden extends Command
  21. {
  22. protected $message = '';
  23. protected function configure()
  24. {
  25. $this->setName('CheckWechatForbidden')
  26. ->addOption("delay","d",Option::VALUE_REQUIRED)
  27. ->setDescription('Here is the remark ');
  28. }
  29. //获取公众号
  30. protected function execute(Input $input, Output $output)
  31. {
  32. Request::instance()->module('admin'); //cli模式下无法获取到当前的项目模块,手动指定一下
  33. $output->writeln("检测微信服务号状态---开始");
  34. Log::info("检测微信服务号状态---开始");
  35. $delay = $input->getOption('delay');
  36. $admin_config = new AdminConfig();
  37. $adminlist = $admin_config
  38. ->join('admin', 'admin.id=admin_config.admin_id','LEFT')
  39. ->join('admin_extend','admin_extend.admin_id=admin_config.admin_id','LEFT')
  40. ->join('auth_group_access ac','ac.uid=admin_config.admin_id','LEFT')
  41. ->field('admin_config.*,admin.id,admin.username,admin.nickname,ac.group_id,admin_extend.create_by')
  42. ->where('admin.status','=','normal')
  43. ->where('admin_config.is_fouce','=','1')
  44. ->select();
  45. $redis = Redis::instance();
  46. $count = 0; //服务号总数
  47. $jmp = 0; //服务号跳过检测数量(半小时内有交互)
  48. $err = 0; //服务号历史异常数量
  49. $new = 0; //服务号新增异常数量
  50. $re = 0; //服务号恢复数量
  51. $configModel = $configdb = new dbconfig();
  52. $siteconfig = $configModel->getConfigSiteArr();
  53. $theme = $siteconfig['theme'];
  54. switch ($theme) {
  55. case 'qy':
  56. $themeName = '袋鼠';
  57. break;
  58. case 'sf':
  59. $themeName = '沙发';
  60. break;
  61. case 'ms':
  62. $themeName = '美书';
  63. break;
  64. case 'px':
  65. $themeName = '点看';
  66. break;
  67. case 'xd':
  68. $themeName = '熊大';
  69. break;
  70. case 'yg':
  71. $themeName = '阳光';
  72. break;
  73. case '':
  74. $themeName = '西瓜';
  75. break;
  76. default:
  77. $themeName = $theme;
  78. }
  79. //$output->writeln("当前平台是:".$siteconfig['theme']);
  80. foreach ($adminlist as &$value) {
  81. if(empty($value['wx_menu']) || empty($value['appid'])){
  82. Log::info("admin_id=".$value['admin_id']."的用户未授权公众平台,跳过");
  83. continue;
  84. }
  85. $adminInfo = $admin_config->getAdminInfoAll($value['admin_id']);
  86. if(empty($adminInfo['refresh_token'])){ //判断refresh_tokan是否为空,为空跳过
  87. Log::info("admin_id=".$value['admin_id']."的用户refresh_token为空,跳过");
  88. continue;
  89. }
  90. $count++;
  91. $value['refresh_token'] = $adminInfo['refresh_token'];
  92. $output->writeln("检测微信服务号状态---渠道ID:{$value['id']} 账号:{$value['username']} 昵称:{$value['nickname']} APPID:{$value['appid']}");
  93. Log::info("检测微信服务号状态---渠道ID:{$value['id']} 账号:{$value['username']} 昵称:{$value['nickname']} APPID:{$value['appid']}");
  94. if (!empty($value['appid']) && !empty($value['refresh_token'])) {
  95. $output->writeln("检测微信服务号状态---服务号授权状态:ok");
  96. Log::info("检测微信服务号状态---服务号授权状态:ok");
  97. $operate_time = $redis->hget('WEOP',$value['admin_id']);
  98. if (!$operate_time || (time() - $operate_time) > 1800) { //无交互时间 或者 交互时间大约半小时
  99. if ($operate_time) {
  100. $redis->hdel('WEOP', $value['admin_id']);
  101. }
  102. $key2 = 'F:' . $value['admin_id'];
  103. $menulist = $this->emptyWechatMenu($value);
  104. if ($menulist) {
  105. if ($menulist === 1) {
  106. $errMsg = ' 错误日志:' . $this->message;
  107. } else {
  108. $errMsg = '';
  109. }
  110. $output->writeln("检测微信服务号状态---服务号菜单状态:异常" . $errMsg);
  111. Log::info("检测微信服务号状态---服务号菜单状态:异常" . $errMsg);
  112. if ($redis->exists($key2)) {
  113. $err++;
  114. $output->writeln("检测微信服务号状态---报警通知:30天内已发送,跳过");
  115. Log::info("检测微信服务号状态---报警通知:30天内已发送,跳过");
  116. continue;
  117. }
  118. $new++;
  119. $output->writeln("检测微信服务号状态---发送微信报警通知");
  120. Log::info("检测微信服务号状态---发送微信报警通知");
  121. $khr = "\n";
  122. if($value['group_id'] == 4){
  123. $khr.="开户渠道商ID:".$value['create_by'];
  124. $admin = new Admin();
  125. $adminInfos = $admin->join('admin_extend ae','admin.id=ae.admin_id')->field('admin.*,ae.create_by')->where('admin.id','=',$value['create_by'])->find();
  126. $khr.="\n开户渠道商账号:".$adminInfos->username;
  127. $khr.="\n开户渠道商昵称:".$adminInfos->nickname;
  128. $madminInfos = $admin->where('id','=',$adminInfos->create_by)->find();
  129. $khr.="\n开户管理员ID:".$adminInfos->create_by;
  130. $khr.="\n开户管理员账号:".$madminInfos->username;
  131. $khr.="\n开户管理员昵称:".$madminInfos->nickname;
  132. }elseif($value['group_id'] == 3){
  133. $khr.="开户管理员ID:".$value['create_by'];
  134. $admin = new Admin();
  135. $adminInfos = $admin->where('id','=',$value['create_by'])->find();
  136. $khr.="\n开户管理员账号:".$adminInfos->username;
  137. $khr.="\n开户管理员昵称:".$adminInfos->nickname;
  138. }
  139. $msg = "平台:{$themeName} 发现异常!" . date('Y-m-d H:i:s') . "\n公众号:" . ($value['json']['authorizer_info']['nick_name']??'') . "\n原始ID:" . ($value['json']['authorizer_info']['user_name']??'') ."\nAppid:".$value['appid']. "\n后台ID:" . $value['id'] . "\n账号:" . $value['username'] . "\n昵称:" . $value['nickname'].$khr;
  140. if ($menulist === 1) {
  141. if (stripos($this->message, 'Resolving timed')) {
  142. $msg .= "\n错误说明: API超时,商务请忽略";
  143. }
  144. if (stripos($this->message, 'user limited')) {
  145. $msg .= "\n错误说明: 公众号被封或菜单功能被封,请商务通知渠道";
  146. }
  147. if (stripos($this->message, 'component is not authorized')) {
  148. $msg .= "\n错误说明: 公众号授权三方权限有问题,请商务通知渠道";
  149. }
  150. $msg .= "\n错误日志:" . $this->message;
  151. }
  152. $this->SendWorkChatMessage($msg);
  153. $redis->setex($key2, 86400*30, 1);
  154. } else {
  155. $output->writeln("检测微信服务号状态---服务号菜单状态:ok");
  156. Log::info("检测微信服务号状态---服务号菜单状态:ok");
  157. if ($redis->exists($key2)) {
  158. $re++;
  159. $redis->del($key2);
  160. }
  161. }
  162. if(empty($delay)){
  163. $delay = 1;
  164. }
  165. sleep($delay); //检测一个延时1秒
  166. } else { // 存在redis hash name,且交互时间小于半小时
  167. $jmp++;
  168. $output->writeln("检测微信服务号状态---半小时内存在交互,跳过检测");
  169. Log::info("检测微信服务号状态---半小时内存在交互,跳过检测");
  170. }
  171. }else{
  172. $output->writeln("检测微信服务号状态---服务号授权状态:异常");
  173. Log::info("检测微信服务号状态---服务号授权状态:异常");
  174. }
  175. }
  176. $msg = "平台:{$themeName} ".date('Y-m-d H:i:s') . " 新增异常:{$new} 历史异常:{$err} 恢复正常:{$re} 跳过检测:{$jmp} 服务号总数:{$count}";
  177. $this->SendWorkChatMessage($msg);
  178. $output->writeln("检测微信服务号状态---完毕!日志->" . $msg);
  179. Log::info("检测微信服务号状态---完毕!日志->" . $msg);
  180. }
  181. //获取菜单
  182. public function emptyWechatMenu($config)
  183. {
  184. if (empty($config)) {
  185. return false;
  186. }
  187. try {
  188. $admin_config = new AdminConfig();
  189. $info = $admin_config->getAdminInfoAll($config['admin_id']);
  190. $wechat = new WeChatObject($info);
  191. $officialAccount = $wechat->getOfficialAccount($config['appid'], $config['refresh_token']);
  192. $menu = $officialAccount->menu->list();//Log::write(1,'1111');
  193. if (empty($menu)) {
  194. return true;
  195. }
  196. } catch (\Exception $exception) {
  197. Log::error('检测微信服务号状态---微信检查脚本触发异常!config:' . json_encode($config));
  198. $this->message = $exception->getMessage();
  199. return 1;
  200. }
  201. return false;
  202. }
  203. //发企业微信
  204. public function SendWorkChatMessage($content)
  205. {
  206. if (empty($content)) {
  207. return false;
  208. }
  209. $wechat = Config::get('wechat');
  210. $wechat['http']['base_uri'] = $wechat['work']['base_uri'];
  211. $wechat['http']['timeout'] = 20;
  212. $wechat['corp_id'] = $wechat['work']['corp_id'];
  213. $wechat['secret'] = $wechat['work']['secret'];
  214. $app = Factory::work($wechat);
  215. $app['cache'] = new RedisCache(Redis::instanceCache());
  216. $res = $app->message
  217. ->message($content)
  218. ->ofAgent($wechat['work']['agent_id'])
  219. ->toParty($wechat['work']['party_id'])
  220. ->send();
  221. return $res;
  222. }
  223. }