Beispiel #1
0
    def update(device_id):

        if isinstance(device_id, Device):
            device = device_id
        else:
            device = Device.get(device_id)
        if device is None:
            log.error("当前设备不存在,或者参数错误: device_id = {}".format(device_id))
            return False

        if DeviceService.get_update_state(
                device) != DeviceUpdateStatus.UPDATE_FINISH:
            log.info(
                "当前设备游戏更新状态不需要设置: device_id = {} update_state = {}".format(
                    device.id, device.update_state))
            return True

        # 判断是否有游戏需要更新
        if not DeviceGameService.is_device_need_update(device.id):
            log.info("当前游戏都是最新版, 不需要更新: device_id = {}".format(device.id))
            return True

        log.info("当前存在游戏需要更新,通知客户端更新: device_id = {}".format(device.id))
        return DeviceService.set_update_state(device,
                                              DeviceUpdateStatus.UPDATE_WAIT)
def update_game():
    log.info("开始后台更新游戏...")
    if DeviceGameService.update_game_all_by_http():
        log.info("游戏更新成功!")
    else:
        log.error("游戏更新失败!")
    log.info("后台更新游戏完成...")
def update_ticket():
    access_token = cache_client.get(WECHAT_ACCESS_TOKEN_KEY)
    url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={}&type=jsapi'.format(
        access_token)

    try:
        resp = requests.get(url, verify=False, timeout=30)
        if resp.status_code != 200:
            log.error("ticket访问状态码不正确: status_code = {}".format(
                resp.status_code))
            return False

        json_data = json.loads(resp.text)
        errcode = json_data.get('errcode')
        if errcode != 0:
            log.error("更新jsapi_ticket错误码不正确: {}".format(resp.text))
            return False

        ticket = json_data.get('ticket')
        expires_in = json_data.get('expires_in')
        if not isinstance(ticket, basestring) or not isinstance(
                expires_in, int):
            log.error("ticket解析出来的数据类型不正确: {}".format(resp.text))
            return False

        if expires_in <= 0:
            log.error("ticket过期时间不正确: {}".format(expires_in))
            return False

        log.info("成功获取ticket: ticket = {} expires_in = {}".format(
            ticket, expires_in))

        # 设置redis
        cache_client.setex(WECHAT_JSAPI_TICKET_KEY, expires_in, ticket)

        return True
    except Exception as e:
        log.error("访问ticket链接失败:")
        log.exception(e)
    return False
Beispiel #4
0
def get_login_oauth_url():
    state = random.randint(1, 10)
    # log.info(request.args)
    # log.info("name = {}".format(auth_url))
    # login_url = url_for("wechat.menu", name=name, _external=True)

    args = copy.deepcopy(request.args.to_dict())
    log.info("当前鉴权 args = {}".format(args))
    args.update(request.view_args)
    log.info("当前鉴权 view_args args = {}".format(args))
    url = url_for(request.endpoint, _external=True, **args)
    log.info("当前鉴权后回调url为: {}".format(url))
    qs = urlencode({
        'appid': settings.WECHAT_APP_ID,
        'redirect_uri': url,
        'scope': 'snsapi_userinfo',
        'state': state,
    })

    return ParseResult('https',
                       'open.weixin.qq.com',
                       '/connect/oauth2/authorize',
                       '',
                       query=qs,
                       fragment='wechat_redirect').geturl()
Beispiel #5
0
    def get_device_status(device):
        '''
        获取设备使用状态
        :param device: basestring or Device 类型
        :return:
        '''

        if isinstance(device, basestring):
            device_code = device
        elif isinstance(device, Device):
            # 如果传入的是设备信息直接返回设备使用状态即可, 缓存和数据库中的设备信息是保持严格一致的,只要写入则同时写入缓存和数据库
            return device.state
        else:
            log.error("当前参数数据类型不正确: device = {} type = {}".format(
                device, type(device)))
            return None

        # 先判断是否在缓存中
        device_status_key = RedisClient.get_device_status_key(device_code)

        device_status = redis_device_client.get(device_status_key)
        if device_status is not None:
            return device_status

        # 没有从缓存中找到设备状态 则去数据库中找
        device = DeviceService.get_device_by_code(device_code)
        if device is None:
            log.error("当前设备码没有从缓存中找到,也不存在于数据库中: device_code = {}".format(
                device_code))
            return None

        # 存储状态到redis中 状态只保存一天,防止数据被删除 缓存一直存在
        redis_device_client.setex(device_status_key,
                                  DEFAULT_EXPIRED_DEVICE_STATUS, device.state)

        log.info(
            "当前设备状态从数据库中加载, 缓存到redis中: device_code = {}".format(device_code))
        return device.state
Beispiel #6
0
    def send_wechat_template(cls, access_token, template_id, openid, data, url=''):
        post_url = cls.TEMPLATE_URL + access_token
        json_data = {
            "touser": openid,
            "template_id": template_id,
            "data": data
        }
        if url != '':
            json_data['url'] = url

        try:
            result = requests.post(post_url, json=json_data)
            if result.status_code != 200:
                log.error("发送模板消息失败: openid = {} data = {}".format(openid, json.dumps(data, ensure_ascii=False)))
                return False

            log.info("发送模板消息result = {}".format(result.text))
        except Exception as e:
            log.error("发送模板消息失败:")
            log.exception(e)
            return False

        return True
Beispiel #7
0
    def create(name, charge_mode):

        try:
            charge = Charge(name=name, charge_mode=charge_mode)
            db.session.add(charge)
            db.session.commit()

            # 更新redis中最新的费率
            # redis_cache_client.setex(REDIS_NEWEST_CHARGE_MODE, DEFAULT_EXPIRED_CHARGE, json.dumps(charge.to_dict()))

            log.info("存储最新费率成功: name = {} charge_mode = {}".format(
                name, charge_mode))
        except IntegrityError:
            log.error("主键重复: name = {} charge_mode = {}".format(
                name, charge_mode))
            db.session.rollback()
            return None, False
        except Exception as e:
            log.error("未知插入错误: name = {} charge_mode = {}".format(
                name, charge_mode))
            log.exception(e)
            return None, False
        return charge, True
