Esempio n. 1
0
def get_image_code():
    """
    获取图片验证码
    1.接收请求,获取UUID和上一个uuid
    2.判断数据库保存的uuid是否等于last_uuid等于删除,
    3.生成图片验证码
    4.保存新的uuid,对应的图片文本信息
    :return: josnify 验证码图片
    """
    # 1.接收请求,获取UUID,last_uuid
    uuid=request.args.get('uuid')
    last_uuid=request.args.get('last_uuid')
    if not uuid:
        #缺省参数报403异常
        abort(403)
    # 2.生成图片验证码 名字,文字信息,图片信息
    name, text, image = captcha.generate_captcha()
    current_app.logger.debug('图片验证码信息:'+text)
    # 4.删除上次生成的验证码图片
    try:
        if last_uuid:
            redis_conn.delete('ImageCode:'+last_uuid)
        # 3.保存UUID对应的验证码文字信息,设置时长
        redis_conn.set('ImageCode:' + uuid, text,constants.IMAGE_CODE_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(re_code=RET.DBERR,msg='保存图片验证码失败')
    response=make_response(image)
    response.headers['Content-Type']='image/jpg'
    return response
Esempio n. 2
0
def sava_order_comment(order_id):
    """ 保存订单评论信息

    Request Body Params:
        {"comment": "评论信息"}

    """
    user_id = g.user_id
    # 获取参数
    req_data = request.get_json()
    comment = req_data.get('comment')

    # 检查参数
    if not comment:
        return jsonify(errcode=RET.PARAMERR, errmsg="您没有提交信息")

    try:
        # 需要确保只能评论自己下的订单, 而且处于待评价状态才可以
        order = Order.query.filter(Order.id == order_id,
                                   Order.user_id == user_id,
                                   Order.status == 'WAIT_COMMENT').first()
        house = order.house
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errcode=RET.DBERR, errmsg='无法获取订单数据')
    else:
        if order is None:
            return jsonify(errcode=RET.DBERR, errmsg="操作无效")

    try:
        # 将订单的状态设置为已完成
        order.status = 'COMPLETE'
        # 保存订单的评价信息
        order.comment = comment
        # 将房屋的完成订单数量增加1
        house.order_count += 1
        db.session.add(order)
        db.session.add(house)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errcode=RET.DBERR, errmsg='数据库异常, 提交失败')

    # 因为房屋详情中有订单的评价信息, 为了让最新的评价信息展示在房屋详情中, 所以删除reidis中关于本订单的的房屋信息
    try:
        redis_conn.delete('house_info_{}'.format(order.house_id))
    except Exception as e:
        current_app.logger.error(e)

    return jsonify(errcode=RET.OK, errmsg='OK')
Esempio n. 3
0
def order_comment(order_id):
    """订单评论提交"""
    user_id = g.user_id

    res_data = request.get_json()
    if not res_data:
        return jsonify(errno=RET.PARAMERR, errmsg=u'参数错误')

    comment = res_data.get('comment', '')
    if not comment:
        return jsonify(errno=RET.DATAEXIST, errmsg=u'评价信息不能为空!')

    try:
        order = Order.query.filter(Order.id == order_id,Order.user_id == user_id,\
                                   Order.status == 'WAIT_COMMENT').first()
        house = order.house
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=u'获取数据失败')

    if not order:
        return jsonify(errno=RET.DATAERR, errmsg=u'操作无效数据')

    try:
        # 更改订单状态
        order.status = 'COMPLETE'
        order.comment = comment
        # 房屋的订单数+1
        house.order_count += 1
        db.session.add(order)
        db.session.add(house)
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg=u'操作数据失败')

    # 删除缓存数据
    try:
        cache_data = redis_conn.delete('house_detail_%s' % house.id)
    except Exception as e:
        current_app.logger.error(e)

    return jsonify(errno=RET.OK, errmsg='ok')
Esempio n. 4
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='短信发送成功')
Esempio n. 5
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="注册成功")
Esempio n. 6
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='用户注册成功')
Esempio n. 7
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="发送失败")