feat: 添加WPS表单处理功能及相关测试
实现WPS表单Webhook接收端点,包括数据解析、验证和存储功能 添加数据库表创建脚本和测试用例 包含Webhook测试页面和日志功能
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
-- 创建WPS表单数据表
|
||||
CREATE TABLE IF NOT EXISTS wps_form_submissions (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
rid VARCHAR(50) NOT NULL COMMENT '表单提交ID',
|
||||
form_id VARCHAR(50) NOT NULL COMMENT '表单ID',
|
||||
form_title VARCHAR(255) NOT NULL COMMENT '表单标题',
|
||||
creator_id VARCHAR(50) NOT NULL COMMENT '创建者ID',
|
||||
create_time DATETIME NOT NULL COMMENT '创建时间',
|
||||
update_time DATETIME NOT NULL COMMENT '更新时间',
|
||||
nick_name VARCHAR(255) COMMENT '创建者昵称',
|
||||
department VARCHAR(255) COMMENT '创建者部门',
|
||||
mobile VARCHAR(20) COMMENT '请输入手机号',
|
||||
name VARCHAR(255) COMMENT '怎么称呼您',
|
||||
license_plate VARCHAR(20) COMMENT '车牌号',
|
||||
date DATE COMMENT '日期',
|
||||
time_slot VARCHAR(20) COMMENT '时间段',
|
||||
car_type VARCHAR(50) COMMENT '车型',
|
||||
wash_type VARCHAR(100) COMMENT '洗车类型',
|
||||
wash_packages VARCHAR(255) COMMENT '洗车套餐',
|
||||
wash_services TEXT COMMENT '洗车服务',
|
||||
additional_services TEXT COMMENT '额外服务',
|
||||
need_wax VARCHAR(10) COMMENT '是否需要打蜡',
|
||||
wax_type VARCHAR(50) COMMENT '蜡的类型',
|
||||
cleaning_needs TEXT COMMENT '清洁需求',
|
||||
interior_cleaning VARCHAR(10) COMMENT '是否需要内饰清洁',
|
||||
exterior_cleaning VARCHAR(10) COMMENT '是否需要外观清洁',
|
||||
vip_member VARCHAR(10) COMMENT '是否为VIP会员',
|
||||
vip_number VARCHAR(50) COMMENT 'VIP卡号',
|
||||
payment_method VARCHAR(50) COMMENT '支付方式',
|
||||
special_requests TEXT COMMENT '特殊要求',
|
||||
technician VARCHAR(50) COMMENT '指定技师',
|
||||
status VARCHAR(20) DEFAULT 'pending' COMMENT '状态',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间',
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '记录更新时间',
|
||||
INDEX idx_rid (rid),
|
||||
INDEX idx_license_plate (license_plate),
|
||||
INDEX idx_date (date),
|
||||
INDEX idx_mobile (mobile)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
// 测试数据库连接和表创建功能
|
||||
require_once 'config.php';
|
||||
|
||||
// 记录日志的函数
|
||||
function log_test_message($message, $type = 'info') {
|
||||
$log_file = 'test_db.log';
|
||||
$timestamp = date('Y-m-d H:i:s');
|
||||
$log_entry = "[$timestamp] [$type] $message\n";
|
||||
file_put_contents($log_file, $log_entry, FILE_APPEND);
|
||||
echo $log_entry;
|
||||
}
|
||||
|
||||
echo "=== 测试数据库连接和表创建功能 ===\n";
|
||||
|
||||
// 测试数据库连接
|
||||
try {
|
||||
$pdo = new PDO("mysql:host=$host;dbname=$database;charset=utf8mb4", $username, $password);
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
log_test_message("数据库连接成功");
|
||||
} catch(PDOException $e) {
|
||||
log_test_message("数据库连接失败: " . $e->getMessage(), 'error');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// 测试创建表
|
||||
try {
|
||||
$sql = "CREATE TABLE IF NOT EXISTS wps_form_submissions (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
rid VARCHAR(50) NOT NULL COMMENT '表单提交ID',
|
||||
form_id VARCHAR(50) NOT NULL COMMENT '表单ID',
|
||||
form_title VARCHAR(255) NOT NULL COMMENT '表单标题',
|
||||
creator_id VARCHAR(50) NOT NULL COMMENT '创建者ID',
|
||||
create_time DATETIME NOT NULL COMMENT '创建时间',
|
||||
update_time DATETIME NOT NULL COMMENT '更新时间',
|
||||
mobile VARCHAR(20) COMMENT '请输入手机号',
|
||||
name VARCHAR(255) COMMENT '怎么称呼您',
|
||||
license_plate VARCHAR(20) COMMENT '车牌号',
|
||||
date DATE COMMENT '日期',
|
||||
time_slot VARCHAR(20) COMMENT '时间段',
|
||||
car_type VARCHAR(50) COMMENT '车型',
|
||||
wash_type VARCHAR(100) COMMENT '洗车类型',
|
||||
wash_packages VARCHAR(255) COMMENT '洗车套餐',
|
||||
wash_services TEXT COMMENT '洗车服务',
|
||||
additional_services TEXT COMMENT '额外服务',
|
||||
need_wax VARCHAR(10) COMMENT '是否需要打蜡',
|
||||
wax_type VARCHAR(50) COMMENT '蜡的类型',
|
||||
cleaning_needs TEXT COMMENT '清洁需求',
|
||||
interior_cleaning VARCHAR(10) COMMENT '是否需要内饰清洁',
|
||||
exterior_cleaning VARCHAR(10) COMMENT '是否需要外观清洁',
|
||||
vip_member VARCHAR(10) COMMENT '是否为VIP会员',
|
||||
vip_number VARCHAR(50) COMMENT 'VIP卡号',
|
||||
payment_method VARCHAR(50) COMMENT '支付方式',
|
||||
special_requests TEXT COMMENT '特殊要求',
|
||||
technician VARCHAR(50) COMMENT '指定技师',
|
||||
status VARCHAR(20) DEFAULT 'pending' COMMENT '状态',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间',
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '记录更新时间',
|
||||
INDEX idx_rid (rid),
|
||||
INDEX idx_license_plate (license_plate),
|
||||
INDEX idx_date (date),
|
||||
INDEX idx_mobile (mobile)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
|
||||
|
||||
$pdo->exec($sql);
|
||||
log_test_message("表创建成功");
|
||||
} catch(PDOException $e) {
|
||||
log_test_message("表创建失败: " . $e->getMessage(), 'error');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// 测试插入数据
|
||||
try {
|
||||
$sql = "INSERT INTO wps_form_submissions (
|
||||
rid, form_id, form_title, creator_id, create_time, update_time,
|
||||
mobile, name, license_plate, date, time_slot, car_type
|
||||
) VALUES (
|
||||
:rid, :form_id, :form_title, :creator_id, :create_time, :update_time,
|
||||
:mobile, :name, :license_plate, :date, :time_slot, :car_type
|
||||
)";
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
|
||||
$stmt->bindValue(':rid', 'test_rid_' . time());
|
||||
$stmt->bindValue(':form_id', 'test_form_id');
|
||||
$stmt->bindValue(':form_title', '测试表单');
|
||||
$stmt->bindValue(':creator_id', 'test_creator_id');
|
||||
$stmt->bindValue(':create_time', date('Y-m-d H:i:s'));
|
||||
$stmt->bindValue(':update_time', date('Y-m-d H:i:s'));
|
||||
$stmt->bindValue(':mobile', '13800138000');
|
||||
$stmt->bindValue(':name', '测试用户');
|
||||
$stmt->bindValue(':license_plate', '京A12345');
|
||||
$stmt->bindValue(':date', date('Y-m-d'));
|
||||
$stmt->bindValue(':time_slot', '14:00-15:00');
|
||||
$stmt->bindValue(':car_type', '轿车');
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
$insert_id = $pdo->lastInsertId();
|
||||
log_test_message("测试数据插入成功,ID: " . $insert_id);
|
||||
} catch(PDOException $e) {
|
||||
log_test_message("测试数据插入失败: " . $e->getMessage(), 'error');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// 测试查询数据
|
||||
try {
|
||||
$sql = "SELECT * FROM wps_form_submissions ORDER BY id DESC LIMIT 1";
|
||||
$stmt = $pdo->query($sql);
|
||||
$row = $stmt->fetch();
|
||||
|
||||
if ($row) {
|
||||
log_test_message("测试数据查询成功");
|
||||
log_test_message("查询结果: " . print_r($row, true));
|
||||
} else {
|
||||
log_test_message("测试数据查询失败: 没有找到数据", 'error');
|
||||
}
|
||||
} catch(PDOException $e) {
|
||||
log_test_message("测试数据查询失败: " . $e->getMessage(), 'error');
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo "\n=== 所有测试完成 ===\n";
|
||||
@@ -0,0 +1,263 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>WPS表单Webhook测试</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
.container {
|
||||
background-color: #f5f5f5;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
h1 {
|
||||
color: #333;
|
||||
text-align: center;
|
||||
}
|
||||
.test-section {
|
||||
margin: 20px 0;
|
||||
padding: 15px;
|
||||
background-color: white;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
button {
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
margin: 5px;
|
||||
}
|
||||
button:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
.response {
|
||||
margin-top: 10px;
|
||||
padding: 10px;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 4px;
|
||||
white-space: pre-wrap;
|
||||
font-family: monospace;
|
||||
}
|
||||
.log-section {
|
||||
margin-top: 30px;
|
||||
}
|
||||
#log-content {
|
||||
height: 300px;
|
||||
overflow-y: auto;
|
||||
background-color: #2d2d2d;
|
||||
color: #f0f0f0;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
font-family: monospace;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>WPS表单Webhook测试工具</h1>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>1. 验证请求测试</h2>
|
||||
<p>模拟WPS表单的验证请求,Webhook应返回绑定码</p>
|
||||
<button onclick="testVerification()">发送验证请求</button>
|
||||
<div class="response" id="verification-response"></div>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>2. 表单数据测试</h2>
|
||||
<p>模拟WPS表单发送数据,Webhook应接收并处理数据</p>
|
||||
<button onclick="testFormData()">发送表单数据</button>
|
||||
<div class="response" id="form-data-response"></div>
|
||||
</div>
|
||||
|
||||
<div class="log-section">
|
||||
<h2>3. Webhook日志</h2>
|
||||
<button onclick="loadLog()">加载日志</button>
|
||||
<button onclick="clearLog()">清空日志</button>
|
||||
<div id="log-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Webhook URL
|
||||
const webhookUrl = 'http://localhost:8000/webhook.php';
|
||||
|
||||
// 发送验证请求
|
||||
async function testVerification() {
|
||||
const responseDiv = document.getElementById('verification-response');
|
||||
responseDiv.innerHTML = '发送中...';
|
||||
|
||||
try {
|
||||
const response = await fetch(webhookUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: '' // 空请求体,模拟验证请求
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
responseDiv.innerHTML = '响应: ' + JSON.stringify(data, null, 2);
|
||||
} catch (error) {
|
||||
responseDiv.innerHTML = '错误: ' + error.message;
|
||||
}
|
||||
}
|
||||
|
||||
// 发送表单数据
|
||||
async function testFormData() {
|
||||
const responseDiv = document.getElementById('form-data-response');
|
||||
responseDiv.innerHTML = '发送中...';
|
||||
|
||||
// 模拟WPS实际表单数据格式
|
||||
const formData = {
|
||||
"rid": "lAFP6N1Tap",
|
||||
"formId": "20251205123619412736007",
|
||||
"formTitle": "张老师撸车(私家车库)预约撸车表单",
|
||||
"aid": "20251205131620432762589",
|
||||
"eventTs": Date.now(),
|
||||
"messageTs": Date.now(),
|
||||
"creatorId": "344573037",
|
||||
"creatorName": "吴展鹏",
|
||||
"event": "create_answer",
|
||||
"version": 2,
|
||||
"answerContents": [
|
||||
{
|
||||
"qid": "eo513g",
|
||||
"type": "input",
|
||||
"title": "怎么称呼您",
|
||||
"value": "吴展鹏"
|
||||
},
|
||||
{
|
||||
"qid": "xKFUcp",
|
||||
"type": "input",
|
||||
"title": "车型",
|
||||
"value": "比亚迪宋PRODMi"
|
||||
},
|
||||
{
|
||||
"qid": "NFJDDT",
|
||||
"type": "input",
|
||||
"title": "车牌号",
|
||||
"value": "新AF10365-普通输入"
|
||||
},
|
||||
{
|
||||
"qid": "t2u2i4",
|
||||
"type": "licensePlate",
|
||||
"title": "车牌号",
|
||||
"value": "新AF10365-车牌专用"
|
||||
},
|
||||
{
|
||||
"qid": "7jgfmh",
|
||||
"type": "telphone",
|
||||
"title": "请输入手机号",
|
||||
"value": "18699627661"
|
||||
},
|
||||
{
|
||||
"qid": "3j6opi",
|
||||
"type": "select",
|
||||
"title": "是否有车衣",
|
||||
"value": ["否,无车衣"]
|
||||
},
|
||||
{
|
||||
"qid": "ej48lk",
|
||||
"type": "select",
|
||||
"title": "有无自己撸车习惯",
|
||||
"value": ["有"]
|
||||
},
|
||||
{
|
||||
"qid": "1tnljp",
|
||||
"type": "select",
|
||||
"title": "撸车经验",
|
||||
"value": ["我是老司机啦"]
|
||||
},
|
||||
{
|
||||
"qid": "x02g35",
|
||||
"type": "select",
|
||||
"title": "洗车频率",
|
||||
"value": ["每2周一次(每月1-2次)"]
|
||||
},
|
||||
{
|
||||
"qid": "54dbo7",
|
||||
"type": "select",
|
||||
"title": "请选择年龄段",
|
||||
"value": ["26~30"]
|
||||
},
|
||||
{
|
||||
"qid": "rwxgkc",
|
||||
"type": "autoNum",
|
||||
"title": "自动编号",
|
||||
"value": "zlslc202512002"
|
||||
},
|
||||
{
|
||||
"qid": "r3ft9n",
|
||||
"type": "input",
|
||||
"title": "备注内容",
|
||||
"value": "谢谢"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch(webhookUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(formData)
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
responseDiv.innerHTML = '响应: ' + JSON.stringify(data, null, 2);
|
||||
} catch (error) {
|
||||
responseDiv.innerHTML = '错误: ' + error.message;
|
||||
}
|
||||
}
|
||||
|
||||
// 加载日志
|
||||
async function loadLog() {
|
||||
const logContent = document.getElementById('log-content');
|
||||
logContent.innerHTML = '加载中...';
|
||||
|
||||
try {
|
||||
const response = await fetch('wps_form_webhook.log');
|
||||
if (response.ok) {
|
||||
const text = await response.text();
|
||||
logContent.innerHTML = text;
|
||||
} else {
|
||||
logContent.innerHTML = '无法加载日志文件: ' + response.statusText;
|
||||
}
|
||||
} catch (error) {
|
||||
logContent.innerHTML = '错误: ' + error.message;
|
||||
}
|
||||
}
|
||||
|
||||
// 清空日志
|
||||
async function clearLog() {
|
||||
const logContent = document.getElementById('log-content');
|
||||
|
||||
try {
|
||||
const response = await fetch('webhook.php?action=clear_log', {
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
logContent.innerHTML = '日志已清空';
|
||||
} else {
|
||||
logContent.innerHTML = '清空日志失败';
|
||||
}
|
||||
} catch (error) {
|
||||
logContent.innerHTML = '错误: ' + error.message;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+359
@@ -0,0 +1,359 @@
|
||||
<?php
|
||||
// WPS表单Webhook接收端点
|
||||
|
||||
// 设置响应头
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
// 绑定码(根据WPS表单要求提供)
|
||||
$bind_code = '20251205123619412736007';
|
||||
|
||||
// 日志文件路径
|
||||
$log_file = 'wps_form_webhook.log';
|
||||
|
||||
// 加载数据库配置
|
||||
require_once 'config.php';
|
||||
|
||||
// 数据库连接函数
|
||||
function get_db_connection() {
|
||||
global $host, $username, $password, $database;
|
||||
try {
|
||||
$pdo = new PDO("mysql:host=$host;dbname=$database;charset=utf8mb4", $username, $password);
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
return $pdo;
|
||||
} catch(PDOException $e) {
|
||||
log_message("数据库连接失败: " . $e->getMessage(), 'error');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 字段对照表(根据提供的文档)
|
||||
$field_mapping = array(
|
||||
// 题目标题 => array(qid, type)
|
||||
'日期' => array('0AmAeI', 'date'),
|
||||
'单选项' => array('y0Rvqm', 'select'),
|
||||
'图片和附件' => array('FOS5GT', 'file'),
|
||||
'等级' => array('0wJSrH', 'star'),
|
||||
'填写ID' => array('vwS7ci', 'input'),
|
||||
'提交时间' => array('yjbQYS', 'date'),
|
||||
'答题时间(秒)' => array('AA2kq8', 'input'),
|
||||
'车牌号2' => array('7nAOz7', 'input'),
|
||||
'车牌号' => array('NFJDDT', 'input'), // 注意:有两个车牌号字段,这里是第一个
|
||||
'怎么称呼您' => array('eo513g', 'input'),
|
||||
'车型' => array('xKFUcp', 'input'),
|
||||
'车牌号' => array('t2u2i4', 'licensePlate'), // 注意:有两个车牌号字段,这里是第二个
|
||||
'请输入手机号' => array('7jgfmh', 'input'),
|
||||
'是否有车衣' => array('3j6opi', 'select'),
|
||||
'有无自己撸车习惯' => array('ej48lk', 'select'),
|
||||
'撸车经验' => array('1tnljp', 'select'),
|
||||
'洗车频率' => array('x02g35', 'select'),
|
||||
'请选择年龄段' => array('54dbo7', 'select'),
|
||||
'提交者' => array('T9OiCe', 'contact'),
|
||||
'自动编号' => array('rwxgkc', 'autoNum'),
|
||||
'备注内容' => array('r3ft9n', 'input')
|
||||
);
|
||||
|
||||
// 反向映射:qid => array(title, type)
|
||||
$qid_mapping = array();
|
||||
foreach ($field_mapping as $title => $info) {
|
||||
$qid = $info[0];
|
||||
$type = $info[1];
|
||||
$qid_mapping[$qid] = array('title' => $title, 'type' => $type);
|
||||
}
|
||||
|
||||
// 记录日志的函数
|
||||
function log_message($message, $type = 'info') {
|
||||
global $log_file;
|
||||
$timestamp = date('Y-m-d H:i:s');
|
||||
$log_entry = "[$timestamp] [$type] $message\n";
|
||||
file_put_contents($log_file, $log_entry, FILE_APPEND);
|
||||
}
|
||||
|
||||
// 获取请求方法
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
|
||||
// 获取请求数据
|
||||
$request_body = file_get_contents('php://input');
|
||||
|
||||
// 记录所有请求
|
||||
log_message("收到请求 - 方法: $method");
|
||||
log_message("请求内容: $request_body");
|
||||
|
||||
// 处理验证请求
|
||||
if ($method == 'POST') {
|
||||
// 尝试解析请求体
|
||||
$data = json_decode($request_body, true);
|
||||
|
||||
// 如果解析失败,可能是验证请求
|
||||
if ($data === null) {
|
||||
// 返回绑定码进行验证
|
||||
log_message("返回绑定码进行验证");
|
||||
echo json_encode(array('bind_code' => $bind_code));
|
||||
exit;
|
||||
}
|
||||
|
||||
// 处理实际的表单数据
|
||||
log_message("处理表单数据");
|
||||
log_message("原始表单数据: " . print_r($data, true), 'data');
|
||||
|
||||
// 解析WPS表单数据结构
|
||||
$form_data = array(
|
||||
'rid' => isset($data['rid']) ? $data['rid'] : '',
|
||||
'form_id' => isset($data['formId']) ? $data['formId'] : '',
|
||||
'form_title' => isset($data['formTitle']) ? $data['formTitle'] : '',
|
||||
'aid' => isset($data['aid']) ? $data['aid'] : '',
|
||||
'event_ts' => isset($data['eventTs']) ? $data['eventTs'] : 0,
|
||||
'message_ts' => isset($data['messageTs']) ? $data['messageTs'] : 0,
|
||||
'creator_id' => isset($data['creatorId']) ? $data['creatorId'] : '',
|
||||
'creator_name' => isset($data['creatorName']) ? $data['creatorName'] : '',
|
||||
'event' => isset($data['event']) ? $data['event'] : '',
|
||||
'version' => isset($data['version']) ? $data['version'] : 1,
|
||||
'answers' => array()
|
||||
);
|
||||
|
||||
// 解析表单字段
|
||||
if (isset($data['answerContents']) && is_array($data['answerContents'])) {
|
||||
foreach ($data['answerContents'] as $content) {
|
||||
$qid = isset($content['qid']) ? $content['qid'] : '';
|
||||
$type = isset($content['type']) ? $content['type'] : '';
|
||||
$title = isset($content['title']) ? $content['title'] : '';
|
||||
$value = isset($content['value']) ? $content['value'] : '';
|
||||
|
||||
// 将数组值转换为字符串,便于处理
|
||||
if (is_array($value)) {
|
||||
$value = implode(', ', $value);
|
||||
}
|
||||
|
||||
$field = array(
|
||||
'qid' => $qid,
|
||||
'type' => $type,
|
||||
'title' => $title,
|
||||
'value' => $value
|
||||
);
|
||||
|
||||
$form_data['answers'][] = $field;
|
||||
|
||||
// 按标题索引存储,便于直接访问
|
||||
if (!empty($title)) {
|
||||
$form_data['answers_by_title'][$title] = $value;
|
||||
}
|
||||
|
||||
// 按qid索引存储,便于精确访问
|
||||
if (!empty($qid)) {
|
||||
$form_data['answers_by_qid'][$qid] = $value;
|
||||
}
|
||||
|
||||
// 使用字段对照表检查并标准化字段
|
||||
if (!empty($qid) && isset($qid_mapping[$qid])) {
|
||||
$standard_title = $qid_mapping[$qid]['title'];
|
||||
$standard_type = $qid_mapping[$qid]['type'];
|
||||
|
||||
// 存储标准化字段
|
||||
$form_data['standardized_answers'][$standard_title] = array(
|
||||
'qid' => $qid,
|
||||
'type' => $standard_type,
|
||||
'title' => $title, // 保留原始标题
|
||||
'value' => $value,
|
||||
'standard_title' => $standard_title
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log_message("解析后的表单数据: " . print_r($form_data, true), 'data');
|
||||
|
||||
// 在这里可以添加数据处理逻辑,例如:
|
||||
// 1. 将数据保存到数据库
|
||||
// 2. 发送通知
|
||||
// 3. 其他业务逻辑
|
||||
|
||||
// 示例:访问特定字段
|
||||
|
||||
// 通过标题访问
|
||||
if (isset($form_data['answers_by_title']['怎么称呼您'])) {
|
||||
$name = $form_data['answers_by_title']['怎么称呼您'];
|
||||
log_message("客户姓名: $name");
|
||||
}
|
||||
|
||||
// 注意:由于有两个"车牌号"字段,通过标题访问可能获取到任意一个
|
||||
// 建议使用qid或标准化字段访问
|
||||
if (isset($form_data['answers_by_title']['车牌号'])) {
|
||||
$license_plate = $form_data['answers_by_title']['车牌号'];
|
||||
log_message("车牌号(通过标题): $license_plate");
|
||||
}
|
||||
|
||||
// 通过qid精确访问特定的车牌号字段
|
||||
if (isset($form_data['answers_by_qid']['t2u2i4'])) {
|
||||
$license_plate_standard = $form_data['answers_by_qid']['t2u2i4'];
|
||||
log_message("车牌号(通过qid t2u2i4 - 标准): $license_plate_standard");
|
||||
}
|
||||
|
||||
// 通过标准化字段访问
|
||||
if (isset($form_data['standardized_answers']['怎么称呼您'])) {
|
||||
$name_standard = $form_data['standardized_answers']['怎么称呼您']['value'];
|
||||
log_message("客户姓名(标准化): $name_standard");
|
||||
}
|
||||
|
||||
if (isset($form_data['standardized_answers']['车型'])) {
|
||||
$car_model = $form_data['standardized_answers']['车型']['value'];
|
||||
log_message("车型: $car_model");
|
||||
}
|
||||
|
||||
if (isset($form_data['standardized_answers']['请输入手机号'])) {
|
||||
$phone = $form_data['standardized_answers']['请输入手机号']['value'];
|
||||
log_message("手机号: $phone");
|
||||
}
|
||||
|
||||
// 返回成功响应
|
||||
$response = array(
|
||||
'code' => 200,
|
||||
'message' => '数据接收成功',
|
||||
'received_at' => date('Y-m-d H:i:s'),
|
||||
'processed_fields' => count($form_data['answers'])
|
||||
);
|
||||
|
||||
// 将数据存储到数据库
|
||||
store_form_data_to_db($form_data);
|
||||
|
||||
log_message("返回成功响应");
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
// 处理非POST请求
|
||||
log_message("不支持的请求方法: $method", 'error');
|
||||
http_response_code(405); // 方法不允许
|
||||
echo json_encode(array('error' => '只支持POST请求'));
|
||||
}
|
||||
|
||||
log_message("请求处理完成\n" . str_repeat('-', 50) . "\n");
|
||||
|
||||
// 将表单数据存储到数据库
|
||||
function store_form_data_to_db($form_data) {
|
||||
try {
|
||||
$pdo = get_db_connection();
|
||||
if (!$pdo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 创建表(如果不存在)
|
||||
create_wps_form_table($pdo);
|
||||
|
||||
// 准备SQL语句
|
||||
$sql = "INSERT INTO wps_form_submissions (
|
||||
rid, form_id, form_title, creator_id, create_time, update_time,
|
||||
mobile, name, license_plate, date, time_slot, car_type,
|
||||
wash_type, wash_packages, wash_services, additional_services, need_wax,
|
||||
wax_type, cleaning_needs, interior_cleaning, exterior_cleaning, vip_member,
|
||||
vip_number, payment_method, special_requests, technician, status
|
||||
) VALUES (
|
||||
:rid, :form_id, :form_title, :creator_id, :create_time, :update_time,
|
||||
:mobile, :name, :license_plate, :date, :time_slot, :car_type,
|
||||
:wash_type, :wash_packages, :wash_services, :additional_services, :need_wax,
|
||||
:wax_type, :cleaning_needs, :interior_cleaning, :exterior_cleaning, :vip_member,
|
||||
:vip_number, :payment_method, :special_requests, :technician, :status
|
||||
)";
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
|
||||
// 绑定参数
|
||||
$stmt->bindValue(':rid', $form_data['rid']);
|
||||
$stmt->bindValue(':form_id', $form_data['form_id']);
|
||||
$stmt->bindValue(':form_title', $form_data['form_title']);
|
||||
$stmt->bindValue(':creator_id', $form_data['creator_id']);
|
||||
$stmt->bindValue(':create_time', date('Y-m-d H:i:s'));
|
||||
$stmt->bindValue(':update_time', date('Y-m-d H:i:s'));
|
||||
|
||||
// 绑定表单字段值
|
||||
$stmt->bindValue(':mobile', isset($form_data['answers_by_title']['请输入手机号']) ? $form_data['answers_by_title']['请输入手机号'] : '');
|
||||
$stmt->bindValue(':name', isset($form_data['answers_by_title']['怎么称呼您']) ? $form_data['answers_by_title']['怎么称呼您'] : '');
|
||||
|
||||
// 处理车牌号字段(优先使用licensePlate类型的)
|
||||
$license_plate = '';
|
||||
if (isset($form_data['answers_by_qid']['t2u2i4'])) {
|
||||
$license_plate = $form_data['answers_by_qid']['t2u2i4'];
|
||||
} elseif (isset($form_data['answers_by_title']['车牌号'])) {
|
||||
$license_plate = $form_data['answers_by_title']['车牌号'];
|
||||
}
|
||||
$stmt->bindValue(':license_plate', $license_plate);
|
||||
|
||||
// 日期处理
|
||||
$date = isset($form_data['answers_by_title']['日期']) ? $form_data['answers_by_title']['日期'] : '';
|
||||
$stmt->bindValue(':date', $date ? date('Y-m-d', strtotime($date)) : null);
|
||||
|
||||
// 其他字段
|
||||
$stmt->bindValue(':time_slot', isset($form_data['answers_by_title']['时间段']) ? $form_data['answers_by_title']['时间段'] : '');
|
||||
$stmt->bindValue(':car_type', isset($form_data['answers_by_title']['车型']) ? $form_data['answers_by_title']['车型'] : '');
|
||||
$stmt->bindValue(':wash_type', isset($form_data['answers_by_title']['洗车类型']) ? $form_data['answers_by_title']['洗车类型'] : '');
|
||||
$stmt->bindValue(':wash_packages', isset($form_data['answers_by_title']['洗车套餐']) ? $form_data['answers_by_title']['洗车套餐'] : '');
|
||||
$stmt->bindValue(':wash_services', isset($form_data['answers_by_title']['洗车服务']) ? $form_data['answers_by_title']['洗车服务'] : '');
|
||||
$stmt->bindValue(':additional_services', isset($form_data['answers_by_title']['额外服务']) ? $form_data['answers_by_title']['额外服务'] : '');
|
||||
$stmt->bindValue(':need_wax', isset($form_data['answers_by_title']['是否需要打蜡']) ? $form_data['answers_by_title']['是否需要打蜡'] : '');
|
||||
$stmt->bindValue(':wax_type', isset($form_data['answers_by_title']['蜡的类型']) ? $form_data['answers_by_title']['蜡的类型'] : '');
|
||||
$stmt->bindValue(':cleaning_needs', isset($form_data['answers_by_title']['清洁需求']) ? $form_data['answers_by_title']['清洁需求'] : '');
|
||||
$stmt->bindValue(':interior_cleaning', isset($form_data['answers_by_title']['是否需要内饰清洁']) ? $form_data['answers_by_title']['是否需要内饰清洁'] : '');
|
||||
$stmt->bindValue(':exterior_cleaning', isset($form_data['answers_by_title']['是否需要外观清洁']) ? $form_data['answers_by_title']['是否需要外观清洁'] : '');
|
||||
$stmt->bindValue(':vip_member', isset($form_data['answers_by_title']['是否为VIP会员']) ? $form_data['answers_by_title']['是否为VIP会员'] : '');
|
||||
$stmt->bindValue(':vip_number', isset($form_data['answers_by_title']['VIP卡号']) ? $form_data['answers_by_title']['VIP卡号'] : '');
|
||||
$stmt->bindValue(':payment_method', isset($form_data['answers_by_title']['支付方式']) ? $form_data['answers_by_title']['支付方式'] : '');
|
||||
$stmt->bindValue(':special_requests', isset($form_data['answers_by_title']['特殊要求']) ? $form_data['answers_by_title']['特殊要求'] : '');
|
||||
$stmt->bindValue(':technician', isset($form_data['answers_by_title']['指定技师']) ? $form_data['answers_by_title']['指定技师'] : '');
|
||||
$stmt->bindValue(':status', 'pending');
|
||||
|
||||
// 执行SQL
|
||||
$stmt->execute();
|
||||
|
||||
log_message("表单数据成功存储到数据库,插入ID: " . $pdo->lastInsertId());
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
log_message("数据存储失败: " . $e->getMessage(), 'error');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 创建WPS表单数据表
|
||||
function create_wps_form_table($pdo) {
|
||||
try {
|
||||
$sql = "CREATE TABLE IF NOT EXISTS wps_form_submissions (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
rid VARCHAR(50) NOT NULL COMMENT '表单提交ID',
|
||||
form_id VARCHAR(50) NOT NULL COMMENT '表单ID',
|
||||
form_title VARCHAR(255) NOT NULL COMMENT '表单标题',
|
||||
creator_id VARCHAR(50) NOT NULL COMMENT '创建者ID',
|
||||
create_time DATETIME NOT NULL COMMENT '创建时间',
|
||||
update_time DATETIME NOT NULL COMMENT '更新时间',
|
||||
mobile VARCHAR(20) COMMENT '请输入手机号',
|
||||
name VARCHAR(255) COMMENT '怎么称呼您',
|
||||
license_plate VARCHAR(20) COMMENT '车牌号',
|
||||
date DATE COMMENT '日期',
|
||||
time_slot VARCHAR(20) COMMENT '时间段',
|
||||
car_type VARCHAR(50) COMMENT '车型',
|
||||
wash_type VARCHAR(100) COMMENT '洗车类型',
|
||||
wash_packages VARCHAR(255) COMMENT '洗车套餐',
|
||||
wash_services TEXT COMMENT '洗车服务',
|
||||
additional_services TEXT COMMENT '额外服务',
|
||||
need_wax VARCHAR(10) COMMENT '是否需要打蜡',
|
||||
wax_type VARCHAR(50) COMMENT '蜡的类型',
|
||||
cleaning_needs TEXT COMMENT '清洁需求',
|
||||
interior_cleaning VARCHAR(10) COMMENT '是否需要内饰清洁',
|
||||
exterior_cleaning VARCHAR(10) COMMENT '是否需要外观清洁',
|
||||
vip_member VARCHAR(10) COMMENT '是否为VIP会员',
|
||||
vip_number VARCHAR(50) COMMENT 'VIP卡号',
|
||||
payment_method VARCHAR(50) COMMENT '支付方式',
|
||||
special_requests TEXT COMMENT '特殊要求',
|
||||
technician VARCHAR(50) COMMENT '指定技师',
|
||||
status VARCHAR(20) DEFAULT 'pending' COMMENT '状态',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间',
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '记录更新时间',
|
||||
INDEX idx_rid (rid),
|
||||
INDEX idx_license_plate (license_plate),
|
||||
INDEX idx_date (date),
|
||||
INDEX idx_mobile (mobile)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;";
|
||||
|
||||
$pdo->exec($sql);
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
log_message("创建表失败: " . $e->getMessage(), 'error');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
?>
|
||||
Reference in New Issue
Block a user