Beispiel #8
0
def gen_address():

    for _ in xrange(40):
        Address.create("广东省", "深圳市", "宝安区", "宝安汽车站{}".format(_), 0)

    Address.create("广东省", "深圳市", "宝安区", "宝安汽车站", 0)
    Address.create("广东省", "深圳市", "宝安区", "白金时代公寓", 0)
    Address.create("广东省", "深圳市", "南山区", "芒果网大厦", 0)
    Address.create("广东省", "深圳市", "南山区", "A8音乐大厦", 0)
    Address.create("广东省", "深圳市", "南山区", "腾讯大厦", 0)
    Address.create("广东省", "深圳市", "南山区", "1111", 0)
    Address.create("广东省", "深圳市", "南山区", "22222", 0)
    Address.create("广东省", "深圳市", "南山区", "33333", 0)
    Address.create("广东省", "深圳市", "南山区", "44444", 0)
    Address.create("广东省", "深圳市", "南山区", "445454", 0)
    Address.create("广东省", "深圳市", "南山区", "fasdf", 0)
    Address.create("广东省", "深圳市", "南山区", "fdas", 0)
    Address.create("广东省", "深圳市", "南山区", "fasdfdsaff", 0)
    Address.create("广东省", "深圳市", "南山区", "fasdfsafsad", 0)
    Address.create("广东省", "深圳市", "南山区", "fdsafadfs", 0)
    Address.create("广东省", "深圳市", "南山区", "fdsafweewf", 0)
    Address.create("广东省", "深圳市", "南山区", "vcxzvzxcv", 0)
    log.info("创建地址数据完成...")
Beispiel #9
0
    def update_device_game(device_id):
        start_time = time.time()
        is_success = True

        while True:
            for game in DeviceGame.query.filter_by(device_id=device_id):
                # game, is_success = DeviceGameService.add(device.id, name, version)
                # if not is_success or game is None:
                #     log.error("游戏更新失败,中断更新: device_id = {}".format(device.id))
                #     break
                game.current_version = game.newest_version
                game.need_update = False
                db.session.add(game)
                log.info(
                    "当前修改版本游戏信息: device_id = {} name = {} current_version = {} newest_version = {}"
                    .format(device_id, game.name, game.current_version,
                            game.newest_version))
            db.session.commit()
            break

        log.info("游戏版本修改耗时: device_id = {} {} s".format(
            device_id,
            time.time() - start_time))
        return is_success
Beispiel #10
0
def get_admin_list():
    if not request.is_json:
        log.warn("参数错误...")
        return fail(HTTP_OK, u"need application/json!!")

    page = request.json.get('page')
    size = request.json.get('size')

    if not isinstance(page, int) or \
            not isinstance(size, int):
        log.warn("请求参数错误: page = {} size = {}".format(page, size))
        return fail(HTTP_OK, u"请求参数错误")

    # 请求参数必须为正数
    if page <= 0 or size <= 0:
        msg = "请求参数错误: page = {} size = {}".format(page, size)
        log.error(msg)
        return fail(HTTP_OK, msg)

    if size > 50:
        log.info("翻页最大数目只支持50个, 当前size超过50 size = {}!".format(size))
        size = 50

    return success(Admin.get_admin_list(page, size))
Beispiel #11
0
    def decorator(*args, **kwargs):
        signature = request.args.get('signature', '')
        timestamp = request.args.get('timestamp', '')
        nonce = request.args.get('nonce', '')

        log.info("微信-signature: {}".format(signature))
        log.info("微信-timestamp: {}".format(timestamp))
        log.info("微信-nonce: {}".format(nonce))

        token = settings.WECHAT_TOKEN

        cal_signature = gen_signature(timestamp, nonce, token)
        if not cal_signature == signature:
            log.warn("微信-%s != %s" % (signature, cal_signature))
            return fail(HTTP_OK, u"签名不一致")

        log.info("微信-签名校验成功: {}".format(cal_signature))
        return func(*args, **kwargs)
Beispiel #12
0
    def redirect_to(action_name):
        # 进入账户中心
        if action_name == 'account':
            log.info("跳转到/account页面...")
            return redirect('#/account')

        # 进入游戏仓
        if action_name == 'playing':
            log.info("跳转到/playing页面...")
            return redirect('#/playing')

        log.info("无法处理请求: action_name = {} 跳转到登录界面".format(action_name))
        return redirect('#/login')
Beispiel #13
0
    def delete_deploy_device_game(device_id):
        log.info("当前需要删除游戏的设备: device_id = {}".format(device_id))
        # 找到游戏列表
        game_list = GameListService.get_game_list()
        for game, version in game_list:
            is_success = DeviceGameService.delete(device_id, game)
            if not is_success:
                log.error("游戏删除失败: device_id = {} game = {}".format(
                    device_id, game))
                continue

            log.info("当前设备游戏删除成功: device_id = {} game = {}".format(
                device_id, game))
        log.info("当前设备游戏删除完成: device_id = {}".format(device_id))
Beispiel #14
0
    def validate_captcha(self, mobile, captcha):
        if not settings.SMS_ENABLED:
            if captcha == settings.SMS_DEBUG_CAPTCHA:
                return True
            log.info("调试模式验证码校验失败: 发送过来的验证码 = {} 需要校验的调试验证码 = {}".format(
                captcha, settings.SMS_DEBUG_CAPTCHA))
            return False

        key = RedisClient.get_captcha_redis_key(mobile)
        value = self.__redis.get(key)
        if value is None:
            log.info("当前手机不存在验证码: {}".format(mobile))
            return False

        if captcha != value:
            log.info("当前手机验证码错误: phone = {} captcha = {} cache = {}".format(
                mobile, captcha, value))
            return False

        # 删除已经验证码完成的验证码
        self.__redis.delete(key)
        log.info("删除手机验证码redis key = {}".format(key))
        return True
