2
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?

LINEミニアプリAdvent Calendar 2024

Day 14

24日目にLINEミニアプリが完成する初心者 ── Day14. 問い合わせメッセージ

Last updated at Posted at 2024-12-13

はじめに

前回は「24 日目に LINE ミニアプリが完成する初心者 ── Day13. 問い合わせ機能の実装」と題して、Flex Message を使用した問い合わせ種別選択の実装を行いました。


今回は、前回の続きで問い合わせ内容の入力を促し、入力完了後にはお礼メッセージを送るよう実装していきたいと思います。

image.png

リファクタリング

前回実装したコードの一部をリファクタリングします。

問い合わせ種別を options としてまとめておきます。

src/nextjs/pages/api/webhook.ts
      const options = [
        "物件情報の問い合わせ",
        "お家探しの情報収集のやり方",
        "住宅購入資金の考え方・予算について",
        "新築と中古どちらを買うべきか?",
        "リノベーションの流れについて",
        "湘南エリアの魅力",
        "リノベ不動産辻堂羽鳥店について",
        "その他",
      ];

これでflexMessageで繰り返しになっている箇所をmapとしてまとめて記述したいと思います。
src/nextjs/pages/api/webhook.ts
        const flexMessage = {
          type: "flex",
          altText: "問い合わせカテゴリ",
          contents: {
            type: "bubble",
            body: {
              type: "box",
              layout: "vertical",
              contents: [
                {
                  type: "box",
                  layout: "vertical",
                  contents: [
                    {
                      type: "text",
                      text: "お問い合わせの種類を選択してください。",
                      weight: "regular",
                      offsetStart: "xxl",
                      margin: "sm",
                      offsetTop: "md",
                    },
                    {
                      type: "separator",
                      margin: "xxl",
                      color: "#e5e5e5",
                    },
                  ],
                  backgroundColor: "#fafafa",
                },
                {
                  type: "box",
                  layout: "vertical",
                  contents: [
                    ...options.map((option) => ({
                      type: "button",
                      action: {
                        type: "message",
                        label: option,
                        text: option,
                      },
                    })),
                  ],
                  paddingTop: "md",
                  paddingBottom: "md",
                },
              ],
              paddingAll: "none",
            },
            styles: {
              footer: {
                separator: true,
              },
            },
          },
        };

