7.8.drf实现短信验证码发送

工具类

apps/utils/yunpian.py

import json
import requests


class YunPian(object):

    def __init__(self, api_key):
        self.api_key = api_key
        self.single_send_url = "https://sms.yunpian.com/v2/sms/single_send.json"

    def send_sms(self, code, mobile):
        params = {
            "apikey": self.api_key,
            "mobile": mobile,
            "text": "【Mo Shop】您的验证码是{code}。如非本人操作,请忽略本短信".format(code=code)
        }

        response = requests.post(self.single_send_url, data=params)
        re_dict = json.loads(response.text)
        return re_dict


if __name__ == "__main__":
    yun_pian = YunPian("")
    yun_pian.send_sms("2548", "")

serializer

apps/users/serializers.py

import re
from datetime import datetime
from datetime import timedelta

from django.contrib.auth import get_user_model
from rest_framework import serializers

from mo_shop.settings import REGEX_MOBILE
from .models import VerifyCode

User = get_user_model()


class SmsSerializer(serializers.Serializer):
    mobile = serializers.CharField(max_length=11)

    def validate_mobile(self, mobile):
        """
        验证手机号码
        :param mobile: 手机号
        :return:
        """

        # 验证手机号码是否合法
        if not re.match(REGEX_MOBILE, mobile):
            raise serializers.ValidationError("手机号码非法")

        # 手机是否注册
        if User.objects.filter(mobile=mobile).count():
            raise serializers.ValidationError("用户已经存在")

        # 验证码发送频率
        one_minute_ago = datetime.now() - timedelta(hours=0, minutes=1, seconds=0)
        if VerifyCode.objects.filter(add_time__gt=one_minute_ago, mobile=mobile).count():
            raise serializers.ValidationError("距离上一次发送未超过60s")

        return mobile

viewSet

apps/users/views.py

from random import choice

from rest_framework import status
from rest_framework import viewsets
from rest_framework.mixins import CreateModelMixin
from rest_framework.response import Response

from mo_shop.settings import APIKEY
from users.models import VerifyCode
from users.serializers import SmsSerializer
from utils.yunpian import YunPian


class SmsCodeViewSet(CreateModelMixin, viewsets.GenericViewSet):
    """
    发送短信验证码
    """
    serializer_class = SmsSerializer

    def generate_code(self):
        """
        生成四位数字的验证码
        :return:
        """
        seeds = "1234567890"
        random_str = []
        for i in range(4):
            random_str.append(choice(seeds))
        return "".join(random_str)

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        mobile = serializer.validated_data["mobile"]
        code = self.generate_code()

        # 发送短信验证码
        # yun_pian = YunPian(APIKEY)
        # sms_status = yun_pian.send_sms(code=code, mobile=mobile)

        # 模拟短信成功发送
        print("【Mo Shop】您的验证码是{code}。如非本人操作,请忽略本短信".format(code=code))
        sms_status = {'code': 0, 'msg': '发送成功', 'count': 1, 'fee': 0.05, 'unit': 'RMB', 'mobile': mobile, 'sid': 16829054647}

        if sms_status["code"] != 0:
            return Response({"mobile": sms_status["msg"]}, status=status.HTTP_400_BAD_REQUEST)
        else:
            code_record = VerifyCode(code=code, mobile=mobile)
            code_record.save()
            return Response({"mobile": mobile}, status=status.HTTP_201_CREATED)

url配置

mo_shop/urls.py

...
from django.urls import path, include
from rest_framework.routers import DefaultRouter

from users.views import SmsCodeViewSet

router = DefaultRouter()

# 配置短信验证码的url
router.register(r'codes', SmsCodeViewSet, basename="codes")

urlpatterns = [
    ...
    path('', include(router.urls)),

]

settings

mo_shop/settings.py

# REGEX
REGEX_MOBILE = "^1[358]\d{9}$|^147\d{8}$|^176\d{8}$"

# 云片网设置
APIKEY = ""

Last updated

Was this helpful?