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(
'
',
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 );
}
} );