From 06e734ec443c48938e928bed9f6704921c4c5c5d Mon Sep 17 00:00:00 2001 From: lion <120344285@qq.com> Date: Thu, 30 Jul 2026 11:53:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E4=BA=8C=E7=BB=B4=E7=A0=81?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Admin/CourseController.php | 79 +++++++++++++------ 1 file changed, 56 insertions(+), 23 deletions(-) diff --git a/app/Http/Controllers/Admin/CourseController.php b/app/Http/Controllers/Admin/CourseController.php index 9eec881..ecd3082 100755 --- a/app/Http/Controllers/Admin/CourseController.php +++ b/app/Http/Controllers/Admin/CourseController.php @@ -439,49 +439,82 @@ class CourseController extends BaseController $generate = !empty($all['generate']); $path = config('filesystems.disks.public.root') . '/course_qrcode/' . $courseId . '.png'; $url = config('filesystems.disks.public.url') . '/course_qrcode/' . $courseId . '.png'; + $debugFile = storage_path('logs/qrcode_debug.log'); + $debug = function ($msg) use ($debugFile, $courseId) { + @file_put_contents( + $debugFile, + date('Y-m-d H:i:s') . " [{$courseId}] {$msg}\n", + FILE_APPEND + ); + }; + $debug('hit generate=' . ($generate ? '1' : '0') . ' sapi=' . PHP_SAPI); - // 已有文件直接返回,避免走微信/旧 OPcache 方法签名问题 + // 已有文件直接返回 clearstatcache(true, $path); if (is_file($path)) { + $debug('return existing file'); return $this->success($url); } if (!$generate) { + $debug('no file and generate=0'); return $this->success(''); } try { - $courseModel = new Course(); - // 兼容 FPM OPcache 未刷新时旧方法只有 1 个参数(PHP8 多传参会直接 500) - $ref = new \ReflectionMethod($courseModel, 'getCourseQrcode'); - if ($ref->getNumberOfParameters() >= 2) { - $result = $courseModel->getCourseQrcode($courseId, true); - } else { - $result = $courseModel->getCourseQrcode($courseId); + // 生成逻辑内联在控制器,避免模型 OPcache/签名不一致 + $appId = (string) config('app.applet_appid'); + $secret = (string) config('app.applet_secret'); + if ($appId === '' || $secret === '') { + $debug('missing appid/secret'); + return $this->fail([ResponseCode::ERROR_BUSINESS, '二维码生成失败:未配置小程序 APPID/SECRET']); } - clearstatcache(true, $path); - if (empty($result) && is_file($path)) { - $result = $url; + + $debug('request wechat app_code'); + $app = Factory::miniProgram([ + 'app_id' => $appId, + 'secret' => $secret, + ]); + $tmp = $app->app_code->get('packages/course/detail?id=' . $courseId, [ + 'env_version' => 'release', + ]); + $content = $tmp instanceof \EasyWeChat\Kernel\Http\StreamResponse + ? $tmp->getBodyContents() + : (string) $tmp; + $debug('wechat bytes=' . strlen($content)); + + if ($content === '' || strpos(ltrim($content), '{') === 0) { + $debug('invalid wechat body=' . substr($content, 0, 200)); + return $this->fail([ResponseCode::ERROR_BUSINESS, '二维码生成失败:微信接口返回异常']); } - if (empty($result)) { - return $this->fail([ResponseCode::ERROR_BUSINESS, '二维码生成失败,请检查微信配置或缓存后重试']); + + $dir = dirname($path); + if (!is_dir($dir)) { + mkdir($dir, 0755, true); } - return $this->success($result); + if (file_put_contents($path, $content) === false) { + $debug('write file failed'); + return $this->fail([ResponseCode::ERROR_BUSINESS, '二维码生成失败:写入文件失败']); + } + @chmod($path, 0644); + $debug('saved ok'); + return $this->success($url); } catch (\Throwable $e) { - \Log::error('courses/qrcode failed', [ - 'id' => $courseId, - 'generate' => $generate, - 'message' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - ]); - // 生成过程异常时,若磁盘已有文件仍返回成功 + $safeMsg = preg_replace('/[^\x09\x0A\x0D\x20-\x7E\x{4e00}-\x{9fff}]/u', '?', $e->getMessage()); + $debug('exception: ' . $safeMsg); + try { + \Log::error('courses/qrcode failed', [ + 'id' => $courseId, + 'message' => $safeMsg, + ]); + } catch (\Throwable $ignored) { + } clearstatcache(true, $path); if (is_file($path)) { return $this->success($url); } return $this->fail([ ResponseCode::ERROR_BUSINESS, - '二维码生成失败: ' . $e->getMessage(), + '二维码生成失败: ' . ($safeMsg ?: '未知错误'), ]); } }