| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- <?php
- namespace Longyi\Wholesale\Http\Controllers;
- use Illuminate\Http\Request;
- use Illuminate\Routing\Controller;
- use Illuminate\Support\Facades\RateLimiter;
- use Longyi\Wholesale\Helpers\ApiResponse;
- use Longyi\Wholesale\Models\Message;
- class WholesaleController extends Controller
- {
- /**
- * 短窗口:同一 IP 允许的最大提交次数(60 秒内最多 1 次)。
- */
- const MAX_ATTEMPTS = 1;
- /**
- * 短窗口时长(秒)。
- */
- const DECAY_SECONDS = 60;
- /**
- * 长窗口:同一 IP 允许的最大提交次数(24 小时内最多 5 次)。
- */
- const DAILY_MAX_ATTEMPTS = 5;
- /**
- * 长窗口时长(秒):24 小时。
- */
- const DAILY_DECAY_SECONDS = 86400;
- /**
- * 重复提交去重窗口(秒):同一 IP 相同邮箱在该时间内只允许提交一次。
- */
- const DUPLICATE_SECONDS = 60;
- /**
- * Store a new wholesale enquiry.
- *
- * POST /api/wholesale
- */
- public function store(Request $request)
- {
- $ip = $request->ip();
- // 1. IP 级限流,防止高频恶意提交。
- // 短窗口:60 秒内最多 1 次。
- $throttleKey = 'wholesale-submit:'.$ip;
- if (RateLimiter::tooManyAttempts($throttleKey, self::MAX_ATTEMPTS)) {
- return ApiResponse::error(
- 'Too many requests. Please try again later.',
- [],
- 429
- );
- }
- // 长窗口:24 小时内最多 5 次。
- $dailyThrottleKey = 'wholesale-submit-daily:'.$ip;
- if (RateLimiter::tooManyAttempts($dailyThrottleKey, self::DAILY_MAX_ATTEMPTS)) {
- return ApiResponse::error(
- 'Too many requests. Please try again later.',
- [],
- 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(
- 'You have already submitted an enquiry. Please try again later.',
- [],
- 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,
- ], 'Your enquiry has been submitted successfully.');
- } catch (\Exception $e) {
- return ApiResponse::error($e->getMessage());
- }
- }
- }
|