setName('ChangeMenuWx') ->addArgument('channel_id', Argument::OPTIONAL, '需要更新的渠道OR配号代理商ID,不传值则处理所有') ->addArgument('nums', Argument::OPTIONAL, 'Limit条数限制') ->setDescription('更新微信菜单'); } /** * 执行命令: * php think ChangeMenuWx # 更新所有微信菜单 * php think ChangeMenuWx 48 1 # 仅更新渠道商ID为48的微信菜单 * php think ChangeMenuWx 48 100 # 更新渠道商ID 大于或等于48的微信菜单,更新100条 * * @param Input $input * @param Output $output * @return int|null|void */ protected function execute(Input $input, Output $output) { //cli模式下无法获取到当前的项目模块,手动指定一下 Request::instance()->module('admin'); $channel_map = null; $channel_map['wx_menu'] = ['neq', '']; $output->writeln("开始执行刷新菜单:" . date('Y-m-d H:i:s', time())); $channel_id = $input->getArgument('channel_id'); if(empty($channel_id) || !is_numeric($channel_id)){ $channel_id = ''; } if($channel_id){ $channel_map['admin_id'] = ['>=',$channel_id]; } $nums = is_numeric($input->getArgument('nums')) ? $input->getArgument('nums') : 0; $output->writeln("参数channel_id:".$channel_id); $output->writeln("参数nums:".$nums); //0.获取默认配置的菜单 $default_menu_obj = model('config')->where(['name'=>'wx_menu'])->field('value')->find(); $default_menu_arr = json_decode($default_menu_obj->value, true); if($nums){ $adminConfig = model('AdminConfig')->where($channel_map)->field('admin_id,appid,refresh_token,wx_menu')->limit($nums)->select(); } else{ $adminConfig = model('AdminConfig')->where($channel_map)->field('admin_id,appid,refresh_token,wx_menu')->select(); } //1.查找到所有配置了微信菜单的渠道商OR配号代理商 if(!$adminConfig){ $output->error('ChangeMenuWx->Error:没有找到可用数据'); return; } $output->info('ChangeMenuWx->SQL:'.model('AdminConfig')->getLastSql()); Log::info('ChangeMenuWx->SQL:'.model('AdminConfig')->getLastSql()); try{ foreach ($adminConfig as $channel) { //2.检查是否是默认配置的微信菜单,只有是默认的微信菜单才做修改,渠道商自己维护过的菜单不做修改 //$diff_arr = array_diff_key($default_menu_arr, $channel['wx_menu']); $diff_value = $this->isConsistent($default_menu_arr, $channel['wx_menu']); if($diff_value){ // 如果当前渠道配置的默认菜单一致,则修改 //3.将新的菜单结构推送给微信 $nMenu = $this->rePackageMenu($channel['wx_menu']); $admin = model('AdminConfig')->getAdminInfoAll($channel['admin_id']); if(empty($admin['refresh_token'])){ Log::info('ChangeMenuWx->WeChat->Menu: '.date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} refresh_token Empty!!"); continue; } $wechat = new WeChatObject($admin); $officialAccount = $wechat->getOfficialAccount(); try { $ret = $officialAccount->menu->create($nMenu); } catch (\Exception $exception) { Log::info('ChangeMenuWx->WeChat->Menu:' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} WeChat Update Fail"); Log::info('Because:' . $exception->getMessage()); } Log::info('ChangeMenuWx->WeChat->Menu: ret: '.print_r(json_encode($ret), true)); if ($ret['errcode'] == 0) { $output->info('ChangeMenuWx->WeChat->Menu: ' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} WeChat Update Success"); Log::info('ChangeMenuWx->WeChat->Menu: ' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} WeChat Update Success"); //4.维护admin_config表中的wx_menu字段 $update = model('AdminConfig')->update(['wx_menu' => $nMenu], ["admin_id" => $channel['admin_id']]); if ($update) { $output->info('ChangeMenuWx->WeChat->Menu: ' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} Mysql Update Success"); Log::info('ChangeMenuWx->WeChat->Menu: ' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} Mysql Update Success"); } else { $output->info('ChangeMenuWx->WeChat->Menu: ' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} Mysql Update Fail"); Log::error('ChangeMenuWx->WeChat->Menu: ' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} Mysql Update Fail"); } } else { $output->info('ChangeMenuWx->WeChat->Menu: ' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} WeChat Update Fail Error:" . $ret['errmsg']); Log::error('ChangeMenuWx->WeChat->Menu: ' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} WeChat Update Fail Error:" . $ret['errmsg']); } // 暂停50毫秒 usleep(50000); } } }catch (\Exception $exception){ $output->writeln('ChangeMenuWx->WeChat->Menu: '.date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} WeChat Update Fail Error:" . $exception->getMessage()); Log::error('ChangeMenuWx->WeChat->Menu: '.date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} WeChat Update Fail Error:" . $exception->getMessage()); } $output->writeln("刷新菜单完成:" . date('Y-m-d H:i:s', time())); } /** * 重新组装微信菜单数据 * @param array $oldMenu * @return Json */ public function rePackageMenu(array $oldMenu) { $newMenu = []; $tmpMenu = []; foreach ($oldMenu as $item) { if(!isset($item['sub_button'])){ array_push($tmpMenu, $item); }else{ foreach ($item['sub_button'] as $subitem){ array_push($tmpMenu, $subitem); } } } foreach ($tmpMenu as $menu){ if($menu['name'] == '继续阅读' || $menu['name'] == '阅读记录'){ $newMenu[0] = $menu; }elseif($menu['name'] == '签到送币' || $menu['name'] == '每日签到'){ $newMenu[2] = $menu; }else{ $newMenu[1]['name'] = '进入书城'; $newMenu[1]['sub_button'][] = $menu; } } ksort($newMenu); return $newMenu; } /** * 判断菜单元素是否一致 * @param array $defalt_menu_arr 默认配置的菜单 * @param array $b_arr 渠道商实际菜单 * @return bool */ public function isConsistent(array $defalt_menu_arr, array $b_arr) { $defalt_name_arr = array_column($defalt_menu_arr, 'name'); $b_name_arr = array_column($b_arr, 'name'); $diff = array_diff_assoc($defalt_name_arr, $b_name_arr); if(!empty($diff)){ return false; }else{ foreach ($defalt_menu_arr as $key => $default_item) { if(isset($default_item['sub_button'])){ $default_sub_btn_arr = array_column($default_item['sub_button'], 'name'); $b_sub_btn_arr = isset($b_arr[$key]['sub_button']) ? array_column($b_arr[$key]['sub_button'], 'name') : array(); $diff_sub_btn = array_diff_assoc($default_sub_btn_arr, $b_sub_btn_arr); if($diff_sub_btn || count($default_sub_btn_arr) != count($b_sub_btn_arr)){ return false; } }else{ if(isset($b_arr[$key]['sub_button'])){ return false; } } } } return true; } }