Integrate OpenAPI/Swagger documentation using drf-spectacular, enhancing API documentation with comprehensive guides and schema generation. Add multiple documentation files covering authentication, error codes, rate limiting, and migration strategies. Update settings and URLs to support new documentation endpoints and schema configurations.

This commit is contained in:
IGNY8 VPS (Salman)
2025-11-16 02:15:37 +00:00
parent 452d065c22
commit 79648db07f
16 changed files with 3501 additions and 6 deletions

View File

@@ -0,0 +1,575 @@
# WordPress Plugin Integration Guide
**Version**: 1.0.0
**Last Updated**: 2025-11-16
Complete guide for integrating WordPress plugins with IGNY8 API v1.0.
---
## Overview
This guide helps WordPress plugin developers integrate with the IGNY8 API using the unified response format.
---
## Authentication
### Getting Access Token
```php
function igny8_login($email, $password) {
$response = wp_remote_post('https://api.igny8.com/api/v1/auth/login/', [
'headers' => [
'Content-Type' => 'application/json'
],
'body' => json_encode([
'email' => $email,
'password' => $password
])
]);
$body = json_decode(wp_remote_retrieve_body($response), true);
if ($body['success']) {
// Store tokens
update_option('igny8_access_token', $body['data']['access']);
update_option('igny8_refresh_token', $body['data']['refresh']);
return $body['data']['access'];
} else {
return new WP_Error('login_failed', $body['error']);
}
}
```
### Using Access Token
```php
function igny8_get_headers() {
$token = get_option('igny8_access_token');
if (!$token) {
return false;
}
return [
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'application/json'
];
}
```
---
## API Client Class
### Complete PHP Implementation
```php
class Igny8API {
private $base_url = 'https://api.igny8.com/api/v1';
private $access_token = null;
private $refresh_token = null;
public function __construct() {
$this->access_token = get_option('igny8_access_token');
$this->refresh_token = get_option('igny8_refresh_token');
}
/**
* Login and store tokens
*/
public function login($email, $password) {
$response = wp_remote_post($this->base_url . '/auth/login/', [
'headers' => [
'Content-Type' => 'application/json'
],
'body' => json_encode([
'email' => $email,
'password' => $password
])
]);
$body = $this->parse_response($response);
if ($body['success']) {
$this->access_token = $body['data']['access'];
$this->refresh_token = $body['data']['refresh'];
update_option('igny8_access_token', $this->access_token);
update_option('igny8_refresh_token', $this->refresh_token);
return true;
}
return false;
}
/**
* Refresh access token
*/
public function refresh_token() {
if (!$this->refresh_token) {
return false;
}
$response = wp_remote_post($this->base_url . '/auth/refresh/', [
'headers' => [
'Content-Type' => 'application/json'
],
'body' => json_encode([
'refresh' => $this->refresh_token
])
]);
$body = $this->parse_response($response);
if ($body['success']) {
$this->access_token = $body['data']['access'];
$this->refresh_token = $body['data']['refresh'];
update_option('igny8_access_token', $this->access_token);
update_option('igny8_refresh_token', $this->refresh_token);
return true;
}
return false;
}
/**
* Parse unified API response
*/
private function parse_response($response) {
if (is_wp_error($response)) {
return [
'success' => false,
'error' => $response->get_error_message()
];
}
$body = json_decode(wp_remote_retrieve_body($response), true);
$status_code = wp_remote_retrieve_response_code($response);
// Handle non-JSON responses
if (!$body) {
return [
'success' => false,
'error' => 'Invalid response format'
];
}
// Check if response follows unified format
if (isset($body['success'])) {
return $body;
}
// Legacy format - wrap in unified format
if ($status_code >= 200 && $status_code < 300) {
return [
'success' => true,
'data' => $body
];
} else {
return [
'success' => false,
'error' => $body['detail'] ?? 'Unknown error'
];
}
}
/**
* Get headers with authentication
*/
private function get_headers() {
if (!$this->access_token) {
throw new Exception('Not authenticated');
}
return [
'Authorization' => 'Bearer ' . $this->access_token,
'Content-Type' => 'application/json'
];
}
/**
* Make GET request
*/
public function get($endpoint) {
$response = wp_remote_get($this->base_url . $endpoint, [
'headers' => $this->get_headers()
]);
$body = $this->parse_response($response);
// Handle 401 - token expired
if (!$body['success'] && wp_remote_retrieve_response_code($response) == 401) {
// Try to refresh token
if ($this->refresh_token()) {
// Retry request
$response = wp_remote_get($this->base_url . $endpoint, [
'headers' => $this->get_headers()
]);
$body = $this->parse_response($response);
}
}
return $body;
}
/**
* Make POST request
*/
public function post($endpoint, $data) {
$response = wp_remote_post($this->base_url . $endpoint, [
'headers' => $this->get_headers(),
'body' => json_encode($data)
]);
$body = $this->parse_response($response);
// Handle 401 - token expired
if (!$body['success'] && wp_remote_retrieve_response_code($response) == 401) {
// Try to refresh token
if ($this->refresh_token()) {
// Retry request
$response = wp_remote_post($this->base_url . $endpoint, [
'headers' => $this->get_headers(),
'body' => json_encode($data)
]);
$body = $this->parse_response($response);
}
}
return $body;
}
/**
* Make PUT request
*/
public function put($endpoint, $data) {
$response = wp_remote_request($this->base_url . $endpoint, [
'method' => 'PUT',
'headers' => $this->get_headers(),
'body' => json_encode($data)
]);
return $this->parse_response($response);
}
/**
* Make DELETE request
*/
public function delete($endpoint) {
$response = wp_remote_request($this->base_url . $endpoint, [
'method' => 'DELETE',
'headers' => $this->get_headers()
]);
return $this->parse_response($response);
}
}
```
---
## Usage Examples
### Get Keywords
```php
$api = new Igny8API();
// Get keywords
$response = $api->get('/planner/keywords/');
if ($response['success']) {
$keywords = $response['results'];
$count = $response['count'];
foreach ($keywords as $keyword) {
echo $keyword['name'] . '<br>';
}
} else {
echo 'Error: ' . $response['error'];
}
```
### Create Keyword
```php
$api = new Igny8API();
$data = [
'seed_keyword_id' => 1,
'site_id' => 1,
'sector_id' => 1,
'status' => 'active'
];
$response = $api->post('/planner/keywords/', $data);
if ($response['success']) {
$keyword = $response['data'];
echo 'Created keyword: ' . $keyword['id'];
} else {
echo 'Error: ' . $response['error'];
if (isset($response['errors'])) {
foreach ($response['errors'] as $field => $errors) {
echo $field . ': ' . implode(', ', $errors) . '<br>';
}
}
}
```
### Handle Pagination
```php
$api = new Igny8API();
function get_all_keywords($api) {
$all_keywords = [];
$page = 1;
do {
$response = $api->get("/planner/keywords/?page={$page}&page_size=100");
if ($response['success']) {
$all_keywords = array_merge($all_keywords, $response['results']);
$page++;
} else {
break;
}
} while ($response['next']);
return $all_keywords;
}
$keywords = get_all_keywords($api);
```
### Handle Rate Limiting
```php
function make_rate_limited_request($api, $endpoint, $max_retries = 3) {
for ($attempt = 0; $attempt < $max_retries; $attempt++) {
$response = $api->get($endpoint);
// Check if rate limited
if (!$response['success'] && isset($response['error'])) {
if (strpos($response['error'], 'Rate limit') !== false) {
// Wait before retry
sleep(pow(2, $attempt)); // Exponential backoff
continue;
}
}
return $response;
}
return ['success' => false, 'error' => 'Max retries exceeded'];
}
```
---
## Error Handling
### Unified Error Handling
```php
function handle_api_response($response) {
if ($response['success']) {
return $response['data'] ?? $response['results'];
} else {
$error_message = $response['error'];
// Log error with request ID
error_log(sprintf(
'IGNY8 API Error: %s (Request ID: %s)',
$error_message,
$response['request_id'] ?? 'unknown'
));
// Handle field-specific errors
if (isset($response['errors'])) {
foreach ($response['errors'] as $field => $errors) {
error_log(" {$field}: " . implode(', ', $errors));
}
}
return new WP_Error('igny8_api_error', $error_message, $response);
}
}
```
---
## Best Practices
### 1. Store Tokens Securely
```php
// Use WordPress options API with encryption
function save_token($token) {
// Encrypt token before storing
$encrypted = base64_encode($token);
update_option('igny8_access_token', $encrypted, false);
}
function get_token() {
$encrypted = get_option('igny8_access_token');
return base64_decode($encrypted);
}
```
### 2. Implement Token Refresh
```php
function ensure_valid_token($api) {
// Check if token is about to expire (refresh 1 minute before)
// Token expires in 15 minutes, refresh at 14 minutes
$last_refresh = get_option('igny8_token_refreshed_at', 0);
if (time() - $last_refresh > 14 * 60) {
if ($api->refresh_token()) {
update_option('igny8_token_refreshed_at', time());
}
}
}
```
### 3. Cache Responses
```php
function get_cached_keywords($api, $cache_key = 'igny8_keywords', $ttl = 300) {
$cached = get_transient($cache_key);
if ($cached !== false) {
return $cached;
}
$response = $api->get('/planner/keywords/');
if ($response['success']) {
$keywords = $response['results'];
set_transient($cache_key, $keywords, $ttl);
return $keywords;
}
return false;
}
```
### 4. Handle Rate Limits
```php
function check_rate_limit($response) {
// Note: WordPress wp_remote_* doesn't expose all headers easily
// Consider using cURL or checking response for 429 status
if (isset($response['error']) && strpos($response['error'], 'Rate limit') !== false) {
// Wait and retry
sleep(60);
return true; // Should retry
}
return false;
}
```
---
## WordPress Admin Integration
### Settings Page
```php
function igny8_settings_page() {
?>
<div class="wrap">
<h1>IGNY8 API Settings</h1>
<form method="post" action="options.php">
<?php settings_fields('igny8_settings'); ?>
<table class="form-table">
<tr>
<th>API Email</th>
<td><input type="email" name="igny8_email" value="<?php echo get_option('igny8_email'); ?>" /></td>
</tr>
<tr>
<th>API Password</th>
<td><input type="password" name="igny8_password" value="" /></td>
</tr>
</table>
<?php submit_button('Save & Connect'); ?>
</form>
</div>
<?php
}
function igny8_save_settings() {
if (isset($_POST['igny8_email']) && isset($_POST['igny8_password'])) {
$api = new Igny8API();
if ($api->login($_POST['igny8_email'], $_POST['igny8_password'])) {
update_option('igny8_email', $_POST['igny8_email']);
add_settings_error('igny8_settings', 'igny8_connected', 'Successfully connected to IGNY8 API', 'updated');
} else {
add_settings_error('igny8_settings', 'igny8_error', 'Failed to connect to IGNY8 API', 'error');
}
}
}
add_action('admin_init', 'igny8_save_settings');
```
---
## Testing
### Unit Tests
```php
class TestIgny8API extends WP_UnitTestCase {
public function test_login() {
$api = new Igny8API();
$result = $api->login('test@example.com', 'password');
$this->assertTrue($result);
$this->assertNotEmpty(get_option('igny8_access_token'));
}
public function test_get_keywords() {
$api = new Igny8API();
$response = $api->get('/planner/keywords/');
$this->assertTrue($response['success']);
$this->assertArrayHasKey('results', $response);
$this->assertArrayHasKey('count', $response);
}
}
```
---
## Troubleshooting
### Issue: Authentication Fails
**Check**:
1. Email and password are correct
2. Account is active
3. API endpoint is accessible
### Issue: Token Expires Frequently
**Solution**: Implement automatic token refresh before expiration.
### Issue: Rate Limited
**Solution**: Implement request throttling and caching.
---
**Last Updated**: 2025-11-16
**API Version**: 1.0.0