Beispiel #15
0
    def online_recharge(user_id, total_fee):
        # 先获得用户缓存的信息
        user_key = RedisClient.get_user_key(user_id)

        # todo 这里需要加锁, 否则扣费下机时会有影响
        lock = DistributeLock(user_key, redis_cache_client)

        try:
            lock.acquire()
            record_key = redis_cache_client.get(user_key)
            if record_key is None:
                log.info("当前用户没有在线 record_key = None, 不需要同步在线数据: user_id = {}".
                         format(user_id))
                return

            charge_str = redis_cache_client.get(record_key)
            if charge_str is None:
                log.info(
                    "当前用户没有在线 charging = None, 不需要同步在线数据: user_id = {}".format(
                        user_id))
                return

            try:
                charge_dict = json.loads(charge_str)
                if charge_dict is None:
                    log.error("解析json数据失败: {}".format(charge_str))
                    return

                balance_account = charge_dict.get('balance_account')
                if not isinstance(balance_account, int):
                    log.error(
                        "balance_account 数据类型不正确: {}".format(balance_account))
                    return

                charge_dict['balance_account'] = balance_account + total_fee
                redis_cache_client.set(record_key, json.dumps(charge_dict))

                log.info(
                    "同步修改redis中用户余额信息成功! user_id = {} account = {}".format(
                        user_id, balance_account + total_fee))
            except Exception as e:
                log.error("解析json数据失败: {}".format(charge_str))
                log.exception(e)
        finally:
            lock.release()
def update_game_thread():
    log.info("开始启动定时更新游戏线程...")
    pre_update_time = DEFAULT_GAME_UPDATE_TIME
    update_job_id = "update_game"

    parse_time(pre_update_time)

    # 启动定时调度器框架
    scheduler = BackgroundScheduler(logger=log, timezone="Asia/Shanghai")
    scheduler.add_job(update_game,
                      trigger="cron",
                      id=update_job_id,
                      **parse_time(pre_update_time))
    scheduler.start()

    SLEEP_TIME = 30
    while True:

        while True:
            try:
                # 获取当前游戏更新时间
                time_str = DeviceGameService.get_game_update_time(cache_client)
                if time_str == pre_update_time:
                    log.info("当前定时更新游戏时间: {}".format(time_str))
                    break

                log.info("当前游戏更新时间发生变更: pre = {} cur = {}".format(
                    pre_update_time, time_str))
                pre_update_time = time_str
                scheduler.reschedule_job(update_job_id,
                                         trigger="cron",
                                         **parse_time(time_str))
            except Exception as e:
                log.error("游戏更新调度周期异常:")
                log.exception(e)
            break

        time.sleep(SLEEP_TIME)
Beispiel #17
0
def device_game_update():
    if not request.is_json:
        log.warn("参数错误...")
        return fail(HTTP_OK, u"need application/json!!")

    device_id = request.json.get('device_id')
    is_all = request.json.get('all')

    if device_id is None and is_all is None:
        log.warn("参数错误...")
        return fail(HTTP_OK, u"参数错误, device_id or all 必须有一个!")

    log.info("当前设备更新参数为: device_id = {} is_all = {}".format(device_id, is_all))
    if is_all:
        if DeviceGameService.update_all():
            log.info("所有设备游戏更新状态设置成功!")
            return success(u"设备游戏更新状态设置成功!")
        return fail(HTTP_OK, u"游戏更新设置失败,请重试!")

    if DeviceGameService.update(device_id):
        log.info("设备游戏更新状态设置成功: device_id = {}".format(device_id))
        return success(u"设备游戏更新状态设置成功!")

    return fail(HTTP_OK, u"设备设置游戏更新失败!")
Beispiel #18
0
def deploy_device():
    if not request.is_json:
        log.warn("参数错误...")
        return fail(HTTP_OK, u"need application/json!!")

    # json = {
    #     'province': 'xxx',
    #     'city': 'xxxx',
    #     'area': 'xxxx',
    #     'location': 'xxx',
    #     'device_code': 'xxxx',
    # }

    province = request.json.get('province', None)
    city = request.json.get('city', None)
    area = request.json.get('area', None)
    location = request.json.get('location', None)
    if province is None or city is None \
            or area is None or location is None \
            or province == '' or city == '' \
            or area == '' or location == '':
        log.warn(
            "地址信息传入错误: province = {} city = {} area = {} location = {}".format(
                province, city, area, location))
        return fail(HTTP_OK, u"地址信息传入错误!")

    # 获得设备编号信息
    device_code = request.json.get('device_code', None)
    if device_code is None:
        log.warn("没有设备编号信息无法部署...")
        return fail(HTTP_OK, u"没有设备编号信息无法部署!")

    charge_id = request.json.get('charge_id', None)
    if charge_id is None:
        log.warn("当前部署没有传入费率模板ID: device_code = {}".format(device_code))
        return fail(HTTP_OK, u"没有传入费率模板ID")

    charge = Charge.get(charge_id)
    if charge is None:
        log.warn("当前费率模板不存在: charge_id = {} device_code = {}".format(
            charge_id, device_code))
        return fail(HTTP_OK, u"当前费率模板不存在!")

    # 先获得地址信息 通过地址四个属性进行查找
    address = Address.find_address(province, city, area, location)
    if address is None:
        # 如果地址信息不存在则创建地址但是设备数要先初始化为0
        address, is_success = Address.create(province,
                                             city,
                                             area,
                                             location,
                                             device_num=0)
        if address is None:
            log.warn(
                "部署设备时地址信息创建失败了: province = {} city = {} area = {} location = {} device_code = {}"
                .format(province, city, area, location, device_code))
            return fail(HTTP_OK, u"新建地址信息失败了!")

    # 先判断设备是否已经存在设备列表中
    device = DeviceService.get_device_by_code(device_code)
    if device is None:
        # 如果没有找到设备信息则新建设备信息
        device, is_success = DeviceService.create(device_code, address.id,
                                                  charge_id)
        if device is None:
            log.warn("新建设备信息失败了!!")
            return fail(HTTP_OK, u"新建设备信息失败了!")
        if not address.add_device_num(1):
            log.warn("新增设备数目存储失败!!")
            return fail(HTTP_OK, u"新增设备数目存储失败!")

        # 部署游戏信息
        DeviceGameService.deploy_device_game(device)

        # 这里添加部署记录然后返回
        deploy, is_success = Deploy.create(device.id, province, city, area,
                                           location)
        if deploy is None:
            log.warn("添加部署记录失败!")
            return fail(HTTP_OK, u"添加部署记录失败!")

        log.info(
            "添加部署记录成功: province = {} city = {} area = {} location = {} device_code = {}"
            .format(province, city, area, location, device_code))
        return success(deploy.to_dict())

    # 添加部署记录 先判断当前部署的位置是否和设备当前所处的位置是一样的
    if device.address_id == address.id:
        log.info(
            "当前设备部署的位置没有发生任何变化,不需要记录: device.id = {} address.id = {}".format(
                device.id, address.id))
        return success(u"当前设备部署位置没有发生任何变化,不需要增加部署记录")

    # 先获得之前部署的位置
    address_old = Address.get(device.address_id)
    if address_old.device_num > 0:
        if not address_old.add_device_num(-1):
            return fail(HTTP_OK, u"减少设备数目存储失败!")

    # 然后更改部署的位置
    device.address_id = address.id
    if not address.add_device_num(1):
        log.warn("新增设备数目存储失败!!")
        return fail(HTTP_OK, u"新增设备数目存储失败!")

    # 增加部署记录
    deploy, is_success = Deploy.create(device.id, province, city, area,
                                       location)
    if deploy is None:
        log.warn("添加部署记录失败!")
        return fail(HTTP_OK, u"添加部署记录失败!")

    log.info(
        "添加部署记录成功: province = {} city = {} area = {} location = {} device_code = {}"
        .format(province, city, area, location, device_code))
    return success(deploy.to_dict())
