def post(self): """ 发货通知,由商户实现 :return: """ 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_demo_notify"), IpKit.get_remote_ip(), request.args, request.json) form, error = DepositNotifyForm.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() # 商户自己的业务逻辑处理 current_app.logger.info('notify success: %s', form.json_data) return ResponseSuccess().as_response()
def post(self): client_ip = IpKit.get_remote_ip() if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']): # 无论如何都记录一条log current_app.logger.info('Gpay deposit callback, ip: %s, data: %s', IpKit.get_remote_ip(), request.form) sys_tx_id = request.form['company_order_num'] tx_amount = request.form['amount'] pw_trade_id = request.form['mownecum_order_num'] if not CallbackGpay.check_ip(client_ip): current_app.logger.fatal( 'ip not allow, client_ip: %s, data: %s, body: %s', client_ip, request.args, request.form) return BaseResponse( '{"company_order_num":"%s", "mownecum_order_num":"%s", "status":"1", "error_msg":"%s"}' % (sys_tx_id, pw_trade_id, "订单状态已更新")) order = DepositTransactionCtl.get_order(sys_tx_id) if not order: current_app.logger.error('gpay: no found order, order id: %s' % (sys_tx_id)) return BaseResponse( '{"company_order_num":"%s", "mownecum_order_num":"%s", "status":"0", "error_msg":"%s"}' % (sys_tx_id, pw_trade_id, "查不到该订单")) if order.state.name != OrderStateEnum.INIT.name: return BaseResponse( '{"company_order_num":"%s", "mownecum_order_num":"%s", "status":"1", "error_msg":"%s"}' % (sys_tx_id, pw_trade_id, "订单状态已更新")) sorted_fields = [ "pay_time", "bank_id", "amount", "company_order_num", "mownecum_order_num", "pay_card_num", "pay_card_name", "channel", "area", "fee", "transaction_charge", "deposit_mode" ] request_str = "".join([request.form.get(k, "") for k in sorted_fields]) sign = request.form['key'] flag = CallbackGpay.check_sign(sign, request_str) if not flag: current_app.logger.fatal( 'invalid sign, client_ip: %s, data: %s, body: %s', client_ip, request.args, request_str) return BaseResponse( '{"company_order_num":"%s", "mownecum_order_num":"%s", "status":"0", "error_msg":"%s"}' % (sys_tx_id, pw_trade_id, "更新订单状态失败")) if not DepositTransactionCtl.success_order_process( order, decimal.Decimal(tx_amount), pw_trade_id): return BaseResponse( '{"company_order_num":"%s", "mownecum_order_num":"%s", "status":"0", "error_msg":"%s"}' % (sys_tx_id, pw_trade_id, "更新订单状态失败")) return BaseResponse( '{"company_order_num":"%s", "mownecum_order_num":"%s", "status":"1", "error_msg":""}' % (sys_tx_id, pw_trade_id))
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_config_get"), IpKit.get_remote_ip(), request.args, request.json) form, error = DepositConfigForm.request_validate() if error: return error.as_response() merchant = form.merchant_id.data checker = GatewayFormChecker(merchant) # 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. 返回可用的支付方式以及限额 # 充值每种支付类型的限额 payment_types = ChannelListHelper.get_channels_for_gateway( merchant, PayTypeEnum.DEPOSIT, client_ip=form.user_ip.data, ) # 提现限额 # limit_min, limit_max = ChannelLimitCacheCtl(PayTypeEnum.WITHDRAW).get_channel_limit() limit_min, limit_max = ChannelListHelper.get_channel_limit_range( merchant=merchant, payment_way=PayTypeEnum.WITHDRAW, client_ip=form.user_ip.data, ) withdraw_config = dict( limit_min=limit_min, # 最小限额列表的最小值 limit_max=limit_max, # 最大限额列表的最大值 ) return GatewayResponseConfig(bs_data=dict( payment_types=payment_types, withdraw_config=withdraw_config, )).as_response()
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: """ if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']): # 无论如何都记录一条log current_app.logger.info('jifu deposit callback, ip: %s, data: %s', IpKit.get_remote_ip(), request.form) form, error = JifuCallbackForm().request_validate() if error: current_app.logger.fatal('msg: %s, data: %s', error.message, request.form) return BaseResponse(error.message) # 交易订单id sys_tx_id = form.remark.data # 通道订单id channel_tx_id = form.id.data # 实际支付金额 tx_amount = Decimal(form.money.data) # 客户端IP client_ip = form.client_ip.data # IP白名单校验 checker = DepositCallbackJifu(ChannelConfigEnum.CHANNEL_7001) if not checker.check_ip(client_ip): current_app.logger.fatal('ip not allow, client_ip: %s, data: %s', client_ip, form.form_data) return BaseResponse('ip not allow') # 签名验证 if not checker.check_sign(form.get_sign_fields(), form.get_raw_sign()): current_app.logger.fatal('invalid sign, client_ip: %s, data: %s', client_ip, form.form_data) return BaseResponse('invalid sign') order = DepositTransactionCtl.get_order(sys_tx_id) if not order: return BaseResponse('no order found for sys_tx_id: %s', sys_tx_id) if order.channel_tx_id != channel_tx_id: # 根据API文档的建议,之前已经将code放入数据库的channel_tx_id中,等回调时拿来比对 current_app.logger.fatal( 'invalid channel_tx_id, client_ip: %s, channel_tx_id: %s, data: %s', client_ip, order.channel_tx_id, form.form_data) return BaseResponse('invalid channel_tx_id') # 支付成功 if not DepositTransactionCtl.success_order_process( order, tx_amount, channel_tx_id): return BaseResponse('order process failed, sys_tx_id: %s', sys_tx_id) # 成功返回小写字符串success return BaseResponse('success')
def get(self): """ 立马付,充值回调 :return: """ if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']): # 无论如何都记录一条log current_app.logger.info( 'ponypay deposit callback, ip: %s, data: %s', IpKit.get_remote_ip(), request.args) form, error = PonyPayForm().request_validate() if error: current_app.logger.fatal('msg: %s, data: %s', error.message, request.args) return BaseResponse(error.message) # 交易订单id tx_id = form.orderid.data # 充值通道 订单id channel_tx_id = form.porder.data # 实际支付金额 tx_amount = Decimal(form.money.data) # 订单状态: 成功/失败 status = form.status.data # 客户端IP client_ip = form.client_ip.data # IP白名单校验 if not CallbackPonypay.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 CallbackPonypay.check_sign(form): current_app.logger.fatal('invalid sign, client_ip: %s, data: %s', client_ip, request.args) return BaseResponse('FAIlURE') order = DepositTransactionCtl.get_order(tx_id) if not order: return BaseResponse('FAIlURE') if status == '1': # 支付成功 if not DepositTransactionCtl.success_order_process( order, tx_amount, channel_tx_id): return BaseResponse('FAIlURE') else: # 支付失败 if not DepositTransactionCtl.failed_order_process( order, tx_amount, channel_tx_id): return BaseResponse('FAIlURE') return BaseResponse('SUCCESS')
def post(self): client_ip = IpKit.get_remote_ip() third_config = ThirdPayConfig.EpayTong_PAY_DEPOSIT.value if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']): # 无论如何都记录一条log current_app.logger.info( 'epaytong deposit callback, ip: %s, data: %s', IpKit.get_remote_ip(), request.form) if not CallbackEpayTong.check_ip(client_ip): current_app.logger.fatal( 'ip not allow, client_ip: %s, data: %s, body: %s', client_ip, request.args, request.form) return BaseResponse('FAIlURE') sys_tx_id = request.form['order_no'] order = DepositTransactionCtl.get_order(sys_tx_id) if not order: current_app.logger.error('epaytong: no found order, order id: %s' % (sys_tx_id)) return BaseResponse('FAILURE') no_need_field = ['signType', 'sign'] sorted_fields = sorted([k for k in request.form.keys()]) request_str = "&".join([ "{}={}".format(k, request.form[k]) for k in sorted_fields if (request.form[k] == 0 or request.form[k] == "0" or request.form[k]) and k not in no_need_field ]) sign = request.form['sign'] sign_str = request_str + third_config['secret_key'] flag = CallbackEpayTong.check_sign(sign, sign_str) if not flag: current_app.logger.fatal( 'invalid sign, client_ip: %s, data: %s, body: %s', client_ip, request.args, request_str) return ResponseSuccess(code=500, message='签名错误').as_response() tx_amount = request.form['price'] pwTradeId = request.form['notify_id'] status = request.form['is_success'] trade = request.form['trade_status'] if status == 'T' and trade == "TRADE_FINISHED": if not DepositTransactionCtl.success_order_process( order, decimal.Decimal(tx_amount), pwTradeId): return BaseResponse('FAIlURE') else: if not DepositTransactionCtl.failed_order_process( order, decimal.Decimal(tx_amount), pwTradeId): return BaseResponse('FAIlURE') return BaseResponse('success')
def get(self): """ 渲染第三方跳转页面 :return: """ 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_deposit_redirect"), IpKit.get_remote_ip(), request.args, request.json) return DepositHelper.render_page()
def post(self): if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']): # 无论如何都记录一条log current_app.logger.info( 'one pay deposit callback, ip: %s, 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') sys_tx_id = request.form['merchantTradeId'] order = DepositTransactionCtl.get_order(sys_tx_id) if not order: current_app.logger.error('OnePay: no found order, order id: %s' % (sys_tx_id)) return BaseResponse('FAILURE') no_need_field = ['signType', 'sign'] sorted_fields = sorted([k for k in request.form.keys()]) request_str = "&".join([ "{}={}".format(k, request.form[k]) for k in sorted_fields if k not in no_need_field and request.form[k] ]) sign = request.form['sign'] flag = CallbackOnePay.check_sign(sign, request_str) if not flag: current_app.logger.fatal( 'invalid sign, client_ip: %s, data: %s, body: %s', client_ip, request.args, request_str) return ResponseSuccess(code=500, message='签名错误').as_response() tx_amount = request.form['amountFee'] pwTradeId = request.form['pwTradeId'] status = request.form['tradeStatus'] if status == 'PS_PAYMENT_FAIL': if not DepositTransactionCtl.failed_order_process( order, decimal.Decimal(tx_amount), pwTradeId): return BaseResponse('FAIlURE') elif status == 'PS_PAYMENT_SUCCESS': if not DepositTransactionCtl.success_order_process( order, decimal.Decimal(tx_amount), pwTradeId): 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('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 get(self): """ Tong yi Pay,充值回调 :return: """ if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']): # 无论如何都记录一条log current_app.logger.info('tong yi deposit callback, ip: %s, data: %s', IpKit.get_remote_ip(), request.args) client_ip = IpKit.get_remote_ip() if not CallbackTongYiPay.check_ip(client_ip): current_app.logger.error('ip not allow, client_ip: %s, data: %s, body: %s', client_ip, request.args, request.json) sign = request.args.get("sign") keys = sorted(list(request.args.keys())) sign_str = "&".join(["{}={}".format(k, request.args.get(k)) for k in keys if k not in ['sign'] and request.args.get(k, False)]) flag = CallbackTongYiPay.check_sign(sign, sign_str) if not flag: current_app.logger.error('invalid sign, client_ip: %s, data: %s, body: %s', client_ip, request.args, sign_str) return BaseResponse('error') order_id = request.args.get('order') order = DepositTransactionCtl.get_order(order_id) if not order: current_app.logger.error('invalid order: order_id: %s', order_id) return BaseResponse('FAIlURE') if order.state.name == OrderStateEnum.SUCCESS.name: return BaseResponse('SUCCESS') channel_tx_id = request.args.get('orderId', False) state = request.args.get('status', 0) tx_amount = request.args.get('money', 0) if str(state) == "2" or str(state) == "3": if not DepositTransactionCtl.success_order_process(order, Decimal(tx_amount), channel_tx_id): return BaseResponse('FAIlURE') return BaseResponse('SUCCESS')
def post(self): """ BestPay,充值回调 :return: """ if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']): # 无论如何都记录一条log current_app.logger.info('BestPay deposit callback, ip: %s, data: %s', IpKit.get_remote_ip(), request.form) client_ip = IpKit.get_remote_ip() if not CallbackBestPay.check_ip(client_ip): current_app.logger.error('ip not allow, client_ip: %s, data: %s, body: %s', client_ip, request.args, request.form) return BaseResponse('error') data = request.form['deposit_result'] resp_body = json.loads(data) third_config = ThirdPayConfig.BESTPAY_DEPOSIT.value sign = resp_body["sign"] resp_type = resp_body["type"] if resp_type != "deposit_result": return BaseResponse('error') data = resp_body["data"] print(data) if isinstance(data, list): sign_str = json.dumps(data) else: sign_str = data sign_str += third_config['secret_key'] flag = CallbackBestPay.check_sign(sign, sign_str) if not flag: current_app.logger.error('invalid sign, client_ip: %s, data: %s, body: %s', client_ip, request.args, sign_str) return BaseResponse('error') data_list = json.loads(data) flag = 'error' for data_dict in data_list: order_id = data_dict['client_postscript'] tx_amount = data_dict['amount'] channel_tx_id = data_dict['order_number'] client_transtype = data_dict['client_transtype'] deposit_cardnumber = data_dict['deposit_cardnumber'] user_name = data_dict['client_accountname'] deposit_time = data_dict['deposit_time'] try: order_id = int(order_id) except Exception as e: if client_transtype == '微信转账': DateTimeKit.time_delta() log = OrderTransferLog.query_transfer_log_by_user_info( deposit_cardnumber=deposit_cardnumber, amount='{:.2f}'.format(float(tx_amount)), deposit_time=deposit_time ) else: log = OrderTransferLog.query_transfer_log_by_user_info( deposit_cardnumber=deposit_cardnumber, amount='{:.2f}'.format(float(tx_amount)), client_accountname=user_name, deposit_time=deposit_time ) current_app.logger.info("转账信息数据", log) if log: for o in log: order = DepositTransactionCtl.get_order_by_order_id(order_id=o.order_id) if not order or order.state.name != OrderStateEnum.INIT.name: continue if DepositTransactionCtl.success_order_process(order, Decimal(str(tx_amount)), channel_tx_id): OrderTransferLog.update_transfer_log(order_id=order.order_id) flag = "success" else: log = OrderTransferLog.query_transfer_log(order_id=order_id) if not log: continue order = DepositTransactionCtl.get_order_by_order_id(order_id=log.order_id) if not order or order.state.name != OrderStateEnum.INIT.name: continue if DepositTransactionCtl.success_order_process(order, Decimal(str(tx_amount)), channel_tx_id): OrderTransferLog.update_transfer_log(order_id=order.order_id) flag = "success" return BaseResponse(flag)
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()
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): """ RuKouMy,充值回调 :return: """ client_ip = IpKit.get_remote_ip() if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']): # 无论如何都记录一条log current_app.logger.info( 'RuKouMy deposit callback, ip: %s, json: %s', IpKit.get_remote_ip(), request.json) if not CallbackRuKouMy.check_ip(client_ip): current_app.logger.error( 'ip not allow, client_ip: %s, data: %s, body: %s', client_ip, request.args, request.json) return BaseResponse('error') resp_body = request.json sign = resp_body.pop("sign") sorted_params = sorted(list(resp_body.keys())) resp_body['real_amount'] = "{:.2f}".format( int(resp_body['real_amount'])) resp_body['pay_amount'] = "{:.2f}".format(int(resp_body['pay_amount'])) sign_str = "&".join([ "{}={}".format(k, resp_body[k]) for k in sorted_params if resp_body.get(k, False) or k in ["code"] ]) flag = CallbackRuKouMy.check_sign(sign, sign_str) if not flag: current_app.logger.error( 'invalid sign, data: %s, sign: %s, data: %s', client_ip, sign, sign_str) return BaseResponse('error') order_id = resp_body['order_id'] order = DepositTransactionCtl.get_order(order_id) if not order: return BaseResponse('success') if order.state.name == OrderStateEnum.SUCCESS.name: return BaseResponse('success') tx_amount = Decimal(str(request.json['real_amount'])) channel_tx_id = request.json['order_no'] code = resp_body['code'] if code == 0: # 支付成功 if not DepositTransactionCtl.success_order_process( order, tx_amount, channel_tx_id): return BaseResponse('error') else: # 支付失败 if not DepositTransactionCtl.failed_order_process( order, tx_amount, channel_tx_id): return BaseResponse('error') return BaseResponse('success')
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()
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_deposit_request"), IpKit.get_remote_ip(), request.args, request.json) form, error = DepositRequestForm.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. 获取对应支付方式下的充值通道 channel = ChannelListHelper.get_one_channel_by_payment_type( merchant=form.merchant_id.data, payment_type=form.payment_type.data, amount=form.amount.data, client_ip=form.user_ip.data, ) if not channel: current_app.logger.error("no channel found, request data: %s", form.get_data()) return GatewayChannelError().as_response() # # 境外IP检查 # if channel.is_ip_forbidden(form.user_ip.data): # return GatewayDepositError(message="此通道不支持境外IP,请使用VPN后重试").as_response() # 4. 获取用户对象 user = checker.get_fake_user(form.user_id.data) # 5. 发起支付 rst = DepositHelper.do_deposit_request( client_ip=form.user_ip.data, user_agent=form.user_agent.data, user=user, amount=form.amount.data, channel_enum=channel.channel_enum, notify_url=form.notify_url.data, result_url=form.result_url.data, mch_tx_id=form.mch_tx_id.data, extra=form.extra.data, source=OrderSourceEnum.TESTING if form.merchant_id.data.is_test else OrderSourceEnum.ONLINE, in_type=InterfaceTypeEnum.API, ) if rst['error']: return GatewayDepositError(message=rst['error']) # 6. 解析URL ps_rst = DepositHelper.parse_result( data=rst['data'], order_id=rst['order'].order_id, endpoint='gateway_deposit_redirect', channel_enum=channel.channel_enum, ) return GatewayResponseDeposit(bs_data=dict( redirect_url=ps_rst['redirect_url'], valid_time=ps_rst['valid_time'], sys_tx_id=rst['order'].sys_tx_id, mch_tx_id=rst['order'].mch_tx_id, )).as_response()
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): """ 快汇支付,充值回调 :return: """ if not EnvironEnum.is_local_evn(current_app.config['FLASK_ENV']): # 无论如何都记录一条log current_app.logger.info( 'kuaihui deposit callback, ip: %s, args: %s, data: %s', IpKit.get_remote_ip(), request.args, request.json) form, error = KhpayForm().request_validate() if error: current_app.logger.fatal('msg: %s, args: %s, data: %s', error.message, request.args, request.json) return BaseResponse(error.message) # 交易订单id tx_id = form.client_ordid.data # 充值通道 订单id channel_tx_id = form.ordid.data # 实际支付金额 tx_amount = Decimal(form.amount.data) # 订单状态: 成功/失败 status = form.status.data # 客户端IP client_ip = form.client_ip.data custid = form.custid.data kuai_hui_dict = { "PAY5f34c380-b8e6-11e9-9edc-511803f475f9": ThirdPayConfig.KUAIHUI.value, "PAY5f34c380-b8e6-11e9-9edc-511803f475f9": ThirdPayConfig.KUAIHUI_0bd0d8.value } # 签名验证 if not CallbackKhpay.check_sign(form, kuai_hui_dict[custid]): current_app.logger.fatal('invalid sign, client_ip: %s, data: %s', client_ip, request.json) return BaseResponse('FAIlURE') # IP白名单校验 if not CallbackKhpay.check_ip(client_ip): current_app.logger.fatal('ip not allow, client_ip: %s, data: %s', client_ip, request.json) return BaseResponse('FAIlURE') order = DepositTransactionCtl.get_order(tx_id) if not order: return BaseResponse('FAIlURE') if order.state.is_final_state: # 已经通知了就返回成功 return BaseResponse('{"status_code": 200}') if status == 'waiting': return BaseResponse('FAIlURE') if status == 'finish': # 支付成功 if not DepositTransactionCtl.success_order_process( order, tx_amount, channel_tx_id): return BaseResponse('FAIlURE') else: # 支付失败 if not DepositTransactionCtl.failed_order_process( order, tx_amount, channel_tx_id): return BaseResponse('FAIlURE') return BaseResponse('{"status_code": 200}')
def do_notify(cls, order, op_account=None, comment=None): """ 网关回调通知 :return: """ rst = dict(msg=None) if not order.notify_url: # 不需要通知 rst['msg'] = "没有通知URL,不需要发送通知" return rst if order.state not in OrderStateEnum.get_final_states() and \ EnvironEnum.is_production(current_app.config['FLASK_ENV']): rst['msg'] = "订单不是成功/失败状态,还没有完成,不能通知商户" return rst data = dict( merchant_id=order.merchant.value, amount=str(order.amount), tx_amount=str(order.tx_amount), mch_tx_id=order.mch_tx_id, sys_tx_id=order.sys_tx_id, state=order.state.name, ) data['sign'] = GatewaySign(order.merchant).generate_sign(data) data['extra'] = order.extra try: current_app.logger.info('do_notify: %s, data: %s', order.notify_url, data) rsp = requests.post(order.notify_url, json=data) current_app.logger.info('do_notify: %s, status code: %s, data: %s', order.notify_url, rsp.status_code, rsp.text) except: current_app.logger.fatal(traceback.format_exc()) current_app.logger.error('do_notify, url: %s, request data: %s', order.notify_url, data) rst['msg'] = "通知失败,HTTP网络异常" return rst if rsp.status_code != 200: current_app.logger.error( 'do_notify, url: %s, request data: %s, response data: %s', order.notify_url, data, rsp.text) rst['msg'] = "通知失败,HTTP status_code非200:%s" % rsp.status_code return rst try: json_data = rsp.json() except: current_app.logger.error( 'do_notify, url: %s, request data: %s, response data: %s', order.notify_url, data, rsp.text) current_app.logger.fatal(traceback.format_exc()) rst['msg'] = "通知失败,无法解析json数据" return rst if json_data['error_code'] != 200: rst['msg'] = "通知失败,error_code非200:%s" % json_data['error_code'] current_app.logger.error( 'do_notify, url: %s, request data: %s, response data: %s', order.notify_url, data, json_data) return rst # 更新订单通知完成 if order.deliver != DeliverStateEnum.DONE: order, ref_id = OrderUpdateCtl.update_order_event( order_id=order.order_id, uid=order.uid, merchant=order.merchant, deliver=DeliverStateEnum.DONE, op_account=op_account, comment=comment, ) if not order: rst['msg'] = '订单更新失败, 请研发检查错误日志, sys_tx_id: %s' % ( order.sys_tx_id, ) current_app.logger.fatal(rst['msg']) return rst rst['msg'] = "通知成功" return rst
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()