def join_phone_number(self): account = ''.join( [d for d in [self.zone.data, self.account.data] if d]) account = '+' + account.strip('+').strip() if not PhoneNumberParser.is_valid_number(account): return None return account
def test_hide_number(self): b = 6 e = -4 s = "+8618975532009" h_s = PhoneNumberParser.hide_number(s) print(s, h_s) self.assertEqual('+86189', h_s[:b]) self.assertEqual('****', h_s[b:e]) self.assertEqual('2009', h_s[e:]) s = "+639166630027" h_s = PhoneNumberParser.hide_number(s) print(s, h_s) self.assertEqual('+63916', h_s[:b]) self.assertEqual('****', h_s[b:e]) self.assertEqual('0027', h_s[e:])
def post(self): """ 用户列表 :return: """ form, error = UserListSelectForm.request_validate() if error: return error.as_response() kwargs = dict() if form.phone_number.data: phone_number = str(form.phone_number.data) if phone_number.find("+") < 0: phone_number = "{}{}".format("+", phone_number) kwargs['account'] = phone_number user_query = User.query.filter_by(**kwargs) if form.start_datetime.data: user_query = user_query.filter( User._create_time >= DateTimeKit.datetime_to_timestamp( form.start_datetime.data)) if form.end_datetime.data: user_query = user_query.filter( User._create_time <= DateTimeKit.datetime_to_timestamp( form.end_datetime.data)) paginate = user_query.paginate(form.page_index.data, form.page_size.data, False) total = paginate.total user_lst = paginate.items uid_lst = [u.id for u in user_lst] uid_merchant = UserBalance.query.filter( UserBalance.id.in_(uid_lst)).all() mer_bl_uid = { uid.id: dict(balance=uid.real_balance, merchant=uid.merchant) for uid in uid_merchant } data = [ dict(user_id=u.id, phone_number=PhoneNumberParser.hide_number(u.account), type='测试用户' if u.is_test_user else "普通用户", source=mer_bl_uid[u.id]['merchant'].name, available_bl=mer_bl_uid[u.id]['balance'], register_datetime=u.str_create_time, state=u.state.name) for u in user_lst ] return UserListResult( bs_data=dict(entries=data, total=total)).as_response()
def get(self): """ 给用户绑定信息 :return: """ if not request.args: return ResponseSuccess( message= "参数规则:?merchant=test&account=861891111&perm=DEPOSIT|BINDCARD" ).as_response() try: merchant = MerchantEnum.from_name(request.args['merchant']) except: return ResponseSuccess(message="请输入正确的商户名称,有效的商户名称包括:%s" % MerchantEnum.get_names()).as_response() try: account = request.args['account'] account = '+' + account.strip('+').strip() if not PhoneNumberParser.is_valid_number(account): raise except: return ResponseSuccess( message="请输入正确的用户手机号码,必须有完整区号,不填+号,如:8613812349999" ).as_response() try: perms = request.args['perm'].split('|') perms = [UserPermissionEnum.from_name(perm) for perm in perms] except: return ResponseSuccess( message="标签权限,有效的权限包括: %s" % UserPermissionEnum.get_name_list()).as_response() user = User.query_user(merchant, account=account) if not user: return ResponseSuccess(message="手机号码未注册").as_response() User.update_user_permission(merchant, perms, account=account) user = User.query_user(merchant, account=account) bs_data = dict( account=account, uid=user.uid, perms=user.permission_names, ) return ResponseSuccess(bs_data=bs_data).as_response()
def get(self): """ 给用户绑定信息 :return: """ if not request.args: return ResponseSuccess( message="参数规则:?merchant=test&account=861891111&flag=VIP" ).as_response() try: merchant = MerchantEnum.from_name(request.args['merchant']) except: return ResponseSuccess(message="请输入正确的商户名称,有效的商户名称包括:%s" % MerchantEnum.get_names()).as_response() try: account = request.args['account'] account = '+' + account.strip('+').strip() if not PhoneNumberParser.is_valid_number(account): raise except: return ResponseSuccess( message="请输入正确的用户手机号码,必须有完整区号,不填+号,如:8613812349999" ).as_response() try: flag = AccountFlagEnum.from_name(request.args['flag']) except: return ResponseSuccess( message="标签错误,有效的标签包括: %s" % AccountFlagEnum.get_name_list()).as_response() user = User.query_user(merchant, account=account) if not user: return ResponseSuccess(message="手机号码未注册").as_response() User.update_user_flag(merchant, flag, account=account) user = User.query_user(merchant, account=account) bs_data = dict( account=account, uid=user.uid, flag=user.flag.desc, is_auth=user.is_official_auth, cache_flag=UserFlagCache(user.uid).get_flag().name, ) return ResponseSuccess(bs_data=bs_data).as_response()
def post(self): """ 用户详情 :return: """ form, error = UserInfoForm.request_validate() if error: return error.as_response() uid = form.uid.data kwargs = dict(id=uid) entry = User.query.filter_by(**kwargs).first() if not entry: return AdjustUserBalanceError(message="系统找不到该用户").as_response() balance_info = UserBalance.query.filter_by(**dict(id=uid)).first() if not balance_info: return UserBalanceNoFoundError(message="用户余额数据缺失").as_response() head_info = dict(uid=uid, account=PhoneNumberParser.hide_number(entry.account), type='测试用户' if entry.is_test_user else "普通用户", source=entry.merchant.name, ava_bl=balance_info.real_balance, create_time=entry.str_create_time, state=entry.state.name) card_lst = BankCard.query.filter_by(**dict(uid=uid, valid=1)).order_by( BankCard._create_time.desc()).all() if not card_lst: bankcard_entries = [] else: bankcard_entries = [ dict(bank_id=card.card_id, bank_name=card.bank_name, account_name=card.account_name, card_no=card.card_no_short_description, province="{}/{}".format(card.province, card.city), branch=card.branch) for card in card_lst ] return UserEntriesDetailResult( bs_data=dict(headInfo=head_info, bankcardEntries=bankcard_entries)).as_response()
def get(self): """ 删除某个手机号码的短信发送次数限制 :return: """ try: account = request.args.get('account') if account: account = '+' + account.strip('+').strip() if not PhoneNumberParser.is_valid_number(account): raise else: raise except: return ResponseSuccess( message="请输入正确的用户手机号码,必须有完整区号,不填+号,如:8613812349999" ).as_response() AuthCodeLimiter(account).cache.delete() accounts = list() for key in AuthCodeLimiterCache.scan_iter( AuthCodeLimiterCache.KEY_PREFIX): accounts.append( AuthCodeLimiterCache.split_key(key=key.decode('utf8'))[-1]) if account in accounts: return ResponseSuccess(message="删除失败,accounts: %s" % accounts).as_response() codes = list() for account in accounts: cache = AuthCodeLimiter(account) codes.append( dict( account=account, sent_times=cache.get_times(), is_limited=cache.is_limited(), ttl=cache.cache.get_ttl(), )) return ResponseSuccess(message="删除成功", bs_data=dict(codes=codes, )).as_response()
def validate_number(self, number): """ 验证手机号码 :param number: :return: """ # 去掉中间的空格和两边的空格 data = ''.join(number.data.split(' ')).strip() if not data.startswith('+'): raise ValidationError("区号必须以+号开头") if not data.strip('+').isdigit(): raise ValidationError("号码必须全是数字") if not PhoneNumberParser.is_valid_number(data): raise ValidationError("你输入了无效的手机号,请重新输入") self.number.data = data
def get(self): """ 查询用户余额 :return: """ if not request.args: return ResponseSuccess( message="参数规则:?account=8613812349999&merchant=test" ).as_response() try: account = request.args.get('account') if account: account = '+' + account.strip('+').strip() if not PhoneNumberParser.is_valid_number(account): raise else: raise except: return ResponseSuccess( message="请输入正确的用户手机号码,必须有完整区号,不填+号,如:8613812349999" ).as_response() try: merchant = MerchantEnum.from_name(request.args['merchant']) except: return ResponseSuccess(message="请输入正确的商户名称,有效的商户名称包括:%s" % MerchantEnum.get_names()).as_response() user = User.query_user(merchant, account=account) if not user: return ResponseSuccess(message="手机号码未注册, account: %s" % account).as_response() user_balance = UserBalance.query_balance(user.uid, merchant).first() return ResponseSuccess(bs_data=dict( account=account, uid=user.uid, balance=str(user_balance.real_balance), )).as_response()
def get(self): """ 联通性测试 :return: """ from scripts.user_balance import add_user_balance if not (current_app.config['DEBUG'] or current_app.config['TESTING']): return ResponseSuccess(message="无权限访问") if not request.args: return ResponseSuccess( message="参数规则:?account=8613812349999&balance=100").as_response( ) try: account = '+' + request.args['account'].strip('+').strip() if not PhoneNumberParser.is_valid_number(account): raise except: return ResponseSuccess( message="请输入正确的用户手机号码,必须有完整区号,不填+号,如:8613812349999" ).as_response() try: balance = Decimal(request.args['balance']) except: return ResponseSuccess(message="无效的余额").as_response() total, msg = add_user_balance(account, balance, register=False) if msg: return ResponseSuccess(message=msg).as_response() return ResponseSuccess(bs_data=dict( account=account, delta=str(balance), total=str(total), )).as_response()
def get(self): """ 查询密码错误限制 :return: """ try: account = request.args.get('account') if account: account = '+' + account.strip('+').strip() if not PhoneNumberParser.is_valid_number(account): raise except: return ResponseSuccess( message="请输入正确的用户手机号码,必须有完整区号,不填+号,如:8613812349999" ).as_response() accounts = list() if account: accounts.append(account) else: for key in UserPasswordCache.scan_iter( UserPasswordCache.KEY_PREFIX): accounts.append( UserPasswordCache.split_key(key=key.decode('utf8'))[-1]) codes = list() for account in accounts: cache = UserPasswordLimitCache(account) codes.append( dict( account=account, sent_times=cache.get_times(), is_limited=cache.is_limited(), ttl=cache.cache.get_ttl(), )) return ResponseSuccess(bs_data=codes).as_response()
def test_invalid_number(self): self.assertTrue(PhoneNumberParser.is_valid_number("+639166630027")) self.assertTrue(PhoneNumberParser.is_valid_number("+8618975532009")) self.assertFalse(PhoneNumberParser.is_valid_number("+8633234"))
def get(self): """ 查询用户余额变更流水 :return: """ if not request.args: return ResponseSuccess( message= "参数规则:?merchant=test&account=8618912341234&date=20190901&export=1" ).as_response() try: account = request.args.get('account') if account: account = '+' + account.strip('+').strip() if not PhoneNumberParser.is_valid_number(account): raise except: return ResponseSuccess( message="请输入正确的用户手机号码,必须有完整区号,不填+号,如:8613812349999" ).as_response() try: merchant = MerchantEnum.from_name(request.args['merchant']) except: return ResponseSuccess(message="请输入正确的商户名称,有效的商户名称包括:%s" % MerchantEnum.get_names()).as_response() try: date = request.args.get('date') if date: date = DateTimeKit.str_to_datetime( date, DateTimeFormatEnum.TIGHT_DAY_FORMAT, to_date=True) else: date = DateTimeKit.get_cur_date() except: return ResponseSuccess( message="请输入有效的查询日期,格式为:20190901").as_response() rst = dict( data=list(), sum_value=0, ) events = UserBalanceEvent.query_by_date(date, merchant=merchant, date=date) if account: user = User.query_user(merchant, account=account) if not user: return ResponseSuccess(message="用户不存在,请检查参数。商户:%s,手机号码:%s" % (merchant.name, account)) user_balance = UserBalance.query_balance(user.uid, merchant).first() rst.update(user=dict( account=user.account, uid=user.uid, user_balance=str(user_balance.real_balance), )) events = events.filter_by(uid=user.uid) rst['sql'] = str(events) for event in events: rst['sum_value'] += event.value_real rst['data'].append( dict( create_time=event.create_time, uid=event.uid, ref_id=event.ref_id, order_type=event.order_type.desc, source=event.source.desc, bl_type=event.bl_type.desc, value=str(event.value_real), ad_type=event.ad_type.desc, tx_id=event.tx_id, # 大整数,转为字符串 comment=event.comment, extra=event.raw_extra, )) rst['data'] = sorted(rst['data'], key=lambda x: x['create_time'], reverse=True) for x in rst['data']: x['create_time'] = DateTimeKit.datetime_to_str(x['create_time']) if rst['data'] and request.args.get('export'): filename = 'user_balance_events_%s.csv' % DateTimeKit.datetime_to_str( date, DateTimeFormatEnum.TIGHT_DAY_FORMAT) return CsvKit.send_csv(rst['data'], filename=filename, fields=rst['data'][0].keys()) rst['sum_value'] = str(rst['sum_value']) return ResponseSuccess(bs_data=rst).as_response()
def get(self): """ 给用户绑定信息 :return: """ if not request.args: return ResponseSuccess( message="参数规则:?merchant=test&account=861891111&name=大王&unbind=" ).as_response() try: merchant = MerchantEnum.from_name(request.args['merchant']) except: return ResponseSuccess(message="请输入正确的商户名称,有效的商户名称包括:%s" % MerchantEnum.get_names()).as_response() try: account = request.args['account'] account = '+' + account.strip('+').strip() if not PhoneNumberParser.is_valid_number(account): raise except: return ResponseSuccess( message="请输入正确的用户手机号码,必须有完整区号,不填+号,如:8613812349999" ).as_response() try: name = request.args['name'] except: return ResponseSuccess(message="绑定名称必填").as_response() user = User.query_user(merchant, account=account) if not user: return ResponseSuccess(message="手机号码未注册").as_response() bind_info = UserBindInfo.query_bind_by_uid(user.uid) if request.args.get('unbind'): if not bind_info: return ResponseSuccess(message="未绑定任何别名,无需解绑").as_response() if UserBindInfo.unbind_account(user.uid): return ResponseSuccess(message="解绑成功").as_response() else: return ResponseSuccess(message="解绑失败").as_response() else: if not bind_info: if UserBindInfo.bind_account(user.uid, merchant, account=user.account, name=name): msg = "绑定成功" else: msg = "绑定失败" return ResponseSuccess(message=msg).as_response() else: msg = "无需重复绑定,已经绑定名称:%s" % bind_info.name bind_info = UserBindInfo.query_bind_by_uid(user.uid) bs_data = dict( name=bind_info.name, account=bind_info.account, uid=user.uid, ) return ResponseSuccess(bs_data=bs_data, message=msg).as_response()
def post(self): """ 用户登陆获取token :return: """ # 验证登陆表单是否正确 form, error = LoginForm().request_validate() if error: return error.as_response() if not MerchantFeeConfig.query_latest_one(query_fields=dict( merchant=form.merchant.data, payment_way=PayTypeEnum.DEPOSIT, )): return MerchantConfigDepositError().as_response() if not MerchantFeeConfig.query_latest_one(query_fields=dict( merchant=form.merchant.data, payment_way=PayTypeEnum.WITHDRAW, )): return MerchantConfigWithdrawError().as_response() # 验证手机号是否已注册 user_info = User.query_user(form.merchant.data, account=form.number.data) if not user_info: return AccountNotExistError().as_response() if user_info.state == AccountStateEnum.INACTIVE: return DisableUserError().as_response() # 验证用户名 密码是否正确 if not User.verify_login(merchant=form.merchant.data, account=form.number.data, password=form.password.data): UserPasswordLimitCache(mobile_number=form.number.data).incr_times() # 获取密码输入错误次数是否达到上限 if UserPasswordLimitCache( mobile_number=form.number.data).is_limited(): User.update_user_state(form.merchant.data, account=form.number.data, state=AccountStateEnum.INACTIVE) return OriPasswordError().as_response() return LoginPasswordError().as_response() UserPasswordLimitCache(mobile_number=form.number.data).delete_cache() # 生成token 返回给客户端 token = UserLoginToken.generate_token( uid=user_info.uid, merchant=form.merchant.data.value) # 显示用户名 bind_info = UserBindInfo.query_bind_by_uid(user_info.uid) if bind_info: bind_name = bind_info.name else: bind_name = PhoneNumberParser.hide_number(user_info.account) return ResponseSuccessLogin(bs_data=dict( token=token, service_url=SERVICE_URL, permissions=user_info.permission_names, bind_name=bind_name, user_flag=user_info.flag.name, )).as_response()
def mask_in_account(self): try: return PhoneNumberParser.hide_number(self.in_account) except: return self.in_account