Exemple #1
0
def get_areas():
    """获取城区信息:
    1.查询出所有城区信息
    2.响应数据
    """
    # 1.查询所有城区信息
    try:
        resp_json = redis_conn.get("area_info")
    except Exception as e:
        current_app.logger.error(e)
    else:
        if resp_json:
            current_app.logger.info("hit redis area_info")
            return resp_json.decode(), 200, {"Content-Type": "application/json"}

    try:
        areas = Area.query.all()
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(re_code=RET.DBERR, msg='查询城区信息失败')

    if not areas:
        return jsonify(re_code=RET.NODATA, msg='暂无城区')

    areas = [area.to_dict() for area in areas]

    resp_dict = dict(re_code=RET.OK, msg='查询城区成功', areas=areas)
    resp_json = json.dumps(resp_dict)

    try:
        redis_conn.set("area_info", resp_json, constants.AREA_INFO_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)

    return resp_json, 200, {"Content-Type": "application/json"}
Exemple #2
0
def get_area_info():
    """获取城区信息"""
    try:
        # 1.先尝试从redis中读取数据
        area_info = redis_conn.get("area_info")
    except Exception as e:
        current_app.logger.error(e)
    else:
        if area_info:
            # redis有缓存数据
            current_app.logger.info("hit redis area_info")
            # Content-Type默认是text/html
            return area_info, 200, {"Content-Type": "application/json"}

    try:
        # 2.redis没有数据再去查询数据库
        area_li = Area.query.all()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库异常")

    areas = []
    # 将对象转换为字典
    for area in area_li:
        areas.append(area.to_dict())
    area_info = json.dumps(dict(areas))

    try:
        # 3.将mysql查询数据保存到redis中
        redis_conn.setex("area_info", constants.AREA_INFO_REDIS_CACHE_EXPIRES,
                         area_info)
    except Exception as e:
        current_app.logger.error(e)

    return area_info, 200, {"Content-Type": "application/json"}
Exemple #3
0
def get_areas():
    """
    获取地区地址
    :return: 返回地址信息
    """
    # 尝试从缓存里获取数据,如果没有从读数据库获取
    try:
        areas_dict = redis_conn.get('areas_info') # string
    except Exception as e:
        current_app.logger.error(e)


    if areas_dict:
        areas_dict = eval(areas_dict) # string --> dict
    else:
        try:
            all_areas = Area.query.all()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DATAERR,errmsg=u'数据库错误')

        areas_dict = {}
        for area in all_areas:
            areas_dict[area.id] = area.name
        # 将数据缓存到redis
        try:
            redis_conn.setex('areas_info',3600,areas_dict)
        except Exception as e:
            current_app.logger.error(e)

    return jsonify(errno=RET.OK,data=areas_dict)
Exemple #4
0
def login():
    """
    登录
    请求参数:手机号、密码
    参数格式:json
    :return:
    """

    # 接收参数
    req_dict = request.get_json()
    mobile = req_dict.get('mobile')
    password = req_dict.get('password')

    # 校验参数完整性
    if not all([mobile, password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')

    # 判断手机号格式
    if not re.match(r"1[34578]\d{9}", mobile):
        return jsonify(errno=RET.PARAMERR, errmsg="手机号格式错误")

    # 判断错误次数是否超过限制
    user_ip = request.remote_addr  # 用户的ip地址
    try:
        # redis记录: "access_nums_请求的ip": "次数"
        access_nums = redis_conn.get("access_num_%s" % user_ip)
    except Exception as e:
        current_app.logger.error(e)
    else:
        if access_nums and int(access_nums) >= constants.LOGIN_ERROR_MAX_TIMES:
            return jsonify(errno=RET.REQERR, errmsg="错误次数过多,请稍后重试")

    # 查询用户信息
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="获取用户信息失败")

    # 密码比对
    if user is None or not user.check_password(password):
        try:
            # 验证失败时记录错误次数:redis的incr方法可以对字符串类型的数字数据进行加一操作,如果数据一开始不存在,则会初始化为1
            redis_conn.incr("access_num_%s" % user_ip)
            # 设置登录错误限制时间
            redis_conn.expire("access_num_%s" % user_ip,
                              constants.LOGIN_ERROR_FORBID_TIME)
        except Exception as e:
            current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg="用户名或密码错误")

    # 保存登录状态到session中
    session["name"] = user.name
    session["mobile"] = user.mobile
    session["user_id"] = user.id

    # 返回结果
    return jsonify(errno=RET.OK, errmsg="登录成功")
