定制 preverus/preverus-laravel 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

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 open for signup, login, and checkout if uptime/revenue continuity is the priority.
  • Use review for withdrawals, payouts, password resets, and payment changes.
  • Use closed only 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-action to 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 review outcomes for step-up auth or manual review.
  • Configure failure mode per risk level.
  • Keep PREVERUS_SERVER_KEY private.
  • Verify and dedupe webhooks before processing them.

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-07-13

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固