Skip to content

cosicosilife.com

ライフハックについていろいろ書きます

Primary Menu
  • サイトマップ
  • クラウド技術
  • 安全資産投資
  • 旅行
  • ライフハック
  • プライバシーポリシー
  • 運営者情報とご連絡先
  • Home
  • クラウド技術
  • LINEとAWSを使った料金確認システムの構築ガイド
  • クラウド技術

LINEとAWSを使った料金確認システムの構築ガイド

david 2025年2月10日
image

この記事の目次(クリックしたらジャンプ)

Toggle
    • はじめに
    • 本記事で作成するもの
    • LINE APIの準備
    • 1. LINE Messaging APIの設定
  • AWSサービスの設定
    • IAMロールの作成
    • AWS Lambdaの設定
    • チャネルアクセストークンと、シークレットを環境変数へ登録
    • チャネルアクセストークンとシークレットを取得
    • 環境変数に追加
    • レイヤーの追加
    • AWS API Gateway
    • テストとデプロイメント
    • 最後に

はじめに

この記事では、LINEのチャネルを通じてAWSの料金情報を確認するシステムを構築する方法を詳しく解説します。このシステムは、AWS API Gateway、Lambda、そしてLINE Messaging APIを組み合わせて実現します。この機能はLINEでお手軽にAWSのコンソールにログインしないで情報を確認できるので非常に便利です。

本記事で作成するもの

このシステムでは、LINEのチャットボットを通じて以下の機能を提供します:

「今月の詳細」「先月の詳細」と入力すれば、下記のように、項目ごとの料金詳細表示

「先月」「今月」と入力すれば、単純に費用のみを表示します

LINE APIの準備

1. LINE Messaging APIの設定

  1. LINEチャネルの作成
    • LINE Developer Consoleにアクセスし、新しいMessaging APIチャネルを作成します。
    • チャネルシークレットとチャネルアクセストークンを取得しておきます。ここでは皆さんはすでに、こちらの記事で、大体やり方はご存じであるという前提で説明していきます

作成出来たら、右端の絵「設定」をクリックして、左側の「Messaging API」をクリックします

設定完了すると下記のように チャネルIDとシークレットが表示されます。Webhook URLはあとでAWSのAPIにつかうURLを入力します. 

AWSサービスの設定

IAMロールの作成

今回はlambda関数に、コストとcloudwatchへのアクセスを許可しますので、ロールを作成します。

「AWSのサービス」をクリック

ユースケースはLambda を栗㏍して 「次へ」

ポリシーは適切なものを許可します。

ポリシーは下記の2つを許可します

AWSBillingReadOnlyAccess  

AWSLambdaBasicExecutionRole

また、カスタムポリシーも許可してください。下記のポリシーをJSONで書いて保存してください

JSONは下記になります

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": "ce:GetCostAndUsage",
			"Resource": "*"
		}
	]
}

ポリシーの信頼関係は「信頼されたエンティティ」で下記を付与してください

JSONはこちらになります

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

こちらは何も設定せず、「次」をクリック

ロール名をつけてください

タグは任意です。「ロールを作成」をクリックしてください

問題なければ下記のようにロールが作成されます。

AWS Lambdaの設定

ここでは、APIゲートウェイで受け取ったリクエストを処理するコードを書きます。

AWSのLambdaから関数を作成します

ロールは先ほど作ったものを利用します

作成出来たら、コードのタブからコードを追加します

下記がコードとなります

import os
import json
from datetime import datetime, timedelta
import boto3
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import LineBotApiError
from linebot.models import TextSendMessage

# 環境変数からLINE Messaging APIのアクセストークンとシークレットを取得
LINE_ACCESS_TOKEN = os.getenv('YOUR_CHANNEL_ACCESS_TOKEN')
LINE_CHANNEL_SECRET = os.getenv('YOUR_CHANNEL_SECRET')

# アクセストークンとシークレットが環境変数に設定されていない場合のエラーハンドリング
if not LINE_ACCESS_TOKEN or not LINE_CHANNEL_SECRET:
    raise ValueError("LINEアクセストークンまたはシークレットが環境変数に設定されていません。")

