← 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.