218 lines
6.2 KiB
PHP
218 lines
6.2 KiB
PHP
<?php
|
|
/**
|
|
* Mailjet API wrapper.
|
|
*
|
|
* @package WPFMJ
|
|
* @subpackage WPFMJ/includes
|
|
*/
|
|
|
|
class WPFMJ_Mailjet_API {
|
|
|
|
/**
|
|
* API base URL.
|
|
*/
|
|
private $api_url = 'https://api.mailjet.com/v3';
|
|
|
|
/**
|
|
* API key.
|
|
*/
|
|
private $api_key;
|
|
|
|
/**
|
|
* API secret.
|
|
*/
|
|
private $api_secret;
|
|
|
|
/**
|
|
* Constructor.
|
|
*/
|
|
public function __construct($api_key = '', $api_secret = '') {
|
|
$this->api_key = $api_key;
|
|
$this->api_secret = $api_secret;
|
|
}
|
|
|
|
/**
|
|
* Test API connection.
|
|
*/
|
|
public function test_connection() {
|
|
$response = $this->request('GET', '/contact');
|
|
return !is_wp_error($response);
|
|
}
|
|
|
|
/**
|
|
* Get all contact lists.
|
|
*/
|
|
public function get_lists() {
|
|
$response = $this->request('GET', '/contactslist?Limit=1000');
|
|
|
|
if (is_wp_error($response)) {
|
|
return $response;
|
|
}
|
|
|
|
return isset($response['Data']) ? $response['Data'] : array();
|
|
}
|
|
|
|
/**
|
|
* Add contact to list(s).
|
|
*/
|
|
public function add_contact_to_lists($email, $lists, $properties = array()) {
|
|
// Validate inputs
|
|
if (empty($email) || !is_email($email)) {
|
|
return new WP_Error('invalid_email', 'Invalid email address provided');
|
|
}
|
|
|
|
if (!is_array($lists) || empty($lists)) {
|
|
return new WP_Error('invalid_lists', 'Lists must be a non-empty array');
|
|
}
|
|
|
|
// First, ensure contact exists
|
|
$contact = $this->get_or_create_contact($email, $properties);
|
|
|
|
if (is_wp_error($contact)) {
|
|
return $contact;
|
|
}
|
|
|
|
// Validate contact response structure
|
|
if (!isset($contact['ID'])) {
|
|
return new WP_Error('invalid_contact_response', 'Contact response missing ID field');
|
|
}
|
|
|
|
$contact_id = $contact['ID'];
|
|
$results = array();
|
|
|
|
// Add contact to each list
|
|
foreach ($lists as $list_id) {
|
|
// Validate list ID
|
|
$list_id = absint($list_id);
|
|
if ($list_id === 0) {
|
|
$results['invalid'] = new WP_Error('invalid_list_id', 'Invalid list ID');
|
|
continue;
|
|
}
|
|
|
|
$result = $this->add_contact_to_list($contact_id, $list_id);
|
|
$results[$list_id] = $result;
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
|
|
/**
|
|
* Get or create a contact.
|
|
*/
|
|
private function get_or_create_contact($email, $properties = array()) {
|
|
// Try to get existing contact
|
|
$response = $this->request('GET', '/contact/' . rawurlencode($email));
|
|
|
|
if (!is_wp_error($response) && isset($response['Data'][0])) {
|
|
// Contact exists, update properties if provided
|
|
if (!empty($properties)) {
|
|
$this->update_contact($email, $properties);
|
|
}
|
|
return $response['Data'][0];
|
|
}
|
|
|
|
// Create new contact
|
|
$data = array('Email' => $email);
|
|
|
|
if (!empty($properties)) {
|
|
$data['Properties'] = $properties;
|
|
}
|
|
|
|
$response = $this->request('POST', '/contact', $data);
|
|
|
|
if (is_wp_error($response)) {
|
|
return $response;
|
|
}
|
|
|
|
return isset($response['Data'][0]) ? $response['Data'][0] : new WP_Error('contact_creation_failed', 'Failed to create contact');
|
|
}
|
|
|
|
/**
|
|
* Update contact properties.
|
|
*/
|
|
private function update_contact($email, $properties) {
|
|
$data = array('Data' => $properties);
|
|
return $this->request('PUT', '/contactdata/' . rawurlencode($email), $data);
|
|
}
|
|
|
|
/**
|
|
* Add contact to a specific list.
|
|
*/
|
|
private function add_contact_to_list($contact_id, $list_id) {
|
|
$data = array(
|
|
'ContactID' => $contact_id,
|
|
'ListID' => $list_id,
|
|
'IsActive' => true
|
|
);
|
|
|
|
return $this->request('POST', '/contactslist/' . $list_id . '/managecontact', $data);
|
|
}
|
|
|
|
/**
|
|
* Make API request with rate limiting.
|
|
*/
|
|
private function request($method, $endpoint, $data = array()) {
|
|
// Rate limiting: configurable via filter, default 60 requests per minute
|
|
$rate_limit = apply_filters('wpfmj_api_rate_limit', 60);
|
|
$rate_limit = max(10, min(300, absint($rate_limit))); // Clamp between 10-300
|
|
|
|
$rate_limit_key = 'wpfmj_api_rate_' . md5($this->api_key);
|
|
$requests = get_transient($rate_limit_key);
|
|
|
|
if ($requests === false) {
|
|
$requests = 0;
|
|
}
|
|
|
|
if ($requests >= $rate_limit) {
|
|
return new WP_Error('rate_limit_exceeded', sprintf(
|
|
'API rate limit exceeded (%d requests per minute). Please wait a moment and try again.',
|
|
$rate_limit
|
|
));
|
|
}
|
|
|
|
// Increment request count
|
|
set_transient($rate_limit_key, $requests + 1, 60);
|
|
|
|
$url = $this->api_url . $endpoint;
|
|
|
|
$args = array(
|
|
'method' => $method,
|
|
'headers' => array(
|
|
'Content-Type' => 'application/json',
|
|
'Authorization' => 'Basic ' . base64_encode($this->api_key . ':' . $this->api_secret)
|
|
),
|
|
'timeout' => 30,
|
|
'sslverify' => true
|
|
);
|
|
|
|
if ($method === 'POST' || $method === 'PUT') {
|
|
$args['body'] = wp_json_encode($data);
|
|
}
|
|
|
|
$response = wp_remote_request($url, $args);
|
|
|
|
if (is_wp_error($response)) {
|
|
return $response;
|
|
}
|
|
|
|
$code = wp_remote_retrieve_response_code($response);
|
|
$body = wp_remote_retrieve_body($response);
|
|
|
|
// Validate JSON response
|
|
$json = json_decode($body, true);
|
|
if (json_last_error() !== JSON_ERROR_NONE) {
|
|
return new WP_Error(
|
|
'mailjet_json_error',
|
|
sprintf('Invalid JSON response from Mailjet API: %s', json_last_error_msg()),
|
|
array('status' => $code, 'body' => substr($body, 0, 200))
|
|
);
|
|
}
|
|
|
|
if ($code >= 400) {
|
|
$message = isset($json['ErrorMessage']) ? sanitize_text_field($json['ErrorMessage']) : 'API request failed';
|
|
return new WP_Error('mailjet_api_error', $message, array('status' => $code));
|
|
}
|
|
|
|
return $json;
|
|
}
|
|
}
|