Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
5.7 KiB
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, installed on the store, then authenticated with the client credentials grant (short-lived Admin API tokens, ~24h).
- Open the Dev Dashboard → Apps → Create app → Start from Dev Dashboard (UI deep-links this).
- Create a version: App URL can be the default API-only home; scopes at least
read_products,write_products,read_orders→ Release. - From the app Home tab → Install app on your store (approve scopes).
- App Settings → copy Client ID and Client secret.
- In Descrybe
/stores/shopify: enter shop domain (your-storeoryour-store.myshopify.com), paste Client ID + secret, enable sync → Save → Test Connection. - 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 Shopify’s
shop_not_permitteddocs)
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).
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/shopifycover 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.SyncCompanyorders→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 JSONBshopify_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
- Cached Shopify product id in
sync_options.product_ids(keyed by Descrybe processed product UUID). - Else GraphQL
productVariants(query: "sku:…"). - Else create a new product with a single variant (SKU/price/barcode) and a
descrybe.product_idmetafield.
Related
- Hub overview: store-connectors.md
- WooCommerce parity: woocommerce-demo.md
- Shopify docs: Create apps (Dev Dashboard), Get API access tokens