腾讯短信发送(基于v3版本封装)

安装模块

pip3 install tencentcloud-sdk-python -i https://pypi.douban.com/simple

url

# 发送短信
path('tencent_sms/', TencentSmsCodeAPIView.as_view()),

view(如果不使用celery的话,使用普通短信发送函数调用接口)

import random
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response

from cat.libs.sms.tencent_sms import t_sms
from celery.result import AsyncResult


class TencentSmsCodeAPIView(APIView):
    """腾讯短信发送(基于v3版本)"""
    permission_classes = []

    def get(self, request, *args, **kwargs):
        telephone = request.GET.get('phone')
        tpl = request.GET.get('tpl')
        # 同步
        """        
        t_sms.telephone = telephone
        t_sms.tpl = tpl
        print(t_sms.telephone, t_sms.tpl)
        ret = t_sms.sms_check()
        """
        # 异步
        from cat_celery.sms.tasks import send_sms
        # 执行任务
        ret = send_sms.delay(telephone, tpl)
        # 异步判断返回值
        if isinstance(ret, AsyncResult):
            return Response(data='ok', status=status.HTTP_200_OK)

        data = {
            'status': ret.get("status"),
            'msg': ret.get("msg"),
        }
        return Response(data=data, status=status.HTTP_200_OK)

TencentSmsCode(发送短信的封装)

import re
import json
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.sms.v20210111 import sms_client, models

from django.conf import settings

from django_redis import get_redis_connection


# pip3 install tencentcloud-sdk-python


class TencentSmsCode(object):
    """
    phone str
    code [str,str]
    tpl_id str
    """

    def __init__(self, telephone, code, tpl):
        self.telephone = telephone
        self.code = code
        self.tpl = tpl
        self.tpl_id = ''

    def __data(self, status, msg):
        """返回格式封装"""
        data = {
            "status": status,
            "msg": msg
        }
        return data

    def __check(self):
        """进行校验是否合法"""
        ret_telephone = self.__check_telephone()
        if not ret_telephone:
            data = self.__data(1001, '手机号格式不正确')
            return data
        # 进行校验是否有tpl
        ret_tpl = self.__check_tpl()
        if not ret_tpl:
            data = self.__data(1002, '模板不正确')
            return data
        # 验证码的生成 redis进行查询是否过期 redis的存储
        ret_code = self.__set_code()
        if not ret_code:
            data = self.__data(1003, '60秒只能发送1次')
            return data
        return self.__data(1005, '发送成功')

    def sms_check(self):
        """
        正常发送
        """
        ret = self.__check()
        # 校验
        # print(ret)
        status = ret.get('status')

        if status in [1001, 1002, 1003]:
            return ret
        self.__send_msg()

        return ret

    def __send_msg(self):
        try:
            phone = '+86%s' % self.telephone
            cred = credential.Credential(settings.TENCENT_SECRET_ID, settings.TENCENT_SECRET_KEY)
            httpProfile = HttpProfile()
            httpProfile.endpoint = "sms.tencentcloudapi.com"

            clientProfile = ClientProfile()
            clientProfile.httpProfile = httpProfile
            client = sms_client.SmsClient(cred, "ap-guangzhou", clientProfile)

            req = models.SendSmsRequest()
            params = {
                "PhoneNumberSet": [phone, ],  # 手机号
                "SmsSdkAppId": settings.TENCENT_APP_ID,  # 应用AppId,v2要应用sdk/key,v3新增了密钥,取消了key
                "SignName": settings.TENCENT_SIGN,  # 签名的模版名称
                "TemplateId": self.tpl_id,  # 短信模板的id,str格式
                "TemplateParamSet": self.code  # 格式必须是 ["验证码",参数]  参数可以为空,具体看自己的模板要求
            }
            req.from_json_string(json.dumps(params))
            resp = client.SendSms(req)

            print("resp.to_json_string()", resp.to_json_string())

            if resp.SendStatusSet[0].Fee == 1:
                return True
            return
        except TencentCloudSDKException as err:
            print('err', err)

    def __check_telephone(self):
        """
            手机号校验
            :param phone: 手机号
            :return: True/None
        """
        ret = re.match('^1[3-9][0-9]{9}$', self.telephone)
        if ret:
            return True
        return

    def __check_tpl(self):
        tpl = self.tpl
        # print('tpl:', tpl)
        tpl_id = settings.TENCENT_SMS_TEMPLATES.get(tpl)
        if tpl_id:
            # print('tpl_id', tpl_id)
            self.tpl_id = tpl_id
            return True
        return

    def __set_code(self):
        """
        生成验证码存放redis
        :param phone: 手机号
        :return:
        """
        # 生成code
        code = self.code[0]
        # print(code)
        # 保存redis
        conn = get_redis_connection('sms_code')
        pipe = conn.pipeline()  # 创建管道
        pipe.multi()  # 开启批量操作  (事务,)
        #  # 后端倒计时校验 查看redis是否有,有抛异常
        init_code = conn.get('init_code_%s' % self.telephone)
        if init_code:
            return
            # 保存正常验证码
        pipe.set('sms_code_%s' % self.telephone, code, ex=60 * 60 * 24 * 14)
        # 保存倒计时码
        pipe.set('init_code_%s' % self.telephone, code, ex=60)
        pipe.execute()  # 批量执行了
        return code