Exemple #5
0
def get_hosue_details():
    """ 获取房屋详情信息 """
    # 接收路径参数
    house_id = request.args.get('house_id')
    if not house_id:
        return jsonify(errcode=RET.PARAMERR, errmsg="缺少必须参数, 请检查路径是否正确")

    # 尝试获取访问者的id, 如果获取为空, 将使用默认值'-1'替代
    call_user_id = session.get('user_id', '-1')

    # 尝试从redis中读取缓存数据
    try:
        json_house = redis_conn.get('house_info_{}'.format(house_id))
    except Exception as e:
        current_app.logger.error(e)
    else:
        if json_house is not None:
            return '{{"errcode": "0", "errmsg": "OK", "data": {0}, "call_user_id": {1}}}'.format(json_house.decode(), call_user_id), \
                200, {"Content-Type": "application/json"}

    # 查询数据库
    try:
        house = House.query.filter_by(id=house_id).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errcode=RET.DBERR, errmsg="数据库异常")

    if house is None:
        return jsonify(errcode=RET.NODATA, errmsg="没有查询到数据")

    try:
        # 先将数据转换为字典, 这是在模型中封装的方法
        house_data_dict = house.to_full_dict()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errcode=RET.SERVERERR, errmsg="数据提取失败, 请联系管理员")
    else:
        # 将数据存放到redis中
        json_house = json.dumps(house_data_dict)

    # 获取设置的redis过期时间, 配置文件中
    redis_expires = current_app.config.get('HOME_PAGE_DATA_REDIS_EXPIRES')
    try:
        redis_conn.set('house_info_{}'.format(house_id),
                       json_house,
                       ex=redis_expires)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errcode=RET.DBERR, errmsg="设置缓存异常")

    # return jsonify(errcode=RET.OK, errmsg="OK", data=house.to_full_dict())
    return '{{"errcode": "0", "errmsg": "OK", "data": {0},  "call_user_id": {1}}}'.format(
        json_house, call_user_id), 200, {
            "Content-Type": "application/json"
        }
Exemple #6
0
def register():
    """用户注册接口:
    1.获取参数phone_num 手机号,phonecode 	短信验证码,password 	密码
    2.校验数据
    3.从Redis获取短信验证码,和传来的数据校验,如果正确
    4.新增user对象,
    5.跳转首页,保持登录状态
    :return 返回注册信息{ 're_code':'0','msg':'注册成功'}
    """
    # 1.获取参数phone_num 手机号,phonecode 	短信验证码,password 	密码
    json_dict = request.json
    phone_num = json_dict.get('phone_num')
    phonecode_client = json_dict.get('phonecode')
    password = json_dict.get('password')
    # 2.校验数据
    if not all([phone_num, phonecode_client, password]):
        return jsonify(re_code=RET.PARAMERR, msg='参数不完整')

    # 校验手机号是否正确
    if not re.match(
            r'^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$',
            phone_num):
        return jsonify(re_code=RET.PARAMERR, msg='手机号不正确')

    # 3.从Redis获取短信验证码,和传来的数据校验,如果正确
    try:
        phonecode_server = redis_conn.get('PhoneCode:' + phone_num)
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(re_code=RET.DBERR, msg='查询短信验证码失败')
    if phonecode_server.decode() != phonecode_client:
        return jsonify(re_code=RET.PARAMERR, msg='短信验证码错误')

    # 4.新增user对象,
    user = User()
    user.name = phone_num
    user.phone_num = phone_num
    user.password_hash = password
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.debug(e)
        db.session.rollback()
        return jsonify(re_code=RET.DBERR, msg='注册失败')
    # 5.跳转首页,保持登录状态
    session['user_id'] = user.id
    session['name'] = user.name
    session['phone_num'] = user.phone_num
    # 6.响应结果
    return jsonify(re_code=RET.OK, msg='注册成功')
