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)
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
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)
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)
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)
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
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)
def get_payment_tx_by_sn(sn): tx = get_tx_by_sn(sn, search_stack=True) return tx