本节代码下载地址:https://download.csdn.net/download/geek_xiong/11527723
目录
短信验证码
云通讯的基本配置
云通讯发送短信验证码工具封装与测试
发送短信验证码 后端代码编写
图片、短信验证码测试
短信验证码的前端完善
短信验证码
本文参考文档下载地址:https://download.csdn.net/download/geek_xiong/11527723
本项目基于云通讯实现短信验证码的发送与验证
云通讯的基本配置
下载短信接口包:https://www.yuntongxun.com/doc/ready/demo/1_4_1_2.html
开发文档自行观看。
由于下载的包是基于python2.7写的,但是本项目是用的python3.7,所示下载的文件中需要进行升级,我把改后的文件以及需要的文件打包上传了,可自行下载 https://download.csdn.net/download/geek_xiong/11523100
添加测试号码,最好输入有效手机号,要不怎么接收验证码嘞!
云通讯发送短信验证码工具封装与测试
将yuntongxun包解压后放到ihome目录的libs子目录下,
编写测试文档sms.py,自定义封装发送短信验证码的辅助类
# -*- coding: UTF-8 -*-from ihome.libs.yuntongxun.CCPRestSDK import REST
import configparser#主帐号
accountSid = '8a216dxxxxxxxxxxxxxx4d82f0dd6'#主帐号Token
accountToken = '154xxxxxxxxxxxxxxxxxxx325cc52a3f'#应用Id
appId = '8a216dxxxxxxxxxxxxxxxxxxxxxxxx8004d8850ddd'#请求地址,格式如下,不需要写http://
serverIP = 'app.cloopen.com'#请求端口
serverPort = '8883'#REST版本号
softVersion='2013-12-26'# 发送模板短信# @param to 手机号码# @param datas 内容数据 格式为数组 例如:{'12','34'},如不需替换请填 ''# @param $tempId 模板Idclass CCP(object):"""自己封装的发送短信的辅助类"""# 用来保存对象的类属性instance = Nonedef __new__(cls):# 判断CCP类有没有创建好的对象,如果没有,创建一个对象,如果有,直接返回if cls.instance is None:obj = super(CCP, cls).__new__(cls)# 初始化REST yuntongxunobj.rest = REST(serverIP, serverPort, softVersion)obj.rest.setAccount(accountSid, accountToken)obj.rest.setAppId(appId)cls.instance = objreturn cls.instancedef sendTemplateSMS(self, to, datas, temp_Id):result = self.rest.sendTemplateSMS(to,datas,temp_Id)# for k,v in result.items():## if k == 'templateSMS':# for k, s in v.items():# print('%s:%s' % (k, s))# else:# print('%s:%s' % (k, v))# statusCode: 000000# smsMessageSid: 54987ccdd2bbxxxxxxxxxxxx7de7ac93aa# dateCreated: 20190811193012status_code = result.get('statusCode')if status_code == '000000':return 0 # 000000表示发送成功return -1 # 发送失败if __name__ == '__main__':ccp = CCP()ret = ccp.sendTemplateSMS('1513xxxxxxx', ["123", "456"], 1)print(ret)# sendTemplateSMS(手机号码,内容数据,模板Id)
运行一下这个测试文件,如果填写的手机收到验证码,并且终端上打印 0 就表示成功了
发送短信验证码 后端代码编写
url:127.0.0.1:5000/api/vi.0/sms_codes/<mobile>?image_code=xxx&image_code_id=xxx
需要传的参数为手机号mobile,image_code和image_code_id可以在request中直接获取
大致流程:
- 获取参数:获取image_code与image_code_id
- 检验参数:验证这两个数据是否完整
- 业务逻辑处理
- 从redis中取出image_code_id对应的真实值
- 判断真实值是否过期
- 对比用户输入的验证码与真实值是否相等
- 判断手机号是否已注册
- 生成短信验证码
- 将手机号对应的短信验证码保存到redis中
- 向注册手机号发送短信验证码
- 判断发送是否成功
- 返回值(上述中已经返回)
#!/usr/bin/env python
# -*- coding: utf-8 -*-import randomfrom flask import current_app, jsonify, make_response, requestfrom . import api
from ihome.utils.captcha.captcha import captcha
from ihome import redis_store, constants, db
from ihome.utils.response_code import RET
from ihome.models import User
from ihome.libs.yuntongxun.sms import CCP...# GET 127.0.0.1:5000/sms_codes/<mobile>?image_code=xxx&image_code_id=xxx@api.route("/sms_codes/<re(r'1[34578]\d{9}'):mobile>")
def get_sms_code(mobile):"""获取短信验证码"""# 获取参数image_code = request.args.get('image_code')image_code_id = request.args.get('image_code_id')# 检验参数if not all([image_code, image_code_id]):# 参数不完整return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')# 逻辑处理# 从redis中取出验证码图片的真实值try:real_image_code = redis_store.get('image_code_%s' % image_code_id)except Exception as e:current_app.logger.error(e)return jsonify(errno=RET.DBERR, errmsg='数据库异常')# 判断真实值是否过期,redis中如果过期则返回Noneif real_image_code is None:return jsonify(errno=RET.NODATA, errmsg='验证码失效')# 验证用户填写的验证码与redis中的真实值是否相等if image_code.lower() != real_image_code.lower():return jsonify(errno=RET.DATAERR, errmssg='图片验证码错误')# 判断手机号是否已注册try:user = User.query.filter_by(mobile=mobile).first()except Exception as e:current_app.logger.error(e)else:if user is not None:return jsonify(errno=RET.DATAEXIST, errmsg='手机号已注册')# 生成短信验证码 6 位# import randomsms_code = "%06d" % random.randint(0, 999999) # %06d 表示生成6位整数,不够的前边补0 ,如029541# 保存短信验证码到redis中try:redis_store.setex("sms_code_%s" % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)except Exception as e:current_app.logger.error(e)return jsonify(errno=RET.DBERR, errmsg='短信验证码保存异常')# 发送短信验证码try:# from ihome.libs.yuntongxun.sms import CCPccp = CCP()result = ccp.sendTemplateSMS(mobile, [sms_code, int(constants.SMS_CODE_REDIS_EXPIRES/60)], 1)except Exception as e:current_app.logger.error(e)return jsonify(errno=RET.THIRDERR, errmsg='验证码发送异常')if result == 0:# 发送成功return jsonify(errno=RET.OK, errmsg='发送成功')else:return jsonify(errno=RET.THIRDERR, errmsg='发送失败')
图片、短信验证码测试
启动项目,刷新一下浏览器
打开postman,先测试一个假的数据
请求方式选择GET,填写地址“127.0.0.1:5000/api/v1.0/sms_codes”,点击右边的Params,分别填入key-value,点击Send,观察左下角的body,应该返回的是“图片验证码错误”
返回的和预想的一样,修改验证码image_code的值为正确的,再验证一下。
注意:
- 验证码有效期
- 手机号在云通讯中未注册
验证码失效了,刷新了一下
现在输入正确的image_code与image_code_id(手机号是错误的)
手机号是正确的
短信验证码的前端完善
页面点击 “ 获取验证码 ” 的时候,需要判断手机号和图片验证码是否填写,如果没有填写,给出提醒,按钮恢复状态(或者不变或者取消点击状态),都填写并正确的情况下,发送短信验证码,按钮开始倒计时,并取消点击状态,当倒计时结束时恢复点击状态
function sendSMSCode() {$(".phonecode-a").removeAttr("onclick");var mobile = $("#mobile").val();if (!mobile) {$("#mobile-err span").html("请填写正确的手机号!");$("#mobile-err").show();$(".phonecode-a").attr("onclick", "sendSMSCode();");return;} var imageCode = $("#imagecode").val();if (!imageCode) {$("#image-code-err span").html("请填写验证码!");$("#image-code-err").show();$(".phonecode-a").attr("onclick", "sendSMSCode();");return;}$.get("/api/v1.0/sms_codes/"+mobile, {image_code:imageCode, image_code_id:imageCodeId},function(data){if (0 != data.errno) {$("#image-code-err span").html(data.errmsg); $("#image-code-err").show();if (2 == data.errno || 3 == data.errno) {generateImageCode();}$(".phonecode-a").attr("onclick", "sendSMSCode();");} else {var $time = $(".phonecode-a");var duration = 60;var intervalid = setInterval(function(){$time.html(duration + "秒"); if(duration === 1){clearInterval(intervalid);$time.html('获取验证码'); $(".phonecode-a").attr("onclick", "sendSMSCode();");}duration = duration - 1;}, 1000, 60); }}, 'json');
}
根据评论,已添加sms.py所在图
本节完