概述
本文档介绍如何在 Shopify Dev Dashboard 中注册和配置 Shopify 公共应用(Public App),并将其集成到 AdlerDo V6.1 中以实现 OAuth 安装。该流程会生成一个 Client ID 和 Client Secret,供 AdlerDo 用于对任何安装该应用的 Shopify 店铺进行身份验证。
架构背景
AdlerDo 将 /api/shopify/install 作为 OAuth 入口点公开。Dev Dashboard 应用会将每个安装请求重定向到该端点,由其执行 OAuth 授权码交换、将访问令牌持久化到租户数据库,并通过 Hangfire 后台作业注册所需的 webhook。
前提条件
开始之前,请确保:
- 拥有 TecSee GmbH Shopify 组织的访问权限,并具备管理应用的权限
- AdlerDo 中间件已部署,并可通过 HTTPS 在为目标环境配置的公共主机上访问
- 端点
/api/shopify/install 和 /api/shopify/callback 可访问并返回有效响应
- 在将凭据推向生产环境之前,已有一个可用于端到端测试的开发店铺
- AdlerDo 所需的 OAuth 权限范围(scope)列表已最终确定并存储在配置中
步骤 1 —— 打开应用开发页面

登录 Shopify 组织,导航至 Settings → Apps and sales channels → App development。点击"Build apps in Dev Dashboard"按钮。
重要提示: 请勿使用 Legacy custom apps 面板下的"Create an app"按钮。自 2026 年 1 月 1 日起,旧版自定义应用(Legacy custom apps)将不再对新商家可用。
步骤 2 —— 在 Dev Dashboard 中创建新应用

Dev Dashboard 在 dev.shopify.com/dashboard/{organizationId}/apps 打开。点击 Apps 列表右上角的"Create app"按钮。
步骤 3 —— 选择创建路径并设置应用名称

系统提供两种创建路径:
- Start with Shopify CLI —— 在本地搭建一个 Node/Remix 项目。AdlerDo 无需使用此路径。
- Start from Dev Dashboard —— 直接在仪表板中注册应用元数据,并立即生成 Client ID 和 Secret。AdlerDo 请使用此路径。
输入应用名称(例如:AdlerDo),然后点击 Create(创建)。
命名约定
使用一个稳定的、面向客户的名称,该名称会显示在安装同意屏幕上。对于 TecSee,如有需要,可按环境添加前缀:AdlerDo (Production)、AdlerDo Staging、AdlerDo Dev。
步骤 4 —— 配置 URL、Webhooks 版本和权限范围

创建后,应用会在 Versions 选项卡上打开,并附带一个新的草稿版本。安装 URL、webhooks API 版本和权限范围都在此处定义。
6.1 App URL
将 App URL 设置为公共的 AdlerDo 安装端点:
https://whlvm133440.wawihost.de/api/shopify/install
当商家安装应用时,Shopify 会重定向到该 URL。AdlerDo 的 ShopifyInstallController 会读取 shop 和 hmac 查询参数,验证 HMAC,并重定向到 Shopify 的 OAuth 授权页面。
6.2 在 Shopify 后台中嵌入应用
保持"Embed app in Shopify admin"复选框处于启用状态。AdlerDo 使用 App Bridge 在 Shopify 后台框架内提供嵌入式后台 UI。
6.3 Preferences URL
可选。除非应用在嵌入式体验之外公开单独的设置页面,否则请留空。
6.4 Webhooks API 版本
明确固定 webhooks API 版本。示例显示为 2026-04,即 AdlerDo 当前使用的版本。提升此值需要审查每一个 webhook 载荷的映射关系。
6.5 访问权限范围
点击"Select scopes"并勾选 AdlerDo 所需的权限范围。请将列表保持在 AdlerDo 实际使用的最小范围内 —— 商家会在安装同意屏幕上看到完整列表。
完全相同的列表还必须持久化在 AdlerDo 配置中(appsettings.Shopify.json → Shopify:Scopes),因为安装控制器会将其作为 scope 查询参数传递。不匹配将导致被迫重新安装。
可选与必需权限范围
可选权限范围可在安装后于运行时请求。AdlerDo 在初次安装期间将所有列出的权限范围视为必需,因此请将 Optional scopes 区块留空。
6.6 Redirect URLs
添加 OAuth 重定向 URL —— 即 AdlerDo OAuth 回调的公共 URL:
https://whlvm133440.wawihost.de/api/shopify/callback
每个环境添加一个重定向 URL。如果 redirect_uri 参数中提供的 URL 不在此白名单中,Shopify 将拒绝 OAuth 回调。
步骤 5 —— 发布版本

保存所有字段后,点击版本页面底部的 Release(发布)。
- Version name —— 人类可读的标签。TecSee 约定:
alderdoo-{n},其中 n 为自动递增的发布编号
- Version message —— 简短的变更日志(例如"added read_locales scope"、"bumped webhooks API to 2026-04")
点击 Release。新版本会立即变为 Active(活动),并在所有新安装中取代之前的 Active 版本。
发布后的权限范围变更
向已发布版本添加新的权限范围,并不会自动为已安装的店铺授予该权限。店铺所有者必须批准重新授权。AdlerDo 会在每次请求时检测权限范围的偏移,并在需要时触发重新安装的重定向。
步骤 6 —— 验证活动版本

从左侧边栏打开 Versions 选项卡。最近发布的版本会标有绿色的"Active"徽章。所有先前的版本仍然可见,以供审计之用。
在此视图中,您可以点击任意历史版本以检查其配置,这在调试旧店铺上的安装时非常有用。
步骤 7 —— 获取 Client ID 和 Secret