Beispiel #19
0
    def find_list(cls,
                  province,
                  city,
                  area,
                  start_time,
                  end_time,
                  state,
                  alive,
                  page,
                  size,
                  filters=None,
                  order_by=None):
        # 条件查询
        total = 0
        query = cls.query

        # 增加过滤条件
        if isinstance(filters, list):
            for filter_item in filters:
                query = query.filter(filter_item)

        # 判断是否由deleted字段,去除掉已经删除的数据信息
        if hasattr(cls, 'deleted'):
            query = query.filter(cls.deleted == False)

        # 根据使用状态查询
        if hasattr(cls, 'state') and state is not None:
            query = query.filter(cls.state == state)

        # 根据存活状态查询
        if hasattr(cls, 'alive') and alive is not None:
            query = query.filter(cls.alive == alive)

        # 根据省份查询
        if province is not None and hasattr(cls, 'province'):
            query = query.filter(cls.province == province)
            log.info("当前按省份筛选: province = {}".format(province))

            # 根据城市查询
            if city is not None and hasattr(cls, 'city'):
                query = query.filter(cls.city == city)
                log.info("当前按城市筛选: city = {}".format(city))

                # 在有城市的前提下按区域查询
                if area is not None and hasattr(cls, 'area'):
                    query = query.filter(cls.area == area)
                    log.info("当前按区域筛选: area = {}".format(area))

        # 根据时间查询
        if start_time is not None and end_time is not None:
            query = query.filter(cls.ctime.between(start_time, end_time))
        elif start_time is not None:
            query = query.filter(cls.ctime >= start_time)
        elif end_time is not None:
            query = query.filter(cls.ctime <= end_time)

        # 是否需要排序
        if order_by is not None:
            query = query.order_by(order_by)

        pagination = query.paginate(page=page, per_page=size, error_out=False)

        if pagination is None:
            return total, None

        # 获取数据总数目
        return pagination.total, pagination.items
Beispiel #20
0
    def search_item_list(cls, _user_id=None):
        if not has_request_context():
            log.warn("上下文异常")
            return fail(HTTP_OK, u"服务器未知!")

        if not request.is_json:
            log.warn("参数错误...")
            return fail(HTTP_OK, u"need application/json!!")

        filters = list()
        page = request.json.get('page')
        size = request.json.get('size')
        city = request.json.get('city')
        area = request.json.get('area')
        province = request.json.get('province')
        start_time_str = request.json.get('start_time')
        end_time_str = request.json.get('end_time')
        state = request.json.get('state')
        alive = request.json.get('alive')

        order_by = request.json.get('order_by')

        # 双重判断user_id是否为None
        user_id = request.json.get('user_id')
        if user_id is not None:
            filters.append(text("user_id={}".format(user_id)))
        elif _user_id is not None:
            filters.append(text("user_id={}".format(_user_id)))

        device_id = request.json.get('device_id')
        if device_id is not None:
            filters.append(text("device_id={}".format(device_id)))

        # 如果存在状态信息,但是状态错误,则返回错误
        if hasattr(cls, 'state') and state is not None:
            if hasattr(cls,
                       'STATUS_VALUES') and state not in cls.STATUS_VALUES:
                return fail(HTTP_OK, u'状态信息错误!')

        # 判断是否有检测设备状态
        if hasattr(cls, 'alive') and alive is not None:
            if hasattr(cls, 'ALIVE_VALUES') and alive not in cls.ALIVE_VALUES:
                return fail(HTTP_OK, u'存活状态信息错误!')

        if isinstance(start_time_str, basestring) and isinstance(
                end_time_str, basestring):
            if end_time_str < start_time_str:
                return fail(
                    HTTP_OK, u"时间区间错误: start_time = {} > end_time = {}".format(
                        start_time_str, end_time_str))

        try:
            # 转换为 datetime 类型
            start_time = None
            if isinstance(start_time_str, basestring):
                start_time = datetime.strptime(start_time_str,
                                               '%Y-%m-%d %H:%M:%S')
                log.info("转换后时间: start_time = {} type = {}".format(
                    start_time, type(start_time)))
            else:
                log.info("start_time 不是字符串: {}".format(start_time_str))

            end_time = None
            if isinstance(end_time_str, basestring):
                end_time = datetime.strptime(end_time_str, '%Y-%m-%d %H:%M:%S')
                log.info("转换后时间: end_time = {} type = {}".format(
                    end_time, type(end_time)))
            else:
                log.info("end_time 不是字符串: {}".format(end_time_str))
        except Exception as e:
            log.error("时间格式转换错误: start_time_str = {} end_time_str = {}".format(
                start_time_str, end_time_str))
            log.exception(e)
            return fail(HTTP_OK, u"时间格式转换错误!")

        if not isinstance(page, int) or \
                not isinstance(size, int):
            log.warn("请求参数错误: page = {} size = {}".format(page, size))
            return fail(HTTP_OK, u"请求参数错误")

            # 请求参数必须为正数
        if page <= 0 or size <= 0:
            msg = "请求参数错误: page = {} size = {}".format(page, size)
            log.error(msg)
            return fail(HTTP_OK, msg)

        if size > 50:
            log.info("翻页最大数目只支持50个, 当前size超过50 size = {}!".format(size))
            size = 50
        total, item_list = cls.find_list(province,
                                         city,
                                         area,
                                         start_time,
                                         end_time,
                                         state,
                                         alive,
                                         page,
                                         size,
                                         filters=filters,
                                         order_by=order_by)
        return total, item_list
