dataLists(new WxcodeLists()); } /** * @notes 添加 * @return \think\response\Json * @author likeadmin * @date 2026/03/06 13:28 */ public function add() { $params = (new WxcodeValidate())->post()->goCheck('add'); $return = $this->getWxacode($params); // var_dump($return); $result = WxcodeLogic::add($params,$return); if (true === $result) { return $this->success('添加成功', [], 1, 1); } return $this->fail(WxcodeLogic::getError()); } /** * @notes 编辑 * @return \think\response\Json * @author likeadmin * @date 2026/03/06 13:28 */ public function edit() { $params = (new WxcodeValidate())->post()->goCheck('edit'); $result = WxcodeLogic::edit($params); if (true === $result) { return $this->success('编辑成功', [], 1, 1); } return $this->fail(WxcodeLogic::getError()); } /** * @notes 删除 * @return \think\response\Json * @author likeadmin * @date 2026/03/06 13:28 */ public function delete() { $params = (new WxcodeValidate())->post()->goCheck('delete'); WxcodeLogic::delete($params); return $this->success('删除成功', [], 1, 1); } /** * @notes 获取详情 * @return \think\response\Json * @author likeadmin * @date 2026/03/06 13:28 */ public function detail() { $params = (new WxcodeValidate())->goCheck('detail'); $result = WxcodeLogic::detail($params); return $this->data($result); } public function getWxacode($params) { try { // 1. 获取参数 $scene = 'default'; $url = 'pages/index/index'; $width = 430; // 'env_version' => 'trial', // 'env_version' => 'develop' $envVersion = 'develop'; // 2. 参数验证 if (strlen($scene) > 32) { return $this->fail('场景值不能超过32个字符'); } // 3. 获取微信配置 $config = WeChatConfigService::getMnpConfig(); if (empty($config['app_id']) || empty($config['secret'])) { return $this->fail('微信小程序配置不完整'); } // 4. 创建微信小程序应用实例 $app = new Application($config); // 5. 使用新的方式调用:通过 createClient() 调用API $response = $app->createClient()->postJson('/wxa/getwxacodeunlimit', [ 'scene' => 'registerSource='.$params['type'] , // 0普通 1电梯 2充电宝 'page' => $url, 'width' => $width, 'auto_color' => false, 'line_color' => ['r' => 0, 'g' => 0, 'b' => 0], 'is_hyaline' => false, 'env_version' => $envVersion, 'check_path' => false, ]); // 6. 处理响应结果 if ($this->isImageResponse($response)) { // 保存到文件并返回URL return $this->saveQrCodeToFile($response, $scene, $url); } else { // 处理错误响应 return $this->handleErrorResponse($response); } } catch (\Throwable $e) { Log::error('生成小程序码异常:' . $e->getMessage()); Log::error('异常追踪:' . $e->getTraceAsString()); return $this->fail('生成失败:' . $e->getMessage()); } } /** * 判断是否为图片响应 */ private function isImageResponse($response): bool { $contentType = $response->getHeaderLine('content-type'); return strpos($contentType, 'image/') !== false || strpos($contentType, 'application/octet-stream') !== false; } /** * 保存二维码到文件 */ private function saveQrCodeToFile($response, $scene, $page) { try { // 生成文件名 $filename = 'wxacode_' . date('YmdHis') . '_' . substr(md5($scene . $page), 0, 8) . '.png'; // 保存目录 $saveDir = public_path() . 'uploads/wxqrcode/'; // 确保目录存在 if (!is_dir($saveDir)) { mkdir($saveDir, 0755, true); } $savePath = $saveDir . $filename; // 保存文件(新版本方式) $content = $response->getContent(); file_put_contents($savePath, $content); // 验证文件 if (!file_exists($savePath) || filesize($savePath) === 0) { throw new \Exception('文件保存失败或为空'); } // 返回结果 $fileUrl = request()->domain() . '/uploads/wxqrcode/' . $filename; return $fileUrl; // return $this->success('生成成功', [ // 'url' => $fileUrl, // 'path' => '/uploads/wxqrcode/' . $filename, // 'filename' => $filename, // 'file_size' => filesize($savePath), // 'scene' => $scene, // 'page' => $page, // ]); } catch (\Exception $e) { Log::error('保存文件失败:' . $e->getMessage()); // 备用方案:返回Base64 $content = $response->getContent(); $base64 = 'data:image/png;base64,' . base64_encode($content); return $this->success('生成成功(Base64格式)', [ 'base64' => $base64, 'scene' => $scene, 'page' => $page, ]); } } /** * 处理错误响应 */ private function handleErrorResponse($response) { $content = $response->getContent(); $data = json_decode($content, true); if (JSON_ERROR_NONE === json_last_error() && isset($data['errcode'])) { $errorMsg = $this->getWeChatErrorMessage($data['errcode']); Log::error('微信接口错误:' . $errorMsg . ',数据:' . $content); return $this->fail('微信接口错误:' . $errorMsg); } Log::error('未知错误响应:' . $content); return $this->fail('生成失败:未知的响应格式'); } /** * 获取微信错误信息 */ private function getWeChatErrorMessage($errcode) { $errorMap = [ -1 => '系统繁忙,请稍候再试', 40001 => 'AppSecret错误或access_token无效', 40002 => '无效的凭证类型', 40013 => '无效的AppID', 41030 => '页面路径不存在或有权限限制', 45009 => '接口调用频率超限', 85064 => '找不到该小程序', 85065 => '小程序未发布或已下架', 86004 => '无效的scene参数', 87009 => '无效的页面路径', 9401020 => '小程序未发布', ]; return $errorMap[$errcode] ?? ('错误码:' . $errcode); } /** * 测试版本 - 直接输出图片 */ public function testGenerate() { try { $scene = $this->request->param('scene', 'test'); $page = $this->request->param('page', 'pages/index/index'); $config = WeChatConfigService::getMnpConfig(); $app = new Application($config); $response = $app->createClient()->postJson('/wxa/getwxacodeunlimit', [ 'scene' => $scene, 'page' => $page, 'width' => 430, ]); // 直接输出图片 header('Content-Type: ' . $response->getHeaderLine('content-type')); echo $response->getContent(); exit; } catch (\Exception $e) { return json([ 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString(), ]); } } /** * 检查配置和环境 */ public function checkEnv() { try { $config = WeChatConfigService::getMnpConfig(); $checks = [ 'config_exists' => !empty($config), 'app_id_exists' => !empty($config['app_id']), 'secret_exists' => !empty($config['secret']), 'class_exists' => class_exists('EasyWeChat\MiniApp\Application'), 'createClient_method' => method_exists('EasyWeChat\MiniApp\Application', 'createClient'), ]; // 测试创建实例 if ($checks['class_exists']) { $app = new Application($config); $checks['instance_created'] = true; // 测试获取access_token try { $accessToken = $app->getAccessToken()->getToken(); $checks['access_token_ok'] = !empty($accessToken); } catch (\Exception $e) { $checks['access_token_error'] = $e->getMessage(); } } return $this->success('环境检查', [ 'checks' => $checks, 'config' => [ 'app_id' => $config['app_id'] ?? '未设置', 'secret_set' => !empty($config['secret']), ], 'suggestions' => $this->getSuggestions($checks), ]); } catch (\Exception $e) { return $this->fail('检查失败:' . $e->getMessage()); } } private function getSuggestions($checks) { $suggestions = []; if (!$checks['config_exists']) { $suggestions[] = '配置不存在,请检查 WeChatConfigService::getMnpConfig()'; } if (!$checks['app_id_exists']) { $suggestions[] = '请在.env中设置 WECHAT_MINI_PROGRAM_APPID'; } if (!$checks['secret_exists']) { $suggestions[] = '请在.env中设置 WECHAT_MINI_PROGRAM_SECRET'; } if (!$checks['class_exists']) { $suggestions[] = 'EasyWeChat未安装或版本不兼容,请执行:composer require overtrue/wechat'; } return $suggestions; } }