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()
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
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
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 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()
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()