Files
descrybe/docs/shopify-connector.md
T
greeneclipse 8580c996c3 Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
2026-08-09 22:47:43 +02:00

103 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Shopify connector
Descrybe v2 connects Shopify as a first-class store source alongside WooCommerce.
UI: **`/stores`** (hub) → **`/stores/shopify`** (setup). `/shopify` redirects to the setup page.
## What syncs
| Data | Direction | Notes |
|------|-----------|--------|
| Products | Push | Processed Descrybe products → Shopify Admin API create/update (queued / scheduled — **not** store webhooks) |
| Orders | Pull | Queued / scheduled pull into `shopify_orders` / `shopify_order_items` (not live webhooks) |
| Reviews | — | Not available (Shopify has no first-party product reviews Admin API) |
| Inbound webhooks | — | Not received; do not register Shopify webhook URLs at Descrybe until a full HMAC receive path ships (`docs/store-connectors.md`) |
## Setup (recommended: Dev Dashboard client credentials)
As of **1 January 2026**, Shopify no longer creates new custom apps in Admin → Develop apps. New apps are created in the [Dev Dashboard](https://dev.shopify.com/dashboard/), installed on the store, then authenticated with the **client credentials** grant (short-lived Admin API tokens, ~24h).
1. Open the Dev Dashboard → **Apps****Create app****Start from Dev Dashboard** (UI deep-links this).
2. Create a **version**: App URL can be the default API-only home; scopes at least `read_products`, `write_products`, `read_orders`**Release**.
3. From the app **Home** tab → **Install app** on your store (approve scopes).
4. App **Settings** → copy **Client ID** and **Client secret**.
5. In Descrybe **`/stores/shopify`**: enter shop domain (`your-store` or `your-store.myshopify.com`), paste Client ID + secret, enable sync → **Save****Test Connection**.
6. Queue **product sync** and **orders sync**. Run the worker so pending flags are claimed.
Descrybe exchanges Client ID + secret for an access token on save and **refreshes automatically** before expiry (no migration; secrets live encrypted in `access_token` + `sync_options`).
### Legacy Admin API token (`shpat_…`)
Custom apps created in Shopify Admin **before** January 2026 still expose a permanent Admin API access token. The connect form has a “legacy token” path for those. Prefer Client ID + secret for anything new.
### Still manual (no one-click App Store install)
- Creating the Dev Dashboard app, releasing a version, and installing it on the merchant store
- Approving scopes in Shopify Admin when scopes change
- Collaborator accounts cannot use the Dev Dashboard — the store owner (or staff with Develop permission) must create the app
- Client credentials only work when the app and store are in the **same** Shopify organization (see Shopifys `shop_not_permitted` docs)
Shop domain must be the `*.myshopify.com` admin host. Custom storefront domains are rejected (Admin API always uses myshopify.com). SSRF guards block IPs, localhost, and private ranges.
## Environment variables (optional live path)
Set in process env or untracked `.env` (never commit secrets):
| Variable | Purpose |
|----------|---------|
| `SHOPIFY_SHOP_DOMAIN` | Shop name or `name.myshopify.com` |
| `SHOPIFY_ACCESS_TOKEN` | Admin API access token (legacy / ops scripts) |
| `SHOPIFY_API_VERSION` | Default `2024-10` |
| `SHOPIFY_DRY_RUN` | When `true`, treat as dry-run (UI also has a Dry run checkbox) |
Aliases are not required; credentials saved via the UI are encrypted at rest (`CREDENTIALS_ENCRYPTION_KEY` / `APP_ENCRYPTION_KEY` — see [ops-runtime.md](ops-runtime.md)).
### No live shop? Dry-run / mock
- In the UI: enable **Dry run**, or set access token to exactly `dry-run`.
- Dry-run skips live HTTP calls: test connection returns a mock shop; product create/update and a sample order page succeed in-process.
- Unit tests in `internal/shopify` cover domain SSRF guards, token encryption, client-credentials parsing, and dry-run client behavior (no network).
## APIs
| Method | Path | Notes |
|--------|------|-------|
| GET | `/api/shopify` | Config + sync badges (no secrets). Includes `auth_mode`, `has_client_credentials`. |
| PUT | `/api/shopify` | Save shop domain + (`client_id`/`client_secret` **or** `access_token`) + api_version + dry_run |
| POST | `/api/shopify/test` | Live or dry-run shop.json (refreshes client-credentials token if needed) |
| POST | `/api/shopify/sync` | Queue product push |
| POST | `/api/shopify/sync-orders` | Queue orders pull |
| GET | `/api/shopify/orders` | List synced orders |
## Worker
`cmd/worker` claims pending Shopify jobs after WooCommerce:
- `products``shopify.Service.SyncCompany`
- `orders``shopify.Service.SyncOrders`
Scheduled enqueue (every 15m ops tick) marks enabled configs whose `last_synced_at` is older than the interval (default 6h).
## Schema
Migration `apps/api/sql/schema/017_shopify.sql`:
- `shopify_configs` — shop domain, encrypted access token, api version, sync_options JSONB
- `shopify_orders` / `shopify_order_items` — pulled order data
Client credentials metadata (`auth_mode`, `client_id`, encrypted `client_secret_enc`, `token_expires_at`) is stored in `sync_options` (no extra migration).
Apply with `make migrate` (or `scripts/migrate.ps1` on Windows).
## Product matching
1. Cached Shopify product id in `sync_options.product_ids` (keyed by Descrybe processed product UUID).
2. Else GraphQL `productVariants(query: "sku:…")`.
3. Else create a new product with a single variant (SKU/price/barcode) and a `descrybe.product_id` metafield.
## Related
- Hub overview: [store-connectors.md](store-connectors.md)
- WooCommerce parity: [woocommerce-demo.md](woocommerce-demo.md)
- Shopify docs: [Create apps (Dev Dashboard)](https://shopify.dev/docs/apps/build/dev-dashboard/create-apps-using-dev-dashboard), [Get API access tokens](https://shopify.dev/docs/apps/build/dev-dashboard/get-api-access-tokens)