SystemConfig::getValue('wechat', 'enabled', false), 'app_id' => SystemConfig::getValue('wechat', 'app_id', ''), 'app_secret' => SystemConfig::getValue('wechat', 'app_secret', ''), 'token' => SystemConfig::getValue('wechat', 'token', ''), 'encoding_aes_key' => SystemConfig::getValue('wechat', 'encoding_aes_key', ''), ]; }); } /** * 小程序登录 */ public function miniProgramLogin(string $code): array { $config = $this->getConfig(); if (!$config['enabled']) { return ['success' => false, 'message' => '微信服务未启用']; } try { $response = \Illuminate\Support\Facades\Http::get('https://api.weixin.qq.com/sns/jscode2session', [ 'appid' => $config['app_id'], 'secret' => $config['app_secret'], 'js_code' => $code, 'grant_type' => 'authorization_code', ]); $data = $response->json(); if (isset($data['errcode']) && $data['errcode'] !== 0) { return ['success' => false, 'message' => $data['errmsg'] ?? '微信登录失败']; } return [ 'success' => true, 'data' => [ 'openid' => $data['openid'], 'unionid' => $data['unionid'] ?? null, 'session_key' => $data['session_key'] ?? null, ], ]; } catch (\Exception $e) { \Log::error('微信小程序登录失败: ' . $e->getMessage()); return ['success' => false, 'message' => '微信登录失败']; } } /** * 公众号登录 - 获取授权URL */ public function getOauthUrl(string $redirectUri, string $state = ''): string { $config = $this->getConfig(); $state = $state ?: md5(uniqid()); $params = [ 'appid' => $config['app_id'], 'redirect_uri' => $redirectUri, 'response_type' => 'code', 'scope' => 'snsapi_userinfo', 'state' => $state, ]; return 'https://open.weixin.qq.com/connect/oauth2/authorize?' . http_build_query($params) . '#wechat_redirect'; } /** * 公众号登录 - 通过code获取用户信息 */ public function officialAccountCallback(string $code): array { $config = $this->getConfig(); if (!$config['enabled']) { return ['success' => false, 'message' => '微信服务未启用']; } try { // 获取 access_token $tokenResponse = \Illuminate\Support\Facades\Http::get('https://api.weixin.qq.com/sns/oauth2/access_token', [ 'appid' => $config['app_id'], 'secret' => $config['app_secret'], 'code' => $code, 'grant_type' => 'authorization_code', ]); $tokenData = $tokenResponse->json(); if (isset($tokenData['errcode']) && $tokenData['errcode'] !== 0) { return ['success' => false, 'message' => $tokenData['errmsg'] ?? '获取access_token失败']; } // 获取用户信息 $userResponse = \Illuminate\Support\Facades\Http::get('https://api.weixin.qq.com/sns/userinfo', [ 'access_token' => $tokenData['access_token'], 'openid' => $tokenData['openid'], 'lang' => 'zh_CN', ]); $userData = $userResponse->json(); return [ 'success' => true, 'data' => [ 'openid' => $userData['openid'], 'unionid' => $userData['unionid'] ?? null, 'nickname' => $userData['nickname'] ?? null, 'headimgurl' => $userData['headimgurl'] ?? null, 'sex' => $userData['sex'] ?? null, 'country' => $userData['country'] ?? null, 'province' => $userData['province'] ?? null, 'city' => $userData['city'] ?? null, ], ]; } catch (\Exception $e) { \Log::error('微信公众号登录失败: ' . $e->getMessage()); return ['success' => false, 'message' => '微信登录失败']; } } /** * 获取用户信息(通过openid) */ public function getUserInfo(string $openid): ?array { $config = $this->getConfig(); try { $response = \Illuminate\Support\Facades\Http::get('https://api.weixin.qq.com/cgi-bin/user/info', [ 'access_token' => $this->getComponentAccessToken(), 'openid' => $openid, 'lang' => 'zh_CN', ]); return $response->json(); } catch (\Exception $e) { \Log::error('获取微信用户信息失败: ' . $e->getMessage()); return null; } } /** * 获取第三方平台 component_access_token */ private function getComponentAccessToken(): ?string { $cacheKey = 'wechat_component_access_token'; $token = Cache::get($cacheKey); if ($token) { return $token; } $config = $this->getConfig(); // 如果是第三方平台模式,需要使用 component_appid 和 component_appsecret // 这里简化处理,假设使用的是独立应用 return null; } /** * 发送模板消息 */ public function sendTemplateMessage(string $openid, string $templateId, array $data, string $url = ''): bool { $config = $this->getConfig(); if (!$config['enabled']) { return false; } try { $accessToken = $this->getComponentAccessToken(); if (!$accessToken) { // 使用小程序的 access_token $accessToken = $this->getMiniProgramAccessToken(); } $response = \Illuminate\Support\Facades\Http::post("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={$accessToken}", [ 'touser' => $openid, 'template_id' => $templateId, 'url' => $url, 'data' => $data, ]); $result = $response->json(); return ($result['errcode'] ?? 1) === 0; } catch (\Exception $e) { \Log::error('发送微信模板消息失败: ' . $e->getMessage()); return false; } } /** * 获取小程序 access_token */ private function getMiniProgramAccessToken(): ?string { $cacheKey = 'wechat_mini_program_access_token'; $token = Cache::get($cacheKey); if ($token) { return $token; } $config = $this->getConfig(); try { $response = \Illuminate\Support\Facades\Http::get('https://api.weixin.qq.com/cgi-bin/token', [ 'grant_type' => 'client_credential', 'appid' => $config['app_id'], 'secret' => $config['app_secret'], ]); $data = $response->json(); if (isset($data['access_token'])) { Cache::put($cacheKey, $data['access_token'], now()->addSeconds($data['expires_in'] - 200)); return $data['access_token']; } } catch (\Exception $e) { \Log::error('获取小程序access_token失败: ' . $e->getMessage()); } return null; } }