botbye/botbye-php-sdk
最新稳定版本:v2.0.1
Composer 安装命令:
composer require botbye/botbye-php-sdk
包简介
Botbye PHP SDK for bot detection and account takeover protection
README 文档
README
PHP SDK for the BotBye Unified Protection Platform — unifying fraud prevention and real-time event monitoring in one platform.
BotBye goes beyond fixed bot/ATO checks. Risk dimensions and metrics are fully dynamic — you define what to measure and what rules to apply per project. This means the same platform covers bot detection, account takeover, multi-accounting, payment fraud, promotion abuse, or any custom fraud scenario specific to your business.
Requirements
- PHP 8.1 or higher
- Composer
- Any PSR-18 compatible HTTP client (Guzzle, Symfony HttpClient, Buzz, etc.)
Installation
composer require botbye/botbye-php-sdk
You also need a PSR-18 HTTP client and PSR-17 factories. Install one of the ready-made implementations:
Guzzle (most common):
composer require guzzlehttp/guzzle
Symfony HttpClient:
composer require symfony/http-client nyholm/psr7
Buzz:
composer require kriswallsmith/buzz nyholm/psr7
Or write a custom adapter for your HTTP transport (e.g. WordPress wp_remote_request) — in that case you only need a PSR-17 factory:
composer require nyholm/psr7
Overview
The SDK provides three request types for different integration levels:
| Request Type | Use Case | Where It Runs |
|---|---|---|
BotbyeValidationEvent |
Level 1 — Bot filtering | Proxy or middleware, before user identity is known |
BotbyeRiskScoringEvent |
Level 2 — Risk scoring & event logging | Application layer, when user identity is known |
BotbyeFullEvent |
Level 1+2 combined | Application layer when no separate proxy exists |
All requests go to a single endpoint (POST /api/v1/protect/evaluate) and return a unified response with a decision (ALLOW, CHALLENGE, BLOCK), risk scores per dimension, and triggered signals. Dimensions are dynamic — the platform ships with built-in ones (bot, ato, abuse) but you can define custom dimensions (e.g., payment_fraud, promotion_abuse) per project without code changes.
Every evaluation call is also recorded as a protection event — logged to the analytics pipeline and used to compute real-time metrics that feed the rules engine. Metrics are fully configurable per project: the platform ships with built-in ones (failed logins, distinct IPs per account, device reuse, etc.) and you can define custom metrics for your specific use case (e.g., "failed transactions over $1000 per account in 1 hour"). This means BotbyeRiskScoringEvent serves a dual purpose: it both evaluates risk and logs the event for future analysis and metric aggregation.
Quick Start
1. Initialize the Client
The SDK uses PSR-18 / PSR-17 interfaces — bring your own HTTP client and message factories.
With Guzzle:
use Botbye\Client\BotbyeClient; use Botbye\Client\BotbyeConfig; use GuzzleHttp\Client; use GuzzleHttp\Psr7\HttpFactory; $config = new BotbyeConfig( serverKey: 'your-server-key' // from https://botbye.com/docs/dashboard/project ); $httpClient = new Client(['timeout' => 2.0]); $psr17Factory = new HttpFactory(); $client = new BotbyeClient( config: $config, httpClient: $httpClient, requestFactory: $psr17Factory, streamFactory: $psr17Factory, );
With Symfony HttpClient:
use Symfony\Component\HttpClient\Psr18Client; use Nyholm\Psr7\Factory\Psr17Factory; $httpClient = new Psr18Client(); $psr17Factory = new Psr17Factory(); $client = new BotbyeClient( config: $config, httpClient: $httpClient, requestFactory: $psr17Factory, streamFactory: $psr17Factory, );
Custom adapter (e.g. WordPress wp_remote_request):
use Botbye\Client\BotbyeClient; use Botbye\Client\BotbyeConfig; use Nyholm\Psr7\Factory\Psr17Factory; use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; // Wrap any HTTP transport as a PSR-18 client class WpHttpClient implements ClientInterface { public function sendRequest(RequestInterface $request): ResponseInterface { $response = wp_remote_request((string) $request->getUri(), [ 'method' => $request->getMethod(), 'headers' => array_map( fn(array $v) => implode(', ', $v), $request->getHeaders(), ), 'body' => (string) $request->getBody(), 'timeout' => 2, ]); if (is_wp_error($response)) { throw new \RuntimeException($response->get_error_message()); } $psr17 = new Psr17Factory(); $psrResponse = $psr17->createResponse( wp_remote_retrieve_response_code($response), ); return $psrResponse->withBody( $psr17->createStream(wp_remote_retrieve_body($response)), ); } } $psr17Factory = new Psr17Factory(); $client = new BotbyeClient( config: $config, httpClient: new WpHttpClient(), requestFactory: $psr17Factory, streamFactory: $psr17Factory, );
2. Bot Validation (Level 1)
Validate device tokens where user identity is not yet available — at the proxy layer or in a middleware before authentication.
use Botbye\Model\BotbyeValidationEvent; use Botbye\Model\Headers; $headers = Headers::fromArray(getallheaders()); $response = $client->evaluate(new BotbyeValidationEvent( ip: $_SERVER['REMOTE_ADDR'], token: $_GET['botbye_token'] ?? '', headers: $headers->jsonSerialize(), requestMethod: $_SERVER['REQUEST_METHOD'], requestUri: $_SERVER['REQUEST_URI'], )); if ($response->isBlocked()) { http_response_code(403); exit('Access denied'); } // Propagate bot score to Level 2 via header header(BotbyeClient::RESULT_HEADER . ': ' . $client->encodeResult($response));
3. Risk Scoring & Event Logging (Level 2)
Evaluate risk and log events when user identity is known. Each call both scores the request and feeds the real-time metrics engine, so you should call evaluate() for every significant user action — not just when you need a decision.
use Botbye\Model\BotbyeRiskScoringEvent; use Botbye\Model\BotbyeUserInfo; use Botbye\Model\EventStatus; use Botbye\Model\Decision; $response = $client->evaluate(new BotbyeRiskScoringEvent( ip: $_SERVER['REMOTE_ADDR'], headers: $headers->jsonSerialize(), user: new BotbyeUserInfo( accountId: $userId, email: $userEmail, // optional phone: $userPhone, // optional ), eventType: 'LOGIN', eventStatus: EventStatus::SUCCESSFUL, botbyeResult: $_SERVER['HTTP_X_BOTBYE_RESULT'] ?? null, // from Level 1 )); match ($response->decision) { Decision::BLOCK => abort(403), Decision::CHALLENGE => showChallenge($response->challenge), Decision::ALLOW => continueRequest(), };
When botbyeResult is null (no Level 1 upstream), bot validation is automatically bypassed.
Event Types
eventType is an arbitrary string — the server accepts any value. Pass any string that matches your business domain:
'LOGIN' 'REGISTRATION' 'TRANSACTION' 'BONUS_CLAIM' 'PASSWORD_RESET' 'WITHDRAWAL'
Using Level 2 for Event Logging
Even when you don't need to act on the decision, sending events builds the metrics profile for the account. This enables rules like "more than 5 failed logins in 10 minutes" or "distinct devices per account in 1 hour":
// Log a failed login attempt — feeds metrics even if you don't act on the decision $client->evaluate(new BotbyeRiskScoringEvent( ip: $_SERVER['REMOTE_ADDR'], headers: $headers->jsonSerialize(), user: new BotbyeUserInfo(accountId: $userId), eventType: 'LOGIN', eventStatus: EventStatus::FAILED, )); // Log a custom business event $client->evaluate(new BotbyeRiskScoringEvent( ip: $_SERVER['REMOTE_ADDR'], headers: $headers->jsonSerialize(), user: new BotbyeUserInfo(accountId: $userId), eventType: 'BONUS_CLAIM', eventStatus: EventStatus::SUCCESSFUL, customFields: ['bonus_id' => 'welcome_100'], ));
4. Full Evaluation (Level 1+2 Combined)
Use when there is no separate proxy layer — validates the device token and evaluates risk in a single call.
use Botbye\Model\BotbyeFullEvent; $response = $client->evaluate(new BotbyeFullEvent( ip: $_SERVER['REMOTE_ADDR'], token: $_GET['botbye_token'] ?? '', headers: $headers->jsonSerialize(), user: new BotbyeUserInfo(accountId: $userId), eventType: 'LOGIN', eventStatus: EventStatus::FAILED, ));
Response
BotbyeEvaluateResponse contains:
| Field | Type | Description |
|---|---|---|
requestId |
?string |
Request UUID |
decision |
Decision |
ALLOW, CHALLENGE, or BLOCK |
riskScore |
?float |
Overall risk score (0–1) |
scores |
?array |
Per-dimension scores (bot, ato, abuse, ...) |
signals |
?array |
Triggered signal names (e.g., BruteForce, ImpossibleTravel) |
challenge |
?BotbyeChallenge |
Challenge type and token (when decision is CHALLENGE) |
extraData |
?BotbyeExtraData |
Enriched device data (IP, country, browser, device, etc.) |
config |
BotbyeEvaluateConfig |
Config flags (bypassBotValidation) |
error |
?BotbyeError |
Error details (on fallback) |
$response->decision; // Decision::ALLOW $response->isBlocked(); // false $response->riskScore; // 0.72 $response->scores; // ['bot' => 0.15, 'ato' => 0.72, 'abuse' => 0.05] $response->signals; // ['BruteForce', 'ImpossibleTravel'] $response->challenge?->type; // 'captcha' $response->extraData?->country; // 'US'
Level 1 to Level 2 Propagation
When using both levels, propagate the Level 1 result to Level 2 via the X-Botbye-Result header. This allows the platform to link both evaluations by requestId and combine bot score from Level 1 with risk scores from Level 2 into a single unified result:
// Level 1 (proxy) — validate and forward result $response = $client->evaluate(new BotbyeValidationEvent(...)); header(BotbyeClient::RESULT_HEADER . ': ' . $client->encodeResult($response)); // Or bypass validation entirely header(BotbyeClient::RESULT_HEADER . ': ' . $client->bypassResult()); // Level 2 (middleware) — pass the header value as botbyeResult $response = $client->evaluate(new BotbyeRiskScoringEvent( // ... botbyeResult: $_SERVER['HTTP_X_BOTBYE_RESULT'] ?? null, ));
Configuration
$config = new BotbyeConfig( serverKey: 'your-server-key', // from https://app.botbye.com botbyeEndpoint: 'https://verify.botbye.com', // default );
Timeouts are configured on the HTTP client you provide:
// Guzzle $httpClient = new \GuzzleHttp\Client(['timeout' => 2.0, 'connect_timeout' => 1.0]); // Symfony $httpClient = new Psr18Client(HttpClient::create(['timeout' => 2.0, 'max_duration' => 3.0]));
PSR-3 Logger
use Monolog\Logger; use Monolog\Handler\StreamHandler; $logger = new Logger('botbye'); $logger->pushHandler(new StreamHandler('/var/log/botbye.log', Logger::WARNING)); $client = new BotbyeClient( config: $config, httpClient: $httpClient, requestFactory: $psr17Factory, streamFactory: $psr17Factory, logger: $logger, );
Error Handling
The SDK follows a fail-open strategy. On network or server errors, evaluate() returns a bypass response (Decision::ALLOW with bypassBotValidation: true) instead of throwing:
$response = $client->evaluate($event); if ($response->error !== null) { // Evaluation failed, request was allowed by default log($response->error->message); }
BotbyeException is only thrown for unrecoverable errors during sendPayload() — the client catches these internally and returns the bypass response.
Framework Integration
Laravel Middleware
namespace App\Http\Middleware; use Botbye\Client\BotbyeClient; use Botbye\Model\BotbyeValidationEvent; use Botbye\Model\Headers; use Closure; use Illuminate\Http\Request; class BotbyeMiddleware { public function __construct(private BotbyeClient $botbye) {} public function handle(Request $request, Closure $next) { $headers = Headers::fromArray($request->headers->all()); $response = $this->botbye->evaluate(new BotbyeValidationEvent( ip: $request->ip(), token: $request->query('botbye_token', ''), headers: $headers->jsonSerialize(), requestMethod: $request->method(), requestUri: $request->getRequestUri(), )); if ($response->isBlocked()) { abort(403, 'Access denied'); } return $next($request); } }
Register the BotbyeClient in a service provider:
// AppServiceProvider.php $this->app->singleton(BotbyeClient::class, function ($app) { $httpClient = new \GuzzleHttp\Client(['timeout' => 2.0]); $factory = new \GuzzleHttp\Psr7\HttpFactory(); return new BotbyeClient( config: new BotbyeConfig(serverKey: config('services.botbye.key')), httpClient: $httpClient, requestFactory: $factory, streamFactory: $factory, ); });
Symfony Event Subscriber
namespace App\EventSubscriber; use Botbye\Client\BotbyeClient; use Botbye\Model\BotbyeValidationEvent; use Botbye\Model\Headers; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\KernelEvents; class BotbyeSubscriber implements EventSubscriberInterface { public function __construct(private BotbyeClient $botbye) {} public static function getSubscribedEvents(): array { return [KernelEvents::REQUEST => 'onKernelRequest']; } public function onKernelRequest(RequestEvent $event): void { $request = $event->getRequest(); $headers = Headers::fromArray($request->headers->all()); $response = $this->botbye->evaluate(new BotbyeValidationEvent( ip: $request->getClientIp(), token: $request->query->get('botbye_token', ''), headers: $headers->jsonSerialize(), requestMethod: $request->getMethod(), requestUri: $request->getRequestUri(), )); if ($response->isBlocked()) { throw new AccessDeniedHttpException('Access denied'); } } }
Testing
composer install vendor/bin/phpunit
License
MIT
Support
For support, visit botbye.com or contact accounts@botbye.com.
统计信息
- 总下载量: 29
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 0
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-11-19