A Flask extension for Shopify app development
Project description
Flask-Shopify-Utils
flask-shopify-utils is a Flask extension that provides common building blocks for Shopify custom apps: OAuth routes, HMAC and webhook validation, Shopify session-token checks, GDPR webhook routes, a GraphQL client, starter models, and a scaffold CLI.
- Features
- Installation
- Quick start
- Starter scaffold
- Configuration
- Route bundles
- Authentication decorators
- Models
- GraphQL utilities
- Development
- License
Features
- Shopify OAuth install and callback helpers for embedded custom apps.
- HMAC validation for OAuth callbacks, embedded-app entry points, app proxies, and webhooks.
- Shopify session-token validation through
check_session_jwt. - Optional default blueprints for app entry, admin reference endpoints, GDPR webhooks, and GraphQL schema generation.
- A retrying Shopify GraphQL client based on
sgqlc. - Starter SQLAlchemy models for stores and webhook jobs.
lazy-dogCLI for copying the example scaffold into a new project.
Installation
Install the package from PyPI:
pip install -U flask-shopify-utils
Or install with uv:
uv pip install -U flask-shopify-utils
The package supports Python 3.9 and newer.
Quick start
Initialize Flask-SQLAlchemy before initializing ShopifyUtil. The extension reads the SQLAlchemy instance from app.extensions['sqlalchemy'] during init_app.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_shopify_utils import ShopifyUtil
app = Flask(__name__)
app.config.update(
SQLALCHEMY_DATABASE_URI="sqlite:///shopify.db",
SHOPIFY_API_KEY="your-shopify-api-key",
SHOPIFY_API_SECRET="your-shopify-api-secret",
SCOPES="read_products,write_products",
)
db = SQLAlchemy()
db.init_app(app)
shopify = ShopifyUtil()
shopify.init_app(app)
# Register only the route bundles your app needs.
shopify.enroll_default_route()
shopify.enroll_gdpr_route()
shopify.enroll_admin_route()
shopify.enroll_graphql_schema_cli()
If you use the bundled models, import them only after ShopifyUtil().init_app(app) has run:
from flask_shopify_utils.model import Store, Webhook
See example/ for complete sample projects.
Starter scaffold
After installing the package, run lazy-dog in an empty project directory to copy the reference scaffold from example/example1:
lazy-dog
The command prompts before overwriting existing files or directories.
Configuration
ShopifyUtil.init_app() sets defaults for the following Flask config values when they are not already configured:
| Key | Default | Purpose |
|---|---|---|
ROOT_PATH |
Current working directory | Base path for generated and temporary files. |
BACKEND_PATH |
<ROOT_PATH>/backend |
Backend application path used by helpers. |
TEMPORARY_PATH |
<BACKEND_PATH>/tmp |
Temporary output path. |
API_VERSION |
Latest supported Shopify API version | Shopify Admin API version used by GraphQL utilities. |
TIMEZONE |
Pacific/Auckland |
Timezone for bundled model timestamps. |
SHOPIFY_API_SECRET |
CUSTOM_APP_SECRET |
Shared secret for HMAC, webhook, and token validation. |
SHOPIFY_API_KEY |
CUSTOM_APP_KEY |
Shopify app API key. |
BYPASS_VALIDATE |
0 |
Local-development validation bypass. Any non-zero integer is treated as the fake store id. |
DEBUG |
False |
Flask debug flag fallback. |
SCOPES |
read_products |
OAuth scopes requested during installation. |
Set BYPASS_VALIDATE to 0 in production.
Route bundles
Routes are opt-in. Call the enrollment methods you need after init_app().
| Method | Routes and behavior |
|---|---|
enroll_default_route() |
Registers /, /admin, /install, /callback, /docs, and a Shopify-aware 404 handler. |
enroll_gdpr_route() |
Registers /webhook/shop/redact, /webhook/customers/redact, and /webhook/customers/data_request; requests are verified with Shopify webhook HMAC. |
enroll_admin_route() |
Registers reference admin endpoints /admin/test_jwt and /admin/check/reinstall. |
enroll_graphql_schema_cli() |
Registers flask generate_schema, which introspects a live Shopify store and emits an sgqlc schema module. |
Authentication decorators
Use the decorator that matches the Shopify surface you are handling. Successful decorators set g.store_key and g.store_id for downstream handlers.
| Decorator | Use case |
|---|---|
check_callback |
Shopify OAuth callback validation. |
check_hmac |
Embedded-app entry validation. |
check_proxy |
Shopify app proxy signature validation. |
check_webhook |
Shopify webhook HMAC validation through X-Shopify-Hmac-Sha256. |
check_session_jwt |
Shopify session-token validation from the Authorization header. |
validate_internal_hash |
Rolling internal hash validation for proxy-style endpoints. |
Deprecated JWT helpers such as check_jwt, validate_jwt, and create_admin_jwt_token remain available for backward compatibility, but new admin endpoints should use check_session_jwt.
Models
The bundled flask_shopify_utils.model module provides:
Store: shop domain, access token, scopes, and JSON-styleextradata storage.Webhook: webhook job/event records with status helpers.BasicMethod: small create/update helper methods shared by the models.
Because the model module uses the SQLAlchemy instance registered by ShopifyUtil, initialize the extension before importing these models.
GraphQL utilities
GraphQLClient wraps sgqlc.endpoint.http.HTTPEndpoint, resolves the Shopify API version through get_version(), and retries throttled or temporary HTTP failures.
from flask_shopify_utils.utils import GraphQLClient
client = GraphQLClient("example.myshopify.com", "shpat_access_token")
operation = ... # Build an sgqlc Operation from your generated schema.
data = client.fetch_data(operation)
To generate a typed Shopify schema after registering the CLI command:
flask generate_schema --store_id 1
Use flask generate_schema --help to see all available options.
Development
Clone the repository, create a virtual environment, and install development dependencies:
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements/dev.txt
pip install -e .
With uv:
uv venv
source .venv/bin/activate
uv pip install -r requirements/dev.txt
uv pip install -e .
Run linting and tests:
flake8
pytest
With uv:
uv run flake8
uv run pytest
Run a specific test file or test case:
pytest -vs tests/test_default_routes.py
pytest -vs tests/test_init.py::test_init_app
Dependency locks
Pinned dependencies live in requirements/. Use uv for new dependency workflows:
uv pip compile pyproject.toml --extra=dev --output-file=requirements/dev.txt
uv pip compile pyproject.toml --output-file=requirements/index.txt
Legacy pip-tools commands are still supported:
pip-compile --extra=dev --output-file=requirements/dev.txt pyproject.toml
pip-compile --output-file=requirements/index.txt pyproject.toml
Build and publish
Build the distribution and verify it with Twine:
python -m build
twine check dist/*
Publish to PyPI when you are ready:
twine upload dist/* --skip-existing
The package version is read from __version__ in src/flask_shopify_utils/__init__.py.
License
This project is licensed under the MIT License. See LICENSE for details.
Reference
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flask_shopify_utils-0.2.12.tar.gz.
File metadata
- Download URL: flask_shopify_utils-0.2.12.tar.gz
- Upload date:
- Size: 19.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5f0e57da8bb6093308af1de5caa573c4ad8644fb6b549d226f36801ff62c3b1c
|
|
| MD5 |
89044c7ac0f4ee7afd41cee90ca04e60
|
|
| BLAKE2b-256 |
6e1ab9f3fb088e55b5898a8833b53e35d8243a0b85185c7288a13b724e6c30e7
|
File details
Details for the file flask_shopify_utils-0.2.12-py3-none-any.whl.
File metadata
- Download URL: flask_shopify_utils-0.2.12-py3-none-any.whl
- Upload date:
- Size: 19.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cb8a241bab323fb280ccaab8cc04b344009bc7b1245cdd0da7f5890c05e8faea
|
|
| MD5 |
678183fea77fb3b999d0322405402bda
|
|
| BLAKE2b-256 |
ff8885ef1f4b9bcc19f0df50b13ffb851a16a6160b72fc0daf8ad2c09db1cd6a
|