Exemple #1
0
    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'])
Exemple #2
0
    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, ))
Exemple #4
0
    def create_one_refund_order(cls):
        """
        创建一个失败的订单,最后退款
        :return:
        """
        amount = Decimal("300")

        order = cls.init_withdraw_order_deal(amount)
        WithdrawTransactionCtl.order_fail(order)
Exemple #5
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')
Exemple #6
0
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)
Exemple #7
0
    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')
Exemple #8
0
    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)
Exemple #9
0
    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, ))
Exemple #11
0
    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()
Exemple #12
0
    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'])
Exemple #13
0
    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()
Exemple #14
0
    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)
Exemple #15
0
    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()
Exemple #16
0
    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()
Exemple #17
0
    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()
Exemple #18
0
    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)
Exemple #21
0
    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')
Exemple #22
0
    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()