WebhookDispatchController.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  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. $startTime = microtime(true);
  39. // 初始化请求日志记录器
  40. $requestLogger = new \App\Module\System\Services\RequestLogger($request);
  41. $requestLogger->setRouter("webhook/{$packageName}/{$handlerRoute}");
  42. try {
  43. Log::info("Webhook分发开始", [
  44. 'request_id' => $requestId,
  45. 'package_name' => $packageName,
  46. 'handler_route' => $handlerRoute,
  47. 'method' => $request->method(),
  48. 'url' => $request->fullUrl(),
  49. 'ip' => $request->ip(),
  50. ]);
  51. // 验证包名格式
  52. $this->validatePackageName($packageName);
  53. // 验证Handler路由格式
  54. $this->validateHandlerRoute($handlerRoute);
  55. // 分发到具体的处理器
  56. $result = $this->dispatchService->dispatch($packageName, $handlerRoute, $request);
  57. Log::info("Webhook分发成功", [
  58. 'request_id' => $requestId,
  59. 'package_name' => $packageName,
  60. 'handler_route' => $handlerRoute,
  61. 'result' => $result,
  62. ]);
  63. // 记录运行时间
  64. $requestLogger->setRunTime($startTime);
  65. // 构建响应数据
  66. $responseData = [
  67. 'success' => $result['success'],
  68. 'data' => $result['data']??[],
  69. 'request_id' => $requestId,
  70. ];
  71. // 记录JSON响应
  72. $requestLogger->setJsonResponse(json_encode($responseData));
  73. return response()->json($responseData);
  74. } catch (\Exception $e) {
  75. Log::error("Webhook分发失败", [
  76. 'request_id' => $requestId,
  77. 'package_name' => $packageName,
  78. 'handler_route' => $handlerRoute,
  79. 'error' => $e->getMessage(),
  80. 'trace' => $e->getTraceAsString(),
  81. ]);
  82. // 记录错误信息和运行时间
  83. $requestLogger->setError($e->getMessage());
  84. $requestLogger->setRunTime($startTime);
  85. // 构建错误响应数据
  86. $errorResponseData = [
  87. 'success' => false,
  88. 'error' => $e->getMessage(),
  89. 'request_id' => $requestId,
  90. ];
  91. // 记录JSON响应
  92. $requestLogger->setJsonResponse(json_encode($errorResponseData));
  93. return response()->json($errorResponseData, 400);
  94. }
  95. }
  96. /**
  97. * 验证包名格式
  98. *
  99. * @param string $packageName 包名
  100. * @throws \Exception
  101. */
  102. protected function validatePackageName(string $packageName): void
  103. {
  104. // 包名只能包含字母、数字、下划线
  105. if (!preg_match('/^[a-zA-Z][a-zA-Z0-9_]*$/', $packageName)) {
  106. throw new \Exception("无效的包名格式: {$packageName}");
  107. }
  108. // 包名长度限制
  109. if (strlen($packageName) > 50) {
  110. throw new \Exception("包名长度不能超过50个字符: {$packageName}");
  111. }
  112. }
  113. /**
  114. * 验证Handler路由格式
  115. *
  116. * @param string $handlerRoute Handler路由
  117. * @throws \Exception
  118. */
  119. protected function validateHandlerRoute(string $handlerRoute): void
  120. {
  121. // Handler路由只能包含字母、数字、下划线、斜杠
  122. if (!preg_match('/^[a-zA-Z0-9_\/]+$/', $handlerRoute)) {
  123. throw new \Exception("无效的Handler路由格式: {$handlerRoute}");
  124. }
  125. // Handler路由长度限制
  126. if (strlen($handlerRoute) > 100) {
  127. throw new \Exception("Handler路由长度不能超过100个字符: {$handlerRoute}");
  128. }
  129. // 不能以斜杠开头或结尾
  130. if (str_starts_with($handlerRoute, '/') || str_ends_with($handlerRoute, '/')) {
  131. throw new \Exception("Handler路由不能以斜杠开头或结尾: {$handlerRoute}");
  132. }
  133. }
  134. /**
  135. * 健康检查接口
  136. *
  137. * @return JsonResponse
  138. */
  139. public function health(): JsonResponse
  140. {
  141. return response()->json([
  142. 'success' => true,
  143. 'message' => 'ThirdParty Webhook分发服务运行正常',
  144. 'timestamp' => now()->toISOString(),
  145. ]);
  146. }
  147. /**
  148. * 获取已注册的包列表
  149. *
  150. * @return JsonResponse
  151. */
  152. public function packages(): JsonResponse
  153. {
  154. try {
  155. $packages = $this->dispatchService->getRegisteredPackages();
  156. return response()->json([
  157. 'success' => true,
  158. 'data' => $packages,
  159. ]);
  160. } catch (\Exception $e) {
  161. return response()->json([
  162. 'success' => false,
  163. 'error' => $e->getMessage(),
  164. ], 500);
  165. }
  166. }
  167. }