文章目录
WPForms 9 个表单同步飞书多维表格 — 详细实施方案
针对你现有的 9 个 WPForms 表单,基于
wordpress-feishu-php-detail.md文档中的自定义 PHP 方案,给出可直接落地的完整实施指南。
一、你的表单清单梳理
| # | 表单名称 | ID | 类型 | 历史量 | 分布 | 同步策略 |
|---|---|---|---|---|---|---|
| 1 | Whitepaper Download | 19054 | 资料下载 | 2 | 1 | 高优先级(线索获取) |
| 2 | Designer Contact Form | 16313 | 设计师联系 | 3 | 1 | 中优先级 |
| 3 | Become a Dealer | 14859 | 经销商申请 | 129 | 3 | 高优先级(渠道拓展) |
| 4 | Schedule a Meeting | 12665 | 会议预约 | 3 | 4 | 高优先级(销售线索) |
| 5 | Simple Contact for PPC Campaign | 4254 | PPC 联系 | 580 | 7 | 高优先级(付费流量) |
| 6 | Simple Quote | 4232 | 简单报价 | 634 | 1 | 最高优先级(核心转化) |
| 7 | Single Product Quote | 4205 | 单品报价 | 366 | 0 | 最高优先级(核心转化) |
| 8 | Advanced Quote | 4170 | 高级报价 | 497 | 1 | 最高优先级(核心转化) |
| 9 | Simple Contact | 4050 | 简单联系 | 584 | 27 | 高优先级(自然流量) |
核心观察:
- Quote 类表单(Simple / Single Product / Advanced)是核心转化路径,历史数据量最大(合计 1497 条)
- Contact 类表单(Simple Contact / PPC / Designer)是流量承接,合计约 1167 条
- Dealer 和 Meeting 是高价值但低频的 B2B 线索
- Whitepaper Download 是内容营销线索,目前量很小但有增长潜力
二、飞书多维表格设计建议
方案推荐:单表统一管理 + 视图分流
建议只创建 1 张多维表格,通过「视图」和「筛选条件」来管理不同业务线,这样数据集中、便于统计、运维简单。
推荐表结构(列设计)
| 列名 | 类型 | 说明 | 适用表单 |
|---|---|---|---|
| 姓名 | 文本 | 联系人姓名 | 全部 |
| 邮箱 | 邮箱 | 联系邮箱 | 全部 |
| 电话 | 电话 | 联系电话 | 全部 |
| 公司 | 文本 | 公司名称 | 全部 |
| 国家/地区 | 文本 | 客户所在国家 | Dealer / Contact |
| 询盘内容 | 文本 | 留言/需求描述 | Contact / Quote |
| 产品型号 | 文本 | 询价产品型号 | Quote 类 |
| 数量 | 数字 | 询价数量 | Quote 类 |
| 预算金额 | 数字 | 客户预算 | Advanced Quote |
| 期望交货日期 | 日期 | 交货时间要求 | Advanced Quote |
| 业务类型 | 单选 | Dealer / Distributor / Agent | Become a Dealer |
| 会议主题 | 文本 | 预约会议主题 | Schedule a Meeting |
| 期望日期 | 日期 | 期望会议时间 | Schedule a Meeting |
| UTM来源 | 文本 | 广告来源标记 | PPC Campaign |
| 来源表单 | 单选 | Whitepaper / Contact / Quote... | 全部(自动写入) |
| 来源页面 | 超链接 | 提交页面的 URL | 全部(自动写入) |
| 提交时间 | 日期 | 表单提交时间 | 全部(自动写入) |
| 状态 | 单选 | 待跟进 / 已联系 / 已报价 / 已成交 / 无效 | 全部 |
| 客户等级 | 单选 | A级 / B级 / C级 | 全部(可按预算自动判断) |
| 负责人 | 人员 | 销售负责人 | 手动分配 |
注意:飞书多维表格支持「隐藏列」和「视图筛选」。你可以为销售团队创建多个视图:
- 【Quote 报价视图】筛选
来源表单包含 Quote- 【Dealer 渠道视图】筛选
来源表单= Become a Dealer- 【PPC 流量视图】筛选
来源表单= Simple Contact for PPC Campaign- 【我的待跟进】筛选
状态= 待跟进 且负责人= 当前用户
三、前置准备(部署前必须完成)
步骤 1:创建飞书自建应用
- 访问 飞书开放平台 → 开发者后台 → 创建企业自建应用
- 应用名称建议:
WordPress 询盘同步 - 进入「权限管理」,申请以下权限:
bitable:appbitable:record:create
- 点击「发布版本」→ 创建版本 → 申请发布 → 让企业管理员审批通过
步骤 2:获取多维表格标识
- 在飞书创建新的多维表格,命名为
WordPress 询盘总表 - 按上方建议创建列(至少先创建:
姓名、邮箱、电话、来源表单、提交时间、状态) - 打开表格,从 URL 提取:</> PLAINTEXT
https://your-company.feishu.cn/base/BaNkbXXXXXX?table=tblYYYYYYYYApp Token=BaNkbXXXXXXTable ID=tblYYYYYYYY
步骤 3:将应用添加为协作者
多维表格右上角「···」→「添加协作者」→ 搜索你的应用名称 → 权限设为「可编辑」
步骤 4:在 wp-config.php 定义常量
编辑 WordPress 根目录的 wp-config.php,在 /* That's all, stop editing! */ 之前添加:
// 飞书多维表格同步配置
define('FEISHU_APP_ID', 'cli_xxxxxxxxxxxxxxx'); // 你的飞书 App ID
define('FEISHU_APP_SECRET', 'xxxxxxxxxxxxxxxxxxxxxxx'); // 你的飞书 App Secret
define('FEISHU_APP_TOKEN', 'BaNkbXXXXXXXXXXXXXXX'); // 多维表格 App Token
define('FEISHU_TABLE_ID', 'tblYYYYYYYYYYYYYYYY'); // 数据表 Table ID
步骤 5:开启调试日志(首次部署需要)
同样在 wp-config.php 中:
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false); // 不在前台显示,只写入日志
日志位置:wp-content/debug.log
四、代码部署
文件结构
将以下文件上传到你的 WordPress 站点:
wp-content/
└── plugins/
└── feishu-form-sync/
├── feishu-form-sync.php ← 插件入口
├── class-feishu-api.php ← 飞书 API 核心封装
└── handlers/
└── wpforms.php ← WPForms 处理器(已针对你的9个表单定制)
步骤 1:创建插件目录并上传文件
通过 FTP / SFTP / 文件管理器,在 wp-content/plugins/ 下创建 feishu-form-sync 目录及其子目录 handlers。
步骤 2:上传代码文件
三个文件的完整代码见下文 五、完整代码。
步骤 3:激活插件
进入 WordPress 后台 → 插件 → 找到「飞书多维表格询盘同步」→ 点击启用。
五、完整代码
文件 1:feishu-form-sync.php(插件入口)
<?php
/**
* Plugin Name: 飞书多维表格询盘同步
* Plugin URI: https://yoursite.com
* Description: 将 WordPress WPForms 表单数据实时同步到飞书多维表格
* Version: 1.0.0
* Author: Your Name
* Text Domain: feishu-form-sync
*/
if (!defined('ABSPATH')) exit;
// 加载核心 API 类
require_once plugin_dir_path(__FILE__) . 'class-feishu-api.php';
// 加载 WPForms 处理器
require_once plugin_dir_path(__FILE__) . 'handlers/wpforms.php';
文件 2:class-feishu-api.php(飞书 API 封装)
此文件与原文档一致,负责 Token 管理、记录写入、错误处理和备用邮件通知。见原文档或下方完整代码。
<?php
/**
* 飞书多维表格 API 封装类
*/
if (!defined('ABSPATH')) exit;
class Feishu_Bitable_API {
const BASE_URL = 'https://open.feishu.cn/open-apis';
const TOKEN_TRANSIENT = 'feishu_tenant_access_token';
public static function get_access_token() {
$cached_token = get_transient(self::TOKEN_TRANSIENT);
if (!empty($cached_token)) {
return $cached_token;
}
if (!defined('FEISHU_APP_ID') || !defined('FEISHU_APP_SECRET')) {
self::log('错误:未定义 FEISHU_APP_ID 或 FEISHU_APP_SECRET 常量');
return false;
}
$response = wp_remote_post(self::BASE_URL . '/auth/v3/tenant_access_token/internal', [
'headers' => ['Content-Type' => 'application/json; charset=utf-8'],
'body' => wp_json_encode([
'app_id' => FEISHU_APP_ID,
'app_secret' => FEISHU_APP_SECRET,
]),
'timeout' => 15,
'sslverify' => true,
]);
if (is_wp_error($response)) {
self::log('获取 Token 网络错误: ' . $response->get_error_message());
return false;
}
$http_code = wp_remote_retrieve_response_code($response);
if ($http_code !== 200) {
self::log("获取 Token HTTP 错误,状态码: {$http_code}");
return false;
}
$body = json_decode(wp_remote_retrieve_body($response), true);
if (empty($body['tenant_access_token'])) {
self::log('获取 Token 失败,飞书返回: ' . wp_json_encode($body, JSON_UNESCAPED_UNICODE));
return false;
}
set_transient(self::TOKEN_TRANSIENT, $body['tenant_access_token'], 90 * MINUTE_IN_SECONDS);
self::log('成功获取新 Token,已缓存 90 分钟');
return $body['tenant_access_token'];
}
public static function refresh_token() {
delete_transient(self::TOKEN_TRANSIENT);
return self::get_access_token();
}
public static function create_record(array $fields, string $app_token = '', string $table_id = '') {
if (empty($app_token)) {
$app_token = defined('FEISHU_APP_TOKEN') ? FEISHU_APP_TOKEN : '';
}
if (empty($table_id)) {
$table_id = defined('FEISHU_TABLE_ID') ? FEISHU_TABLE_ID : '';
}
if (empty($app_token) || empty($table_id)) {
$error = '错误:App Token 或 Table ID 为空';
self::log($error);
return ['success' => false, 'record_id' => null, 'error' => $error];
}
$token = self::get_access_token();
if (!$token) {
return ['success' => false, 'record_id' => null, 'error' => '无法获取飞书访问令牌'];
}
$url = self::BASE_URL . "/bitable/v1/apps/{$app_token}/tables/{$table_id}/records";
$response = wp_remote_post($url, [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'application/json; charset=utf-8',
],
'body' => wp_json_encode(['fields' => $fields], JSON_UNESCAPED_UNICODE),
'timeout' => 15,
]);
if (is_wp_error($response)) {
$error = '网络请求失败: ' . $response->get_error_message();
self::log($error);
return ['success' => false, 'record_id' => null, 'error' => $error];
}
$http_code = wp_remote_retrieve_response_code($response);
$body = json_decode(wp_remote_retrieve_body($response), true);
if ($http_code === 401 || (isset($body['code']) && in_array($body['code'], [99991663, 99991661]))) {
self::log('Token 已失效,正在刷新并重试...');
$token = self::refresh_token();
if (!$token) {
return ['success' => false, 'record_id' => null, 'error' => 'Token 刷新失败'];
}
$response = wp_remote_post($url, [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'application/json; charset=utf-8',
],
'body' => wp_json_encode(['fields' => $fields], JSON_UNESCAPED_UNICODE),
'timeout' => 15,
]);
$body = json_decode(wp_remote_retrieve_body($response), true);
}
if (isset($body['code']) && $body['code'] === 0) {
$record_id = $body['data']['record']['record_id'] ?? null;
self::log("写入成功,Record ID: {$record_id}");
return ['success' => true, 'record_id' => $record_id, 'error' => null];
}
$error_msg = sprintf(
'写入失败,code: %s,msg: %s',
$body['code'] ?? 'unknown',
$body['msg'] ?? 'unknown'
);
self::log($error_msg . ',字段数据: ' . wp_json_encode($fields, JSON_UNESCAPED_UNICODE));
return ['success' => false, 'record_id' => null, 'error' => $error_msg];
}
public static function send_fallback_notification(array $fields, string $error, string $form_name = '') {
$admin_email = get_option('admin_email');
if (empty($admin_email)) return;
$subject = sprintf('[%s] 飞书同步失败 — 询盘数据需手动处理', get_bloginfo('name'));
$body = "飞书多维表格同步失败,请手动录入以下询盘数据:\n\n";
$body .= "错误原因:{$error}\n";
if ($form_name) {
$body .= "表单名称:{$form_name}\n";
}
$body .= "时 间:" . current_time('Y-m-d H:i:s') . "\n\n";
$body .= "---询盘数据---\n";
foreach ($fields as $key => $value) {
if (is_array($value)) {
$value = implode(', ', $value);
}
$body .= "{$key}:{$value}\n";
}
wp_mail($admin_email, $subject, $body);
self::log("已发送备用邮件通知至:{$admin_email}");
}
public static function log(string $message) {
if (defined('WP_DEBUG') && WP_DEBUG && defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
error_log('[飞书同步] ' . $message);
}
}
}
文件 3:handlers/wpforms.php(核心 — 已针对你的 9 个表单定制)
<?php
/**
* WPForms → 飞书多维表格
*
* 已针对以下 9 个表单定制:
* 19054 Whitepaper Download
* 16313 Designer Contact Form
* 14859 Become a Dealer
* 12665 Schedule a Meeting
* 4254 Simple Contact for PPC Campaign
* 4232 Simple Quote
* 4205 Single Product Quote
* 4170 Advanced Quote
* 4050 Simple Contact
*
* 钩子:wpforms_process_complete
*/
if (!defined('ABSPATH')) exit;
add_action('wpforms_process_complete', 'feishu_sync_wpforms_submission', 10, 4);
function feishu_sync_wpforms_submission($fields, $entry, $form_data, $entry_id) {
$form_id = (int) $form_data['id'];
$form_title = sanitize_text_field($form_data['settings']['form_title'] ?? "Form #{$form_id}");
// ─── 1. 只处理指定的 9 个表单 ───────────────────────────────────────
$allowed_form_ids = [19054, 16313, 14859, 12665, 4254, 4232, 4205, 4170, 4050];
if (!in_array($form_id, $allowed_form_ids, true)) {
return;
}
// ─── 2. 调试模式:首次部署时开启,记录字段结构到日志 ──────────────
// 开启 WP_DEBUG 后,每次提交会在 wp-content/debug.log 中输出字段结构
// 你可以根据日志中的 id / name 来精确配置下方的字段映射
if (defined('WP_DEBUG') && WP_DEBUG) {
Feishu_Bitable_API::log("[WPForms Debug] Form ID: {$form_id}, Title: {$form_title}");
Feishu_Bitable_API::log("[WPForms Debug] 字段结构: " . wp_json_encode(
array_map(fn($f) => [
'id' => $f['id'] ?? '',
'type' => $f['type'] ?? '',
'name' => $f['name'] ?? '',
'value' => $f['value'] ?? '',
], $fields),
JSON_UNESCAPED_UNICODE
));
}
// ─── 3. 辅助函数:按标签名查找字段值 ────────────────────────────────
// WPForms 的 $fields[字段ID] 结构包含 'name'(标签)和 'value'(值)
// 先通过标签名匹配,适配大多数场景;如需更精确,可改用字段 ID
$get_by_label = function(string $label, string $default = '') use ($fields): string {
foreach ($fields as $field) {
if (strcasecmp(trim($field['name'] ?? ''), trim($label)) === 0) {
return sanitize_text_field($field['value'] ?? $default);
}
}
return $default;
};
$get_textarea_by_label = function(string $label, string $default = '') use ($fields): string {
foreach ($fields as $field) {
if (strcasecmp(trim($field['name'] ?? ''), trim($label)) === 0) {
return sanitize_textarea_field($field['value'] ?? $default);
}
}
return $default;
};
$get_email_by_label = function(string $label, string $default = '') use ($fields): string {
foreach ($fields as $field) {
if (strcasecmp(trim($field['name'] ?? ''), trim($label)) === 0) {
return sanitize_email($field['value'] ?? $default);
}
}
return $default;
};
// ─── 4. 按表单 ID 分流映射 ───────────────────────────────────────────
$feishu_fields = [];
switch ($form_id) {
// ───────────────────────────────────────────────────────────────
// 1. Whitepaper Download(资料下载)
// ───────────────────────────────────────────────────────────────
case 19054:
$feishu_fields = [
'姓名' => $get_by_label('Name'),
'邮箱' => $get_email_by_label('Email'),
'公司' => $get_by_label('Company'),
'职位' => $get_by_label('Job Title'),
'需求类型' => $get_by_label('Interested In'),
'来源表单' => 'Whitepaper Download',
'来源页面' => sanitize_url($_SERVER['HTTP_REFERER'] ?? ''),
'提交时间' => time() * 1000,
'状态' => '待发送资料',
];
break;
// ───────────────────────────────────────────────────────────────
// 2. Designer Contact Form(设计师联系)
// ───────────────────────────────────────────────────────────────
case 16313:
$feishu_fields = [
'姓名' => $get_by_label('Name'),
'邮箱' => $get_email_by_label('Email'),
'电话' => $get_by_label('Phone'),
'公司' => $get_by_label('Company'),
'询盘内容' => $get_textarea_by_label('Message'),
'来源表单' => 'Designer Contact Form',
'来源页面' => sanitize_url($_SERVER['HTTP_REFERER'] ?? ''),
'提交时间' => time() * 1000,
'状态' => '待跟进',
];
break;
// ───────────────────────────────────────────────────────────────
// 3. Become a Dealer(经销商申请)
// ───────────────────────────────────────────────────────────────
case 14859:
$feishu_fields = [
'姓名' => $get_by_label('Name'),
'邮箱' => $get_email_by_label('Email'),
'电话' => $get_by_label('Phone'),
'公司' => $get_by_label('Company Name'),
'国家/地区'=> $get_by_label('Country'),
'询盘内容' => $get_textarea_by_label('Message'),
'业务类型' => $get_by_label('Business Type'),
'来源表单' => 'Become a Dealer',
'来源页面' => sanitize_url($_SERVER['HTTP_REFERER'] ?? ''),
'提交时间' => time() * 1000,
'状态' => '待审核',
];
break;
// ───────────────────────────────────────────────────────────────
// 4. Schedule a Meeting(会议预约)
// ───────────────────────────────────────────────────────────────
case 12665:
$meeting_date_raw = $get_by_label('Preferred Date');
$feishu_fields = [
'姓名' => $get_by_label('Name'),
'邮箱' => $get_email_by_label('Email'),
'电话' => $get_by_label('Phone'),
'公司' => $get_by_label('Company'),
'期望日期' => !empty($meeting_date_raw) ? strtotime($meeting_date_raw) * 1000 : null,
'会议主题' => $get_textarea_by_label('Meeting Topic'),
'来源表单' => 'Schedule a Meeting',
'来源页面' => sanitize_url($_SERVER['HTTP_REFERER'] ?? ''),
'提交时间' => time() * 1000,
'状态' => '待安排',
];
break;
// ───────────────────────────────────────────────────────────────
// 5. Simple Contact for PPC Campaign(PPC 联系)
// ───────────────────────────────────────────────────────────────
case 4254:
$feishu_fields = [
'姓名' => $get_by_label('Name'),
'邮箱' => $get_email_by_label('Email'),
'电话' => $get_by_label('Phone'),
'询盘内容' => $get_textarea_by_label('Message'),
'UTM来源' => $get_by_label('UTM Source'), // 若表单中有隐藏字段传 UTM
'来源表单' => 'PPC Campaign',
'来源页面' => sanitize_url($_SERVER['HTTP_REFERER'] ?? ''),
'提交时间' => time() * 1000,
'状态' => '待跟进',
'客户等级' => 'B 级(付费流量)',
];
break;
// ───────────────────────────────────────────────────────────────
// 6. Simple Quote(简单报价)
// ───────────────────────────────────────────────────────────────
case 4232:
$feishu_fields = [
'姓名' => $get_by_label('Name'),
'邮箱' => $get_email_by_label('Email'),
'电话' => $get_by_label('Phone'),
'公司' => $get_by_label('Company'),
'产品型号' => $get_by_label('Product'),
'数量' => is_numeric($get_by_label('Quantity')) ? floatval($get_by_label('Quantity')) : null,
'询盘内容' => $get_textarea_by_label('Message'),
'来源表单' => 'Simple Quote',
'来源页面' => sanitize_url($_SERVER['HTTP_REFERER'] ?? ''),
'提交时间' => time() * 1000,
'状态' => '待报价',
];
break;
// ───────────────────────────────────────────────────────────────
// 7. Single Product Quote(单品报价)
// ───────────────────────────────────────────────────────────────
case 4205:
$feishu_fields = [
'姓名' => $get_by_label('Name'),
'邮箱' => $get_email_by_label('Email'),
'电话' => $get_by_label('Phone'),
'公司' => $get_by_label('Company'),
'产品型号' => $get_by_label('Product Model'),
'数量' => is_numeric($get_by_label('Quantity')) ? floatval($get_by_label('Quantity')) : null,
'来源表单' => 'Single Product Quote',
'来源页面' => sanitize_url($_SERVER['HTTP_REFERER'] ?? ''),
'提交时间' => time() * 1000,
'状态' => '待报价',
];
break;
// ───────────────────────────────────────────────────────────────
// 8. Advanced Quote(高级报价)
// ───────────────────────────────────────────────────────────────
case 4170:
$delivery_raw = $get_by_label('Delivery Date');
$budget_raw = $get_by_label('Budget');
$feishu_fields = [
'姓名' => $get_by_label('Name'),
'邮箱' => $get_email_by_label('Email'),
'电话' => $get_by_label('Phone'),
'公司' => $get_by_label('Company'),
'产品型号' => $get_by_label('Product'),
'数量' => is_numeric($get_by_label('Quantity')) ? floatval($get_by_label('Quantity')) : null,
'预算金额' => is_numeric($budget_raw) ? floatval($budget_raw) : null,
'期望交货日期' => !empty($delivery_raw) ? strtotime($delivery_raw) * 1000 : null,
'询盘内容' => $get_textarea_by_label('Message'),
'来源表单' => 'Advanced Quote',
'来源页面' => sanitize_url($_SERVER['HTTP_REFERER'] ?? ''),
'提交时间' => time() * 1000,
'状态' => '待报价',
];
// 根据预算自动判断客户等级
if (!empty($feishu_fields['预算金额'])) {
$budget = $feishu_fields['预算金额'];
$feishu_fields['客户等级'] = match(true) {
$budget >= 100000 => 'A 级(高价值)',
$budget >= 10000 => 'B 级(中等)',
default => 'C 级(普通)',
};
}
break;
// ───────────────────────────────────────────────────────────────
// 9. Simple Contact(简单联系)
// ───────────────────────────────────────────────────────────────
case 4050:
$feishu_fields = [
'姓名' => $get_by_label('Name'),
'邮箱' => $get_email_by_label('Email'),
'电话' => $get_by_label('Phone'),
'询盘内容' => $get_textarea_by_label('Message'),
'来源表单' => 'Simple Contact',
'来源页面' => sanitize_url($_SERVER['HTTP_REFERER'] ?? ''),
'提交时间' => time() * 1000,
'状态' => '待跟进',
];
break;
}
// ─── 5. 过滤空值(避免覆盖飞书默认值) ──────────────────────────────
$feishu_fields = array_filter($feishu_fields, fn($v) => $v !== '' && $v !== null && $v !== []);
// ─── 6. 防重复提交(10 分钟窗口) ───────────────────────────────────
$dedup_key = 'feishu_dedup_' . md5(
($feishu_fields['邮箱'] ?? '') . '|' .
($feishu_fields['询盘内容'] ?? '') . '|' .
($feishu_fields['姓名'] ?? '') . '|' .
$form_id
);
if (get_transient($dedup_key)) {
Feishu_Bitable_API::log("重复提交已拦截,Form: {$form_id}");
return;
}
set_transient($dedup_key, 1, 10 * MINUTE_IN_SECONDS);
// ─── 7. 写入飞书多维表格 ────────────────────────────────────────────
$result = Feishu_Bitable_API::create_record($feishu_fields);
if (!$result['success']) {
Feishu_Bitable_API::send_fallback_notification(
$feishu_fields,
$result['error'],
"WPForms: {$form_title}"
);
}
}
六、字段映射校准指南(关键步骤)
上方的 wpforms.php 使用了按标签名匹配的策略,这种方式在字段标签是标准英文时(如 Name / Email / Phone)可以直接工作。但如果你的表单使用了自定义标签名,就需要校准。
如何获取准确的字段信息
方法一:查看 debug.log(推荐)
- 确保
wp-config.php中WP_DEBUG_LOG为true - 在浏览器中提交一次测试数据
- 查看
wp-content/debug.log,你会看到类似:
[飞书同步] [WPForms Debug] Form ID: 19054, Title: Whitepaper Download
[飞书同步] [WPForms Debug] 字段结构: [
{"id":0,"type":"name","name":"Name","value":"Test User"},
{"id":1,"type":"email","name":"Email","value":"test@example.com"},
{"id":2,"type":"text","name":"Company","value":"ABC Corp"},
...
]
方法二:在 WPForms 后台查看字段 ID
- 进入 WPForms → 选择一个表单 → 编辑
- 点击任意字段,右侧面板会显示 Field ID
- 记录下每个字段的 ID 数字
如果需要改用字段 ID 精确映射
在 wpforms.php 中,将 $get_by_label('Name') 替换为:
sanitize_text_field($fields[1]['value'] ?? ''), // 假设 Name 的字段 ID 是 1
建议先用标签名匹配快速上线,后续再逐步优化为字段 ID 映射,以提高稳定性。
七、测试验证流程
步骤 1:测试 Token 获取
创建一个临时测试文件 wp-content/plugins/feishu-form-sync/test.php:
<?php
define('ABSPATH', dirname(dirname(dirname(dirname(__FILE__)))) . '/');
require_once ABSPATH . 'wp-load.php';
require_once plugin_dir_path(__FILE__) . 'class-feishu-api.php';
$test_fields = [
'姓名' => '测试用户',
'邮箱' => 'test@example.com',
'电话' => '13800138000',
'询盘内容' => '这是一条测试数据,请忽略',
'来源表单' => '系统测试',
'提交时间' => time() * 1000,
'状态' => '测试',
];
$result = Feishu_Bitable_API::create_record($test_fields);
echo '<pre>';
echo '写入结果: ' . ($result['success'] ? '✅ 成功' : '❌ 失败') . "\n";
echo 'Record ID: ' . ($result['record_id'] ?? 'N/A') . "\n";
echo '错误信息: ' . ($result['error'] ?? '无') . "\n";
echo '</pre>';
通过浏览器访问:https://yoursite.com/wp-content/plugins/feishu-form-sync/test.php
- 若显示 ✅ 成功 且飞书表格出现测试数据 → Token 和表格配置正确
- 若显示错误 → 对照下方常见错误码排查
测试完毕后务必删除 test.php 文件!
步骤 2:逐表单提交测试
对每个表单提交一条测试数据,检查:
debug.log中是否记录了字段结构- 飞书表格中是否出现了对应记录
- 各字段是否正确映射(姓名、邮箱、来源表单等)
步骤 3:关闭调试模式(生产环境)
测试全部通过后,将 wp-config.php 中的调试常量改为:
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false);
define('WP_DEBUG_DISPLAY', false);
八、常见错误码速查
| 错误码 | 含义 | 解决方法 |
|---|---|---|
99991663 |
Token 无效或过期 | 删除 Transient 缓存,检查 App ID / Secret |
99991661 |
Token 格式错误 | 确认请求头格式:Bearer {token} |
1254200 |
找不到多维表格 | 检查 App Token 是否正确,应用是否为协作者 |
1254203 |
无写入权限 | 在多维表格中将应用权限升级为「编辑」 |
1254302 |
字段名不存在 | 检查飞书列名与代码中是否完全一致(包括空格) |
1254304 |
字段值类型错误 | 对照字段类型对照表检查传参格式 |
1254800 |
表格行数超限 | 单表上限 50,000 行,需归档旧数据 |
九、进阶优化建议
1. 历史数据批量导入
如果你希望把已有的 2000+ 条历史数据也导入飞书,可以使用 WPForms 的 Entries 导出功能(需 Pro 版),导出 CSV 后通过飞书「导入数据」功能批量上传。
2. 按来源页面区分渠道质量
代码中已经自动记录了 来源页面,你可以在飞书中:
- 创建「来源域名」列,用公式提取 URL 中的域名
- 统计不同页面的转化率
3. 自动化通知
在飞书多维表格中设置「自动化流程」:
- 当新记录创建时 → 发送飞书消息给销售群
- 当
状态变更为「待报价」超过 24 小时 → 发送提醒给负责人
4. 多表分流(未来扩展)
如果业务增长后单表太乱,可以修改代码实现多表分流:
// 在 wpforms.php 的 switch 中,为 Quote 类表单指定不同的 App Token / Table ID
$result = Feishu_Bitable_API::create_record(
$feishu_fields,
'另一个AppToken', // 报价专用表格
'另一个TableID'
);
十、部署检查清单
- 飞书自建应用已创建并发布审批通过
- 已申请
bitable:app和bitable:record:create权限 - 已获取 App Token 和 Table ID
- 已将应用添加为多维表格协作者(编辑权限)
wp-config.php中已定义FEISHU_APP_ID、FEISHU_APP_SECRET、FEISHU_APP_TOKEN、FEISHU_TABLE_ID- 已开启
WP_DEBUG和WP_DEBUG_LOG - 已上传插件文件到
wp-content/plugins/feishu-form-sync/ - 已在 WordPress 后台激活插件
- 已通过
test.php验证 API 连通性 - 已对每个表单提交测试数据并验证字段映射
- 已关闭
WP_DEBUG_LOG(生产环境) - 已删除
test.php
基于 wordpress-feishu-php-detail.md 方案 B(WPForms)定制,适用 WPForms 1.8.x+
评论