Add update-check endpoint support (v0.2.1)

Implement /update-check endpoint aligned with remote OpenAPI spec:
- Add checkForUpdates() method to LicenseClientInterface
- Add UpdateInfo DTO for update check responses
- Add ProductNotFoundException for product_not_found error
- Update local openapi.json to v0.4.0

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-27 20:52:12 +01:00
parent 5e4b5a970f
commit 760e1e752a
11 changed files with 633 additions and 7 deletions

View File

@@ -40,6 +40,7 @@ composer require magdev/wc-licensed-product-client
│ + validate() │
│ + status() │
│ + activate() │
│ + checkForUpdates() │
└─────────────┬───────────────┘
│ implements
├───────────────────────┐
@@ -57,6 +58,7 @@ composer require magdev/wc-licensed-product-client
│ LicenseInfo │
│ LicenseStatus │
│ ActivationResult │
│ UpdateInfo │
│ LicenseState (enum) │
└─────────────────────┘
```
@@ -71,7 +73,8 @@ src/
├── Dto/
│ ├── LicenseInfo.php # Validation response DTO
│ ├── LicenseStatus.php # Status response DTO + LicenseState enum
── ActivationResult.php # Activation response DTO
── ActivationResult.php # Activation response DTO
│ └── UpdateInfo.php # Update check response DTO
├── Exception/
│ ├── LicenseException.php # Base exception
│ ├── LicenseNotFoundException.php
@@ -82,6 +85,7 @@ src/
│ ├── DomainMismatchException.php
│ ├── MaxActivationsReachedException.php
│ ├── ActivationFailedException.php
│ ├── ProductNotFoundException.php
│ └── RateLimitExceededException.php
└── Security/
├── ResponseSignature.php # HMAC signature verification
@@ -120,6 +124,18 @@ interface LicenseClientInterface
* @throws LicenseException When activation fails
*/
public function activate(string $licenseKey, string $domain): ActivationResult;
/**
* Check for available plugin updates.
*
* @throws LicenseException When update check fails
*/
public function checkForUpdates(
string $licenseKey,
string $domain,
?string $pluginSlug = null,
?string $currentVersion = null,
): UpdateInfo;
}
```
@@ -306,6 +322,57 @@ if ($result->success) {
}
```
### UpdateInfo
Returned by `checkForUpdates()`. Contains plugin update information.
```php
final readonly class UpdateInfo
{
public function __construct(
public bool $updateAvailable, // Whether an update is available
public ?string $version, // Latest available version
public ?string $slug, // Plugin slug for WordPress
public ?string $plugin, // Plugin basename (slug/slug.php)
public ?string $downloadUrl, // Secure download URL
public ?\DateTimeImmutable $lastUpdated,// Date of the latest release
public ?string $tested, // Highest WordPress version tested
public ?string $requires, // Minimum WordPress version
public ?string $requiresPhp, // Minimum PHP version
public ?string $changelog, // Release notes
public ?string $packageHash, // SHA256 hash for integrity
public ?string $name, // Product name
public ?string $homepage, // Product homepage URL
public ?array $icons, // Plugin icons for WordPress admin
public ?array $sections, // Content sections for plugin info
) {}
public static function fromArray(array $data): self;
public function hasValidPackageHash(): bool; // Check package hash format
}
```
**Usage:**
```php
$updateInfo = $client->checkForUpdates(
'ABCD-1234-EFGH-5678',
'example.com',
'my-plugin',
'1.0.0',
);
if ($updateInfo->updateAvailable) {
echo "New version available: " . $updateInfo->version;
echo "Download URL: " . $updateInfo->downloadUrl;
if ($updateInfo->hasValidPackageHash()) {
echo "Package hash: " . $updateInfo->packageHash;
}
}
```
## Exception Hierarchy
All exceptions extend `LicenseException` and include an `errorCode` property for programmatic handling.
@@ -320,8 +387,9 @@ LicenseException (base)
├── DomainMismatchException // error: domain_mismatch
├── MaxActivationsReachedException // error: max_activations_reached
├── ActivationFailedException // error: activation_failed
├── ProductNotFoundException // error: product_not_found
├── RateLimitExceededException // error: rate_limit_exceeded (has retryAfter)
── Security\SignatureException // error: signature_invalid
── Security\SignatureException // error: signature_invalid
└── Security\IntegrityException // error: integrity_check_failed
```
@@ -925,6 +993,7 @@ The client communicates with these REST API endpoints:
| `/wp-json/wc-licensed-product/v1/validate` | POST | Validate license for domain |
| `/wp-json/wc-licensed-product/v1/status` | POST | Get license status details |
| `/wp-json/wc-licensed-product/v1/activate` | POST | Activate license on domain |
| `/wp-json/wc-licensed-product/v1/update-check` | POST | Check for plugin updates |
### Request Format
@@ -974,6 +1043,7 @@ All requests use JSON bodies:
| `domain_mismatch` | `DomainMismatchException` | Domain not authorized |
| `max_activations_reached` | `MaxActivationsReachedException` | Too many activations |
| `activation_failed` | `ActivationFailedException` | Server error during activation |
| `product_not_found` | `ProductNotFoundException` | Licensed product doesn't exist |
| `rate_limit_exceeded` | `RateLimitExceededException` | Too many requests |
| `signature_invalid` | `SignatureException` | Response signature invalid |
| `integrity_check_failed` | `IntegrityException` | Source files modified |