ChangeMenuWx.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Elton
  5. * Date: 2019/5/21
  6. * Time: 11:19
  7. */
  8. namespace app\admin\command;
  9. use app\common\library\WeChatObject;
  10. use app\common\utility\WeChatMenu;
  11. use think\Config;
  12. use think\console\Command;
  13. use think\console\Input;
  14. use think\console\input\Argument;
  15. use think\console\input\Option;
  16. use think\console\Output;
  17. use think\Log;
  18. use think\Request;
  19. use think\response\Json;
  20. class ChangeMenuWx extends Command
  21. {
  22. /**
  23. * 配置指令
  24. */
  25. protected function configure()
  26. {
  27. $this->setName('ChangeMenuWx')
  28. ->addArgument('channel_id', Argument::OPTIONAL, '需要更新的渠道OR配号代理商ID,不传值则处理所有')
  29. ->addArgument('nums', Argument::OPTIONAL, 'Limit条数限制')
  30. ->setDescription('更新微信菜单');
  31. }
  32. /**
  33. * 执行命令:
  34. * php think ChangeMenuWx # 更新所有微信菜单
  35. * php think ChangeMenuWx 48 1 # 仅更新渠道商ID为48的微信菜单
  36. * php think ChangeMenuWx 48 100 # 更新渠道商ID 大于或等于48的微信菜单,更新100条
  37. *
  38. * @param Input $input
  39. * @param Output $output
  40. * @return int|null|void
  41. */
  42. protected function execute(Input $input, Output $output)
  43. {
  44. //cli模式下无法获取到当前的项目模块,手动指定一下
  45. Request::instance()->module('admin');
  46. $channel_map = null;
  47. $channel_map['wx_menu'] = ['neq', ''];
  48. $output->writeln("开始执行刷新菜单:" . date('Y-m-d H:i:s', time()));
  49. $channel_id = $input->getArgument('channel_id');
  50. if(empty($channel_id) || !is_numeric($channel_id)){
  51. $channel_id = '';
  52. }
  53. if($channel_id){
  54. $channel_map['admin_id'] = ['>=',$channel_id];
  55. }
  56. $nums = is_numeric($input->getArgument('nums')) ? $input->getArgument('nums') : 0;
  57. $output->writeln("参数channel_id:".$channel_id);
  58. $output->writeln("参数nums:".$nums);
  59. //0.获取默认配置的菜单
  60. $default_menu_obj = model('config')->where(['name'=>'wx_menu'])->field('value')->find();
  61. $default_menu_arr = json_decode($default_menu_obj->value, true);
  62. if($nums){
  63. $adminConfig = model('AdminConfig')->where($channel_map)->field('admin_id,appid,refresh_token,wx_menu')->limit($nums)->select();
  64. } else{
  65. $adminConfig = model('AdminConfig')->where($channel_map)->field('admin_id,appid,refresh_token,wx_menu')->select();
  66. }
  67. //1.查找到所有配置了微信菜单的渠道商OR配号代理商
  68. if(!$adminConfig){
  69. $output->error('ChangeMenuWx->Error:没有找到可用数据');
  70. return;
  71. }
  72. $output->info('ChangeMenuWx->SQL:'.model('AdminConfig')->getLastSql());
  73. Log::info('ChangeMenuWx->SQL:'.model('AdminConfig')->getLastSql());
  74. try{
  75. foreach ($adminConfig as $channel)
  76. {
  77. //2.检查是否是默认配置的微信菜单,只有是默认的微信菜单才做修改,渠道商自己维护过的菜单不做修改
  78. //$diff_arr = array_diff_key($default_menu_arr, $channel['wx_menu']);
  79. $diff_value = $this->isConsistent($default_menu_arr, $channel['wx_menu']);
  80. if($diff_value){
  81. // 如果当前渠道配置的默认菜单一致,则修改
  82. //3.将新的菜单结构推送给微信
  83. $nMenu = $this->rePackageMenu($channel['wx_menu']);
  84. $admin = model('AdminConfig')->getAdminInfoAll($channel['admin_id']);
  85. if(empty($admin['refresh_token'])){
  86. Log::info('ChangeMenuWx->WeChat->Menu: '.date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} refresh_token Empty!!");
  87. continue;
  88. }
  89. $wechat = new WeChatObject($admin);
  90. $officialAccount = $wechat->getOfficialAccount();
  91. try {
  92. $ret = $officialAccount->menu->create($nMenu);
  93. } catch (\Exception $exception) {
  94. Log::info('ChangeMenuWx->WeChat->Menu:' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} WeChat Update Fail");
  95. Log::info('Because:' . $exception->getMessage());
  96. }
  97. Log::info('ChangeMenuWx->WeChat->Menu: ret: '.print_r(json_encode($ret), true));
  98. if ($ret['errcode'] == 0) {
  99. $output->info('ChangeMenuWx->WeChat->Menu: ' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} WeChat Update Success");
  100. Log::info('ChangeMenuWx->WeChat->Menu: ' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} WeChat Update Success");
  101. //4.维护admin_config表中的wx_menu字段
  102. $update = model('AdminConfig')->update(['wx_menu' => $nMenu], ["admin_id" => $channel['admin_id']]);
  103. if ($update) {
  104. $output->info('ChangeMenuWx->WeChat->Menu: ' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} Mysql Update Success");
  105. Log::info('ChangeMenuWx->WeChat->Menu: ' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} Mysql Update Success");
  106. } else {
  107. $output->info('ChangeMenuWx->WeChat->Menu: ' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} Mysql Update Fail");
  108. Log::error('ChangeMenuWx->WeChat->Menu: ' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} Mysql Update Fail");
  109. }
  110. } else {
  111. $output->info('ChangeMenuWx->WeChat->Menu: ' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} WeChat Update Fail Error:" . $ret['errmsg']);
  112. Log::error('ChangeMenuWx->WeChat->Menu: ' . date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} WeChat Update Fail Error:" . $ret['errmsg']);
  113. }
  114. // 暂停50毫秒
  115. usleep(50000);
  116. }
  117. }
  118. }catch (\Exception $exception){
  119. $output->writeln('ChangeMenuWx->WeChat->Menu: '.date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} WeChat Update Fail Error:" . $exception->getMessage());
  120. Log::error('ChangeMenuWx->WeChat->Menu: '.date('Y-m-d H:i:s') . " admin_id:{$channel['admin_id']} WeChat Update Fail Error:" . $exception->getMessage());
  121. }
  122. $output->writeln("刷新菜单完成:" . date('Y-m-d H:i:s', time()));
  123. }
  124. /**
  125. * 重新组装微信菜单数据
  126. * @param array $oldMenu
  127. * @return Json
  128. */
  129. public function rePackageMenu(array $oldMenu)
  130. {
  131. $newMenu = [];
  132. $tmpMenu = [];
  133. foreach ($oldMenu as $item)
  134. {
  135. if(!isset($item['sub_button'])){
  136. array_push($tmpMenu, $item);
  137. }else{
  138. foreach ($item['sub_button'] as $subitem){
  139. array_push($tmpMenu, $subitem);
  140. }
  141. }
  142. }
  143. foreach ($tmpMenu as $menu){
  144. if($menu['name'] == '继续阅读' || $menu['name'] == '阅读记录'){
  145. $newMenu[0] = $menu;
  146. }elseif($menu['name'] == '签到送币' || $menu['name'] == '每日签到'){
  147. $newMenu[2] = $menu;
  148. }else{
  149. $newMenu[1]['name'] = '进入书城';
  150. $newMenu[1]['sub_button'][] = $menu;
  151. }
  152. }
  153. ksort($newMenu);
  154. return $newMenu;
  155. }
  156. /**
  157. * 判断菜单元素是否一致
  158. * @param array $defalt_menu_arr 默认配置的菜单
  159. * @param array $b_arr 渠道商实际菜单
  160. * @return bool
  161. */
  162. public function isConsistent(array $defalt_menu_arr, array $b_arr)
  163. {
  164. $defalt_name_arr = array_column($defalt_menu_arr, 'name');
  165. $b_name_arr = array_column($b_arr, 'name');
  166. $diff = array_diff_assoc($defalt_name_arr, $b_name_arr);
  167. if(!empty($diff)){
  168. return false;
  169. }else{
  170. foreach ($defalt_menu_arr as $key => $default_item)
  171. {
  172. if(isset($default_item['sub_button'])){
  173. $default_sub_btn_arr = array_column($default_item['sub_button'], 'name');
  174. $b_sub_btn_arr = isset($b_arr[$key]['sub_button']) ? array_column($b_arr[$key]['sub_button'], 'name') : array();
  175. $diff_sub_btn = array_diff_assoc($default_sub_btn_arr, $b_sub_btn_arr);
  176. if($diff_sub_btn || count($default_sub_btn_arr) != count($b_sub_btn_arr)){
  177. return false;
  178. }
  179. }else{
  180. if(isset($b_arr[$key]['sub_button'])){
  181. return false;
  182. }
  183. }
  184. }
  185. }
  186. return true;
  187. }
  188. }