Exemple #1
0
    def post(self):
        form, error = TransferAccountQueryForm().request_validate()
        if error:
            return error.as_response()

        bind_user = UserBindInfo.query_bind(form.merchant.data,
                                            form.account.data)
        if not bind_user:
            # 未绑定账号,验证手机号码是否正确
            account = form.join_phone_number()
            if not account:
                return AccountNotExistError(message="您输入的账号不存在").as_response()
            form.account.data = account
        else:
            # 使用绑定的手机号码
            form.account.data = bind_user.account

        user_info = User.query_user(form.merchant.data,
                                    account=form.account.data)
        if not user_info:
            return AccountNotExistError(message="您输入的账号未注册").as_response()

        no_transfer_limit = UserBindInfo.query_bind_by_uid(user_info.uid)

        return ResponseTransferUserQueryResult(bs_data=dict(
            is_auth=user_info.is_official_auth,
            transfer_limit=0 if no_transfer_limit else TRANSFER_AMOUNT_LIMIT,
        )).as_response()
Exemple #2
0
def verify_credential(token):
    """
    使用basic auth进行JWT token鉴权
    加了装饰器 @auth.login_required 的view都需要先进这个函数进行token鉴权
    :param token:
    :return:
    """

    # 初始化g对象的error属性
    g.error = None

    rst = UserLoginToken.verify_token(token)
    if isinstance(rst, (APIException, )):
        # token 验证失败
        g.error = rst
        return False

    # 账户被封处理
    merchant = MerchantEnum(rst['merchant'])
    user = User.query_user(merchant=merchant, uid=rst['uid'])
    if not user:
        # 用户不存在
        g.error = AccountNotExistError()
        return False

    if not user.is_active:
        g.error = DisableUserError()
        return False

    g.user = user
    return True
Exemple #3
0
    def request_validate(cls):
        """
        数据库中检查手机号码是否已经注册
        :return:
        """
        form, error = super(MobileRegisterTrueCheckForm,
                            cls).request_validate()

        if not error:
            if not User.query_user(form.merchant.data,
                                   account=form.number.data):
                error = AccountNotExistError()

        return form, error
Exemple #4
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()
Exemple #5
0
    def post(self):
        """
        转账
        判断接受转账的用户是否存在
        判断是否存在支付密码
        校验老的支付密码
        判断余额是否足够
        执行转账操作
        """

        form, error = TransferForm().request_validate()
        if error:
            return error.as_response()

        # 从全局变量中取出用户ID,参考:verify_credential
        uid = g.user.uid

        if not g.user.has_permission(UserPermissionEnum.TRANSFER):
            return UserPermissionDeniedError().as_response()

        # 判断接受转账的用户是否存在
        bind_user = UserBindInfo.query_bind(form.merchant.data,
                                            form.number.data)
        if not bind_user:
            # 未绑定账号,验证手机号码是否正确
            account = form.join_phone_number()
            if not account:
                return AccountNotExistError(message="您输入的账号不存在").as_response()
            form.number.data = account
        else:
            # 使用绑定的手机号码
            form.number.data = bind_user.account

        user_info = User.query_user(form.merchant.data,
                                    account=form.number.data)
        if not user_info:
            return AccountNotExistError(message="账号(%s)不存在" %
                                        form.number.data).as_response()

        no_transfer_limit = UserBindInfo.query_bind_by_uid(user_info.uid)
        if not no_transfer_limit and form.amount.data > TRANSFER_AMOUNT_LIMIT:
            # 非绑定用户转账限额检查
            return UserPermissionDeniedError(
                message="单次转账额度不能超过%s" % TRANSFER_AMOUNT_LIMIT).as_response()

        # 判断是否是给自己转账
        if uid == user_info.uid:
            return TransferToMeError().as_response()

        # 判断是否存在支付密码
        user = User.query_user(form.merchant.data, uid)

        if not user.trade_pwd:
            return PaymentPwdNotExistError().as_response()

        cache = UserPaymentPasswordLimitCache(uid=uid)

        # 获取支付密码输入错误次数是否达到上限
        if cache.is_limited():
            return PaymentPasswordLimitedError().as_response()

        # 校验支付密码
        flag = User.verify_payment_password(
            form.merchant.data, uid=uid, password=form.payment_password.data)

        # 交易密码校验失败
        if not flag:
            cache.incr_times()
            times = cache.get_left_times()
            return PaymentPasswordError(message=PaymentPasswordError.message.
                                        format(times)).as_response()

        # 密码校验成功 删除密码输入错误记录
        cache.delete_cache()

        # 判断余额是否足够
        balance = UserBalance.query_balance(uid=uid,
                                            merchant=g.user.merchant).first()
        if BalanceKit.divide_unit(balance.balance) < form.amount.data:
            return AccountBalanceInsufficientError().as_response()

        # 执行转账动作
        flag, msg = UserBalanceEvent.transfer(from_user=g.user,
                                              to_user=user_info,
                                              merchant=form.merchant.data,
                                              amount=form.amount.data,
                                              comment=form.comment.data)

        # 设置失败的情况
        if not flag:
            return NoSourceError().as_response()

        return ResponseSuccess().as_response()
