mcpField
W
wix-base44-connector

wix-base44-connector

github.com/wix開発3681 回インストール今日更新
リポジトリ

wix-base44-connector について

wix-base44-connectorは、Wixに接続するBase44アプリの構築を支援するスキルです。サイトのコンテキスト確認やAPIの調査を行い、訪問者向けと管理者向けのフローを分けて、実際の設定とドキュメントに基づく実装を案内します。

主な機能

  1. 01サイト設定とコンテキストの取得
  2. 02APIドキュメントと管理レシピの検索
  3. 03メソッドの正確なスキーマ確認
  4. 04訪問者と管理者の呼び出しフローを分離
  5. 05OAuthアプリ作成とWixアプリのインストール

活用シーン

  1. 01サイト設定に沿った訪問者向け機能の開発
  2. 02管理者向け管理画面の構築
  3. 03商品や連絡先などの管理操作
  4. 04訪問者認証やWixホスト型フローのOAuth設定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/wix/skills --skill wix-base44-connector

インストール後、Claude Code で/wix-base44-connectorを入力して読み込まれたか確認します。

同梱ファイルreferences/CAPABILITY_MAP.mdscripts/utils.cjs

詳細

Base44 から Wix 上で構築する

Wix コネクターは接続済みです。この上でアプリを構築する方法を説明します。サイトのコンテキストを収集し、API を見つけてドキュメントから仕様を確認し、コードを書きます。すべてを確認してください。エンドポイント、パス、ドキュメントの URL、リクエストとレスポンスのフィールドはすべて以下の呼び出しから取得し、記憶やパターンから補ってはいけません。404 または空の結果が返った場合は、組み合わせを試すのではなく、見つけてください。例は仕組みを理解するのに役立ちますが、古くなります。利用する前に確認してください。

Wix に関するすべてのタスクは、サイトのコンテキストを取得するところから始めてください(以下の wx.context)。サイトに実際に何があり、それぞれがどのように設定されているかが報告されるため、名前から推測するのではなく、実際に存在するものを対象に各呼び出しを行えます。これはタスクの最初の手順であり、一度だけ行う設定ではありません。後続のターンに前のターンのコンテキストは引き継がれないため、Wix API を利用して構築または呼び出す前に、改めて読み込んでください。

管理または管理者向けのタスクは、レシピから始めてください。wx.mgmtRecipes(Learn Wix)を呼び出し、適切なレシピに従います。レシピには、API でサポートされない内容、一括呼び出しで実際に書き込まれるフィールド、2 つの呼び出しを行う順序が明記されています。スキーマだけを見てこれらを判断すると、複数のエラーを経てようやく再発見することになります。wx.search では該当するレシピもランク付けされます(hits 内のレシピ項目)。そのため、メソッドから始めた検索でもレシピが見つかります。

このスキルでは:

  • 何を構築しますか? — 訪問者向け、オーナー向け、または代行する管理業務向けのいずれかを、ユーザーの意図に基づいてリクエストごとに判断し、それぞれ独立したフローで進めます
  • ヘルパー — すべての exec の冒頭で読み込む wx.* ローダー
  • コンテキストを収集する — wx.context。サイトに実際に何があるかを報告します
  • Wix を学ぶ — API を見つけ、その仕様を確認します
    • 管理レシピ — 管理者向けタスクの最初のステップ(wx.mgmtRecipes)
    • 検索と参照 — メソッド、レシピ、記事を対象とした wx.search
    • ドキュメントページを読む — 見つかったドキュメント URL を指定する wx.page
    • 仕様インデックス — 見つかったメソッドの正確なスキーマを取得する wx.spec
  • コードを書く
    • 構築中の管理操作 — exec_tool 内であなたが実行します
    • バックエンド関数 — アプリがオーナーとして実行します
    • 訪問者の認証と Wix ホストのフロー — 訪問者クライアント、リダイレクトセッション、ヘッドレス OAuth アプリ、そして wix-vibe-headless によるバーティカル全体のブートストラップ

何を構築しますか?