从左侧边栏打开 Settings 选项卡。顶部的 Credentials 区块会显示 Client ID 和 Secret。
9.1 Client ID
公开标识符。可安全地提交到配置中。通过剪贴板图标复制它,并粘贴到 AdlerDo 配置中。
9.2 Client Secret
敏感信息。请将其视为凭据。该密钥仅在首次生成时显示一次;之后仅显示遮盖后的形式。使用眼睛图标将其显示一次以便复制,然后通过标准的 AdlerDo 密钥存储路径进行存储。
在 AdlerDo 中,市场平台集成的密钥会通过 MarketplaceCredentialEncryptor 以 AES-256 加密的方式持久化在租户数据库中。
9.3 轮换密钥
点击 Rotate(轮换)以生成新密钥。先前的密钥会立即失效。请将密钥轮换与新密钥向 AdlerDo 的部署协调进行。
9.4 API 联系邮箱
将其设置为一个受监控的邮箱(当前为 dev@tecsee.de)。Shopify 会将 API 弃用通知和安全公告发送到该地址。
将凭据接入 AdlerDo
获得 Client ID 和 Secret 后,将凭据添加到 AdlerDo 配置中。
10.1 配置
将以下区块添加到特定于环境的配置中:
"Shopify": {
"ClientId": "1d15c8413f636e7cfda6f4402d9ef552",
"ClientSecret": "<from Settings page>",
"Scopes": "read_products,write_products,read_orders,write_orders,…",
"WebhooksApiVersion": "2026-04",
"InstallRedirectUrl": "https://whlvm133440.wawihost.de/api/shopify/callback"
}
10.2 安装流程
端到端的安装握手过程如下:
- 商家点击安装链接 → Shopify 携带 shop 和 hmac 查询参数重定向到 App URL
- AdlerDo
/api/shopify/install 根据 Client Secret 验证 HMAC,并携带配置的权限范围列表和生成的 state nonce 重定向到 https://{shop}/admin/oauth/authorize
- 商家在 Shopify 同意屏幕上批准权限范围
- Shopify 携带 code、hmac 和 state 参数重定向到
/api/shopify/callback
- AdlerDo 验证 HMAC 和 state nonce,然后将 code + Client ID + Client Secret POST 到
https://{shop}/admin/oauth/access_token,以接收离线访问令牌
- 该令牌以 AES-256 加密的方式针对该租户存储;同时注册 webhook 订阅和周期性同步的 Hangfire 作业
- AdlerDo 将商家重定向到嵌入式后台 URL
10.3 验证安装
握手完成后:
- 确认租户数据库中存在一个新的
ShopifyConnection 实体,其 EncryptedAccessToken 非空并包含已授予的权限范围列表
- 确认周期性作业(
SyncShopifyOrdersV2026、SyncShopifyProductsV2026)已在 Hangfire 中以新的租户标识符注册
- 从 Shopify 后台触发一个测试 webhook,并确认 AdlerDo 处理程序在没有 HMAC 错误的情况下处理它
附录 A —— AdlerDo 常用权限范围
| 权限范围 |
在 AdlerDo 中的用途 |
read_products, write_products |
目录同步:从 Odoo 或 JTL-Wawi 创建/更新产品和变体 |
read_orders, write_orders |
将订单拉取到 AdlerDo,并将订单修改/履约信息推回 |
read_inventory, write_inventory |
按地点同步库存水平 |
read_locations |
解析用于库存和运输的履约地点 |
read_fulfillments, write_fulfillments |
创建履约,并从承运商推送物流追踪号:DHL、GLS、DPD、DB Schenker |
read_assigned_fulfillment_orders, write_assigned_fulfillment_orders |
当 AdlerDo 作为已注册的履约服务时需要 |
read_customers, write_customers |
客户同步和 B2B 细分 |
read_shipping |
读取承运商和区域配置以进行费率计算 |
read_app_proxy, write_app_proxy |
嵌入式后台代理路由所需 |
read_analytics |
嵌入式后台中的报表仪表板 |
附录 B —— 故障排除
安装重定向返回 401 / 无效的 HMAC
原因: AdlerDo 配置中的 Client Secret 与 Settings 中的密钥不匹配,或密钥已轮换但未重新部署。
处理措施: 从 Dev Dashboard Settings 页面复制密钥并重新部署。
OAuth 回调返回 'redirect_uri is not whitelisted'
原因: 回调 URL 未出现在活动版本的 Redirect URLs 字段中。
处理措施: 打开活动版本,添加该 URL,发布新版本,然后重试安装。
店铺已安装但未出现 Hangfire 作业
原因: OAuth 授权码交换成功,但安装后的引导流程失败(例如租户配置)。
处理措施: 检查安装时间戳前后的 AdlerDo 日志;ShopifyInstallController 会为每个阶段发出一条 Information 日志,并针对出问题的步骤发出一条 Error 日志。
Webhook 投递因 HMAC 错误而失败
原因: AdlerDo 是基于解析后的载荷(而非原始请求体)计算的 webhook HMAC。
处理措施: 确认请求中间件在为 /api/shopify/webhooks/* 路由进行模型绑定之前缓冲了原始请求体。
商家报告在添加权限范围后缺少数据
原因: 该店铺是基于不包含该权限范围的旧版本安装的。
处理措施: 触发重新安装的重定向 —— AdlerDo 会在 ShopifyConnectionMiddleware 中检测权限范围偏移,并重定向到安装端点,商家在此批准新的权限范围。