Ejemplo n.º 1
0
def handle_refund_notify(is_success, sn, vas_name, vas_sn, data):
    """
    :param is_success: 是否成功
    :param sn: 订单号
    :param vas_name: 来源系统
    :param vas_sn: 来源系统订单号
    :param data: 数据
    :return:
    """
    import time
    tx = get_tx_by_sn(sn)
    if tx is None:
        for i in range(10):
            # 这是因为_create_and_request_refund在一个事务中,notify到这儿的时候,事务没有结束,导致tx获取不到。
            # 这里的解决办法就是重试
            tx = get_tx_by_sn(sn)
            if tx is None:
                logger.warn(
                    'apply refund [{0}] is not finish, sleep then retry.')
                time.sleep(0.5)
                continue
            break
    refund_record = tx.record

    logger.info('refund notify: {0}, {1}, {2}, {3}, {4}'.format(
        is_success, sn, vas_name, vas_sn, data))
    if tx is None or refund_record is None:
        # 不存在
        logger.warning('refund [{0}] not exits.'.format(sn))
        return

    if is_duplicated_notify(tx, vas_name, vas_sn):
        logger.warning('refund notify duplicated: [{0}, {1}]'.format(
            vas_name, vas_sn))
        return

    if tx.state not in [RefundTxState.PROCESSING, RefundTxState.REFUNDED_IN]:
        logger.warning('bad refund notify: [sn: {0}]'.format(sn))
        return

    payment_tx = tx.super
    payment_record = payment_tx.record

    if payment_tx.state != PaymentTxState.REFUNDING:
        logger.warning(
            'bad refund notify: [sn: {0}], [payment_sn: {1}]'.format(
                sn, payment_tx.sn))
        return

    with require_transaction_context():
        tx = update_transaction_info(refund_record.tx_id, vas_sn)
        if is_success:
            handle_succeed_refund(vas_name, payment_record, refund_record)
        else:
            handle_fail_refund(payment_record, refund_record)

    # notify client.
    tx = get_tx_by_id(tx.id)
    _try_notify_client(tx, refund_record)
Ejemplo n.º 2
0
def _request_refund(payment_tx,
                    payment_record,
                    refund_tx,
                    refund_record,
                    data=None):
    from api_x.zyt.evas import test_pay, lianlian_pay, weixin_pay, ali_pay
    from api_x.zyt import vas

    vas_name = payment_tx.vas_name

    if vas_name == test_pay.NAME:
        res = _refund_by_test_pay(payment_tx, refund_record, data)
    elif vas_name == lianlian_pay.NAME:
        res = _refund_by_lianlian_pay(payment_tx, refund_record)
    elif weixin_pay.is_weixin_pay(vas_name):
        res = _refund_by_weixin_pay(payment_tx, payment_record, refund_tx,
                                    refund_record)
    elif vas_name == ali_pay.NAME:
        res = _refund_by_ali_pay(payment_tx, payment_record, refund_tx,
                                 refund_record)
    elif vas_name == vas.NAME:
        res = _refund_by_zyt(refund_record)
        refund_tx = get_tx_by_sn(refund_tx.sn)
    else:
        raise RefundFailedError('unknown vas {0}'.format(vas_name))

    _refund_to_processing(refund_tx)
    return res
Ejemplo n.º 3
0
def handle_withdraw_notify(is_success, sn, vas_name, vas_sn, data):
    tx = get_tx_by_sn(sn)
    withdraw_record = tx.record

    logger.info('withdraw notify: {0}'.format(data))
    if tx is None or withdraw_record is None:
        # 不存在
        logger.warning('withdraw [{0}] not exits.'.format(sn))
        return

    if is_duplicated_notify(tx, vas_name, vas_sn):
        logger.warning('withdraw notify duplicated: [{0}, {1}]'.format(
            vas_name, vas_sn))
        return

    if tx.state != WithdrawTxState.PROCESSING:
        logger.warning('bad withdraw notify: [sn: {0}]'.format(sn))
        return

    _record_withdraw_extra_info(withdraw_record, data)
    with require_transaction_context():
        tx = update_transaction_info(tx.id, vas_sn, vas_name=vas_name)
        if is_success:
            _success_withdraw(tx, withdraw_record)
        else:
            _fail_withdraw(tx, withdraw_record)

    # notify client.
    tx = get_tx_by_id(tx.id)
    _try_notify_client(tx, withdraw_record)
