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
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()
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
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
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
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("创建地址数据完成...")
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
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))
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)
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')
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))
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
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)
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"设备设置游戏更新失败!")
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())
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
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
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()
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"登录成功")
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())
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"回调查询订单失败!!!")
# -*- 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)
def run_status(): log.info("server is running...") return "server is runing..."
def index(): log.info("微信心跳....") return request.args.get('echostr')
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
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 初始化完成!!")
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]))