def post(self): """ 给商户发通知 :return: """ form, error = OrderStateNotifyFrom().request_validate() if error: return error.as_response() order_id = form.order_id.data order_type = form.order_type.data if order_type == PayTypeEnum.WITHDRAW: order = WithdrawTransactionCtl.get_order_by_order_id(order_id) rst = WithdrawTransactionCtl.do_notify( order=order, op_account=g.user.account, comment="后台人工状态通知", ) else: order = DepositTransactionCtl.get_order_by_order_id(order_id) rst = DepositTransactionCtl.do_notify( order=order, op_account=g.user.account, comment="后台人工状态通知", ) return ResponseSuccess(message=rst['msg'])
def init_withdraw_order_deal(cls, amount): """ 初始化一个提款订单 :param amount: :return: """ client_ip = '127.0.0.1' user = cls.get_user() bank_card = cls.get_bank_card() admin_user = cls.get_admin_user() order, error = WithdrawTransactionCtl.order_create( user=user, amount=amount, client_ip=client_ip, user_bank_id=bank_card.card_id, ) assert error is None rst = WithdrawTransactionCtl.order_alloc(admin_user.account, order.order_id, cls.merchant) assert isinstance(rst, (ResponseSuccess, )) channel = cls.get_withdraw_channel() rst = WithdrawTransactionCtl.order_deal(admin_user.account, order.order_id, order.merchant, channel.channel_id, test=True) assert isinstance(rst, (ResponseSuccess, )) return WithdrawTransactionCtl.get_order(order.sys_tx_id)
def __test_manually_withdraw_success(self): amount = Decimal("200.25") channel_cost = Decimal('3.5') admin_user = InitData.get_admin_user() order = InitData.init_withdraw_order_alloc(amount) rsp = WithdrawTransactionCtl.manually_withdraw(admin_user, order.merchant, order.order_id) self.assertIsInstance(rsp, (ResponseSuccess, )) # 先成功 rsp = WithdrawTransactionCtl.manually_withdraw_success( admin_user=admin_user, merchant=order.merchant, order_id=order.order_id, channel_cost=channel_cost, comment="好贵啊", ) self.assertIsInstance(rsp, (ResponseSuccess, )) # 后失败 rsp = WithdrawTransactionCtl.manually_withdraw_failed( admin_user=admin_user, merchant=order.merchant, order_id=order.order_id, ) self.assertIsInstance(rsp, (ResponseSuccess, ))
def create_one_refund_order(cls): """ 创建一个失败的订单,最后退款 :return: """ amount = Decimal("300") order = cls.init_withdraw_order_deal(amount) WithdrawTransactionCtl.order_fail(order)
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 withdraw_epay_tong(): from app.main import flask_app with flask_app.app_context(): tasks = list(OrderTasks.query_all()) for task in tasks: order_id = task.order_id batch_date = DateTimeKit.datetime_to_str(task.create_time, DateTimeFormatEnum.TIGHT_DAY_FORMAT) current_app.logger.info('EpayTong withdraw check: order_id: %s, batch_date: %s', order_id, batch_date) order = WithdrawTransactionCtl.get_order_by_order_id(order_id) current_app.logger.info('EpayTong withdraw check: order_state: %s, state_type: %s', order.state, type(order.state)) if not order: current_app.logger.info('EpayTong withdraw check, order_id: %s', order_id) OrderTasks.delete_task(task_id=task.id) continue if order.state.name == OrderStateEnum.SUCCESS.name or order.state.name == OrderStateEnum.FAIL.name: OrderTasks.delete_task(task_id=task.id) continue elif order.state.name != "DEALING": current_app.logger.info('EpayTong withdraw check, order_id: %s, order_state: %s', order_id, order.state) continue current_app.logger.info('EpayTong withdraw check, order_id: %s, order_state: %s', order_id, order.state) params = { "tx_id": order.sys_tx_id, "batch_date": batch_date } rst = EpayTongWithdrawRequest(channel_enum=ChannelConfigEnum.CHANNEL_6013).launch_pay(params) if rst['code'] == 0: tx_amount = rst['data']['tx_amount'] code = rst['data']['tradeFeedbackcode'] print(code, "******************") if code == "成功": if WithdrawTransactionCtl.order_success(order, tx_amount): OrderTasks.delete_task(task_id=task.id) elif code == "失败": if WithdrawTransactionCtl.order_fail(order): OrderTasks.delete_task(task_id=task.id)
def post(self): if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']): # 无论如何都记录一条log current_app.logger.info('yinsao withdraw callback, ip: %s, data: %s, headers: %s', IpKit.get_remote_ip(), request.form, request.headers) # form, error = YinSaoForm.request_validate() # if error: # current_app.logger.fatal('msg: %s, data: %s', error.message, request.json) # return BaseResponse('FAIlURE') client_ip = IpKit.get_remote_ip() if not CallbackYinSao.check_ip(client_ip): current_app.logger.fatal('ip not allow, client_ip: %s, data: %s', client_ip, request.args) return BaseResponse('FAIlURE') data = {k: v for k, v in request.form.items()} tx_amount = Decimal(data['transAmt']) / Decimal('100') sys_tx_id = data['orderNo'] signature = data.pop('signature') key_list = sorted(list(data.keys())) request_str = "&".join(["{}={}".format(field, data[field]) for field in key_list if field != "risk"]) sign = CallbackYinSao.generate_sign(request_str) flag = CallbackYinSao.check_sign(signature, sign) if not flag: current_app.logger.fatal('invalid sign, data: %s, sign: %s, signature: %s', client_ip, data, sign, signature) return BaseResponse('FAIlURE') order = WithdrawTransactionCtl.get_order(sys_tx_id) if not order: return BaseResponse('FAIlURE') if str(data['respCode']) == '0000': # 支付成功 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 init_withdraw_order_alloc(cls, amount): client_ip = '127.0.0.1' user = cls.get_user() bank_card = cls.get_bank_card() admin_user = cls.get_admin_user() order, error = WithdrawTransactionCtl.order_create( user=user, amount=amount, client_ip=client_ip, user_bank_id=bank_card.card_id, ) assert error is None rst = WithdrawTransactionCtl.order_alloc(admin_user.account, order.order_id, cls.merchant) assert isinstance(rst, (ResponseSuccess, )) return WithdrawTransactionCtl.get_order(order.sys_tx_id)
def get(self): """ 手动通知商户 :return: """ if not request.args: return ResponseSuccess(message="参数规则:?tx_id=xx").as_response() try: tx_id = request.args['tx_id'] except: return ResponseSuccess(message="请输入 tx_id=,系统交易ID").as_response() order = WithdrawTransactionCtl.get_order(tx_id) rst = WithdrawTransactionCtl.do_notify( order=order, op_account='somebody', comment="后台人工状态通知", ) return ResponseSuccess(message=rst['msg']).as_response()
def __test_manually_withdraw_fail(self): amount = Decimal("200.25") admin_user = InitData.get_admin_user() # 先认领 order = InitData.init_withdraw_order_alloc(amount) # 直接拒绝 rsp = WithdrawTransactionCtl.manually_withdraw_failed( admin_user=admin_user, merchant=order.merchant, order_id=order.order_id, ) self.assertIsInstance(rsp, (ResponseSuccess, ))
def post(self): """ 提现订单: 运营人员认领订单 :return: """ form, error = WithDrawOrderAllowedForm().request_validate() if error: return error.as_response() order_id = form.order_id.data merchant = form.merchant_name.data rst = WithdrawTransactionCtl.order_alloc(g.user.account, order_id, merchant) return rst.as_response()
def post(self): """ 给商户发通知 :return: """ form, error = OrderStateNotifyFrom().request_validate() if error: return error.as_response() order_id = str(form.order_id.data) if form.type.data == PayTypeEnum.WITHDRAW: order = WithdrawTransactionCtl.get_order(order_id) rst = WithdrawTransactionCtl.do_notify(order=order, op_account=g.user.account, comment="商户后台手动通知") elif form.type.data == PayTypeEnum.DEPOSIT: order = DepositTransactionCtl.get_order(order_id) rst = DepositTransactionCtl.do_notify( order=order, op_account=g.user.account, comment="商户后台手动通知", ) return ResponseSuccess(message=rst['msg'])
def post(self): """ 运营发起确认对订单的提现,向第三方发起提现请求 :return: """ form, error = WithdrawOrderPerformForm().request_validate() if error: return error.as_response() merchant = form.merchant.data order_id = form.order_id.data channel_id = form.channel_id.data rst = WithdrawTransactionCtl.order_deal(g.user.account, order_id, merchant, channel_id) return rst.as_response()
def create_one_withdraw_order(cls, amount=None): client_ip = '127.0.0.1' amount = amount or Decimal("300") user = cls.get_user() bank_card = cls.get_bank_card() order, error = WithdrawTransactionCtl.order_create( user=user, amount=amount, client_ip=client_ip, user_bank_id=bank_card.card_id, ) assert error is None return cls.get_user_latest_order(user.uid, PayTypeEnum.WITHDRAW)
def post(self): """ 拒绝提现 或 提现失败 :return: """ form, error = WithDrawBankForm().request_validate() if error: return error.as_response() rsp = WithdrawTransactionCtl.manually_withdraw_failed( admin_user=g.user, merchant=form.merchant.data, order_id=form.order_id.data, ) return rsp.as_response()
def post(self): """ 运营确定出款成功 :return: """ form, error = WithDrawPersonExecutedDoneForm().request_validate() if error: return error.as_response() fee = form.fee.data if form.fee.data else "0" comment = form.comment.data rsp = WithdrawTransactionCtl.manually_withdraw_success( admin_user=g.user, merchant=form.merchant.data, order_id=form.order_id.data, channel_cost=fee, comment=comment, ) return rsp.as_response()
def post(self): """ 提现接口: 检查支付密码是否正确,如果密码正确则创建用户提现订单 """ form, error = CreateWithdrawOrderForm().request_validate() if error: return error.as_response() uid = g.user.uid merchant = g.user.merchant if not g.user.has_permission(UserPermissionEnum.WITHDRAW): return UserPermissionDeniedError().as_response() amount = BalanceKit.round_4down_5up(Decimal(form.amount.data)) user_bank_id = form.user_bank.data client_ip = form.client_ip.data trade_password = form.trade_password.data # 判断 支付密码是否正确 if not User.verify_payment_password( merchant=merchant, uid=uid, password=trade_password): cache = UserPaymentPasswordLimitCache(uid=uid) cache.incr_times() times = cache.get_left_times() return PaymentPasswordError(message=PaymentPasswordError.message. format(times)).as_response() order, error = WithdrawTransactionCtl.order_create( user=g.user, amount=amount, client_ip=client_ip, user_bank_id=user_bank_id, ) if error: return error.as_response() return ResponseSuccess().as_response()
def post(self): """ 专一付代付回调 :return: """ if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']): # 无论如何都记录一条log current_app.logger.info( 'zhuanyifu withdraw 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') pp = signature.split('.') if event != "Pay.Succeeded": return ResponseSuccess(code=500).as_response() # 交易ID tx_id = form.order.data fee = Decimal(form.fee.data) order = WithdrawTransactionCtl.get_order(tx_id) if not order: return ResponseSuccess( code=500, message='curr order no found').as_response() curr_status = order.state if curr_status != OrderStateEnum.DEALING: return ResponseSuccess( code=500, message='curr order status must be DEALING').as_response() print(order.channel_id, form.order.data, order.merchant, order.create_time, order.order_id, order.uid) channel_config = ProxyChannelConfig.query_by_channel_id( order.channel_id) channel_cost = FeeCalculator.calc_cost(order.amount, channel_config.fee_type, channel_config.fee) if fee != channel_cost: current_app.logger.error( "ZYF withdraw fee info order_id:{}, channel_fee: {}, channel_cost:{}" .format(order.order_id, fee, channel_cost)) try: flag = CryptoKit.rsa_verify( pp[1], pp[0], channel_config.channel_enum.conf['plat_public_key']) if flag != True: return ResponseSuccess(code=500, message='签名错误').as_response() except Exception as e: return ResponseSuccess(code=500).as_response() # 代付金额 tx_amount = Decimal(form.amount.data) # 代付费率 fee = Decimal(form.fee.data) # 通道订单号 transaction = form.transaction.data client_ip = form.client_ip.data status = form.status.data if str(status) == "1": """ 修改订单状态, 记录代付费率 """ if not WithdrawTransactionCtl.order_success(order, tx_amount): return ResponseSuccess(code=500).as_response() elif str(status) == "2": """ 代付订单失败, 1.给用户退款,给商户退款+手续费 2. 修改订单状态 """ # order = WithdrawTransactionCtl.get_order(merchant, order_id) if not WithdrawTransactionCtl.order_fail(order): return ResponseSuccess(code=500).as_response() return ResponseSuccess(code=204).as_response()
def __test_withdraw_fail(self): amount = Decimal("100.25") order = InitData.init_withdraw_order_deal(amount) rst = WithdrawTransactionCtl.order_fail(order) self.assertTrue(rst)
def __test_withdraw_success(self): amount = tx_amount = Decimal("100.25") order = InitData.init_withdraw_order_deal(amount) rst = WithdrawTransactionCtl.order_success(order, tx_amount) self.assertTrue(rst)
def post(self): if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']): # 无论如何都记录一条log current_app.logger.info( 'onepay withdraw callback, ip: %s, headers: %s, json data: %s', IpKit.get_remote_ip(), request.headers, request.json) # form, error = YinSaoForm.request_validate() # if error: # current_app.logger.fatal('msg: %s, data: %s', error.message, request.json) # return BaseResponse('FAIlURE') current_app.logger.fatal( 'onepay withdraw callback, ip: %s, form data: %s, headers: %s, json data: %s', IpKit.get_remote_ip(), request.form, request.headers, request.json) client_ip = IpKit.get_remote_ip() if not CallbackOnePay.check_ip(client_ip): current_app.logger.fatal('ip not allow, client_ip: %s, data: %s', client_ip, request.args) return BaseResponse('FAIlURE') flag = request.json['flag'] if flag == 'FAILED': return BaseResponse('FAIlURE') data = {k: v for k, v in request.json['data'].items()} no_need_sign = ['totalFactorage', 'sign', 'signType', 'detailList'] signature = data.pop('sign') key_list = sorted(list(data.keys())) request_str = "&".join([ "{}={}".format(field, data[field]) for field in key_list if data.get(field, False) and field not in no_need_sign ]) flag = CallbackOnePay.check_sign(signature, request_str) if not flag: current_app.logger.fatal( 'invalid sign, data: %s, sign: %s, data: %s', client_ip, data, signature, request_str) return BaseResponse('FAIlURE') withdraw_order = request.json['data']['detailList'][0] tx_id = withdraw_order['serialNo'] tx_amount = withdraw_order['amount'] order = WithdrawTransactionCtl.get_order(tx_id) if not order: return BaseResponse('FAIlURE') if str(withdraw_order['tradeStatus']) == '1': # 支付成功 if not WithdrawTransactionCtl.order_success( order, decimal.Decimal(tx_amount)): return BaseResponse('FAILURE') elif str(withdraw_order['tradeStatus']) == '2': # 支付失败 if not WithdrawTransactionCtl.order_fail(order): return BaseResponse('FAIlURE') return BaseResponse('SUCCESS')
def post(self): """ 充值请求 """ if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']): # 无论如何都记录一条log current_app.logger.info('path: %s, ip: %s, args: %s, data: %s', url_for("gateway_withdraw_request"), IpKit.get_remote_ip(), request.args, request.json) form, error = WithdrawRequestForm.request_validate() if error: return error.as_response() checker = GatewayFormChecker(form.merchant_id.data) # 1. IP白名单校验 if not checker.verify_ip(form.client_ip.data): current_app.logger.error('msg: %s, ip: %s, white ips: %s', GatewayIPError.message, IpKit.get_remote_ip(), checker.get_white_ips()) return GatewayIPError().as_response() # 2. 签名校验 sign_fields = form.get_sign_fields() if not checker.verify_sign(form.sign.data, sign_fields): current_app.logger.error( 'msg: %s, sign: %s, fields: %s, sign_str: %s', GatewaySignError.message, form.sign.data, sign_fields, checker.get_sign_str(sign_fields)) return GatewaySignError().as_response() # 3. 获取用户对象 user = checker.get_fake_user(form.user_id.data) # 银行卡信息 bank_info = BankCard.generate_model( bank_name=form.bank_type.data.desc, bank_code=form.bank_type.data.bank_code, card_no=form.card_no.data, account_name=form.account_name.data, branch=form.branch.data or '', province=form.province.data or '', city=form.city.data or '', ) # 4. 创建订单 order, error = WithdrawTransactionCtl.order_create( user=user, amount=form.amount.data, client_ip=form.user_ip.data, notify_url=form.notify_url.data, mch_tx_id=form.mch_tx_id.data, bank_info=bank_info.bank_info_dict, extra=form.extra.data, ) if error: return error.as_response() return GatewayResponseWithdraw(bs_data=dict( sys_tx_id=order.sys_tx_id, mch_tx_id=order.mch_tx_id, )).as_response()