offiAccountConfig['app_id']) || empty($this->offiAccountConfig['secret'])) { $this->result('请配置公众号appid或secret'); } $this->app = new Application([ 'app_id' => $this->offiAccountConfig['app_id'], 'secret' => $this->offiAccountConfig['secret'], 'token' => $this->offiAccountConfig['server_token'], 'aes_key' => $this->offiAccountConfig['encoding_aes_key'], ]); $accessToken = $this->app->getAccessToken(); $this->accessToken = $accessToken->getToken(); // file_put_contents(dirname(__FILE__) . '/Token.txt',$this->accessToken); } /** * 微信开发文档 https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_event_pushes.html * @return ResponseInterface * @throws InvalidArgumentException * @throws BadRequestException * @throws RuntimeException * @throws \ReflectionException * @throws \Throwable * @author jsjxsz */ public function messageServe(): ResponseInterface { $server = $this->app->getServer(); // 自定义菜单click事件 // {"ToUserName":"gh_3fd79f90b5af","FromUserName":"oluKa548P2NdCeiEbvlAomQxLKfM","CreateTime":"1693377845","MsgType":"event","Event":"CLICK","EventKey":"fq99mlqge3"} $server->addEventListener('CLICK', function ($message) { Log::info('event-message-CLICK' . json_encode($message,JSON_UNESCAPED_UNICODE)); $eventKey = $message['EventKey']; return $this->getReplyContentByEvent('click', $eventKey); }); // 订阅事件 // {"ToUserName":"gh_3fd79f90b5af","FromUserName":"oluKa548P2NdCeiEbvlAomQxLKfM","CreateTime":"1693377844","MsgType":"event","Event":"subscribe","EventKey":""} $server->addEventListener('subscribe', function ($message) { // 发起 GET 请求 $url='https://api.weixin.qq.com/cgi-bin/user/info?access_token='.$this->accessToken.'&openid='.$message['FromUserName'].'&lang=zh_CN'; $options = [ 'http' => [ 'method' => 'GET', 'header' => 'Content-type: application/x-www-form-urlencoded\r\n', ], ]; $context = stream_context_create($options); $response = file_get_contents($url, false, $context); $response=json_decode($response, true); Db::name('oauth_log')->where('uuid', $response['unionid'])->update(['opid' => $response['openid'],'opid_status' => '1']); Log::info('event-message-subscribe' . json_encode($message,JSON_UNESCAPED_UNICODE)); return $this->getReplyContentByEvent('subscribe'); }); //解除绑定 $server->addEventListener('unsubscribe', function ($message) { Db::name('oauth_log')->where('opid', $message['FromUserName'])->update(['opid' => null,'opid_status' => null]); // Log::info('接收普通消息text-message' . json_encode($message,JSON_UNESCAPED_UNICODE)); // return $this->getReplyContentByMessage($message['Content']); }); // 接收普通消息 $server->addMessageListener('text', function ($message) { Log::info('接收普通消息text-message' . json_encode($message,JSON_UNESCAPED_UNICODE)); return $this->getReplyContentByMessage($message['Content']); }); return $server->serve(); } /** * 事件消息回复内容 * @param $event * @return array|string * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException * @author jsjxsz */ public function getReplyContentByEvent($event, $eventKey = ''): array|string { if ($event == 'subscribe') { // 订阅事件回复内容 $autoreply = Autoreply::where('type', 'follow')->where('status', 1)->find(); if ($autoreply['msg_type'] == 'text') { return htmlspecialchars_decode($autoreply['reply_content']); } elseif ($autoreply['msg_type'] == 'image') { $content = json_decode($autoreply['reply_content'], true); return [ 'MsgType' => 'image', 'Image' => [ 'MediaId' => $content['media_id'], ], ]; } elseif ($autoreply['msg_type'] == 'voice') { $content = json_decode($autoreply['reply_content'], true); return [ 'MsgType' => 'voice', 'Voice' => [ 'MediaId' => $content['media_id'], ], ]; } elseif ($autoreply['msg_type'] == 'video') { $content = json_decode($autoreply['reply_content'], true); return [ 'MsgType' => 'video', 'Video' => [ 'MediaId' => $content['media_id'], 'Title' => $content['name'], 'Description' => $content['description'], ], ]; } elseif ($autoreply['msg_type'] == 'news') { $content = json_decode($autoreply['reply_content'], true); return [ 'MsgType' => 'news', 'Articles' => [ 'item' => [ 'Title' => $content['title'], 'Description' => $content['digest'], 'PicUrl' => $content['show_cover_pic'], 'Url' => $content['url'], ] ], ]; } else { return $this->getDefaultReply(); } } else if ($event == 'click') { $content = Material::where('event_key', $eventKey)->value('content'); return htmlspecialchars_decode($content); } else { return $this->getDefaultReply(); } } // 普通消息获取回复内容 public function getReplyContentByMessage($content) { $autoreply = Autoreply::where('keyword', $content)->where('status', 1)->find(); if (!empty($autoreply)) { $msg_type = $autoreply['msg_type']; if ($msg_type == 'text') { return htmlspecialchars_decode($autoreply['reply_content']); } elseif ($msg_type == 'image') { $content = json_decode($autoreply['reply_content'], true); return [ 'MsgType' => 'image', 'Image' => [ 'MediaId' => $content['media_id'], ], ]; } elseif ($msg_type == 'voice') { $content = json_decode($autoreply['reply_content'], true); return [ 'MsgType' => 'voice', 'Voice' => [ 'MediaId' => $content['media_id'], ], ]; } elseif ($msg_type == 'video') { $content = json_decode($autoreply['reply_content'], true); return [ 'MsgType' => 'video', 'Video' => [ 'MediaId' => $content['media_id'], 'Title' => $content['name'], 'Description' => $content['description'], ], ]; } elseif ($msg_type == 'news') { $content = json_decode($autoreply['reply_content'], true); return [ 'MsgType' => 'news', 'Articles' => [ 'item' => [ 'Title' => $content['title'], 'Description' => $content['digest'], 'PicUrl' => $content['show_cover_pic'], 'Url' => $content['url'], ] ], ]; } else { return $this->getDefaultReply(); } } else { return $this->getDefaultReply(); } } /** * 默认回复 * @return mixed * @author jsjxsz */ public function getDefaultReply(): mixed { $content = Autoreply::where('type', 'default')->where('status', 1)->value('reply_content'); return htmlspecialchars_decode($content); } /** * @param array $params * @return bool * @author jsjxsz */ public function checkSignature(array $params): bool { $offiAccount = config('xmwechat')['offiAccount']; $server_token = $offiAccount['server_token']; $tmpArr = array($server_token, $params['timestamp'], $params['nonce']); sort($tmpArr, SORT_STRING); $tmpStr = implode($tmpArr); $tmpStr = sha1($tmpStr); if ($tmpStr == $params['signature']) { return true; } else { return false; } } }