preverus/preverus-laravel
Composer 安装命令:
composer require preverus/preverus-laravel
包简介
Laravel integration for Preverus hosted-script form protection and backend fraud decisions.
README 文档
README
Laravel integration for Preverus hosted-script form protection and backend fraud decisions.
This package is designed for Laravel, PHP, and server-rendered applications that do not use the JavaScript npm SDK. It pairs the hosted Preverus browser script with trusted Laravel backend enforcement.
Install
composer require preverus/preverus-laravel php artisan vendor:publish --tag=preverus-config
Add keys to .env:
PREVERUS_BROWSER_KEY=pk_live_xxx PREVERUS_SERVER_KEY=sk_live_xxx
Use two keys in production:
- Browser key: publishable, used by the hosted script.
- Server key: private, used only by Laravel for decisions and lookups.
Never put your server key in Blade, JavaScript, or public config.
Quick Start
Add the hosted script to your main layout:
@preverusScript(['auto' => true, 'trackForms' => true])
Protect a server-rendered form:
<form method="POST" action="{{ route('register') }}" data-preverus-action="signup"> @csrf <input name="email" type="email"> <button type="submit">Create account</button> </form>
Before submit, the hosted script attaches hidden fields:
preverus_fingerprint
preverus_visitor_id
preverus_risk_session_token
preverus_browser_session_event_id
Evaluate risk in your controller:
use Illuminate\Http\Request; use Preverus\Laravel\Facades\Preverus; public function register(Request $request) { $decision = Preverus::evaluate($request, [ 'event_type' => 'signup', 'user_id' => $request->input('user_id'), 'metadata' => [ 'email' => $request->input('email'), ], ]); if ($decision->isBlock()) { abort(403, 'Unable to create account.'); } if ($decision->isReview()) { return redirect()->route('verify'); } // Continue registration. }
No try/catch is required for normal use. If Preverus is unavailable, the package returns a fallback DecisionResult based on your configured failure mode.
Failure Modes
Failure mode is optional. If you do not configure it, the package defaults to open so your Laravel app keeps working if Preverus is temporarily unreachable.
Optional .env value:
PREVERUS_FAILURE_MODE=open
Supported modes:
open -> allow if Preverus is unavailable
review -> send to step-up/manual review if Preverus is unavailable
closed -> block if Preverus is unavailable
Recommended defaults:
- Use
openfor signup, login, and checkout if uptime/revenue continuity is the priority. - Use
reviewfor withdrawals, payouts, password resets, and payment changes. - Use
closedonly when your business explicitly wants to stop the action during vendor/API failure.
You can override per call:
$decision = Preverus::evaluate($request, [ 'event_type' => 'withdraw', 'user_id' => $user->id, 'failure_mode' => 'review', ]);
Fallback decisions are still valid objects:
$decision->isFallback(); $decision->failureReason(); $decision->recommendedAction();
Retries And Timeouts
Defaults are short so your Laravel request does not hang:
PREVERUS_TIMEOUT_MS=1500 PREVERUS_CONNECT_TIMEOUT_MS=500 PREVERUS_RETRIES=2 PREVERUS_RETRY_DELAY_MS=150 PREVERUS_MAX_RETRY_DELAY_MS=1000
The underlying PHP client retries transient network failures and retryable HTTP statuses:
408, 409, 425, 429, 500, 502, 503, 504
It does not retry validation or auth failures like 400, 401, 403, or 422.
The Laravel wrapper automatically sends X-Idempotency-Key for decision and event POSTs.
Circuit Breaker
The package includes a simple cache-backed circuit breaker. If repeated Preverus calls fail, Laravel temporarily stops making outbound calls and immediately returns fallback decisions.
PREVERUS_CIRCUIT_BREAKER=true PREVERUS_CIRCUIT_FAILURE_THRESHOLD=5 PREVERUS_CIRCUIT_COOLDOWN_SECONDS=30
This protects merchant apps from slow request chains during an outage.
What evaluate() Sends
Preverus::evaluate($request, [...]) automatically extracts:
preverus_fingerprint
preverus_visitor_id
preverus_risk_session_token
preverus_browser_session_event_id
request IP
user agent
accept language
current URL
referrer
It sends preverus_visitor_id as X-Visitor-ID when available.
It sends preverus_risk_session_token as risk_session_token when available. This is preferred because it links the trusted backend action to the stored browser session collected moments earlier.
Sensitive Actions
Use synchronous decisions for actions where your app needs an immediate allow/review/block answer:
$decision = Preverus::evaluate($request, [ 'event_type' => 'withdraw', 'user_id' => $user->id, 'metadata' => [ 'payment_address' => $request->input('payment_address'), ], 'failure_mode' => 'review', ]); if ($decision->isBlock()) { abort(403); } if ($decision->isReview()) { return redirect()->route('withdraw.review'); }
Good event names include:
signup
login
checkout
password_reset
payout
withdraw
payment_change
account_update
Middleware
For simple routes, you can use middleware:
Route::post('/withdraw', WithdrawController::class) ->middleware('preverus:withdraw,withdraw.review');
The first argument is the event_type. The second optional argument is a route name for review outcomes.
Controller-level usage is still recommended for complex flows because every application handles step-up and manual review differently.
Queue Non-Blocking Events
Use queued events for telemetry that does not need to block the user:
Preverus::dispatchEvent($request, [ 'event_type' => 'profile_update', 'user_id' => $user->id, 'metadata' => [ 'email' => $user->email, ], ]);
Queue config:
PREVERUS_QUEUE_EVENTS=true PREVERUS_QUEUE_CONNECTION=redis PREVERUS_QUEUE=default
Queued event jobs retry with backoff:
10s, 30s, 120s, 300s
Lookups
Visitor lookup:
$visitor = Preverus::lookupVisitor(visitorId: 'v_abc123'); $visitor = Preverus::lookupVisitor(fingerprint: 'fp_hash');
Metadata lookup:
$metadata = Preverus::lookupMetadata('email', 'person@example.com');
Use lookups for investigations and added context. Do not use lookups as the only enforcement decision for sensitive actions; call evaluate() for final allow/review/block guidance.
Webhook Verification
use Illuminate\Http\Request; use Preverus\Laravel\Facades\Preverus; Route::post('/preverus/webhook', function (Request $request) { if (!Preverus::verifyWebhook($request, config('services.preverus.webhook_secret'))) { abort(400, 'Invalid webhook signature'); } $payload = $request->json()->all(); // Store $payload['id'] or X-Fraud-Webhook-Id for idempotency. return response()->noContent(); });
Webhook delivery is at-least-once. Always dedupe by X-Fraud-Webhook-Id or payload id.
For a complete verify-parse-dispatch flow:
Route::post('/preverus/webhook', function (Request $request) { Preverus::handleWebhook( $request, config('services.preverus.webhook_secret'), [ 'decision.high_risk' => function ($event) { // Open a case, notify ops, or hold the account action. }, '*' => function ($event) { // Optional catch-all handler. }, ], function ($event) { return DB::table('processed_webhooks')->where('id', $event->id())->exists(); }, ); return response()->noContent(); });
The package does not own your idempotency table because every Laravel app stores operational events differently.
Strict Exceptions
If you want exceptions instead of fallback decisions:
$decision = Preverus::evaluateOrFail($request, [ 'event_type' => 'signup', 'user_id' => $user->id, ]);
Most production apps should use evaluate() so a temporary external failure does not crash the customer flow.
Full Config
return [ 'server_key' => env('PREVERUS_SERVER_KEY'), 'browser_key' => env('PREVERUS_BROWSER_KEY'), 'endpoint' => env('PREVERUS_ENDPOINT', 'https://api.preverus.com'), 'script_url' => env('PREVERUS_SCRIPT_URL', 'https://cdn.preverus.com/v1/preverus.js'), // Optional. Defaults to open. 'failure_mode' => env('PREVERUS_FAILURE_MODE', 'open'), 'http' => [ 'timeout_ms' => env('PREVERUS_TIMEOUT_MS', 1500), 'connect_timeout_ms' => env('PREVERUS_CONNECT_TIMEOUT_MS', 500), 'retries' => env('PREVERUS_RETRIES', 2), ], 'circuit_breaker' => [ 'enabled' => true, 'failure_threshold' => 5, 'cooldown_seconds' => 30, ], 'queue' => [ 'events' => true, 'connection' => env('PREVERUS_QUEUE_CONNECTION'), 'queue' => env('PREVERUS_QUEUE', 'default'), ], ];
Production Checklist
- Add
@preverusScript(['auto' => true])to layouts with protected forms. - Add
data-preverus-actionto signup, login, checkout, withdraw, payout, password reset, and payment-change forms. - Call
Preverus::evaluate()before approving sensitive actions. - Send your real account ID as
user_id. - Include metadata such as email, phone, username, and payment address where available.
- Use
reviewoutcomes for step-up auth or manual review. - Configure failure mode per risk level.
- Keep
PREVERUS_SERVER_KEYprivate. - Verify and dedupe webhooks before processing them.
统计信息
- 总下载量: 0
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 0
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-07-13