Initial commit: 投注游戏平台初始化

This commit is contained in:
li
2026-02-25 01:26:58 +08:00
commit 77ca2cc8b3
275 changed files with 237479 additions and 0 deletions
+371
View File
@@ -0,0 +1,371 @@
<?php
namespace Plugins\WxShare\Controllers\Admin;
use App\Core\PluginBaseController;
class WxShareController extends PluginBaseController {
protected $pluginManager;
protected $db;
public function __construct() {
global $pluginManager;
$this->pluginManager = $pluginManager;
$this->db = $this->pluginManager->getDB();
}
public function index() {
$this->checkLogin(); // 登录保护
// 获取配置信息(带默认值,避免空值)
$settings = $this->db->get('wxshare_settings', '*') ?: []; // 如果没有数据,返回空数组
// 传数据给视图(统一封装在data中)
$this->renderPluginView('WxShare', 'Admin/index.php', [
'data' => [
'settings' => '', // 配置信息
'domain' => '' // 带协议的完整域名
],
'title' => '微信卡片分享管理中心'
]);
}
public function list() {
$this->checkLogin(); // 登录保护
// 获取分页参数
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
$pageSize = isset($_GET['page_size']) ? max(1, min(100, intval($_GET['page_size']))) : 10;
$offset = ($page - 1) * $pageSize;
// 1. 获取总记录数
$totalItems = $this->db->count('wxshare_list', '*');
// 2. 获取当前页数据
$shortlinks = $this->db->select('wxshare_list', '*', [
'ORDER' => ['id' => 'DESC'],
'LIMIT' => [$offset, $pageSize]
]);
// 3. 计算分页信息
$totalPages = max(1, ceil($totalItems / $pageSize));
// 4. 返回JSON格式数据
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'success' => true,
'data' => [
'items' => $shortlinks,
'current_page' => $page,
'total_pages' => $totalPages,
'total_items' => $totalItems,
'page_size' => $pageSize,
'has_prev' => $page > 1,
'has_next' => $page < $totalPages
]
], JSON_UNESCAPED_UNICODE);
exit;
}
public function get($id) {
$this->checkLogin();
// 设置响应内容类型为JSON
header('Content-Type: application/json');
$row = $this->db->get('wxshare_list', '*', ['id' => $id]);
if ($row) {
// 成功响应,包含状态和数据
echo json_encode([
'success' => true,
'data' => $row
]);
} else {
echo json_encode([
'success' => false,
'message' => '无效的ID或记录不存在'
]);
}
exit;
}
public function update() {
// 设置JSON响应头
header('Content-Type: application/json');
$this->checkLogin();
// 获取表单数据(使用表中定义的字段)
$id = intval($_POST['id'] ?? 0);
$share_link = trim($_POST['share_link'] ?? '');
$code = trim($_POST['code'] ?? '');
$share_title = trim($_POST['share_title'] ?? '');
$share_desc = trim($_POST['share_desc'] ?? '');
$share_img = trim($_POST['share_img'] ?? '');
$status = isset($_POST['status']) ? 1 : 0;
// 验证参数
$errors = [];
if (!$share_title) $errors[] = '分享标题不能为空';
if (!$share_link) $errors[] = '分享链接不能为空';
if (!$code) $errors[] = 'code不能为空';
if (!$share_desc) $errors[] = '分享描述不能为空';
if (!$share_img) $errors[] = '分享封面图不能为空';
if (!empty($errors)) {
// 返回 JSON 错误信息
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'status' => 'error',
'message' => implode('; ', $errors)
]);
exit;
}
try {
// 有ID则更新
if ($id > 0) {
$data = [
'share_link' => $share_link, // 原url改为share_link
'name' => $share_link,
'code' => $code,
'share_title' => $share_title, // 新增字段
'share_desc' => $share_desc, // 原description改为share_desc
'share_img' => $share_img, // 新增字段
'status' => $status,
'updated_at' => date('Y-m-d H:i:s')
];
$result = $this->db->update('wxshare_list', $data, ['id' => $id]);
if ($result) {
$qrcode = $this->db->get('wxshare_list', '*', ['id' => $id]);
echo json_encode([
'success' => true,
'message' => '更新成功',
'data' => $qrcode
]);
} else {
http_response_code(500);
echo json_encode([
'success' => false,
'message' => '更新失败,请稍后重试'
]);
}
}
// 无ID则新增
else {
$insertId = $this->db->insert('wxshare_list', [
'share_link' => $share_link, // 原url改为share_link
'name' => $share_link,
'code' => $code,
'share_title' => $share_title, // 新增字段
'share_desc' => $share_desc, // 原description改为share_desc
'share_img' => $share_img, // 新增字段
'status' => 1,
'views' => 0,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
]);
if ($insertId) {
echo json_encode([
'success' => true,
'message' => '创建成功',
'data' => [
'id' => $insertId,
'share_link' => $share_link,
'name' => $share_link,
'code' => $code,
'share_title' => $share_title,
'share_desc' => $share_desc,
'share_img' => $share_img,
'status' => $status,
'views' => 0
]
]);
} else {
http_response_code(500);
echo json_encode([
'success' => false,
'message' => '创建失败,请稍后重试'
]);
}
}
} catch (Exception $e) {
http_response_code(500);
echo json_encode([
'success' => false,
'message' => '操作失败: ' . $e->getMessage()
]);
}
exit;
}
public function settings() {
$this->checkLogin();
header('Content-Type: application/json');
$id = intval($_REQUEST['id'] ?? 0);
try {
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
// 获取第一条设置记录
$row = $this->db->get('wxshare_settings', '*');
if ($row) {
echo json_encode([
'success' => true,
'data' => $row
]);
} else {
echo json_encode([
'success' => false,
'message' => '设置不存在'
]);
}
} else if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// 获取提交数据
$wechat_name = trim($_POST['wechat_name'] ?? '');
$wechat_account = trim($_POST['wechat_account'] ?? '');
$appid = trim($_POST['appid'] ?? '');
$appsecret = trim($_POST['appsecret'] ?? '');
$token = trim($_POST['token'] ?? '');
$encoding_aes_key = trim($_POST['encoding_aes_key'] ?? '');
$qrcode_url = trim($_POST['qrcode_url'] ?? '');
$wechat_type = trim($_POST['wechat_type'] ?? 'service');
$status = isset($_POST['status']) ? 1 : 0;
// 验证必填项
if (empty($wechat_name) || empty($wechat_account) || empty($appid) || empty($appsecret)) {
echo json_encode([
'success' => false,
'message' => '公众号名称、原始ID、AppID和AppSecret为必填项'
]);
exit;
}
if ($id > 0) {
// 更新
$data = [
'wechat_name' => $wechat_name,
'wechat_account' => $wechat_account,
'appid' => $appid,
'appsecret' => $appsecret,
'token' => $token,
'encoding_aes_key' => $encoding_aes_key,
'qrcode_url' => $qrcode_url,
'wechat_type' => $wechat_type,
'status' => $status,
'updated_at' => date('Y-m-d H:i:s')
];
$result = $this->db->update('wxshare_settings', $data, ['id' => $id]);
if ($result) {
$setting = $this->db->get('wxshare_settings', '*', ['id' => $id]);
echo json_encode([
'success' => true,
'message' => '设置更新成功',
'data' => $setting
]);
} else {
echo json_encode([
'success' => false,
'message' => '更新失败或数据无变化'
]);
}
} else {
// 新增
$insertId = $this->db->insert('wxshare_settings', [
'wechat_name' => $wechat_name,
'wechat_account' => $wechat_account,
'appid' => $appid,
'appsecret' => $appsecret,
'token' => $token,
'encoding_aes_key' => $encoding_aes_key,
'qrcode_url' => $qrcode_url,
'wechat_type' => $wechat_type,
'status' => 1,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
]);
if ($insertId) {
$setting = $this->db->get('wxshare_settings', '*');
echo json_encode([
'success' => true,
'message' => '设置创建成功',
'data' => $setting
]);
} else {
echo json_encode([
'success' => false,
'message' => '创建失败,请稍后重试'
]);
}
}
} else {
http_response_code(405);
echo json_encode([
'success' => false,
'message' => '只支持 GET 和 POST 请求'
]);
}
} catch (Exception $e) {
http_response_code(500);
echo json_encode([
'success' => false,
'message' => '操作失败: ' . $e->getMessage()
]);
}
exit;
}
public function delete($id) {
$this->checkLogin();
header('Content-Type: application/json');
try {
$row = $this->db->get('wxshare_list', '*', ['id' => $id]);
if (!$row) {
echo json_encode([
'success' => false,
'message' => '要删除的记录不存在'
]);
exit;
}
// 执行删除
$result = $this->db->delete('wxshare_list', ['id' => $id]);
if ($result) {
echo json_encode([
'success' => true,
'message' => '记录已删除'
]);
} else {
echo json_encode([
'success' => false,
'message' => '删除失败,请稍后再试'
]);
}
} catch (Exception $e) {
http_response_code(500);
echo json_encode([
'success' => false,
'message' => '删除失败: ' . $e->getMessage()
]);
}
exit;
}
}
+97
View File
@@ -0,0 +1,97 @@
<?php
namespace Plugins\WxShare\Controllers\Web;
use App\Core\WebBaseController;
class WxShareController extends WebBaseController {
protected $pluginManager;
protected $db;
public function __construct() {
global $pluginManager;
$this->pluginManager = $pluginManager;
$this->db = $this->pluginManager->getDB();
}
public function index($code) {
// 引入 JSSDK 类文件
$jssdkPath = dirname(__FILE__) . '/../../../WxShare/Controllers/lib/jssdk.php';
if (!file_exists($jssdkPath)) {
$this->showError("JSSDK 文件不存在:{$jssdkPath}");
}
require_once($jssdkPath);
try {
// 1. 从wxshare_settings表获取公众号配置(假设系统中只有一条配置记录)
$settings = $this->db->get('wxshare_settings', '*');
if (empty($settings)) {
$this->showError('未找到公众号配置,请先在后台完成设置');
}
// 2. 验证必要配置是否存在
$requiredFields = ['appid', 'appsecret'];
foreach ($requiredFields as $field) {
if (empty($settings[$field])) {
$this->showError("公众号配置不完整,缺少:{$field}");
}
}
// 3. 从wxshare_list表获取token与URL的映射关系
$share = $this->db->get('wxshare_list', '*', ['code' => $code] );
// 2. 判断是否存在该类型记录
if (empty($share)) {
$this->showError('未找到' . $code . '的URL配置,请先添加');
exit; // 无此类型记录,停止执行
}
// 3. 检查该记录是否启用(status = 1)
if ($share['status'] != 1) {
$this->showError('当前' . $code . '的URL未启用,请启用后再使用');
exit;
}
if (isset($_GET['rep'])) {
// 更新访问次数
$this->db->update('wxshare_list', [
'views[+]' => 1
], [
'code' => $code,
'status' => 1
]);
// 跳转
header("Location: " . $share['share_link']);
exit;
}
$url = $share['share_link'];
$jssdk = new \Plugins\WxShare\Controllers\lib\JSSDK($settings['appid'], $settings['appsecret']);
$signPackage = $jssdk->GetSignPackage();
} catch (Exception $e) {
echo '<script>alert("错误: '. addslashes($e->getMessage()). '"); window.close();</script>';
exit;
}
// 传数据给视图
include __DIR__ . '/../../Views/Web/index.php';
}
public function redirect($code) {
$row = $this->db->get('wxshare_list', '*', ['code' => $code]);
if ($row) {
// 检查链接是否处于激活状态
if ($row['is_active'] != 1) {
$this->showError($code . ' 此链接已被停用!');
exit;
}
// 若激活,则更新访问量并跳转
$update = $this->db->update('wxshare_list', ['views[+]' => 1 ], ['id' => $row['id'] ]);
if ($update->rowCount() > 0) {
header("Location: " . $row['share_link']);
exit;
}
} else {
$this->showError( $code . ' 此链接不存在!');
}
}
}
+1
View File
@@ -0,0 +1 @@
<?php exit();?>{"expire_time":1755715644,"access_token":"95_eDc_CzaW9yYbHNhPFs5_UmwQIjx-j25vgX2a-m5scHEaxnFNg5d3FufMFvGS2eegNbhRhh01duV_i23i5zpz96UKWyM7f-rlohmxzqSjqRuYhhwYSZqRKCqZ1zsIRIhAHAXGX"}
+1
View File
@@ -0,0 +1 @@
<?php exit();?>{"expire_time":1755715644,"jsapi_ticket":"7mo9kzLF0zXvfXKd2ScDpJkaYOCMtHVFZ1MqnrYmJLj66DEsamUjaZ0-iUq3MJWpwWiTm_vt903SF5b7Y9dB2w"}
+151
View File
@@ -0,0 +1,151 @@
<?php
namespace Plugins\WxShare\Controllers\lib;
class JSSDK {
private $appId;
private $appSecret;
// 缓存文件路径(使用绝对路径避免问题)
private $cacheDir;
public function __construct($appId, $appSecret) {
$this->appId = $appId;
$this->appSecret = $appSecret;
// 初始化缓存目录(与jssdk.php同目录)
$this->cacheDir = dirname(__FILE__) . '/';
// 确保缓存目录可写
$this->checkCacheDir();
}
// 检查缓存目录是否存在且可写
private function checkCacheDir() {
if (!is_dir($this->cacheDir)) {
mkdir($this->cacheDir, 0755, true);
}
if (!is_writable($this->cacheDir)) {
echo "缓存目录不可写:{$this->cacheDir}.需要手动改写权限 777";
exit();
}
}
// 检查并创建缓存文件
private function checkCacheFile($filename) {
$filePath = $this->cacheDir . $filename;
// 如果文件不存在则创建并初始化
if (!file_exists($filePath)) {
$initialData = json_encode([
'expire_time' => 0,
'access_token' => '',
'jsapi_ticket' => ''
]);
$this->set_php_file($filename, $initialData);
}
return $filePath;
}
public function getSignPackage() {
$jsapiTicket = $this->getJsApiTicket();
// 动态获取当前URL
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
$url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$timestamp = time();
$nonceStr = $this->createNonceStr();
// 按ASCII码升序排序
$string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
$signature = sha1($string);
return [
"appId" => $this->appId,
"nonceStr" => $nonceStr,
"timestamp" => $timestamp,
"url" => $url,
"signature" => $signature,
"rawString" => $string
];
}
private function createNonceStr($length = 16) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$str = "";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
private function getJsApiTicket() {
// 先检查并创建缓存文件
$this->checkCacheFile("jsapi_ticket.php");
$data = json_decode($this->get_php_file("jsapi_ticket.php"));
// 处理空数据或过期情况
if (empty($data) || $data->expire_time < time()) {
$accessToken = $this->getAccessToken();
$url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
$res = json_decode($this->httpGet($url));
if (isset($res->ticket)) {
$data = new \stdClass(); // 初始化空对象
$data->expire_time = time() + 7000;
$data->jsapi_ticket = $res->ticket;
$this->set_php_file("jsapi_ticket.php", json_encode($data));
} else {
throw new \Exception("获取jsapi_ticket失败: " . json_encode($res));
}
}
return $data->jsapi_ticket ?? '';
}
private function getAccessToken() {
// 先检查并创建缓存文件
$this->checkCacheFile("access_token.php");
$data = json_decode($this->get_php_file("access_token.php"));
// 处理空数据或过期情况
if (empty($data) || $data->expire_time < time()) {
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appId&secret=$this->appSecret";
$res = json_decode($this->httpGet($url));
if (isset($res->access_token)) {
$data = new \stdClass(); // 初始化空对象
$data->expire_time = time() + 7000;
$data->access_token = $res->access_token;
$this->set_php_file("access_token.php", json_encode($data));
} else {
throw new \Exception("获取access_token失败: " . json_encode($res));
}
}
return $data->access_token ?? '';
}
private function httpGet($url) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 500);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);
curl_setopt($curl, CURLOPT_URL, $url);
$res = curl_exec($curl);
curl_close($curl);
return $res;
}
private function get_php_file($filename) {
$filePath = $this->cacheDir . $filename;
return trim(substr(file_get_contents($filePath), 15));
}
private function set_php_file($filename, $content) {
$filePath = $this->cacheDir . $filename;
$fp = fopen($filePath, "w");
fwrite($fp, "<?php exit();?>" . $content);
fclose($fp);
}
}