LoginSignup
1
2

ウオッ?! Django REST FrameworkとAWS SNSでアルティメットにクールなSMS送信を実現!!!🐰

Last updated at Posted at 2024-01-16

概要

Django REST FrameworkとAWS SNSを利用してSMSテキストを送信する実装を説明します!

使用技術

pyproject.toml
python = "^3.11.2"
Django = "^4.2.7"
djangorestframework = "^3.14.0"
boto3 = "^1.28.84"
injector = "^0.21.0"
pydantic = "^1.10.7"
gunicorn = "^21.2.0"

説明する前の前提

コードの細部の説明はあまりしません
また、インポートもとのコードが不要な場合は明記していません
ご了承ください🙇

AWS SNSとは

以下、公式サイトに説明は任せる

まずはコードの確認

sms_view.py
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.viewsets import ViewSet

from common.environment_variable import settings
from common.sms import SnsWrapper
from app.injectors import injector
from app.serializers import SmsSerializer


class SmsViewSet(ViewSet):
    """SMSを送信するAPI"""

    serializer_class = SmsSerializer

    @action(methods=["post"], detail=False)
    def sms(self, request):
        """SMS送信API

        Parameters:
            phone_number(str): 電話番号

        Returns:
            detail (str): メッセージ
        """

        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)

        sms = injector.get(SnsWrapper)
        sms.publish_text_message(
            settings.INTERNATIONAL_TEL_IDENTIFICATION_NUMBER
            + serializer.validated_data.get("phone_number"),
        )
        return Response(
            {"detail": "SMS送信に成功しました"},
            status=status.HTTP_200_OK,
        )

SMS送信のAPIのビュー部分です

injector.py
import boto3
from injector import Binder, Injector, Module

from common.environment_variable import aws_settings
from common.sms import SnsResource, SnsWrapper


class SnsWrapperModule(Module):
    def configure(self, binder):
        binder.bind(SnsWrapper)


class LocalModule(Module):
    """Local環境用のモジュール"""

    def configure(self, binder: Binder) -> None:
        sns_resource = SnsResource(
            boto3.resource(
                "sns",
                region_name=aws_settings.REGION_NAME,
                # localstackに接続(http://localhost:4566)
                endpoint_url=aws_settings.ENDPOINT_URL,
            )
        )
        binder.bind(SnsResource, to=sns_resource)


class DevModule(Module):
    """Dev環境用のモジュール"""

    def configure(self, binder: Binder) -> None:
        sns_resource = SnsResource(
            boto3.resource("sns", region_name=aws_settings.REGION_NAME)
        )
        binder.bind(SnsResource, to=sns_resource)


injector = Injector([SnsWrapperModule()])

ローカル環境とDEV環境で含めるラッパーモジュールを切り替えられるようにしています
ローカルではlocalstackを使用して、SNSの擬似的なレスポンスを返してくれるようにしています

sms.py
from injector import inject

from common.environment_variable import settings


class SnsResource:
    """SNSのResource用のクラス"""

    def __init__(self, sns_resource):
        self.sns_resource = sns_resource


class SnsWrapper:
    """Amazon SNSのトピックとサブスクリプションの機能をカプセル化する"""

    @inject
    def __init__(self, sns_resource: SnsResource):
        """
        :param sns_resource: Boto3 Amazon SNSリソース
        """
        self.sns_resource = sns_resource.sns_resource

    def publish_text_message(self, phone_number):
        """
        サブスクリプションを必要とせずに、直接電話番号にテキストメッセージを送信するメソッド

        :Parameters:
            phone_number(str): 電話番号
        """
        message = "SMSテキストメッセージだぽん"
        self.sns_resource.meta.client.publish(
            PhoneNumber=phone_number,
            Message=message,
            MessageAttributes={
                "AWS.SNS.SMS.SenderID": {
                    "DataType": "String",
                    # 差出人名を指定できます
                    "StringValue": settings.SMS_SENDER_NAME,
                }
            },
        )

以下記事を参考に送信メソッドを実装します

環境変数の管理方法について

環境変数の管理方法については以下を参照ください

boto3について

最後に

流れさえ、抑えればスムーズに開発が進められると思います🐰

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