Пример #1
0
 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
Пример #2
0
    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:])
Пример #3
0
    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()
Пример #4
0
    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()
Пример #5
0
    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()
Пример #6
0
    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()
Пример #7
0
    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()
Пример #8
0
    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
Пример #9
0
    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()
Пример #10
0
    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()
Пример #11
0
    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()
Пример #12
0
 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"))
Пример #13
0
    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()
Пример #14
0
    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()
Пример #15
0
    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()
Пример #16
0
 def mask_in_account(self):
     try:
         return PhoneNumberParser.hide_number(self.in_account)
     except:
         return self.in_account