ip(); // 1. IP 级限流,防止高频恶意提交。 // 短窗口:60 秒内最多 1 次。 $throttleKey = 'wholesale-submit:'.$ip; if (RateLimiter::tooManyAttempts($throttleKey, self::MAX_ATTEMPTS)) { return ApiResponse::error( trans('wholesale::app.shop.too-many-attempts'), [], 429 ); } // 长窗口:24 小时内最多 5 次。 $dailyThrottleKey = 'wholesale-submit-daily:'.$ip; if (RateLimiter::tooManyAttempts($dailyThrottleKey, self::DAILY_MAX_ATTEMPTS)) { return ApiResponse::error( trans('wholesale::app.shop.too-many-attempts'), [], 429 ); } RateLimiter::hit($throttleKey, self::DECAY_SECONDS); RateLimiter::hit($dailyThrottleKey, self::DAILY_DECAY_SECONDS); // 2. 重复提交检测:同一 IP + 邮箱在窗口期内只允许提交一次。 $duplicateKey = 'wholesale-dup:'.md5($ip.'|'.strtolower((string) $request->input('email'))); if (cache()->has($duplicateKey)) { return ApiResponse::error( trans('wholesale::app.shop.duplicate-submission'), [], 429 ); } try { $validated = $request->validate([ 'name' => 'required|string|max:200', 'email' => 'required|email|max:50', 'number' => 'nullable|string|max:300', 'message' => 'nullable|string|max:600', 'country' => 'nullable|string|max:50', 'business_name' => 'nullable|string|max:300', 'business_role' => 'nullable|string|max:50', ]); $message = Message::create([ 'name' => $validated['name'], 'Email' => $validated['email'], 'number' => $validated['number'] ?? null, 'message' => $validated['message'] ?? null, 'country' => $validated['country'] ?? null, 'business_name' => $validated['business_name'] ?? '', 'business_role' => $validated['business_role'] ?? '', ]); // 记录去重标记,窗口期内重复提交会被拒绝。 cache()->put($duplicateKey, $message->message_id, self::DUPLICATE_SECONDS); return ApiResponse::success([ 'id' => $message->message_id, ], trans('wholesale::app.shop.success')); } catch (\Exception $e) { return ApiResponse::error($e->getMessage()); } } }