提交其他文件

This commit is contained in:
2026-03-14 16:20:49 +08:00
parent a227deaecd
commit 0a19b334f8
1385 changed files with 73568 additions and 0 deletions

View File

@ -0,0 +1,267 @@
<?php
namespace app\api\controller;
use app\common\service\wechat\WeChatConfigService;
use EasyWeChat\MiniApp\Application;
use think\facade\Log;
class WxCodeController extends BaseApiController
{
public function getWxacode()
{
try {
// 1. 获取参数
$scene = $this->request->param('scene', 'default');
$url = $this->request->param('page', 'pages/index/index');
$width = $this->request->param('width', 430);
// 'env_version' => 'trial',
// 'env_version' => 'develop'
$envVersion = $this->request->param('env_version', '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=2' , // 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 $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;
}
}