Wix には訪問者と管理者という2つのIDがあり、それぞれに独自のフローがあります。リクエストを実行する前に、技術的な観点ではなく、ユーザーの希望に基づいて、どちらに該当するかを判断してください。

  • 訪問者 — サイトを利用する人です。閲覧、予約、購入、メンバーとしてのサインインなどを行います。訪問者トークンを使用し、ブラウザーから共有の訪問者クライアントを介して呼び出します。
  • 管理者、構築する — オーナー自身の管理画面です。カスタムビュー、一括操作、内部ツールなどが該当します。管理者コネクタートークンを使用し、フロントエンドから呼び出すバックエンド関数でサーバー側から実行します。
  • 管理者、代行する — ユーザーがアプリを求めているのではなく、今すぐビジネスの管理を依頼しています。商品を作成する、設定を変更する、連絡先をインポートするなどが該当します。管理者トークンを使用し、exec_tool でその場限りの処理を行います。アプリには何も追加しません。

オーナーはすでに、注文、商品、予約、設定など、ビジネスを運営するための完全な Wix ダッシュボードを持っています。そのため、管理機能の構築はユーザーが選択するものであり、最初から不足を埋めるために作るものではありません。リクエストに訪問者と管理者の両方の要素がある場合、それぞれ固有のフローを維持してください。

リクエストでどちらかが明示されていない場合は、技術的な言葉(ID、トークン、フロー)ではなく、ユーザーの言葉(その機能を誰が使うのか)で確認してください。確認せずに判断する場合は、同じように、どちらを選んだかを伝えてください。

この区分から導かれるルールは次のとおりです。

  • チェックアウトでは訪問者トークンを使用し、管理者トークンは決して使用しません。このアプリが訪問者向けにチェックアウトを作成する場合も同様です。管理者トークンでもチェックアウト URL は返されますが、そこが落とし穴です。その URL は購入者ではなくサイトに紐づいており(カートの保持、チェックアウト放棄からの復帰、アトリビューションがありません)、リダイレクトセッションでは拒否されます(403)。アプリに戻れるのは、OAuth アプリのリダイレクトリストにある URL からのみです(後述の「訪問者認証」と「Wix ホスト型フロー」を参照)。
  • OAuth アプリがまだないからといって、管理者トークンを使ってよいわけではありません。 wx.ensureOAuthApp は clientId を返し、サイトにアプリがない場合は作成します。これは訪問者フローの最初の手順です。誰でも、この公開 clientId から匿名の訪問者トークンを発行できます。訪問者のログインは必要ありません。
  • ログインがなくても、訪問者フローです。 asServiceRole はこのアプリ独自のデータアクセスを制御するものであり、Wix からどのIDとして認識されるかとは関係ありません。公開ページからの Wix 呼び出しには訪問者トークンを使用します。管理者トークンを使うのは、機能がオーナー側のものだからであり、誰もサインインしないからではありません。
  • ページ以外のオーナー側の作業(Webhook、スケジュールされたジョブ、明示的に認可された権限昇格操作など)も、バックエンド関数で実行する管理者フローです。
visitor pages ──(visitor token)────────────────────────► wixapis.com
admin pages   ──► base44/functions/… ──(admin token)────► wixapis.com
exec_tool     ──(admin token, ad hoc management)────────► wixapis.com

接続先サイトが決済を管理します。 訪問者が購入したものは、このアプリから引き渡される Wix ホスト型ページで、そのサイトにすでに設定されているプロバイダーを使って決済されます。Base44 の <available_payment_providers> に関する注記は、Base44 がホストするチェックアウトについてのものです。ここでのフローには適用されず、記載されているプロバイダーの種類や制限にかかわらず、これらのフローで何か対応を求められることはありません。

ヘルパー

調査と確認は exec_tool で行い、すべての exec を開くローダーが 1 つあります(exec 間で状態は共有されません — 毎回読み込み直してください。モジュールはこのファイルの隣にディスク上にあり、ネットワークは初回読み込み時の フォールバックとしてのみ使用します):

const fs = require("fs"), P = ".agents/skills/wix-base44-connector/utils.cjs";
if (!fs.existsSync(P)) { fs.mkdirSync(".agents/skills/wix-base44-connector", { recursive: true });
  fs.writeFileSync(P, await (await fetch("https://www.wix.com/skills/wix-base44-connector/scripts/utils.cjs")).text()); }
const wx = require(require("path").resolve(P));

