def cancel(self, payment_id: str, cancel_amount: int = 0, full_cancel: bool = True) -> tuple:
        """Cancels payment and refunds to card
        https://oplata.tinkoff.ru/develop/api/payments/cancel-description/
        """
        if self.status in ['NEW', 'AUTHORIZED', 'CONFIRMED']:
            request_url = self.used_payment_gate_url + 'Cancel'

            request_dict = {
                "TerminalKey": self.terminal_key,
                "PaymentId": payment_id
            }

            if not full_cancel:
                request_dict["Amount"] = cancel_amount

            token = get_token(request_dict, self.token_password)
            request_dict["Token"] = token

            if not full_cancel:
                if self.receipt:
                    request_dict["Receipt"] = self.receipt

            response_list = send_request(request_dict, request_url)

            logger.log_into_file(response_list[0], response_list[1], 'Cancel', level='Debug',
                                 request_dict=request_dict)

            return response_list

        else:
            raise PaymentStatusError(f"Status is not valid for Cancel. Status: {self.status}.")
    def init(self, order_id: str, terminal_key: str = test_terminal_key,
             token_password: str = test_terminal_token_password, amount: int = 100, url: str = test_environment_url,
             two_step:  bool = False, init_token_required: bool = False, recurrent: bool = False) -> tuple:
        """Initialises payment session
        https://oplata.tinkoff.ru/develop/api/payments/init-description/
        """
        self.set_used_terminal_and_token_password(terminal_key, token_password)

        self.set_used_payment_gate_url(url)

        request_url = self.get_used_payment_gate_url() + 'Init'

        if two_step:
            self.pay_type = 'T'
        elif not two_step:
            self.pay_type = 'O'

        request_dict = {
            "TerminalKey": self.get_used_terminal_and_token_password(),
            "Amount": amount,
            "OrderId": order_id,
            "PayType": self.pay_type
        }

        if recurrent:
            request_dict["Recurrent"] = 'Y'

        if self.description:
            request_dict["Description"] = self.description

        if init_token_required:
            token = get_token(request_dict, self.token_password)
            request_dict["Token"] = token

        if self.data:
            request_dict["DATA"] = self.data

        if self.receipt:
            request_dict["Receipt"] = self.receipt

        answer_code, response = send_request(request_dict, request_url)

        logger.log_into_file(answer_code, response, 'Init', level='Debug', request_dict=request_dict)

        return answer_code, response
    def get_state(self, payment_id: str) -> tuple:
        """Gets payment status in acquiring system of bank
        https://oplata.tinkoff.ru/develop/api/payments/getstate-description/
        """
        request_url = self.used_payment_gate_url + 'GetState'

        request_dict = {
            "TerminalKey": self.terminal_key,
            "PaymentId": payment_id
        }

        token = get_token(request_dict, self.token_password)
        request_dict["Token"] = token

        response_list = send_request(request_dict, request_url)

        logger.log_into_file(response_list[0], response_list[1], 'GetState', level='Debug', request_dict=request_dict)

        return response_list
def send_eacq_confirm(payment_id: str) -> dict:
    """
    Sends Confirm and handles possible answers and exceptions.
    Can be used as example of realization only.

    :param payment_id: str
    :return: payment gateway response dictionary
    """

    try:

        answer_code, confirm_response = eacq.confirm(payment_id)
        eacq.set_internal_payment_status(confirm_response["Status"])

        return confirm_response

    except ConnectionError:
        logger.log_into_file('send_eacq_confirm', 'Error', message='Connection error')
        logger.log_exception("Exception occurred", exc_info=True)
    except MAPI_EACQ.RequestError:
        logger.log_into_file('send_eacq_init', 'Error', message='Request was not successful')
        logger.log_exception(MAPI_EACQ.RequestError, exc_info=True)
    except MAPI_EACQ.PaymentStatusError:
        logger.log_into_file('send_eacq_init', 'Error', message='Connection error')
        logger.log_exception(MAPI_EACQ.PaymentStatusError, exc_info=True)
def send_eacq_init() -> tuple:
    """Sends Init and handles possible answers and exceptions.
    Can be used as example of realization only.
    """
    order_id = gen_order_id()

    try:

        answer_code, init_response = eacq.init(order_id, two_step=True)

        payment_url = init_response["PaymentURL"]
        eacq.set_internal_payment_status(init_response["Status"])
        payment_id = init_response["PaymentId"]
        webbrowser.open_new(payment_url)
        time.sleep(20)

        get_state_response = eacq.get_state(payment_id)
        eacq.set_internal_payment_status(get_state_response[1]["Status"])

        return payment_id, get_state_response

    except ConnectionError:
        logger.log_into_file('send_eacq_init', 'Error', message='Connection error')
        logger.log_exception(ConnectionError, exc_info=True)
    except MAPI_EACQ.RequestError:
        logger.log_into_file('send_eacq_init', 'Error', message='Request was not successful')
        logger.log_exception(MAPI_EACQ.RequestError, exc_info=True)
    except MAPI_EACQ.PaymentStatusError:
        logger.log_into_file('send_eacq_init', 'Error', message='Connection error')
        logger.log_exception(MAPI_EACQ.PaymentStatusError, exc_info=True)
    def confirm(self, payment_id: str) -> tuple:
        """Confirms payment and transaction
        https://oplata.tinkoff.ru/develop/api/payments/confirm-description/
        """
        if self.status not in ['CONFIRMED', 'None']:
            request_url = self.used_payment_gate_url + 'Confirm'

            request_dict = {
                "TerminalKey": self.terminal_key,
                "PaymentId": payment_id
            }

            token = get_token(request_dict, self.token_password)
            request_dict["Token"] = token

            response_list = send_request(request_dict, request_url)

            logger.log_into_file(response_list[0], response_list[1], 'Confirm', level='Debug',
                                 request_dict=request_dict)

            return response_list
        else:
            raise PaymentStatusError(f"Status is not valid for Confirm. Status: {self.status}.")
    def charge(self, payment_id: str, rebill_id: str) -> tuple:
        """Makes recurrent payment from pre-saved card
        https://oplata.tinkoff.ru/develop/api/autopayments/charge-description/
        """
        if self.status in ['NEW']:
            request_url = self.used_payment_gate_url + 'Charge'

            request_dict = {
                "TerminalKey": self.terminal_key,
                "PaymentId": payment_id,
                "RebillId": rebill_id
            }

            token = get_token(request_dict, self.token_password)
            request_dict["Token"] = token

            response_list = send_request(request_dict, request_url)

            logger.log_into_file(response_list[0], response_list[1], 'Charge', level='Debug',
                                 request_dict=request_dict)

            return response_list
        elif self.status not in ['NEW']:
            raise PaymentStatusError(f"Status is not valid for Charge. Status: {self.status}.")