Exemple #6
0
    def post(self):
        """
        手动补单
        :return:
        """
        form, error = CreateDepositOrderForm().request_validate()
        if error:
            return error.as_response()
        '''
        根据商户查询用户是否存在
        构造数据
        创建充值订单
        更改订单状态为完成
        '''
        # 根据商户查询用户是否存在
        user = User.query_user(form.merchant.data, uid=form.uid.data)
        if not user:
            return AccountNotExistError().as_response()

        # 构造数据
        client_ip = form.client_ip.data
        channel_enum = form.channel_id.data
        payment_type = form.payment_type.data
        amount = Decimal(form.amount.data)

        # 判断当前传入的支付类型是否该渠道支持
        if payment_type != channel_enum.conf['payment_type']:
            return InvalidDepositPaymentTypeError()

        merchant = form.merchant.data

        # 找出最新版本的商户费率配置
        channel_config = ChannelConfig.query_latest_one(query_fields=dict(
            channel_enum=channel_enum))
        if not channel_config:
            return InvalidDepositChannelError().as_response()

        if not channel_config.is_channel_valid(merchant.is_test):
            return ChannelNoValidityPeriodError().as_response()

        if ChannelListHelper.is_amount_out_of_range(
                amount=amount,
                merchant=merchant,
                payment_way=PayTypeEnum.DEPOSIT,
                client_ip=client_ip):
            return DepositOrderAmountInvalidError().as_response()

        # limit_min, limit_max = ChannelLimitCacheCtl(
        #     PayTypeEnum.DEPOSIT).get_channel_limit()
        # try:
        #     if limit_min > amount or limit_max < amount:
        #         return DepositOrderAmountInvalidError().as_response()
        # except Exception as e:
        #     return MustRequestDepositLimitError().as_response()

        # 找出最新版本的商户费率配置
        merchant_fee = MerchantFeeConfig.query_latest_one(
            query_fields=dict(merchant=merchant,
                              payment_way=PayTypeEnum.DEPOSIT,
                              payment_method=channel_enum.conf.payment_method))

        if not merchant_fee:
            return MerchantConfigDepositError().as_response()

        try:
            with db.auto_commit():
                # 创建待支付订单
                order, _ = OrderCreateCtl.create_order_event(
                    uid=user.uid,
                    merchant=merchant,
                    amount=amount,
                    channel_id=channel_config.channel_id,
                    mch_fee_id=merchant_fee.config_id,
                    order_type=PayTypeEnum.DEPOSIT,
                    source=OrderSourceEnum.MANUALLY,
                    in_type=InterfaceTypeEnum.CASHIER_H5,
                    ip=client_ip,
                    pay_method=channel_enum.conf.payment_method,
                    op_account=g.user.account,  # 后台管理员账号,后台人工修改数据时必填
                    comment=form.remark.data,  # 管理后台修改备注,后台人工修改数据时必填
                    mch_tx_id=form.mch_tx_id.data,
                    commit=False,
                )
                if not order:
                    raise Exception('order create failed')

                # 支付成功
                if not DepositTransactionCtl.success_order_process(
                        order=order,
                        tx_amount=amount,
                        channel_tx_id=form.mch_tx_id.data,
                        comment="手动补单订单",
                        commit=False,
                ):
                    raise Exception('order process failed')
        except Exception as e:
            if str(e).find("Duplicate entry") >= 0:
                return PreOrderCreateError(message="商户订单号重复: {}".format(
                    form.mch_tx_id.data)).as_response()
            return PreOrderCreateError(message=str(e)).as_response()

        return ResponseSuccess().as_response()