wx は次のヘルパーをエクスポートします:

  • wx.post/get/patch/put/del(url, [body], token?) — 動詞ごとに 1 つの JSON 通信関数(get/del は本文を受け取りません):token から Bearer トークンを設定し、2xx 以外の場合は API 独自のエラーをスローします
  • wx.clip(value) — 戻り値のサイズを制限します。大きすぎる場合は { truncated, total, head } を返します。undefined は null として表示し、値がないことが分かるようにします
  • wx.context(token) — サイトの完全な動的コンテキストレポートです。小さい場合はインラインで返し、大きい場合は見出しのアウトライン付きの Markdown ファイルとして保存します
  • wx.browse(menuUrl, { include, filter, depth }) — ドキュメントポータルのメニューを決定論的にたどります
  • wx.search(term, { type, max, lines }) — REST ドキュメント、Headless の記事、管理レシピをランク付けした 1 つの hits リストで返します。レスポンスの型については「検索とブラウズ」を参照してください。エンドポイントを持つのはメソッドの検索結果だけです
  • wx.page(docsUrl) — ドキュメントページを読み込みます。実例はタイトルと行番号で返されます
  • wx.bash(cmd) — 保存済みファイルに対するシェル(GNU grep/sed を使用。awk は mawk、rg は使用できません)
  • wx.spec(docsUrl | code) — メソッドの正確なスキーマと、examplesPath に保存されているドキュメント独自のリクエスト例のタイトルを返します。検索結果の docsUrl を渡して直接読み込むか、インデックスを自分で検索するために生のコードを渡してください
  • wx.mgmtRecipes(q?) — 管理レシピのインデックスです。引数なしの場合はカテゴリを返し、単語を指定すると一致するレシピを返します
  • wx.ensureOAuthApp(token, { name, redirectUris, redirectDomains }) — 名前で検索するか、origin: "base44-app" を指定してヘッドレス OAuth アプリを作成し、許可済みのリダイレクト先にリダイレクトリストを追加します。{ clientId, created } を返します。clientId はブラウザーが訪問者トークンを発行するために使用します。context が OAuth アプリなしと報告した場合、またはこのアプリに戻る Wix ホストのフローを実行する前に呼び出してください。「訪問者認証と Wix ホストのフロー」を参照してください
  • wx.installApp(appDefId, siteId, token) — サイトに Wix アプリをインストールします(Apps Installer)。検出した API のアプリがサイトにインストールされていない場合は、まずインストールしてください。これは 1 回の呼び出しで済む前提条件であり、手作りの代替手段に切り替える理由にはなりません。appDefId は search または Apps-Created-by-Wix の表から取得し、siteId は context(サイトレポート)から取得します

デフォルトでは、検索は REST、管理レシピ、Headless を対象とした統合リクエストを 1 回送信します。 サービスがそれらをまとめてランク付けし、メソッドと記事を交互に並べます。ヘルパーはその順序を 維持します。max は統合された結果数を制限します(デフォルトは 15 件です)。

すべてのヘルパーは、結果が収まる場合はインラインで返します(4,000 文字以下 — exec の結果は約 5,000 文字で切り詰められます)。 それを超える結果は .agents/skills/wix-base44-connector/tmp/ に保存され、{ path, bytes, lines, outline } として返されます。outline はファイル内の位置を探すための目印です。保存済みファイルは次の 2 段階で扱います。まず wx.bash("grep -n 'term' <path> | head -40") で検索します(すべての保存ファイルを対象にする場合は grep -rn 'term' .agents/skills/wix-base44-connector/tmp/)。次に、grep で見つけた行を基準に offset/limit を指定して read_file で引用するか、45K の上限に収まる場合はファイル全体を読み込みます。

コンテキストを収集する — 動的コンテキストレポート

const { accessToken } = await base44.asServiceRole.connectors.getConnection("wix");
return await wx.context(accessToken);

1 つのレポートに、インストール済みアプリ(ID を含みます)、Stores のカタログバージョン(V1 と V3 のどちらかによってエンドポイントが決まります)、OAuth アプリ ID(訪問者の clientId でもあります)、ロケール、通貨、CMS コレクションが含まれます。 レポートが空の場合はトークンが無効であり、サイトが空という意味ではありません。

レポートに OAuth アプリがない場合、サイトにはまだアプリがありません。訪問者が操作する機能では、wx.ensureOAuthApp を呼び出して作成してください。この呼び出しで、フロントエンドが訪問者トークンを発行するための clientId が返されます。機能は訪問者フロー上に構築してください。

4,000 文字を超えるレポートは、一時 Markdown ファイルに全内容が保存されます。結果にはファイルのパス、バイト数と行数、見出しのアウトラインが含まれます。サイトのコンテキストを確認するには、そのファイルを読み込んでください。

