예제 #1
0
    def _build_pay_system_url_for_payment(payment: Payment, pay_system_service: PaymentSystemService,
                                          transaction_id: uuid, pay_return_url: str):
        """Build pay system url which will be used to redirect to the payment system."""
        current_app.logger.debug('<build_pay_system_url')
        invoice_reference = InvoiceReference.find_any_active_reference_by_invoice_number(payment.invoice_number)
        return_url = f'{pay_return_url}/{payment.id}/transaction/{transaction_id}'

        current_app.logger.debug('>build_pay_system_url')
        return pay_system_service.get_payment_system_url_for_payment(payment, invoice_reference, return_url)
예제 #2
0
    def update_transaction(
            transaction_id: uuid,  # pylint: disable=too-many-locals
            pay_response_url: str):
        """Update transaction record.

        Does the following:
        1. Find the payment record with the id
        2. Find the invoice record using the payment identifier
        3. Call the pay system service and get the receipt details
        4. Save the receipt record
        5. Change the status of Invoice
        6. Change the status of Payment
        7. Update the transaction record
        """
        #  TODO for now assumption is this def will be called only for credit card, bcol and internal payments.
        #  When start to look into the PAD and Online Banking may need to refactor here
        transaction_dao: PaymentTransactionModel = PaymentTransactionModel.find_by_id(
            transaction_id)
        if not transaction_dao:
            raise BusinessException(Error.INVALID_TRANSACTION_ID)
        if transaction_dao.status_code == TransactionStatus.COMPLETED.value:
            raise BusinessException(Error.INVALID_TRANSACTION)

        payment: Payment = Payment.find_by_id(transaction_dao.payment_id)
        payment_account: PaymentAccount = PaymentAccount.find_by_id(
            payment.payment_account_id)

        # For transactions other than Credit Card, there could be more than one invoice per payment.
        invoices: [Invoice] = Invoice.find_invoices_for_payment(
            transaction_dao.payment_id)

        if payment.payment_status_code == PaymentStatus.COMPLETED.value:
            # if the transaction status is EVENT_FAILED then publish to queue and return, else raise error
            if transaction_dao.status_code == TransactionStatus.EVENT_FAILED.value:
                # Publish status to Queue
                for invoice in invoices:
                    PaymentTransaction.publish_status(transaction_dao, invoice)

                transaction_dao.status_code = TransactionStatus.COMPLETED.value
                return PaymentTransaction.__wrap_dao(transaction_dao.save())

            raise BusinessException(Error.COMPLETED_PAYMENT)

        pay_system_service: PaymentSystemService = PaymentSystemFactory.create_from_payment_method(
            payment_method=payment.payment_method_code)

        invoice_reference = InvoiceReference.find_any_active_reference_by_invoice_number(
            payment.invoice_number)
        try:
            receipt_details = pay_system_service.get_receipt(
                payment_account, pay_response_url, invoice_reference)
            txn_reason_code = None
        except ServiceUnavailableException as exc:
            txn_reason_code = exc.status
            transaction_dao.pay_system_reason_code = txn_reason_code
            receipt_details = None

        if receipt_details:
            PaymentTransaction._update_receipt_details(invoices, payment,
                                                       receipt_details,
                                                       transaction_dao)
        else:
            transaction_dao.status_code = TransactionStatus.FAILED.value

        # check if the pay_response_url contains any failure status
        if not txn_reason_code:
            pay_system_reason_code = pay_system_service.get_pay_system_reason_code(
                pay_response_url)
            transaction_dao.pay_system_reason_code = pay_system_reason_code

        # Save response URL
        transaction_dao.transaction_end_time = datetime.now()
        transaction_dao.pay_response_url = pay_response_url
        transaction_dao = transaction_dao.save()

        # Publish message to unlock account if account is locked.
        if payment.payment_status_code == PaymentStatus.COMPLETED.value:
            active_failed_payments = Payment.get_failed_payments(
                auth_account_id=payment_account.auth_account_id)
            current_app.logger.info('active_failed_payments %s',
                                    active_failed_payments)
            if not active_failed_payments:
                PaymentAccount.unlock_frozen_accounts(
                    payment.payment_account_id)

        transaction = PaymentTransaction.__wrap_dao(transaction_dao)

        current_app.logger.debug('>update_transaction')
        return transaction