import random

code = str(random.randrange(1000, 9999))
print(code)
t_sms = TencentSmsCode(telephone='1223334444', code=[code], tpl='login')

 settings.py

# redis
# 上面是django项目settings中的其他配置....
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://106.14.42.253:3306",  # 安装redis的主机的 IP 和 端口
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "CONNECTION_POOL_KWARGS": {
                "max_connections": 1000,
                "encoding": 'utf-8'
            },
            "PASSWORD": "foobared"  # redis密码
        }
    },
    # 提供存储短信验证码
    "sms_code": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://106.14.42.253:3306/2",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "CONNECTION_POOL_KWARGS": {
                "max_connections": 1000,
                "encoding": 'utf-8'
            },
            "PASSWORD": "foobared"  # redis密码
        }
    },
}

# ############################# 腾讯云短信配置 ##########################
TENCENT_SECRET_ID = "AKIDbz7yZyxxxxxxxUO1MQDjzxf5E6h1"  # 密钥id
TENCENT_SECRET_KEY = "4rMbZGgxxxxxxxz5ukJbcMp1vYv0o"  # 密钥key
TENCENT_CITY = "ap-guangzhou"  # 地域,默认即可,
TENCENT_APP_ID = "14xxxxx1766"  # 应用id,v2要应用id/key,v3新增了密钥
TENCENT_SIGN = "python后端接口开发"  # 签名的模版名称
# 短信模板
TENCENT_SMS_TEMPLATES = {
    # 单个参数
    'register': "993292",
    'login': "993155"
}

异步调用配置(需要安装django-redis)

安装

pip install redis==3.4.1 -i https://pypi.douban.com/simple/
pip install celery==4.4.2 -i https://pypi.douban.com/simple/

目录结构

auc_celery(文件夹,一般放在根目录下)
    sms(包)
        __init__.py
        task.py
    __init__.py
    config.py
    main.py

main.py

from celery import Celery

# 创建celery实例对象
app = Celery("auction")  # celery对象可以创建多个,所以我们最好给我们当前的celery应用起个名字,比如叫做dbj

# 把celery和django进行组合,需要识别和加载django的配置文件
import os

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'auction_api.settings')
# 如果只是使用了logging日志功能的话可以不写以下两句,因为logging是python提供的模块,但是将来可能使用celery来执行其他的django任务,所以我们先写上
import django

django.setup()

# 通过app对象加载配置
app.config_from_object("auc_celery.config")

# 加载任务
# 参数必须必须是一个列表,里面的每一个任务都是任务的路径名称
# app.autodiscover_tasks(["任务1","任务2"])
app.autodiscover_tasks(["auc_celery.sms", ])

config.py

# 配置文件
# 1. 有redis有密码
# 任务队列的链接地址(变量名必须叫这个)
broker_url = 'redis://:foobared@106.14.42.253:3306/14'
# 结果队列的链接地址(变量名必须叫这个)
result_backend = 'redis://:foobared@106.14.42.253:3306/15'

# 2. redis无密码写法
# 任务队列的链接地址(变量名必须叫这个)
# broker_url = 'redis://127.0.0.1:6379/14'
# 结果队列的链接地址(变量名必须叫这个)
# result_backend = 'redis://127.0.0.1:6379/15'

task.py

# celery的任务必须写在tasks.py的文件中,别的文件名称不识别!!!
from auc_celery.main import app

from utils.common.tencent_sms import TencentSmsCode


@app.task(name="send_sms")  # name表示设置任务的名称,如果不填写,则默认使用函数名(路径)做为任务名
def send_sms(telephone, code, tpl):
    t_sms = TencentSmsCode(telephone, code, tpl)
    t_sms.sms_check()
    return 'ok'

启动celery

celery -A cat_celery.main worker -l info -P eventlet --logfile=D:/pythonProject/cat/logs/celery.log

settings.py

# redis
# 上面是django项目settings中的其他配置....
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://106.14.42.253:3306",  # 安装redis的主机的 IP 和 端口
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "CONNECTION_POOL_KWARGS": {
                "max_connections": 1000,
                "encoding": 'utf-8'
            },
            "PASSWORD": "foobared"  # redis密码
        }
    },
    # 提供存储短信验证码
    "sms_code": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://106.14.42.253:3306/2",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "CONNECTION_POOL_KWARGS": {
                "max_connections": 1000,
                "encoding": 'utf-8'
            },
            "PASSWORD": "foobared"  # redis密码
        }
    },
}

# ############################# 腾讯云短信配置 ##########################
TENCENT_SECRET_ID = "AKIDbz7yZyxxxxxxxUO1MQDjzxf5E6h1"  # 密钥id
TENCENT_SECRET_KEY = "4rMbZGgxxxxxxxz5ukJbcMp1vYv0o"  # 密钥key
TENCENT_CITY = "ap-guangzhou"  # 地域,默认即可,
TENCENT_APP_ID = "14xxxxx1766"  # 应用id,v2要应用id/key,v3新增了密钥
TENCENT_SIGN = "python后端接口开发"  # 签名的模版名称
# 短信模板
TENCENT_SMS_TEMPLATES = {
    # 单个参数
    'register': "993292",
    'login': "993155"
}

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骑猪去兜风z1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值