Wix を学ぶ — API を探し、仕様を確認する

管理レシピ — 管理タスクの最初の手がかり

カテゴリ別に整理された管理フローです。eコマース、予約、ストア、cms、google-ads、サイト、連絡先、 get-paid、マーケティング、pricing-plans、イベント、ブログ、フォーム、レストラン、ドメイン、メディアなど:

await wx.mgmtRecipes();           // categories with counts
await wx.mgmtRecipes("stores");   // a category's list — or any task word: wx.mgmtRecipes("coupon")
// each row points at its recipe: `file` when the wix-manage skill is installed — read_file it
// straight off disk — else `url`: wx.page(url), whole when small, saved + outline when big

レシピには、どのメソッドのページにも載っていない前提条件、手順、注意点が記載されています。wx.search は同じレシピを hits リストに表示するため、どちらの方法でも見つけられます。

検索と閲覧

wx.search は、保存ファイルへの参照と、順位付けされたヒットを返します。各ヒットはメソッド、記事、またはレシピで、title フィールドで識別されます。エンドポイントがあるのはメソッドだけです。

type Section = { title: string; line: number }; // 1-based line in the saved file
type SearchResult = {
  path: string; bytes: number; lines: number; note?: string;
  hits: ({ docsUrl: string } & (
    | { method: string; endpoint: string | null; gist?: string; examples?: Section[] }
    | { article: string | null; line: number; outline?: Section[] }
    | { recipe: string | null; line: number; lines: number;
        file?: string; steps?: string[]; calls?: string[] }
  ))[];
};

path のファイルには、返された Markdown 全文が保存されています。一方、任意の詳細や上限を超えたヒットはインライン応答から省略される場合があります。タイトルまたはエンドポイントが null の項目は解析されていません。結果ブロックを解析できない場合は、hits の代わりに head と note が返されます。最終的なサイズ制限によるフォールバックでは、上記のオブジェクトではなく { truncated: true, total: number, head: string } が返されます。

// name the method? search finds it in one call:
const result = await wx.search("stores v3 update product"); // SearchResult above
// Keep all hit kinds; only a method hit has an endpoint to call and a schema for wx.spec.
// exploring an unfamiliar product? browse is deterministic — menuUrl alone orients (children + counts);
// filter before listing methods. browse works for both portals this skill uses — REST
// (api-reference) and WIX_HEADLESS (go-headless) — just pass that portal's menu URL.
await wx.browse("https://dev.wix.com/docs/api-reference/business-solutions/bookings/bookings",
                { include: ["METHOD"], filter: "resched", depth: 4 });
// non-REST portal — same call, that portal's menu URL:
await wx.browse("https://dev.wix.com/docs/go-headless/authentication", { depth: 2 });

// don't know where it lives? search ranks, never says "no match" — drop wrong-product hits
await wx.search("pause a pricing plan subscription and resume it");
// Same SearchResult: methods, articles, and recipes remain in ranked order.

製品とその機能 — よく使われるものを一部掲載:

  • Stores — 商品 · カテゴリ · 商品オプションとバリエーション · 在庫 · プロモーション · ほか7項目
  • Bookings — サービス · 予約 · クラス · スタッフ · 時間枠 · ウェイトリスト · ほか7項目
  • eCommerce — カート · チェックアウト · 注文 · 注文のフルフィルメント · 割引ルール · ほか7項目
  • Events — イベント · チケット定義 · RSVP · チェックイン · ほか6項目
  • Restaurants — メニュー · 商品 · 商品のオプション · オンライン注文 · 予約 · ほか9項目
  • Blog — 投稿 · 下書き投稿 · カテゴリ · タグ · ほか3項目
  • CMS — データ項目 · データコレクション · コレクションの権限 · 外部データベース · ほか4項目
  • Pricing Plans — プラン · 注文 · 定期購入 · 無料トライアル期間 · ほか4項目
  • Members & Contacts — 連絡先 · ラベル · 拡張フィールド · メンバー · バッジ · ほか7項目
  • Forms — フォームスキーマ · フォーム送信 · インタラクティブフォームセッション · ほか3項目
  • Loyalty — ロイヤルティポイント · 獲得ルール · ティア · リワード · ほか5項目

全リスト — 36製品すべての機能とドキュメントのパス:references/CAPABILITY_MAP.md。