Beispiel #21
0
def qr_code_online(device_code):
    # # 当前用户没有登录
    # LOGIN_ERROR_BIND = -1
    # # 当前用户已经被删除
    # LOGIN_ERROR_DELETE = -2
    # # 当前用户被禁止使用
    # LOGIN_ERROR_FORBID = -3
    # # 当前设备不存在
    # LOGIN_ERROR_NOT_FIND = -4
    # # 用户余额不足
    # LOGIN_ERROR_NOT_SUFFICIENT_FUNDS = -5
    # # 上机失败 未知错误
    # LOGIN_ERROR_UNKNOW = -6
    # # 设备已经在使用了
    # LOGIN_ERROR_DEVICE_IN_USEING = -7
    # # 当前用户已经在使用上机了,但是不是当前设备在使用
    # LOGIN_ERROR_USER_IN_USEING = -8
    # # 当前设备不处于空闲状态,不能上机
    # LOGIN_ERROR_DEVICE_NOT_FREE = -9

    scan_from = request.args.get('from')
    # 登录链接
    login_url = url_for("wechat.menu", name="login")
    # 通过微信二维码扫描则需要判断当前用户是否已经关注公众号
    if scan_from != 'playing':
        # # 初始化用户关注信息
        # subscribe, nick_name, head_img_url = 0, '', ''

        openid = session.get('openid', None)
        # 如果不是微信二维码扫描 则跳转到登录界面
        if openid is None:
            log.info("当前扫描登录没有openid,需要跳转到登录界面..")
            return redirect(login_url)

        # 获得用户的关注状态 以及头像和昵称信息
        subscribe, nick_name, head_img_url = get_wechat_user_info(openid)
        # 如果用户没有关注微信号 直接跳转到关注页面
        if subscribe != 1:
            log.info("当前用户没有关注公众号: subscribe = {} openid = {}".format(
                subscribe, openid))
            return redirect(ATTENTION_URL)

        # 如果当前用户已经关注 则直接跳转到 祥基指定的链接 2017-10-13 15:26:00
        url = '#/playing?code={}'.format(device_code)
        log.info("当前用户已经关注了公众号,跳转链接: {}".format(url))
        return redirect(url)

    user_id_cookie = session.get('u_id')
    if user_id_cookie is None:
        log.warn("当前session中没有u_id 信息,需要登录...")
        return fail(HTTP_OK, u'当前用户没有登录', LOGIN_ERROR_BIND)

    user_id = decode_user_id(user_id_cookie)
    if user_id is None:
        log.warn(
            "当前用户信息被篡改,需要重新登录: user_id_cookie = {}".format(user_id_cookie))
        return fail(HTTP_OK, u'当前用户登录信息被篡改, 不能登录', LOGIN_ERROR_BIND)

    # 获得用户信息
    user = get_current_user(user_id)
    if user is None:
        log.warn("当前user_id还未绑定手机号码: user_id = {}".format(user_id))
        return fail(HTTP_OK, u"用户还绑定手机号码登录!", LOGIN_ERROR_BIND)

    # 如果当前用户 被禁用 则不能上机
    if user.deleted:
        log.warn("当前用户已经被删除了,无法上机: user_id = {}".format(user.id))
        return fail(HTTP_OK, u"当前用户已经被删除了,不能上机", LOGIN_ERROR_DELETE)

    # 判断当前用户是否已经被禁用了
    if user.state == 'unused':
        log.warn("当前用户已经被禁用了,无法上机: user_id = {}".format(user.id))
        return fail(HTTP_OK, u"当前用户已经被禁用了,不能上机", LOGIN_ERROR_FORBID)

    # 获得设备信息
    device = DeviceService.get_device_by_code(device_code=device_code)
    if device is None:
        log.warn("当前设备号没有对应的设备信息: device_code = {}".format(device_code))
        return fail(HTTP_OK, u"设备信息异常,设备不存在", LOGIN_ERROR_NOT_FIND)

    # 获得最新费率
    charge_mode = DeviceService.get_charge_mode(device)
    log.info("当前费率: charge_mode = {}".format(charge_mode))

    # 判断用户是否余额充足 如果小于一分钟不能上机
    if user.balance_account < charge_mode:
        log.info(
            "用户余额不足,不能上机: user_id = {} device_id = {} account = {}".format(
                user.id, device.id, user.balance_account))
        return fail(HTTP_OK, u"用户余额不足,不能上机!", LOGIN_ERROR_NOT_SUFFICIENT_FUNDS)

    # 判断是否已经在redis中进行记录
    record_key = RedisClient.get_record_key(user.id, device.id)
    # 获得用户上机key
    user_key = RedisClient.get_user_key(user.id)
    # 获得设备上机key
    device_key = RedisClient.get_device_key(device.id)

    # 判断是否已经登录了
    charging = redis_cache_client.get(record_key)
    if charging is None:

        # 判断当前设备是否已经在使用了
        if redis_cache_client.get(device_key):
            log.warn("当前设备{}已经在被使用,但是用户ID = {}又在申请".format(device.id, user.id))
            return fail(HTTP_OK, u"当前设备已经在使用上机了,但是不是当前用户在使用!",
                        LOGIN_ERROR_DEVICE_IN_USING)

        # 判断当前用户是否已经上机了
        if redis_cache_client.get(user_key):
            log.warn("当前用户{}已经在上机,但是又在申请当前设备ID = {}".format(
                user.id, device.id))
            return fail(HTTP_OK, u"当前用户已经在使用上机了,但是不是当前设备在使用!",
                        LOGIN_ERROR_USER_IN_USING)

        # 判断当前设备是否处于空闲状态 且设备必须处于在线状态
        device_status = DeviceService.get_device_status(device)
        device_alive = DeviceService.get_device_alive_status(device)
        if device_status != DeviceStatus.STATUE_FREE or device_alive != Device.ALIVE_ONLINE:
            log.warn("当前设备不处于空闲状态,不能上机: device_id = {} state = {} alive = {}".
                     format(device.id, device_status, device_alive))
            return fail(HTTP_OK, u"当前设备不处于空闲状态,或者当前设备不在线,不能上机!",
                        LOGIN_ERROR_DEVICE_NOT_FREE)

        # 判断当前设备是否正在更新 或者正在自检,这种状态下不能够登录上机
        current_update_state = DeviceService.get_update_state(device)
        if current_update_state == DeviceUpdateStatus.UPDATE_ING or \
                        current_update_state == DeviceUpdateStatus.UPDATE_CHECK:
            log.info(
                "当前设备正在更新或者自检中,不能登录: device_id = {} current_update_state = {}".
                format(device.id, current_update_state))
            return fail(HTTP_OK, u"当前设备处于自检或者更新中,不能上机!",
                        LOGIN_ERROR_DEVICE_NOT_FREE)

        log.info("用户还未上机可以进行上机: user_id = {} device_id = {}".format(
            user.id, device.id))
        if not WindowsService.do_online(user, device, charge_mode):
            log.warn("上机记录创建失败,上机失败: user_id = {} device_id = {}".format(
                user.id, device.id))
            return fail(HTTP_OK, u"上机异常!!", LOGIN_ERROR_UNKNOW)

    log.info("来自微信端游戏仓界面扫描: user_id = {} device_id = {}".format(
        user.id, device.id))
    return success()