Exemple #7
0
def get_house_index():
    """ 获取主页幻灯片 """
    # 设置首页获取首页的幻灯片数量
    HOME_PAGE_MAX_IMAGE = 5
    # 尝试从缓存中读取
    try:
        json_houses = redis_conn.get('home_page_data')
    except Exception as e:
        current_app.logger.error(e)

    if json_houses is not None:
        return '{{"errcode": "0", "errmsg": "OK", "data": {}}}'.format(
            json_houses.decode()), 200, {
                "Content-Type": "application/json"
            }
    else:
        # 查询数据库
        try:
            houses = House.query.order_by(
                House.order_count.desc()).limit(HOME_PAGE_MAX_IMAGE).all()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errcode=RET.DBERR, errmsg="查询数据库失败")

        if not houses:
            return jsonify(errcode=RET.NODATA, errmsg="抱歉, 暂时没有查到数据")

        houses_list = []
        # 遍历house表的查询集
        for house in houses:
            # 如果房屋未设置主图片, 则跳过
            if not house.index_image_url:
                continue
            houses_list.append(house.to_basic_dict())

        # 将数据转换为json, 并保存到redis缓存中, 字符串类型
        json_houses = json.dumps(houses_list)
        # 获取redis缓存时间
        home_page_data_redis_expires = current_app.config.get(
            'HOME_PAGE_DATA_REDIS_EXPIRES')
        try:
            redis_conn.set('home_page_data',
                           json_houses,
                           ex=home_page_data_redis_expires)
        except Exception as e:
            current_app.logger.error(e)

        return '{{"errcode": "0", "errmsg": "OK", "data": {}}}'.format(
            json_houses), 200, {
                "Content-Type": "application/json"
            }
Exemple #8
0
def get_house_detail(house_id):
    """
    展示房屋的详细信息
    前端在房屋详情页面展示时,如果浏览页面的用户不是该房屋的房东,则展示预定按钮,否则不展示,
    所以需要后端返回登录用户的user_id
    尝试获取用户登录的信息,若登录,则返回给前端登录用户的user_id,否则返回user_id=-1
    :param house_id: int<house_id>
    :return: json
    """
    user_id = session.get('user_id',0)

    # 检查参数
    if not house_id:
        return jsonify(errno=RET.PARAMERR,errmsg=u'参数错误')

    # 尝试从redis读取缓存
    try:
        cache_data = redis_conn.get('house_detail_%s' %house_id)
    except Exception as e:
        current_app.logger.error(e)
    if cache_data:
        print ('从redis中读取缓存数据')
        response = {'errno': RET.OK, 'errmsg': u'ok', 'data': {'user_id': user_id, 'house_info': eval(cache_data)}}
        return json.dumps(response), 200, {'Content-Type': 'application/json'}

    try:
        house = House.query.get(house_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=u'查询失败')

    if not house:
        return jsonify(errno=RET.DATAEXIST, errmsg=u'房屋不存在')
    # 获取详细信息(dict)
    house_data = house.to_full_dict()
    # json_data = json.dumps(house_data)

    # 设置缓存数据
    try:
        redis_conn.setex('house_detail_%s' %house_id,3600,house_data)
    except Exception as e:
        current_app.logger.error(e)

    response = {'errno':RET.OK,'errmsg':u'ok','data':{'user_id':user_id,'house_info':house_data}}

    return json.dumps(response),200,{'Content-Type':'application/json'}
Exemple #9
0
def register():
    """用户注册接口"""
    # 1.获取参数phone_num 手机号,phonecode 	短信验证码,password 	密码
    phone_num = request.json.get('phone_num')
    phonecode_client = request.json.get('phonecode')
    password = request.json.get('password')
    #2.校验数据
    if not all([phone_num, phonecode_client, password]):
        return jsonify(re_code=RET.PARAMERR, msg='参数不完整')

    # 校验手机号是否正确
    if not re.match(r'1[3456789]\d{9}$', phone_num):
        return jsonify(re_code=RET.PARAMERR, msg='手机号不正确')

    # 3.从Redis获取短信验证码,和传来的数据校验,如果正确
    try:
        phonecode_server = redis_conn.get('PhoneCode:' + phone_num)
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(re_code=RET.DBERR, msg='查询短信验证码失败')
    if phonecode_server != phonecode_client:
        return jsonify(re_code=RET.PARAMERR, msg='短信验证码错误')

    #4.新增user对象,
    user = User()
    user.name = phone_num
    user.phone_num = phone_num
    user.password_hash = password
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.debug(e)
        db.session.rollback()
        return jsonify(re_code=RET.DBERR, msg='注册失败')
    #5.跳转首页,保持登录状态
    session['user_id'] = user.id
    session['name'] = user.name
    session['phone_num'] = user.phone_num
    #6.响应结果
    return jsonify(re_code=RET.OK, msg='注册成功')
