| name | violetconnect-woocommerce |
| description | WooCommerce REST API authentication and credential-based onboarding patterns for VioletConnect |
VioletConnect: WooCommerce Integration
Overview
VioletConnect integrates with WooCommerce via REST API Keys (not centralized OAuth). Each WooCommerce store is self-hosted on WordPress, so merchants must generate API keys manually and enter them in VioletConnect.
Integration Type: REST API Keys (no centralized OAuth)
Store Identifier: Store URL (any WordPress domain)
Credential Storage: consumerKey + consumerSecret
Authentication: HTTP Basic Auth
Pre-Registration Support: Flows B and C only (no Flow A - WC has no OAuth)
Related Skills:
- violetconnect: Core VioletConnect features and architecture
- violetconnect-patterns: Code patterns (Redux, axiosWrapper, AppContext)
- v-woocommerce: General WooCommerce API patterns and integration details
WooCommerce Authentication Flow
Key Difference: No OAuth
WooCommerce does NOT have centralized OAuth like Shopify or BigCommerce. Instead:
- Each WooCommerce store is self-hosted on WordPress
- No central OAuth server exists
- Merchants generate REST API keys in WordPress admin
- Keys are entered manually in VioletConnect
- Validation via test API call
Why No OAuth: WooCommerce is open-source software installed on merchants' own servers. There's no central authority like Shopify or BigCommerce to manage OAuth.
REST API Credentials Flow
1. Merchant lands on VioletConnect: connect.violet.io/{appAlias}/platforms/woocommerce
2. Merchant enters email → Creates session
3. Merchant selects "WooCommerce" platform
4. Merchant enters store URL (e.g., "https://mystore.com")
5. VioletConnect validates URL format (any domain)
6. VioletConnect shows credential entry form
7. Merchant enters WooCommerce REST API credentials:
- Consumer Key (e.g., "ck_abc123...")
- Consumer Secret (e.g., "cs_xyz789...")
8. VioletConnect validates credentials via test API call
9. If valid: Create merchant record in MerchantService
10. Merchant completes commission/payout setup
11. Merchant redirected to success page
Security Note: Credentials are never stored client-side. They are sent directly to the backend via API proxy.
REST API Implementation Details
Dynamic Routing
Page Files:
pages/[appAlias]/platforms/woocommerce/
├── index.tsx # Store URL + credentials entry
└── callback.tsx # Not used (no OAuth redirect)
Key Utility Files:
// utils/woocommerce/validation.ts
// Store URL validation (any valid URL)
// Credential validation via test API call
// utils/woocommerce/auth.ts
// Basic Auth header construction
Note: There is no callback.tsx page needed for WooCommerce since there's no OAuth redirect.
Credential Structure
interface WooCommerceCredentials {
storeUrl: string; // e.g., "https://mystore.com"
consumerKey: string; // e.g., "ck_abc123def456..."
consumerSecret: string; // e.g., "cs_xyz789ghi012..."
}
Consumer Key Format: Starts with ck_
Consumer Secret Format: Starts with cs_
Validation: Test API Call
Validate credentials by making a test call to the WooCommerce REST API:
// Validate credentials by calling WC REST API
async function validateCredentials(creds: WooCommerceCredentials): Promise<{
valid: boolean;
wcVersion?: string;
error?: string;
}> {
try {
// Construct Basic Auth header
const auth = Buffer.from(
`${creds.consumerKey}:${creds.consumerSecret}`
).toString('base64');
// Test API call to system_status endpoint
const response = await axios.get(
`${creds.storeUrl}/wp-json/wc/v3/system_status`,
{
headers: {
Authorization: `Basic ${auth}`,
'Content-Type': 'application/json'
},
timeout: 10000 // 10 second timeout
}
);
// Success - credentials are valid
return {
valid: true,
wcVersion: response.data.environment?.version || 'Unknown'
};
} catch (error: any) {
// Failed - credentials invalid or other error
return {
valid: false,
error: error.response?.data?.message || error.message || 'Validation failed'
};
}
}
Why /wp-json/wc/v3/system_status:
- Requires valid credentials (will return 401 if invalid)
- Returns WooCommerce version (useful for debugging)
- Doesn't modify any data (read-only endpoint)
Credential Entry UX
Key Generation Instructions
Merchants must generate REST API keys in their WordPress Admin panel. VioletConnect should guide them through this process.
Step-by-Step Instructions to Show Merchant:
1. Log in to your WordPress Admin Dashboard
2. Navigate to: WooCommerce → Settings
3. Click the "Advanced" tab
4. Click "REST API"
5. Click "Add Key" button
6. Configure the key:
- Description: "Violet Integration"
- User: Select an admin user
- Permissions: Read/Write
7. Click "Generate API Key"
8. Copy the Consumer Key and Consumer Secret
(You'll only see these once!)
Visual Aid: Consider adding screenshots or a link to WooCommerce docs: https://woocommerce.com/document/woocommerce-rest-api/
Credential Form Component
<WooCommerceCredentialForm
onSubmit={async (data: WooCommerceCredentials) => {
// Show loading state
setValidating(true);
// Validate credentials
const validation = await validateCredentials(data);
setValidating(false);
if (validation.valid) {
// Success - create merchant
await createMerchant({
platform: 'woocommerce',
storeUrl: data.storeUrl,
credentials: {
consumerKey: data.consumerKey,
consumerSecret: data.consumerSecret
}
});
// Redirect to commission setup
router.push(`/${appAlias}/commission`);
} else {
// Show error
setError(validation.error || 'Invalid credentials');
}
}}
>
<input
name="consumerKey"
placeholder="Consumer Key (ck_...)"
required
/>
<input
name="consumerSecret"
type="password"
placeholder="Consumer Secret (cs_...)"
required
/>
<HelpText>
<a
href="https://woocommerce.com/document/woocommerce-rest-api/"
target="_blank"
rel="noopener noreferrer"
>
How to generate API keys
</a>
</HelpText>
<Checkbox required>
I understand these credentials will be used to:
- Read products, orders, and customers
- Create orders on my behalf
- Update order statuses
</Checkbox>
<button type="submit" disabled={validating}>
{validating ? 'Validating...' : 'Validate & Connect'}
</button>
</WooCommerceCredentialForm>
Security Best Practice
CRITICAL: Always show merchants what the credentials will be used for:
- Read products, orders, customers
- Create orders on their behalf
- Update order statuses
Require explicit consent: Merchant must check "I understand and approve" before submitting credentials.
Why: Builds trust and ensures merchants understand what permissions they're granting.
Pre-Registration Integration
WooCommerce supports Flow B (Store URL Lookup) and Flow C (MerchantId Link) only.
No Flow A: WooCommerce has no OAuth, so there's no "direct install link" pattern.
Flow B: Store URL Lookup
- Merchant enters WooCommerce store URL on VioletConnect
- VioletConnect calls
/api/pre-register/lookup?storeUrl={url}&appId={appId} - If found:
- Show
PreRegFoundcomponent - Display merchant name + store URL
- "Connect to WooCommerce" button → Goes to credential entry form
- Show
- If not found: Continue normal email-first flow
API Endpoint:
// pages/api/pre-register/lookup.ts
GET /api/pre-register/lookup?storeUrl=https://mystore.com&appId=1
Response (if found): {
merchantId: 123,
merchantName: "My Store",
storeUrl: "https://mystore.com",
platform: "woocommerce",
installLink: null, // WC has no install link
credentials: {
consumerKey: "ck_...", // Pre-stored
consumerSecret: "cs_..." // Pre-stored
},
status: "pending"
}
Response (if not found): 404
Note: For WooCommerce, pre-registration can store credentials (consumerKey + consumerSecret) upfront, but merchant must still review and approve before submission (security).
Flow C: MerchantId Link
- Channel sends link:
connect.violet.io/{appAlias}?merchantId={id} - AppContext detects
merchantIdquery param - Dispatches
lookupByMerchantId(merchantId) - If found: Redirect to
/pre-registration/confirm - Merchant reviews pre-stored credentials
- Merchant clicks "Approve and Connect"
- VioletConnect validates credentials via test API call
- If valid: Create merchant record
Confirmation Page:
// pages/[appAlias]/pre-registration/confirm.tsx
<PreRegConfirmation
preRegistration={current}
onConfirm={async () => {
// Validate credentials before creating merchant
const validation = await validateCredentials({
storeUrl: current.storeUrl,
consumerKey: current.credentials.consumerKey,
consumerSecret: current.credentials.consumerSecret
});
if (validation.valid) {
// Create merchant
await createMerchant({
merchantId: current.merchantId,
platform: 'woocommerce',
storeUrl: current.storeUrl,
credentials: current.credentials
});
router.push(`/${appAlias}/success`);
} else {
setError('Credentials are no longer valid. Please contact support.');
}
}}
/>
WooCommerce Constraint: Even with pre-registered credentials, merchant should review before submitting (security best practice).
WooCommerce Components
StoreUrlInput (WooCommerce)
// Validates any valid URL (WC can be on any domain)
const wcUrlPattern = /^https?:\/\/.+\.[a-z]{2,}$/i;
<StoreUrlForm
platform="woocommerce"
placeholder="https://mystore.com"
validation={wcUrlPattern}
helpText="Enter your WordPress store URL"
onSubmit={handleStoreUrlSubmit}
errorMessage="Invalid URL format"
/>
Key Difference: Unlike Shopify (*.myshopify.com) or BigCommerce (store-*.mybigcommerce.com), WooCommerce URLs can be any domain.
CredentialForm
<WooCommerceCredentialForm>
{/* Consumer Key Input */}
<input
name="consumerKey"
placeholder="Consumer Key (ck_...)"
pattern="^ck_[a-zA-Z0-9]+"
/>
{/* Consumer Secret Input */}
<input
name="consumerSecret"
type="password"
placeholder="Consumer Secret (cs_...)"
pattern="^cs_[a-zA-Z0-9]+"
/>
{/* Help Text */}
<HelpText>
<a href="https://woocommerce.com/document/woocommerce-rest-api/" target="_blank">
How to generate API keys
</a>
</HelpText>
{/* Consent Checkbox */}
<Checkbox required>
I understand these credentials will be used to read products, orders, and customers
</Checkbox>
{/* Submit Button */}
<button type="submit">Validate & Connect</button>
</WooCommerceCredentialForm>
CredentialValidator
// Real-time credential validation
const [validating, setValidating] = useState(false);
const [validationMessage, setValidationMessage] = useState<string>('');
const onValidate = async () => {
setValidating(true);
setValidationMessage('');
const result = await validateCredentials(formData);
setValidating(false);
if (result.valid) {
setValidationMessage(`✓ Connected to WooCommerce ${result.wcVersion}`);
} else {
setValidationMessage(`✗ ${result.error}`);
}
};
return (
<div>
<button onClick={onValidate} disabled={validating}>
{validating ? 'Validating...' : 'Test Credentials'}
</button>
{validationMessage && <p className={result.valid ? 'success' : 'error'}>{validationMessage}</p>}
</div>
);
Error Handling
WooCommerce-Specific Errors
| Error | Trigger | User Message | Recovery |
|---|---|---|---|
| Invalid Store URL | URL doesn't respond or times out | "Could not connect to store. Please check the URL." | Re-enter URL |
| Invalid Credentials | REST API returns 401 Unauthorized | "Invalid credentials. Please check your Consumer Key and Secret." | Re-enter credentials |
| WC Not Installed | /wp-json/wc/v3 returns 404 |
"WooCommerce is not installed on this store." | Install WooCommerce plugin |
| Insufficient Permissions | API key has read-only access | "API key must have Read/Write permissions." | Generate new key with correct permissions |
| Plugin Conflict | REST API error 500 | "Store configuration error. Please contact support." | Disable conflicting plugins |
| SSL Required | HTTP URL provided (WC requires HTTPS) | "HTTPS is required for WooCommerce API. Please use https://" | Use HTTPS URL |
| Firewall Blocking | Connection timeout | "Could not reach your store. Check firewall settings." | Whitelist VioletConnect IPs |
Error Component
<WCError
error={error}
onRetry={() => {
setCredentials(null);
setError(null);
}}
supportUrl={channelConfig.supportUrl}
channelName={channelName}
/>
Error Recovery Patterns:
- Invalid credentials: Allow merchant to re-enter
- WC not installed: Show installation instructions
- Permissions issue: Show key generation instructions with emphasis on "Read/Write"
Testing
Local Setup (Docker Compose)
Set up a local WordPress + WooCommerce environment:
# docker-compose.yml
version: '3'
services:
wordpress:
image: wordpress:latest
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: password
volumes:
- ./wordpress:/var/www/html
woocommerce:
image: woocommerce/woocommerce:latest
depends_on:
- wordpress
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: wordpress
volumes:
- ./db:/var/lib/mysql
Setup Steps:
# Start containers
docker-compose up -d
# Access WordPress
# URL: http://localhost:8080
# Complete WordPress setup
# Install WooCommerce plugin (should auto-install with woocommerce image)
# Navigate to WooCommerce → Settings → Advanced → REST API
# Generate API keys
E2E Testing
// tests/e2e/woocommerce-credentials.spec.ts
import { test, expect } from '@playwright/test';
test('WooCommerce credential flow with pre-registration', async ({ page }) => {
// Navigate to WooCommerce platform page
await page.goto('http://localhost:3001/testchannel/platforms/woocommerce');
// Enter store URL
await page.fill('[name="storeUrl"]', 'https://mystore.test');
await page.click('button[type="submit"]');
// Verify pre-registration found
await expect(page.locator('text=Your store is already set up!')).toBeVisible();
await expect(page.locator('text=My Store')).toBeVisible();
// Click "Review Credentials"
await page.click('text=Review Credentials');
// Should show pre-filled credentials (masked)
await expect(page.locator('input[name="consumerKey"]')).toHaveValue(/^ck_/);
await expect(page.locator('input[name="consumerSecret"]')).toHaveAttribute('type', 'password');
// Check consent checkbox
await page.check('input[type="checkbox"][required]');
// Click "Approve and Connect"
await page.click('text=Approve and Connect');
// Should validate and create merchant
await expect(page.locator('text=Successfully connected')).toBeVisible();
});
Unit Testing
// tests/unit/woocommerce-validation.test.ts
import { validateCredentials } from '@/utils/woocommerce/validation';
import axios from 'axios';
jest.mock('axios');
describe('WooCommerce Credential Validation', () => {
const validCreds = {
storeUrl: 'https://test.com',
consumerKey: 'ck_test123',
consumerSecret: 'cs_test456'
};
test('validates correct credentials', async () => {
(axios.get as jest.Mock).mockResolvedValue({
data: {
environment: {
version: '6.5.0'
}
}
});
const result = await validateCredentials(validCreds);
expect(result.valid).toBe(true);
expect(result.wcVersion).toBe('6.5.0');
});
test('handles invalid credentials (401)', async () => {
(axios.get as jest.Mock).mockRejectedValue({
response: {
status: 401,
data: { message: 'Invalid signature' }
}
});
const result = await validateCredentials(validCreds);
expect(result.valid).toBe(false);
expect(result.error).toContain('Invalid signature');
});
test('handles WooCommerce not installed (404)', async () => {
(axios.get as jest.Mock).mockRejectedValue({
response: {
status: 404,
data: { message: 'No route was found' }
}
});
const result = await validateCredentials(validCreds);
expect(result.valid).toBe(false);
expect(result.error).toContain('No route was found');
});
test('handles connection timeout', async () => {
(axios.get as jest.Mock).mockRejectedValue({
message: 'timeout of 10000ms exceeded'
});
const result = await validateCredentials(validCreds);
expect(result.valid).toBe(false);
expect(result.error).toContain('timeout');
});
});
Configuration
Environment Variables
# WooCommerce does NOT require central credentials
# Each merchant provides their own Consumer Key + Secret
# Optional: WC version requirements
MIN_WOOCOMMERCE_VERSION=5.0.0
# Optional: Test store for development
WC_TEST_STORE_URL=http://localhost:8080
WC_TEST_CONSUMER_KEY=ck_test123abc...
WC_TEST_CONSUMER_SECRET=cs_test456def...
Note: Unlike Shopify/BigCommerce, there are no central CLIENT_ID or CLIENT_SECRET environment variables. Each merchant has their own API keys.
Channel-Specific Config
interface ChannelConfig {
requiresWCVersion?: string; // e.g., ">=5.0.0"
wcScopesRequired: string[]; // Permissions needed (for display only)
showCredentialInstructions: boolean; // Show key generation instructions?
wcTestStoreUrl?: string; // Test store for development
}
Example:
const channelConfig: ChannelConfig = {
requiresWCVersion: '>=5.0.0',
wcScopesRequired: ['read_products', 'read_orders', 'write_orders'],
showCredentialInstructions: true, // Show merchants how to generate keys
wcTestStoreUrl: process.env.WC_TEST_STORE_URL
};
WooCommerce REST API Authentication
HTTP Basic Auth
All WooCommerce API calls use HTTP Basic Auth:
// Server-side API call pattern
const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString('base64');
const response = await axios.get(
`${storeUrl}/wp-json/wc/v3/products`,
{
headers: {
Authorization: `Basic ${auth}`,
'Content-Type': 'application/json'
}
}
);
Why Basic Auth:
- Simple and widely supported
- No token expiration (keys are long-lived)
- No refresh token flow needed
API Endpoint Format
WooCommerce REST API endpoints follow this pattern:
{storeUrl}/wp-json/wc/v3/{resource}
Examples:
- Products:
https://mystore.com/wp-json/wc/v3/products - Orders:
https://mystore.com/wp-json/wc/v3/orders - Customers:
https://mystore.com/wp-json/wc/v3/customers - System Status:
https://mystore.com/wp-json/wc/v3/system_status
API Version: Always use /wc/v3 (latest stable version)
Related Documentation
System Docs
- WooCommerce Integration:
prism-brain/systems/violet-connect/woocommerce-integration.md - REST API Patterns:
prism-brain/systems/violet-connect/wc-rest-api.md - Credential Security:
prism-brain/systems/violet-connect/credential-management.md
Code Patterns
- violetconnect: Core features (subdomain routing, session management, 13-step wizard)
- violetconnect-patterns: Redux, axiosWrapper, AppContext, API proxy patterns
Platform Integration
- v-woocommerce: WooCommerce API patterns (products, orders, webhooks, WordPress integration)
Implementation Guides
- Pre-Registration Implementation:
prism-brain/product/specs/merchant-pre-registration/guides/violet-connect/ - WooCommerce PR Guides:
prism-brain/product/specs/merchant-pre-registration/guides/violet-connect/pr-*-woocommerce.md