Files
2026-03-11 18:24:59 +08:00

367 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\adminapi\controller;
use app\adminapi\controller\BaseAdminController;
use app\adminapi\lists\WxcodeLists;
use app\adminapi\logic\WxcodeLogic;
use app\adminapi\validate\WxcodeValidate;
use app\common\service\wechat\WeChatConfigService;
use EasyWeChat\MiniApp\Application;
use think\facade\Log;
/**
* Wxcode控制器
* Class WxcodeController
* @package app\adminapi\controller
*/
class WxcodeController extends BaseAdminController
{
/**
* @notes 获取列表
* @return \think\response\Json
* @author likeadmin
* @date 2026/03/06 13:28
*/
public function lists()
{
return $this->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;
}
}