← back to Designer Wallcoverings
DW-Agents/dw-agents/amazon-paapi-integration.ts
291 lines
/**
* Amazon Product Advertising API Integration
* Fetches REAL product data and prices from Amazon
*/
import { amazon } from 'amazon-paapi';
import * as fs from 'fs';
import * as dotenv from 'dotenv';
// Load environment variables
dotenv.config();
interface AmazonProduct {
asin: string;
title: string;
price: number;
currency: string;
url: string;
imageUrl?: string;
rating?: number;
reviewCount?: number;
}
interface AmazonSearchResult {
query: string;
products: AmazonProduct[];
timestamp: Date;
}
// Amazon PA-API Configuration
const PAAPI_CONFIG = {
accessKey: process.env.PAAPI_ACCESS_KEY || '',
secretKey: process.env.PAAPI_SECRET_KEY || '',
partnerTag: process.env.PAAPI_PARTNER_TAG || '',
host: process.env.PAAPI_HOST || 'webservices.amazon.com',
region: process.env.PAAPI_REGION || 'us-east-1'
};
/**
* Check if PA-API credentials are configured
*/
export function isPaapiConfigured(): boolean {
return !!(PAAPI_CONFIG.accessKey && PAAPI_CONFIG.secretKey && PAAPI_CONFIG.partnerTag);
}
/**
* Search Amazon for products using PA-API
*/
export async function searchAmazonProducts(query: string, maxResults: number = 10): Promise<AmazonSearchResult> {
console.log(`🔍 Searching Amazon PA-API for: "${query}"`);
if (!isPaapiConfigured()) {
console.error('❌ Amazon PA-API not configured!');
console.log('\n📝 To configure:');
console.log(' 1. Sign up at: https://associates.amazon.com');
console.log(' 2. Get API credentials from Tools → Product Advertising API');
console.log(' 3. Copy .env.example to .env');
console.log(' 4. Add your credentials to .env\n');
return {
query,
products: [],
timestamp: new Date()
};
}
try {
const requestParameters = {
Keywords: query,
SearchIndex: 'All',
ItemCount: Math.min(maxResults, 10), // PA-API max is 10 per request
Resources: [
'ItemInfo.Title',
'Offers.Listings.Price',
'Images.Primary.Large',
'ItemInfo.ByLineInfo',
'CustomerReviews.StarRating',
'CustomerReviews.Count'
]
};
const response = await amazon.searchItems(requestParameters);
const products: AmazonProduct[] = [];
if (response.SearchResult && response.SearchResult.Items) {
response.SearchResult.Items.forEach((item: any) => {
try {
const asin = item.ASIN || '';
const title = item.ItemInfo?.Title?.DisplayValue || 'Unknown Product';
let price = 0;
let currency = 'USD';
if (item.Offers?.Listings && item.Offers.Listings.length > 0) {
const listing = item.Offers.Listings[0];
if (listing.Price) {
price = listing.Price.Amount || 0;
currency = listing.Price.Currency || 'USD';
}
}
const url = item.DetailPageURL || `https://www.amazon.com/dp/${asin}`;
const imageUrl = item.Images?.Primary?.Large?.URL || undefined;
let rating = undefined;
let reviewCount = undefined;
if (item.CustomerReviews) {
rating = item.CustomerReviews.StarRating?.Value || undefined;
reviewCount = item.CustomerReviews.Count || undefined;
}
products.push({
asin,
title,
price: price / 100, // Convert cents to dollars
currency,
url,
imageUrl,
rating,
reviewCount
});
console.log(` ✅ ${title} - $${(price / 100).toFixed(2)}`);
} catch (err) {
console.error(' ⚠️ Error parsing item:', err);
}
});
}
console.log(`✅ Found ${products.length} products\n`);
return {
query,
products,
timestamp: new Date()
};
} catch (error: any) {
console.error('❌ Amazon PA-API Error:', error.message || error);
return {
query,
products: [],
timestamp: new Date()
};
}
}
/**
* Get product details by ASIN
*/
export async function getProductByAsin(asin: string): Promise<AmazonProduct | null> {
console.log(`🔍 Fetching product details for ASIN: ${asin}`);
if (!isPaapiConfigured()) {
console.error('❌ Amazon PA-API not configured!');
return null;
}
try {
const requestParameters = {
ItemIds: [asin],
Resources: [
'ItemInfo.Title',
'Offers.Listings.Price',
'Images.Primary.Large',
'CustomerReviews.StarRating',
'CustomerReviews.Count'
]
};
const response = await amazon.getItems(requestParameters);
if (response.ItemsResult?.Items && response.ItemsResult.Items.length > 0) {
const item = response.ItemsResult.Items[0];
const title = item.ItemInfo?.Title?.DisplayValue || 'Unknown Product';
let price = 0;
let currency = 'USD';
if (item.Offers?.Listings && item.Offers.Listings.length > 0) {
const listing = item.Offers.Listings[0];
if (listing.Price) {
price = listing.Price.Amount || 0;
currency = listing.Price.Currency || 'USD';
}
}
const url = item.DetailPageURL || `https://www.amazon.com/dp/${asin}`;
const imageUrl = item.Images?.Primary?.Large?.URL || undefined;
let rating = undefined;
let reviewCount = undefined;
if (item.CustomerReviews) {
rating = item.CustomerReviews.StarRating?.Value || undefined;
reviewCount = item.CustomerReviews.Count || undefined;
}
const product: AmazonProduct = {
asin,
title,
price: price / 100,
currency,
url,
imageUrl,
rating,
reviewCount
};
console.log(`✅ ${title} - $${product.price.toFixed(2)}`);
return product;
}
console.log('⚠️ Product not found');
return null;
} catch (error: any) {
console.error('❌ Amazon PA-API Error:', error.message || error);
return null;
}
}
/**
* Compare prices for office supplies
*/
export async function compareOfficeSupplyPrices(itemName: string): Promise<void> {
console.log(`\n💰 Comparing Prices for: ${itemName}\n`);
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
const results = await searchAmazonProducts(itemName, 5);
if (results.products.length === 0) {
console.log('⚠️ No products found');
return;
}
// Sort by price (lowest first)
results.products.sort((a, b) => a.price - b.price);
console.log('📊 Price Comparison:\n');
results.products.forEach((product, idx) => {
const badge = idx === 0 ? '🏆 BEST PRICE' : '';
console.log(`${idx + 1}. ${product.title}`);
console.log(` 💵 Price: $${product.price.toFixed(2)} ${badge}`);
if (product.rating) {
console.log(` ⭐ Rating: ${product.rating} (${product.reviewCount} reviews)`);
}
console.log(` 🔗 URL: ${product.url}`);
console.log('');
});
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
}
// Test function
if (require.main === module) {
(async () => {
console.log('🧪 Testing Amazon PA-API Integration\n');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
if (!isPaapiConfigured()) {
console.log('⚠️ Amazon PA-API credentials not configured\n');
console.log('📝 Setup Instructions:\n');
console.log('1. Visit: https://associates.amazon.com');
console.log('2. Sign up for Amazon Associates Program');
console.log('3. Navigate to: Tools → Product Advertising API');
console.log('4. Create API credentials (Access Key, Secret Key)');
console.log('5. Copy .env.example to .env in this directory');
console.log('6. Add your credentials to .env:\n');
console.log(' PAAPI_ACCESS_KEY=your_access_key');
console.log(' PAAPI_SECRET_KEY=your_secret_key');
console.log(' PAAPI_PARTNER_TAG=your_associate_id\n');
console.log('7. Run this script again: npx tsx amazon-paapi-integration.ts\n');
process.exit(0);
}
// Test searches for common office supplies
await compareOfficeSupplyPrices('printer paper');
await compareOfficeSupplyPrices('black ink cartridge');
await compareOfficeSupplyPrices('post-it notes');
})();
}
export { AmazonProduct, AmazonSearchResult };