def get(self): """ 商户配置查询 :return: """ if not request.args: return ResponseSuccess(message="参数规则:?merchant=test").as_response() try: merchant = MerchantEnum.from_name(request.args['merchant']) except: return ResponseSuccess(message="请输入正确的商户名称,有效的商户名称包括:%s" % MerchantEnum.get_names()).as_response() merchant_info = MerchantInfo.query_merchant(merchant) if not merchant_info: return ResponseSuccess(message="未创建商户").as_response() bs_data = dict( balance=dict( balance_total=str(merchant_info.balance_total), balance_available=str(merchant_info.balance_available), balance_income=str(merchant_info.balance_income), balance_frozen=str(merchant_info.balance_frozen), ), merchant=merchant.name, domains=MerchantDomainConfig.get_domains(merchant), # db=DBEnum(merchant.name).get_db_name(), ) deposit_fees = MerchantFeeConfig.query_active_configs( query_fields=dict( merchant=merchant, payment_way=PayTypeEnum.DEPOSIT, )) deposit_fees = MerchantFeeConfig.filter_latest_items(deposit_fees) if not deposit_fees: return MerchantConfigDepositError(bs_data=bs_data).as_response() bs_data['deposit_fees'] = [x.short_description for x in deposit_fees] withdraw_fees = MerchantFeeConfig.query_latest_one(query_fields=dict( merchant=merchant, payment_way=PayTypeEnum.WITHDRAW, )) if not withdraw_fees: return MerchantConfigWithdrawError(bs_data=bs_data).as_response() bs_data['withdraw_fees'] = withdraw_fees.short_description channels = ChannelListHelper.get_available_channels( merchant, PayTypeEnum.DEPOSIT) bs_data['deposit_channels'] = [x.short_description for x in channels] channels = ChannelListHelper.get_available_channels( merchant, PayTypeEnum.WITHDRAW) bs_data['withdraw_channels'] = [x.short_description for x in channels] return ResponseSuccess(bs_data=bs_data).as_response()
def post(self): """ 检查手机号是否已经注册 """ form, error = MobileRegisterCheckForm().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() return ResponseSuccess().as_response()
def check_result(self, conf_dict): payment_method = conf_dict.get('payment_method') conf = MerchantFeeConfig.query_latest_one(query_fields=dict( merchant=conf_dict['merchant'], payment_way=conf_dict['payment_way'], payment_method=payment_method )) self.assertIsNotNone(conf) self.assertEqual(conf_dict['merchant'], conf['merchant']) if payment_method: self.assertEqual(conf_dict['payment_method'], conf['payment_method']) self.assertEqual(conf_dict['fee_type'], conf['fee_type']) self.assertEqual(conf_dict['value'], conf['value'])
def post(self): """ 手机号码注册 :return: """ # 验证 手机号 验证码 密码格式 form, error = PasswordForm().request_validate() if error: return error.as_response() # 判断验证码是否过期 if AuthCodeGenerator(form.number.data).is_expired(form.auth_code.data): return AuthCodeExpiredError().as_response() # 判断验证码是否正确 if not AuthCodeGenerator(form.number.data).verify_code( form.auth_code.data): return AuthCodeError().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.register_account( merchant=form.merchant.data, account=form.number.data, ac_type=AccountTypeEnum.MOBILE, login_pwd=form.password.data, ) return ResponseSuccess().as_response()
def __test_callback_ponypay_deposit(self): self.path = "/callback/ponypay/deposit" # 初始化数据 kwargs = dict( fee="2.5", fee_type=PaymentFeeTypeEnum.PERCENT_PER_ORDER, limit_per_min="200", limit_per_max="10000", trade_begin_hour="00", trade_begin_minute="00", trade_end_hour="23", trade_end_minute="59", maintain_begin=DateTimeKit.str_to_datetime("2019-09-07 09:00:00"), maintain_end=DateTimeKit.str_to_datetime("2019-09-07 09:00:00"), settlement_type=SettleTypeEnum.D0, state=ChannelStateEnum.TESTING, priority="101") rst, error = ChannelConfig.update_channel( ChannelConfigEnum.CHANNEL_1001, **kwargs) self.assertEqual(rst, True) self.assertEqual(error, None) # ChannelLimitCacheCtl(PayTypeEnum.DEPOSIT).sync_db_channels_to_cache() merchant = MerchantEnum.TEST merchant_fee_list = [ dict(merchant=merchant, payment_way=PayTypeEnum.DEPOSIT, value="3", fee_type=PaymentFeeTypeEnum.PERCENT_PER_ORDER, payment_method=PayMethodEnum.ZHIFUBAO_SAOMA), dict(merchant=merchant, payment_way=PayTypeEnum.WITHDRAW, value="3.2", fee_type=PaymentFeeTypeEnum.PERCENT_PER_ORDER) ] ret, error = MerchantFeeConfig.update_fee_config( merchant, merchant_fee_list) self.assertEqual(rst, True) self.assertEqual(error, None) info = dict( account="+8618977772222", merchant=MerchantEnum.TEST, ac_type=AccountTypeEnum.MOBILE, login_pwd="123456789", ) MerchantInfo.create_merchant(MerchantEnum.TEST, MerchantTypeEnum.TEST) user = User.register_account(merchant=info['merchant'], account=info['account'], ac_type=info['ac_type'], login_pwd=info['login_pwd']) uid = user.id channel_config = ChannelConfig.query_latest_one(query_fields=dict( channel_enum=ChannelConfigEnum.CHANNEL_1001)) channel_conf = ChannelConfigEnum.CHANNEL_1001.conf channel_conf['white_ip'].append("127.0.0.1") merchant_fee = MerchantFeeConfig.query_latest_one( query_fields=dict(merchant=MerchantEnum.TEST, payment_way=PayTypeEnum.DEPOSIT, payment_method=channel_conf.payment_method)) self.__test_callback_order_success(uid, channel_config, merchant_fee, '1') self.__test_callback_order_success(uid, channel_config, merchant_fee, '-1') stop = 1
def __test_api_withdraw(self): """ 1. 新建用户提现订单 :return: """ order_cls = OrderWithdraw uid = 1000 channel_enum = ChannelConfigEnum.CHANNEL_1001 banks = [ PaymentBankEnum(int(bank)) for bank in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] ] proxy_channel = dict(fee=Decimal("2.5"), fee_type=PaymentFeeTypeEnum.PERCENT_PER_ORDER, limit_per_min=300, limit_per_max=1000, limit_day_max=0, trade_begin_hour=0, trade_begin_minute=0, trade_end_hour=23, trade_end_minute=59, maintain_begin=DateTimeKit.str_to_datetime( "2019-12-11 09:00:00", DateTimeFormatEnum.SECONDS_FORMAT), maintain_end=DateTimeKit.str_to_datetime( "2025-12-20 23:00:00", DateTimeFormatEnum.SECONDS_FORMAT), state=ChannelStateEnum.TESTING, banks=banks) ProxyChannelConfig.update_channel(channel_enum, **proxy_channel) merchant = MerchantEnum.TEST # 准备配置数据 bank = BankCard.add_bank_card( merchant, uid=uid, bank_name="中国工商银行", bank_code="ICBC", card_no="6212260405014627955", account_name="张三", branch="广东东莞东莞市长安镇支行", province="广东省", city="东莞市", ) OrderMixes.add_one_channel_config(channel_enum) OrderMixes.add_one_merchant_config(merchant, channel_enum, payment_way=PayTypeEnum.WITHDRAW) channel_config = ChannelConfig.query_latest_one( dict(channel_enum=channel_enum)) merchant_fee_config = MerchantFeeConfig.query_latest_one( dict( merchant=merchant, payment_way=PayTypeEnum.WITHDRAW, payment_method=channel_enum.conf.payment_method, )) amount = Decimal("500") fee = BalanceKit.round_4down_5up( Decimal(merchant_fee_config.value) * amount / Decimal(100)) # 创建提现订单 params = dict( uid=uid, merchant=merchant, channel_id=channel_config.channel_id, mch_fee_id=merchant_fee_config.config_id, source=OrderSourceEnum.TESTING, order_type=PayTypeEnum.WITHDRAW, in_type=InterfaceTypeEnum.CASHIER_H5, amount=amount, bank_id=bank.id, fee=fee, ) order, ref_id = OrderCreateCtl.create_order_event(**params) event = OrderEvent.query_one(dict(ref_id=ref_id), merchant=merchant, date=order.create_time) data = order_cls.query_by_order_id(order_id=event.order_id, merchant=merchant) begin_time, end_time = DateTimeKit.get_month_begin_end( year=int(DateTimeKit.get_cur_datetime().year), month=int(DateTimeKit.get_cur_datetime().month)) withdraw_params = dict(merchant_name="TEST", page_size=10, page_index=1, begin_time=DateTimeKit.datetime_to_str( begin_time, DateTimeFormatEnum.SECONDS_FORMAT), end_time=DateTimeKit.datetime_to_str( end_time, DateTimeFormatEnum.SECONDS_FORMAT), state="0") self.path = "/trade_manage/withdraw/list" # 通过接口 查询提现订单 response = self.do_request(json_data=withdraw_params) print(response.json, "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&") self.assertEqual("1", response.json['data']['total']) self.assertEqual("待认领", response.json['data']['entries'][0]['state']) self.path = "/trade_manage/order/allowed" # 通过接口, 认领订单 allowed_params = dict(order_id=order.id, merchant_name="TEST") response = self.do_request(allowed_params) self.assertEqual(ResponseSuccess.code, response.status_code) self.assertEqual(ResponseSuccess.error_code, response.json['error_code']) # 查询当前订单状态是否已修改为已认领 data = order_cls.query_by_order_id(order_id=event.order_id, merchant=merchant) self.assertEqual(OrderStateEnum.ALLOC, data.state) # 通过接口查询 审核列表 已有的认领订单为1 self.path = '/trade_manage/withdraw/review/list' request_review_params = dict( year=str(DateTimeKit.get_cur_datetime().year), mouth=str(DateTimeKit.get_cur_datetime().month)) response = self.do_request(json_data=request_review_params) self.assertEqual(1, len(response.json['data']['entries'])) self.assertEqual("已认领", response.json['data']['entries'][0]['state']) # 通过接口查询 当前可用的 代付通道 proxy_channel_suppor = dict(bank_type=bank.bank_enum.name, merchant_name="TEST", amount=str(amount)) self.path = "/trade_manage/withdraw/available/channel" response = self.do_request(json_data=proxy_channel_suppor) self.assertEqual(WithdrawBankEntryResult.code, response.status_code) self.assertEqual(WithdrawBankEntryResult.error_code, response.json['error_code']) self.assertEqual( channel_enum.conf['provider'] + channel_enum.conf['mch_id'], response.json['data']['entries'][0]['key']) # 测试人工出款 处理订单 self.path = '/trade_manage/withdraw/person/execute' execute_params = dict(order_id=order.order_id, merchant="Test") response = self.do_request(json_data=execute_params) self.assertEqual(ResponseSuccess.code, response.status_code) self.assertEqual(ResponseSuccess.error_code, response.json['error_code']) data = order_cls.query_by_order_id(order_id=event.order_id, merchant=merchant) self.assertEqual(OrderStateEnum.DEALING, data.state) # 测试人工出款 出款 self.path = "/trade_manage/withdraw/person/done" done_params = dict(order_id=order.order_id, merchant='TEST', comment='测试', fee='5') response = self.do_request(json_data=done_params) self.assertEqual(ResponseSuccess.code, response.status_code) self.assertEqual(ResponseSuccess.error_code, response.json['error_code']) data = order_cls.query_by_order_id(order_id=event.order_id, merchant=merchant) self.assertEqual(OrderStateEnum.SUCCESS, data.state)
def __add_event(self, uid, merchant, channel_enum, order_type): order_cls = OrderDeposit if order_type == PayTypeEnum.DEPOSIT else OrderWithdraw channel_config = ChannelConfig.query_latest_one( dict(channel_enum=channel_enum)) merchant_fee_config = MerchantFeeConfig.query_latest_one( dict( merchant=merchant, payment_way=PayTypeEnum.DEPOSIT, payment_method=channel_enum.conf.payment_method, )) params = dict( uid=uid, merchant=merchant, channel_id=channel_config.channel_id, mch_fee_id=merchant_fee_config.config_id, source=OrderSourceEnum.TESTING, order_type=order_type, in_type=InterfaceTypeEnum.CASHIER_H5, amount=Decimal("500"), comment='谢谢', op_account='xxx', bank_id=123, fee=10 if order_type == PayTypeEnum.WITHDRAW else 0, ) order, ref_id = OrderCreateCtl.create_order_event(**params) self.assertIsNotNone(order) event = OrderEvent.query_one(dict(ref_id=ref_id), merchant=merchant, date=order.create_time) self.assertIsNotNone(event) self.assertEqual(order.order_id, event.order_id) self.assertEqual(order.uid, event.uid) self.assertEqual(ref_id, event.ref_id) order = order_cls.query_by_order_id(order_id=event.order_id, merchant=merchant) self.assertIsNotNone(order) self.assertEqual(params['uid'], order.uid) self.assertEqual(params['merchant'], order.merchant) self.assertEqual(params['channel_id'], order.channel_id) self.assertEqual(params['source'], order.source) self.assertEqual(params['amount'], order.amount) self.assertTrue(len(order.mch_tx_id) > 0) self.assertTrue(len(order.sys_tx_id) > 0) # 更新订单 order, ref_id = OrderUpdateCtl.update_order_event( order_id=order.order_id, uid=order.uid, merchant=merchant, state=OrderStateEnum.SUCCESS if order_type == PayTypeEnum.DEPOSIT else OrderStateEnum.ALLOC, tx_amount=Decimal("500.32"), channel_tx_id='1232283838229929292', settle=SettleStateEnum.DONE, deliver=DeliverStateEnum.DONE, channel_id=channel_config.channel_id, mch_fee_id=merchant_fee_config.config_id, op_account='xxxx', comment='改了改了', offer=Decimal('1.22'), fee=Decimal('1.22'), cost=Decimal('1.22'), profit=Decimal('1.22'), deliver_type=DeliverTypeEnum.PROXY, alloc_time=DateTimeKit.get_cur_datetime(), deal_time=DateTimeKit.get_cur_datetime(), ) self.assertIsNotNone(order) event = OrderEvent.query_one(dict(ref_id=ref_id), merchant=merchant, date=order.create_time) self.assertEqual(order.order_id, event.order_id) self.assertEqual(order.uid, event.uid) self.assertEqual(ref_id, event.ref_id) order3 = order_cls.query_by_order_id(order_id=event.order_id, merchant=merchant) self.assertIsNotNone(order3) self.assertEqual(params['uid'], order3.uid) self.assertEqual(params['merchant'], order3.merchant) self.assertEqual(params['channel_id'], order3.channel_id) self.assertEqual(params['source'], order3.source) self.assertEqual(Decimal("500.32"), order3.tx_amount) self.assertEqual(order.order_id, order3.order_id) self.assertEqual(order.mch_tx_id, order3.mch_tx_id) self.assertEqual(order.sys_tx_id, order3.sys_tx_id) order3 = order_cls.query_by_tx_id(tx_id=order.sys_tx_id) self.assertIsNotNone(order3) self.assertEqual(params['uid'], order3.uid) self.assertEqual(params['merchant'], order3.merchant) self.assertEqual(params['channel_id'], order3.channel_id) self.assertEqual(params['source'], order3.source) self.assertEqual(Decimal("500.32"), order3.tx_amount) self.assertEqual(order.order_id, order3.order_id) self.assertEqual(order.mch_tx_id, order3.mch_tx_id) self.assertEqual(order.sys_tx_id, order3.sys_tx_id) order3 = order_cls.query_by_uid_someday( merchant=merchant, uid=uid, someday=order.create_time).all()[0] self.assertIsNotNone(order3) self.assertEqual(params['uid'], order3.uid) self.assertEqual(params['merchant'], order3.merchant) self.assertEqual(params['channel_id'], order3.channel_id) self.assertEqual(params['source'], order3.source) self.assertEqual(Decimal("500.32"), order3.tx_amount) self.assertEqual(order.order_id, order3.order_id) self.assertEqual(order.mch_tx_id, order3.mch_tx_id) self.assertEqual(order.sys_tx_id, order3.sys_tx_id) begin_time, end_time = DateTimeKit.get_day_begin_end(order.create_time) orders = order_cls.query_by_create_time(begin_time, end_time, merchant=merchant, uid=uid).all() order3 = orders[-1] self.assertIsNotNone(order3) self.assertFalse(order3.is_cold_table()) self.assertEqual(params['uid'], order3.uid) self.assertEqual(params['merchant'], order3.merchant) self.assertEqual(params['channel_id'], order3.channel_id) self.assertEqual(params['source'], order3.source) self.assertEqual(Decimal("500.32"), order3.tx_amount) self.assertEqual(order.order_id, order3.order_id) self.assertEqual(order.mch_tx_id, order3.mch_tx_id) self.assertEqual(order.sys_tx_id, order3.sys_tx_id) # 冷表查询测试 begin_time, end_time = DateTimeKit.get_day_begin_end(order.create_time) clean_date = order_cls.get_clean_date() if clean_date.month == begin_time.month: begin_time = clean_date orders = order_cls.query_by_create_time(begin_time, end_time, merchant=merchant, uid=uid).all() order3 = orders[-1] self.assertIsNotNone(order3) self.assertTrue(order3.is_cold_table()) self.assertEqual(params['uid'], order3.uid) self.assertEqual(params['merchant'], order3.merchant) self.assertEqual(params['channel_id'], order3.channel_id) self.assertEqual(params['source'], order3.source) self.assertEqual(Decimal("500.32"), order3.tx_amount) self.assertEqual(order.order_id, order3.order_id) self.assertEqual(order.mch_tx_id, order3.mch_tx_id) self.assertEqual(order.sys_tx_id, order3.sys_tx_id)
def order_create(cls, user, amount, client_ip, user_bank_id=None, bank_info=None, notify_url=None, mch_tx_id=None, extra=None): """ 申请创建订单 :return: """ params = copy.deepcopy(locals()) params.pop('cls') order = None if not bank_info: card_entry = BankCard.query_bankcard_by_id(card_id=user_bank_id) if not card_entry: msg = '%s, params: %s' % (WithdrawBankNoExistError.message, params) current_app.logger.error(msg) return order, WithdrawBankNoExistError() # 判断 金额是否在有效范围 获取代付系统当前最高最低交易金额 # limit_min, limit_max = ChannelLimitCacheCtl(PayTypeEnum.WITHDRAW).get_channel_limit() # if amount < limit_min or amount > limit_max: if ChannelListHelper.is_amount_out_of_range( amount=amount, merchant=user.merchant, payment_way=PayTypeEnum.WITHDRAW, client_ip=client_ip): msg = '%s, params: %s' % (WithdrawOrderAmountInvalidError.message, params) current_app.logger.error(msg) return order, WithdrawOrderAmountInvalidError() # 商户配置信息 merchant_config = MerchantFeeConfig.query_latest_one(query_fields=dict( merchant=user.merchant, payment_way=PayTypeEnum.WITHDRAW, )) # 手续费计算 fee_value = FeeCalculator.calc_fee(amount, merchant_config.fee_type, merchant_config.value) user_fee = merchant_fee = 0 if merchant_config.cost_type == CostTypeEnum.MERCHANT: merchant_fee = fee_value elif merchant_config.cost_type == CostTypeEnum.USER: user_fee = fee_value # 用户实际到账金额要减去手续费 amount -= user_fee # 用户余额判断 if user.uid: user_balance = UserBalance.query_balance( uid=user.uid, merchant=user.merchant).first() if user_balance.real_balance < amount + user_fee: msg = '%s, params: %s' % ("用户余额不足", params) current_app.logger.error(msg) return order, AccountBalanceInsufficientError(message="用户余额不足") # 判断商户余额是否充足 merchant_balance = MerchantInfo.query_merchant(m_name=user.merchant) if merchant_balance.balance_available <= amount + merchant_fee: msg = '%s, params: %s' % ("商户余额不足", params) current_app.logger.error(msg) return order, AccountBalanceInsufficientError(message="商户余额不足") # 订单来源 source = OrderSourceEnum.TESTING if user.is_test_user else OrderSourceEnum.ONLINE try: # 创建提现订单/扣商户余额/扣用户余额,在同一个事务里面 with db.auto_commit(): order, ref_id = OrderCreateCtl.create_order_event( uid=user.uid, amount=amount, merchant=user.merchant, source=source, order_type=PayTypeEnum.WITHDRAW, in_type=InterfaceTypeEnum.CASHIER_H5, bank_id=user_bank_id, # 提现时需要填入 银行卡信息 mch_fee_id=merchant_config.config_id, mch_tx_id=mch_tx_id, ip=client_ip, fee=fee_value, cost_type=merchant_config.cost_type, notify_url=notify_url, bank_info=bank_info, extra=extra, commit=False, ) if not order: msg = '%s, params: %s' % (WithdrawOrderCreateError.message, params) current_app.logger.error(msg) raise WithdrawOrderCreateError() # 扣提现金额 flag, msg = MerchantBalanceEvent.update_balance( merchant=user.merchant, ref_id=ref_id, source=source, order_type=PayTypeEnum.WITHDRAW, bl_type=BalanceTypeEnum.AVAILABLE, value=amount, ad_type=BalanceAdjustTypeEnum.MINUS, tx_id=order.sys_tx_id, commit=False, ) if flag < 0: msg = '%s, params: %s' % ("扣商户余额失败, %s" % msg, params) current_app.logger.error(msg) raise DepositCallbackUserBalanceError(message="扣商户余额失败") if merchant_fee: # 扣商户手续费 flag, msg = MerchantBalanceEvent.update_balance( merchant=user.merchant, ref_id=OrderUtils.gen_unique_ref_id(), source=source, order_type=PayTypeEnum.FEE, bl_type=BalanceTypeEnum.AVAILABLE, value=merchant_fee, ad_type=BalanceAdjustTypeEnum.MINUS, tx_id=order.sys_tx_id, commit=False, ) if flag < 0: msg = '%s, params: %s' % ("扣商户手续费失败, %s" % msg, params) current_app.logger.error(msg) raise DepositCallbackUserBalanceError( message="扣商户手续费失败") if user_fee: # 扣除用户手续费 flag, msg = UserBalanceEvent.update_user_balance( uid=user.uid, merchant=user.merchant, ref_id=OrderUtils.gen_unique_ref_id(), source=source, order_type=PayTypeEnum.FEE, bl_type=BalanceTypeEnum.AVAILABLE, value=user_fee, ad_type=BalanceAdjustTypeEnum.MINUS, tx_id=order.sys_tx_id, commit=False, ) if flag < 0: msg = '%s, params: %s' % ("扣用户手续费失败, %s" % msg, params) current_app.logger.error(msg) raise DepositCallbackUserBalanceError( message="扣用户手续费失败") # 扣除用户余额 flag, msg = UserBalanceEvent.update_user_balance( uid=user.uid, merchant=user.merchant, ref_id=ref_id, source=source, order_type=PayTypeEnum.WITHDRAW, bl_type=BalanceTypeEnum.AVAILABLE, value=amount, ad_type=BalanceAdjustTypeEnum.MINUS, tx_id=order.sys_tx_id, commit=False, ) if flag < 0: msg = '%s, params: %s' % ("扣用户余额失败, %s" % msg, params) current_app.logger.error(msg) raise DepositCallbackUserBalanceError(message="扣用户余额失败") except APIException as e: current_app.logger.error(traceback.format_exc()) return order, e return order, None
def order_create(cls, user, amount, channel_enum, client_ip, source: OrderSourceEnum, in_type: InterfaceTypeEnum, notify_url=None, result_url=None, mch_tx_id=None, extra=None): """ 申请创建订单 :return: """ merchant = user.merchant # 找出最新版本的商户费率配置 channel_config = ChannelConfig.query_latest_one(query_fields=dict( channel_enum=channel_enum)) if not channel_config: current_app.logger.error( 'no channel config found, channel_enum: %s', channel_enum.desc) return None, InvalidDepositChannelError() if channel_config.is_in_maintain_time(): current_app.logger.error('channel in maintain, channel_enum: %s', channel_enum.desc) return None, ChannelNoValidityPeriodError(message="通道(%s)维护中" % channel_enum.desc) if not channel_config.is_in_trade_time(): current_app.logger.error( 'channel not in trade time, channel_enum: %s', channel_enum.desc) return None, ChannelNoValidityPeriodError( message="当前时间不在通道(%s)交易时间内" % channel_enum.desc) if channel_config.is_amount_per_limit(amount): current_app.logger.error( 'per amount limit, channel_enum: %s, amount: %s', channel_enum.desc, amount) return None, DepositOrderAmountInvalidError( message="%s,通道(%s)" % (DepositOrderAmountInvalidError.message, channel_enum.desc)) if channel_enum.is_fixed_amount_channel( ) and not channel_enum.is_amount_in_fixed_list(amount): current_app.logger.error( 'invalid amount, channel: %s, input amount: %s, fixed amounts: %s', channel_enum.desc, amount, channel_enum.get_fixed_amounts()) return DepositOrderAmountInvalidError(message="固额支付类型额度匹配失败") if not channel_config.state.is_available(user.is_test_user): current_app.logger.error( 'channel state not available, channel_enum: %s, uid: %s, merchant: %s', channel_enum.desc, user.uid, merchant.name) return None, ChannelNoValidityPeriodError( message="通道(%s)状态:%s" % (channel_enum.desc, channel_config.state.desc)) # 找出最新版本的商户费率配置 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: current_app.logger.error( 'no merchant fee config for channel, channel_enum: %s, uid: %s, merchant: %s', channel_enum.desc, user.uid, merchant.name) return None, MerchantConfigDepositError() kwargs = dict( 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=source, in_type=in_type, ip=client_ip, pay_method=channel_enum.conf.payment_method, notify_url=notify_url, result_url=result_url, mch_tx_id=mch_tx_id, extra=extra, ) try: order, _ = OrderCreateCtl.create_order_event(**kwargs) except Exception as e: return None, PreOrderCreateError(message=str(e)) if not order: return None, PreOrderCreateError() return order, None
def get_merchant_fee_config(cls, payment_way: PayTypeEnum): return MerchantFeeConfig.query_latest_one(query_fields=dict( merchant=cls.merchant, payment_way=payment_way, ))
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): """ 手动补单 :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()