WebhookController.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. <?php
  2. namespace App\Module\OpenAPI\Controllers;
  3. use App\Module\OpenAPI\Models\OpenApiWebhook;
  4. use App\Module\OpenAPI\Services\WebhookService;
  5. use Illuminate\Http\Request;
  6. use Illuminate\Http\JsonResponse;
  7. use Spatie\RouteAttributes\Attributes\Route;
  8. use Spatie\RouteAttributes\Attributes\Prefix;
  9. use Spatie\RouteAttributes\Attributes\Middleware;
  10. /**
  11. * OpenAPI Webhook控制器
  12. *
  13. * 提供Webhook配置和管理的API接口
  14. */
  15. #[Prefix('openapi/webhook')]
  16. #[Middleware(['api', 'openapi.auth'])]
  17. class WebhookController
  18. {
  19. protected WebhookService $webhookService;
  20. public function __construct(WebhookService $webhookService)
  21. {
  22. $this->webhookService = $webhookService;
  23. }
  24. /**
  25. * 获取Webhook列表
  26. *
  27. * @param Request $request
  28. * @return JsonResponse
  29. */
  30. #[Route('GET', '/', name: 'openapi.webhook.index')]
  31. #[Middleware('openapi.scope:WEBHOOK_READ')]
  32. public function index(Request $request): JsonResponse
  33. {
  34. try {
  35. $app = $request->attributes->get('openapi_app');
  36. if (!$app) {
  37. return response()->json([
  38. 'success' => false,
  39. 'message' => '应用信息不存在',
  40. ], 404);
  41. }
  42. $webhooks = OpenApiWebhook::where('app_id', $app->app_id)
  43. ->orderBy('created_at', 'desc')
  44. ->get()
  45. ->map(function ($webhook) {
  46. return [
  47. 'id' => $webhook->id,
  48. 'name' => $webhook->name,
  49. 'url' => $webhook->url,
  50. 'events' => $webhook->events,
  51. 'status' => $webhook->status,
  52. 'status_label' => $webhook->status_label,
  53. 'success_rate' => $webhook->success_rate,
  54. 'total_deliveries' => $webhook->total_deliveries,
  55. 'successful_deliveries' => $webhook->successful_deliveries,
  56. 'failed_deliveries' => $webhook->failed_deliveries,
  57. 'last_success_at' => $webhook->last_success_at,
  58. 'last_failure_at' => $webhook->last_failure_at,
  59. 'created_at' => $webhook->created_at,
  60. ];
  61. });
  62. return response()->json([
  63. 'success' => true,
  64. 'data' => $webhooks,
  65. ]);
  66. } catch (\Exception $e) {
  67. return response()->json([
  68. 'success' => false,
  69. 'message' => '获取Webhook列表失败',
  70. 'error' => $e->getMessage(),
  71. ], 500);
  72. }
  73. }
  74. /**
  75. * 创建Webhook
  76. *
  77. * @param Request $request
  78. * @return JsonResponse
  79. */
  80. #[Route('POST', '/', name: 'openapi.webhook.store')]
  81. #[Middleware('openapi.scope:WEBHOOK_WRITE')]
  82. public function store(Request $request): JsonResponse
  83. {
  84. $startTime = microtime(true);
  85. // 初始化请求日志记录器
  86. $requestLogger = new \App\Module\System\Services\RequestLogger($request);
  87. $requestLogger->setRouter("openapi/webhook/store");
  88. try {
  89. $app = $request->attributes->get('openapi_app');
  90. if (!$app) {
  91. $requestLogger->setError('应用信息不存在');
  92. $requestLogger->setRunTime($startTime);
  93. return response()->json([
  94. 'success' => false,
  95. 'message' => '应用信息不存在',
  96. ], 404);
  97. }
  98. // 使用标准验证系统
  99. $validation = new \App\Module\OpenAPI\Validations\WebhookCreateValidation($request->all());
  100. $validation->validate();
  101. if ($validation->isFail()) {
  102. $requestLogger->setError('数据验证失败: ' . json_encode($validation->getErrors()));
  103. $requestLogger->setRunTime($startTime);
  104. return response()->json([
  105. 'success' => false,
  106. 'message' => '数据验证失败',
  107. 'errors' => $validation->getErrors(),
  108. ], 422);
  109. }
  110. $data = $validation->getSafeData();
  111. // 创建Webhook
  112. $webhook = $this->webhookService->createWebhook($app, $data);
  113. // 记录运行时间
  114. $requestLogger->setRunTime($startTime);
  115. return response()->json([
  116. 'success' => true,
  117. 'message' => 'Webhook创建成功',
  118. 'data' => [
  119. 'id' => $webhook->id,
  120. 'name' => $webhook->name,
  121. 'url' => $webhook->url,
  122. 'events' => $webhook->events,
  123. 'secret' => $webhook->secret,
  124. 'status' => $webhook->status,
  125. 'timeout' => $webhook->timeout,
  126. 'retry_count' => $webhook->retry_count,
  127. 'created_at' => $webhook->created_at,
  128. ],
  129. ]);
  130. } catch (\Exception $e) {
  131. // 记录错误信息和运行时间
  132. $requestLogger->setError($e->getMessage());
  133. $requestLogger->setRunTime($startTime);
  134. return response()->json([
  135. 'success' => false,
  136. 'message' => '创建Webhook失败',
  137. 'error' => $e->getMessage(),
  138. ], 500);
  139. }
  140. }
  141. /**
  142. * 获取Webhook详情
  143. *
  144. * @param Request $request
  145. * @param int $id
  146. * @return JsonResponse
  147. */
  148. #[Route('GET', '/{id}', name: 'openapi.webhook.show')]
  149. #[Middleware('openapi.scope:WEBHOOK_READ')]
  150. public function show(Request $request, int $id): JsonResponse
  151. {
  152. try {
  153. $app = $request->attributes->get('openapi_app');
  154. if (!$app) {
  155. return response()->json([
  156. 'success' => false,
  157. 'message' => '应用信息不存在',
  158. ], 404);
  159. }
  160. $webhook = OpenApiWebhook::where('app_id', $app->app_id)
  161. ->where('id', $id)
  162. ->first();
  163. if (!$webhook) {
  164. return response()->json([
  165. 'success' => false,
  166. 'message' => 'Webhook不存在',
  167. ], 404);
  168. }
  169. return response()->json([
  170. 'success' => true,
  171. 'data' => [
  172. 'id' => $webhook->id,
  173. 'name' => $webhook->name,
  174. 'url' => $webhook->url,
  175. 'events' => $webhook->events,
  176. 'secret' => $webhook->masked_secret,
  177. 'status' => $webhook->status,
  178. 'status_label' => $webhook->status_label,
  179. 'timeout' => $webhook->timeout,
  180. 'retry_count' => $webhook->retry_count,
  181. 'current_retry_count' => $webhook->current_retry_count,
  182. 'total_deliveries' => $webhook->total_deliveries,
  183. 'successful_deliveries' => $webhook->successful_deliveries,
  184. 'failed_deliveries' => $webhook->failed_deliveries,
  185. 'success_rate' => $webhook->success_rate,
  186. 'last_success_at' => $webhook->last_success_at,
  187. 'last_failure_at' => $webhook->last_failure_at,
  188. 'created_at' => $webhook->created_at,
  189. 'updated_at' => $webhook->updated_at,
  190. ],
  191. ]);
  192. } catch (\Exception $e) {
  193. return response()->json([
  194. 'success' => false,
  195. 'message' => '获取Webhook详情失败',
  196. 'error' => $e->getMessage(),
  197. ], 500);
  198. }
  199. }
  200. /**
  201. * 更新Webhook
  202. *
  203. * @param Request $request
  204. * @param int $id
  205. * @return JsonResponse
  206. */
  207. #[Route('PUT', '/{id}', name: 'openapi.webhook.update')]
  208. #[Middleware('openapi.scope:WEBHOOK_WRITE')]
  209. public function update(Request $request, int $id): JsonResponse
  210. {
  211. try {
  212. $app = $request->attributes->get('openapi_app');
  213. if (!$app) {
  214. return response()->json([
  215. 'success' => false,
  216. 'message' => '应用信息不存在',
  217. ], 404);
  218. }
  219. $webhook = OpenApiWebhook::where('app_id', $app->app_id)
  220. ->where('id', $id)
  221. ->first();
  222. if (!$webhook) {
  223. return response()->json([
  224. 'success' => false,
  225. 'message' => 'Webhook不存在',
  226. ], 404);
  227. }
  228. // 使用标准验证系统
  229. $requestData = $request->only(['name', 'url', 'events', 'status', 'timeout', 'retry_count']);
  230. $validation = new \App\Module\OpenAPI\Validations\WebhookUpdateValidation($requestData);
  231. $validation->validate();
  232. if ($validation->isFail()) {
  233. return response()->json([
  234. 'success' => false,
  235. 'message' => '数据验证失败',
  236. 'errors' => $validation->getErrors(),
  237. ], 422);
  238. }
  239. $data = $validation->getSafeData();
  240. // 更新Webhook
  241. $webhook->update(array_filter($data));
  242. return response()->json([
  243. 'success' => true,
  244. 'message' => 'Webhook更新成功',
  245. 'data' => [
  246. 'id' => $webhook->id,
  247. 'name' => $webhook->name,
  248. 'url' => $webhook->url,
  249. 'events' => $webhook->events,
  250. 'status' => $webhook->status,
  251. 'timeout' => $webhook->timeout,
  252. 'retry_count' => $webhook->retry_count,
  253. 'updated_at' => $webhook->updated_at,
  254. ],
  255. ]);
  256. } catch (\Exception $e) {
  257. return response()->json([
  258. 'success' => false,
  259. 'message' => '更新Webhook失败',
  260. 'error' => $e->getMessage(),
  261. ], 500);
  262. }
  263. }
  264. /**
  265. * 删除Webhook
  266. *
  267. * @param Request $request
  268. * @param int $id
  269. * @return JsonResponse
  270. */
  271. #[Route('DELETE', '/{id}', name: 'openapi.webhook.destroy')]
  272. #[Middleware('openapi.scope:WEBHOOK_WRITE')]
  273. public function destroy(Request $request, int $id): JsonResponse
  274. {
  275. try {
  276. $app = $request->attributes->get('openapi_app');
  277. if (!$app) {
  278. return response()->json([
  279. 'success' => false,
  280. 'message' => '应用信息不存在',
  281. ], 404);
  282. }
  283. $webhook = OpenApiWebhook::where('app_id', $app->app_id)
  284. ->where('id', $id)
  285. ->first();
  286. if (!$webhook) {
  287. return response()->json([
  288. 'success' => false,
  289. 'message' => 'Webhook不存在',
  290. ], 404);
  291. }
  292. $webhook->delete();
  293. return response()->json([
  294. 'success' => true,
  295. 'message' => 'Webhook删除成功',
  296. ]);
  297. } catch (\Exception $e) {
  298. return response()->json([
  299. 'success' => false,
  300. 'message' => '删除Webhook失败',
  301. 'error' => $e->getMessage(),
  302. ], 500);
  303. }
  304. }
  305. /**
  306. * 测试Webhook
  307. *
  308. * @param Request $request
  309. * @param int $id
  310. * @return JsonResponse
  311. */
  312. #[Route('POST', '/{id}/test', name: 'openapi.webhook.test')]
  313. #[Middleware('openapi.scope:WEBHOOK_WRITE')]
  314. public function test(Request $request, int $id): JsonResponse
  315. {
  316. try {
  317. $app = $request->attributes->get('openapi_app');
  318. if (!$app) {
  319. return response()->json([
  320. 'success' => false,
  321. 'message' => '应用信息不存在',
  322. ], 404);
  323. }
  324. $webhook = OpenApiWebhook::where('app_id', $app->app_id)
  325. ->where('id', $id)
  326. ->first();
  327. if (!$webhook) {
  328. return response()->json([
  329. 'success' => false,
  330. 'message' => 'Webhook不存在',
  331. ], 404);
  332. }
  333. // 测试Webhook
  334. $result = $this->webhookService->testWebhook($webhook);
  335. return response()->json([
  336. 'success' => true,
  337. 'message' => 'Webhook测试完成',
  338. 'data' => $result,
  339. ]);
  340. } catch (\Exception $e) {
  341. return response()->json([
  342. 'success' => false,
  343. 'message' => 'Webhook测试失败',
  344. 'error' => $e->getMessage(),
  345. ], 500);
  346. }
  347. }
  348. /**
  349. * 重新生成Webhook密钥
  350. *
  351. * @param Request $request
  352. * @param int $id
  353. * @return JsonResponse
  354. */
  355. #[Route('POST', '/{id}/regenerate-secret', name: 'openapi.webhook.regenerate_secret')]
  356. #[Middleware('openapi.scope:WEBHOOK_WRITE')]
  357. public function regenerateSecret(Request $request, int $id): JsonResponse
  358. {
  359. try {
  360. $app = $request->attributes->get('openapi_app');
  361. if (!$app) {
  362. return response()->json([
  363. 'success' => false,
  364. 'message' => '应用信息不存在',
  365. ], 404);
  366. }
  367. $webhook = OpenApiWebhook::where('app_id', $app->app_id)
  368. ->where('id', $id)
  369. ->first();
  370. if (!$webhook) {
  371. return response()->json([
  372. 'success' => false,
  373. 'message' => 'Webhook不存在',
  374. ], 404);
  375. }
  376. // 重新生成密钥
  377. $newSecret = $webhook->regenerateSecret();
  378. return response()->json([
  379. 'success' => true,
  380. 'message' => 'Webhook密钥重新生成成功',
  381. 'data' => [
  382. 'webhook_id' => $webhook->id,
  383. 'secret' => $newSecret,
  384. 'regenerated_at' => now(),
  385. ],
  386. ]);
  387. } catch (\Exception $e) {
  388. return response()->json([
  389. 'success' => false,
  390. 'message' => '重新生成密钥失败',
  391. 'error' => $e->getMessage(),
  392. ], 500);
  393. }
  394. }
  395. }