Exemple #10
0
def get_area_info():
    """ 获取城区信息 """
    # 尝试从redis中读取数据, 如果读取成功则使用缓存返回给前端, 否则从数据库获取
    try:
        resp_json = redis_conn.get('area_info')
    except Exception as e:
        current_app.logger.error(e)
    else:
        if resp_json is not None:
            # 代表redis中已经具有缓存数据
            current_app.logger.info('hit redis area_info')  # 表示拿到了数据, 记录日志
            return resp_json, 200, {'Content-Type': 'application/json'}

    # 查询数据库读取城区信息
    try:
        area_li = Area.query.all()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errcode=RET.DBERR, errmsg="数据库异常")

    area_dict_li = []
    # 将对象转为字典
    for area in area_li:
        # 得到每行数据的字段, to_dict是在model里封装的方法
        area_dict_li.append(area.to_dict())

    # 将返回的数据转换为json字符串
    resp_dict = dict(errcode=RET.OK, errmsg='ok', data=area_dict_li)
    resp_json = json.dumps(resp_dict)

    # 将数据保存到redis中
    try:
        # 注意这里一定要设置有效期, 否则哪怕数据库的记录更新了, 返回给前端的也是历史记录的缓存
        redis_conn.set(
            'area_info',
            resp_json,
            ex=current_app.config.get('AREA_INFO_REDIS_CACHE_EXPIRES'))
    except Exception as e:
        current_app.logger.error(e)

    return resp_json, 200, {'Content-Type': 'application/json'}
Exemple #11
0
def house_detail(house_id):
    """房屋详情页面:
    1.获取url栏中的house_id
    2.根据house_id获取house详细信息
    3.判断用户是否登录,
    4.响应结果
    """
    # 1.获取url栏中的house_id
    # 2.根据house_id获取house详细信息
    try:
        resp_json = redis_conn.get("house_info_{}".format(house_id))
    except Exception as e:
        current_app.logger.error(e)
    else:
        if resp_json:
            current_app.logger.info("hit redis house_info_{}".format(house_id))
            return resp_json.decode(), 200, {"Content-Type": "application/json"}
    try:
        house = House.query.get(house_id)
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(re_code=RET.DBERR, msg='查询房屋信息失败')

    if not house:
        return jsonify(re_code=RET.NODATA, msg='房屋不存在')
    house = house.to_full_dict()
    # 3. 获取user_id : 当用户登录后访问detail.html,就会有user_id,反之,没有user_id
    login_user_id = session.get('user_id', -1)

    resp_dict = dict(re_code=RET.OK, msg='查询成功', data={'house': house, 'login_user_id': login_user_id})
    resp_json = json.dumps(resp_dict)

    try:
        redis_conn.set("house_info_{}".format(house_id), resp_json, constants.AREA_INFO_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)

    # 4.响应结果
    return resp_json, 200, {"Content-Type": "application/json"}
Exemple #12
0
def get_houses_index():
    """
    获取房屋的index_image_url图片,并展示到主页
    :return: image_urls
    """
    # 尝试从redis获取缓存
    try:
        cache_data = redis_conn.get('index_urls_data')
    except Exception as e:
        current_app.logger.error(e)

    if cache_data:
        print ('从redis读取数据')
        response = {'errno': RET.OK, 'errmsg': 'ok', 'data': {'houses_info': eval(cache_data)}}
        return json.dumps(response), 200, {'Content-Type': 'application/json'}

    try:
        houses = House.query.order_by(House.order_count.desc()).limit(5)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg=u'获取数据失败')

    index_data = []

    for house in houses:
        if not house.index_image_url:
            continue
        index_data.append({'img_url':current_app.config.get('IMAGE_STORAGE_URL') + house.index_image_url,
                           'title':house.title,
                           'house_id':house.id})

    # 设置缓存
    try:
        redis_conn.setex('index_urls_data',3600,index_data)
    except Exception as e:
        current_app.logger.error(e)

    response = {'errno':RET.OK,'errmsg':'ok','data':{'houses_info':index_data}}
    return json.dumps(response),200,{'Content-Type':'application/json'}
