600) { //发送时间大于当前时间10分钟 continue; } else { \Log::info('========现将模板消息设置成发送状态 "8" 用户不能操作(删除,编辑,停止) = ' . $wechatTemplateMsgs['id']); $wechatTemplateMsgs['status'] = '8'; $wechatTemplateMsgs->save(); $officialAccountArray = $wechatTemplateMsgs->toArray(); Redis::hset('send_wechat_msg:task_id:' . $wechatTemplateMsgs['id'], 'wechat_msg', json_encode($officialAccountArray)); $allStandByWechatTemplateMsgsArray[] = $wechatTemplateMsgs; } } for ($x=0; $x < count($allStandByWechatTemplateMsgsArray); $x++){ $wechatTemplateMsgs = $allStandByWechatTemplateMsgsArray[$x]; \Log::info($wechatTemplateMsgs); // $send_time = $wechatTemplateMsgs['send_time']; // if (strtotime($send_time) - time() > 600){ //发送时间大于当前时间10分钟 // continue; // } $wechatTemplateMsgs['redirect_url'] = self::redirect_url_add_param($wechatTemplateMsgs['redirect_url'],$wechatTemplateMsgs['id'],'template',false); \Log::info('template_redirect_url_convert:id:'.$wechatTemplateMsgs['id'].' redirect_url:'.$wechatTemplateMsgs['redirect_url']); $appid = $wechatTemplateMsgs['appid']; $template_id = $wechatTemplateMsgs['template_id']; $template_content = $wechatTemplateMsgs['template_content']; $origin_template_content = $template_content; $redirect_url = $wechatTemplateMsgs['redirect_url']; // 新版要自动添加域名 $redirect_url = self::checkAddDomain($wechatTemplateMsgs['distribution_channel_id'],$redirect_url); \Log::info('checkAddDomain_after:distribution_channel_id:'.$wechatTemplateMsgs['distribution_channel_id'].' redirect_url:'.$redirect_url); $task_id = $wechatTemplateMsgs['id']; $send_time = $wechatTemplateMsgs['send_time']; $is_full_send = isset($wechatTemplateMsgs['is_full_send'])?$wechatTemplateMsgs['is_full_send']:0; \Log::info('-----------------模板消息参数--------------appid = '.$appid.', channelid = '.$wechatTemplateMsgs['distribution_channel_id']); \Log::info('========发送的模板消息内容========== template_content'); \Log::info($template_content); //1,通过筛选得到条件符合的强关用户 $skip = 0; $next_openid = ''; $loop = 0; while ( $skip <= 2500000) { $loop++; \Log::info('-------------模板消息-----分页取强关用户,目前页数----------'.$skip.' is_full_send:'.$is_full_send.' task_id:'.$task_id.' loop:'.$loop); $users = array(); // 全服务号粉丝发,要记录next_openid if($is_full_send){ if($loop > 1 && empty($next_openid)){ \Log::info('send_template_appid:'.$appid.' break,skip:'.$skip); break; } $user_res = ForceSubscribeService::getFullOfficialAccountUsers($appid,$next_openid); $users = $user_res['openids'];// TODO格式化成一样的格式 $next_openid = $user_res['next_openid']; }else{ $users = ForceSubscribeService::forceUserCountByTemplatePrams($appid,$wechatTemplateMsgs['distribution_channel_id'],$wechatTemplateMsgs['subscribe_time'],$wechatTemplateMsgs['sex'],$wechatTemplateMsgs['balance'],$wechatTemplateMsgs['category_id'],$wechatTemplateMsgs['order_type'],$skip); } \Log::info('-----------------实际发送模板消息用户数量-------------'.count($users).' $next_openid:'.$next_openid); // \Log::info($users); $skip += count($users); // continue; // die('end2'); if(count($users)>0){ for ($i=0; $i < count($users); $i++) { // 占位符替换 $place_holder_params = array(); $place_holder_params['nickname'] = isset($users[$i]['nickname'])?$users[$i]['nickname']:''; \Log::info('openid:'.$users[$i]['openid'].' nickname:'.$place_holder_params['nickname']); $template_content = ForceSubscribeService::change_placeholder($origin_template_content,$place_holder_params); //2,循环用户发送模板消息 //发送到最后一条时,将 if ($i == count($users)-1) { $data = array(); $data['statusstr'] = (time()); $data['openid'] = $users[$i]['openid']; $data['appid'] = $appid; $data['template_id'] = $template_id; //4,通过RebitMQ发送模板消息 // $data['template_content'] = $templateSendContents; $data['template_content'] =str_replace(".DATA","",$template_content); $data['type'] = 'last_task';// last_task,one_task $data['url'] = $redirect_url; $data['task_id'] = $task_id; $data['send_time'] = $send_time; $send_data=array( 'send_time'=>$send_time, 'data' => $data ); $now_time = strtotime($send_time)-time(); $delay = $now_time < 0 ? 0:$now_time; \Log::info('------------------发送最后一条模板消息----------task_id = '.$task_id.', 时间差 = '.$now_time.' openid:'.$data['openid']); $job = (new SendTemplate($send_data))->onConnection('rabbitmq')->delay($delay)->onQueue('send_template_list'); dispatch($job); }else{ $data = array(); $data['statusstr'] = (time()); $data['openid'] = $users[$i]['openid']; $data['appid'] = $appid; $data['template_id'] = $template_id; \Log::info('========================[[[[send template message]]]]===================='); \Log::info(str_replace(".DATA","",$template_content)); $data['template_content'] =str_replace(".DATA","",$template_content); $data['type'] = 'one_task';// last_task,one_task $data['url'] = $redirect_url; $data['task_id'] = $task_id; $data['send_time'] = $send_time; $send_data=array( 'send_time'=>$send_time, 'data' => $data ); $now_time = strtotime($send_time)-time(); $delay = $now_time < 0 ? 0:$now_time; \Log::info('========================发送模板消息 不是最后一条模板=================task_id = '.$task_id.'. openid = '.$data['openid'].', 时间差 = '.$delay); $job = (new SendTemplate($send_data))->onConnection('rabbitmq')->delay($delay)->onQueue('send_template_list'); dispatch($job); } } }else{ \Log::info('========================发送模板消息_没找到用户===================='.$task_id); break; } } //更新模板消息的用户数量并更新redis \Log::info('========================更新模板消息并存redis====================task_id = '.$task_id); $wechatTemplateMsgs['user_num'] = $skip; // 若没有用户,则直接更新为已发送 if($skip == 0){ \Log::info('has_no_template_users:'.$wechatTemplateMsgs['id']); $wechatTemplateMsgs['status'] = '3'; } $wechatTemplateMsgs->save(); $officialAccountArray = $wechatTemplateMsgs->toArray(); Redis::hset('send_wechat_msg:task_id:'.$wechatTemplateMsgs['id'], 'wechat_msg', json_encode($officialAccountArray)); } }else{ \Log::info('========================!!!数据库中没有要发送的模板消息!!!===================='); } } catch (\Exception $e) { \Log::info('========================循环用户发送模板消息时报错===================='); \Log::info($e->getMessage()); } } /** * @return int|void toCheckAndSendCustomMsg * 查找并发送客服消息 */ static function toCheckAndSendCustomMsg() { // try { //查找模板消息并发送 $statusPram = '1'; $allStandByWechatCustomMsgs = CustomSendMsgs::customSendMsgsByStatusStandBy($statusPram); // \Log::info($allStandByWechatCustomMsgs); $allStandByWechatCustomMsgsArray = []; if ($allStandByWechatCustomMsgs) { //先单独更新数据库 把要发送的状态改为8 以免发送期间超时,导致重复发送 for ($x = 0; $x < count($allStandByWechatCustomMsgs); $x++) { $customSendMsgsPrams = $allStandByWechatCustomMsgs[$x]; $send_time = $customSendMsgsPrams['send_time']; if (strtotime($send_time) - time() > 60*15) { //发送时间大于当前时间25分钟 //\Log::info('=====客服消息超时被过滤=====ID为'.$customSendMsgsPrams['id']); continue; } else { \Log::info('========现将客服消息设置成发送状态 "8" 用户不能操作(删除,编辑,停止) = ' . $customSendMsgsPrams['id']); $customSendMsgsPrams['status'] = '8'; $customSendMsgsPrams->save(); $officialAccountArray = $customSendMsgsPrams->toArray(); Redis::hset('send_wechat_msg:task_id:' . $customSendMsgsPrams['task_id'], 'wechat_msg', json_encode($officialAccountArray)); $allStandByWechatCustomMsgsArray[] = $customSendMsgsPrams; } } for ($x = 0; $x < count($allStandByWechatCustomMsgsArray); $x++) { $customSendMsgsPrams = $allStandByWechatCustomMsgsArray[$x]; $is_has_user_tag = 0; try { if (strstr($customSendMsgsPrams['content'], '{user}')) $is_has_user_tag = 1; }catch (\Exception $e) { \Log::error($e); } if($customSendMsgsPrams['custom_type'] == 'image'){ // 转化图文的链接url $customSendMsgsPrams['content'] = self::convert_custom_content($customSendMsgsPrams['content'],$customSendMsgsPrams['id'],$customSendMsgsPrams['distribution_channel_id'],$customSendMsgsPrams['trusteeship']); }else{ // 转化文字的链接url $customSendMsgsPrams['content'] = self::convert_custom_text_content($customSendMsgsPrams['content'],$customSendMsgsPrams['id'],$customSendMsgsPrams['distribution_channel_id'],$customSendMsgsPrams['trusteeship']); } $appids = $customSendMsgsPrams['appid']; $is_full_send = 0; \Log::info('------------------客服消息强关用户,appids:'.$appids.' is_full_send:'.$is_full_send); $appidArray = explode(',', $appids); $usercountnum = 0; for ($j=0; $j < count($appidArray); $j++) { $skip = 0; $next_openid = ''; $loop = 0; while ( $skip <= 2500000) { $loop++; \Log::info('------------------分页取强关用户,目前页数----------'.$skip.' loop:'.$loop.' next_openid:'.$next_openid); $users = array(); // 全服务号粉丝发,要记录next_openid if($is_full_send){ // 防止异常 if($loop > 1 && empty($next_openid)){ \Log::info('send_template_appid:'.$appidArray[$j].' break,skip:'.$skip); break; } try{ $user_res = ForceSubscribeService::getFullOfficialAccountUsers($appidArray[$j],$next_openid); $users = $user_res['openids'];// TODO格式化成一样的格式 $next_openid = $user_res['next_openid']; } catch (\Exception $e) { \Log::info($e); } }else{ //5,获取所选条件下筛选出的用户 $sign_time = 'z'; $users = ForceSubscribeService::forceUserCountByCustomPrams($appidArray[$j],$customSendMsgsPrams['distribution_channel_id'],$customSendMsgsPrams['subscribe_time'],$customSendMsgsPrams['sex'],$customSendMsgsPrams['balance'],$customSendMsgsPrams['category_id'],$customSendMsgsPrams['order_type'],$sign_time,$skip,$customSendMsgsPrams['subscribe_time_attach']); } \Log::info('--------------------users_num:'.count($users)); // continue; if (count($users)>0) { $usercountnum += count($users); try { if ($is_has_user_tag) { $current_openids = []; foreach ($users as $_u) { $current_openids[] = $_u['openid']; } $user_properties = ForceSubscribeService::getForceUsersNickname($current_openids); } }catch (\Exception $e){ \Log::error($e);} for ($i=0; $i < count($users); $i++) { // 7,循环用户发送客服消息 $data = array(); if ($i == count($users)-1) { $data['type'] = 'last_task'; }else{ $data['type'] = 'one_task'; } $content = $customSendMsgsPrams['content']; //判断是否有标志位 if($is_has_user_tag) { try{ $current_nickname = isset($user_properties[$users[$i]['openid']]) ? $user_properties[$users[$i]['openid']] :'书友'; $content = str_replace('{user}',$current_nickname,$customSendMsgsPrams['content']); }catch (\Exception $e){ \Log::error($e);} } if($customSendMsgsPrams['custom_type'] == 'image'){ $data['news_content'] = $content; }else{ $data['content'] = json_decode($content); } $data['openid'] = $users[$i]['openid']; $data['appid'] = $appidArray[$j]; $data['type'] = 'last_task'; $data['task_id'] = $customSendMsgsPrams['task_id']; $data['send_time'] = $customSendMsgsPrams['send_time']; $send_data=array( 'send_time'=>$customSendMsgsPrams['send_time'], 'data' => $data ); $now_time = strtotime($customSendMsgsPrams['send_time'])-time(); $delay = $now_time < 0 ? 0:$now_time; if($customSendMsgsPrams['custom_type'] == 'image') { $job = (new SendNews($send_data))->onConnection('rabbitmq')->delay($delay)->onQueue('send_news_list'); }else{ $job = (new SendTexts($send_data))->onConnection('rabbitmq')->delay($delay)->onQueue('send_texts_list'); } dispatch($job); } }else{ \Log::info('------------------发送客服消息没有查找到强关用户----------'.$customSendMsgsPrams['task_id']); break; } $skip += count($users); } } $customSendMsgsPrams['user_num'] = $usercountnum; // 若没有用户,则直接更新为已发送 if($usercountnum == 0){ \Log::info('has_no_custom_users:'.$customSendMsgsPrams['task_id']); $customSendMsgsPrams['status'] = '3'; } \Log::info('------------------更新发送用户----------'.$customSendMsgsPrams['task_id'].' usercountnum:'.$usercountnum); $customSendMsgsPrams->save(); } }else{ \Log::info('========================!!!数据库中没有要发送的客服消息!!!===================='); } } catch (\Exception $e) { \Log::info('===================================发送客服消息报错'); \Log::info($e->getMessage()); } } /** * 转换客服消息内容 * 1条--新版 * @param unknown_type $content * @return string */ public static function convert_custom_content($content,$mark_str,$distribution_channel_id,$trusteeship=0){ \Log::info('convert_custom_content_start:'); $_contents = json_decode($content); // \Log::info('convert_custom_content_before:'); // \Log::info($_contents); $new_contents = null; // 智能托管,加上各自渠道域名,统计精确到图文每条 if($trusteeship){ $origin_mark_str = $mark_str; foreach($_contents as $key=>$_content){ $url = env('PROTOCOL').'://site'.encodeDistributionChannelId($distribution_channel_id).'.'.env('CUSTOM_HOST').'.com'.$_content[2]->url; $mark_str = $origin_mark_str.'_'.($key+1).'&source=wechatmsg';// source能让用户继续阅读 \Log::info('convert_custom_content_url:'.$url.' mark_str:'.$mark_str); $_contents[$key][2]->url = self::redirect_url_add_param($url,$mark_str,'custom',true); $new_contents[] = $_contents[$key]; break; } } // 非托管 else{ $origin_mark_str = $mark_str; $send_type = 'custom'; // 智能推送不加前缀 if(strpos($origin_mark_str,'smart_push_') > -1){ $send_type = 'smart_push'; $origin_mark_str = str_replace('smart_push_','',$origin_mark_str); } \Log::info('origin_mark_str:'.$origin_mark_str); foreach($_contents as $key=>$_content){ // 新版要自动添加域名 $_content[2]->url = self::checkAddDomain($distribution_channel_id,$_content[2]->url); $mark_str = $origin_mark_str.'&source=wechatmsg';// source能让用户继续阅读 $_contents[$key][2]->url = self::redirect_url_add_param($_content[2]->url,$mark_str,$send_type,false); $new_contents[] = $_contents[$key]; break; } } // \Log::info('convert_custom_content_after:'); // \Log::info($new_contents); $_convert_contents = json_encode($new_contents); return $_convert_contents; } /** * 转换客服消息内容--文字版 * @param unknown_type $content * @return string */ public static function convert_custom_text_content($content,$mark_str,$distribution_channel_id,$trusteeship=0){ \Log::info('convert_custom_content_start:'); $new_content = $content = json_decode($content); $origin_mark_str = $mark_str; $send_type = 'custom'; \Log::info('origin_mark_str:'.$origin_mark_str); \Log::info('convert_custom_text_content_before:'); \Log::info($content); myLog('htx_test')->notice($content); preg_match_all("/]+s*)href(\s*)=(\s*)([\"|']?)([^\"'>\s]+)([\"|']?)/ies",$content,$matchs); $matchs_all = isset($matchs[5])?$matchs[5]:[]; \Log::info('$matchs_all');\Log::info($matchs_all); myLog('htx_test')->notice($matchs_all); if(!empty($matchs_all)){ foreach($matchs_all as $match){ $new_url = $url = $match; myLog('htx_test')->notice($url); $mark_str = $origin_mark_str.'&source=wechatmsg';// source能让用户继续阅读 $new_url = self::redirect_url_add_param($url,$mark_str,$send_type,false); // 小链接可能多次被替换,所以一定要引号结尾 $new_content = str_replace($url.'"',$new_url.'"',$new_content); $new_content = str_replace($url."'",$new_url."'",$new_content); } } \Log::info('convert_custom_text_content_after:'); \Log::info($new_content); $_convert_contents = json_encode($new_content); return $_convert_contents; } /** * 转换客服消息内容 * 多条--老版 * @param unknown_type $content * @return string */ public static function convert_custom_content_multy($content,$mark_str,$distribution_channel_id,$trusteeship=0){ \Log::info('convert_custom_content_start:'); $_contents = json_decode($content); // 智能托管,加上各自渠道域名,统计精确到图文每条 if($trusteeship){ $origin_mark_str = $mark_str; foreach($_contents as $key=>$_content){ $url = env('PROTOCOL').'://site'.encodeDistributionChannelId($distribution_channel_id).'.'.env('CUSTOM_HOST').'.com'.$_content[2]->url; $mark_str = $origin_mark_str.'_'.($key+1).'&source=wechatmsg';// source能让用户继续阅读 \Log::info('convert_custom_content_url:'.$url.' mark_str:'.$mark_str); $_contents[$key][2]->url = self::redirect_url_add_param($url,$mark_str,'custom',true); } } // 非托管 else{ $origin_mark_str = $mark_str; $send_type = 'custom'; // 智能推送不加前缀 if(strpos($origin_mark_str,'smart_push_') > -1){ $send_type = 'smart_push'; $origin_mark_str = str_replace('smart_push_','',$origin_mark_str); } \Log::info('origin_mark_str:'.$origin_mark_str); foreach($_contents as $key=>$_content){ $mark_str = $origin_mark_str.'&source=wechatmsg';// source能让用户继续阅读 $_contents[$key][2]->url = self::redirect_url_add_param($_content[2]->url,$mark_str,$send_type,false); } } $_convert_contents = json_encode($_contents); //\Log::info('convert_custom_content_after:'); //\Log::info($_convert_contents); return $_convert_contents; } /** * 跳转地址加参 * @param unknown_type $redirect_url * @param unknown_type $type * @return string */ public static function redirect_url_add_param($redirect_url,$mark_str,$type='template',$trusteeship=false){ $pre_str = ''; if($type == 'template'){ $pre_str = 'template_'; }elseif($type == 'custom'){ $pre_str = 'custom_'; } // 模板客服消息,单独加参 $inner_order_id = ''; if(!$trusteeship){ $inner_order_id = '&inner_order_id='.$pre_str.$mark_str; } $send_time_str = ''; if(strpos($redirect_url,'newUser') > -1){ \Log::info('newUserActivity_send_time:'.$inner_order_id); $send_time_str = '&send_time='.time(); } // 跳转链接加参 if(strpos($redirect_url,'?') > -1){ $redirect_url .= '&fromtype='.$pre_str.$mark_str.$inner_order_id.$send_time_str; }else{ $redirect_url .= '?fromtype='.$pre_str.$mark_str.$inner_order_id.$send_time_str; } return $redirect_url; } // 新版要自动添加域名 public static function checkAddDomain($distribution_channel_id,$redirect_url){ // 非托管,如果url没有域名,则加上 if(strpos($redirect_url, 'http') !== false){ \Log::info('not_need_add_domain:'.$distribution_channel_id.' url:'.$redirect_url); }else{ \Log::info('need_add_domain_before:'.$distribution_channel_id.' url:'.$redirect_url); $redirect_url = env('PROTOCOL').'://site'.encodeDistributionChannelId($distribution_channel_id).'.'.env('CUSTOM_HOST').'.com'.$redirect_url; \Log::info('need_add_domain_after:'.$distribution_channel_id.' url:'.$redirect_url); } return $redirect_url; } }