WebhookDispatchController.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. <?php
  2. namespace App\Module\ThirdParty\Controllers;
  3. use Illuminate\Http\Request;
  4. use Illuminate\Http\JsonResponse;
  5. use Illuminate\Routing\Controller;
  6. use Illuminate\Support\Facades\Log;
  7. use App\Module\ThirdParty\Services\WebhookDispatchService;
  8. /**
  9. * Webhook分发控制器
  10. *
  11. * 实现路由规则:/thirdParty/webhook/{包名}/{Handler路由}
  12. * 负责将Webhook请求分发到对应的包处理器
  13. */
  14. class WebhookDispatchController extends Controller
  15. {
  16. /**
  17. * Webhook分发服务
  18. */
  19. protected WebhookDispatchService $dispatchService;
  20. /**
  21. * 构造函数
  22. */
  23. public function __construct(WebhookDispatchService $dispatchService)
  24. {
  25. $this->dispatchService = $dispatchService;
  26. }
  27. /**
  28. * 处理Webhook请求
  29. *
  30. * @param Request $request 请求对象
  31. * @param string $packageName 包名
  32. * @param string $handlerRoute Handler路由
  33. * @return JsonResponse
  34. */
  35. public function dispatch(Request $request, string $packageName, string $handlerRoute): JsonResponse
  36. {
  37. $requestId = uniqid('webhook_dispatch_', true);
  38. try {
  39. Log::info("Webhook分发开始", [
  40. 'request_id' => $requestId,
  41. 'package_name' => $packageName,
  42. 'handler_route' => $handlerRoute,
  43. 'method' => $request->method(),
  44. 'url' => $request->fullUrl(),
  45. 'ip' => $request->ip(),
  46. ]);
  47. // 验证包名格式
  48. $this->validatePackageName($packageName);
  49. // 验证Handler路由格式
  50. $this->validateHandlerRoute($handlerRoute);
  51. // 分发到具体的处理器
  52. $result = $this->dispatchService->dispatch($packageName, $handlerRoute, $request);
  53. Log::info("Webhook分发成功", [
  54. 'request_id' => $requestId,
  55. 'package_name' => $packageName,
  56. 'handler_route' => $handlerRoute,
  57. 'result' => $result,
  58. ]);
  59. return response()->json([
  60. 'success' => true,
  61. 'data' => $result,
  62. 'request_id' => $requestId,
  63. ]);
  64. } catch (\Exception $e) {
  65. Log::error("Webhook分发失败", [
  66. 'request_id' => $requestId,
  67. 'package_name' => $packageName,
  68. 'handler_route' => $handlerRoute,
  69. 'error' => $e->getMessage(),
  70. 'trace' => $e->getTraceAsString(),
  71. ]);
  72. return response()->json([
  73. 'success' => false,
  74. 'error' => $e->getMessage(),
  75. 'request_id' => $requestId,
  76. ], 400);
  77. }
  78. }
  79. /**
  80. * 验证包名格式
  81. *
  82. * @param string $packageName 包名
  83. * @throws \Exception
  84. */
  85. protected function validatePackageName(string $packageName): void
  86. {
  87. // 包名只能包含字母、数字、下划线
  88. if (!preg_match('/^[a-zA-Z][a-zA-Z0-9_]*$/', $packageName)) {
  89. throw new \Exception("无效的包名格式: {$packageName}");
  90. }
  91. // 包名长度限制
  92. if (strlen($packageName) > 50) {
  93. throw new \Exception("包名长度不能超过50个字符: {$packageName}");
  94. }
  95. }
  96. /**
  97. * 验证Handler路由格式
  98. *
  99. * @param string $handlerRoute Handler路由
  100. * @throws \Exception
  101. */
  102. protected function validateHandlerRoute(string $handlerRoute): void
  103. {
  104. // Handler路由只能包含字母、数字、下划线、斜杠
  105. if (!preg_match('/^[a-zA-Z0-9_\/]+$/', $handlerRoute)) {
  106. throw new \Exception("无效的Handler路由格式: {$handlerRoute}");
  107. }
  108. // Handler路由长度限制
  109. if (strlen($handlerRoute) > 100) {
  110. throw new \Exception("Handler路由长度不能超过100个字符: {$handlerRoute}");
  111. }
  112. // 不能以斜杠开头或结尾
  113. if (str_starts_with($handlerRoute, '/') || str_ends_with($handlerRoute, '/')) {
  114. throw new \Exception("Handler路由不能以斜杠开头或结尾: {$handlerRoute}");
  115. }
  116. }
  117. /**
  118. * 健康检查接口
  119. *
  120. * @return JsonResponse
  121. */
  122. public function health(): JsonResponse
  123. {
  124. return response()->json([
  125. 'success' => true,
  126. 'message' => 'ThirdParty Webhook分发服务运行正常',
  127. 'timestamp' => now()->toISOString(),
  128. ]);
  129. }
  130. /**
  131. * 获取已注册的包列表
  132. *
  133. * @return JsonResponse
  134. */
  135. public function packages(): JsonResponse
  136. {
  137. try {
  138. $packages = $this->dispatchService->getRegisteredPackages();
  139. return response()->json([
  140. 'success' => true,
  141. 'data' => $packages,
  142. ]);
  143. } catch (\Exception $e) {
  144. return response()->json([
  145. 'success' => false,
  146. 'error' => $e->getMessage(),
  147. ], 500);
  148. }
  149. }
  150. }