def __clean_order(self, order_type, day_num, uid_range): test_order = OrderMixes(order_type) test_order.batch_add_orders(day_num, uid_range) if order_type == PayTypeEnum.DEPOSIT: OrderDeposit.clean_hot_table() OrderDetailDeposit.clean_hot_table() else: OrderWithdraw.clean_hot_table() OrderDetailWithdraw.clean_hot_table() test_order.check_clean_result(day_num, uid_range) test_order.test_one_day_order_clean(day_num, uid_range) test_order.check_clean_result(day_num, uid_range)
def order_alloc(cls, admin_account, order_id, merchant): """ 认领分配订单 :return: """ params = copy.deepcopy(locals()) params.pop('cls') order = OrderWithdraw.query_by_order_id(merchant, order_id) if not order: msg = '%s, params: %s' % (NoSuchWithdrawOrderError.message, params) current_app.logger.error(msg) return NoSuchWithdrawOrderError() if order.state != OrderStateEnum.INIT: msg = '%s, params: %s' % (DoNotAllowedOrderError.message, params) current_app.logger.error(msg) return DoNotAllowedOrderError() order, ref_id = OrderUpdateCtl.update_order_event( order.order_id, uid=order.uid, merchant=merchant, state=OrderStateEnum.ALLOC, op_account=admin_account, alloc_time=DateTimeKit.get_cur_datetime(), ) if not order: msg = '%s, params: %s' % (AllowedOrderError.message, params) current_app.logger.error(msg) return AllowedOrderError() return ResponseSuccess()
def query_order_list(cls, uid, merchant, begin_time, end_time, payment_type=None): """ 查询订单列表 :param uid: :param merchant: :param begin_time: :param end_time: :param payment_type: :return: """ order_items = [] deposit_query = OrderDeposit.query_by_create_time( begin_time=begin_time, end_time=end_time, merchant=merchant).filter_by(uid=uid) withdraw_query = OrderWithdraw.query_by_create_time( begin_time=begin_time, end_time=end_time, merchant=merchant).filter_by(uid=uid) if payment_type == PayTypeEnum.DEPOSIT: order_items.extend(deposit_query) elif payment_type == PayTypeEnum.WITHDRAW: order_items.extend(withdraw_query) else: order_items.extend(deposit_query) order_items.extend(withdraw_query) return order_items
def post(self): """ 人工出款: 用户银行信息查询 :return: """ form, error = WithDrawBankForm().request_validate() if error: return error.as_response() # 查询 提现订单表 获取提现金额, 提现用户指定行 order = OrderWithdraw.query_by_order_id(merchant=form.merchant.data, order_id=form.order_id.data) if not order: return OrderInfoMissingError().as_response() if order.state not in [OrderStateEnum.ALLOC, OrderStateEnum.DEALING]: return BankOrderStateError().as_response() bank = order.get_bank_card() if not bank: return BankInfoMissingError().as_response() bank_entry = dict(amount=order.amount, account_name=bank.account_name, card_no=bank.card_no, bank_name=bank.bank_name, province=bank.province, city=bank.city, branch=bank.branch) return WithdrawBankEntryResult(bs_data=dict( bank_entry=bank_entry)).as_response()
def manually_withdraw(cls, admin_user, merchant, order_id): """ 人工出款 :return: """ # 查询 提现订单表 获取提现金额, 提现用户指定行 withdraw_entry = OrderWithdraw.query_by_order_id(merchant=merchant, order_id=order_id) if not withdraw_entry: return OrderInfoMissingError() if withdraw_entry.state != OrderStateEnum.ALLOC: return BankOrderStateError() # 更新订单状态 order, ref_id = OrderUpdateCtl.update_order_event( withdraw_entry.order_id, uid=int(withdraw_entry.uid), merchant=merchant, state=OrderStateEnum.DEALING, tx_amount=withdraw_entry.amount, deliver_type=DeliverTypeEnum.MANUALLY, deal_time=DateTimeKit.get_cur_datetime(), op_account=admin_user.account, mch_fee_id=withdraw_entry.mch_fee_id, commit=True) if not order: return WithdrawOrderStateChangeError() return ResponseSuccess()
def manually_withdraw_success(cls, admin_user, merchant, order_id, channel_cost, comment): """ 完成人工出款 :return: """ withdraw_entry = OrderWithdraw.query_by_order_id(merchant=merchant, order_id=order_id) if not withdraw_entry: return OrderInfoMissingError() if withdraw_entry.state != OrderStateEnum.DEALING: return BankOrderStateError() detail = OrderDetailWithdraw.query_by_order_id( order_id=withdraw_entry.order_id, merchant=merchant, create_time=withdraw_entry.create_time) if not detail: return NosuchOrderDetailDataError() if detail.fee == 0: return WithdrawFeeEmptyError() # 更新订单状态 profit = FeeCalculator.calc_profit(detail.fee, channel_cost) order, ref_id = OrderUpdateCtl.update_order_event( withdraw_entry.order_id, uid=int(withdraw_entry.uid), merchant=merchant, tx_amount=withdraw_entry.amount, state=OrderStateEnum.SUCCESS, deliver_type=DeliverTypeEnum.MANUALLY, op_account=admin_user.account, comment=comment, cost=channel_cost, profit=profit, mch_fee_id=withdraw_entry.mch_fee_id, commit=True) if not order: return WithdrawOrderStateChangeError() cls.do_notify( order=order, op_account=admin_user.account, comment=comment, ) return ResponseSuccess()
def clean_order_table(): # 每天凌晨4点清理数据 from app.main import flask_app print('job clean_order_table running') with flask_app.app_context(): rst = OrderDeposit.clean_hot_table() print(rst) rst = OrderWithdraw.clean_hot_table() print(rst) rst = OrderDetailDeposit.clean_hot_table() print(rst) rst = OrderDetailWithdraw.clean_hot_table() print(rst)
def get(self): """ 检查热表数据 :return: """ if not request.args: return ResponseSuccess( message="参数规则:?merchant=test&date=20190901").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() kwargs = dict( date=date, merchant=merchant, only_hot=request.args.get('only_hot'), only_cold=request.args.get('only_cold'), ) rst = dict( OrderDeposit=OrderDeposit.query_by_date(date, **kwargs).count(), OrderWithdraw=OrderWithdraw.query_by_date(date, **kwargs).count(), OrderDetailDeposit=OrderDetailDeposit.query_by_date( date, **kwargs).count(), OrderDetailWithdraw=OrderDetailWithdraw.query_by_date( date, **kwargs).count(), ) kwargs['merchant'] = merchant.name kwargs['date'] = DateTimeKit.datetime_to_str(date) rst['kwargs'] = kwargs return ResponseSuccess(bs_data=rst).as_response()
def get_order_by_order_id(cls, order_id): """ 根据order id查询订单 :param order_id: :return: """ g_order_id = GlobalOrderId.query_global_id(order_id) if not g_order_id: msg = '无法从 GlobalOrderId 查到订单,order_id: %s' % order_id current_app.config['SENTRY_DSN'] and current_app.logger.fatal( 'msg: %s', msg) return None order = OrderWithdraw.query_by_order_id(merchant=g_order_id.merchant, order_id=order_id) if not order: msg = '无法从 OrderWithdraw 查到订单,order_id: %s' % order_id current_app.config['SENTRY_DSN'] and current_app.logger.fatal( 'msg: %s', msg) return None return order
def post(self): """ 运营代付审核列表: :return: """ form, error = YearMouthForm().request_validate() if error: return error.as_response() # 遍历系统所有商户 begin_time, end_time = DateTimeKit.get_month_begin_end( year=int(form.year.data), month=int(form.mouth.data)) if not MerchantMonthMix.is_valid_shard_date(begin_time): # 查询的时间太早,没有数据,直接返回空列表 return ReviewWithdrawResult(bs_data=dict( entries=[], total=len( []), operator=g.user.account)).as_response() withdraw_list = [] detail_list = OrderDetailWithdraw.query_by_create_time( begin_time=begin_time, end_time=end_time) detail_dict = dict([(o.order_id, o) for o in detail_list]) order_list_query = OrderWithdraw.query_by_create_time( begin_time=begin_time, end_time=end_time) query = order_list_query.filter( or_( OrderWithdraw._state == OrderStateEnum.ALLOC.value, OrderWithdraw._state == OrderStateEnum.DEALING.value, )).all() for order in query: detail_order = detail_dict[order.order_id] if detail_order.op_account != g.user.account: continue bank = order.get_bank_card(valid_check=False) if not bank: current_app.logger.error( 'bank not exit, order.sys_tx_id: %s, order.bank_id: %s, order.bank_info: %s', order.sys_tx_id, order.bank_id, order.bank_info) continue user_flag = UserFlagCache(order.uid).get_flag() withdraw_list.append( dict( uid=order.uid, order_id=order.order_id, sys_tx_id=order.sys_tx_id, merchant=order.merchant.name, source=order.source.desc, state=order.state.desc, amount=order.amount, bank_name=bank.bank_name, bank_type=bank.bank_enum.name, create_time=order.str_create_time, user_flag=user_flag.name if user_flag else None, )) withdraw_list = sorted(withdraw_list, key=lambda item: item['create_time']) return ReviewWithdrawResult( bs_data=dict(entries=withdraw_list, total=len(withdraw_list), operator=g.user.account)).as_response()
def get_user_latest_order(cls, uid, order_type: PayTypeEnum): g_order_id = GlobalOrderId.query_latest_one(uid, order_type) return OrderWithdraw.query_by_order_id(merchant=g_order_id.merchant, order_id=g_order_id.order_id)
def query_withdraw_order_list(cls, form, export=False): """ 查询提现订单列表 :param form: :param export: :return: """ merchant = form.merchant_name.data if not form.begin_time.data: begin_time, end_time = DateTimeKit.get_day_begin_end(DateTimeKit.get_cur_date()) else: begin_time = form.begin_time.data end_time = form.end_time.data kwargs = {} if form.state.data != "0": kwargs["_state"] = form.state.data.value tx_id = form.order_id.data if tx_id: if OrderUtils.is_sys_tx_id(tx_id): kwargs["sys_tx_id"] = tx_id else: kwargs["mch_tx_id"] = tx_id try: order_list = OrderWithdraw.query_by_create_time(begin_time=begin_time, end_time=end_time, merchant=merchant).filter_by(**kwargs) except MultiMonthQueryException: return MultiMonthQueryError().as_response() all_channels = dict([(x.channel_id, x) for x in ChannelConfig.query_all()]) order_detail_dict = dict() order_list = OrderFilters.filter_from_order_list(order_list, filters=[ functools.partial(OrderFilters.filter_tx_id, tx_id), functools.partial(OrderFilters.filter_channel, all_channels, form.channel.data), ]) if order_list: # 订单详情列表 order_detail_list = OrderDetailWithdraw.query_by_create_time(begin_time=begin_time, end_time=end_time, merchant=merchant) # 订单列表和订单详情列表相互过滤 order_list, order_detail_dict = OrderFilters.filter_from_detail_list( order_list, order_detail_list, filters=[ functools.partial( OrderFilters.filter_done_time, form.done_begin_time.data, form.done_end_time.data), ]) # 按时间倒序 order_list = sorted(order_list, key=itemgetter('create_time'), reverse=True) if export and order_list: return CsvOrderExport.export_withdraw_list_csv(order_list, order_detail_dict, all_channels) return cls.render_withdraw_list(form, order_list, order_detail_dict)
def post(self): """ 用户最近一周充值提现交易记录 :return: """ form, error = UserTransactionForm().request_validate() if error: return error.as_response() uid = form.uid.data pay_type = form.pay_type.data page_size = form.page_size.data page_index = form.page_index.data entry = User.query.filter_by(**dict(id=uid)).first() if not entry: return AdjustUserBalanceError(message="系统找不到该用户").as_response() # 获取用户最近一周的充值提现记录 query_datetime_lst = [] c_date = DateTimeKit.get_cur_datetime() s_date = c_date + DateTimeKit.time_delta(days=-7) if not DateTimeKit.is_same_month(s_date, DateTimeKit.get_cur_datetime()): _, e_m_date = DateTimeKit.get_month_begin_end(year=s_date.year, month=s_date.month) s_m_date, _ = DateTimeKit.get_month_begin_end(year=c_date.year, month=c_date.month) s_date, _ = DateTimeKit.get_day_begin_end(s_date) query_datetime_lst.append([s_date, e_m_date]) query_datetime_lst.append([s_m_date, c_date]) else: s_date, _ = DateTimeKit.get_day_begin_end(s_date) query_datetime_lst.append([s_date, c_date]) order_list = [] for s_e_date in query_datetime_lst: if pay_type == PayTypeEnum.DEPOSIT: base_order = OrderDeposit.query_by_create_time( begin_time=s_e_date[0], end_time=s_e_date[1], merchant=entry.merchant).filter_by(**dict( uid=entry.uid)).all() # order_detail = OrderDetailDeposit.query_by_create_time(begin_time=s_e_date[0], # end_time=s_e_date[1], # merchant=entry.merchant).filter_by( # uid=entry.uid).all() # detail_dict = [{detail.order_id: detail} for detail in order_detail] [ order_list.append( dict(mch_tx_id=item.mch_tx_id, sys_tx_id=item.sys_tx_id, pay_method=item.pay_method.desc, amount=item.amount, tx_amount=item.tx_amount, create_time=item.str_create_time, state=item.state.get_back_desc( PayTypeEnum.DEPOSIT))) for item in base_order ] elif pay_type == PayTypeEnum.WITHDRAW: base_order = OrderWithdraw.query_by_create_time( begin_time=s_e_date[0], end_time=s_e_date[1], merchant=entry.merchant).filter_by(**dict( uid=entry.uid)).all() detail_order = OrderDetailWithdraw.query_by_create_time( begin_time=s_e_date[0], end_time=s_e_date[1], merchant=entry.merchant).filter_by(**dict( uid=entry.uid)).all() detail_dict = { detail.order_id: detail for detail in detail_order } bank_lst = [order.bank_id for order in base_order] bank_info = BankCard.query.filter( BankCard.id.in_(bank_lst)).all() bank_dct = {bank.id: bank for bank in bank_info} [ order_list.append( dict(mch_tx_id=item.mch_tx_id, sys_tx_id=item.sys_tx_id, amount=item.amount, fee=detail_dict[item.order_id].fee, bank_name=bank_dct[item.bank_id].bank_name, card_no=bank_dct[ item.bank_id].card_no_short_description, state=item.state.get_back_desc( PayTypeEnum.WITHDRAW), done_time=item.update_time, create_time=item.str_create_time)) for item in base_order ] items, total = Pagination.paginate_list(items=order_list, page_index=page_index, page_size=page_size, sort_key="create_time") if pay_type == PayTypeEnum.WITHDRAW: return UserDepositResult(bs_data=dict( depositInfo=dict(entries=[], total=0), withdrawInfo=dict(entries=items, total=total))).as_response() elif pay_type == PayTypeEnum.DEPOSIT: return UserDepositResult(bs_data=dict( depositInfo=dict(entries=items, total=total), withdrawInfo=dict(entries=[], total=0))).as_response()
def post(self): """ 商户提现订单查询 :return: """ form, error = WithdrawOrderSelectForm().request_validate() if error: return error.as_response() user = g.user try: order_list_query = OrderWithdraw.query_by_create_time( begin_time=form.start_datetime.data, end_time=form.end_datetime.data, merchant=MerchantEnum(user.mid)) except MultiMonthQueryException as e: return MultiMonthQueryError().as_response() kwargs = {} if form.order_id.data: kwargs["mch_tx_id"] = form.order_id.data if form.state.data != "0": kwargs["_state"] = form.state.data.value entries = order_list_query.filter_by(**kwargs).all() bank_lst = list(set([o.bank_id for o in entries])) kwargs = {} if form.order_id.data and entries: kwargs['id'] = entries[0].order_id if not MerchantEnum(user.mid).is_api_merchant: bank_items = { bank.id: bank for bank in BankCard.query.filter(BankCard.id.in_( bank_lst)).all() } order_items = { item.id: item for item in OrderDetailWithdraw.query_by_create_time( begin_time=form.start_datetime.data, end_time=form.end_datetime.data, merchant=MerchantEnum(user.mid)).filter_by(**kwargs).all() } items = [] for order in entries: if not MerchantEnum(user.mid).is_api_merchant: bank = bank_items.get(order.bank_id, {}) else: bank = order.get_bank_card() detail = order_items.get(order.order_id, {}) if not bank or not detail: continue items.append( dict(mch_tx_id=order.mch_tx_id, sys_tx_id=order.sys_tx_id, amount=detail.amount, fee=detail.fee, account_name=bank.account_name, bank_name=bank.bank_name, branch="{}{}{}".format(bank.province, bank.city, bank.branch), card_no=bank.card_no, create_time=order.str_create_time, done_time=order.update_time, state=order.state.desc, deliver=order.deliver.desc)) items = sorted(items, key=lambda item: item['create_time']) if items: data = list() for item in items: data.append({ "商户订单号": item['mch_tx_id'], "提现金额": str(item['amount']), "手续费": str(item['fee']), "开户名": item['account_name'], "开户银行": item['bank_name'], "开户地址": item['branch'], "银行卡号": item['card_no'], "创建时间": item['create_time'], "完成时间": item['done_time'], "订单状态": item['state'], "通知状态": item['deliver'] }) filename = 'epay_withdraw_record_%s.csv' % ( DateTimeKit.datetime_to_str( DateTimeKit.get_cur_datetime(), DateTimeFormatEnum.TIGHT_DAY_FORMAT)) return CsvKit.send_csv(data, filename=filename, fields=data[0].keys())
def post(self): """ 商户提现订单查询 :return: """ form, error = WithdrawOrderSelectForm().request_validate() if error: return error.as_response() user = g.user try: order_list_query = OrderWithdraw.query_by_create_time( begin_time=form.start_datetime.data, end_time=form.end_datetime.data, merchant=MerchantEnum(user.mid)) except MultiMonthQueryException as e: return MultiMonthQueryError().as_response() kwargs = {} tx_id = form.order_id.data if tx_id: if OrderUtils.is_sys_tx_id(tx_id): kwargs["sys_tx_id"] = tx_id else: kwargs["mch_tx_id"] = tx_id if form.state.data != "0": kwargs["_state"] = form.state.data.value query = order_list_query.filter_by(**kwargs) pagination = query.paginate(form.page_index.data, form.page_size.data, False) entries = pagination.items total = pagination.total bank_lst = list(set([o.bank_id for o in entries])) kwargs = {} if tx_id and entries: kwargs['id'] = entries[0].order_id bank_items = dict() if not MerchantEnum(user.mid).is_api_merchant: bank_items = { bank.id: bank for bank in BankCard.query.filter(BankCard.id.in_( bank_lst)).all() } order_items = { item.id: item for item in OrderDetailWithdraw.query_by_create_time( begin_time=form.start_datetime.data, end_time=form.end_datetime.data, merchant=MerchantEnum(user.mid)).filter_by(**kwargs).all() } items = [] for order in entries: if not MerchantEnum(user.mid).is_api_merchant: bank = bank_items.get(order.bank_id, {}) else: bank = order.get_bank_card() detail = order_items.get(order.order_id, {}) if not bank or not detail: continue items.append( dict(mch_tx_id=order.mch_tx_id, sys_tx_id=order.sys_tx_id, amount=detail.amount, fee=detail.fee, account_name=bank.account_name, bank_name=bank.bank_name, branch="{}{}{}".format(bank.province, bank.city, bank.branch), card_no=bank.card_no, create_time=order.str_create_time, done_time=order.update_time, state=order.state.desc, deliver=order.deliver.desc)) items = sorted(items, key=lambda item: item['create_time']) return MerchantWithdrawOrderResult( bs_data=dict(entries=items, total=total)).as_response()
def manually_withdraw_failed(cls, admin_user, merchant, order_id): """ 手动更新提款状态为失败 退款/审核拒绝 流程: 1. 获取创建订单时 扣除 用户及商户的费用 获取订单 withdrawOrderDetail 数据, 获取 手续费 提现金额 2. 给用户和商户新增费用 更新 UserBalance 表 更新 MerchantBalance表 3. 修改订单状态 更新 OrderUpdateCtl :param admin_user: :param merchant: :param order_id: :return: """ # 查询该笔订单是否存在 withdraw_entry = OrderWithdraw.query_by_order_id(merchant=merchant, order_id=order_id) # 判断是否存在 if not withdraw_entry: return OrderInfoMissingError() # 判断订单状态是否为 已认领 或 提现成功 if withdraw_entry.state not in [ OrderStateEnum.ALLOC, OrderStateEnum.SUCCESS ]: return BankOrderStateError() detail = OrderDetailWithdraw.query_by_order_id( order_id=withdraw_entry.order_id, merchant=merchant, create_time=withdraw_entry.create_time) if not detail: return NosuchOrderDetailDataError() # 提现订单 手续费 提现订单费用 fee = detail.fee amount = detail.amount comment = "出款失败" if withdraw_entry.state == OrderStateEnum.SUCCESS else "系统拒绝" order_type = PayTypeEnum.REFUND if withdraw_entry.state == OrderStateEnum.SUCCESS else PayTypeEnum.MANUALLY merchant_config = MerchantFeeConfig.query_by_config_id( withdraw_entry.mch_fee_id) # 更新订单状态 try: with db.auto_commit(): order, ref_id = OrderUpdateCtl.update_order_event( withdraw_entry.order_id, uid=int(withdraw_entry.uid), merchant=merchant, state=OrderStateEnum.FAIL, tx_amount=withdraw_entry.amount, deliver_type=DeliverTypeEnum.MANUALLY, op_account=admin_user.account, commit=False) if not order: msg = WithdrawOrderStateChangeError.message current_app.logger.error(msg) raise WithdrawOrderStateChangeError() # 加提现金额 flag, msg = MerchantBalanceEvent.update_balance( merchant=merchant, ref_id=ref_id, order_type=order_type, bl_type=BalanceTypeEnum.AVAILABLE, value=amount, ad_type=BalanceAdjustTypeEnum.PLUS, tx_id=order.sys_tx_id, source=OrderSourceEnum.MANUALLY, comment=comment, commit=False, ) if flag < 0: msg = '%s' % ("提现退回增加商户余额失败, %s" % msg) current_app.logger.error(msg) raise DepositCallbackUserBalanceError() if merchant_config.cost_type == CostTypeEnum.MERCHANT: # 给商户加手续费 flag, msg = MerchantBalanceEvent.update_balance( merchant=merchant, ref_id=OrderUtils.gen_unique_ref_id(), order_type=PayTypeEnum.FEE, bl_type=BalanceTypeEnum.AVAILABLE, value=fee, ad_type=BalanceAdjustTypeEnum.PLUS, tx_id=order.sys_tx_id, commit=False, comment=comment, source=OrderSourceEnum.MANUALLY) if flag < 0: msg = '%s' % ("提现退款增加商户手续费失败, %s" % msg) current_app.logger.error(msg) raise DepositCallbackUserBalanceError() refund_fee = amount if merchant_config.cost_type == CostTypeEnum.USER: # 给用户退回手续费 refund_fee += fee # 增加用户余额 flag, msg = UserBalanceEvent.update_user_balance( uid=order.uid, merchant=merchant, ref_id=ref_id, order_type=order_type, bl_type=BalanceTypeEnum.AVAILABLE, value=refund_fee, ad_type=BalanceAdjustTypeEnum.PLUS, tx_id=order.sys_tx_id, commit=False, comment=comment, source=OrderSourceEnum.MANUALLY) if flag < 0: msg = '%s' % ("提现退款增加用户余额失败, %s" % msg) current_app.logger.error(msg) raise DepositCallbackUserBalanceError() except APIException as e: current_app.logger.error(traceback.format_exc()) return e cls.do_notify( order=order, op_account=admin_user.account, comment=comment, ) return ResponseSuccess()
def order_deal(cls, admin_account, order_id, merchant, channel_id, test=False): """ :param admin_account: :param order_id: :param merchant: :param channel_id: :param test: 单元测试填写 :return: """ params = copy.deepcopy(locals()) params.pop('cls') if EnvironEnum.is_production(current_app.config['FLASK_ENV']) and test: # 非调试环境不该填写 channel_tx_id,应该发送请求到第三方去申请 raise RuntimeError('invalid test param') order = OrderWithdraw.query_by_order_id(merchant, order_id) if not order: msg = '%s, params: %s' % (NoSuchWithdrawOrderError.message, params) current_app.logger.error(msg) return NoSuchWithdrawOrderError() if order.state != OrderStateEnum.ALLOC: msg = '%s, params: %s, state: %s, tx_id: %s' % ( NotAllocOrderError.message, params, order.state.desc, order.sys_tx_id) current_app.logger.error(msg) return NotAllocOrderError(message=NotAllocOrderError.message + ", 订单状态:" + order.state.desc) channel_config = ProxyChannelConfig.query_by_channel_id(channel_id) if not channel_config: msg = '%s, params: %s' % (InvalidChannelError.message, params) current_app.logger.error(msg) return InvalidChannelError() bank_card = order.get_bank_card() if not bank_card: msg = '%s, params: %s' % (WithdrawBankNoExistError.message, params) current_app.logger.error(msg) return WithdrawBankNoExistError() # 开始更新订单,根据通道计算费率和成本 # 通道收取的手续费 channel_cost = FeeCalculator.calc_cost(order.amount, channel_config.fee_type, channel_config.fee) tx_amount = order.amount channel_enum = channel_config.channel_enum if channel_enum.plus_fee_for_withdraw(): # 特殊通道,要发起金额要加上手续费,通道测扣除手续费才是实际到账金额 # 实际提款金额=发起金额+通道手续费 tx_amount += channel_cost # 发起支付 launch_pay = channel_enum.get_launch_pay_func(PayTypeEnum.WITHDRAW) if not test: # 第三方返回由第三方生成交易ID:channel_tx_id rst = launch_pay( dict(order_id=order.order_id, tx_id=order.sys_tx_id, amount=tx_amount, channel_cost=channel_cost, bank_code=bank_card.bank_code, bank_name=bank_card.bank_name, bank_account=bank_card.account_name, bank_number=bank_card.card_no, bank_address=bank_card.bank_address, bank_branch=bank_card.branch, province=bank_card.province, city=bank_card.city)) current_app.logger.info('withdraw launch_pay, params: %s, rst: %s', params, rst) if rst['code'] != 0: # 不要改变订单状态,让客服去选择其它通道重试 # cls.order_fail(order, client_ip) current_app.logger.error( '%s, %s, params: %s' % (FailedLaunchWithdrawError.message, rst['msg'], params)) return FailedLaunchWithdrawError(message=rst['msg']) # 发起成功后更新状态为处理中 order, _ = OrderUpdateCtl.update_order_event( order.order_id, uid=order.uid, merchant=merchant, state=OrderStateEnum.DEALING, channel_id=channel_id, cost=channel_cost, deal_time=DateTimeKit.get_cur_datetime(), op_account=admin_account, ) if not order: msg = '%s, params: %s' % (WithdrawUpdateDealingError.message, params) current_app.logger.error(msg) return WithdrawUpdateDealingError() return ResponseSuccess()
def post(self): """ 提现订单详情 :return: """ form, error = WithDrawBankForm().request_validate() if error: return error.as_response() order_id = form.order_id.data order_map = GlobalOrderId.query_global_id(order_id) merchant = order_map.merchant entry = OrderWithdraw.query_by_order_id(order_id=order_id, merchant=merchant) detail = OrderDetailWithdraw.query_by_order_id(merchant=merchant, order_id=order_id) detail_head = dict(source=entry.source.desc, op_account=detail.op_account, deliver_type=detail.deliver_type.desc if detail.deliver_type else None, create_time=entry.str_create_time, alloc_time=detail.str_alloc_time, deal_time=detail.str_deal_time, done_time=detail.str_done_time, mch_tx_id=entry.mch_tx_id, sys_tx_id=entry.sys_tx_id, state=entry.state.get_back_desc( PayTypeEnum.WITHDRAW), settle=entry.settle.desc, deliver=entry.deliver.desc, amount=entry.amount) order_merchant_info = dict( merchant_name=merchant.name, fee=detail.fee, cost=detail.cost, profit=detail.profit, withdraw_type="测试" if merchant.is_test else "用户提现") deliver_info = None if entry.channel_id: proxy_entry = ProxyChannelConfig.query_by_channel_id( entry.channel_id) channel_enum = proxy_entry.channel_enum deliver_info = dict(channel_name=channel_enum.desc, mch_id=channel_enum.conf['mch_id'], channel_tx_id=entry.channel_tx_id) user_info = dict( user_id=entry.uid, ip=detail.ip, location=GeoIpKit(detail.ip).location, device="", ) event_entries = OrderEvent.query_model( query_fields=dict(order_id=entry.order_id), date=entry.create_time) event_log_list = list() for event in event_entries: order_event = event.data_after[0] order_event.update(event.data_after[1]) if 'state' in order_event: state = list(order_event['state'].keys())[0] event_log_list.append( dict( operate_type=OrderStateEnum.from_name( state).get_back_desc(PayTypeEnum.WITHDRAW), operator=order_event.get('op_account') or '', result="成功", operate_time=DateTimeKit.timestamp_to_datetime( order_event['update_time']), comment=order_event.get('comment') or '', )) if 'deliver' in order_event: deliver = list(order_event['deliver'].keys())[0] event_log_list.append( dict( operate_type=DeliverStateEnum.from_name(deliver).desc, operator=order_event.get('op_account') or '', result="成功", operate_time=DateTimeKit.timestamp_to_datetime( order_event['update_time']), comment=order_event.get('comment') or '', )) return WithdrawOrderDetailResult( bs_data=dict(detail_head=detail_head, order_merchant_info=order_merchant_info, deliver_info=deliver_info, user_info=user_info, event_log_list=event_log_list)).as_response()