フィールド、列挙型、または機能の不在を詳しく調べる場合は、仕様インデックスを確認してください。不在を証明できるのは仕様インデックスだけです。

ドキュメントページを読む

メソッドのページは100 KB以上あり、REST版とSDK版が並んでいて、同じフィールド名が異なる型で繰り返されています。マッピングとウィンドウ表示は同じ exec で行ってください。座標はコードで使うものであり、2回目の処理に使うものではありません:

const pg = await wx.page(docsUrl);   // whole text when small; else { path, bytes, lines, outline }
// pg.examples lists the page's worked requests as { title, line } — a complete request (URL,
// headers, body) is usually all you need: read_file(pg.path, offset: <its line>)
// anything else, windowed to your term in the same round:
return wx.bash(`sed -n '/^## REST API/,/^## JavaScript SDK/p' ${pg.path} | grep -B5 -A40 -i 'examples\\|<term>' | head -c 3800`);
// a giant fenced example → its field vocabulary instead of paging it:
// wx.bash(`sed -n '<a>,<b>p' ${pg.path} | grep -oE '"[a-zA-Z]+":' | sort -u | head -60`)

search はインラインのヒット情報とともに生のコンテンツも保存します。ヒットの6行だけでは足りない場合は、path を使って grep してください。

仕様インデックス — 特定したメソッドの正確なスキーマ

メソッドの docsUrl を渡します(検索または閲覧のヒットに含まれています)。spec はそのメソッドのスキーマ(リクエスト本文、レスポンス、フィルター可能なフィールドのマップ、例)を1回の呼び出しで直接取得します。フィールド名だけでなく、フィールドの説明も読んでください。そこにはルール(正規のフィールドはどれか、どのような場合に値が空になるか)が記載されています:

const sp = await wx.spec(hit.docsUrl);
// sp.examples — the method's worked requests as { title, line }, all saved at sp.examplesPath.
// The one that matches the task is rarely the first: read_file(sp.examplesPath, offset: <its line>)

結果を自分で組み立てますか?インデックスに対して生のコードを渡してください(lightIndex + getResourceSchemaByUrl):

await wx.spec(`
  const url = "<docsUrl from search/browse>";           // API method page, not a skill/article page
  const s = await getResourceSchemaByUrl(url);
  // A method URL resolves to exactly that method — take methods[0]. Don't match on docsUrl:
  // the reader normalizes the url, so equality against the one you passed can miss.
  const m = s.methods[0];
  return {
    call: m.publicUrl,                                       // callable https://www.wixapis.com/… URL
    body: m.requestBody?.content["application/json"].schema.properties,
    responses: m.responses,
    filterable: m.queryMethodData?.queryFieldsCapabilitiesMap      // query methods
             || m.searchMethodData?.searchFieldsCapabilitiesMap,   // search methods
    example: m.legacyExamples?.[0]?.content,
  };
  // { $circular: "<name>" } types resolve via s.components.schemas["<name>"] — complete in this call
`);

filterable は各フィールドで使用できる演算子とソート方法を示します。サーバー側でフィルターするのは、ここに記載された項目だけにしてください。それ以外はコード内でフィルターします。

コードを書く

JS SDK ではなく REST を使います — 構築中に実行する管理操作、バックエンド関数、フロントエンドページなど、あらゆる場面で同じです。ドキュメントページにはREST版とSDK版が並んでいます。REST版を読んでください。

ページに記載されたものだけを送信します — 必須フィールド、ネスト、列挙値は、記載どおりに指定してください。ヘッダーを付けるのは、その操作のRESTセクションに記載されている場合だけです。wix-site-id は絶対に指定しないでください。ここで使うトークンはすべてすでにサイトに紐付けられており、ブラウザーではこのヘッダーによって CORS プリフライトが完全に失敗します。

データ構造の確認も探索の一部です:spec() からメソッドのリクエスト/レスポンススキーマを読み取ってください。フィールドの説明には、正規のフィールドと、読み戻したときに値が空になる条件が記載されています。1回のライブプローブだけからデータ構造を推測しないでください。プローブに反映されるのは送信したパラメーターだけなので、コードで使うリクエストと同じものを使ってプローブしてください。

exec_tool で構築中に行う管理操作 — あなた自身が実行
const { accessToken } = await base44.asServiceRole.connectors.getConnection("wix");
const data = await wx.post("https://www.wixapis.com/contacts/v5/contacts/query",   // spec-index publicUrl
  { query: { cursorPaging: { limit: 10 } } }, accessToken);