メッセージ送信処理は関数としてまとめておきたいと思います。
src/nextjs/pages/api/webhook.ts
async function sendReply(replyToken, messages) {
  const url = "https://api.line.me/v2/bot/message/reply";
  await fetch(url, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${process.env.NEXT_PUBLIC_LINE_ACCESS_TOKEN}`,
    },
    body: JSON.stringify({ replyToken, messages }),
  });
}

返信内容の追加

リファクタリングが完了したので、ここから実際に返信内容を追加していきます。

先にステータスが保持できるようコード冒頭で Map を作成しておきます。

src/nextjs/pages/api/webhook.ts
const userState = new Map();

今回はユーザー ID ごとに状態を追跡していきます。

これに伴い、お問い合わせがあった際にuserIduserStateを更新する行を追加しておきます。

src/nextjs/pages/api/webhook.ts
      if (userMessage === ">お問い合わせ") {
        userState.set(userId, { step: "categorySelection" });

        const flexMessage = {
          // (中略)
        };

        await sendReply(event.replyToken, [flexMessage]);
      }

お問い合わせ内容確認

問い合わせ種別が選択されたら、「問い合わせ内容を入力してください。」という返信を返すよう追加していきます。

else ifとしてuserMessageが options に含まれているかを確認します。

src/nextjs/pages/api/webhook.ts
      if (userMessage === ">お問い合わせ") {
        // (中略)
      } else if (options.includes(userMessage)) {
        userState.set(userId, { step: "detailsInput", category: userMessage });

        await sendReply(event.replyToken, [
          { type: "text", text: "お問い合わせ内容を入力してください。" },
        ]);
      }

お礼メッセージ

上記同様else ifで条件を追加していきます。

src/nextjs/pages/api/webhook.ts
      else if (options.includes(userMessage)) {
        // (中略)
      } else if (
        userState.has(userId) &&
        userState.get(userId).step === "detailsInput"
      ) {
        userState.get(userId);

        userState.delete(userId);

        await sendReply(event.replyToken, [
          {
            type: "text",
            text: "お問い合わせいただきありがとうございます!ご回答には通常2営業日以内に返答いたします。なにかご不明点があれば、お気軽にお問合せください!",
          },
        ]);
      }

コードの全体像は以下の通りです。
src/nextjs/pages/api/webhook.ts
const userState = new Map();

export default async function handler(req, res) {
  if (req.method === "POST") {
    const { events } = req.body;

    if (!events || events.length === 0) {
      return res.status(200).json({ message: "No events" });
    }

    const event = events[0];
    if (event.type === "message" && event.message.type === "text") {
      const userMessage = event.message.text;
      const userId = event.source.userId;

      const options = [
        "物件情報の問い合わせ",
        "お家探しの情報収集のやり方",
        "住宅購入資金の考え方・予算について",
        "新築と中古どちらを買うべきか?",
        "リノベーションの流れについて",
        "湘南エリアの魅力",
        "リノベ不動産辻堂羽鳥店について",
        "その他",
      ];

      if (userMessage === ">お問い合わせ") {
        userState.set(userId, { step: "categorySelection" });

        const flexMessage = {
          type: "flex",
          altText: "問い合わせカテゴリ",
          contents: {
            type: "bubble",
            body: {
              type: "box",
              layout: "vertical",
              contents: [
                {
                  type: "box",
                  layout: "vertical",
                  contents: [
                    {
                      type: "text",
                      text: "お問い合わせの種類を選択してください。",
                      weight: "regular",
                      offsetStart: "xxl",
                      margin: "sm",
                      offsetTop: "md",
                    },
                    {
                      type: "separator",
                      margin: "xxl",
                      color: "#e5e5e5",
                    },
                  ],
                  backgroundColor: "#fafafa",
                },
                {
                  type: "box",
                  layout: "vertical",
                  contents: [
                    ...options.map((option) => ({
                      type: "button",
                      action: {
                        type: "message",
                        label: option,
                        text: option,
                      },
                    })),
                  ],
                  paddingTop: "md",
                  paddingBottom: "md",
                },
              ],
              paddingAll: "none",
            },
            styles: {
              footer: {
                separator: true,
              },
            },
          },
        };

        await sendReply(event.replyToken, [flexMessage]);
      } else if (options.includes(userMessage)) {
        userState.set(userId, { step: "detailsInput", category: userMessage });

        await sendReply(event.replyToken, [
          { type: "text", text: "お問い合わせ内容を入力してください。" },
        ]);
      } else if (
        userState.has(userId) &&
        userState.get(userId).step === "detailsInput"
      ) {
        userState.get(userId);

        userState.delete(userId);

        await sendReply(event.replyToken, [
          {
            type: "text",
            text: "お問い合わせいただきありがとうございます!ご回答には通常2営業日以内に返答いたします。なにかご不明点があれば、お気軽にお問合せください!",
          },
        ]);
      }
    }

    return res.status(200).json({ message: "Event processed" });
  } else {
    res.setHeader("Allow", ["POST"]);
    return res.status(405).json({ error: `Method ${req.method} Not Allowed` });
  }
}

// メッセージ返信
async function sendReply(replyToken, messages) {
  const url = "https://api.line.me/v2/bot/message/reply";
  await fetch(url, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${process.env.NEXT_PUBLIC_LINE_ACCESS_TOKEN}`,
    },
    body: JSON.stringify({ replyToken, messages }),
  });
}

デプロイ

以下のコマンドでいつも通りデプロイを行っていきましょう。

$ netlify deploy --build --prod

動作確認

LINE の画面で「>お問い合わせ」->「お問い合わせ種別の選択」と進んでみると、先ほど設定したお問い合わせ内容確認と、お礼メッセージが表示されると思います!

まとめ

ここまでで、Flex Message による問い合わせの流れが完成しました。

次回は、問い合わせのあった内容のスプレッドシート出力を実装していきたいと思います。

残りは 10 日!
気になる方は是非フォローやカレンダー購読をお願いします:star:

2
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
2
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?