$qrcodeUrl, 'diagnosis_id' => $diagnosisId, 'patient_id' => $patientId ]; } catch (\Exception $e) { self::setError($e->getMessage()); return false; } } /** * @notes 获取小程序配置 * @return array|null */ private static function getMiniProgramConfig(): ?array { try { // 从配置表获取小程序配置 $appId = \app\common\service\ConfigService::get('mnp_setting', 'app_id', ''); $appSecret = \app\common\service\ConfigService::get('mnp_setting', 'app_secret', ''); if (empty($appId) || empty($appSecret)) { return null; } return [ 'app_id' => $appId, 'app_secret' => $appSecret ]; } catch (\Exception $e) { return null; } } /** * @notes 生成微信小程序码 * @param array $config * @param string $page * @param string $scene * @return string|false */ private static function generateWxQrcode(array $config, string $page, string $scene) { try { // 记录请求参数 \think\facade\Log::info('开始生成小程序码', [ 'page' => $page, 'scene' => $scene, 'app_id' => $config['app_id'] ]); // 获取access_token $accessToken = self::getWxAccessToken($config['app_id'], $config['app_secret']); if (!$accessToken) { throw new \Exception('获取access_token失败: ' . self::getError()); } // 调用微信接口生成小程序码 $url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={$accessToken}"; $data = [ 'scene' => $scene, 'page' => $page, 'check_path' => false, 'env_version' => 'release', 'width' => 280 ]; \think\facade\Log::info('调用微信API生成小程序码', ['data' => $data]); $response = self::httpPost($url, json_encode($data)); // 检查是否返回错误(JSON格式) $result = json_decode($response, true); if (is_array($result) && isset($result['errcode']) && $result['errcode'] != 0) { $errorMsg = "生成小程序码失败: errcode={$result['errcode']}, errmsg=" . ($result['errmsg'] ?? '未知错误'); \think\facade\Log::error($errorMsg); // 如果是AccessToken错误,清除缓存 if ($result['errcode'] == 40001 || $result['errcode'] == 42001) { $cacheKey = 'wx_access_token_' . $config['app_id']; cache($cacheKey, null); \think\facade\Log::info('已清除无效的AccessToken缓存'); } throw new \Exception($errorMsg); } // 如果不是JSON错误,说明返回的是图片二进制数据 // 保存图片 $filename = 'qrcode_' . $config['app_id'] . '_' . md5($scene) . '_' . time() . '.png'; $savePath = 'uploads/qrcode/' . date('Ymd') . '/'; $fullPath = public_path() . $savePath; if (!is_dir($fullPath)) { mkdir($fullPath, 0755, true); } $saved = file_put_contents($fullPath . $filename, $response); if (!$saved) { throw new \Exception('保存二维码图片失败'); } $qrcodeUrl = request()->domain() . '/' . $savePath . $filename; \think\facade\Log::info('小程序码生成成功', ['url' => $qrcodeUrl]); return $qrcodeUrl; } catch (\Exception $e) { \think\facade\Log::error('generateWxQrcode异常: ' . $e->getMessage()); self::setError($e->getMessage()); return false; } } /** * @notes 获取微信access_token * @param string $appId * @param string $appSecret * @return string|false */ private static function getWxAccessToken(string $appId, string $appSecret) { try { // 尝试从缓存获取 $cacheKey = 'wx_access_token_' . $appId; $accessToken = cache($cacheKey); if ($accessToken) { return $accessToken; } // 从微信服务器获取 $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appId}&secret={$appSecret}"; $response = self::httpGet($url); // 记录原始响应用于调试 \think\facade\Log::info('微信AccessToken响应: ' . $response); $result = json_decode($response, true); // 检查是否有错误 if (isset($result['errcode']) && $result['errcode'] != 0) { $errorMsg = "获取AccessToken失败: errcode={$result['errcode']}, errmsg=" . ($result['errmsg'] ?? '未知错误'); \think\facade\Log::error($errorMsg); throw new \Exception($errorMsg); } if (isset($result['access_token'])) { // 缓存access_token,有效期7000秒(微信官方7200秒,提前200秒过期) cache($cacheKey, $result['access_token'], 7000); \think\facade\Log::info('AccessToken获取成功并已缓存'); return $result['access_token']; } throw new \Exception('获取access_token失败: 响应中没有access_token字段'); } catch (\Exception $e) { \think\facade\Log::error('getWxAccessToken异常: ' . $e->getMessage()); self::setError($e->getMessage()); return false; } } /** * @notes HTTP GET请求 * @param string $url * @return string|false */ private static function httpGet(string $url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $response = curl_exec($ch); curl_close($ch); return $response; } /** * @notes HTTP POST请求 * @param string $url * @param string $data * @return string|false */ private static function httpPost(string $url, string $data) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); $response = curl_exec($ch); curl_close($ch); return $response; } PHP; // 在最后一个}之前插入方法 $lastBrace = strrpos($content, '}'); if ($lastBrace !== false) { $content = substr($content, 0, $lastBrace) . $methods . "\n}"; } else { echo "错误:找不到类的结束括号\n"; exit(1); } // 写回文件 file_put_contents($file, $content); echo "✓ 方法添加成功\n"; echo "已添加以下方法:\n"; echo " - generateMiniProgramQrcode()\n"; echo " - getMiniProgramConfig()\n"; echo " - generateWxQrcode()\n"; echo " - getWxAccessToken()\n"; echo " - httpGet()\n"; echo " - httpPost()\n";