代码提交优化新增的渠道码限制24小时有效

This commit is contained in:
wong
2025-12-20 11:09:04 +08:00
parent 3f5a2189ce
commit 7a0ae54705

View File

@@ -9,6 +9,8 @@ use library\ResponseHelper;
use think\Db;
use think\Exception;
use think\facade\Env;
use think\facade\Cache;
use think\facade\Log;
use Endroid\QrCode\QrCode;
use Endroid\QrCode\ErrorCorrectionLevel;
use EasyWeChat\Factory;
@@ -860,6 +862,43 @@ class ChannelController extends BaseController
'expireTime' => time() + 86400 // 24小时后过期
];
$token = base64_encode(json_encode($tokenData));
// 如果是小程序码提前计算scene并存储映射关系到数据库
if ($type === 'miniprogram') {
$scene = substr(md5($token), 0, 32);
// 使用数据库存储映射关系(更可靠)
try {
Db::name('distribution_channel_scene_token')->insert([
'scene' => $scene,
'token' => $token,
'companyId' => $companyId,
'expireTime' => time() + 86400,
'createTime' => time()
]);
Log::info('生成小程序码 - 存储映射到数据库scene: ' . $scene . ', companyId: ' . $companyId);
} catch (\Exception $e) {
// 如果表不存在,尝试创建表
Log::warning('存储映射关系失败,尝试创建表: ' . $e->getMessage());
$this->createSceneTokenTable();
// 重试一次
try {
Db::name('distribution_channel_scene_token')->insert([
'scene' => $scene,
'token' => $token,
'companyId' => $companyId,
'expireTime' => time() + 86400,
'createTime' => time()
]);
} catch (\Exception $e2) {
Log::error('重试存储映射关系失败: ' . $e2->getMessage());
}
}
// 同时存储到缓存(双重保险)
$sceneCacheKey = 'channel_register_scene_' . $scene;
Cache::set($sceneCacheKey, $token, 86400);
}
if ($type === 'h5') {
// 生成H5二维码
@@ -905,6 +944,18 @@ class ChannelController extends BaseController
// scene参数长度限制为32位使用token的MD5值
$scene = substr(md5($token), 0, 32);
// 再次确保映射关系已存储到数据库和缓存(双重保险)
$sceneCacheKey = 'channel_register_scene_' . $scene;
Cache::set($sceneCacheKey, $token, 86400);
// 验证数据库和缓存是否存储成功
$dbToken = Db::name('distribution_channel_scene_token')
->where('scene', $scene)
->where('expireTime', '>', time())
->value('token');
$cacheToken = Cache::get($sceneCacheKey);
Log::info('生成小程序码 - scene: ' . $scene . ', 数据库验证: ' . ($dbToken ? '成功' : '失败') . ', 缓存验证: ' . ($cacheToken ? '成功' : '失败'));
// 调用接口生成小程序码
// 注意page 必须是小程序里已经存在且发布过的页面路径
@@ -1125,6 +1176,43 @@ class ChannelController extends BaseController
]);
}
// 记录接收到的参数
Log::info('registerByQrCode - 接收到的token参数: ' . $token . ', 长度: ' . strlen($token) . ', 是否为32位MD5: ' . (preg_match('/^[a-f0-9]{32}$/i', $token) ? '是' : '否'));
// 判断传入的是scene32位MD5还是tokenbase64编码
// 如果是32位MD5字符串则从数据库或缓存中查找对应的token
if (strlen($token) == 32 && preg_match('/^[a-f0-9]{32}$/i', $token)) {
// 这是scene先从数据库查找对应的token
$sceneData = Db::name('distribution_channel_scene_token')
->where('scene', $token)
->where('expireTime', '>', time())
->find();
if ($sceneData && !empty($sceneData['token'])) {
$realToken = $sceneData['token'];
Log::info('registerByQrCode - 从数据库获取token成功scene: ' . $token);
} else {
// 如果数据库中没有,尝试从缓存获取
$sceneCacheKey = 'channel_register_scene_' . $token;
$realToken = Cache::get($sceneCacheKey);
if (empty($realToken)) {
Log::warning('registerByQrCode - 数据库和缓存中均未找到tokenscene: ' . $token);
return json([
'code' => 400,
'success' => false,
'msg' => '二维码已过期,请重新生成',
'data' => null
]);
}
Log::info('registerByQrCode - 从缓存获取token成功scene: ' . $token);
}
$token = $realToken;
} else {
Log::info('registerByQrCode - 识别为token非scene直接使用token长度: ' . strlen($token));
}
// 解析token
$tokenData = json_decode(base64_decode($token), true);
if (!$tokenData || !isset($tokenData['companyId'])) {
@@ -1307,5 +1395,31 @@ class ChannelController extends BaseController
]);
}
}
/**
* 创建scene和token映射表如果不存在
*/
protected function createSceneTokenTable()
{
try {
$sql = "CREATE TABLE IF NOT EXISTS `ck_distribution_channel_scene_token` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`scene` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '小程序scene参数MD5值',
`token` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '原始tokenbase64编码',
`companyId` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '公司ID',
`expireTime` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '过期时间戳',
`createTime` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `uk_scene` (`scene`) USING BTREE,
INDEX `idx_companyId` (`companyId`) USING BTREE,
INDEX `idx_expireTime` (`expireTime`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='分销渠道小程序码scene和token映射表';";
Db::execute($sql);
Log::info('创建scene和token映射表成功');
} catch (\Exception $e) {
Log::error('创建scene和token映射表失败: ' . $e->getMessage());
}
}
}