This tutorial was written by Claude Code (an AI) and has not yet been reviewed. Follow along with caution. If the tutorial was helpful or a specific part was not clear/correct, please provide feedback at the bottom of the page. Thank you.
Consumer keys provide secure, authenticated access to the CoCart API. This guide covers setup and best practices for API authentication.
Overview
CoCart uses WooCommerce’s built-in consumer key/secret authentication system to provide secure API access. This OAuth 1.0a implementation ensures that only authorized applications can access your checkout API.
Why Consumer Keys?
Security Prevents unauthorized access to your checkout API and customer data
Rate Limiting Built-in request throttling and abuse protection per application
Audit Trail Track which applications are making requests and monitor usage
Granular Control Different permission levels and access controls per application
Step 1: Generate Consumer Keys
Via WordPress Admin
Navigate to WooCommerce Settings
WooCommerce → Settings → Advanced → REST API
Click “Add Key”
Configure Key Settings
Description : Enter a meaningful name (e.g., “Mobile App - Production”)
User : Select a user account (typically an admin)
Permissions : Choose appropriate level:
Read
- For read-only access (GET requests only)
Write
- For write access (POST, PUT, DELETE)
Read/Write
- Full access (recommended for checkout)
Generate and Save Keys
Consumer Key : Starts with ck_
(public identifier)
Consumer Secret : Starts with cs_
(private secret)
Copy and securely store both keys immediately. The consumer secret cannot be retrieved again after this screen.
Via WP-CLI
# Generate read/write API key
wp wc api create --user=1 --description= "CoCart Mobile App" --permissions=read_write
# Generate read-only API key
wp wc api create --user=1 --description= "CoCart Analytics" --permissions=read
Programmatically (PHP)
// Generate consumer keys programmatically
function generate_cocart_api_keys ( $description , $user_id , $permissions = 'read_write' ) {
global $wpdb ;
$consumer_key = 'ck_' . wc_rand_hash ();
$consumer_secret = 'cs_' . wc_rand_hash ();
$data = array (
'user_id' => $user_id ,
'description' => $description ,
'permissions' => $permissions ,
'consumer_key' => wc_api_hash ( $consumer_key ),
'consumer_secret' => $consumer_secret ,
'truncated_key' => substr ( $consumer_key , - 7 ),
);
$wpdb -> insert (
$wpdb -> prefix . 'woocommerce_api_keys' ,
$data ,
array ( '%d' , '%s' , '%s' , '%s' , '%s' , '%s' )
);
return array (
'consumer_key' => $consumer_key ,
'consumer_secret' => $consumer_secret ,
'key_id' => $wpdb -> insert_id
);
}
Development Environment
// Store in environment variables
const config = {
consumer_key: process . env . COCART_DEV_CONSUMER_KEY ,
consumer_secret: process . env . COCART_DEV_CONSUMER_SECRET ,
api_url: 'https://dev.yourstore.com/wp-json/cocart/preview'
};
Production Environment
// Use secure configuration management
const config = {
consumer_key: process . env . COCART_PROD_CONSUMER_KEY ,
consumer_secret: process . env . COCART_PROD_CONSUMER_SECRET ,
api_url: 'https://yourstore.com/wp-json/cocart/preview'
};
Environment Variables (.env)
# Development
COCART_DEV_CONSUMER_KEY = ck_dev_1234567890abcdef
COCART_DEV_CONSUMER_SECRET = cs_dev_1234567890abcdef
# Production
COCART_PROD_CONSUMER_KEY = ck_prod_1234567890abcdef
COCART_PROD_CONSUMER_SECRET = cs_prod_1234567890abcdef
# API URLs
COCART_DEV_API_URL = https://dev.yourstore.com/wp-json/cocart/preview
COCART_PROD_API_URL = https://yourstore.com/wp-json/cocart/preview
Step 3: Implement Authentication in Your Application
Basic Implementation
class CoCartAPI {
constructor ( config ) {
this . consumerKey = config . consumer_key ;
this . consumerSecret = config . consumer_secret ;
this . baseURL = config . api_url ;
}
async makeRequest ( endpoint , options = {}) {
const url = new URL ( ` ${ this . baseURL }${ endpoint } ` );
// Add authentication parameters
url . searchParams . append ( 'consumer_key' , this . consumerKey );
url . searchParams . append ( 'consumer_secret' , this . consumerSecret );
const response = await fetch ( url . toString (), {
... options ,
headers: {
'Content-Type' : 'application/json' ,
... options . headers
}
});
if ( ! response . ok ) {
const error = await response . json ();
throw new Error ( error . message || `HTTP ${ response . status } ` );
}
return response . json ();
}
}
// Usage
const api = new CoCartAPI ({
consumer_key: 'ck_1234567890abcdef' ,
consumer_secret: 'cs_1234567890abcdef' ,
api_url: '/wp-json/cocart/preview'
});
Advanced Implementation with OAuth Signature
// Using oauth-1.0a library for proper OAuth implementation
import OAuth from 'oauth-1.0a' ;
import crypto from 'crypto' ;
class SecureCoCartAPI {
constructor ( config ) {
this . oauth = OAuth ({
consumer: {
key: config . consumer_key ,
secret: config . consumer_secret
},
signature_method: 'HMAC-SHA1' ,
hash_function : ( baseString , key ) => {
return crypto . createHmac ( 'sha1' , key )
. update ( baseString )
. digest ( 'base64' );
}
});
this . baseURL = config . api_url ;
}
async makeRequest ( endpoint , options = {}) {
const url = ` ${ this . baseURL }${ endpoint } ` ;
const method = options . method || 'GET' ;
// Generate OAuth authorization data
const requestData = {
url: url ,
method: method
};
const authHeader = this . oauth . toHeader ( this . oauth . authorize ( requestData ));
const response = await fetch ( url , {
... options ,
method ,
headers: {
'Content-Type' : 'application/json' ,
'Authorization' : authHeader . Authorization ,
... options . headers
}
});
return this . handleResponse ( response );
}
}
Step 4: Handle Customer Authentication
For Registered Customers
class CustomerCoCartAPI extends CoCartAPI {
constructor ( config ) {
super ( config );
this . cartKey = config . cart_key ;
}
async makeRequest ( endpoint , options = {}) {
const url = new URL ( ` ${ this . baseURL }${ endpoint } ` );
// Add authentication
url . searchParams . append ( 'consumer_key' , this . consumerKey );
url . searchParams . append ( 'consumer_secret' , this . consumerSecret );
// Cart key contains customer context automatically
const headers = {
'Content-Type' : 'application/json' ,
... options . headers
};
if ( this . cartKey ) {
headers [ 'Cart-Key' ] = this . cartKey ;
}
return super . makeRequest ( endpoint , {
... options ,
url: url . toString (),
headers
});
}
// Update cart key when cart changes
updateCartKey ( cartKey ) {
this . cartKey = cartKey ;
}
}
// Usage with cart context (automatically includes customer info)
const customerAPI = new CustomerCoCartAPI ({
consumer_key: 'ck_1234567890abcdef' ,
consumer_secret: 'cs_1234567890abcdef' ,
cart_key: 'user-cart-key-here' , // Cart key includes customer context
api_url: '/wp-json/cocart/preview'
});
Dynamic Customer Handling
// Handle login/logout events
function handleUserLogin ( newCartKey ) {
// Update API instance with new cart key (contains customer context)
coCartAPI . updateCartKey ( newCartKey );
// Refresh any cached data
refreshCheckoutData ();
}
function handleUserLogout () {
// Switch to guest cart key or create new session
const guestCartKey = createGuestCartSession ();
coCartAPI . updateCartKey ( guestCartKey );
// Clear sensitive cached data
clearCustomerData ();
}
// Helper function to create guest cart session
function createGuestCartSession () {
// This would typically make a request to create a new cart
return 'guest-cart-key-' + generateUniqueId ();
}
Step 5: Security Best Practices
Key Storage
Never store consumer secrets in client-side code // ❌ DON'T DO THIS - Exposes secret to users
const config = {
consumer_key: 'ck_1234567890abcdef' ,
consumer_secret: 'cs_1234567890abcdef' // Visible in browser
};
// ✅ DO THIS - Use a backend proxy
const config = {
consumer_key: 'ck_1234567890abcdef' ,
// Consumer secret handled by your backend
};
Use environment variables or secure configuration // ✅ Good - Environment variables
$consumer_key = $_ENV [ 'COCART_CONSUMER_KEY' ];
$consumer_secret = $_ENV [ 'COCART_CONSUMER_SECRET' ];
// ✅ Good - WordPress options (if properly secured)
$consumer_key = get_option ( 'cocart_consumer_key' );
$consumer_secret = get_option ( 'cocart_consumer_secret' );
Use secure storage mechanisms // React Native example with Keychain/Keystore
import { setInternetCredentials , getInternetCredentials } from 'react-native-keychain' ;
// Store securely
await setInternetCredentials ( 'cocart-api' , consumerKey , consumerSecret );
// Retrieve securely
const credentials = await getInternetCredentials ( 'cocart-api' );
Key Rotation
class RotatingKeyAPI extends CoCartAPI {
constructor ( config ) {
super ( config );
this . backupKeys = config . backup_keys || [];
}
async makeRequest ( endpoint , options = {}) {
try {
// Try primary keys first
return await super . makeRequest ( endpoint , options );
} catch ( error ) {
if ( error . status === 401 && this . backupKeys . length > 0 ) {
// Try backup keys if primary fails
return await this . tryBackupKeys ( endpoint , options );
}
throw error ;
}
}
async tryBackupKeys ( endpoint , options ) {
for ( const backupKey of this . backupKeys ) {
try {
// Temporarily use backup keys
const originalKey = this . consumerKey ;
const originalSecret = this . consumerSecret ;
this . consumerKey = backupKey . key ;
this . consumerSecret = backupKey . secret ;
const result = await super . makeRequest ( endpoint , options );
// Restore original keys
this . consumerKey = originalKey ;
this . consumerSecret = originalSecret ;
return result ;
} catch ( backupError ) {
continue ; // Try next backup key
}
}
throw new Error ( 'All authentication keys failed' );
}
}
Step 6: Monitor and Manage API Keys
Key Usage Monitoring
-- Check API key usage
SELECT
k . description ,
k . permissions ,
k . last_access ,
COUNT ( l . log_id ) as request_count
FROM wp_woocommerce_api_keys k
LEFT JOIN wp_wc_webhooks_deliveries l ON k . key_id = l . webhook_id
WHERE k . consumer_key LIKE 'ck_%'
GROUP BY k . key_id ;
Automated Key Management
// WordPress cron job for key management
add_action ( 'wp' , 'schedule_api_key_cleanup' );
function schedule_api_key_cleanup () {
if ( ! wp_next_scheduled ( 'cocart_cleanup_old_keys' )) {
wp_schedule_event ( time (), 'daily' , 'cocart_cleanup_old_keys' );
}
}
add_action ( 'cocart_cleanup_old_keys' , 'cleanup_unused_api_keys' );
function cleanup_unused_api_keys () {
global $wpdb ;
// Disable keys not used in 90 days
$wpdb -> query ( "
UPDATE { $wpdb -> prefix }woocommerce_api_keys
SET permissions = 'disabled'
WHERE last_access < DATE_SUB(NOW(), INTERVAL 90 DAY)
AND permissions != 'disabled'
" );
// Log the cleanup
error_log ( 'CoCart: Cleaned up unused API keys' );
}
Troubleshooting
Common Issues
401 Unauthorized Causes:
Invalid consumer key/secret
Key disabled or expired
Incorrect permissions
Solutions:
Verify key exists in WooCommerce
Check key permissions
Regenerate if necessary
403 Forbidden Causes:
Read-only key used for write operations
Cart session access violation
Rate limiting triggered
Solutions:
Check key permissions
Verify cart key ownership
Implement rate limit handling
Rate Limiting Causes:
Too many requests per timeframe
Shared keys across applications
Solutions:
Implement request queuing
Use separate keys per app
Add retry logic with backoff
Key Exposure Causes:
Keys in client-side code
Keys in version control
Insecure transmission
Solutions:
Use backend proxy
Environment variables
HTTPS only
Payment Gateway Issues Causes:
Gateway configuration mismatch
Missing credentials
Environment misalignment
Solutions:
Use payment methods debug endpoint
Verify gateway credentials match
Check test vs production settings
Debug Mode
class DebugCoCartAPI extends CoCartAPI {
constructor ( config ) {
super ( config );
this . debug = config . debug || false ;
}
async makeRequest ( endpoint , options = {}) {
if ( this . debug ) {
console . group ( 'CoCart API Request' );
console . log ( 'Endpoint:' , endpoint );
console . log ( 'Method:' , options . method || 'GET' );
console . log ( 'Consumer Key:' , this . consumerKey );
console . log ( 'Options:' , options );
}
try {
const result = await super . makeRequest ( endpoint , options );
if ( this . debug ) {
console . log ( 'Response:' , result );
console . groupEnd ();
}
return result ;
} catch ( error ) {
if ( this . debug ) {
console . error ( 'Error:' , error );
console . groupEnd ();
}
throw error ;
}
}
}
Payment Gateway Debugging
For admin users, the payment methods endpoint provides debug information to help understand gateway configurations:
class AdminCoCartAPI extends CoCartAPI {
constructor ( config ) {
super ( config );
this . isAdmin = config . is_admin || false ;
}
/**
* Get payment methods with debug info (admin only)
*/
async getPaymentMethodsWithDebug () {
if ( ! this . isAdmin ) {
throw new Error ( 'Debug information requires admin privileges' );
}
const response = await this . makeRequest ( '/checkout/payment-methods' , {
method: 'GET' ,
headers: {
'Authorization' : `Bearer ${ this . adminJwtToken } ` // Admin JWT required
}
});
return response ;
}
/**
* Log debug information for payment methods
*/
async debugPaymentMethods () {
try {
const methods = await this . getPaymentMethodsWithDebug ();
console . group ( 'Payment Methods Debug' );
console . log ( 'Available Methods:' , methods . payment_methods );
if ( methods . debug_info ) {
console . group ( 'Gateway Debug Information' );
console . warn ( '🚨 Debug info - DO NOT use in production' );
Object . entries ( methods . debug_info . payment_context ). forEach (([ gateway , config ]) => {
console . group ( ` ${ gateway . toUpperCase () } Configuration` );
console . log ( 'Gateway Config:' , config );
console . groupEnd ();
});
console . groupEnd ();
}
console . groupEnd ();
} catch ( error ) {
console . error ( 'Payment methods debug failed:' , error );
}
}
}
// Usage for admin debugging
const adminAPI = new AdminCoCartAPI ({
consumer_key: 'ck_admin_key' ,
consumer_secret: 'cs_admin_secret' ,
cart_key: 'admin-cart-key' ,
is_admin: true ,
admin_jwt_token: 'admin_jwt_token_here' ,
api_url: '/wp-json/cocart/preview'
});
// Debug payment gateway configurations
await adminAPI . debugPaymentMethods ();
Example Debug Response:
{
"payment_methods" : {
"stripe" : {
"id" : "stripe" ,
"title" : "Credit Card" ,
"enabled" : true
},
"paypal" : {
"id" : "paypal" ,
"title" : "PayPal" ,
"enabled" : true
}
},
"debug_info" : {
"payment_context" : {
"stripe" : {
"publishable_key" : "pk_test_xxx" ,
"webhook_endpoint" : "/wc-api/stripe" ,
"gateway_mode" : "test"
},
"paypal" : {
"client_id" : "paypal_client_id_xxx" ,
"environment" : "sandbox"
}
},
"note" : "Debug information - DO NOT use in production"
}
}
Important Security Notes:
Debug information is only available to users with manage_options
capability
Debug info should never be used in production applications
Use this only for development, testing, and troubleshooting gateway configurations
Ensure your admin JWT tokens are properly secured
Integration Examples
WordPress Plugin
// Add consumer key settings to admin
class CoCart_Admin_Settings {
public function add_settings_fields () {
add_settings_field (
'cocart_consumer_key' ,
__ ( 'Consumer Key' , 'cocart' ),
array ( $this , 'consumer_key_field' ),
'cocart-settings'
);
add_settings_field (
'cocart_consumer_secret' ,
__ ( 'Consumer Secret' , 'cocart' ),
array ( $this , 'consumer_secret_field' ),
'cocart-settings'
);
}
public function consumer_key_field () {
$value = get_option ( 'cocart_consumer_key' );
echo '<input type="text" name="cocart_consumer_key" value="' . esc_attr ( $value ) . '" class="regular-text" />' ;
echo '<p class="description">' . __ ( 'WooCommerce API consumer key for CoCart authentication.' , 'cocart' ) . '</p>' ;
}
}
React/Next.js Integration
// components/CoCartProvider.js
import { createContext , useContext , useState } from 'react' ;
const CoCartContext = createContext ();
export function CoCartProvider ({ children }) {
const [ api ] = useState (() => new CoCartAPI ({
consumer_key: process . env . NEXT_PUBLIC_COCART_CONSUMER_KEY ,
consumer_secret: process . env . COCART_CONSUMER_SECRET , // Server-side only
api_url: process . env . NEXT_PUBLIC_COCART_API_URL
}));
return (
< CoCartContext.Provider value = { api } >
{ children }
</ CoCartContext.Provider >
);
}
export const useCoCart = () => {
const context = useContext ( CoCartContext );
if ( ! context ) {
throw new Error ( 'useCoCart must be used within CoCartProvider' );
}
return context ;
};
Remember to never expose consumer secrets in client-side applications. Use backend proxies or server-side rendering to handle secret authentication securely.