line_bot_api = LineBotApi(LINE_ACCESS_TOKEN)
handler = WebhookHandler(LINE_CHANNEL_SECRET)

def get_billing_info(message):
    """
    AWS料金情報を取得する。
    - メッセージに応じて期間や表示形式を切り替える。
    """
    client = boto3.client('ce', region_name='us-east-1')
    today = datetime.today()

    # 料金期間と出力形式を設定
    if message == "今月":
        start_date = today.replace(day=1).strftime('%Y-%m-%d')
        end_date = (today + timedelta(days=1)).strftime('%Y-%m-%d')
        detail = False
    elif message == "先月":
        first_day_last_month = (today.replace(day=1) - timedelta(days=1)).replace(day=1)
        start_date = first_day_last_month.strftime('%Y-%m-%d')
        end_date = today.replace(day=1).strftime('%Y-%m-%d')
        detail = False
    elif message == "今月の詳細":
        start_date = today.replace(day=1).strftime('%Y-%m-%d')
        end_date = (today + timedelta(days=1)).strftime('%Y-%m-%d')
        detail = True
    elif message == "先月の詳細":
        first_day_last_month = (today.replace(day=1) - timedelta(days=1)).replace(day=1)
        start_date = first_day_last_month.strftime('%Y-%m-%d')
        end_date = today.replace(day=1).strftime('%Y-%m-%d')
        detail = True
    else:
        return "サポートされていないコマンドです。"

    try:
        # AWSの料金情報を取得
        response = client.get_cost_and_usage(
            TimePeriod={'Start': start_date, 'End': end_date},
            Granularity='MONTHLY',
            Metrics=['AmortizedCost'],
            GroupBy=[{'Type': 'DIMENSION', 'Key': 'SERVICE'}]
        )

        if detail:
            # サービスごとの詳細情報を整形
            details = [
                f"{group['Keys'][0]}: {group['Metrics']['AmortizedCost']['Amount']} USD"
                for group in response['ResultsByTime'][0]['Groups']
            ]
            return f"{start_date}から{end_date}までのサービスごとの料金詳細:\n" + "\n".join(details)
        else:
            # 合計料金を取得
            total_billing = response['ResultsByTime'][0]['Total']['AmortizedCost']['Amount']
            return f"{start_date}から{end_date}までの総料金: {total_billing} USD"

    except boto3.exceptions.Boto3Error as e:
        # AWSサービス関連のエラー処理
        print(f"AWS Error: {str(e)}")
        return "料金情報の取得に失敗しました。AWSサービスに接続できませんでした。"
    except Exception as e:
        # その他の予期しないエラー処理
        print(f"Unexpected Error: {str(e)}")
        return "料金情報の取得に失敗しました。予期しないエラーが発生しました。"

def lambda_handler(event, context):
    """
    Lambda関数のエントリーポイント。
    - LINEからのWebhookイベントを処理し、返信を送信。
    """
    try:
        # イベントデータのログ出力(デバッグ用)
        print("Event received:", event)

        # イベントのボディをパース
        body = json.loads(event['body'])
        message_text = body['events'][0]['message']['text']
        reply_token = body['events'][0]['replyToken']

        # 無効なリプライトークンの場合、ログ出力して終了
        if reply_token == "dummyReplyToken":
            print("Dummy reply token detected. Skipping reply.")
            return {'statusCode': 200, 'body': 'Dummy token, no reply sent'}

        # メッセージに基づいてAWS料金情報を取得
        billing_info = get_billing_info(message_text)

        # LINE Messaging APIで返信
        line_bot_api.reply_message(
            reply_token,
            TextSendMessage(text=billing_info)
        )
        return {'statusCode': 200, 'body': 'Success'}

    except LineBotApiError as e:
        # LINE Messaging APIのエラー処理
        print(f"LineBotApiError: {e.status_code}, {e.error.message}")
        return {'statusCode': 400, 'body': 'LineBotApiError occurred'}

    except Exception as e:
        # その他の例外処理
        print(f"Unexpected Error: {str(e)}")
        return {'statusCode': 500, 'body': 'Internal Server Error'}

