* [ * 'gzhId' => $gzhId, // wechat_authorization_infos.id * 'messageId' => $item->id, // wechat_kf_messages.id * 'traceInfo' => $traceContext->getTraceInfo() // traceInfo * ] * */ private $info; private $isTest; /** * @var TraceContext */ private $traceContext; /** * Create a new job instance. */ public function __construct($info) { $this->info = $info; $this->isTest = $info['isTest'] ?? false; } /** * Execute the job. */ public function handle(): void { $this->traceContext = TraceContext::newFromParent($this->info['traceInfo']); myLog('KFMessageSend')->info('公众号开始发送客服消息', [ 'info' => $this->info, 'traceInfo' => $this->traceContext->getTraceInfo(), ]); $gzh = $this->getGZH(); if(!$gzh) return; $message = $this->getMessage(); if(!$message) return; $messageContent = collect(\json_decode($message->message_content, true)); $messageStr = $messageContent->pluck('text')->join("\n"); $officialAccount = $this->getOfficialAccount($gzh); if(false === $officialAccount) return; if($this->isTest) { $openid = $this->info['openid'] ?? ''; if(!$openid) { myLog('KFMessageSend')->error('测试回传没有openid', [ 'info' => $this->info ]); } GZHSendKFMessageService::sendText($officialAccount, $openid, $messageStr, $this->traceContext); } else { $next_openid = ''; $loop = 1; while (true) { if($loop++ > 10000) { break; } if(1 == $message->u_type) { $info = $this->getUserOpenids($officialAccount, $next_openid); foreach ($info['openid'] as $opid){ GZHSendKFMessageService::sendText($officialAccount, $opid, $messageStr, $this->traceContext); } $next_openid = $info['next_openid']; if(!$next_openid) { break; } } elseif (2 == $message->u_type) { // todo, 从人群包中获取. } } } } private function getMessage() { $message = DB::table('wechat_kf_messages') ->where('id', $this->info['messageId']) ->first(); if(!$message) { myLog('KFMessageSend')->error('消息不存在', [ 'info' => $this->info, 'traceInfo' => $this->traceContext->getTraceInfo(), ]); return false; } if(1 != $message->message_type) { myLog('KFMessageSend')->error('不支持的消息类型', [ 'info' => $this->info, 'traceInfo' => $this->traceContext->getTraceInfo(), ]); return false; } return $message; } /** * * @param $officialAccount Application */ private function getUserOpenids($officialAccount, $next_openid) { $result = $officialAccount->getClient() ->get('cgi-bin/user/get', [ 'query' => [ 'next_openid' => $next_openid, ] ])->toArray(); if(0 != ($result['errcode'] ?? 0)) { return false; } return $result; } /** * 获取公众号调用对象 * @param $gzh * @return \EasyWeChat\OfficialAccount\Application * @throws \EasyWeChat\Kernel\Exceptions\BadResponseException * @throws \EasyWeChat\Kernel\Exceptions\HttpException * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \Psr\SimpleCache\InvalidArgumentException * @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface */ private function getOfficialAccount($gzh) { try{ return WechatPlatform::buildApplication($gzh) ->getOfficialAccountWithRefreshToken($gzh->authorizer_appid, $gzh->authorizer_refresh_token); } catch (\Throwable $exception) { myLog('KFMessageSend')->error('获取公众号调用对象失败', [ 'exceptionMessage' => $exception->getMessage(), 'traceInfo' => $this->traceContext->getTraceInfo() ]); return false; } } private function getGZH() { $gzh = DB::table('wechat_authorization_infos as a') ->join('wechat_open_platform_infos as b', 'a.component_appid', 'b.app_id') ->where([ ['a.id', '=', $this->info['gzhId']], ['a.is_enabled', '=', 1], ['b.is_enabled', '=', 1] ])->select('a.authorizer_appid', 'a.authorizer_refresh_token', 'b.app_id', 'b.secret', 'b.token', 'b.aes_key') ->first(); if(!$gzh) { myLog('KFMessageSend')->error('公众号不可用', [ 'traceInfo' => $this->traceContext->getTraceInfo(), ]); } return $gzh; } }