This repository has been archived on 2026-06-20. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files

316 lines
13 KiB
PHP
Raw Permalink 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
// WPS表单Webhook接收端点
// 设置响应头
header('Content-Type: application/json; charset=utf-8');
// 绑定码(根据WPS表单要求提供)
$bind_code = '20251205123619412736007';
// 日志文件路径
$log_file = 'log/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;
}
}
// 字段对照表(根据WPS表单实际字段)
$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'),
'车牌号' => array('t2u2i4', 'licensePlate'), // 只使用这个车牌号字段(qid: t2u2i4, type: licensePlate
'车牌号2' => array('7nAOz7', 'input'), // 不使用
'车牌号(普通)' => array('NFJDDT', 'input'), // 不使用
'怎么称呼您' => array('eo513g', 'input'),
'车型' => array('xKFUcp', 'input'),
'请输入手机号' => 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";
// 检查日志目录是否存在,如果不存在则创建
$log_dir = dirname($log_file);
if (!is_dir($log_dir)) {
mkdir($log_dir, 0755, true);
}
file_put_contents($log_file, $log_entry, FILE_APPEND);
}
// 获取请求方法
$method = $_SERVER['REQUEST_METHOD'];
// 获取请求数据
$request_body = file_get_contents('php://input');
// 记录所有请求(仅记录方法)
log_message("收到请求 - 方法: $method");
// 处理验证请求
if ($method == 'POST') {
// 尝试解析请求体
$data = json_decode($request_body, true);
// 如果解析失败,可能是验证请求
if ($data === null) {
// 返回绑定码进行验证
log_message("返回绑定码进行验证");
echo json_encode(array('bind_code' => $bind_code));
exit;
}
// 检查是否是绑定验证请求
if (isset($data['event']) && $data['event'] === 'bind') {
log_message("收到绑定验证请求");
echo json_encode(array('bind_code' => $bind_code));
exit;
}
// 处理实际的表单数据
log_message("处理表单数据");
// 解析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
);
}
}
}
// 在这里可以添加数据处理逻辑,例如:
// 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');
log_message("完整请求内容: $request_body", '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) {
// 在错误时记录完整表单数据
log_message("数据库连接失败,表单数据: " . print_r($form_data, true), 'error');
return false;
}
// 准备SQL语句(只包含实际WPS表单存在的字段)
$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,
has_car_coat, car_wash_habit, car_wash_experience, wash_frequency,
age_group, remarks, auto_number, status, updated_at
) VALUES (
:rid, :form_id, :form_title, :creator_id, :create_time, :update_time,
:mobile, :name, :license_plate, :date, :time_slot, :car_type,
:has_car_coat, :car_wash_habit, :car_wash_experience, :wash_frequency,
:age_group, :remarks, :auto_number, :status, :updated_at
)";
$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(':updated_at', 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']['怎么称呼您'] : '');
// 处理车牌号字段(只使用qid为t2u2i4、type为licensePlate的车牌号字段)
$license_plate = '';
if (isset($form_data['answers_by_qid']['t2u2i4'])) {
$license_plate = $form_data['answers_by_qid']['t2u2i4'];
}
$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(':has_car_coat', isset($form_data['answers_by_title']['是否有车衣']) ? $form_data['answers_by_title']['是否有车衣'] : '');
$stmt->bindValue(':car_wash_habit', isset($form_data['answers_by_title']['有无自己撸车习惯']) ? $form_data['answers_by_title']['有无自己撸车习惯'] : '');
$stmt->bindValue(':car_wash_experience', isset($form_data['answers_by_title']['撸车经验']) ? $form_data['answers_by_title']['撸车经验'] : '');
$stmt->bindValue(':wash_frequency', isset($form_data['answers_by_title']['洗车频率']) ? $form_data['answers_by_title']['洗车频率'] : '');
$stmt->bindValue(':age_group', isset($form_data['answers_by_title']['请选择年龄段']) ? $form_data['answers_by_title']['请选择年龄段'] : '');
$stmt->bindValue(':remarks', isset($form_data['answers_by_title']['备注内容']) ? $form_data['answers_by_title']['备注内容'] : '');
$stmt->bindValue(':auto_number', 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');
log_message("表单数据: " . print_r($form_data, true), 'error');
return false;
}
}
?>