insert( $wpdb->prefix . 'woocommerce_api_keys', array( 'user_id' => get_current_user_id() ?: 1, 'description' => 'AgentCart', 'permissions' => 'read_write', 'consumer_key' => wc_api_hash( $consumer_key ), 'consumer_secret' => $consumer_secret, 'truncated_key' => $truncated_key, ), array( '%d', '%s', '%s', '%s', '%s', '%s' ) ); if ( $wpdb->insert_id ) { update_option( 'agentcart_consumer_key', $consumer_key ); update_option( 'agentcart_consumer_secret', $consumer_secret ); update_option( 'agentcart_truncated_key', $truncated_key ); return true; } return false; } /** * Check if WooCommerce is active and show admin notice if not. * * @return bool True if WooCommerce is active. */ function agentcart_check_woocommerce() { if ( ! class_exists( 'WooCommerce' ) ) { add_action( 'admin_notices', function () { printf( '

%s

', esc_html__( 'AgentCart requires WooCommerce to be installed and active.', 'agentcart' ) ); } ); return false; } return true; } /** * Activation hook — generate WC API keys and set default options. */ function agentcart_activate() { if ( ! class_exists( 'WooCommerce' ) ) { deactivate_plugins( plugin_basename( __FILE__ ) ); wp_die( esc_html__( 'AgentCart requires WooCommerce to be installed and active.', 'agentcart' ), esc_html__( 'Plugin Activation Error', 'agentcart' ), array( 'back_link' => true ) ); } if ( ! get_option( 'agentcart_consumer_key' ) ) { agentcart_generate_api_keys(); } if ( get_option( 'agentcart_connected' ) === false ) { update_option( 'agentcart_connected', false ); } if ( ! get_option( 'agentcart_merchant_id' ) ) { update_option( 'agentcart_merchant_id', '' ); } if ( ! get_option( 'agentcart_api_url' ) ) { update_option( 'agentcart_api_url', 'https://app.agentcart.io' ); } agentcart_rewrite_rules(); flush_rewrite_rules(); } register_activation_hook( __FILE__, 'agentcart_activate' ); /** * Deactivation hook — notify AgentCart and clean up transients. */ function agentcart_deactivate() { $merchant_id = get_option( 'agentcart_merchant_id' ); if ( $merchant_id && get_option( 'agentcart_connected' ) ) { wp_remote_post( AGENTCART_API_URL . '/api/woocommerce/disconnect', array( 'body' => wp_json_encode( array( 'merchant_id' => $merchant_id ) ), 'headers' => array( 'Content-Type' => 'application/json' ), 'timeout' => 5, ) ); } delete_option( 'agentcart_ucp_slug' ); global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- One-time removal of our own transients on deactivation; caching does not apply to a delete. $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", $wpdb->esc_like( '_transient_agentcart_' ) . '%', $wpdb->esc_like( '_transient_timeout_agentcart_' ) . '%' ) ); flush_rewrite_rules(); } register_deactivation_hook( __FILE__, 'agentcart_deactivate' ); /** * Initialize plugin — load classes and register hooks. */ function agentcart_init() { if ( ! agentcart_check_woocommerce() ) { return; } require_once AGENTCART_PLUGIN_DIR . 'includes/class-agentcart-connect.php'; require_once AGENTCART_PLUGIN_DIR . 'includes/class-agentcart-api.php'; if ( is_admin() ) { require_once AGENTCART_PLUGIN_DIR . 'admin/class-agentcart-settings.php'; new AgentCart_Settings(); } $api = new AgentCart_API(); $api->register_hooks(); } add_action( 'plugins_loaded', 'agentcart_init' ); /** * Fetch the UCP slug from AgentCart API and cache it locally. * * @return string|false The slug, or false on failure. */ function agentcart_fetch_slug() { $merchant_id = get_option( 'agentcart_merchant_id', '' ); if ( ! $merchant_id ) { return false; } $api_url = get_option( 'agentcart_api_url', 'https://app.agentcart.io' ); $response = wp_remote_get( $api_url . '/api/woocommerce/slug?merchant_id=' . rawurlencode( $merchant_id ), array( 'timeout' => 5 ) ); if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) !== 200 ) { return false; } $body = json_decode( wp_remote_retrieve_body( $response ), true ); if ( empty( $body['ucp_slug'] ) ) { return false; } $slug = sanitize_text_field( $body['ucp_slug'] ); update_option( 'agentcart_ucp_slug', $slug ); return $slug; } /** * Serve /.well-known/ucp manifest so AI agents can discover this store. * Uses parse_request to intercept before WordPress routing kicks in. */ function agentcart_serve_ucp_manifest( $wp ) { if ( ! isset( $wp->request ) || $wp->request !== '.well-known/ucp' ) { return; } if ( ! get_option( 'agentcart_connected', false ) ) { status_header( 404 ); header( 'Content-Type: application/json' ); echo wp_json_encode( array( 'error' => 'UCP not configured' ) ); exit; } $slug = get_option( 'agentcart_ucp_slug', '' ); // Fetch slug from AgentCart if not stored locally (e.g. paired before slug support) if ( ! $slug ) { $slug = agentcart_fetch_slug(); if ( ! $slug ) { status_header( 404 ); header( 'Content-Type: application/json' ); echo wp_json_encode( array( 'error' => 'UCP not configured' ) ); exit; } } $api_url = get_option( 'agentcart_api_url', 'https://app.agentcart.io' ); $endpoint = $api_url . '/api/ucp/' . $slug; $version = '2026-04-08'; $manifest = array( 'ucp' => array( 'version' => $version, 'services' => array( 'dev.ucp.shopping' => array( array( 'version' => $version, 'spec' => 'https://ucp.dev/2026-04-08/specification/overview/', 'transport' => 'rest', 'endpoint' => $endpoint, 'schema' => 'https://ucp.dev/2026-04-08/services/shopping/rest.openapi.json', ), array( 'version' => $version, 'spec' => 'https://ucp.dev/2026-04-08/specification/overview/', 'transport' => 'mcp', 'endpoint' => $endpoint . '/mcp', 'schema' => 'https://ucp.dev/2026-04-08/services/shopping/mcp.openrpc.json', ), ), ), 'capabilities' => array( 'dev.ucp.shopping.checkout' => array( array( 'version' => $version, 'spec' => 'https://ucp.dev/2026-04-08/specification/checkout', 'schema' => 'https://ucp.dev/2026-04-08/schemas/shopping/checkout.json', ), ), 'dev.ucp.shopping.catalog.search' => array( array( 'version' => $version, 'spec' => 'https://ucp.dev/2026-04-08/specification/catalog', 'schema' => 'https://ucp.dev/2026-04-08/schemas/shopping/catalog_search.json', ), ), 'dev.ucp.shopping.catalog.lookup' => array( array( 'version' => $version, 'spec' => 'https://ucp.dev/2026-04-08/specification/catalog', 'schema' => 'https://ucp.dev/2026-04-08/schemas/shopping/catalog_lookup.json', ), ), 'dev.ucp.shopping.cart' => array( array( 'version' => $version, 'spec' => 'https://ucp.dev/2026-04-08/specification/cart', 'schema' => 'https://ucp.dev/2026-04-08/schemas/shopping/cart.json', ), ), 'dev.ucp.shopping.order' => array( array( 'version' => $version, 'spec' => 'https://ucp.dev/2026-04-08/specification/order', 'schema' => 'https://ucp.dev/2026-04-08/schemas/shopping/order.json', ), ), 'dev.ucp.shopping.fulfillment' => array( array( 'version' => $version, 'spec' => 'https://ucp.dev/2026-04-08/specification/fulfillment', 'schema' => 'https://ucp.dev/2026-04-08/schemas/shopping/fulfillment.json', 'extends' => array( 'dev.ucp.shopping.checkout', 'dev.ucp.shopping.cart' ), ), ), 'dev.ucp.shopping.discount' => array( array( 'version' => $version, 'spec' => 'https://ucp.dev/2026-04-08/specification/discount', 'schema' => 'https://ucp.dev/2026-04-08/schemas/shopping/discount.json', 'extends' => array( 'dev.ucp.shopping.checkout', 'dev.ucp.shopping.cart' ), ), ), ), 'payment_handlers' => array( 'dev.ucp.payment.redirect' => array( array( 'id' => 'redirect', 'version' => $version, 'spec' => 'https://ucp.dev/2026-04-08/specification/checkout', 'schema' => 'https://ucp.dev/2026-04-08/schemas/shopping/payment.json', 'config' => array( 'redirect_url' => $endpoint . '/checkout-sessions', ), ), ), ), ), ); status_header( 200 ); header( 'Content-Type: application/json' ); header( 'Access-Control-Allow-Origin: *' ); header( 'Cache-Control: no-store' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo wp_json_encode( $manifest, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ); exit; } add_action( 'parse_request', 'agentcart_serve_ucp_manifest' ); /** * Register rewrite rule for /.well-known/ucp so WordPress routes it instead of 404. */ function agentcart_rewrite_rules() { add_rewrite_rule( '^\.well-known/ucp$', 'index.php', 'top' ); } add_action( 'init', 'agentcart_rewrite_rules' ); /** * Add "Settings" link on the Plugins page. * * @param array $links Existing plugin action links. * @return array Modified links. */ function agentcart_plugin_action_links( $links ) { $settings_link = sprintf( '%s', esc_url( admin_url( 'admin.php?page=agentcart-settings' ) ), esc_html__( 'Settings', 'agentcart' ) ); array_unshift( $links, $settings_link ); return $links; } add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'agentcart_plugin_action_links' ); /** * Declare compatibility with WooCommerce HPOS (High-Performance Order Storage). */ add_action( 'before_woocommerce_init', function () { if ( class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) { \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true ); } } );