false, 'code' => sanitize_key( (string) $code ), 'status' => sanitize_key( (string) $status ), 'message' => sanitize_text_field( (string) $message ), 'entitlement_decision' => 'unchanged', 'advisory_only' => true, 'source' => 'paid_licence_registry_client', 'checked_at' => time(), 'privacy_note' => 'No IP address, visitor data, chat content, lead content, raw WhatsApp number, raw admin email, or full raw licence key is collected by this advisory client.', ); if ( is_array( $extra ) && ! empty( $extra ) ) { $result = array_merge( $result, $extra ); } $result['entitlement_decision'] = 'unchanged'; $result['advisory_only'] = true; return $result; } } if ( ! function_exists( 'matewa_paid_licence_registry_get_stored_paid_result' ) ) { function matewa_paid_licence_registry_get_stored_paid_result( $licence_key = '' ) { if ( '' === trim( (string) $licence_key ) || ! function_exists( 'matewa_get_stored_license_validation_result' ) ) { return array(); } $stored = matewa_get_stored_license_validation_result( $licence_key ); return is_array( $stored ) ? $stored : array(); } } if ( ! function_exists( 'matewa_paid_licence_registry_build_payload' ) ) { function matewa_paid_licence_registry_build_payload( $licence_key = '', $extra = array() ) { $licence_key = trim( (string) $licence_key ); if ( '' === $licence_key && function_exists( 'matewa_get_license_key' ) ) { $licence_key = matewa_get_license_key(); } $is_founder_beta_key = function_exists( 'matewa_license_key_is_founder_beta_access' ) ? matewa_license_key_is_founder_beta_access( $licence_key ) : false; $paid_licence_key_for_hash = $is_founder_beta_key ? '' : $licence_key; $stored_paid_result = $is_founder_beta_key ? array() : matewa_paid_licence_registry_get_stored_paid_result( $licence_key ); $local_paid_valid = ! empty( $stored_paid_result['valid'] ); $founder_beta_last = function_exists( 'matewa_founder_beta_get_last_result' ) ? matewa_founder_beta_get_last_result() : array(); $founder_beta_last = is_array( $founder_beta_last ) ? $founder_beta_last : array(); $founder_beta_status = sanitize_key( (string) ( $founder_beta_last['status'] ?? '' ) ); $founder_beta_record_present = ! empty( $founder_beta_last['success'] ) && in_array( $founder_beta_status, array( 'active', 'converted', 'expired' ), true ); $founder_beta_active = function_exists( 'matewa_founder_beta_is_active' ) ? matewa_founder_beta_is_active() : false; if ( function_exists( 'matewa_trial_active' ) && matewa_trial_active() ) { $trial_status = 'trial_active'; } elseif ( function_exists( 'matewa_trial_expired' ) && matewa_trial_expired() ) { $trial_status = 'trial_expired'; } elseif ( function_exists( 'matewa_trial_has_started' ) && matewa_trial_has_started() ) { $trial_status = 'trial_started'; } else { $trial_status = 'trial_not_started'; } $conversion_observed = $local_paid_valid && $founder_beta_record_present; $payload = array( 'action' => 'paid_licence_registry_mirror', 'plugin' => '247chatmate', 'plugin_version' => defined( 'MATEWA_VERSION' ) ? (string) MATEWA_VERSION : '', 'site_url' => esc_url_raw( home_url( '/' ) ), 'domain' => matewa_paid_licence_registry_get_domain(), 'licence_key_hash' => matewa_paid_licence_registry_hash_licence_key( $paid_licence_key_for_hash ), 'local_paid_valid' => $local_paid_valid, 'local_paid_code' => sanitize_key( (string) ( $stored_paid_result['code'] ?? '' ) ), 'local_paid_source' => sanitize_key( (string) ( $stored_paid_result['source'] ?? '' ) ), 'local_plan_status' => function_exists( 'matewa_license_status' ) ? sanitize_key( (string) matewa_license_status() ) : '', 'founder_beta_active' => (bool) $founder_beta_active, 'founder_beta_status' => $founder_beta_status, 'founder_beta_source' => $founder_beta_record_present ? 'founder_beta_registry' : '', 'trial_status' => sanitize_key( $trial_status ), 'conversion_observed' => (bool) $conversion_observed, 'conversion_type' => $conversion_observed ? 'founder_beta_to_paid' : '', 'entitlement_decision' => 'unchanged', 'advisory_only' => true, 'request_created' => time(), ); if ( is_array( $extra ) && ! empty( $extra ) ) { foreach ( $extra as $key => $value ) { $key = sanitize_key( (string) $key ); if ( '' === $key || in_array( $key, array( 'ip', 'ip_address', 'ip_hash', 'hashed_ip', 'visitor_id', 'visitor_identifier', 'chat_content', 'chat_message', 'lead_content', 'lead_message', 'whatsapp_number', 'raw_whatsapp_number', 'admin_email', 'raw_admin_email', 'licence_key', 'license_key', 'raw_licence_key', 'raw_license_key', 'beta_code', 'founder_beta_code', 'founder_beta_invite_code', 'access_code', 'raw_founder_beta_invite_code' ), true ) ) { continue; } if ( is_scalar( $value ) || null === $value ) { $payload[ $key ] = sanitize_text_field( (string) $value ); } } } return $payload; } } if ( ! function_exists( 'matewa_paid_licence_registry_sanitise_result' ) ) { function matewa_paid_licence_registry_sanitise_result( $result ) { if ( ! is_array( $result ) ) { $result = array(); } return array( 'ok' => ! empty( $result['ok'] ), 'code' => sanitize_key( (string) ( $result['code'] ?? 'unknown' ) ), 'status' => sanitize_key( (string) ( $result['status'] ?? '' ) ), 'message' => sanitize_text_field( (string) ( $result['message'] ?? '' ) ), 'entitlement_decision' => 'unchanged', 'advisory_only' => true, 'source' => sanitize_key( (string) ( $result['source'] ?? 'paid_licence_registry_client' ) ), 'checked_at' => isset( $result['checked_at'] ) ? (int) $result['checked_at'] : time(), 'privacy_note' => 'No IP address, visitor data, chat content, lead content, raw WhatsApp number, raw admin email, or full raw licence key is collected by this advisory client.', ); } } if ( ! function_exists( 'matewa_paid_licence_registry_store_result' ) ) { function matewa_paid_licence_registry_store_result( $result ) { $safe = matewa_paid_licence_registry_sanitise_result( $result ); update_option( MATEWA_PAID_LICENCE_REGISTRY_LAST_RESULT_OPTION, $safe, false ); update_option( MATEWA_PAID_LICENCE_REGISTRY_LAST_SYNC_OPTION, time(), false ); return $safe; } } if ( ! function_exists( 'matewa_paid_licence_registry_store_error' ) ) { function matewa_paid_licence_registry_store_error( $result ) { $safe = matewa_paid_licence_registry_sanitise_result( $result ); update_option( MATEWA_PAID_LICENCE_REGISTRY_LAST_ERROR_OPTION, $safe, false ); update_option( MATEWA_PAID_LICENCE_REGISTRY_LAST_SYNC_OPTION, time(), false ); return $safe; } } if ( ! function_exists( 'matewa_paid_licence_registry_get_last_result' ) ) { function matewa_paid_licence_registry_get_last_result() { $result = get_option( MATEWA_PAID_LICENCE_REGISTRY_LAST_RESULT_OPTION, array() ); return is_array( $result ) ? matewa_paid_licence_registry_sanitise_result( $result ) : array(); } } if ( ! function_exists( 'matewa_paid_licence_registry_get_last_error' ) ) { function matewa_paid_licence_registry_get_last_error() { $result = get_option( MATEWA_PAID_LICENCE_REGISTRY_LAST_ERROR_OPTION, array() ); return is_array( $result ) ? matewa_paid_licence_registry_sanitise_result( $result ) : array(); } } if ( ! function_exists( 'matewa_paid_licence_registry_get_last_sync' ) ) { function matewa_paid_licence_registry_get_last_sync() { return (int) get_option( MATEWA_PAID_LICENCE_REGISTRY_LAST_SYNC_OPTION, 0 ); } } if ( ! function_exists( 'matewa_paid_licence_registry_manual_admin_sync' ) ) { function matewa_paid_licence_registry_manual_admin_sync() { if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) { return matewa_paid_licence_registry_store_error( matewa_paid_licence_registry_advisory_result( 'admin_required', 'Paid licence registry manual sync requires an authorised WordPress admin.', 'blocked' ) ); } if ( matewa_paid_licence_registry_is_cron_request() ) { return matewa_paid_licence_registry_store_error( matewa_paid_licence_registry_advisory_result( 'cron_blocked', 'Paid licence registry manual sync is not available to cron in this phase.', 'blocked' ) ); } if ( get_transient( MATEWA_PAID_LICENCE_REGISTRY_SYNC_LOCK_TRANSIENT ) ) { return matewa_paid_licence_registry_store_error( matewa_paid_licence_registry_advisory_result( 'sync_locked', 'Paid licence registry manual sync is already running. Try again shortly.', 'locked' ) ); } $lock_ttl = defined( 'MINUTE_IN_SECONDS' ) ? MINUTE_IN_SECONDS : 60; set_transient( MATEWA_PAID_LICENCE_REGISTRY_SYNC_LOCK_TRANSIENT, 1, $lock_ttl ); $payload = matewa_paid_licence_registry_build_payload( '', array( 'source_marker' => 'manual_admin_sync', 'sync_mode' => 'manual_admin_sync', ) ); $result = matewa_paid_licence_registry_post( $payload, true ); delete_transient( MATEWA_PAID_LICENCE_REGISTRY_SYNC_LOCK_TRANSIENT ); return $result; } } if ( ! function_exists( 'matewa_paid_licence_registry_post' ) ) { function matewa_paid_licence_registry_post( $payload = array(), $store_result = false ) { if ( ! matewa_paid_licence_registry_can_request() ) { $result = matewa_paid_licence_registry_advisory_result( 'frontend_blocked', 'Paid licence registry sync is blocked on normal frontend requests.', 'blocked' ); return $store_result ? matewa_paid_licence_registry_store_error( $result ) : $result; } if ( ! matewa_paid_licence_registry_is_configured() ) { $result = matewa_paid_licence_registry_advisory_result( 'registry_not_configured', 'Paid licence registry client is not configured.', 'not_configured' ); return $store_result ? matewa_paid_licence_registry_store_error( $result ) : $result; } if ( empty( $payload ) || ! is_array( $payload ) ) { $payload = matewa_paid_licence_registry_build_payload(); } $payload['entitlement_decision'] = 'unchanged'; $payload['advisory_only'] = true; $body = wp_json_encode( $payload, JSON_UNESCAPED_SLASHES ); if ( ! is_string( $body ) || '' === $body ) { $result = matewa_paid_licence_registry_advisory_result( 'invalid_payload', 'Paid licence registry payload could not be created.', 'invalid' ); return $store_result ? matewa_paid_licence_registry_store_error( $result ) : $result; } $timestamp = (string) time(); $signature = hash_hmac( 'sha256', $timestamp . '.' . $body, matewa_paid_licence_registry_get_secret() ); $response = wp_remote_post( matewa_paid_licence_registry_get_endpoint(), array( 'timeout' => MATEWA_PAID_LICENCE_REGISTRY_TIMEOUT, 'headers' => array( 'Content-Type' => 'application/json; charset=utf-8', 'X-Matewa-Timestamp' => $timestamp, 'X-Matewa-Signature' => $signature, 'X-Matewa-Registry' => 'paid-licence-v1', ), 'body' => $body, ) ); if ( is_wp_error( $response ) ) { $result = matewa_paid_licence_registry_advisory_result( 'registry_unavailable', 'Paid licence registry could not be reached.', 'unavailable' ); return $store_result ? matewa_paid_licence_registry_store_error( $result ) : $result; } $status_code = (int) wp_remote_retrieve_response_code( $response ); $response_body = (string) wp_remote_retrieve_body( $response ); $data = json_decode( $response_body, true ); if ( $status_code < 200 || $status_code >= 300 || ! is_array( $data ) ) { $result = matewa_paid_licence_registry_advisory_result( 'invalid_registry_response', 'Paid licence registry returned an invalid response.', 'invalid' ); return $store_result ? matewa_paid_licence_registry_store_error( $result ) : $result; } $data['source'] = 'paid_licence_registry'; $data['entitlement_decision'] = 'unchanged'; $data['advisory_only'] = true; $result = matewa_paid_licence_registry_sanitise_result( $data ); return $store_result ? matewa_paid_licence_registry_store_result( $result ) : $result; } }