6.2 KiB
6.2 KiB
name, category, description
| name | category | description |
|---|---|---|
| atomk-to-woocommerce | cross-border-ecommerce | Claim products from AtomK, generate AI listing data, and publish them to WooCommerce via REST API. |
AtomK → WooCommerce Product Publishing
Automates the full pipeline: log into AtomK, claim products from the Product Pool, generate AI listing data, and publish them to an existing WooCommerce store via its REST API.
Prerequisites
- Node.js Playwright at
/home/ubuntu/.hermes/hermes-agent/node_modules/playwright sharpnpm package installed for image resizing- Python with
requestsandPillowpackages - AtomK credentials: admincao / Tt123456!
- An existing WooCommerce instance (e.g.
us1.atomk.cn)
Step 1: Claim Products from AtomK & Generate AI Data
Use the atomk-bulk-claim skill approach. Key points for this workflow:
export NODE_PATH=/home/ubuntu/.hermes/hermes-agent/node_modules
node /path/to/atomk_claim_script.js
Script essentials:
- Login at
https://atomlisting.com/login(press Enter on password field, do NOT click login button) - Navigate to
https://atomlisting.com/products - Select category via
selectelement (e.g.家居百货) - Click
认领并编辑buttons - For each claimed product (URL contains
/editor/{id}):- Click a platform tab (速卖通 / Temu / 亚马逊 / TikTok Shop / etc.)
- Click
AI 生成and poll until text no longer contains生成中 - Extract: title, description, price, keywords, image URLs, weight/dimensions
- Save results to JSON (e.g.
/tmp/atomk_claimed_products.json)
Step 2: Prepare WooCommerce API Access
Discover the WooCommerce instance
Check for existing containers:
sudo docker ps --filter name=wordpress
Check Caddyfile for domain:
sudo docker exec <caddy_container> cat /etc/caddy/Caddyfile
Verify the store:
curl -s -L https://<domain>/wp-json/ | head -5
Generate API Keys programmatically
Critical: Find the actual admin username first — it may NOT be admin.
# List WP users
sudo docker exec <wpcli_container> wp user list --format=csv --fields=user_login,user_email
# Generate WooCommerce API key pair
sudo docker exec <wpcli_container> wp eval '
if (function_exists("wc_rand_hash")) {
$u = get_user_by("login","admincao"); # <-- use actual username
if ($u) {
global $wpdb;
$ck = "ck_" . wc_rand_hash();
$cs = "cs_" . wc_rand_hash();
$wpdb->insert($wpdb->prefix . "woocommerce_api_keys", [
"user_id" => $u->ID,
"description" => "Auto API Key",
"permissions" => "read_write",
"consumer_key" => wc_api_hash($ck),
"consumer_secret" => $cs,
"truncated_key" => substr($ck, -7)
]);
echo "CONSUMER_KEY:" . $ck . "\nCONSUMER_SECRET:" . $cs . "\n";
} else { echo "user not found\n"; }
} else { echo "wc functions not found\n"; }
'
Step 3: Publish to WooCommerce
Python publisher script
import json, os, requests
from io import BytesIO
from PIL import Image
WC_URL = "https://us1.atomk.cn/wp-json/wc/v3"
CK = "ck_..."
CS = "cs_..."
def resize_image(data):
img = Image.open(BytesIO(data)).convert("RGB")
img = img.resize((800, 800), Image.LANCZOS)
out = BytesIO()
img.save(out, format="JPEG", quality=90)
out.seek(0)
return out.read()
def create_product(data, image_url):
url = f"{WC_URL}/products"
payload = {
"name": data.get("title", data.get("productCode")),
"type": "simple",
"regular_price": data.get("price", "10.00"),
"description": data.get("description", ""),
"short_description": data.get("keywords", ""),
"images": [{"src": image_url}],
"manage_stock": False,
"stock_status": "instock",
"status": "publish",
"tags": [{"name": t.strip()} for t in data.get("keywords", "").split(",") if t.strip()]
}
r = requests.post(url, auth=(CK, CS), json=payload)
if r.status_code in (200, 201):
return r.json().get("id"), r.json().get("permalink")
else:
print(f"Failed: {r.status_code} {r.text[:500]}")
return None, None
def main():
with open("/tmp/atomk_claimed_products.json") as f:
products = json.load(f)
for p in products:
code = p.get("productCode")
imgs = p.get("images", [])
if not imgs:
continue
# Download first image
r = requests.get(imgs[0], timeout=30)
r.raise_for_status()
# Resize
resized = resize_image(r.content)
# Save locally
path = f"/tmp/wc_images/{code}_800x800.jpg"
os.makedirs("/tmp/wc_images", exist_ok=True)
with open(path, "wb") as f:
f.write(resized)
# Publish (use external image URL; media upload via WP REST often 401 with WC creds)
pid, url = create_product(p, imgs[0])
print(f"Created {code} -> ID={pid} {url}")
if __name__ == "__main__":
main()
Pitfalls & Lessons Learned
- WP admin username discovery: The WooCommerce container on this system uses
admincaoas the WP admin, notadmin. Always runwp user listfirst. - WP REST media upload 401: Uploading images via
/wp-json/wp/v2/mediausing WooCommerce consumer key/secret often fails withinvalid_username. The workaround is to pass the external image URL directly in the productimagesarray as{ "src": "https://..." }; WooCommerce will download and attach it automatically. - Image resizing: AtomK images may be large or in webp format. Always convert to 800x800 JPEG before referencing, or let WooCommerce handle the external URL and resize server-side.
- HTTPS cert: atomlisting.com has a cert mismatch;
ignoreHTTPSErrors: trueis required at bothchromium.launch()andbrowser.newContext()levels. - Login trap: The login form has
method="get". Clicking the button submits GET tologin?and stays on the page. Press Enter on the password field to trigger the correct JS POST handler. - Platform tab order: In the AtomK editor, click the platform tab FIRST, THEN click
AI 生成. The button text changes to reflect the selected platform.
Verification
List published products:
curl -s -u 'CK:CS' 'https://us1.atomk.cn/wp-json/wc/v3/products?per_page=10'