3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【個人開発】Next.jsでLINE BOTアプリ作ってみた

Last updated at Posted at 2024-09-26

目次

1. アプリ概要
2. 使用技術
3. 開発
4. 終わりに

アプリ概要

QRコード

友達追加お願いします!

請求書発行BOT

機能

  • LIFFのアプリ内で請求書を作成できる
  • その請求書をLINEの友達に送信できる

作成動機

  • 家族や友達とお金の貸し借りをよくする
  • お金を返してと言いづらいことを解消したい
  • 身近なアプリであるLINEでNext.jsを使用したものを作りたかった
  • デプロイまでしたかった

Githubリンク

使用技術

技術一覧

  • TypeScript (Next.js)
  • Image Generation
  • LIFF(LINEログインチャネル)
  • LINE Official Account Manager
  • Vercel
  • Git
  • Github

開発

開発の流れ

  1. LINEログインチャネルを作成し、LIFFアプリを作成
  2. Next.jsでWebアプリを作成し、LIFFアプリに登録
  3. LINE公式アカウントを作成し、作成したLIFFアプリを埋め込む

1. LINEログインチャネルを作成しLIFFアプリを作成

LIFFアプリを作成するためにLINEログインチャネルを作成します。(LINEログインとLINEミニアプリ以外のチャネルにはLIFFアプリを追加できないみたいです。)
https://developers.line.biz/console/ にアクセスし、LINEアカウントでログインし、プロバイダーを作成し、そのプロバイダーの中にLINEログインチャネルを作成します。

請求書発行BOT

ログインチャネルを作成したら、「LIFF」タブからLIFFアプリを作成します。
エンドポイントURLは一旦 http://localhost:3000/ としておきます。

image.png

2. Next.jsでWebアプリを作成

環境変数

先ほど作成したLIFFアプリのLIFF IDをenvファイルに記載します。
LIFF IDはLIFFアプリ詳細画面に記載してあります。

請求書発行BOT
.env.local
NEXT_PUBLIC_LIFF_ID=my-liff-id

画像生成API

今回のアプリでは、ユーザーからの入力に応じて請求書の画像を動的に生成したいので、Next.jsの機能である Image Generation を利用してAPIを作成しました。

参考記事

src/app/api/og/invoice/route.ts
import { NextRequest } from "next/server";
import { ImageResponse } from "@vercel/og";

export const runtime = "edge";

export function GET(req: NextRequest) {
  if (req.method !== "GET") {
    return new Response("Method Not Allowed", { status: 405 });
  }

  try {
    const { searchParams } = new URL(req.url);

    const issueDate = searchParams.get("issueDate") || "";
    const dueDate = searchParams.get("dueDate") || "";
    const amount = searchParams.get("amount") || "";
    const message = searchParams.get("message") || "";

    return new ImageResponse(

      ()
    
    );
  } catch (e: unknown) {
    if (e instanceof Error) {
      console.log(`${e.message}`);
    } else {
      console.log("An unknown error occurred");
    }
    return new Response("画像の生成に失敗しました", {
      status: 500,
    });
  }
}

例えば
http://localhost:3000/api/og/invoice?issueDate=2024-09-25&dueDate=2024-10-01&amount=1000&message=支払いお願いします。
というURLにアクセスすると

請求書発行BOT

このような画像が返ってきます。

フロントエンド

src/app/page.tsx
"use client";

import { useEffect, useState } from 'react';
import liff from '@line/liff';

interface Profile {
  name: string;
  picture: string;
}

export default function Home() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [profile, setProfile] = useState<Profile>({ name: '', picture: '' });
  const [amount, setAmount] = useState('');
  const [dueDate, setDueDate] = useState('');
  const [message, setMessage] = useState('');

  useEffect(() => {
    const liffId = process.env.NEXT_PUBLIC_LIFF_ID;
    console.log('LIFF ID:', liffId);
    console.log('All env variables:', process.env);

    if (!liffId) {
      console.error('LIFF ID is missing');
      return;
    }

    liff
      .init({ liffId })
      .then(() => {
        if (liff.isLoggedIn()) {
          const idToken = liff.getDecodedIDToken();
          setProfile({ name: idToken?.name ?? '', picture: idToken?.picture ?? '' });
          setIsLoggedIn(true);
        }
      })
      .catch((error) => {
        console.log('LIFF initialization failed', error);
      });
  }, []);

  const handleLogin = () => {
    liff.login();
  };

  const getCurrentDate = () => {
    const today = new Date();
    const year = today.getFullYear();
    const month = String(today.getMonth() + 1).padStart(2, '0');
    const day = String(today.getDate()).padStart(2, '0');
    return `${year}-${month}-${day}`;
  };

  function handleCreateInvoice() {
    if (!amount || !dueDate || !message) {
      alert('金額、期日、メッセージを入力してください');
      return;
    }

    const issueDate = getCurrentDate();

    const invoiceImageUrl = `https://nextjs-line-invoice-bot.vercel.app/api/og/invoice?amount=${amount}&dueDate=${dueDate}&issueDate=${issueDate}&message=${encodeURIComponent(message)}`;

    liff.shareTargetPicker([
      {
        type: "text",
        text: "下記の内容にて請求書をお送りいたしますので、ご確認ください。",
      },
      {
        type: "image",
        originalContentUrl: invoiceImageUrl, 
        previewImageUrl: invoiceImageUrl,
      },
      {
        type: 'text',
        text: `このメッセージは請求書送信BOTから送信されています。\nhttps://lin.ee/qeZlCxi`,
      },
    ]);
  }

  return (

    ()

  );
}

デプロイ

今回はVercelを使ってデプロイしました。
Vercelの管理画面の Settings の Environment Variables からLIFF IDを設定する必要があります。
デプロイが完了したら、LIFFアプリのエンドポイントURLをデプロイ先のURLに変更します。

3. LINE公式アカウントを作成し、作成したLIFFアプリを埋め込む

LIFFの設定

LIFFアプリを自分以外の人が使えるように、ステータスを「開発中」から「公開済み」に変更します。

請求書発行BOT

またLIFFアプリのシェアターゲットピッカーはオンにしておきます。

公式LINEアカウントの作成

https://manager.line.biz/ にアクセスし公式LINEアカウントを作成します。

LIFFアプリを埋め込む

作成した公式アカウント内でLIFFアプリを使用します。
LIFFアプリのURLはLIFFアプリの管理画面に記載されています。

請求書発行BOT 

今回はリッチメニューから作成したLIFFアプリにアクセスできるようにしました。

請求書発行BOT  請求書発行BOT

色々面白い設定もできて触っていて楽しかったです。

終わりに

今回作成したアプリはシンプルなものなので、機能を追加してもっと便利なアプリにしたいと思いました。
はじめてLINEのアプリを作成してみて、さまざまな機能があることを知り、使いこなせるともっと面白くて便利なアプリを作成できると思いました。

追記

このアプリを改良して、機能の追加やデザインの修正をしてみました。

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?