Shopify ストアの注文・発送イベントを Chatwork に即時通知する Shopify アプリ
EC 運営チームでは Shopify 管理画面と業務チャットを行き来しながら受注対応を進めることが多く、確認漏れや初動の遅れが発生しやすい状態でした。本アプリは注文・支払い・キャンセル・発送の各イベントを Chatwork ルームに自動投稿し、チャットに張り付くだけで受注フローを回せる状態を作ります。Webhook と Shopify Flow の両方に対応しているため、定型通知から条件分岐つきのワークフローまで同じアプリで賄えます。
- Shopify Webhook 購読:
orders/create/orders/paid/orders/cancelled/fulfillments/createを購読し Chatwork に通知(shopify.app.tomlで宣言的登録) - Shopify Flow Action:
Send Chatwork Messageアクションを提供し、Flow 上の任意条件で Chatwork ルームへ送信 - トピックごとの送信先 / テンプレート設定: 管理画面(Polaris)からトピック単位で有効化・ルーム ID・本文テンプレートを編集(
{{変数}}プレースホルダ対応) - 冪等性 / 重複排除:
X-Shopify-Webhook-Idベースの一意制約に加え、同一orderId× トピックの 10 秒時間窓で多重配信を防止 - 指数バックオフ + ジッターでの再送: 5xx / 429 / ネットワーク系エラーをリトライキューに投入し、最大 5 回まで自動再送
- 送信ログ: 成功・失敗・エラーメッセージを Prisma に記録し、
/app/logsから横断確認 - シークレット保護: Chatwork API トークンは Shopify Shop Metafield に保存、追加の機微情報は AES-256-GCM + PBKDF2 で暗号化
- Remix v2 (
@remix-run/node/@remix-run/react) + TypeScript + Vite 6 - Shopify App Remix Template (
@shopify/shopify-app-remixv4 /@shopify/app-bridge-react/@shopify/polarisv12) - Prisma 6 + SQLite(本番は Fly.io ボリューム + Litestream で S3 互換ストレージへレプリケーション)
- GraphQL Admin API 2025-01(Metafield 経由で Chatwork 設定を保存)
- Chatwork API v2 (
/v2/rooms/{room_id}/messages) - Shopify Flow Extension (
flow_action拡張) - Fly.io ホスティング (
fly.toml、primary_region = nrt)
- Node.js
>=20.19 <22 || >=22.12 - Shopify CLI(最新版)
- Shopify Partner アカウントと開発ストア
- Chatwork アカウント(API トークンを発行できるプラン)
# 1. 依存をインストール
npm install
# 2. 環境変数を用意(プレースホルダ)
cat > .env <<'EOF'
DATABASE_URL="file:./dev.sqlite"
SHOPIFY_API_KEY="your_shopify_api_key"
SHOPIFY_API_SECRET="your_shopify_api_secret"
SCOPES="read_orders,read_shipping,read_fulfillments"
PRIVATE_KEY_ENC_SECRET="generate_a_64_char_random_string"
EOF
# 3. DB を初期化
npx prisma generate
npx prisma migrate dev
# 4. Shopify CLI 経由でアプリを起動(トンネル / 認証 / Webhook 登録を自動化)
npm run dev
# 5. デプロイ(拡張定義と Webhook 購読を Shopify に反映)
npm run deployインストール後、アプリ管理画面の /app で Chatwork API トークンとデフォルトルーム ID を保存し、/app/webhooks でトピックごとの有効化と通知先を設定します。/app/logs で送信履歴と失敗時のエラーを追跡できます。
app/
routes/
app._index.tsx # Chatwork API トークン / Room ID 設定画面
app.webhooks.tsx # トピック別の有効化・送信先・テンプレート編集
app.logs.tsx # 送信履歴ビューア
webhooks.shopify.tsx # orders/* と fulfillments/create の受信エンドポイント
api.flow-action.tsx # Shopify Flow Action のランタイム
webhooks.app.*.tsx # app/uninstalled, app/scopes_update のハンドラ
services/
chatwork.server.ts # Chatwork API クライアント + 注文メッセージ整形
chatworkConfig.server.ts # Shop Metafield 経由の設定 read/write
shopifyWebhook.server.ts # トピック購読の同期
retry.server.ts # リトライ可否判定 + 指数バックオフ
retryWorker.server.ts # RetryJob のドレイン
template.server.ts # {{変数}} レンダラ
encryption.server.ts # AES-256-GCM + PBKDF2 ユーティリティ
extensions/flow-action/ # Shopify Flow Action 拡張定義
prisma/schema.prisma # Session / Configuration / MessageLog / RetryJob / WebhookSetting / WebhookEvent
fly.toml / Dockerfile / litestream.yml # Fly.io デプロイ + SQLite レプリケーション
通知パスは「Shopify Webhook → webhooks.shopify.tsx で HMAC 検証 → 冪等性チェック → 設定読み込み → chatwork.server.ts で送信 → 成功/失敗を MessageLog に記録、再送可能なら RetryJob を投入」という単線で、Shopify Flow 経路 (api.flow-action.tsx) も同じ送信レイヤーを共有します。
MIT