def post(self): """ 后台配置信息 :return: """ # 获取 充值通道信息 channel_list = [] channels = ChannelConfig.query_all() channels = ChannelConfig.filter_latest_items(channels) for channel in channels: channel_enum = channel.channel_enum channel_list.append( dict(desc=channel_enum.desc, value=channel_enum.value)) # 获取商户数据 merchant_list = [ dict(desc=m.name, value=m.value) for m in MerchantEnum ] # 获取支付类型 payment_type_list = [ dict(desc=p.desc, value=p.value) for p in PaymentTypeEnum ] return BackOfficeConfigResult( bs_data=dict(merchant=merchant_list, payment_type=payment_type_list, deposit_channel=channel_list)).as_response()
def __update_channel(self, data, latest, count): ChannelConfig.update_channel(**data) channels = ChannelConfig.query_all() self.assertEqual(count, len(channels)) all_configs = list(ChannelConfig.filter_latest_items(channels)) self.assertEqual(latest, len(all_configs))
def get(self): """ 立马付充值回调 :return: """ if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']): # 无论如何都记录一条log current_app.logger.info( 'ponypay withdraw callback, ip: %s, data: %s', IpKit.get_remote_ip(), request.args) form, error = PonyPayWithdrawForm().request_validate() if error: current_app.logger.fatal('msg: %s, data: %s', error.message, request.args) return BaseResponse('FAIlURE') # 交易订单id tx_id = form.corderid.data # 实际支付金额 tx_amount = Decimal(form.money.data) # 订单状态: 成功/失败 status = form.status.data # 签名 sign = form.sign.data # 客户端IP client_ip = form.client_ip.data order = WithdrawTransactionCtl.get_order(tx_id) if not order: return BaseResponse('FAIlURE') channel_config = ChannelConfig.query_by_channel_id(order.channel_id) controller = WithdrawCallbackPonypay(channel_config.channel_enum) # IP白名单校验 if not controller.check_ip(client_ip): current_app.logger.fatal('ip not allow, client_ip: %s, data: %s', client_ip, request.args) return BaseResponse('FAIlURE') # 签名验证 if not controller.check_sign(tx_id, tx_amount, sign): current_app.logger.fatal('invalid sign, client_ip: %s, data: %s', client_ip, request.args) return BaseResponse('FAIlURE') if status == '1': # 支付成功 if not WithdrawTransactionCtl.order_success(order, tx_amount): return BaseResponse('FAIlURE') else: # 支付失败 if not WithdrawTransactionCtl.order_fail(order): return BaseResponse('FAIlURE') return BaseResponse('SUCCESS')
def post(self): """ 通道管理: 新建通道 :return: """ form, error = ChannelAddForm().request_validate() if error: return error.as_response() # if form.start_time.data >= form.end_time.data: # return DateStartMoreThanError().as_response() if form.maintain_begin.data: if form.maintain_begin.data >= form.maintain_end.data or form.maintain_begin.data < DateTimeKit.get_cur_datetime( ): return DateStartMoreThanError().as_response() if Decimal(form.limit_per_min.data) >= Decimal( form.limit_per_max.data): return DataStartMoreThanError().as_response() if form.limit_day_max.data and Decimal( form.limit_per_max.data) > Decimal(form.limit_day_max.data): return PerLimitMustLittleDayLimitError().as_response() kwargs = dict(fee=form.fee.data, fee_type=form.fee_type.data, limit_per_min=form.limit_per_min.data, limit_per_max=form.limit_per_max.data, limit_day_max=form.limit_day_max.data if form.limit_day_max.data != "" else 0, trade_begin_hour=form.start_time.data.hour, trade_begin_minute=form.start_time.data.minute, trade_end_hour=form.end_time.data.hour, trade_end_minute=form.end_time.data.minute, maintain_begin=form.maintain_begin.data, maintain_end=form.maintain_end.data, settlement_type=form.settlement_type.data, state=form.state.data, priority=form.priority.data) rst, error = ChannelConfig.update_channel(form.channel_id.data, **kwargs) if error: return error.as_response() # 同步缓存 # ChannelLimitCacheCtl(PayTypeEnum.DEPOSIT).sync_db_channels_to_cache() return ResponseSuccess().as_response()
def get(self): """ 查询可用的通道 :return: """ if not request.args: return ResponseSuccess( message="参数规则:?tx_id=xxxx,交易ID,必填").as_response() try: tx_id = request.args['tx_id'] except: return ResponseSuccess(message="必填交易ID").as_response() order = OrderDeposit.query_by_tx_id(tx_id) if not order: return ResponseSuccess(message="订单不存在,请确认交易号是否正确: %s" % tx_id).as_response() order_detail = OrderDetailDeposit.query_by_tx_id(tx_id) channel = ChannelConfig.query_by_channel_id(order.channel_id) fee_config = MerchantFeeConfig.query_by_config_id(order.mch_fee_id) order_info = dict( order_id=order.order_id, create_time=order.str_create_time, uid=order.uid, sys_tx_id=order.sys_tx_id, mch_tx_id=order.mch_tx_id, channel_tx_id=order.channel_tx_id, amount=str(order.amount), tx_amount=str(order.tx_amount), source=order.source.desc, pay_method=order.pay_method.desc, state=order.state.desc, settle=order.settle.desc, deliver=order.deliver.desc, channel_id=order.channel_id, channel=channel.short_description, mch_fee_id=order.mch_fee_id, mch_fee=fee_config.short_description, in_type=order_detail.in_type.desc, offer=str(order_detail.offer), fee=str(order_detail.fee), cost=str(order_detail.cost), profit=str(order_detail.profit), ip=order_detail.ip, ) return ResponseSuccess(bs_data=order_info).as_response()
def do_ponypay_withdraw_callback(self, status): amount = tx_amount = Decimal("100.25") # 生成一个可以回调的订单 order = InitData.init_withdraw_order_deal(amount) channel_config = ChannelConfig.query_by_channel_id(order.channel_id) controller = WithdrawCallbackPonypay(channel_config.channel_enum) sign = controller.generate_sign(order.sys_tx_id, tx_amount) self.path = "/callback/ponypay/withdraw" params = """merchant_id={}&corderid={}&money={}&status={}&sign={}""".format( controller.third_config['mch_id'], order.sys_tx_id, tx_amount, status, sign, ) response = self.do_get_request(params=params) self.assertEqual(200, response.status_code) self.assertEqual("SUCCESS", response.data.decode("utf-8"))
def __test_api_channel(self): # 充值通道管理 新增通道 channel_enum = ChannelConfigEnum.CHANNEL_1001 post_data = dict(channel_id=channel_enum.value, fee="2.3", fee_type="1", limit_per_min="2000", limit_per_max="50000", limit_day_max="50000", start_time="09:00", end_time="23:59", state="10", settlement_type="1", priority="1") post_data["state"] = 10 # 数值型参数类型错误 self.path = '/channel/deposit/add' response = self.do_request(post_data) self.assertEqual(response.status_code, ParameterException.code) self.assertEqual(response.json['error_code'], ParameterException.error_code) # print(response.json['message'], "this field must be String type") post_data["state"] = "10" # 测试交易日期为空的情况 response = self.do_request(post_data) print(response.json) self.assertEqual(ResponseSuccess.code, response.status_code, response.json['message']) self.assertEqual(ResponseSuccess.error_code, response.json['error_code'], response.json['message']) # print(response.json['message'], "this field must be String type") post_data['maintain_begin'] = "2019-09-27 09:10:00" post_data['maintain_end'] = "2019-10-20 23:09:00" # 测试每笔交易上限大于日交易上限 post_data['limit_day_max'] = "40000" response = self.do_request(post_data) print(response.json) self.assertEqual(PerLimitMustLittleDayLimitError.code, response.status_code) self.assertEqual(PerLimitMustLittleDayLimitError.error_code, response.json['error_code']) # print(response.json['message'], "this field must be String type") # self.assertEqual(response.json['message'], "单笔交易最大值必须小于当日交易限额") post_data['limit_day_max'] = "60000" # 时间类型参数业务数据不对 post_data["maintain_begin"] = "2020-08-23 09:30:00" response = self.do_request(post_data) self.assertEqual(response.status_code, DateStartMoreThanError.code) self.assertEqual(response.json['error_code'], DateStartMoreThanError.error_code) self.assertEqual(response.json['message'], DateStartMoreThanError.message) post_data["maintain_begin"] = "2019-09-27 09:00:00" # 业务类型数据不对 post_data["limit_per_min"] = "100000" response = self.do_request(post_data) self.assertEqual(response.status_code, DataStartMoreThanError.code) self.assertEqual(response.json['error_code'], DataStartMoreThanError.error_code) self.assertEqual(response.json['message'], DataStartMoreThanError.message) post_data["limit_per_min"] = "2000" # 时间类型数据格式错误 post_data["maintain_begin"] = "2019/09/27 09:00:00" response = self.do_request(post_data) self.assertEqual(response.status_code, ParameterException.code) self.assertEqual(response.json['error_code'], ParameterException.error_code) # self.assertEqual(response.json['message'], "无效的时间格式") post_data["maintain_begin"] = "2019-09-27 09:00:00" # 测试成功添加数据 response = self.do_request(post_data) self.assertEqual(response.status_code, ResponseSuccess.code) channel = ChannelConfig.query_latest_one( dict(channel_enum=channel_enum)) self.assertEqual(channel.channel_enum.value, post_data['channel_id']) self.assertEqual(channel.settlement_type.value, int(post_data['settlement_type'])) # 渠道管理:编辑通道 self.path = '/channel/deposit/edit' post_data['settlement_type'] = '3' response = self.do_request(post_data) self.assertEqual(response.status_code, ResponseSuccess.code) channel = ChannelConfig.query_latest_one( dict(channel_enum=channel_enum)) self.assertEqual(channel.channel_enum.value, post_data['channel_id']) self.assertEqual(channel.settlement_type.value, 3) # 测试 不支持的 枚举类型数据 self.path = '/channel/deposit/edit' post_data['state'] = '110' response = self.do_request(post_data) self.assertEqual(response.status_code, ParameterException.code) self.assertEqual(response.json['error_code'], ParameterException.error_code) # self.assertEqual(response.json['message'], "无效的通道状态") post_data['state'] = "10" # 代付通道管理: 新增代付通道 self.path = "/channel/withdraw/add" withdraw_postdata = dict(channel_id=channel_enum.value, fee="2.3", fee_type="1", limit_per_min="2000", limit_per_max="50000", limit_day_max="50000", start_time="09:00", end_time="23:59", maintain_begin="2019-09-27 09:00:00", maintain_end="2019-10-20 23:00:00", state="10", banks=["1", "2", "4", "6", "3", "5", "15"]) # 测试参数类型错误 withdraw_postdata['channel_id'] = '123' response = self.do_request(withdraw_postdata) self.assertEqual(response.status_code, ParameterException.code) self.assertEqual(response.json['error_code'], ParameterException.error_code) # self.assertEqual(response.json['message'], str({'channel_id': 'this field must be Integer type'})) # 测试时间格式错误 withdraw_postdata['channel_id'] = channel_enum.value withdraw_postdata["maintain_begin"] = "2019/09/27 09:00:00" response = self.do_request(withdraw_postdata) self.assertEqual(response.status_code, ParameterException.code) self.assertEqual(response.json['error_code'], ParameterException.error_code) # self.assertEqual(response.json['message'], "无效的时间格式") withdraw_postdata["maintain_begin"] = "2019-09-27 09:00:00" # 测试成功添加代付通道 ProxyChannelConfig.delete_all() response = self.do_request(withdraw_postdata) self.assertEqual(response.status_code, ResponseSuccess.code) self.assertEqual(response.json['error_code'], ResponseSuccess.error_code) channel = ProxyChannelConfig.query_latest_one( dict(channel_enum=channel_enum)) self.assertEqual(withdraw_postdata['maintain_begin'], DateTimeKit.datetime_to_str(channel.maintain_begin)) self.assertEqual(withdraw_postdata['channel_id'], channel.channel_enum.value) # 测试编辑 代付通道 self.path = "/channel/withdraw/edit" withdraw_postdata['banks'] = ["4", "6", "3"] withdraw_postdata['limit_day_max'] = '180000' withdraw_postdata['maintain_begin'] = "2019-10-30 09:30:01" withdraw_postdata['maintain_end'] = "2019-12-30 09:30:01" response = self.do_request(withdraw_postdata) self.assertEqual(response.status_code, ResponseSuccess.code) self.assertEqual(response.json['error_code'], ResponseSuccess.error_code) channel = ProxyChannelConfig.query_latest_one( dict(channel_enum=channel_enum)) self.assertEqual(channel_enum.value, channel.channel_enum.value) self.assertEqual(withdraw_postdata['maintain_begin'], DateTimeKit.datetime_to_str(channel.maintain_begin)) self.assertEqual(withdraw_postdata['maintain_end'], DateTimeKit.datetime_to_str(channel.maintain_end)) self.assertEqual( [PaymentBankEnum(4), PaymentBankEnum(6), PaymentBankEnum(3)], channel.banks) self.assertEqual(180000, channel.limit_day_max) # 测试代付列表 self.path = "/channel/withdraw/list" response = self.do_request() self.assertEqual(response.status_code, ResponseSuccess.code) self.assertEqual(response.json['error_code'], ResponseSuccess.error_code) self.assertEqual('1', response.json['data']['counts']) self.assertEqual(channel_enum.value, response.json['data']['withdraws'][0]['channel_id']) ProxyChannelConfig.delete_all()
def post(self): """ 充值通道列表 :return: """ router2_dict = ChannelListHelper.get_router2_dict() channel_list = [] channels = ChannelConfig.query_all() channels = ChannelConfig.filter_latest_items(channels) for channel in channels: channel_enum = channel.channel_enum channel_conf = channel_enum.conf merchants = list() router = router2_dict.get(channel_enum) if router: merchants = router.merchants channel_list.append( dict( channel_id=channel_enum.value, channel_desc=channel_enum.desc, id=channel_conf['mch_id'], provider=channel_conf['provider'], payment_type=dict(desc=PaymentTypeEnum( channel_conf['payment_type']).desc, value=PaymentTypeEnum( channel_conf['payment_type']).value), payment_method=dict( desc=PayMethodEnum( channel_conf['payment_method']).desc, value=PayMethodEnum( channel_conf['payment_method']).value), fee=channel.fee, fee_type=dict( desc=PaymentFeeTypeEnum(channel.fee_type).desc, value=PaymentFeeTypeEnum(channel.fee_type).value), limit_per_min=channel.limit_per_min, limit_per_max=channel.limit_per_max, limit_day_max=channel.limit_day_max, settlement_type=dict( key=SettleTypeEnum(channel.settlement_type).value, value=SettleTypeEnum(channel.settlement_type).name), trade_start_time=":".join([ str(channel.trade_begin_hour), str(channel.trade_begin_minute) ]), # trade_start_time=dict(trade_begin_hour=channel.trade_begin_hour, # trade_begin_minute=channel.trade_begin_minute), trade_end_time=":".join([ str(channel.trade_end_hour), str(channel.trade_end_minute) ]), # trade_end_time=dict(trade_end_hour=channel.trade_end_hour, # trade_end_minute=channel.trade_end_minute), main_time=dict(maintain_begin=channel.maintain_begin if channel.maintain_begin else None, maintain_end=channel.maintain_end if channel.maintain_end else None), state=dict(desc=channel.state.desc, value=channel.state.value), reason=channel.get_reason_desc(), priority=channel.priority, merchants=[x.name for x in merchants], )) channel_list = sorted(channel_list, key=lambda item: item['state']['value']) data = dict(counts=len(channel_list), channels=channel_list) return ChannelListResult(bs_data=data).as_response()
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表单验证用提款的 form, error = WithDrawBankForm().request_validate() if error: return error.as_response() # 取得订单id order_id = form.order_id.data # 根据订单id获取对应的商户 用户id order_map = GlobalOrderId.query_global_id(order_id) # 获取商户id merchant = order_map.merchant # 根据商户id 订单id查询具体的订单信息 entry = OrderDeposit.query_by_order_id(order_id=order_id, merchant=merchant) # 查询对应的订单详情表 detail = OrderDetailDeposit.query_by_order_id(merchant=merchant, order_id=order_id) # 拼接返回数据 detail_head = dict( source=entry.source.desc, create_time=entry.str_create_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.DEPOSIT), settle=entry.settle.desc, deliver=entry.deliver.desc, amount=entry.amount, ) order_merchant_info = dict(merchant_name=merchant.name, offer=detail.offer, fee=detail.fee, cost=detail.cost, profit=detail.profit) deliver_info = None if entry.channel_id: proxy_entry = ChannelConfig.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.DEPOSIT), 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 DepositOrderDetailResult(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()
def success_order_process(cls, order, tx_amount, channel_tx_id=None, comment: str = '', op_account=None, commit=True): """ 处理充值成功的订单 :param order: :param tx_amount: 实际支付金额 :param channel_tx_id: 通道订单号 :param comment: 备注 :param op_account: 备注 :param commit: 是否立即提交事务 :return: """ params = copy.deepcopy(locals()) params.pop('cls') params.pop('order') params['tx_id'] = order.sys_tx_id rst = dict( code=0, msg='', ) # 计算一笔订单的各种费用 channel_config = ChannelConfig.query_by_channel_id(order.channel_id) merchant_config = MerchantFeeConfig.query_by_config_id( order.mch_fee_id) order_fee = OrderFeeHelper.calc_order_fee(order, tx_amount, channel_config, merchant_config) try: with db.auto_commit(commit): order, ref_id = OrderUpdateCtl.update_order_event( order.order_id, uid=order.uid, merchant=order.merchant, state=OrderStateEnum.SUCCESS, channel_tx_id=channel_tx_id, tx_amount=tx_amount, offer=order_fee['offer'], # 优惠金额 fee=order_fee['merchant_fee'], # 手续费 cost=order_fee['channel_cost'], # 成本金额 profit=order_fee['profit'], # 利润(收入)金额 commit=False, pay_method=channel_config.channel_enum. conf['payment_method'], comment=comment, op_account=op_account, ) if not order: msg = '订单更新失败, params: %s' % params raise RuntimeError(msg) # 给用户充值 code, msg = UserBalanceEvent.update_user_balance( uid=order.uid, merchant=order.merchant, ref_id=ref_id, source=order.source, order_type=order.order_type, bl_type=BalanceTypeEnum.AVAILABLE, value=order.amount, ad_type=BalanceAdjustTypeEnum.PLUS, comment=comment, tx_id=order.sys_tx_id, commit=False, ) if code != 0: raise RuntimeError(msg) # 根据结算类型获取商户余额变更类型 balance_type = SettleHelper.get_balance_type_by_settle( channel_config.settlement_type) # 更新商户余额,加用户充值金额 code, msg = MerchantBalanceEvent.update_balance( merchant=order.merchant, ref_id=ref_id, source=order.source, order_type=order.order_type, bl_type=balance_type, value=order.amount, ad_type=BalanceAdjustTypeEnum.PLUS, tx_id=order.sys_tx_id, comment=comment, commit=False, ) if code != 0: raise RuntimeError(msg) # 更新商户余额,扣手续费 ref_id = OrderUtils.gen_unique_ref_id() code, msg = MerchantBalanceEvent.update_balance( merchant=order.merchant, ref_id=ref_id, source=order.source, order_type=PayTypeEnum.FEE, bl_type=balance_type, value=order_fee['merchant_fee'], ad_type=BalanceAdjustTypeEnum.MINUS, tx_id=order.sys_tx_id, comment=comment, commit=False, ) if code != 0: raise RuntimeError(msg) except RuntimeError as e: current_app.logger.error('An error occurred.', exc_info=True) return False # 累计当天通道充值额度 ChannelLimitCacheCtl.add_day_amount(channel_config.channel_enum, order.amount) cls.do_notify(order) return True
def get_deposit_channel2(cls): return ChannelConfig.query_latest_one(query_fields=dict( channel_enum=cls.channel_enum2))
def init_channel2(cls): if not cls.get_deposit_channel2(): # 充值通道配置 kwargs = dict(fee="2.5", fee_type=PaymentFeeTypeEnum.PERCENT_PER_ORDER, limit_per_min="500", limit_per_max="20000", trade_begin_hour="0", trade_begin_minute="0", trade_end_hour="0", trade_end_minute="0", 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 if cls.merchant.is_test else ChannelStateEnum.ONLINE, priority="101") ChannelConfig.update_channel(cls.channel_enum2, **kwargs) channel_config = ChannelConfig.query_latest_one(query_fields=dict( channel_enum=cls.channel_enum2)) # print(channel_config) # limit_min, limit_max = ChannelLimitCacheCtl(PayTypeEnum.DEPOSIT).get_channel_limit() limit_min, limit_max = ChannelListHelper.get_channel_limit_range( merchant=cls.merchant, payment_way=PayTypeEnum.DEPOSIT, ) # print('limit_min: %s, limit_max: %s' % (limit_min, limit_max)) assert 0 != limit_min assert 0 != limit_max if not cls.get_withdraw_channel2(): # 提款代付通道配置 withdraw_item = dict( fee="1.3", fee_type=PaymentFeeTypeEnum.PERCENT_PER_ORDER, limit_per_min="300", limit_per_max="10000", limit_day_max="500000", trade_begin_hour="0", trade_begin_minute="0", trade_end_hour="0", trade_end_minute="0", maintain_begin=DateTimeKit.str_to_datetime( "2019-09-07 09:00:00"), maintain_end=DateTimeKit.str_to_datetime( "2019-09-07 09:00:00"), state=ChannelStateEnum.TESTING if cls.merchant.is_test else ChannelStateEnum.ONLINE, banks=[ PaymentBankEnum.ZHONGGUO, PaymentBankEnum.GONGSHANG, PaymentBankEnum.JIANSHE, ]) ProxyChannelConfig.update_channel(cls.channel_enum2, **withdraw_item) channel_config = ProxyChannelConfig.query_latest_one( query_fields=dict(channel_enum=cls.channel_enum2)) # print(channel_config) # limit_min, limit_max = ChannelLimitCacheCtl(PayTypeEnum.WITHDRAW).get_channel_limit() limit_min, limit_max = ChannelListHelper.get_channel_limit_range( merchant=cls.merchant, payment_way=PayTypeEnum.WITHDRAW, ) # print('limit_min: %s, limit_max: %s' % (limit_min, limit_max)) assert 0 != limit_min assert 0 != limit_max
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()
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 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 __test_api_deposit(self): self.path = "/auth/account/register" register_data = dict(number="+8618912341234", auth_code="8888", password="******") response = self.do_request(register_data) self.assertEqual(ResponseSuccess.code, response.status_code) self.assertEqual(ResponseSuccess.error_code, response.json['error_code']) self.path = '/auth/account/login' login_data = dict(number="+8618912341234", password="******") response = self.do_request(login_data) print(response.json) self.assertEqual(ResponseSuccessLogin.code, response.status_code) self.assertEqual(ResponseSuccessLogin.error_code, response.json['error_code']) self.token = response.json['data']['token'] 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") # print(channel1['channel_id']) ChannelConfig.update_channel(ChannelConfigEnum.CHANNEL_1001, **kwargs) 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.path = "/deposit/limit/config/get" response = self.do_request() self.assertEqual(ResponseDepositLimitConfig.code, response.status_code) self.assertEqual(ResponseDepositLimitConfig.error_code, response.json['error_code']) self.path = "/deposit/payment/type/list" response = self.do_request(dict(amount=500)) self.assertEqual(ResponsePaymentType.code, response.status_code) self.assertEqual(ResponsePaymentType.error_code, response.json['error_code'], response.json['message']) self.path = "/deposit/order/create" create_order_data = dict( payment_type="20", amount="400.03", channel_id=ChannelConfigEnum.CHANNEL_1001.value, ) response = self.do_request(create_order_data) self.assertEqual(InvalidDepositPaymentTypeError.code, response.status_code) self.assertEqual(InvalidDepositPaymentTypeError.error_code, response.json['error_code'], response.json['message']) # create_order_data['payment_type'] = '10' # response = self.do_request(create_order_data) # self.assertEqual(ResponseSuccess.code, response.status_code) # self.assertEqual(ResponseSuccess.error_code, response.json['error_code']) # create_order_data['channel_id'] = '105' # response = self.do_request(create_order_data) # self.assertEqual(InvalidDepositChannelError.code, response.status_code) # self.assertEqual(InvalidDepositChannelError.error_code, response.json['error_code']) # create_order_data['channel_id'] = '101' # create_order_data['payment_type'] = "20" # response = self.do_request(create_order_data) # self.assertEqual(ChannelNoValidityPeriodError.code, response.status_code) # self.assertEqual(ChannelNoValidityPeriodError.error_code, response.json['error_code']) # create_order_data['payment_type'] = "30" # create_order_data['channel_id'] = '107' # response = self.do_request(create_order_data) # self.assertEqual(ResponseSuccess.code, response.status_code) # self.assertEqual(ResponseSuccess.error_code, response.json['error_code']) self.path = "/user/balance/get" response = self.do_request() print(response.json) self.assertEqual(ResponseUserBalance.code, response.status_code) self.assertEqual(ResponseUserBalance.error_code, response.json['error_code'])
def get_config_channels(cls, payment_way: PayTypeEnum, ret_dict=False): if payment_way == PayTypeEnum.DEPOSIT: return ChannelConfig.get_latest_active_configs(ret_dict) else: return ProxyChannelConfig.get_latest_active_configs(ret_dict)
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 __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 post(self): if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']): # 无论如何都记录一条log current_app.logger.info( 'zhuanyifu deposit callback, ip: %s, data: %s, headers: %s', IpKit.get_remote_ip(), request.json, request.headers) event = request.headers.get('ChinaRailway-Event') signature = request.headers.get('ChinaRailway-Signature') form, error = ZhuanYeFuWithdrawForm().request_validate() if error: current_app.logger.fatal('msg: %s, data: %s', error.message, request.args) return BaseResponse('FAIlURE') client_ip = form.client_ip.data tx_amount = Decimal(form.amount.data) fee = Decimal(form.fee.data) channel_tx_id = form.transaction.data # if not CallbackZYF.check_ip(client_ip): # current_app.logger.fatal('ip not allow, client_ip: %s, data: %s, body: %s', client_ip, request.args, # request.json) # return ResponseSuccess(code=500, message='ip not allow').as_response() pp = signature.split('.') if event != "Charge.Succeeded": return ResponseSuccess(code=500).as_response() order = DepositTransactionCtl.get_order(form.order.data) if not order: return ResponseSuccess( code=500, message='curr order no found').as_response() curr_status = order.state if curr_status != OrderStateEnum.INIT: return ResponseSuccess( code=500, message='curr order status must be DEALING').as_response() channel_config = ChannelConfig.query_by_channel_id(order.channel_id) # 检查通道手续费与系统计算出的手续费 channel_cost = FeeCalculator.calc_cost(order.amount, channel_config.fee_type, channel_config.fee) if Decimal(fee) != channel_cost: current_app.logger.error( "ZYF deposit fee info order_id:{}, channel_fee: {}, channel_cost:{}" .format(order.order_id, Decimal(fee), channel_cost)) flag = CallbackZYF.check_sign(pp=pp, channel_config=channel_config) if not flag: current_app.logger.fatal( 'invalid sign, client_ip: %s, data: %s, body: %s', client_ip, request.args, request.json) return ResponseSuccess(code=500, message='签名错误').as_response() status = form.status.data if str(status) == '1': if not DepositTransactionCtl.success_order_process( order, tx_amount, channel_tx_id, client_ip): return ResponseSuccess(code=500, message='订单状态更新失败').as_response() else: return ResponseSuccess(code=500, message='签名错误').as_response() elif str(status) == '2': if not DepositTransactionCtl.failed_order_process( order, tx_amount, channel_tx_id, client_ip): return ResponseSuccess(code=500, message='订单状态更新失败').as_response() elif str(status) == '0': pass return ResponseSuccess(code=204).as_response()