send(); exit; } return $ctx; } /** * 订阅客资 webhook * POST /v1/open/leads/subscribe * * 入参: * url string 必填,必须 http:// 或 https:// * secret string 可选,HMAC-SHA256 签名秘钥(推送时放 X-CKB-Signature 头) */ public function subscribe() { $ctx = $this->ctx(); $url = trim((string) Request::param('url', '')); $secret = (string) Request::param('secret', ''); if ($url === '') { return ResponseHelper::error('url 不能为空', 400); } // 复用 PlanLeadWebhookService 的校验规则 $err = PlanLeadWebhookService::validateConfig([ 'leadPushWebhookEnabled' => 1, 'leadPushWebhook' => $url, ]); if ($err) { return ResponseHelper::error($err, 400); } $r = OpenPlatformService::saveWebhookSubscription($ctx['planId'], $url, $secret); if (($r['code'] ?? 0) !== 200) { return ResponseHelper::error($r['msg'] ?? 'subscribe failed', $r['code'] ?? 400); } return ResponseHelper::success($r['data'], $r['msg']); } /** * 取消订阅 * POST /v1/open/leads/unsubscribe */ public function unsubscribe() { $ctx = $this->ctx(); $r = OpenPlatformService::removeWebhookSubscription($ctx['planId']); if (($r['code'] ?? 0) !== 200) { return ResponseHelper::error($r['msg'] ?? 'unsubscribe failed', $r['code'] ?? 400); } return ResponseHelper::success($r['data'], $r['msg']); } /** * 查询当前订阅状态 * GET /v1/open/leads/subscription */ public function subscription() { $ctx = $this->ctx(); $r = OpenPlatformService::readWebhookSubscription($ctx['planId']); if (($r['code'] ?? 0) !== 200) { return ResponseHelper::error($r['msg'] ?? 'query failed', $r['code'] ?? 400); } return ResponseHelper::success($r['data'], $r['msg']); } /** * 触发一次测试推送(不写入数据,仅按真实事件链路推一次 ping) * POST /v1/open/leads/test */ public function test() { $ctx = $this->ctx(); // 读最近一条 task_customer 作为样本;若无则返回提示 $sample = \think\Db::name('task_customer') ->where('task_id', $ctx['planId']) ->order('id DESC') ->find(); if (!$sample) { return ResponseHelper::error('计划下还没有客资可供测试推送', 404); } try { PlanLeadWebhookService::dispatch( (int) $ctx['planId'], (int) $sample['id'], PlanLeadWebhookService::EVENT_TAGS_UPDATED ); return ResponseHelper::success([ 'planId' => $ctx['planId'], 'sampleId' => (int) $sample['id'], 'event' => PlanLeadWebhookService::EVENT_TAGS_UPDATED, 'dispatched' => true, ], '测试推送已发出(请到你的接收端确认)'); } catch (\Throwable $e) { return ResponseHelper::error('推送失败:' . $e->getMessage(), 500); } } }