Exemple #13
0
def register():
    """ 用户注册

    POST Request :
        需要携带的参数: 手机号, 短信验证码, 密码
        返回数据格式: json

    """
    # 获取请求的json数据, 返回字典
    req_dict = request.get_json()
    mobile = req_dict.get('mobile')
    sms_code = req_dict.get('sms_code')
    password = req_dict.get('password')
    password2 = req_dict.get('password2')

    # 1.效验参数
    if not all([mobile, sms_code, password]):
        return jsonify(errcode=RET.PARAMERR, errmsg='参数不完整')

    if not re.match(r'^1[3456789]\d{9}$', mobile):
        # 表示格式不对
        return jsonify(errcode=RET.PARAMERR, errmsg='手机号格式不正确')

    if password != password2:
        return jsonify(errcode=RET.PARAMERR, errmsg='两次输入的密码不一致')

    # 2. 从redis中取出短信验证码, 判断是是否过期
    try:
        real_sms_code = redis_conn.get('sms_code_{}'.format(mobile)).decode()
    except Exception as e:
        # 记录错误日志
        current_app.logger.error(e)
        return jsonify(errcode=RET.DBERR, errmsg='验证码读取异常')
    else:
        if real_sms_code is None:
            return jsonify(errcode=RET.NODATA, errmsg='短信验证码已过期')

    # 3. 判断用户填写短信验证码的正确性
    if real_sms_code != sms_code:
        return jsonify(errcode=RET.DATAERR, errmsg='短信验证码输入错误')

    # 4. 删除已经使用的短信验证码
    try:
        redis_conn.delete('sms_code_{}'.format(mobile))
    except Exception as e:
        current_app.logger.error(e)

    # 4. 判断用户的手机号是否注册过, 如未注册则保存数据到数据库中
    user = User(name=mobile, mobile=mobile)
    user.password = password
    try:
        # 因为mobile字段是唯一的, 如果用户提交的手机号被注册, 则会抛出异常
        db.session.add(user)
        db.session.commit()
    except IntegrityError as e:
        # 事务回滚
        db.session.rollback()
        # 记录错误日志, 该异常代表手机号出现重复(mobile字段)
        current_app.logger.error(e)
        return jsonify(errcode=RET.DATAEXIST, errmsg='该手机号已经注册')
    except Exception as e:
        # 数据库的其它异常
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errcode=RET.DBERR, errmsg='数据库异常')

    # 5. 保存登录状态到session中
    session['name'] = mobile
    session['mobile'] = mobile
    session['user_id'] = user.id

    # 6. 返回结果
    return jsonify(errcode=RET.OK, errmsg='用户注册成功')
Exemple #14
0
def login():
    """ 用户登录

    POST Request :
        需要携带的参数: 手机号, 密码
        返回数据格式: json

    """
    # 1. 获取参数
    req_dict = request.get_json()
    mobile = req_dict.get('mobile')
    password = req_dict.get('password')

    # 2. 效验参数
    if not all([mobile, password]):
        return jsonify(errcode=RET.PARAMERR, errmsg='参数不完整')

    if not re.match(r'1[3456789]\d{9}', mobile):
        # 表示格式不对
        return jsonify(errcode=RET.PARAMERR, errmsg='手机号格式不正确')

    # 判断用户请求的次数有没有超过限制
    # 获取请求的地址, 和最大的登录错误次数限制
    user_ip = request.remote_addr
    login_error_max_nums = current_app.config.get('LOGIN_ERROR_MAX_NUMS')
    try:
        # 尝试获取用户redis中的请求次数记录
        request_nums = redis_conn.get('request_nums_{}'.format(user_ip))
    except Exception as e:
        current_app.logger.error(e)
    else:
        if request_nums is not None and int(request_nums.decode()) >= login_error_max_nums:
            return jsonify(errcode=RET.IPERR, errmsg='登录次数受限, 请于10分钟后再试')

    # 验证用户密码
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        jsonify(errcode=RET.DBERR, errmsg='获取用户信息失败')

    # 判断用户名和密码
    if user is None or not user.check_password(password):
        # 如果验证失败, 记录错误次数, 返回信息
        try:
            # 该方法会key的值累加1, 如果key不存在则自动创建并设置初始值为0
            redis_conn.incr('request_nums_{}'.format(user_ip))
            # 设置登录错误记录的过期时间为600/S
            redis_conn.expire('request_nums_{}'.format(user_ip), 600)
        except Exception as e:
            current_app.logger.error(e)
        return jsonify(errcode=RET.DATAERR, errmsg='用户名或密码错误')

    # 3. 保存登录状态到session中
    if user.name is None:
        # 如果用户昵称未设置, 则使用手机号
        session['name'] = mobile
    else:
        session['name'] = user.name
        session['mobile'] = mobile
        session['user_id'] = user.id

    # 4. 返回结果
    return jsonify(errcode=RET.OK, errmsg='登录成功')
