verify_signature( $payload, $signature ) ) { wp_die( 'Forbidden', 'Forbidden', [ 'response' => 403 ] ); } $data = json_decode( $payload, true ); if ( ! is_array( $data ) ) { wp_send_json( [ 'status' => 'error', 'message' => 'Invalid JSON' ], 400 ); } $action = $data['config']['action'] ?? ''; $api_url = $data['api_url'] ?? ''; // Extract EB event ID from the API URL (e.g. .../events/123456789/). $eb_event_id = $this->extract_event_id_from_url( $api_url ); switch ( $action ) { case 'event.published': case 'event.updated': if ( $eb_event_id ) { $this->event_sync->pull_event( $eb_event_id ); } break; case 'event.unpublished': if ( $eb_event_id ) { $this->handle_event_unpublished( $eb_event_id ); } break; case 'attendee.updated': $this->handle_attendee_updated( $data ); break; default: // Unknown action — acknowledge without processing. break; } wp_send_json( [ 'status' => 'ok' ], 200 ); } private function verify_signature( string $payload, string $signature ): bool { $secret = (string) get_option( 'eb4tec_webhook_secret', '' ); // If no secret is configured, skip verification (allows initial setup). if ( empty( $secret ) ) { return true; } if ( empty( $signature ) ) { return false; } $expected = hash_hmac( 'sha256', $payload, $secret ); return hash_equals( $expected, $signature ); } private function handle_event_unpublished( string $eb_event_id ): void { $query = new WP_Query( [ 'post_type' => 'tribe_events', 'post_status' => [ 'publish', 'draft' ], 'posts_per_page' => 1, 'fields' => 'ids', 'meta_query' => [ [ 'key' => '_eb4tec_event_id', 'value' => $eb_event_id, ] ], ] ); if ( ! empty( $query->posts ) ) { $post_id = $query->posts[0]; wp_update_post( [ 'ID' => $post_id, 'post_status' => 'draft', ] ); update_post_meta( $post_id, '_eb4tec_eb_status', 'unpublished' ); } } private function handle_attendee_updated( array $data ): void { // Extract attendee ID from the API URL if present. $api_url = $data['api_url'] ?? ''; $attendee_id = $this->extract_id_from_url( $api_url, 'attendees' ); if ( ! $attendee_id ) { return; } // Find any WC order that has this attendee and update its note. global $wpdb; $order_ids = $wpdb->get_col( $wpdb->prepare( "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_eb4tec_attendee_ids' AND meta_value LIKE %s", '%' . $wpdb->esc_like( $attendee_id ) . '%' ) ); foreach ( $order_ids as $order_id ) { $order = wc_get_order( $order_id ); if ( $order ) { $order->add_order_note( sprintf( __( 'EB4TEC: Eventbrite attendee %s was updated.', 'eb4tec' ), esc_html( $attendee_id ) ), false, false ); } } } private function extract_event_id_from_url( string $url ): string { return $this->extract_id_from_url( $url, 'events' ); } private function extract_id_from_url( string $url, string $resource ): string { // URLs look like: https://www.eventbriteapi.com/v3/events/123456789/ if ( preg_match( '#/' . preg_quote( $resource, '#' ) . '/(\d+)/#', $url, $matches ) ) { return $matches[1]; } return ''; } }