You've already forked wc-licensed-product-client
Security classes: - ResponseSignature: HMAC-SHA256 signing and verification - StringEncoder: XOR-based string obfuscation for source code - IntegrityChecker: Source file hash verification - SignatureException, IntegrityException for error handling SecureLicenseClient: - Verifies server response signatures - Prevents response tampering and replay attacks - Per-license derived signing keys - Optional code integrity checking Documentation: - docs/server-implementation.md with complete WordPress/WooCommerce integration guide for signing responses Tests: - 34 new security tests (66 total, all passing) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
171 lines
4.6 KiB
Markdown
171 lines
4.6 KiB
Markdown
# WooCommerce Licensed Product Client
|
|
|
|
A PHP client library for the WooCommerce Licensed Product Plugin REST API. Activate, validate, and check the status of software licenses.
|
|
|
|
## Requirements
|
|
|
|
- PHP 8.3 or higher
|
|
- Composer
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
composer require magdev/wc-licensed-product-client
|
|
```
|
|
|
|
## Features
|
|
|
|
- Object-oriented client library
|
|
- **Secure client with response signature verification (HMAC-SHA256)**
|
|
- PSR-3 logging support
|
|
- PSR-6 caching support
|
|
- PSR-18 HTTP client compatible
|
|
- License validation against domains
|
|
- License activation on domains
|
|
- License status checking
|
|
- Comprehensive exception handling
|
|
- Code integrity verification
|
|
- Built on Symfony HttpClient
|
|
|
|
## Usage
|
|
|
|
### Basic Usage
|
|
|
|
```php
|
|
use Magdev\WcLicensedProductClient\LicenseClient;
|
|
use Symfony\Component\HttpClient\HttpClient;
|
|
|
|
$httpClient = HttpClient::create();
|
|
$client = new LicenseClient(
|
|
httpClient: $httpClient,
|
|
baseUrl: 'https://your-wordpress-site.com',
|
|
);
|
|
|
|
// Validate a license
|
|
$licenseInfo = $client->validate('ABCD-1234-EFGH-5678', 'example.com');
|
|
echo "Product ID: " . $licenseInfo->productId;
|
|
|
|
// Check license status
|
|
$status = $client->status('ABCD-1234-EFGH-5678');
|
|
echo "Status: " . $status->status->value;
|
|
|
|
// Activate a license
|
|
$result = $client->activate('ABCD-1234-EFGH-5678', 'example.com');
|
|
echo "Activated: " . ($result->success ? 'Yes' : 'No');
|
|
```
|
|
|
|
### With Logging
|
|
|
|
```php
|
|
use Magdev\WcLicensedProductClient\LicenseClient;
|
|
use Psr\Log\LoggerInterface;
|
|
use Symfony\Component\HttpClient\HttpClient;
|
|
|
|
$client = new LicenseClient(
|
|
httpClient: HttpClient::create(),
|
|
baseUrl: 'https://your-wordpress-site.com',
|
|
logger: $yourPsrLogger, // Any PSR-3 compatible logger
|
|
);
|
|
```
|
|
|
|
### With Caching
|
|
|
|
```php
|
|
use Magdev\WcLicensedProductClient\LicenseClient;
|
|
use Psr\Cache\CacheItemPoolInterface;
|
|
use Symfony\Component\HttpClient\HttpClient;
|
|
|
|
$client = new LicenseClient(
|
|
httpClient: HttpClient::create(),
|
|
baseUrl: 'https://your-wordpress-site.com',
|
|
cache: $yourPsrCache, // Any PSR-6 compatible cache
|
|
cacheTtl: 600, // Cache TTL in seconds (default: 300)
|
|
);
|
|
```
|
|
|
|
### Exception Handling
|
|
|
|
```php
|
|
use Magdev\WcLicensedProductClient\Exception\LicenseNotFoundException;
|
|
use Magdev\WcLicensedProductClient\Exception\LicenseExpiredException;
|
|
use Magdev\WcLicensedProductClient\Exception\DomainMismatchException;
|
|
use Magdev\WcLicensedProductClient\Exception\RateLimitExceededException;
|
|
use Magdev\WcLicensedProductClient\Exception\LicenseException;
|
|
|
|
try {
|
|
$licenseInfo = $client->validate($licenseKey, $domain);
|
|
} catch (LicenseNotFoundException $e) {
|
|
// License key does not exist
|
|
} catch (LicenseExpiredException $e) {
|
|
// License has expired
|
|
} catch (DomainMismatchException $e) {
|
|
// License is not valid for this domain
|
|
} catch (RateLimitExceededException $e) {
|
|
// Too many requests, retry after $e->retryAfter seconds
|
|
} catch (LicenseException $e) {
|
|
// Other license-related errors
|
|
}
|
|
```
|
|
|
|
## Secure Client
|
|
|
|
For enhanced security, use `SecureLicenseClient` which verifies response signatures:
|
|
|
|
```php
|
|
use Magdev\WcLicensedProductClient\SecureLicenseClient;
|
|
use Magdev\WcLicensedProductClient\Security\SignatureException;
|
|
use Symfony\Component\HttpClient\HttpClient;
|
|
|
|
$client = new SecureLicenseClient(
|
|
httpClient: HttpClient::create(),
|
|
baseUrl: 'https://your-wordpress-site.com',
|
|
serverSecret: 'shared-secret-with-server', // Must match server configuration
|
|
);
|
|
|
|
try {
|
|
$licenseInfo = $client->validate('ABCD-1234-EFGH-5678', 'example.com');
|
|
} catch (SignatureException $e) {
|
|
// Response signature invalid - possible tampering!
|
|
}
|
|
```
|
|
|
|
**Important:** The secure client requires the server to sign responses. See [docs/server-implementation.md](docs/server-implementation.md) for server setup instructions.
|
|
|
|
### Security Features
|
|
|
|
- **Response Signatures**: HMAC-SHA256 verification prevents response tampering
|
|
- **Timestamp Validation**: Prevents replay attacks (5-minute tolerance)
|
|
- **Per-License Keys**: Each license has a unique verification key
|
|
- **Code Integrity**: Optional verification of source file integrity
|
|
|
|
## Testing
|
|
|
|
Run the test suite with PHPUnit:
|
|
|
|
```bash
|
|
./vendor/bin/phpunit
|
|
```
|
|
|
|
## API Endpoints
|
|
|
|
This client interacts with the following WooCommerce Licensed Product API endpoints:
|
|
|
|
- **POST /validate** - Validate a license key for a specific domain
|
|
- **POST /status** - Get detailed license status information
|
|
- **POST /activate** - Activate a license on a domain
|
|
|
|
## License
|
|
|
|
GPL-2.0-or-later
|
|
|
|
## Author
|
|
|
|
Marco Graetsch
|
|
|
|
- Website: <https://src.bundespruefstelle.ch/magdev>
|
|
- Email: <magdev3.0@gmail.com>
|
|
|
|
## Contributing
|
|
|
|
Issues and pull requests are welcome at <https://src.bundespruefstelle.ch/magdev/wc-licensed-product-client/issues>
|