Azure function with insertion error into a MySQL table

Fabrício Fortaleza 150 Reputation points
2024-01-05T12:45:35.1233333+00:00

I have an Azure function that receives a POST request, uses the received values to make a GET request to another API, which returns a JSON containing several key-value pairs. The function extracts these values and inserts them into a table in a MySQL database.

I had to change the table name and updated it in my Azure Function, but upon checking the logs, I noticed that the code is still referencing the old table.

Does anyone have an idea how to fix this?

Here is the code below:

@app.route(route="information/send", auth_level=func.AuthLevel.ANONYMOUS)
def send_information(req: func.HttpRequest) -> func.HttpResponse:
    
    # Importa a public_key para descriptografar o webhook recebido
    public_key = os.environ["public_key_baas"]
    public_key_baas = base64.b64decode(public_key).decode("utf-8")
    
    try:
        # Decodifica o webhook recebido e salva os dados em uma variável
        signature_recebida = req.headers.get('SIGNATURE')

        # Se a assinatura não foi fornecida
        if signature_recebida is None:
            logging.error("A assinatura não foi fornecida.")
            return HttpResponse("A assinatura não foi fornecida.")

        header_decodificado = jwt.decode(signature_recebida, public_key_baas, algorithms='ES512')
        payload_extraido = req.get_json()

    except jwt.JWTError as jwt_error:
        logging.error(f"Erro no token: {str(jwt_error)}")
        return HttpResponse("O token fornecido não era o esperado.")

    except Exception as e:
        logging.error(f"Ocorreu um erro inesperado: {str(e)}")
        return HttpResponse("Ocorreu um erro inesperado.")

    # Importa as chaves private_key e api_key usadas na requisição feita com a bank_slip_key
    bank_slip_key = payload_extraido.get("Chave de consulta do titulo")
    api_key = os.environ["api_key_baas"]
    private_key_baas = os.environ["private_key_baas"]
    client_private_key = base64.b64decode(private_key_baas).decode("utf-8")
    
    def request_get():
        endpoint = f"/bank_slip/{bank_slip_key}"
        method = "GET"
        base_url = "https://api-auth.qitech.app"
        request_body = {}
        timestamp = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%fZ")

        jwt_header = {"typ": "JWT", "alg": "ES512"}

        json_body = json.dumps(request_body)
        md5_hash = md5(json_body.encode()).hexdigest()

        jwt_body = {"payload_md5": md5_hash, "timestamp": timestamp, "method": method, "uri": endpoint}

        encoded_header_token = jwt.encode(claims=jwt_body, key=client_private_key, algorithm="ES512", headers=jwt_header)

        signed_header = {"AUTHORIZATION": encoded_header_token, "API-CLIENT-KEY": api_key}

        url = f"{base_url}{endpoint}"

        response = requests.get(url=url, headers=signed_header, json=None)

        if response.status_code == 200:
            response_json = response.json()
            beneficiary_account_branch = response_json.get("beneficiary_account_branch")
            beneficiary_account_number = response_json.get("beneficiary_account_number")
            beneficiary_document_number = response_json.get("beneficiary_document_number")
            beneficiary_account_digit = response_json.get("beneficiary_account_digit")
            beneficiary_name = response_json.get("beneficiary_name")
            document_number = response_json.get("document_number")
            payer_document = response_json.get("payer_document")
            payer_name = response_json.get("payer_name")
            payer_postal_code = response_json.get("payer_postal_code")
            payer_adress = response_json.get("payer_address")
            code_number = next((item["payment_bank"]["name"] for item in response_json.get("occurrences", []) if item.get("payment_bank")), None)
            digitable_line = response_json.get("digitable_line")

            payload_extraido['Agencia do beneficiario'] = beneficiary_account_branch
            payload_extraido['Conta do beneficiario'] = beneficiary_account_number
            payload_extraido['Digito da conta'] = beneficiary_account_digit
            payload_extraido['Documento do beneficiario'] = beneficiary_document_number
            payload_extraido['Nome do beneficiario'] = beneficiary_name
            payload_extraido['Numero do titulo'] = document_number
            payload_extraido['Linha digitavel'] = digitable_line

            payload_extraido['Documento do pagador'] = payer_document
            payload_extraido['Nome do pagador'] = payer_name
            payload_extraido['CEP do pagador'] = payer_postal_code
            payload_extraido['Endereco do pagador'] = payer_adress
            payload_extraido['Banco do pagador'] = code_number

            try:
                # Declara as variáveis de conexão com o MySQL
                usuario = os.environ["usuario"]
                senha = os.environ["senha"]
                banco_de_dados = os.environ["banco_de_dados"]
                servidor = os.environ["servidor"]

                # Conectar ao banco de dados MySQL no Azure
                conn = mysql.connector.connect(
                    user=usuario,
                    password=senha,
                    database=banco_de_dados,
                    host=servidor,
                )

                cursor = conn.cursor()

                # Montar a query SQL de inserção
                query = '''
                    INSERT INTO qi_informe_pagamentos (`STATUS`, `MONTANTE_PAGO`, `CHAVE_CONSULTA`, `AGENCIA`, `CONTA`, `DIGITO`, `DOC_BENEFICIARIO`, `NOME_BENEFICIARIO`, `NUMERO_TITULO`, `LINHA_DIGITAVEL`, `DOC_PAGADOR`, `NOME_PAGADOR`, `CEP_PAGADOR`, `ENDERECO_PAGADOR`, `BANCO_PAGADOR`)
                    VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
                '''

                # Extrair os valores do dicionário e executar a query SQL
                valores = tuple(payload_extraido.values())
                cursor.execute(query, valores)

                # Commit (salvar) as alterações e fechar a conexão
                conn.commit()
                conn.close()
                
                logging.info(f"Webhook gravado na base de dados com sucesso!")
                return HttpResponse("Webhook gravado na base de dados com sucesso!", status_code=200)
                
            except mysql.connector.Error as err:
                logging.error(f"Ocorreu um erro na gravação dos dados: {err}")
                return HttpResponse("Ocorreu um erro na gravação dos dados.", status_code=500)

            except Exception as e:
                logging.error(f"Ocorreu um erro inesperado: {str(e)}")
                return HttpResponse("Ocorreu um erro inesperado.", status_code=500)
            
        else:
            logging.error(f"A requisição à API da QI falou, o status de retorno não foi == 200. Título que deu problema na consulta foi o: {bank_slip_key}.")
            return HttpResponse("Webhook não pôde ser gravado na fila, o status de retorno não foi == 200.")
    result = request_get()
    return result

Information in the logs:

"Table 'nerocapital.boletos_pagos' doesn't exist"

"boletos_pagos" That was the last name the table had.

Azure Functions
Azure Functions
An Azure service that provides an event-driven serverless compute platform.
5,911 questions
Azure Database for MySQL
Azure Database for MySQL
An Azure managed MySQL database service for app development and deployment.
986 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. MikeUrnun 9,777 Reputation points Moderator
    2024-01-11T03:50:31.7433333+00:00

    Hi @Fabrício Fortaleza - Thanks for reaching out, posting on the MS Q&A. I'm not sure which deployment method you're using but if it's the "run from package" method, is it possible that App Service may still be pointing to the old deployment package for serving requests? Could you check by verifying what's in the packagename.txt file matches the latest deployment package that was uploaded? If deployment method isn't the issue, we might check if there could've been an instance of the older version of your app attemping to process request after the table was renamed?

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.