在做自动化运维平台的时候免不了要做用户认证这块的功能,一般采取的是手机号验证码登录方式会比较多,今天我们来测试下用腾讯云做短信测试功能


一,首先我们在微信上申请一个订阅号

访问:微信公众平台 (qq.com)

腾讯云sms测试_验证码

点击立即注册,然后点击订阅号

腾讯云sms测试_公众号_02

腾讯云sms测试_验签_03

填写信息


二,完成注册后,我们登录腾讯云控制台

创建应用

应用列表 - 应用管理 - 短信 - 控制台 (tencent.com)

腾讯云sms测试_腾讯云_04

我们把 appid和key拿到后面发短信会用到


三,创建签名

签名管理 - 国内短信 - 短信 - 控制台 (tencent.com)

国内短信这块我们创建签名

腾讯云sms测试_sms_05


腾讯云sms测试_公众号_06

填写信息,完成后等待审核,一般是2到3个小时就审核完成后,如果想快点审核可以找腾讯云客服提交工单


四,创建短信模板

腾讯云sms测试_公众号_07

完成后等待审核,将ID下面的模板id拿到,后面我们会用到


五,购买下零元购资源包

云产品免费体验馆_云产品免费试用_个人云产品试用-腾讯云 (tencent.com)

腾讯云sms测试_腾讯云_08


六,完成上面步骤后我们就可以开始调用短信发送测试了,一般可以通过api或云商的sdk去调用,什么是api调用,一般是向一个api域名发送请求并按照文档带上相应参数请求,而sdk一般是云商对api请求的一个封装,我们一般直接拿云商的sdk调用就ok了

from qcloudsms_py import SmsMultiSender, SmsSingleSender
from qcloudsms_py.httpclient import HTTPError

from django.conf import settings


def send_sms_single(phone_num, template_id, template_param_list):
    """
    单条发送短信
    :param phone_num: 手机号码
    :param template_id: 腾讯云短信模板ID
    :param template_param_list: 短信模板所需参数列表, 例如: [验证码: {1}, 描述: {2}],则传递参数[888, 666]按顺序去格式化模板
    :return:
    """
    appid = settings.TENCENT_SMS_APP_ID  # 自己应用ID
    appkey = settings.TENCENT_SMS_APP_KEY  # 自己应用key
    sms_sign = settings.TENCENT_SMS_SIGN  # 自己腾讯云创建签名时填写的签名内容(使用公众号的话这个值一般是公众号全称或简称)
    sender = SmsSingleSender(appid, appkey)
    try:
        response = sender.send_with_param(86, phone_num, template_id, template_param_list, sign=sms_sign)
    except HTTPError as e:
        response = {'result': 1000, 'errmsg': "网络异常发送失败"}
    return response


def send_sms_multi(phone_num_list, template_id, template_param_list):
    """
    批量发送短信
    :param phone_num_list: 手机号码列表
    :param template_id: 腾讯云短信模板ID
    :param template_param_list: 短信模板所需参数列表, 例如: [验证码: {1}, 描述: {2}],则传递参数[888, 666]按顺序去格式化模板
    :return:
    """
    appid = settings.TENCENT_SMS_APP_ID  # 自己应用ID
    appkey = settings.TENCENT_SMS_APP_KEY  # 自己应用key
    sms_sign = settings.TENCENT_SMS_SIGN  # 自己腾讯云创建签名时填写的签名内容(使用公众号的话这个值一般是公众号全称或简称)
    sender = SmsMultiSender(appid, appkey)
    try:
        response = sender.send_with_param(86, phone_num_list, template_id, template_param_list, sign=sms_sign)
    except HTTPError as e:
        response = {'result': 1000, 'errmsg': "网络异常发送失败"}
    return response


七,上面是短信调用原始方法,当我们需要将自己的系统对外的话,那么短信验证调用肯定也是要对外的,那么这就涉及到接口的安全问题,包括接口限流,防刷,白名单,黑名单,签名验证...,今天做下这个签名验证的演示

写一个路由视图函数

import hashlib
import json

from django.http import JsonResponse

from utils.tencent.sms import send_sms_single
from django.views.decorators.csrf import csrf_exempt


# Create your views here.

@csrf_exempt    # 禁用csrf检查,这里为了方便测试调用了,生产环境下慎用
def send_sms(request):
    """发送短信
    """
    template_id = request.POST.get('template_id')  # 短信模板id
    tpl_params = request.POST.get('tpl_params')  # 短信模板所需参数,我这里用的是短信验证码模板只接收一个参数code验证码
    phones = request.POST.get('phones')  # 将短信发送到目的手机号码
    sign = request.POST.get('sign')  # 签名验证信息,由请求方按照我方服务方给的token和机密方法生成出来,发送给我们服务方
    # 验证签名
    token = 'xxxxxxx'  # 我方的token,可以将此配置项放到settings中

    data = {'template_id': template_id, 'tpl_params': tpl_params, 'phones': phones}
    sdata = sorted(data.items())
    s_list = ['%s=%s' % (s[0], s[1]) for s in sdata]
    nstr = '&'.join(s_list)

    # 计算签名
    m = hashlib.md5()
    m.update((nstr + token).encode())
    calculated_sign = m.hexdigest()
    print(calculated_sign)
    if calculated_sign != sign:
        return JsonResponse({'success': False, 'msg': '无效签名'})

    tpl_params_int = (json.loads(tpl_params)['code'])  # 获取code验证码后转列表,方便后面调用短信发送原始函数
    res = send_sms_single(phones, template_id, [tpl_params_int, ])
    print(res)
    if res['result'] == 0:
        return JsonResponse({'success': True, 'msg': '短信发送成功'})
    else:
        return JsonResponse({'success': False, 'msg': res['msg']})


八,通过apihost进行测试

腾讯云sms测试_sms_09

腾讯云sms测试_公众号_10