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; } } ?>