// let it throw — the thrown message is your result; .catch hides the answer
return wx.clip({ error: null, count: data.contacts?.length, first: data.contacts[0] });
// `first` is one complete record — read the real field shapes off it; don't code from remembered key names
バックエンド関数 — アプリが所有者として実行

同じ API 呼び出しをデプロイして実行します。ここではヘルパーは実行されません — wx.* は exec に読み込まれるビルドツールであり、base44/functions/… には存在しません。そのため、通常の fetch を記述してください。また、exec の戻り値を制限する clip もありません。関数はデータをアプリに返します。

// inside base44/functions/… — plain fetch, no wx
const { accessToken } = await base44.asServiceRole.connectors.getConnection("wix");
const res = await fetch("https://www.wixapis.com/contacts/v5/contacts/query", {
  method: "POST",
  headers: { Authorization: `Bearer ${accessToken}`, "Content-Type": "application/json" },
  body: JSON.stringify({ query: { cursorPaging: { limit: 10 } } }),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);   // the API's own error, not a generic one
return (await res.json()).contacts;
  • この経路では、対象操作のページに別途記載がない限り、Authorization: Bearer … だけで認証が完了します。
  • 呼び出しごとではなく、業務領域ごとに 1 つのファイルを作成します。各ファイルは個別にデプロイされ、デプロイには時間がかかります。
  • デプロイした関数はすべて呼び出し、問題があれば修正してください。デプロイはテストではありません。
訪問者の認証と Wix ホスト型フロー

コードで表した「訪問者向けサイト」の構成(「What are you building?」)です。ページがインポートするファイルは 1 つです。コンテキストレポートにある clientId も、生成したトークンも秘密情報ではありません。2 つを合わせたものは「匿名の訪問者」であり、公開コードに含めても安全です。

// src/lib/wixClient.js
let token;
const mint = async (body) => {
  const r = await (await fetch("https://www.wixapis.com/oauth2/token", { method: "POST",
    headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) })).json();
  token = r.access_token; sessionStorage.setItem("wixRefresh", r.refresh_token);   // expires_in: 14400s = 4h
};
// first visit:  mint({ clientId: WIX_CLIENT_ID, grantType: "anonymous" });
// on expiry:    mint({ refreshToken: sessionStorage.getItem("wixRefresh"), grantType: "refresh_token" });
export const wix = (path, opts = {}) => fetch("https://www.wixapis.com" + path, { ...opts,
  headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" } });

リダイレクトセッションを含め、訪問者向け API をテストする必要がある場合は、exec_tool でテストできます。訪問者トークンを生成して API 呼び出しに渡すと、訪問者向けフロントエンドと同じ ID を使用してテストできます。 トークンの仕様については、トークンの取得を参照してください。 たとえば、公開読み取りをテストするには、次のようにします。

const { access_token: visitorToken } = await wx.post("https://www.wixapis.com/oauth2/token",
  { clientId: WIX_CLIENT_ID, grantType: "anonymous" });   // clientId: from the context report
return await wx.post("<a public read from Learn Wix>", { query: {} }, visitorToken);
// 200 ⇒ every visitor-facing page in the app is this same call, no server between
// a lean default response isn't the whole shape — contracts often define a fields param
// that opts INTO heavier parts (formatted prices, media); read the contract for it

訪問者をアプリに戻す Wix ホスト型フローでは、すべてヘッドレス OAuth アプリのリダイレクト設定が必要です。 これには、リダイレクトセッションだけでなく、購入者を Wix ホスト型チェックアウトの checkoutUrl に移動させてから戻す処理も含まれます。つまり、Wix がアプリ上の URL にリダイレクトするフローすべてが対象です。

訪問者向けフローの最初の手順は、このアプリ独自の URL を指定して wx.ensureOAuthApp を実行することです。 これにより、フロントエンドが訪問者トークンの生成に使う clientId が返されます(匿名の訪問者はログイン不要です)。サイトに OAuth アプリがない場合は作成し、すでにある場合は URL をそのリストに追加します。戻り先として有効なのはリストにある URL だけです。URL が不足していても、チェックアウトの作成や匿名トークンの取得は成功するため、不足に気づかないまま、実際の購入者がリダイレクトされたときに Wix 上で行き場を失うことになります。名前を基準に冪等に動作するため、同じ Base44 アプリに対して OAuth アプリを 2 つ作成しないでください。作成すると、最初の clientId への戻り先が機能しなくなります。このアプリは origin: "base44-app" を指定して作成され、これは OAuth アプリ上でこのフローを識別する名前です。origin は作成時にのみ設定されるため、手動で作成する OAuth アプリにも、作成時の呼び出しで同じ値を指定してください。

// Register BOTH of this app's own URLs — its preview URL and its published URL — so returns work
// before AND after publish. Both are built from the Base44 app id (NOT the Wix OAuth client_id /
// appId used above):
//   preview:   https://preview-sandbox--<base44-app-id>.base44.app
//   published: https://<app-name-slug>-<last 8 of the base44-app-id>.base44.app
//              where <app-name-slug> is the app's name (the brand name) slugified — e.g.
//              "Flash Sale Spark" -> flash-sale-spark-a4615088.base44.app.
// A custom domain the owner connects overrides the published one; the app name (hence the slug)
// can also change. So prefer the app's real current published URL when you have it, and update
// this same OAuth app whenever the name or domain changes — never create another.
const appOrigins = [previewUrl, publishedUrl]; // this app's actual preview + published URLs
const loginCallbacks = appOrigins.map(origin => new URL("/login-callback", origin).href);
const returnDomains = appOrigins.map(origin => new URL(origin).hostname);

// OAuth redirect configuration: exact login URLs versus domains for other returns.
// https://dev.wix.com/docs/go-headless/authentication/setup/allow-redirect-uris-and-domains.md
const { accessToken: adminToken } = await base44.asServiceRole.connectors.getConnection("wix");
const { clientId, created } = await wx.ensureOAuthApp(adminToken, {
  name: "My App",                     // this app's name; the lookup key on later runs
  redirectUris: loginCallbacks,       // login callbacks: matched exactly by the auth request
  redirectDomains: returnDomains,     // returns from Wix-hosted flows: hostnames only
});
// clientId is the public visitor client id the frontend client above mints from.
// When destinations change later — a custom domain, a renamed app — call this again with the
// new URLs: it updates the same OAuth app and preserves the entries already there.

訪問者トークンを取得した後、前述の訪問者クライアントを使うフロントエンドのリダイレクト例です。

import { wix } from "@/lib/wixClient";

// Flow prerequisites and supported intents:
// https://dev.wix.com/docs/go-headless/business-solutions/wix-hosted-pages/redirect-using-the-rest-api.md
export async function redirectToWix(intent, returnPath = "/") {
  // wix sends the minted visitor token. Never use the admin token here.
  // Admin tokens are for ad hoc management calls or backend functions implementing admin logic.
  // Pass the intent required by the selected flow's schema.
  const response = await wix("/headless/v1/redirect-session", {
    method: "POST",
    body: JSON.stringify({
      ...intent,
      callbacks: {
        postFlowUrl: new URL(returnPath, window.location.origin).href,
      },
    }),
  });
  if (!response.ok) throw new Error(`${response.status} ${await response.text()}`);
  const { redirectSession } = await response.json();
  window.location.assign(redirectSession.fullUrl);
}

垂直領域全体を構築するなら、wix-vibe-headless でブートストラップしてください。 対応する Wix の垂直領域(ストアフロント、予約、料金プラン、イベント、レストラン、レンタル、ブログなど)で訪問者向けサイトを構築する場合、wix-vibe-headless スキルを使えば、その領域をすばやく立ち上げられます。このスキルと同じ Wix API だけで構築されていますが、動作するコード(REST トランスポート、スキャフォールド、UI)に加えて、管理 API の抽象化(シーディング、設定)も提供するため、呼び出し回数を大幅に抑えて Base44 上に垂直領域をブートストラップできます。 エントリーポイントは www.wix.com/skills/wix-vibe-headless/platforms/base44.md を参照してください。STEP 1 にはインストール手順が含まれています。exec_tool で実行するそのままの npx skills add 呼び出し、関連スキル、垂直領域の表、スキャフォールドのデプロイが記載されており、その後ガイドは .agents/skills/wix-vibe-headless/platforms/base44.md に配置されます。参考資料として読むだけでもかまいませんが、インストールする場合は手順を最初から最後まで実行してください。提供されるスキャフォールドとシードの手順が、このスキルの価値の大部分を占めています。

コメント