Ejemplo n.º 4
0
def handle_prepaid_notify(is_success, sn, vas_name, vas_sn, amount, data):
    """
    :param is_success: 是否成功
    :param sn: 订单号
    :param vas_name: 来源系统
    :param vas_sn: 来源系统订单号
    :param data: 数据
    :return:
    """
    tx = get_tx_by_sn(sn)
    prepaid_record = tx.record

    if is_duplicated_notify(tx, vas_name, vas_sn):
        return

    if _is_duplicated_prepaid(tx, vas_name, vas_sn):
        # 重复支付
        logger.warning('duplicated prepaid: [{0}, {1}], [{2}, {3}]'.format(
            tx.vas_name, tx.vas_sn, vas_name, vas_sn))
        if is_success:
            # 成功支付, 充值到余额
            handle_duplicate_pay(vas_name, vas_sn, tx, prepaid_record)
        return

    with require_transaction_context():
        tx = update_transaction_info(tx.id, vas_sn, vas_name=vas_name)
        if is_success:
            succeed_prepaid(vas_name, tx, prepaid_record)
        else:
            fail_prepaid(tx)

    # notify client.
    tx = get_tx_by_id(tx.id)
    _try_notify_client(tx, prepaid_record)
Ejemplo n.º 5
0
def handle_refund_in(vas_name, sn, notify_handle=None):
    tx = get_tx_by_sn(sn)
    refund_record = tx.record
    payment_tx = tx.super
    _succeed_refund_in(vas_name, payment_tx, refund_record)

    if notify_handle is not None:
        notify_handle(True)
Ejemplo n.º 6
0
def try_unblock_refund(refund_tx):
    refund_record = refund_tx.record
    _unblock_refund(refund_record)

    payment_sn = refund_record.payment_sn
    payment_tx = get_tx_by_sn(payment_sn)
    payment_record = payment_tx.record

    try:
        _request_refund(payment_tx, payment_record, refund_tx, refund_record)
        return True
    except Exception as e:
        logger.info("failed to unblock refund: [{0}], [{1}]".format(
            refund_tx.sn, e.message))
        _block_refund(refund_record)
    return False
Ejemplo n.º 7
0
def query_withdraw(user_id, sn):
    data = request.values
    channel = request.channel

    user_map = channel.get_user_map(user_id)
    if user_map is None:
        return response.bad_request(
            msg='user not exists: [{0}]'.format(user_id))
    from_user_id = user_map.account_user_id

    tx = get_tx_by_sn(sn)
    if tx is None:
        return response.not_found(
            msg="withdraw tx not exits: [sn: {0}]".format(sn))
    withdraw_record = tx.record

    if withdraw_record.from_user_id != from_user_id:
        return response.bad_request('user [{0}] has no withdraw [{1}]'.format(
            user_id, sn))

    if tx.state == WithdrawTxState.SUCCESS:
        code = 0
    elif tx.state == WithdrawTxState.FAILED:
        code = 1
    else:
        code = 2

    params = {
        'code': code,
        'user_id': user_id,
        'sn': tx.sn,
        'amount': withdraw_record.amount,
        'actual_amount': withdraw_record.actual_amount,
        'fee': withdraw_record.fee
    }

    return response.success(data=params)
Ejemplo n.º 8
0
def get_payment_tx_by_sn(sn):
    tx = get_tx_by_sn(sn, search_stack=True)
    return tx