0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

『miibo』WebHook機能でGASによるバリデーションを行う

Last updated at Posted at 2025-06-30

1. きっかけ

Googleスプレッドシートからデータを取得する場合、GASでWebアプリを生成して外部システムからWebHookで取得する方法がありますが、
試作時にはデプロイで「アクセスできるユーザ:全員」に設定しがちです。(そんなことはないですか!?)
それは当然セキュリティ観点としてはよくありません。

今回は、簡単に認証(バリデーション)する方法を、
会話型AI構築プラットフォーム「miibo」を使った実例で書いていきます。

2. 実際のGASコード

コード.gs
/* miiboエージェントは次のようなPOSTリクエストを送るのでstate.idをバリデーションに使います。
{
  "history": "ai: どうしましたか?お話しましょう。\n",
  "state": {
    "id": "[miiboのエージェントID],
    "name": "[miiboのエージェント名]"
  },
  "timestamp": "1751254417",
  "timestampString": "2025-06-30 12:33:37",
  "userId": "[セッション毎のユーザーID]",
  "utterance": "POST",
  "webhookType": "user_utterance"
}
*/

// 共通のJSONレスポンス生成関数
function jsonOutput(obj) {
  return ContentService
    .createTextOutput(JSON.stringify(obj))
    .setMimeType(ContentService.MimeType.JSON);
}

// POST関数(バリデーションとその後の処理関数実行)
function doPost(e) {
  const VALID_AGENT_ID = '[miiboのエージェントID]';  // miiboのエージェントID

  try {
    const data = JSON.parse(e.postData.contents);
    const agentId = data?.state?.id;

    if (!agentId) {
      return jsonOutput({ error: 'ERROR: state.id が指定されていません' });
    }

    if (agentId !== VALID_AGENT_ID) {
      return jsonOutput({ error: 'ERROR: エージェントIDが一致しません' });
    }

    // バリデーション成功 → シートデータ取得関数呼び出し
    return fetchSheetData('シート1');

  } catch (err) {
    return jsonOutput({ error: 'ERROR: JSONパース失敗または無効なリクエスト' });
  }
}

// シートデータ取得関数 ※以降を自由にコーディングする。
function fetchSheetData(sheetName) {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName(sheetName);

  if (!sheet) {
    return jsonOutput({ error: `Sheet "${sheetName}" not found.` });
  }

  const values = sheet.getDataRange().getValues();
  if (values.length === 0) {
    return jsonOutput([]);
  }

  if (values.length === 1) {
    let rowObj = {};
    for (let c = 0; c < values[0].length; c++) {
      const key = (values[0].length === 1) ? 'value' : `col${c + 1}`;
      rowObj[key] = values[0][c];
    }
    return jsonOutput([rowObj]);
  }

  const headers = values.shift();
  const dataRows = values.map(row => {
    let record = {};
    for (let c = 0; c < headers.length; c++) {
      const key = headers[c] || `col${c + 1}`;
      record[key] = row[c];
    }
    return record;
  });

  return jsonOutput(dataRows);
}

デプロイ時の権限は変えません。

  • 次のユーザとして実行:自分
  • アクセスできるユーザ:全員

「アクセスできるユーザ:全員」にしていても「doGET」関数は無いので、
WebアプリのURLを表示しても直接データが出力されることはありません。
WebアプリURLを直接叩いてもデータは採れない.png

3. miiboのWebHook設定

(参考情報)Webhook連携でシステム接続ガイド | miibo公式マニュアル
miibo_Webhook設定.png

  • 連携タイプ:通常のWebHook
  • Webhook名:(任意)
  • URL:(GASでデプロイしたWebアプリURL)
  • メソッド:POST
  • トリガーの種類:ユーザーが発言をした(*)
  • トリガー条件:何らかの発話があったら(*)
  • ペイロード(JSON):{"key":"value"}※プレースホルダーで表示されている初期値のまま。
  • シークレット:(自動で生成されています)

(*)トリガーについては是非、AIにタイミングを判断させる(Function Calling)などもお試しください。
・・・私は使いこなし方が分からなかったので、、とりあえずユーザの発話という基本的な方法にて設定します。

4. 動作の様子

  • スプレッドシート(シート1)にデータを用意して、、
    スプレッドシートのデータ.png
  • miiboチャットから質問するとWebhook発動+バリデーションが成功し、レスポンスが取れた。
    miiboチャット応答.png

以上です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?