チャネルアクセストークンと、シークレットを環境変数へ登録

YOUR_CHANNEL_ACCESS_TOKEN

YOUR_CHANNEL_SECRET

については環境変数として作成します。

チャネルアクセストークンとシークレットを取得

チャネルのアクセストークンは、「Messaging API 設定」のタブの下側にあります

「発行」ボタンをクリックして

発行された トークンをコピペしておいてください

環境変数に追加

「設定」タブから「環境変数」で追加します

チャネルのアクセストークンは,「チャネルの基本設定」の下側にあります

設定を完了したら「保存」ボタンを押してください

これが完了すれば「テスト」でOKとなるはずです

レイヤーの追加

最後にlinebot のレイヤーを追加します。コードの画面から下に向かってスクロールダウンして「レイヤー」の「レイヤーの追加」をクリック

arn:aws:lambda:us-east-1:590184098214:layer:linebot:1 を追加できるので ARNを指定して追加します 「追加」ボタンを教えて、保存します

これでlambdaの設定は完了です

AWS API Gateway

  1. API GatewayでREST APIの作成

REST API を構築します

新しいAPI

エンドポイントタイプはリージョンで問題ありません。「APIの作成」をクリックします

リソースを作成

CORSを有効にして、「リソースを作成」をクリック

作成されたらCORSを有効にします

メソッドを作成でPOSTを作成します

POSTを選択して、先ほど作成した Lambda 関数をリンクします

ほかの箇所は変更せずに、APIメソッドを作成 ボタンを押します

作成出来たら「メソッドレスポンス」を編集して

下記の3つを追加して、保存します

下記のようになればOKです


この状態でAPIをデプロイします

モーダル画面でステージを設定して、デプロイします

デプロイが成功すれば、URLを呼び出す の箇所にURLが出てきますので、これをコピペします

テストとデプロイメント

先ほど作成したLINEチャネルで上記のAPIゲートウェイのデプロイで取得した URLを下記のWebhook URLに登録します

LINEからテストしてみれば成功するはずです

最後に

いかがでしたでしょうか?LINEを使えば無料でこのようなツールが作れるので面白いかとおもいます。次回はGAS(Google App Script)とLINEを連携したいと思います

Continue Reading

Previous: AWS cloudformation とbeanstalk でアプリ作成
Next: 【初心者向け】DNSのSRVレコードとは?役割・設定・動作を詳しく解説

Related Stories

A realistic whale with the word Docker in a manga style, without making the eyes too cute
  • クラウド技術

david 2025年6月2日
A realistic whale with the word Docker in a manga style, without making the eyes too cute
  • クラウド技術

Ubuntu上にArgo CDをインストールし、ブラウザアクセスできるようにする手順(k8s.cosicosilife.com対応)

david 2025年6月1日
A realistic whale with the word Docker in a manga style, without making the eyes too cute
  • クラウド技術

【初心者向け】Argo CD に初めてのアプリケーションをデプロイしてみよう!

david 2025年6月1日
  • argocdの導入
  • (タイトルなし)
  • オンプレUbuntuでHelm中心にKubernetes運用・CI/CD構築
  • Ubuntu上にArgo CDをインストールし、ブラウザアクセスできるようにする手順(k8s.cosicosilife.com対応)
  • 【初心者向け】Argo CD に初めてのアプリケーションをデプロイしてみよう!
  • サイトマップ
  • クラウド技術
  • 安全資産投資
  • 旅行
  • ライフハック
  • プライバシーポリシー
  • 運営者情報とご連絡先
  • サイトマップ
  • クラウド技術
  • 安全資産投資
  • 旅行
  • ライフハック
  • プライバシーポリシー
  • 運営者情報とご連絡先
Copyright © Cosicosilife | MoreNews by AF themes.