jakuborava / ehub-client
Publisher API client for EHUB affiliate network
Fund package maintenance!
Jakub Orava
Installs: 7
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/jakuborava/ehub-client
Requires
- php: ^8.4
- illuminate/contracts: ^11.0||^12.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^10.0.0||^9.0.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
README
A comprehensive Laravel package for interacting with the eHub Affiliate Network API. This package provides a fluent, type-safe interface for all Publisher endpoints with full DTO support, request objects, and comprehensive error handling.
Features
- ✅ Full support for all Publisher endpoints
- ✅ Type-safe DTOs for all responses
- ✅ Fluent Request objects for building queries
- ✅ Pagination support with metadata
- ✅ Comprehensive exception hierarchy
- ✅ PHP 8.4+ with strict typing
- ✅ PHPStan Level MAX compliant
- ✅ Laravel HTTP Client integration
- ✅ Easy userId switching per request
Installation
You can install the package via composer:
composer require jakuborava/ehub-client
Configuration
You can configure the API key in two ways:
1. Environment Variable (Recommended)
Add your eHub API key to your .env file:
EHUB_API_KEY=your-api-key-here
Then use the client without any parameters:
use JakubOrava\EhubClient\EhubClient; $client = new EhubClient();
2. Programmatically
Pass the API key directly to the client constructor:
use JakubOrava\EhubClient\EhubClient; $client = new EhubClient('your-api-key-here');
This is useful when you need to:
- Use different API keys for different requests
- Load the API key from a custom source
- Switch between multiple API keys dynamically
Usage
Basic Usage
The client uses a fluent, hierarchical API design. All methods require a userId (publisher ID) to be passed per request, allowing you to easily switch between different publisher accounts.
use JakubOrava\EhubClient\EhubClient; // Initialize with API key from config/env $client = new EhubClient(); // Or initialize with API key parameter $client = new EhubClient('your-api-key-here'); $publisherId = 'your-publisher-id'; // Get vouchers $vouchers = $client->publishers() ->vouchers() ->list($publisherId); // Access the results foreach ($vouchers->items as $voucher) { echo $voucher->code; echo $voucher->campaignName; echo $voucher->url; } // Pagination info echo $vouchers->totalItems; // Total number of items echo $vouchers->currentPage; // Current page number echo $vouchers->perPage; // Items per page echo $vouchers->getTotalPages(); // Total pages echo $vouchers->hasMorePages(); // Check if more pages exist
Using Request Objects
Request objects provide a fluent interface for building queries with pagination, filtering, and sorting:
use JakubOrava\EhubClient\Requests\VouchersListRequest; $request = (new VouchersListRequest()) ->page(2) ->perPage(100) ->type('voucher') ->isValid(true) ->sort('-validFrom') ->fields(['id', 'code', 'campaignName', 'url']); $vouchers = $client->publishers() ->vouchers() ->list($publisherId, $request);
Switching Between Users
Since userId is passed per request, you can easily switch between different publisher accounts:
$publisher1Vouchers = $client->publishers() ->vouchers() ->list('publisher-1-id'); $publisher2Vouchers = $client->publishers() ->vouchers() ->list('publisher-2-id');
Available Endpoints
Campaigns
List all campaigns accessible to the publisher:
use JakubOrava\EhubClient\Requests\CampaignsListRequest; $request = (new CampaignsListRequest()) ->page(1) ->perPage(50) ->name('Campaign Name') ->categories([4, 6]) // Finance and E-shops ->status('approved') ->sort('name'); $campaigns = $client->publishers() ->campaigns() ->list($publisherId, $request); foreach ($campaigns->items as $campaign) { echo $campaign->id; echo $campaign->name; echo $campaign->web; echo $campaign->cookieLifetime; // Access nested collections foreach ($campaign->categories as $category) { echo $category->name; } foreach ($campaign->commissionGroups as $group) { echo $group->name; foreach ($group->commissions as $commission) { echo $commission->value . $commission->valueType; } } }
Creatives
List all creatives (banners, links, etc.) for the publisher:
use JakubOrava\EhubClient\Requests\CreativesListRequest; $request = (new CreativesListRequest()) ->campaignId('campaign-id') ->type('link') ->name('Default link') ->sort('-id'); $creatives = $client->publishers() ->creatives() ->list($publisherId, $request); foreach ($creatives->items as $creative) { echo $creative->id; echo $creative->campaignId; echo $creative->type; echo $creative->destinationUrl; }
Outbound Clicks
Track outbound clicks from your affiliate links:
use JakubOrava\EhubClient\Requests\OutboundClicksListRequest; $request = (new OutboundClicksListRequest()) ->from('2024-01-01T00:00:00') ->to('2024-01-31T23:59:59') ->campaignId('campaign-id') ->processed(true) ->sort('-dateTime'); $clicks = $client->publishers() ->outboundClicks() ->list($publisherId, $request); foreach ($clicks->items as $click) { echo $click->id; echo $click->campaignId; echo $click->clickDateTime; echo $click->commission; }
Transactions
List and retrieve transaction details:
use JakubOrava\EhubClient\Requests\TransactionsListRequest; // List transactions $request = (new TransactionsListRequest()) ->dateInsertedFrom('2024-01-01T00:00:00') ->dateInsertedTo('2024-01-31T23:59:59') ->campaignId('campaign-id') ->status('approved') ->payoutStatus('paid') ->sort('-dateInserted'); $transactions = $client->publishers() ->transactions() ->list($publisherId, $request); foreach ($transactions->items as $transaction) { echo $transaction->id; echo $transaction->uuid; echo $transaction->commission; echo $transaction->amount; echo $transaction->status; } // Get single transaction detail $transaction = $client->publishers() ->transactions() ->get($publisherId, 'transaction-id'); echo $transaction->orderId; echo $transaction->productId;
Vouchers
List vouchers and promotional codes:
use JakubOrava\EhubClient\Requests\VouchersListRequest; $request = (new VouchersListRequest()) ->type('voucher') // or 'action' ->isValid(true) ->sort('-validFrom'); $vouchers = $client->publishers() ->vouchers() ->list($publisherId, $request); foreach ($vouchers->items as $voucher) { echo $voucher->code; echo $voucher->campaignName; echo $voucher->rules; echo $voucher->url; // Affiliate tracking URL echo $voucher->destinationUrl; echo $voucher->validFrom; echo $voucher->validTill; }
Error Handling
The package throws specific exceptions for different error scenarios:
use JakubOrava\EhubClient\Exceptions\AuthenticationException; use JakubOrava\EhubClient\Exceptions\ValidationException; use JakubOrava\EhubClient\Exceptions\ApiErrorException; use JakubOrava\EhubClient\Exceptions\UnexpectedResponseException; try { $vouchers = $client->publishers() ->vouchers() ->list($publisherId); } catch (AuthenticationException $e) { // Invalid API key } catch (ValidationException $e) { // Invalid request parameters } catch (ApiErrorException $e) { // API returned an error (4xx or 5xx) echo $e->getCode(); // HTTP status code } catch (UnexpectedResponseException $e) { // Unexpected response format }
Architecture
DTOs (Data Transfer Objects)
All responses are mapped to strictly typed DTOs with public readonly properties:
$campaign = $campaigns->items->first(); // All properties are typed and readonly $campaign->id; // string $campaign->name; // string $campaign->cookieLifetime; // int|null $campaign->categories; // Collection<CampaignCategoryDTO>
Request Objects
Request objects use a fluent interface and extend BaseRequest:
class VouchersListRequest extends BaseRequest { public function type(string $type): self; public function isValid(bool $isValid): self; }
All request objects support:
page(int $page)- Set page numberperPage(int $perPage)- Set items per pagesort(string $sort)- Set sort field (prefix with-for descending)fields(array $fields)- Specify which fields to return
Future: Advertiser Endpoints
The package architecture is designed to support Advertiser endpoints in the future without breaking changes. The folder structure is prepared:
src/Endpoints/
├── PublisherEndpoints/
└── AdvertiserEndpoints/ (future)
Credits
License
The MIT License (MIT). Please see License File for more information.