短信验证码
云通讯的基本配置
云通讯发送短信验证码工具封装与测试
发送短信验证码 后端代码编写
图片、短信验证码测试
短信验证码的前端完善
本文参考文档下载地址: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 模板Id
class CCP(object):
"""自己封装的发送短信的辅助类"""
# 用来保存对象的类属性
instance = None
def __new__(cls):
# 判断CCP类有没有创建好的对象,如果没有,创建一个对象,如果有,直接返回
if cls.instance is None:
obj = super(CCP, cls).__new__(cls)
# 初始化REST yuntongxun
obj.rest = REST(serverIP, serverPort, softVersion)
obj.rest.setAccount(accountSid, accountToken)
obj.rest.setAppId(appId)
cls.instance = obj
return cls.instance
def 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: 20190811193012
status_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和image_code_id可以在request中直接获取
大致流程:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import random
from flask import current_app, jsonify, make_response, request
from . 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/?image_code=xxx&image_code_id=xxx
@api.route("/sms_codes/")
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中如果过期则返回None
if 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 random
sms_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 CCP
ccp = 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所在图
本节完