checkSignature(); } elseif (Request::method() == 'POST') { // 接收消息并回复 $response = $this->receiveMessage(); // 直接输出回复的XML字符串 echo $response; exit; } } // 验证签名 protected function checkSignature() { $signature = Request::get('signature'); $timestamp = Request::get('timestamp'); $nonce = Request::get('nonce'); $echostr = Request::get('echostr'); $token = AdminConfig::where('config_name', 'wechat_token')->value('config_value'); $tmpArr = array($token, $timestamp, $nonce); sort($tmpArr, SORT_STRING); $tmpStr = implode($tmpArr); $tmpStr = sha1($tmpStr); if ($tmpStr == $signature) { echo $echostr; exit; } } // 接收消息 protected function receiveMessage() { $postStr = file_get_contents("php://input"); if (empty($postStr)) { return ''; } libxml_disable_entity_loader(true); $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); Log::write($postObj); // 检查消息类型 $msgType = strtolower((string) $postObj->MsgType); if ($msgType == 'text') { // 提取消息内容 $fromUsername = (string) $postObj->FromUserName; // 微信用户openid $toUsername = (string) $postObj->ToUserName; // 公众号id $keyword = trim((string) $postObj->Content); // 构造自动回复的文本消息 $time = time(); $textTpl = " %s 0 "; $responseContent = "消息标题"; $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $responseContent); // 假设已经确定要发送小程序卡片消息 $this->sendMiniProgramCard((string) $postObj->FromUserName); return $resultStr; } // 如果需要处理其他类型的消息,可以在这里添加相应的逻辑 // 如果不是文本消息,可以返回一个空字符串或错误消息 return ''; } // 发送小程序卡片消息的方法 private function sendMiniProgramCard($openid) { $accessToken = $this->getGZHAccessToken(); print_r($accessToken); if (!$accessToken) { // 处理获取access_token失败的情况 return; } $postData = json_encode([ 'touser' => $openid, // 接收者(用户)的openid 'msgtype' => 'miniprogrampage', 'miniprogrampage' => [ 'title' => '小程序标题', 'appid' => '小程序appid', 'pagepath' => '小程序路径', 'thumb_media_id' => '你的thumb_media_id' ] ], JSON_UNESCAPED_UNICODE); $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={$accessToken}"; $result = json_decode(file_get_contents($url, false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-type: application/json\r\n", 'content' => $postData, 'timeout' => 60 // 超时时间(单位:s) ] ])), true); // 处理返回结果 if ($result['errcode'] == 0) { // 发送成功 } else { // 发送失败 } } // 获取公众号Access token public function getGZHAccessToken() { // 从数据库获取配置 $appid = AdminConfig::where('config_name', 'wechat_appid')->value('config_value'); $secret = AdminConfig::where('config_name', 'wechat_appsecret')->value('config_value'); if (empty($appid) || empty($secret)) { throw new \Exception('微信配置信息未设置'); } // 构建请求URL $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$secret}"; try { // 使用 GuzzleHttp 发送请求,禁用SSL验证 $client = new Client([ 'verify' => false ]); $response = $client->get($url); $data = json_decode($response->getBody(), true); if (!isset($data['access_token'])) { throw new \Exception("获取access_token失败: {$data['errmsg']}", $data['errcode'] ?? -1); } return $data['access_token']; } catch (\Exception $e) { Log::error('获取access_token失败:' . $e->getMessage()); throw $e; } } /** * 获取微信登录二维码 * @return \think\response\Json */ public function getLoginTicket() { try { // 获取access_token $access_token = $this->getGZHAccessToken(); // 构建请求URL - 使用正确的接口生成临时二维码 $url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={$access_token}"; // 准备请求数据 - 生成临时二维码,有效期5分钟 $postData = json_encode([ 'expire_seconds' => 300, // 5分钟有效期 'action_name' => 'QR_STR_SCENE', 'action_info' => [ 'scene' => [ 'scene_str' => md5(uniqid() . time()) // 生成唯一场景值 ] ] ]); // 发送请求获取ticket $client = new Client(['verify' => false]); $response = $client->post($url, [ 'body' => $postData, 'headers' => [ 'Content-Type' => 'application/json' ] ]); $result = json_decode($response->getBody(), true); if (isset($result['errcode']) && $result['errcode'] != 0) { return json(['code' => 1, 'msg' => '获取二维码失败:' . $result['errmsg']]); } // 使用ticket获取二维码图片URL $ticket = urlencode($result['ticket']); $qrcodeUrl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket={$ticket}"; // 将场景值保存到缓存中,用于后续验证 Cache::set('wx_login_scene_' . $result['ticket'], [ 'scene_str' => $postData['action_info']['scene']['scene_str'], 'create_time' => time(), 'expire_time' => time() + 300 ], 300); return json([ 'code' => 0, 'msg' => '获取二维码成功', 'data' => [ 'ticket' => $result['ticket'], 'expire_seconds' => $result['expire_seconds'], 'url' => $qrcodeUrl, 'scene_str' => $postData['action_info']['scene']['scene_str'] ] ]); } catch (\Exception $e) { Log::error('获取微信登录二维码失败:' . $e->getMessage()); return json(['code' => 1, 'msg' => '获取二维码失败:' . $e->getMessage()]); } } }