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 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 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 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 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()