Beispiel #22
0
def maintain_login():
    if not request.is_json:
        log.warn("参数错误...")
        return fail(HTTP_OK, u"need application/json!!")

    device_code = request.json.get('device_code')
    username = request.json.get('username')
    password = request.json.get('password')

    if device_code is None or username is None or password is None:
        log.error(
            "参数错误,无法登录维修账号: device_code = {} username = {} password = {}".
            format(device_code, username, password))
        return fail(HTTP_OK, u"参数错误!!")

    # 判断维修人员用户密码是否正确
    maintain = MaintainService.get_maintain_by_username(username)
    if maintain is None:
        log.error("当前维修人员账号不存在: username = {} password = {}".format(
            username, password))
        return fail(HTTP_OK, u"当前维修人员账号不存在,维修人员无法登录!!")

    # 判断当前用户是否已经被禁用了
    if maintain.state == Maintain.STATUS_FORBID:
        return fail(HTTP_OK, u"当前账户已被禁用,无法登录!!")

    # 判断密码是否正确
    if not maintain.verify_password(password):
        log.error("当前维护人员密码错误: username = {} password = {}".format(
            username, password))
        return fail(HTTP_OK, u"密码错误,维修人员无法登录!!")

    # 判断当前设备信息是否存在
    device = DeviceService.get_device_by_code(device_code)
    if device is None:
        log.error("当前设备号没有设备信息: device_code = {}".format(device_code))
        return fail(HTTP_OK, u"当前设备号没有设备信息!!")

    # 判断当前设备存活状态
    if DeviceService.get_device_alive_status(device) == Device.ALIVE_OFFLINE:
        log.error("当前设备离线,维修人员无法登录: device_code = {}".format(device_code))
        return fail(HTTP_OK, u"当前设备离线,维修人员无法登录!!")

    # 判断当前设备使用状态
    if DeviceService.get_device_status(device) == DeviceStatus.STATUE_BUSY:
        log.error("当前设备用户正在使用,维修人员无法登录: device_code = {}".format(device_code))
        return fail(HTTP_OK, u"当前设备用户正在使用,维修人员无法登录!!")

    # 判断当前维护人员账号能否登录当前地址
    if maintain.address_id != Maintain.ALL_ADDRESS_ID:
        address = Address.get(maintain.address_id)
        if address is None:
            log.error("当前维护人员管理的地址信息不存在,无法登录")
            return fail(HTTP_OK, u"当前维护人员管理的地址信息不存在,无法登录!")
        device_address = device.address.get_full_address()
        maintain_address = address.get_full_address()
        if device_address != maintain_address:
            log.error(
                "当前维护人员管理的地址与设备所在地址不一致,无法登录: maintain_id = {} device_id = {}"
                " device_address = {} maintain_address = {}".format(
                    maintain.id, device.id, device_address, maintain_address))
            return fail(HTTP_OK, u"当前维护人员管理的地址与设备所在地址不一致,无法登录!")

    # 开始登录,先设置设备状态
    if not DeviceService.set_device_status(device,
                                           DeviceStatus.STATUS_MAINTAIN):
        log.error(
            "设备状态切换错误, 维修人员无法登录: device_code = {} username = {} password = {}".
            format(device_code, username, password))
        return fail(HTTP_OK, u"设备状态切换异常, 维修人员无法登录!")

    log.info("维修人员登录设备成功: device_code = {} username = {} password = {}".format(
        device_code, username, password))
    return success(u"登录成功")
