← back to Wallco Ai
docs/SHOPIFY-WEBHOOK-REGISTRATION.md
82 lines
# Shopify webhook registration — manual UI path
**Why this exists:** the wallco-ai Shopify Admin token has `read/write_products + inventory + publications` but not `read_orders`, which blocks API-side registration of `orders/paid` webhooks. Adding it via Shopify admin UI bypasses the scope entirely. ~2 minutes.
## Steps
1. **Shopify admin** → Settings → Notifications → Webhooks (bottom of the page).
2. Click **"Create webhook"**.
3. Fill in:
- **Event:** `Order paid`
- **Format:** `JSON`
- **URL:** `https://wallco.ai/api/shopify/webhooks/orders-paid`
- **Webhook API version:** `2026-01` (or latest)
4. Click **Save**.
5. **Above the webhooks table you'll see:**
> Your webhooks are signed with the following key so you can verify their integrity:
> `[long base64 string]`
Copy that key.
6. Paste it back here as a single line:
```
SHOPIFY_WEBHOOK_SECRET=<the-key-from-step-5>
```
I'll route it via the `secrets` skill into Mac2 + prod `.env` files. Then PM2 restarts.
## Smoke test after
Once the secret lands and pm2 restarts, the handler is fully wired. To verify against the live Shopify infrastructure, send a `Test notification` from the same Webhooks page — Shopify pings the endpoint with a real signed payload. Expect:
- ✅ Shopify shows green check next to the webhook (handler returned 2xx)
- ✅ wallco_audit_log row appears with `action='bundle_download'` would only land on real downloads — the test notification doesn't mint a token (the test payload lacks line_items)
For a real per-order test, place a $0.01 test order via Shopify's test gateway, paid status = paid, and confirm:
```sql
SELECT bundle_slug, customer_email, max_downloads, expires_at
FROM wallco_download_tokens
WHERE shopify_order_id = <your test order id>;
```
Should show one row per bundle in the order (1 row for cactus-only orders, 1 each for the others).
## What changes after registration
- Buyer pays → Shopify fires `orders/paid` webhook → wallco.ai mints a unique token per bundle → URL set as `note_attribute` on the order → buyer sees the link on their Shopify order-status page (no email template edit needed).
- Each per-order token: `max_downloads=5`, `expires_at = now() + 90 days`. Captures `shopify_order_id` + `customer_email` for accounting + DMCA evidence.
## Alternative if you'd rather grant the orders scope
Shopify Partners dashboard → the Admin API app → Access scopes → check `read_orders` → save → reinstall on the DW store → paste the new admin token. Then:
```
node scripts/register-shopify-webhooks.js
```
…registers automatically via API and prints the secret. Same outcome, different starting point.
## Manual fallback (while this is dormant)
Until the webhook is registered, you can mint per-order tokens by hand when a sale comes in:
```bash
node scripts/mint-shopify-download-token.js \
--slug cactus \
--date 2026-05-28 \
--product 7843826270259 \
--order <real-shopify-order-id> \
--email <buyer-email> \
--days 90 \
--max 5
```
Prints the URL → you copy-paste it into the Shopify order's notes / email to the buyer. Lossy and manual, but works today.