'value'] * @return array ['success' => bool, 'message' => string] */ public static function subscribe( $lead_id, $email, $full_name, $extra_fields = array() ) { if ( ! self::is_enabled() ) { return array( 'success' => false, 'message' => 'MailWizz integration disabled.' ); } // Adding an address to a mailing list is marketing: an unsubscribed address is never re-added. if ( ! apply_filters( 'acquis_marketing_allowed', true, $email ) ) { return array( 'success' => false, 'message' => 'Skipped: this address unsubscribed from marketing.' ); } $api_url = untrailingslashit( get_option( 'acquis_mailwizz_api_url', '' ) ); $public_key = get_option( 'acquis_mailwizz_public_key', '' ); $private_key = get_option( 'acquis_mailwizz_private_key', '' ); $list_uid = get_option( 'acquis_mailwizz_list_uid', '' ); $double_optin= (bool) get_option( 'acquis_mailwizz_double_optin', false ); $field_map = get_option( 'acquis_mailwizz_custom_fields', array() ); if ( empty( $api_url ) || empty( $public_key ) || empty( $private_key ) || empty( $list_uid ) ) { return array( 'success' => false, 'message' => 'MailWizz: missing API credentials or list UID.' ); } // Parse first/last name $name_parts = explode( ' ', trim( $full_name ), 2 ); $fname = $name_parts[0]; $lname = isset( $name_parts[1] ) ? $name_parts[1] : ''; // Build subscriber data $data = array( 'EMAIL' => $email, 'FNAME' => $fname, 'LNAME' => $lname, ); // Apply custom field mapping from settings if ( ! empty( $field_map ) && is_array( $field_map ) ) { foreach ( $field_map as $mw_tag => $wp_value ) { $data[ sanitize_text_field( $mw_tag ) ] = sanitize_text_field( $wp_value ); } } // Merge any runtime extra fields foreach ( $extra_fields as $tag => $value ) { $data[ sanitize_text_field( $tag ) ] = sanitize_text_field( $value ); } $endpoint = "{$api_url}/lists/{$list_uid}/subscribers"; $payload = array( 'subscriber' => $data, ); // MailWizz also supports ?confirm_optin=yes on the URL if ( ! $double_optin ) { $endpoint .= '?confirm_optin=no'; } $response = self::api_request( 'POST', $endpoint, $payload, $public_key, $private_key ); $success = isset( $response['body']['status'] ) && $response['body']['status'] === 'success'; if ( ! $success ) { // Some MailWizz versions return 'error' with a message $err_msg = $response['body']['error'] ?? ( $response['body']['message'] ?? 'Unknown MailWizz API error.' ); // Handle "already subscribed" gracefully if ( stripos( $err_msg, 'already' ) !== false || $response['http_code'] === 409 ) { $success = true; $err_msg = 'Already subscribed record updated.'; } } $message = $success ? ( $response['body']['message'] ?? "Subscribed to MailWizz list {$list_uid}." ) : ( $response['body']['error'] ?? 'MailWizz subscription failed.' ); ACQUIS_Database::log_integration( $lead_id, 'mailwizz', $success ? 'success' : 'failed', wp_json_encode( $response['body'] ?? array() ) ); return array( 'success' => $success, 'message' => $message ); } /** * Ping the API to test credentials. * * @param string $api_url * @param string $public_key * @param string $private_key * @return array ['success' => bool, 'message' => string] */ public static function test_connection( $api_url, $public_key, $private_key ) { $api_url = untrailingslashit( $api_url ); $endpoint = "{$api_url}/customers/profile"; $response = self::api_request( 'GET', $endpoint, array(), $public_key, $private_key ); $success = in_array( $response['http_code'] ?? 0, array( 200, 201 ), true ) && isset( $response['body']['status'] ) && $response['body']['status'] === 'success'; return array( 'success' => $success, 'message' => $success ? 'MailWizz connection successful.' : ( $response['body']['error'] ?? 'Connection failed.' ), ); } /** * Fetch available lists for the admin dropdown. * * @param string $api_url * @param string $public_key * @param string $private_key * @return array [['uid' => ..., 'name' => ...], ...] */ public static function get_lists( $api_url, $public_key, $private_key ) { $api_url = untrailingslashit( $api_url ); $response = self::api_request( 'GET', "{$api_url}/lists?per_page=100", array(), $public_key, $private_key ); if ( empty( $response['body']['data']['records'] ) ) return array(); return array_map( function( $list ) { return array( 'uid' => $list['list_uid'], 'name' => $list['name'] ); }, $response['body']['data']['records'] ); } public static function is_enabled() { return (bool) get_option( 'acquis_mailwizz_enabled', false ); } /** * MailWizz uses HMAC-SHA1 signed requests. * Signature = base64(HMAC-SHA1(timestamp + "\n" + public_key, private_key)) */ private static function build_signature( $public_key, $private_key ) { $timestamp = (string) time(); $signature = base64_encode( hash_hmac( 'sha1', $timestamp . "\n" . $public_key, $private_key, true ) ); return array( 'timestamp' => $timestamp, 'signature' => $signature ); } /** * Execute a signed API request. */ private static function api_request( $method, $url, $body, $public_key, $private_key ) { $sig = self::build_signature( $public_key, $private_key ); $headers = array( 'X-MW-PUBLIC-KEY' => $public_key, 'X-MW-TIMESTAMP' => $sig['timestamp'], 'X-MW-SIGNATURE' => $sig['signature'], 'Content-Type' => 'application/json', 'Accept' => 'application/json', ); $args = array( 'method' => strtoupper( $method ), 'headers' => $headers, 'timeout' => 15, ); if ( ! empty( $body ) ) { $args['body'] = wp_json_encode( $body ); } $response = wp_remote_request( $url, $args ); $http_code = wp_remote_retrieve_response_code( $response ); $raw_body = wp_remote_retrieve_body( $response ); $decoded = json_decode( $raw_body, true ); return array( 'http_code' => $http_code, 'body' => $decoded, 'raw' => $raw_body ); } }