示例#1
0
    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')
示例#2
0
    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()
示例#3
0
    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"))
示例#4
0
    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
示例#5
0
    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()
示例#6
0
    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()