Exemple #15
0
def send_sms_code():
    """发送手机短信息验证码:
    1.接收参数,手机号,图片验证码,uuid
    2.校验数据
    3.判断图片验证码是否正确,如果正确
    4.发送短信验证码
    """
    # 1.接收参数,手机号,图片验证码,uuid
    json_str=request.data
    json_dict=json.loads(json_str)
    phone_num=json_dict.get('phone_num')
    image_code_client=json_dict.get('image_code')
    uuid=json_dict.get('uuid')
    # 2.校验数据
    if not all([phone_num,image_code_client,uuid]):
        return jsonify(re_code=RET.PARAMERR,msg='参数缺少')

    # 校验手机号是否正确
    if not re.match(r'^0\d{2,3}\d{7,8}$|^1[358]\d{9}$|^147\d{8}$',phone_num):
        return jsonify(re_code=RET.PARAMERR,msg='手机号不正确')

    #判断用户是否已注册
    try:
        user=User.query.filter(User.phone_num == phone_num).first()
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(re_code=RET.DBERR,msg='查询数据库错误')
    #用户存在,提示该账户已被注册
    if user:
        return jsonify(re_code=RET.DATAEXIST,msg='该用户已被注册')
    # 3.判断图片验证码是否正确,如果正确
    try:
        # 从Redis取出值图片验证码
        image_code_server=redis_conn.get('ImageCode:'+uuid)
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(re_code=RET.DBERR,msg='获取服务器图片验证码失败')

    #判断为验证码空或者过期
    if not image_code_server:
        return jsonify(re_code=RET.NODATA,msg='验证码已过期')

    #校验和前端传的验证码是否相等
    if image_code_server.lower()!=image_code_client.lower():
        return jsonify(re_code=RET.DATAERR,msg='验证码输入有误')

    # 4.生成验证码
    sms_code='%06d' % random.randint(0,99999)
    current_app.logger.debug('短信验证码为:'+sms_code)
    # 5.发送短信验证码            验证码         过期时间:容联的时间单位为:分   短信模板1
    # result = CCP().send_sms('15770633066',[sms_code,constants.SMS_CODE_REDIS_EXPIRES/60],'1')
    # if result != 1:
    #     # 短信发送失败
    #     return jsonify(re_code=RET.THIRDERR,msg='发送短信验证码失败')
    # 6.发送成功,验证码存储到Redis
    try:
        redis_conn.set('PhoneCode:'+phone_num,sms_code,constants.SMS_CODE_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(re_code=RET.DBERR,msg='存储短信验证码失败')
    #响应结果
    return jsonify(re_code=RET.OK,msg='验证码发送成功')
Exemple #16
0
def send_sms_code():
    """发送手机短信息验证码:
    1.接收参数,手机号,图片验证码,uuid
    2.校验数据
    3.判断图片验证码是否正确,如果正确
    4.发送短信验证码
    """
    # 接收参数,手机号,图片验证码,uuid
    json_str = request.data
    json_dict = json.loads(json_str)
    phone_num = json_dict.get('phone_num')
    image_code_client = json_dict.get('image_code')
    uuid = json_dict.get('uuid')
    # 校验数据
    if not all([phone_num, image_code_client, uuid]):
        return jsonify(re_code=RET.PARAMERR, msg='参数缺少')

    # 校验手机号是否正确
    if not re.match(
            r'^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$',
            phone_num):
        return jsonify(re_code=RET.PARAMERR, msg='手机号不正确')

    # 判断用户是否已注册
    try:
        user = User.query.filter(User.phone_num == phone_num).first()
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(re_code=RET.DBERR, msg='查询数据库错误')

    # 用户存在,提示该账户已被注册
    if user:
        return jsonify(re_code=RET.DATAEXIST, msg='该用户已被注册')

    # 判断图片验证码是否正确,如果正确
    try:
        # 从Redis取出值图片验证码
        image_code_server = redis_conn.get('ImageCode:' + uuid)
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(re_code=RET.DBERR, msg='获取服务器图片验证码失败')

    # 判断为验证码空或者过期
    if not image_code_server:
        return jsonify(re_code=RET.NODATA, msg='验证码已过期')

    # 校验和前端传的验证码是否相等
    if image_code_server.decode().lower() != image_code_client.lower():
        return jsonify(re_code=RET.DATAERR, msg='验证码输入有误')

    # 4.生成验证码
    sms_code = '%06d' % random.randint(0, 99999)
    current_app.logger.debug('短信验证码为:' + sms_code)
    # 5.发送短信验证码            验证码
    # 后台设置
    # 同一个手机号同一个验证码模板,每30秒只能获取1条
    # 同一个手机号验证码类内容,每小时最多能获取3条
    # 同一个手机号验证码类内容,24小时内最多能获取到10条
    # result = SendSMS().send_sms(phone_num, sms_code)
    # if not result:
    #     # 短信发送失败
    #     return jsonify(re_code=RET.THIRDERR, msg='发送短信验证码失败')
    # 6.发送成功,验证码存储到Redis
    try:
        redis_conn.set('PhoneCode:' + phone_num, sms_code,
                       constants.SMS_CODE_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(re_code=RET.DBERR, msg='存储短信验证码失败')
    # 响应结果
    return jsonify(re_code=RET.OK, msg='验证码发送成功')
Exemple #17
0
def register():
    """
    注册
    请求参数:手机号、短信验证码、密码、确认密码
    参数格式:json
    :return:
    """

    # 接收参数
    req_dict = request.get_json()
    mobile = req_dict.get('mobile')
    sms_code = req_dict.get('sms_code')
    password = req_dict.get('password')
    password2 = req_dict.get('password2')

    # 校验参数完整性
    if not all([mobile, sms_code, password, password2]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不完整')

    # 判断手机号格式
    if not re.match(r"1[34578]\d{9}", mobile):
        return jsonify(errno=RET.PARAMERR, errmsg="手机号格式错误")

    # 判断密码
    if password != password2:
        return jsonify(errno=RET.PARAMERR, errmsg="两次密码不一致")

    # 从redis中取出短信验证码
    try:
        sms_code_redis = redis_conn.get("sms_code_%s" % mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="读取短信验证码异常")

    # 判断短信验证码是否过期
    if sms_code_redis is None:
        return jsonify(errno=RET.NODATA, errmsg="短信验证码失效")

    # 删除redis中的短信验证码,防止重复使用校验
    try:
        redis_conn.delete("sms_code_%s" % mobile)
    except Exception as e:
        current_app.logger.error(e)

    # 判断用户填写短信验证码的正确性
    if sms_code_redis != sms_code:
        return jsonify(errno=RET.DATAERR, errmsg="短信验证码错误")

    # 将新注册用户保存到数据库
    user = User(name=mobile, mobile=mobile)
    # 设置属性
    user.password = password
    try:
        # 添加数据
        db.session.add(user)
        # 提交
        db.session.commit()
    except IntegrityError as e:
        # 数据库操作异常时要回滚
        db.session.rollback()
        # mobile字段出现重复值,表示该手机号已经注册过
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAEXIST, errmsg="手机号已存在")
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库操作异常")

    # 保存登录状态到session中
    session["name"] = mobile
    session["mobile"] = mobile
    session["user_id"] = user.id

    # 返回结果
    return jsonify(errno=RET.OK, errmsg="注册成功")
Exemple #18
0
def get_sms_code(mobile):
    """ 获取短信验证码
    Args:
        mobile: 注册人的手机号

    URL Param:
        image_code_id: 图片验证码id
        image_code   : 图片验证码

    Retruns:
        正常情况: 发送成功的json信息
        错误情况: 异常的json信息

    """
    # 1. 业务逻辑处理
    # 获取短信验证码的过期时间
    sms_code_redis_expire = current_app.config.get('SMS_CODE_REDIS_EXPIRE')
    if sms_code_redis_expire % 60 != 0:
        return jsonify(errcode=RET.PARAMERR, errmsg='短信验证码过期时间不合法, 需为60的整除数')

    # 效验参数是否缺失
    image_code_id = request.args.get('image_code_id')
    image_code = request.args.get('image_code')
    if not all([mobile, image_code_id, image_code]):
        return jsonify(errcode=RET.PARAMERR, errmsg='参数不全')

    # 效验手机号是否合法
    res = re.match(r"^1[3456789]\d{9}$", mobile)
    if res is None:
        return jsonify(errcode=RET.DATAERR, errmsg='非法数据, 不是合法的手机号')

    # 效验图片验证码是否正确, 从redis中取出真实的验证码, 与用户输入的值对比
    try:
        real_image_code = redis_conn.get('image_code_{}'.format(image_code_id))
    except Exception as e:
        # 记录错误日志
        current_app.logger.error(e)
        return jsonify(errcode=RET.DBERR, errmsg='读取Redis数据库异常')

    # 判断图片验证码是否过期
    if real_image_code is None:
        return jsonify(errcode=RET.NODATA, errmsg='图片验证码已失效, 请点击更换重试')

    # 对比验证码
    if real_image_code.decode().lower() != image_code.lower():
        # 表示用户填写错误
        return jsonify(errcode=RET.DATAERR, errmsg='图片验证码错误')

    # 删除已经使用的验证码, 防止对同一个验证码进行多次验证
    try:
        redis_conn.delete('image_code_{}'.format(image_code_id))
    except Exception as e:
        # 记录错误日志, 这里只是一个逻辑操作, 不要提前返回
        current_app.logger.error(e)

    # 判断用户在短时间内是否发送过验证码, 如60s内, 如果有发送记录, 则在规定时间内不允许发送第二次
    try:
        send_sign = redis_conn.get('send_sms_code_{}'.format(mobile))
    except Exception as e:
        # 记录错误日志
        current_app.logger.error(e)
    else:
        if send_sign is not None:
            # 表示用于在短时间内有发送短信的记录, RET.REQERR = "4201"
            return jsonify(errcode=RET.REQERR, errmsg='请求次数受限, 请于60秒后发送')

    # 判断手机号是否已存在, 如果不存在, 则生成短信验证码, 发送短信
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        # 记录错误日志, 这里不能return终止, 因为可能会出现用户信息正确, 但数据库异常的情况, 此时应该让用户继续注册
        current_app.logger.error(e)
    else:
        if user is not None:
            # 表示手机号已存在
            return jsonify(errcode=RET.DATAEXIST, errmsg='该手机号已经注册')

    # 设置短信验证码, 并保存在redis中
    sms_code = '{0:0>6}'.format(random.randint(0, 999999))
    try:
        # 在redis保存字符串数据
        redis_conn.set('sms_code_{}'.format(mobile),
                       sms_code,
                       ex=sms_code_redis_expire)
        # 保存发送短信的手机号记录, 防止用户在短时间内(如60s)执行重复发送短信的操作
        redis_conn.set('send_sms_code_{}'.format(mobile),
                       'yes',
                       ex=current_app.config.get('SEND_SMS_CODE_INTERVAL'))
    except Exception as e:
        # 记录错误日志
        current_app.logger.error(e)
        return jsonify(errcode=RET.DBERR, errmsg='短信验证码保存异常')

    # 保存短信验证码到redis中: 手机号(key): 验证码(value) 字符串类型
    # ccp = CCP()
    # result = ccp.sendTemplateSMS(mobile, [sms_code, str(sms_code_redis_expire / 60)], '1')
    # if result == 0:
    #     # 发送成功
    #     return jsonify(errcode=RET.OK, errmsg='短信发送成功')
    # else:
    #     return jsonify(errcode=RET.THIRDERR, errmsg='短信发送失败, 第三方错误')

    # 使用celery进行异步请求, 发送短信
    send_sms.delay(mobile, [sms_code, str(sms_code_redis_expire / 60)], '1')

    # 因为selery是异步操作的, 它的执行不会对这里产生阻塞, 所以我们设想, 只要发送了, 就代表成功了
    return jsonify(errcode=RET.OK, errmsg='短信发送成功')
Exemple #19
0
def get_sms_code(mobile):
    """
    获取短信验证码
    :param mobile:
    :return:
    """

    # 1.获取参数
    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='参数不完整')

    # 2.校验图片验证码
    try:
        # 从redis中取出图片验证码
        image_code_redis = redis_conn.get('image_code_%s' % image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg='redis连接异常')
    # 判断验证码是否过期
    if image_code_redis is None:
        return jsonify(errno=RET.NODATA, errmsg='验证码失效')
    # 取完就删掉防止用户多次使用同一个验证码
    try:
        redis_conn.delete('image_code_%s' % image_code_id)
    except Exception as e:
        current_app.logger.error(e)
    # 与用户填写的图片验证码比对
    if image_code.lower() != image_code_redis.lower():
        return jsonify(errno=RET.DATAERR, errmsg='验证码输入错误')

    # 3.校验手机号是否已注册
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
    else:
        if user:
            return jsonify(errno=RET.DATAERR, errmsg='手机号已存在')
    # 判断该手机号60秒内是否有过操作
    try:
        flag = redis_conn.get(mobile)
    except Exception as e:
        current_app.logger.error(e)
    else:
        if flag:
            return jsonify(errno=RET.REQERR, errmsg='请求过于频繁,请稍后重试')

    # 4.未注册的话就生成短信验证码并保存
    sms_code = "%06d" % random.randint(0, 999999)
    try:
        # 将验证码保存到redis
        redis_conn.setex('sms_code_%s' % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
        # 同时也保存发送给该手机号的记录,防止用户60s内再次发送发短信请求
        redis_conn.setex(mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
    except Exception as e:
        current_app.logger.eror(e)
        return jsonify(errno=RET.DBERR, errmsg='保存验证码失败')

    # 5.调用接口发送短信
    try:
        ccp = CCP()
        result = ccp.send_template_sms(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="发送失败")