Beispiel #23
0
def wechat_login():
    if not request.is_json:
        log.warn("参数错误...")
        return fail(HTTP_OK, u"need application/json!!")

    mobile = request.json.get('mobile', None)
    if mobile is None:
        return fail(HTTP_OK, u'请输入手机号')

    if not isinstance(mobile, basestring):
        return fail(HTTP_OK, u"手机号不合法")

    if len(mobile.strip()) != 11:
        return fail(HTTP_OK, u'手机号不合法')

    code = request.json.get('code', None)
    if code is None:
        return fail(HTTP_OK, u'请输入验证码')

    if not isinstance(code, basestring):
        return fail(HTTP_OK, u"验证码不合法")

    if code.strip() == '':
        return fail(HTTP_OK, u'请输入验证码')

    mobile = mobile.strip()
    code = code.strip()

    # 如果验证码错误
    if not sms_client.validate_captcha(mobile, code):
        return fail(HTTP_OK, u'验证码错误')

    user = UserService.get_user_by_mobile(mobile)

    # 校验完成正确
    if user is not None and user.openid == g.openid:
        u_id = encode_user_id(user.id)
        session['u_id'] = u_id
        log.info("当前绑定的user_id cookie = {}".format(u_id))
        # 去除用户删除标志
        user.deleted = False
        user.save()
        return success(user.to_dict())

    if user is not None and user.openid != g.openid:
        log.info("当前手机号码已绑定其他微信,不能登录: openid = {} mobile = {}".format(
            g.openid, mobile))
        return fail(HTTP_OK, u"当前手机号码已绑定其他微信,不能登录!")

    # 如果能够通过openid找到对应的用户信息则说明当前openid已经绑定过了,不能登录
    user = UserService.get_by_openid(g.openid)
    if user is not None:
        log.info("当前微信已绑定其他手机号,不能登录: openid = {} mobile = {}".format(
            g.openid, mobile))
        return fail(HTTP_OK, u"当前微信已绑定其他手机号,不能登录!")

    # 如果手机号与微信号都没有任何记录,则需要建立账号

    # 获得用户的头像与昵称信息
    subscribe, nick_name, head_img_url = get_wechat_user_info(g.openid)
    log.info("当前用户获取的信息为: openid = {} head = {} nick_name = {}".format(
        g.openid, head_img_url, nick_name))
    user, is_success = UserService.create(mobile,
                                          g.openid,
                                          head_img_url=head_img_url,
                                          nick_name=nick_name)
    if not is_success:
        log.error("创建用户信息异常: openid = {}".format(g.openid))
        return fail(HTTP_OK, u"创建新用户失败!")

    u_id = encode_user_id(user.id)
    session['u_id'] = u_id
    log.info("当前绑定的user_id cookie = {}".format(u_id))
    return success(user.to_dict())
Beispiel #24
0
def notify():
    # log.info("当前回调携带数据为: data = {}".format(request.data))
    data_dict = XMLData.parse(request.data)
    log.info("进入支付响应回调...")
    if data_dict.return_code != 'SUCCESS' or data_dict.result_code != 'SUCCESS':
        log.warn("支付失败: {}".format(request.data))
        return fail(HTTP_OK, '支付失败!')

    log.info("开始进行支付记录存储!!")

    # 微信订单
    transaction_id = data_dict.transaction_id

    # 用户ID信息
    user_id = int(data_dict.attach)

    try:
        # 如果充值记录已经存在则不再存储
        if RechargeService.find_by_transaction_id(transaction_id) is not None:
            log.info("当前记录已经存储过,不在进行存储: {}".format(transaction_id))
            return success()

        log.info("当前通过微信查询订单: user_id = {} transaction_id = {}".format(
            user_id, transaction_id))
        result = wx_pay.order_query(transaction_id=transaction_id)
        if result is None:
            log.warn("查询订单失败: {}".format(transaction_id))
            return fail(HTTP_OK, '查询订单失败!')

        if result.get('return_code') != 'SUCCESS' or \
                        result.get('result_code') != 'SUCCESS':
            log.warn("查询订单返回结果失败: {}".format(transaction_id))
            return fail(HTTP_OK, '查询订单失败!')

        if 'total_fee' not in result:
            log.warn('订单返回信息, total_fee not in result: {}'.format(
                json.dumps(result, ensure_ascii=False)))
            return fail(HTTP_OK, '解析订单信息失败!')

        # 订单金额
        total_fee = result.get('total_fee', 0)
        # 如果不为数值 则改为数值
        if isinstance(total_fee, basestring):
            total_fee = int(total_fee)
        if total_fee < 0:
            total_fee = 0

        if 'time_end' not in result:
            log.warn('订单返回信息, time_end not in result: {}'.format(
                json.dumps(result, ensure_ascii=False)))
            return fail(HTTP_OK, '解析订单信息失败!')

        # 支付时间
        pay_time = datetime.strptime(result.get('time_end', "20170926111841"),
                                     '%Y%m%d%H%M%S')

        log.info("当前充值记录还未存在,存储记录: transaction_id = {}".format(transaction_id))
        # 创建充值记录
        obj, is_success = RechargeService.create(user_id, total_fee,
                                                 transaction_id, pay_time)
        if not is_success:
            log.error("存储充值记录失败: user_id = {} transaction_id = {}".format(
                user_id, transaction_id))
            return fail(HTTP_OK, u"充值记录存储失败!")

        # 如果当前用户正在上线则需要更新redis中的总余额数据
        RechargeService.online_recharge(user_id, total_fee)

        return success()
    except Exception as e:
        log.error("查询订单失败:")
        log.exception(e)

    return fail(HTTP_OK, u"回调查询订单失败!!!")
