空间配置
APP
tiangongSpaceID
project_456名称 Codex开发测试群1
外部模式 飞书应用
Webhook
https://feige.3e8.cn/api/webhooks/feishu/tiangong/project_456三方集成配置
API 文档说明
创建/刷新空间
PUT /api/v1/spaces查询通讯录
GET /api/v1/contacts?app=...&space_id=...发送文本消息
POST /api/v1/messages/text发送卡片消息
POST /api/v1/messages/card同步通讯录
POST /api/v1/contact-sync-jobs三方 Webhook
https://feige.3e8.cn/api/webhooks/feishu/tiangong/project_456签名规则
METHOD + "\n" + PATH_WITH_QUERY + "\n" + TIMESTAMP + "\n" + RAW_BODYPHP 示例代码
运行前设置 FEIGE_APP_SECRET=应用管理中该 APP 的 Secret。示例已带入当前空间信息,三方凭证请替换为真实值。
<?php
$baseUrl = 'https://feige.3e8.cn';
$app = 'tiangong';
$spaceId = 'project_456';
function feigeApiSecret(): string
{
$secret = getenv('FEIGE_APP_SECRET') ?: '';
if ($secret === '') {
throw new RuntimeException('未配置 FEIGE_APP_SECRET');
}
return $secret;
}
function feigeRequest(string $method, string $path, ?array $body = null): array
{
global $baseUrl, $app;
$method = strtoupper($method);
$rawBody = $body === null ? '' : json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);
$timestamp = (string) time();
$signingText = implode("\n", [$method, $path, $timestamp, $rawBody]);
$signature = hash_hmac('sha256', $signingText, feigeApiSecret());
$curl = curl_init(rtrim($baseUrl, '/') . $path);
$options = [
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'Content-Type: application/json',
'X-Feige-App: ' . $app,
'X-Feige-Timestamp: ' . $timestamp,
'X-Feige-Signature: ' . $signature,
],
];
if ($body !== null) {
$options[CURLOPT_POSTFIELDS] = $rawBody;
}
curl_setopt_array($curl, $options);
$response = curl_exec($curl);
if ($response === false) {
throw new RuntimeException(curl_error($curl));
}
$status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
curl_close($curl);
return [
'status' => $status,
'body' => json_decode($response, true, 512, JSON_THROW_ON_ERROR),
];
}
// 0. 验证 APP ID、APP Secret 和签名算法
$authResult = feigeRequest('GET', '/api/v1/spaces?app=' . rawurlencode($app));
// 1. 创建或刷新当前空间
$spaceResult = feigeRequest('PUT', '/api/v1/spaces', [
'app' => $app,
'space_id' => $spaceId,
'space_name' => 'Codex开发测试群1',
'external_mode' => 'feishu',
'third_party_key' => [
'app_id' => 'cli_xxx',
'app_secret' => 'your_app_secret',
],
]);
// 2. 同步当前空间通讯录
$syncResult = feigeRequest('POST', '/api/v1/contact-sync-jobs', [
'app' => $app,
'space_id' => $spaceId,
]);
// 3. 查询通讯录,取得飞鸽 contact_id
$contactsResult = feigeRequest('GET', '/api/v1/contacts?' . http_build_query([
'app' => $app,
'space_id' => $spaceId,
'status' => 'active',
]));
$contactId = $contactsResult['body']['data'][0]['contact_id'] ?? null;
// 4. 向联系人发送文本消息
$textResult = feigeRequest('POST', '/api/v1/messages/text', [
'app' => $app,
'space_id' => $spaceId,
'contact_id' => $contactId,
'content' => '这是一条来自 PHP 的飞鸽测试消息',
]);
// 5. 向联系人发送卡片消息
$cardResult = feigeRequest('POST', '/api/v1/messages/card', [
'app' => $app,
'space_id' => $spaceId,
'contact_id' => $contactId,
'content' => [
'card' => [
'schema' => '2.0',
'header' => ['title' => ['tag' => 'plain_text', 'content' => '测试通知']],
'body' => ['elements' => [
['tag' => 'markdown', 'content' => 'PHP 调用飞鸽成功。'],
]],
],
],
]);
print_r([$authResult, $spaceResult, $syncResult, $contactsResult, $textResult, $cardResult]);
支持功能
能力 send_message / receive_message