.api.mailchimp.com/3.0'; /** * Subscribe a lead to the configured Mailchimp audience. * * @param int $lead_id * @param string $email * @param string $full_name * @return array ['success' => bool, 'message' => string] */ public static function subscribe( $lead_id, $email, $full_name ) { if ( ! self::is_enabled() ) { return array( 'success' => false, 'message' => 'Mailchimp 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_key =get_option( 'acquis_mailchimp_api_key', '' ); $list_id = get_option( 'acquis_mailchimp_list_id', '' ); $tags_raw = get_option( 'acquis_mailchimp_tags', '' ); $dbl_optin = (bool) get_option( 'acquis_mailchimp_double_optin', false ); if ( empty( $api_key ) || empty( $list_id ) ) { return array( 'success' => false, 'message' => 'Mailchimp API key or List ID not configured.' ); } // Parse data center from API key (e.g. us21 from xxxx-us21) $parts = explode( '-', $api_key ); $dc = count( $parts ) === 2 ? trim( $parts[1] ) : 'us1'; $base_url = str_replace( '', $dc, self::API_BASE ); $endpoint = "{$base_url}/lists/{$list_id}/members"; // Split name into first / last $name_parts = explode( ' ', trim( $full_name ), 2 ); $fname = $name_parts[0]; $lname = isset( $name_parts[1] ) ? $name_parts[1] : ''; $payload = array( 'email_address' => $email, 'status' => $dbl_optin ? 'pending' : 'subscribed', 'merge_fields' => array( 'FNAME' => $fname, 'LNAME' => $lname, ), ); // Tags $tags = array_filter( array_map( 'trim', explode( ',', $tags_raw ) ) ); if ( ! empty( $tags ) ) { $payload['tags'] = array_values( $tags ); } // If subscriber already exists, PATCH instead of POST (avoids error 400) $subscriber_hash = md5( strtolower( $email ) ); $check_url = "{$base_url}/lists/{$list_id}/members/{$subscriber_hash}"; $check_response = self::api_request( 'GET', $check_url, array(), $api_key ); $method = ( isset( $check_response['http_code'] ) && $check_response['http_code'] === 200 ) ? 'PUT' : 'POST'; $url = ( 'PUT' === $method ) ? $check_url : $endpoint; $response = self::api_request( $method, $url, $payload, $api_key ); $success = in_array( $response['http_code'] ?? 0, array( 200, 201 ), true ); $message = $success ? "Subscribed to Mailchimp list {$list_id}." : ( $response['body']['detail'] ?? 'Unknown Mailchimp API error.' ); ACQUIS_Database::log_integration( $lead_id, 'mailchimp', $success ? 'success' : 'failed', wp_json_encode( $response['body'] ?? array() ) ); // Apply tags separately (Mailchimp tags endpoint) if ( $success && ! empty( $tags ) ) { self::apply_tags( $base_url, $list_id, $subscriber_hash, $api_key, $tags ); } return array( 'success' => $success, 'message' => $message ); } /** * Apply tags via the member tags endpoint (POST). */ private static function apply_tags( $base_url, $list_id, $subscriber_hash, $api_key, $tags ) { $tags_payload = array( 'tags' => array_map( function( $t ) { return array( 'name' => $t, 'status' => 'active' ); }, $tags ), ); self::api_request( 'POST', "{$base_url}/lists/{$list_id}/members/{$subscriber_hash}/tags", $tags_payload, $api_key ); } /** * Fetch all available lists for the settings dropdown. * * @param string $api_key * @return array Array of ['id' => ..., 'name' => ...] */ public static function get_lists( $api_key ) { if ( empty( $api_key ) ) return array(); $parts = explode( '-', $api_key ); $dc = count( $parts ) === 2 ? trim( $parts[1] ) : 'us1'; $base_url = str_replace( '', $dc, self::API_BASE ); $response = self::api_request( 'GET', "{$base_url}/lists?count=100", array(), $api_key ); if ( empty( $response['body']['lists'] ) ) return array(); return array_map( function( $list ) { return array( 'id' => $list['id'], 'name' => $list['name'] ); }, $response['body']['lists'] ); } public static function is_enabled() { return (bool) get_option( 'acquis_mailchimp_enabled', false ); } /** * Shared HTTP helper using wp_remote_request. */ private static function api_request( $method, $url, $body, $api_key ) { $args = array( 'method' => strtoupper( $method ), 'headers' => array( 'Authorization' => 'Basic ' . base64_encode( 'anystring:' . $api_key ), 'Content-Type' => 'application/json', ), '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 ); } }