Beispiel #25
0
# -*- coding: utf-8 -*-
from flask import request
from werkzeug.contrib.fixers import ProxyFix

from app import create_app
from exts.common import log
from tools.wechat_api import check_signature

log.info("开始进入初始化流程..")
application = create_app('share-bar-server')

application.wsgi_app = ProxyFix(application.wsgi_app)


@application.route('/', methods=['GET'])
@check_signature
def index():
    log.info("微信心跳....")
    return request.args.get('echostr')


@application.route("/test")
def run_status():
    log.info("server is running...")
    return "server is runing..."


if __name__ == "__main__":
    application.run(port=8080)
Beispiel #26
0
def run_status():
    log.info("server is running...")
    return "server is runing..."
Beispiel #27
0
def index():
    log.info("微信心跳....")
    return request.args.get('echostr')
Beispiel #28
0
    def find_list(province,
                  city,
                  area,
                  start_time,
                  end_time,
                  state,
                  alive,
                  page,
                  size,
                  filters=None,
                  order_by=None):
        # 条件查询
        total = 0
        query = Device.query

        # 根据省份查询
        if province is not None:
            query = query.join(Address).filter(Address.province == province)
            log.info("当前按省份筛选: province = {}".format(province))

            # 根据城市查询
            if city is not None:
                query = query.filter(Address.city == city)
                log.info("当前按城市筛选: city = {}".format(city))

                # 在有城市的前提下按区域查询
                if area is not None:
                    query = query.filter(Address.area == area)
                    log.info("当前按区域筛选: area = {}".format(area))

        # 增加过滤条件
        if isinstance(filters, list):
            for filter_item in filters:
                query = query.filter(filter_item)

        # 根据使用状态查询
        if state is not None:
            query = query.filter(Device.state == state)

        # 根据存活状态查询
        if alive is not None:
            query = query.filter(Device.alive == alive)

        # 根据时间查询
        if start_time is not None and end_time is not None:
            query = query.filter(Device.ctime.between(start_time, end_time))
        elif start_time is not None:
            query = query.filter(Device.ctime >= start_time)
        elif end_time is not None:
            query = query.filter(Device.ctime <= end_time)

        # 是否需要排序
        if order_by is not None:
            query = query.order_by(order_by)

        pagination = query.paginate(page=page, per_page=size, error_out=False)

        if pagination is None:
            return total, None

        # 获取数据总数目
        return pagination.total, pagination.items
Beispiel #29
0
 def __init__(self, db=0):
     self._client = redis.StrictRedis.from_url(
         settings.REDIS_URI,
         db=db,
         max_connections=settings.REDIS_MAX_CONNECTIONS)
     log.info("redis 初始化完成!!")
Beispiel #30
0
    def search_list():

        if not has_request_context():
            log.warn("上下文异常")
            return fail(HTTP_OK, u"服务器未知!")

        if not request.is_json:
            log.warn("参数错误...")
            return fail(HTTP_OK, u"need application/json!!")

        filters = list()
        page = request.json.get('page')
        size = request.json.get('size')
        province = request.json.get('province')
        city = request.json.get('city')
        area = request.json.get('area')
        start_time_str = request.json.get('start_time')
        end_time_str = request.json.get('end_time')
        state = request.json.get('state')
        alive = request.json.get('alive')

        order_by = request.json.get('order_by')

        # 如果存在状态信息,但是状态错误,则返回错误
        if state is not None:
            if state not in Device.STATUS_VALUES:
                return fail(HTTP_OK, u'状态信息错误!')

        # 判断是否有检测设备状态
        if alive is not None:
            if alive not in Device.ALIVE_VALUES:
                return fail(HTTP_OK, u'存活状态信息错误!')

        if isinstance(start_time_str, basestring) and isinstance(
                end_time_str, basestring):
            if end_time_str < start_time_str:
                return fail(
                    HTTP_OK, u"时间区间错误: start_time = {} > end_time = {}".format(
                        start_time_str, end_time_str))

        try:
            # 转换为 datetime 类型
            start_time = None
            if isinstance(start_time_str, basestring):
                start_time = datetime.strptime(start_time_str,
                                               '%Y-%m-%d %H:%M:%S')
                log.info("转换后时间: start_time = {} type = {}".format(
                    start_time, type(start_time)))
            else:
                log.info("start_time 不是字符串: {}".format(start_time_str))

            end_time = None
            if isinstance(end_time_str, basestring):
                end_time = datetime.strptime(end_time_str, '%Y-%m-%d %H:%M:%S')
                log.info("转换后时间: end_time = {} type = {}".format(
                    end_time, type(end_time)))
            else:
                log.info("end_time 不是字符串: {}".format(end_time_str))
        except Exception as e:
            log.error("时间格式转换错误: start_time_str = {} end_time_str = {}".format(
                start_time_str, end_time_str))
            log.exception(e)
            return fail(HTTP_OK, u"时间格式转换错误!")

        if not isinstance(page, int) or \
                not isinstance(size, int):
            log.warn("请求参数错误: page = {} size = {}".format(page, size))
            return fail(HTTP_OK, u"请求参数错误")

            # 请求参数必须为正数
        if page <= 0 or size <= 0:
            msg = "请求参数错误: page = {} size = {}".format(page, size)
            log.error(msg)
            return fail(HTTP_OK, msg)

        if size > 50:
            log.info("翻页最大数目只支持50个, 当前size超过50 size = {}!".format(size))
            size = 50
        total, item_list = DeviceService.find_list(province,
                                                   city,
                                                   area,
                                                   start_time,
                                                   end_time,
                                                   state,
                                                   alive,
                                                   page,
                                                   size,
                                                   filters=filters,
                                                   order_by=order_by)
        if total <= 0 or item_list is None:
            return success(package_result(0, []))
        return success(
            package_result(total, [item.to_dict() for item in item_list]))