Novo Ambiente | Atualização 4
17
.env
|
|
@ -10,6 +10,7 @@ SMTP_PASSWORD=j5j@QaSB\Z4<)W]M|hOYbC\605zfGcv:
|
|||
SMTP_HOST=mail.itguys.com.br
|
||||
SMTP_PORT=465
|
||||
SMTP_RECIPIENT=comercial@itguys.com.br
|
||||
|
||||
# Configurações LDAP (Windows AD)
|
||||
LDAP_SERVER=10.10.253.199/itguys.com.br
|
||||
LDAP_DOMAIN=itguys.com.br
|
||||
|
|
@ -17,7 +18,21 @@ LDAP_BASE_DN=dc=itguys,dc=com,dc=br
|
|||
LDAP_USER=itguys\teste.dev
|
||||
LDAP_PASSWORD=123Mudar
|
||||
|
||||
ZAMMAD_API=http://10.10.253.59/api/v1/
|
||||
#API ZAMMAD
|
||||
ZAMMAD_API= https://zammad.itguys.com.br/api/v1
|
||||
ZAMMAD_USERNAME=teste.dev@itguys.com.br
|
||||
ZAMMAD_PASSWORD=123Mudar
|
||||
ZAMMAD_TOKEN =QiFbQ7txT0BS_3N8GrwOzAS6f7ziVTa1VqcGGpaPFscvdcfnBVjgq699fFj6NpQW #Token expira em 2065
|
||||
|
||||
|
||||
#API Inter
|
||||
CLIENT_ID = bfedfb96-7caf-4310-8632-a924c5daa7e1
|
||||
CLIENT_SECRET = 502d577e-b324-4b93-9624-e6b082588dc5
|
||||
CERT_PATH = InterAPI_Certificado.crt
|
||||
CERT_KEY_PATH = keyinter.pem
|
||||
|
||||
#API ZABBIX
|
||||
ZABBIX_URL = https://mimir.itguys.com.br/zabbix/api_jsonrpc.php
|
||||
TOKEN_ZABBIX = 10925e9e452cade5270f4d930feb3b5e1aa2cc9b366c1c5b4d72996212b12c93
|
||||
ZABBIX_USER = vitoria.oliveira
|
||||
ZABBIX_PASSWORD = 123Mudar
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEljCCA36gAwIBAgIQJ18cUeVWL5QojTvvnDiLyTANBgkqhkiG9w0BAQsFADCB
|
||||
ijELMAkGA1UEBhMCQlIxFTATBgNVBAgMDE1pbmFzIEdlcmFpczEXMBUGA1UEBwwO
|
||||
QmVsbyBIb3Jpem9udGUxDDAKBgNVBAoMA0FQSTELMAkGA1UECwwCSVQxMDAuBgNV
|
||||
BAMMJ0FQSSBJbnRlcm1lZGlhdGUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5CTAeFw0y
|
||||
NTAxMjcxOTAyNTlaFw0yNjAxMjcyMDAyNTlaMIGrMQswCQYDVQQGEwJCUjELMAkG
|
||||
A1UECBMCUkoxFzAVBgNVBAcTDlJJTyBERSBKQU5FSVJPMS0wKwYDVQQLEyRjMzI3
|
||||
NWVhZi04NDA2LTQzMDAtOTMzNC04OTRlZTRhMWYyOGIxDTALBgNVBAoTBG51bGwx
|
||||
ODA2BgNVBAMTL1IgUk9DQU5DT1VSVCBDQVZBREFTIENPTlNVTFRPUklBIEVNIElO
|
||||
Rk9STUFUSUNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl8fvYOJe
|
||||
kMJ1BH9m95lQO9zLEG153PZuoSBgEvCJ522tJlAPp1oo+SgC1LCSRLaDOxhlJbIo
|
||||
0BIC5/ule6QmAMtaoC+qt+e8QzT8PKm7IX/SzpjziV7HNHKlEiNCeGC047iYTOWv
|
||||
c843uUVicMBZfSJXodzE9RYIC4oTZnB83gvlaVk7xVyP4Auimg09F4dZTQjeI06T
|
||||
RBgiPNJDn0+ilKWRUX2HGs0wnD2JX7wGPB+mkV0z5Rsv0F1D7IsIa3TdMsyBdzxX
|
||||
0haz/bSB/R5ZxMTHZ3bzYoPWd5cSKenYu1FyFTKHebFhIFy2Vz6kbakVOgrWZDFx
|
||||
yg8dzuTnKUzdWwIDAQABo4HUMIHRMAkGA1UdEwQCMAAwHwYDVR0jBBgwFoAUFBVp
|
||||
/TT0EQj/WbtOGcyVlyKK4DwwHQYDVR0OBBYEFHQ+z6vbCts4TrDS5s+hIVHbh6rz
|
||||
MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
|
||||
VQYDVR0fBE4wTDBKoEigRoZEaHR0cDovL2NybC1hcGkuYmkubG9jYWwvY3JsLzE5
|
||||
MzY0ZTc2LWM0YmUtNDBiNi05YzcxLWEzYTdiNDA0NzRhNC5jcmwwDQYJKoZIhvcN
|
||||
AQELBQADggEBAHbjYT794YA7W9KsX+uXQIxXvd5IBVt+xzQw787/PgQ3elJNS36R
|
||||
Yq5FdFjdvYDXTyFEi2YS+egqW+4wdBIvMUcM+86HhuhcKbkAjeMu1yM6vcORuuTV
|
||||
BJ47vbR3hQiABGYhzOeq00CazFcpnDgydxx0sIhzWsEYrKOozUcXqdPFxVCpeR0X
|
||||
rzEJgyrJd1l6fI+X8z/n3BCqYfCk+OJ8HYgTT8wpAJBVynuRNJRjYTIU3yySyEal
|
||||
Fyny4CZxltqbnS+gZedyJZYf9aEPxQKNXcdpqGdvnmLv62EuWU129Z97FJ9rWB39
|
||||
uFVdK6Uz+Klv+DqP3hDLatxqDsp30QrdwG0=
|
||||
-----END CERTIFICATE-----
|
||||
|
|
@ -9,6 +9,13 @@ from .routes.perfil import perfil
|
|||
from .routes.montagem import montagem
|
||||
from .routes.zabbix import zabbix
|
||||
from .routes.integrator import zammad
|
||||
from.routes.boletos import boletos
|
||||
from.routes.upload_img import imagem
|
||||
from.routes.servicos import servicos
|
||||
from.routes.empresas import empresas
|
||||
from.routes.newuser import newuser
|
||||
from.routes.integrazabbix import integra
|
||||
|
||||
# Inicializa o MySQL
|
||||
mysql = MySQL()
|
||||
|
||||
|
|
@ -33,7 +40,14 @@ def create_app():
|
|||
app.register_blueprint(perfil)
|
||||
app.register_blueprint(montagem)
|
||||
app.register_blueprint(zabbix)
|
||||
app.register_blueprint(integra)
|
||||
app.register_blueprint(zammad)
|
||||
app.register_blueprint(boletos)
|
||||
app.register_blueprint(imagem)
|
||||
app.register_blueprint(servicos)
|
||||
app.register_blueprint(empresas)
|
||||
app.register_blueprint(newuser)
|
||||
|
||||
|
||||
@app.route('/')
|
||||
def home():
|
||||
|
|
|
|||
|
|
@ -25,8 +25,14 @@ class Config:
|
|||
LDAP_PASSWORD = os.getenv('LDAP_PASSWORD', '123Mudar') # Senha do usuário LDAP
|
||||
|
||||
#Api Zammad
|
||||
zammad_api_url = 'http://zammad.itguys.com.br/api/v1'
|
||||
zammad_token = 'L081vJ19kood2uDlTSSt59LWBaewT9-a-MH_VKno8RY'
|
||||
zammad_api_url = os.getenv('zammad_api_url','http://zammad.itguys.com.br/api/v1')
|
||||
zammad_token = os.getenv('zammad_token','L081vJ19kood2uDlTSSt59LWBaewT9-a-MH_VKno8RY')
|
||||
|
||||
#ID Inter
|
||||
CLIENT_ID = os.getenv('CLIENT_ID',"bfedfb96-7caf-4310-8632-a924c5daa7e1")
|
||||
CLIENT_SECRET = os.getenv ('CLIENT_SECRET',"502d577e-b324-4b93-9624-e6b082588dc5")
|
||||
CERT_PATH = os.getenv('CERT_PATH',"InterAPI_Certificado.crt")
|
||||
CERT_KEY_PATH = os.getenv('CERT_KEY_PATH',"keyinter.pem")
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import re
|
|||
import ldap3
|
||||
from ldap3.core.exceptions import LDAPSocketOpenError, LDAPException
|
||||
from functools import wraps
|
||||
from flask_mysqldb import MySQL
|
||||
import logging
|
||||
from flask_mysqldb import MySQL
|
||||
|
||||
# Configuração de logging para depuração
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
|
@ -14,7 +14,6 @@ logging.basicConfig(level=logging.DEBUG)
|
|||
auth = Blueprint('auth', __name__)
|
||||
mysql = MySQL()
|
||||
|
||||
|
||||
# Decorador para validar o token JWT
|
||||
def token_required(f):
|
||||
@wraps(f)
|
||||
|
|
@ -26,22 +25,7 @@ def token_required(f):
|
|||
try:
|
||||
data = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=["HS256"])
|
||||
except jwt.ExpiredSignatureError:
|
||||
# Caso o token esteja expirado, gere um novo token
|
||||
try:
|
||||
# Obter o payload original para criar um novo token
|
||||
payload = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=["HS256"], options={"verify_exp": False})
|
||||
|
||||
# Gere um novo token com nova validade
|
||||
new_token = jwt.encode({
|
||||
'user_id': payload['user_id'],
|
||||
'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=1)
|
||||
}, current_app.config['SECRET_KEY'], algorithm="HS256")
|
||||
|
||||
response = jsonify({'msg': 'Token expirado! Novo token gerado.', 'new_token': new_token})
|
||||
response.status_code = 401
|
||||
return response
|
||||
except Exception as e:
|
||||
return jsonify({'msg': 'Erro ao processar o token expirado.', 'error': str(e)}), 401
|
||||
return jsonify({'msg': 'Token expirado!'}), 401
|
||||
except jwt.InvalidTokenError:
|
||||
return jsonify({'msg': 'Token inválido!'}), 401
|
||||
|
||||
|
|
@ -84,31 +68,20 @@ def login():
|
|||
except ValueError:
|
||||
return jsonify({'msg': 'Formato de usuário inválido. Use "usuario@dominio.com".'}), 400
|
||||
|
||||
# Buscar informações de domínio no banco de dados
|
||||
try:
|
||||
with mysql.connection.cursor() as cur:
|
||||
cur.execute("SELECT idempresa, ip_dominio FROM empresa WHERE dominio = %s", (domain,))
|
||||
empresa_result = cur.fetchone()
|
||||
|
||||
if not empresa_result:
|
||||
return jsonify({'msg': 'Domínio não encontrado no banco de dados'}), 404
|
||||
|
||||
id_empresa, ip_dominio = empresa_result
|
||||
|
||||
# Verificar se o usuário está associado à empresa no MySQL
|
||||
try:
|
||||
with mysql.connection.cursor() as cur:
|
||||
cur.execute("SELECT empresa_id, dominio FROM view_usuario_empresa WHERE usuario = %s AND dominio = %s", (username, domain))
|
||||
result = cur.fetchone()
|
||||
|
||||
if not result:
|
||||
return jsonify({'msg': 'Usuário não associado à empresa'}), 404
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Erro no banco de dados: {str(e)}")
|
||||
return jsonify({'msg': 'Erro no banco de dados'}), 500
|
||||
|
||||
# Conexão LDAP com autenticação
|
||||
ldap_server = f'ldap://{"itguys.com.br:389"}'
|
||||
# Autenticação LDAP usando domínio extraído
|
||||
ldap_server = f'ldap://{domain}:389'
|
||||
ldap_user = f'{domain}\\{username}'
|
||||
|
||||
try:
|
||||
|
|
@ -144,6 +117,3 @@ def login():
|
|||
except Exception as e:
|
||||
logging.error(f"Erro inesperado: {str(e)}")
|
||||
return jsonify({'msg': 'Erro inesperado durante a autenticação.'}), 500
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,334 @@
|
|||
import os
|
||||
import json
|
||||
import requests
|
||||
from time import time
|
||||
from functools import wraps
|
||||
from base64 import b64decode
|
||||
from datetime import datetime, timedelta
|
||||
from flask import Flask, Blueprint, jsonify, request, Response
|
||||
from flask_mysqldb import MySQL
|
||||
from flask_cors import CORS
|
||||
from .auth import token_required
|
||||
from dotenv import load_dotenv
|
||||
from flask import send_file
|
||||
import io
|
||||
|
||||
load_dotenv()
|
||||
|
||||
# Configurações da API do Banco Inter
|
||||
CLIENT_ID = os.environ.get("CLIENT_ID")
|
||||
CLIENT_SECRET = os.environ.get("CLIENT_SECRET")
|
||||
CERT_PATH = os.environ.get("CERT_PATH")
|
||||
CERT_KEY_PATH = os.environ.get("CERT_KEY_PATH")
|
||||
ACCOUNT = os.environ.get("ACCOUNT", None)
|
||||
API_BASE_URL = "https://cdpj.partners.bancointer.com.br"
|
||||
|
||||
boletos = Blueprint('boletos', __name__)
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
cors = CORS(app, resources={r"/v1/boletos/*": {"origins": "*", "methods": ["GET", "POST", "PUT", "OPTIONS"]}})
|
||||
app.config["CORS_HEADERS"] = ["Content-Type", "Authorization", "Content-Disposition", "Content-Length"]
|
||||
|
||||
MYSQL_HOST = os.environ.get('MYSQL_HOST')
|
||||
MYSQL_PORT = os.environ.get('MYSQL_PORT')
|
||||
MYSQL_USER = os.environ.get('MYSQL_USER')
|
||||
MYSQL_PASSWORD = os.environ.get('MYSQL_PASSWORD')
|
||||
MYSQL_DB = os.environ.get('MYSQL_DB')
|
||||
MYSQL_CURSORCLASS = os.environ.get("MYSQL_CURSORCLASS")
|
||||
|
||||
mysql = MySQL()
|
||||
token_cache = {}
|
||||
|
||||
def intercept_options(f):
|
||||
@wraps(f)
|
||||
def decorated(*args, **kwargs):
|
||||
if request.method == "OPTIONS":
|
||||
response = jsonify({"status": "ok"})
|
||||
response.headers.add("Access-Control-Allow-Origin", "*")
|
||||
response.headers.add("Access-Control-Allow-Methods", "GET,POST,PUT,OPTIONS")
|
||||
response.headers.add("Access-Control-Allow-Headers", "Content-Type,Authorization,Content-Disposition,Content-Length")
|
||||
return response, 200
|
||||
return f(*args, **kwargs)
|
||||
return decorated
|
||||
|
||||
|
||||
def obter_token(scopes=["boleto-cobranca.write", "boleto-cobranca.read"]):
|
||||
"""Obtem um token de acesso para a API do Banco Inter."""
|
||||
scopes_param = " ".join(scopes)
|
||||
if token_cache.get(scopes_param):
|
||||
cached_token = token_cache.get(scopes_param)
|
||||
# token is still valid
|
||||
if cached_token.get("expires_at") > int(time()):
|
||||
return cached_token["token"]
|
||||
try:
|
||||
request_string = f"client_id={CLIENT_ID}&client_secret={CLIENT_SECRET}&scope={scopes_param}&grant_type=client_credentials"
|
||||
print("request_string", request_string)
|
||||
response = requests.post(url=f"{API_BASE_URL}/oauth/v2/token",
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
cert=(CERT_PATH, CERT_KEY_PATH),
|
||||
data=request_string)
|
||||
data_json = response.json()
|
||||
token = data_json.get("access_token")
|
||||
token_cache[scopes_param] = {
|
||||
"token": token,
|
||||
"expires_at": data_json.get("expires_in") + int(time()),
|
||||
}
|
||||
return token
|
||||
except Exception as e:
|
||||
print(f"Erro ao obter token de acesso: {e}")
|
||||
return None
|
||||
|
||||
def emitir_cobranca(token, dados_cobranca):
|
||||
"""Emite uma cobrança para o Banco Inter de forma assíncrona."""
|
||||
headers = {
|
||||
"Authorization": f"Bearer {token}",
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json"
|
||||
}
|
||||
try:
|
||||
response = requests.post(
|
||||
f"{API_BASE_URL}/cobranca/v3/cobrancas",
|
||||
headers=headers,
|
||||
cert=(CERT_PATH, CERT_KEY_PATH),
|
||||
json=dados_cobranca
|
||||
)
|
||||
|
||||
# Captura a resposta completa
|
||||
resposta_json = response.json()
|
||||
|
||||
# Exibe detalhes da resposta para debug
|
||||
print("Código de status:", response.status_code)
|
||||
print("Resposta da API:", json.dumps(resposta_json, indent=4, ensure_ascii=False))
|
||||
|
||||
return resposta_json
|
||||
except Exception as e:
|
||||
print(f"Erro ao emitir cobrança: {e}")
|
||||
return None
|
||||
|
||||
def obter_cobranca(token, codigo_solicitacao):
|
||||
"""Obtem uma cobrança."""
|
||||
headers = {
|
||||
"Authorization": f"Bearer {token}",
|
||||
"Content-Type": "Application/json",
|
||||
}
|
||||
try:
|
||||
response = requests.get(f"{API_BASE_URL}/cobranca/v3/cobrancas/{codigo_solicitacao}",
|
||||
headers=headers,
|
||||
cert=(CERT_PATH, CERT_KEY_PATH))
|
||||
return response.json()
|
||||
except Exception as e:
|
||||
print(f"Erro ao emitir cobrança:{e}")
|
||||
return None
|
||||
|
||||
def obter_cobranca_pdf(token, codigo_solicitacao):
|
||||
"""Obtem o PDF de uma cobrança."""
|
||||
headers = {
|
||||
"Authorization": f"Bearer {token}",
|
||||
"Content-Type": "Application/json",
|
||||
}
|
||||
try:
|
||||
# Certifique-se de que o codigo_solicitacao seja inserido corretamente na URL
|
||||
url = f"{API_BASE_URL}/cobranca/v3/cobrancas/{codigo_solicitacao}/pdf"
|
||||
response = requests.get(url,
|
||||
headers=headers,
|
||||
cert=(CERT_PATH, CERT_KEY_PATH))
|
||||
return response.json()
|
||||
except Exception as e:
|
||||
print(f"Erro ao emitir cobrança:{e}")
|
||||
return None
|
||||
|
||||
def processar_cobranca_cliente(cliente, token):
|
||||
"""
|
||||
Processa a emissão da cobrança para um cliente específico,
|
||||
retornando os dados relevantes.
|
||||
"""
|
||||
id_empresa = cliente["idempresa"]
|
||||
hoje = datetime.now()
|
||||
vencimento = (hoje + timedelta(days=5)).strftime("%Y-%m-%d")
|
||||
|
||||
dados_cobranca = {
|
||||
"seuNumero": f"boleto-{id_empresa}",
|
||||
"valorNominal": str(cliente["valor_servico"]),
|
||||
"dataVencimento": vencimento,
|
||||
"numDiasAgenda": 30,
|
||||
"pagador": {
|
||||
"cpfCnpj": cliente["cpf_cnpj"],
|
||||
"tipoPessoa": cliente["tipo_pessoa"],
|
||||
"nome": cliente["nome"],
|
||||
"telefone": cliente["telefone"],
|
||||
"endereco": cliente["endereco"],
|
||||
"cidade": cliente["cidade"],
|
||||
"uf": cliente["uf"],
|
||||
"cep": cliente["cep"],
|
||||
},
|
||||
"formasRecebimento": ["BOLETO", "PIX"],
|
||||
}
|
||||
|
||||
emissao_cobranca = emitir_cobranca(token, dados_cobranca)
|
||||
codigo_solicitacao = emissao_cobranca.get("codigoSolicitacao") if emissao_cobranca else None
|
||||
if not codigo_solicitacao:
|
||||
return {
|
||||
"cliente": cliente,
|
||||
"status": "erro",
|
||||
"mensagem": "Falha ao emitir cobrança."
|
||||
}
|
||||
|
||||
cobranca = obter_cobranca(token, codigo_solicitacao)
|
||||
if not cobranca:
|
||||
return {
|
||||
"cliente": cliente,
|
||||
"status": "erro",
|
||||
"mensagem": "Falha ao obter cobrança."
|
||||
}
|
||||
|
||||
boleto_data = cobranca.get("cobranca", {}).get("boleto", {})
|
||||
codigo_barras = boleto_data.get("codigoBarras")
|
||||
linha_digitavel = cobranca.get("boleto", {}).get("linhaDigitavel")
|
||||
pix_data = cobranca.get("pix", {})
|
||||
pix_copia_e_cola = pix_data.get("pixCopiaECola")
|
||||
|
||||
cobranca_pdf = obter_cobranca_pdf(token, codigo_solicitacao)
|
||||
if not cobranca_pdf or "pdf" not in cobranca_pdf:
|
||||
return {
|
||||
"cliente": cliente,
|
||||
"status": "erro",
|
||||
"mensagem": "Falha ao obter PDF da cobrança."
|
||||
}
|
||||
|
||||
return {
|
||||
"cliente": cliente,
|
||||
"status": "sucesso",
|
||||
"codigo_solicitacao": codigo_solicitacao,
|
||||
"codigo_barras": codigo_barras,
|
||||
"linha_digitavel": linha_digitavel,
|
||||
"pix_copia_e_cola": pix_copia_e_cola,
|
||||
"pdf": cobranca_pdf["pdf"],
|
||||
}
|
||||
|
||||
|
||||
@boletos.route('/', methods=['POST', 'OPTIONS'])
|
||||
@intercept_options
|
||||
@token_required
|
||||
def gerar_boletos(data):
|
||||
|
||||
domain = data.get('domain')
|
||||
escopos = data.get('scopes', [])
|
||||
escopos.append("boleto-cobranca.write")
|
||||
escopos.append("boleto-cobranca.read")
|
||||
print("data", data)
|
||||
print(domain)
|
||||
print(escopos)
|
||||
if 'boleto-cobranca.write' not in escopos:
|
||||
return jsonify({"erro": "Permissão necessária: boleto-cobranca.write"}), 403
|
||||
if not domain:
|
||||
return jsonify({"error": "Domínio não encontrado no token"}), 400
|
||||
|
||||
hoje = datetime.now()
|
||||
if hoje.day > 12:
|
||||
return jsonify({"erro": "Boletos só podem ser gerados até o dia 12 de cada mês."}), 403
|
||||
|
||||
try:
|
||||
cur = mysql.connection.cursor()
|
||||
cur.execute(
|
||||
"SELECT idempresa, nome, cpf_cnpj, tipo_pessoa, telefone, endereco, cidade, uf, cep, valor_servico FROM empresa WHERE dominio = %s",
|
||||
(domain,)
|
||||
)
|
||||
clientes = cur.fetchall()
|
||||
cur.close()
|
||||
if not clientes:
|
||||
return jsonify({"erro": "Nenhum cliente encontrado."}), 404
|
||||
except Exception as e:
|
||||
print(f"Erro ao acessar o banco de dados: {e}")
|
||||
return jsonify({"erro": "Erro ao acessar o banco de dados."}), 500
|
||||
|
||||
token = obter_token(escopos)
|
||||
if not token:
|
||||
return jsonify({"erro": "Falha ao obter o token de acesso."}), 401
|
||||
|
||||
resultados = []
|
||||
for cliente in clientes:
|
||||
resultado = processar_cobranca_cliente(cliente, token)
|
||||
resultados.append(resultado)
|
||||
|
||||
return jsonify({"resultados": resultados}), 200
|
||||
|
||||
|
||||
@boletos.route('/<codigo_solicitacao>', methods=['GET', 'OPTIONS'])
|
||||
@intercept_options
|
||||
@token_required
|
||||
def recuperar_cobranca(token_data, codigo_solicitacao):
|
||||
print("codigo_solicitacao", codigo_solicitacao)
|
||||
|
||||
scopes = token_data.get('scopes', [])
|
||||
print("token_data", token_data)
|
||||
|
||||
if 'boleto-cobranca.read' not in scopes:
|
||||
return jsonify({"erro": "Permissao necessaria: boleto-cobranca.read"}), 403
|
||||
|
||||
token = obter_token(scopes)
|
||||
if not token:
|
||||
return jsonify({"erro": "Falha ao obter o token de acesso"}), 401
|
||||
|
||||
cobranca = obter_cobranca(token, codigo_solicitacao)
|
||||
if cobranca is None:
|
||||
return jsonify({"erro": "Erro ao obter PDF"}), 404
|
||||
|
||||
try:
|
||||
codigo_barras = cobranca.get("boleto").get("codigoBarras")
|
||||
linha_digitavel = cobranca.get("boleto").get("linhaDigitavel")
|
||||
pix_copia_e_cola = cobranca.get("pix").get("pixCopiaECola")
|
||||
|
||||
return jsonify({
|
||||
"codigo_solicitacao": codigo_solicitacao,
|
||||
"codigo_barras": codigo_barras,
|
||||
"linha_digitavel": linha_digitavel,
|
||||
"pix_copia_e_cola": pix_copia_e_cola,
|
||||
}), 200
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({"erro": f"Erro ao buscar cobranca: {e}"}), 500
|
||||
|
||||
|
||||
@boletos.route('/<codigo_solicitacao>/pdf', methods=['GET', 'OPTIONS'])
|
||||
@intercept_options
|
||||
@token_required
|
||||
def recuperar_boleto(token_data, codigo_solicitacao):
|
||||
print("codigo_solicitacao", codigo_solicitacao)
|
||||
|
||||
scopes = token_data.get('scopes', [])
|
||||
print("token_data", token_data)
|
||||
|
||||
if 'boleto-cobranca.read' not in scopes:
|
||||
return jsonify({"erro": "Permissao necessaria: boleto-cobranca.read"}), 403
|
||||
|
||||
token = obter_token(scopes)
|
||||
if not token:
|
||||
return jsonify({"erro": "Falha ao obter o token de acesso"}), 401
|
||||
|
||||
cobranca_pdf = obter_cobranca_pdf(token, codigo_solicitacao)
|
||||
if cobranca_pdf is None:
|
||||
return jsonify({"erro": "Erro ao obter PDF"}), 404
|
||||
|
||||
try:
|
||||
pdf_content_base64 = cobranca_pdf["pdf"]
|
||||
pdf_content_bytes = b64decode(pdf_content_base64, validate=True)
|
||||
return Response(pdf_content_bytes,
|
||||
mimetype='application/pdf',
|
||||
headers={
|
||||
"Content-Disposition": "inline; filename=boleto.pdf",
|
||||
"Content-Type": "application/pdf",
|
||||
"Content-Length": len(pdf_content_bytes)
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({"erro": f"Erro ao decodificar PDF: {e}"}), 500
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.register_blueprint(boletos)
|
||||
app.run(port=5000, debug=True)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import os
|
||||
import sys
|
||||
import requests
|
||||
from dotenv import load_dotenv
|
||||
from flask import Blueprint
|
||||
|
||||
load_dotenv()
|
||||
|
||||
codigo_solicitacao = "<ALGUM_CODIGO_DE_SOLICITACAO>"
|
||||
API_BASE_URL = "https://dev.itguys.com.br"
|
||||
url = f"{API_BASE_URL}/v1/boletos/{codigo_solicitacao}/pdf"
|
||||
headers = {
|
||||
"Authorization": "Bearer <JWT_SECRET>",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
try:
|
||||
response = requests.get(url, headers=headers)
|
||||
if response.status_code != 200:
|
||||
print("Erro obtendo o PDF")
|
||||
sys.exit(1)
|
||||
# salva o conteudo da resposta em um arquivo, pois ja retorna como bytes
|
||||
with open(f"{codigo_solicitacao}-cobranca.pdf", "wb") as pdf_file:
|
||||
pdf_file.write(response.content)
|
||||
print(f"PDF salvo em {codigo_solicitacao}-cobranca.pdf")
|
||||
except Exception as e:
|
||||
print(e)
|
||||
sys.exit(1)
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import logging
|
||||
from flask import Blueprint, jsonify
|
||||
from flask_mysqldb import MySQL
|
||||
from .auth import token_required # Importando o token_required
|
||||
|
||||
|
||||
|
||||
empresas = Blueprint('empresas', __name__) # Criando o Blueprint
|
||||
mysql = MySQL() # Criando a instância do MySQL
|
||||
|
||||
@empresas.route('/empresas', methods=['GET'])
|
||||
@token_required
|
||||
def listar_empresas(data): # Agora aceita o argumento 'data'
|
||||
try:
|
||||
cur = mysql.connection.cursor()
|
||||
cur.execute("SELECT idempresa, nome, dominio FROM empresa")
|
||||
resultados = cur.fetchall()
|
||||
|
||||
# Ajuste aqui: Adicionando o 'id_empresa' no dicionário
|
||||
empresas_list = [{"idempresa": row['idempresa'], "nome": row['nome'], "dominio": row['dominio']} for row in resultados]
|
||||
|
||||
return jsonify(empresas_list), 200
|
||||
except Exception:
|
||||
return jsonify({"erro": "Erro interno no servidor"}), 500
|
||||
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
import os
|
||||
from time import time
|
||||
from functools import wraps
|
||||
from datetime import date
|
||||
import requests
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Carregar variáveis de ambiente do arquivo .env
|
||||
load_dotenv()
|
||||
|
||||
# Definição das credenciais e URL base da API
|
||||
CLIENT_ID = os.environ.get("CLIENT_ID")
|
||||
CLIENT_SECRET = os.environ.get("CLIENT_SECRET")
|
||||
CERT_PATH = os.environ.get("CERT_PATH")
|
||||
CERT_KEY_PATH = os.environ.get("CERT_KEY_PATH")
|
||||
ACCOUNT = os.environ.get("ACCOUNT", None)
|
||||
API_BASE_URL = "https://cdpj.partners.bancointer.com.br"
|
||||
|
||||
# Cache para tokens de acesso
|
||||
token_cache = {}
|
||||
|
||||
def token_required(f):
|
||||
@wraps(f)
|
||||
def decorated(*args, **kwargs):
|
||||
data = {
|
||||
"domain": "example.com",
|
||||
"scopes": ["boleto-cobranca.write", "boleto-cobranca.read"]
|
||||
}
|
||||
return f(data, *args, **kwargs)
|
||||
return decorated
|
||||
|
||||
def obter_token(scopes=["boleto-cobranca.write", "boleto-cobranca.read"]):
|
||||
"""Obtem um token de acesso para a API do Banco Inter."""
|
||||
scopes_param = " ".join(scopes)
|
||||
if token_cache.get(scopes_param):
|
||||
cached_token = token_cache.get(scopes_param)
|
||||
# token is still valid
|
||||
if cached_token.get("expires_at") > int(time()):
|
||||
return cached_token["token"]
|
||||
try:
|
||||
request_string = f"client_id={CLIENT_ID}&client_secret={CLIENT_SECRET}&scope={scopes_param}&grant_type=client_credentials"
|
||||
print("request_string", request_string)
|
||||
response = requests.post(url=f"{API_BASE_URL}/oauth/v2/token",
|
||||
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||
cert=(CERT_PATH, CERT_KEY_PATH),
|
||||
data=request_string)
|
||||
|
||||
# Verificar o status da resposta
|
||||
if response.status_code != 200:
|
||||
print(f"Erro na requisição: {response.status_code}")
|
||||
print("Resposta bruta:", response.text) # Imprime a resposta bruta para debugar
|
||||
|
||||
data_json = response.json()
|
||||
print("Resposta JSON:", data_json) # Imprimir o JSON da resposta
|
||||
token = data_json.get("access_token")
|
||||
|
||||
# Cache do token
|
||||
token_cache[scopes_param] = {
|
||||
"token": token,
|
||||
"expires_at": data_json.get("expires_in") + int(time()),
|
||||
}
|
||||
return token
|
||||
except Exception as e:
|
||||
print(f"Erro ao obter token de acesso: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def get_balance():
|
||||
"""Obtém o saldo da conta no Banco Inter."""
|
||||
token = obter_token(["saldo.read"])
|
||||
if not token:
|
||||
print("Erro: não foi possível obter o token de acesso.")
|
||||
return None
|
||||
|
||||
try:
|
||||
response = requests.get(
|
||||
f"{API_BASE_URL}/banking/v2/saldo",
|
||||
headers={"Authorization": f"Bearer {token}"},
|
||||
cert=(CERT_PATH, CERT_KEY_PATH)
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
except requests.RequestException as e:
|
||||
print(f"Erro ao obter saldo: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def get_statements(start_date: str, end_date: str):
|
||||
"""Obtém o extrato da conta no Banco Inter entre as datas informadas."""
|
||||
token = obter_token(["extrato.read"])
|
||||
if not token:
|
||||
print("Erro: não foi possível obter o token de acesso.")
|
||||
return None
|
||||
|
||||
try:
|
||||
response = requests.get(
|
||||
f"{API_BASE_URL}/banking/v2/extrato",
|
||||
params={"dataInicio": start_date, "dataFim": end_date},
|
||||
headers={"Authorization": f"Bearer {token}"},
|
||||
cert=(CERT_PATH, CERT_KEY_PATH)
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
except requests.RequestException as e:
|
||||
print(f"Erro ao obter extrato: {e}")
|
||||
return None
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
time_now = time()
|
||||
yesterday = date.fromtimestamp(time_now - 60 * 60 * 24).strftime("%Y-%m-%d")
|
||||
today = date.fromtimestamp(time_now).strftime("%Y-%m-%d")
|
||||
|
||||
print(f"Obtendo informações financeiras para o período: {yesterday} - {today}")
|
||||
|
||||
# Obter saldo
|
||||
balance_data = get_balance()
|
||||
print("Saldo:", balance_data)
|
||||
|
||||
# Obter extrato
|
||||
statements_data = get_statements(yesterday, today)
|
||||
print("Extrato:", statements_data)
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
from flask import Blueprint, jsonify
|
||||
from .auth import token_required # Importa o decorador de autenticação
|
||||
from .newzabbix import zapi # Importa a conexão Zabbix
|
||||
|
||||
integra = Blueprint('integra', __name__)
|
||||
|
||||
def obter_dados_zabbix():
|
||||
try:
|
||||
grupos = zapi.hostgroup.get(output="extend")
|
||||
resultado = []
|
||||
|
||||
for grupo in grupos:
|
||||
hosts = zapi.host.get(groupids=grupo['groupid'], output="extend")
|
||||
hosts_info = []
|
||||
|
||||
for host in hosts:
|
||||
itens = zapi.item.get(hostids=host['hostid'], output="extend",
|
||||
filter={"key_": ["system.uptime", "net.if.in", "net.if.out", "vm.memory.size", "vfs.fs.size"]})
|
||||
|
||||
metricas = {item['key_']: item.get('lastvalue', 'N/A') for item in itens}
|
||||
|
||||
packet_loss = zapi.item.get(hostids=host['hostid'], filter={"key_": "net.ping.loss"}, output="extend")
|
||||
metricas["net.ping.loss"] = packet_loss[0]['lastvalue'] if packet_loss else 'N/A'
|
||||
|
||||
hosts_info.append({
|
||||
"host_name": host['name'],
|
||||
"metrics": metricas
|
||||
})
|
||||
|
||||
resultado.append({
|
||||
"group_id": grupo['groupid'],
|
||||
"group_name": grupo['name'],
|
||||
"hosts": hosts_info
|
||||
})
|
||||
|
||||
return resultado, 200
|
||||
|
||||
except Exception as e:
|
||||
return {"error": "Erro ao buscar dados do Zabbix", "details": str(e)}, 500
|
||||
|
||||
@integra.route('/zabbix/hosts', methods=['GET'])
|
||||
@token_required
|
||||
def hosts_e_metricas(_):
|
||||
dados, status_code = obter_dados_zabbix()
|
||||
return jsonify(dados), status_code
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
import logging
|
||||
from flask import Blueprint, jsonify, request
|
||||
from .auth import token_required
|
||||
from flask_mysqldb import MySQL
|
||||
|
||||
newuser = Blueprint('newuser', __name__)
|
||||
|
||||
mysql = MySQL()
|
||||
|
||||
# Configuração de logging
|
||||
logging.basicConfig(level=logging.DEBUG) # Log no nível de debug
|
||||
|
||||
@newuser.route('/inserir', methods=['POST'])
|
||||
@token_required
|
||||
def inserir_dados(get): # Recebe current_user do decorador
|
||||
data = request.get_json()
|
||||
|
||||
nome_completo = data.get('nome_completo')
|
||||
usuario_ad = data.get('usuario_ad')
|
||||
empresa = data.get('empresa')
|
||||
dominio_empresa = data.get('dominio_empresa')
|
||||
|
||||
if not nome_completo or not usuario_ad or not empresa or not dominio_empresa:
|
||||
return jsonify({'erro': 'Todos os campos são obrigatórios'}), 400
|
||||
|
||||
conn = mysql.connection
|
||||
cursor = conn.cursor()
|
||||
|
||||
try:
|
||||
query = """
|
||||
INSERT INTO usuarios (nome, usuario, empresa, dominio)
|
||||
VALUES (%s, %s, %s, %s)
|
||||
"""
|
||||
cursor.execute(query, (nome_completo, usuario_ad, empresa, dominio_empresa))
|
||||
conn.commit()
|
||||
|
||||
return jsonify({'message': 'Dados inseridos com sucesso!'}), 200
|
||||
|
||||
except Exception as err:
|
||||
logging.error(f"Erro ao inserir dados: {str(err)}", exc_info=True) # Logando erro com traceback
|
||||
return jsonify({'erro': f'Erro ao inserir dados: {str(err)}'}), 500
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
from pyzabbix import ZabbixAPI
|
||||
|
||||
# Connect to the Zabbix server
|
||||
zapi = ZabbixAPI("https://mimir.itguys.com.br/zabbix/api_jsonrpc.php")
|
||||
|
||||
# Login to the Zabbix API
|
||||
zapi.login(token="10925e9e452cade5270f4d930feb3b5e1aa2cc9b366c1c5b4d72996212b12c93")
|
||||
|
||||
# Retrieve a list of host groups (not hosts themselves)
|
||||
groups = zapi.hostgroup.get(output="extend")
|
||||
|
||||
# Print group information and metrics
|
||||
for group in groups:
|
||||
print(f"Group ID: {group['groupid']}, Group Name: {group['name']}")
|
||||
|
||||
# Retrieve hosts in this group
|
||||
hosts = zapi.host.get(groupids=group['groupid'], output="extend")
|
||||
|
||||
for host in hosts:
|
||||
print(f" Host Name: {host['name']}")
|
||||
|
||||
# Retrieve items (metrics) for each host
|
||||
items = zapi.item.get(hostids=host['hostid'], output="extend",
|
||||
filter={"key_": ["system.uptime", "net.if.in", "net.if.out", "vm.memory.size", "vfs.fs.size"]})
|
||||
|
||||
# Print metrics for each host
|
||||
for item in items:
|
||||
# Check which metric it corresponds to and print it
|
||||
if item['key_'] == "system.uptime":
|
||||
print(f" Uptime: {item['lastvalue']} seconds")
|
||||
elif item['key_'] == "net.if.in":
|
||||
print(f" Network In: {item['lastvalue']} bytes")
|
||||
elif item['key_'] == "net.if.out":
|
||||
print(f" Network Out: {item['lastvalue']} bytes")
|
||||
elif item['key_'] == "vm.memory.size":
|
||||
print(f" Memory Usage: {item['lastvalue']} bytes")
|
||||
elif item['key_'] == "vfs.fs.size":
|
||||
print(f" Disk Usage: {item['lastvalue']} bytes")
|
||||
|
||||
# Retrieve the network packet loss (example metric)
|
||||
# This can vary depending on your Zabbix configuration for ping or similar metrics
|
||||
network_packet_loss = zapi.item.get(hostids=host['hostid'],
|
||||
filter={"key_": "net.ping.loss"}, output="extend")
|
||||
for loss in network_packet_loss:
|
||||
print(f" Packet Loss: {loss['lastvalue']} %")
|
||||
|
||||
# Logout from the Zabbix API
|
||||
zapi.user.logout()
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
from flask import Blueprint, jsonify
|
||||
from flask_mysqldb import MySQL
|
||||
from .auth import token_required
|
||||
|
||||
servicos = Blueprint('servicos', __name__)
|
||||
|
||||
mysql = MySQL() # Instância do MySQL será configurada no app principal
|
||||
|
||||
@servicos.route('/servicos', methods=['GET'])
|
||||
@token_required
|
||||
def listar_servicos(data):
|
||||
try:
|
||||
domain = data.get('domain', '') # Obtém o domínio do usuário do token
|
||||
if not domain:
|
||||
return jsonify({"status": "error", "message": "Usuário não autenticado!"}), 401
|
||||
|
||||
# Conecta ao banco de dados e consulta os serviços
|
||||
cur = mysql.connection.cursor()
|
||||
|
||||
query = """
|
||||
SELECT `servico1`, `servico2`, `servico3`, `servico4`, `servico5`,
|
||||
`servico6`, `servico9`, `servico12`
|
||||
FROM `servicos` WHERE `dominio` = %s
|
||||
"""
|
||||
cur.execute(query, (domain,))
|
||||
results = cur.fetchall()
|
||||
cur.close()
|
||||
|
||||
|
||||
# Verificando se resultados foram retornados
|
||||
if results:
|
||||
# Quando a consulta retorna uma tupla com dicionário, acessamos o primeiro item da tupla
|
||||
row = results[0] # A primeira linha é um dicionário
|
||||
servicos_prestados = {
|
||||
"servico1": row.get('servico1'),
|
||||
"servico2": row.get('servico2'),
|
||||
"servico3": row.get('servico3'),
|
||||
"servico4": row.get('servico4'),
|
||||
"servico5": row.get('servico5'),
|
||||
"servico6": row.get('servico6'),
|
||||
"servico9": row.get('servico9'),
|
||||
"servico12": row.get('servico12'),
|
||||
}
|
||||
|
||||
return jsonify(servicos_prestados), 200
|
||||
else:
|
||||
return jsonify({"erro": "Nenhum serviço encontrado"}), 404
|
||||
except Exception as e:
|
||||
print(f"Erro interno: {e}") # Print detalhado do erro
|
||||
return jsonify({"status": "error", "message": "Erro interno"}), 500
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
from flask_mysqldb import MySQL
|
||||
from flask import Flask, Blueprint, jsonify, request
|
||||
from .auth import token_required
|
||||
import os
|
||||
import traceback
|
||||
import MySQLdb
|
||||
|
||||
imagem = Blueprint('imagem', __name__)
|
||||
mysql = MySQL()
|
||||
|
||||
CAMINHO_PERFIL = "/var/www/Backend/itguys/ambiente_python/repositorio_img/perfil/"
|
||||
CAMINHO_FUNDOS = "/var/www/Backend/itguys/ambiente_python/repositorio_img/fundos/"
|
||||
|
||||
def salvar_imagem(arquivo, tipo_imagem, nome_usuario):
|
||||
"""Salva a imagem no diretório correspondente e retorna o caminho relativo"""
|
||||
nome_arquivo = f"{nome_usuario}.jpg"
|
||||
|
||||
if tipo_imagem == "perfil":
|
||||
caminho_diretorio = CAMINHO_PERFIL
|
||||
caminho_relativo = f"perfil/{nome_arquivo}"
|
||||
else:
|
||||
caminho_diretorio = CAMINHO_FUNDOS
|
||||
caminho_relativo = f"fundos/{nome_arquivo}"
|
||||
|
||||
caminho_completo = os.path.join(caminho_diretorio, nome_arquivo)
|
||||
|
||||
# Garante que o diretório existe
|
||||
os.makedirs(caminho_diretorio, exist_ok=True)
|
||||
|
||||
# Salva a imagem
|
||||
arquivo.save(caminho_completo)
|
||||
|
||||
return caminho_relativo # Retorna o caminho relativo para o banco de dados
|
||||
|
||||
def get_db_connection():
|
||||
"""Verifica e retorna uma conexão válida com o banco de dados"""
|
||||
try:
|
||||
conn = mysql.connection
|
||||
conn.ping() # Verifica se a conexão está ativa
|
||||
return conn
|
||||
except MySQLdb.OperationalError:
|
||||
return mysql.connection # Tenta criar uma nova conexão
|
||||
|
||||
@imagem.route('/imagem', methods=['POST'])
|
||||
@token_required
|
||||
def receber_imagem(data):
|
||||
try:
|
||||
nome_usuario = data.get('user', '') # Separa o usuário do dominío
|
||||
if not nome_usuario:
|
||||
return jsonify({"status": "error", "message": "Usuário não autenticado!"}), 405
|
||||
|
||||
nome_usuario = nome_usuario.split('@')[0]
|
||||
|
||||
|
||||
imagem_perfil = request.files.get('perfil')
|
||||
imagem_foto_fundo = request.files.get('foto_fundo')
|
||||
|
||||
# Verifica se as imagens foram enviadas corretamente
|
||||
if not imagem_perfil or not imagem_foto_fundo:
|
||||
return jsonify({"status": "error", "message": "Imagens não enviadas corretamente!"}), 400
|
||||
|
||||
# Salva as imagens e obtém os caminhos relativos
|
||||
caminho_perfil = salvar_imagem(imagem_perfil, "perfil", nome_usuario)
|
||||
caminho_foto_fundo = salvar_imagem(imagem_foto_fundo, "fundo", nome_usuario)
|
||||
|
||||
# Conecta-se ao banco e executa a query de atualização
|
||||
conn = get_db_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
query = """
|
||||
UPDATE usuarios
|
||||
SET img_perfil = %s, img_fundo = %s
|
||||
WHERE usuario = %s
|
||||
"""
|
||||
valores = (caminho_perfil, caminho_foto_fundo, nome_usuario)
|
||||
|
||||
cursor.execute(query, valores)
|
||||
conn.commit()
|
||||
cursor.close()
|
||||
|
||||
return jsonify({"status": "success", "message": "Imagens enviadas e salvas com sucesso!"}), 200
|
||||
|
||||
except MySQLdb.OperationalError as e:
|
||||
return jsonify({"status": "error", "message": f"Erro de conexão com o banco de dados: {str(e)}"}), 500
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
return jsonify({"status": "error", "message": str(e)}), 500
|
||||
|
||||
|
|
@ -1,9 +1,12 @@
|
|||
import requests
|
||||
from dotenv import load_dotenv
|
||||
|
||||
base_url = "http://zammad.itguys.com.br/api/v1"
|
||||
zammad_token = "kT0IXO8aVhPoTLcMRNL290rqd9jbRhhM0zf8MgBo3n00NLChToSU6rOGnMgWA0M2"
|
||||
load_dotenv()
|
||||
|
||||
def listar_tickets(domain):
|
||||
base_url = "https://zammad.itguys.com.br/api/v1"
|
||||
zammad_token = "QiFbQ7txT0BS_3N8GrwOzAS6f7ziVTa1VqcGGpaPFscvdcfnBVjgq699fFj6NpQW" #Token expira em 2065
|
||||
|
||||
def listar_tickets(domain, limit=500, offset=0):
|
||||
try:
|
||||
headers = {
|
||||
"Authorization": f"Token token={zammad_token}",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCXx+9g4l6QwnUE
|
||||
f2b3mVA73MsQbXnc9m6hIGAS8Innba0mUA+nWij5KALUsJJEtoM7GGUlsijQEgLn
|
||||
+6V7pCYAy1qgL6q357xDNPw8qbshf9LOmPOJXsc0cqUSI0J4YLTjuJhM5a9zzje5
|
||||
RWJwwFl9Ileh3MT1FggLihNmcHzeC+VpWTvFXI/gC6KaDT0Xh1lNCN4jTpNEGCI8
|
||||
0kOfT6KUpZFRfYcazTCcPYlfvAY8H6aRXTPlGy/QXUPsiwhrdN0yzIF3PFfSFrP9
|
||||
tIH9HlnExMdndvNig9Z3lxIp6di7UXIVMod5sWEgXLZXPqRtqRU6CtZkMXHKDx3O
|
||||
5OcpTN1bAgMBAAECggEAC9e4SEVxXnclvTuZk6EdPwZ7u6TnGMQLnrvRczjccbe/
|
||||
hllB12tz/fjOu7ypNP5On/pHzhioEZAONP6QC2Uj5/T19cCyX9YPfOjx82PE65i3
|
||||
IJKTkfjYrzFwyskAgzb8djYtf/Z96ZnCBE0zIJwJf3eCAemhXoQhDZFw8RG+1G5X
|
||||
YtOoItBE5oIAXuUe3pYTaMY/1XnGe/vynFKeIcU9O2v6E3au8oueevqppmhfHkiM
|
||||
a6gtNhjU3wpii3ZJk/L4Cpka752CjbXrZCaU1qMXB4hNkSuOi1Hq9clU91Fz4PXw
|
||||
MHzeAZInlH3J29uxvDlGoMwTvpFIL2iRnrVzr40AfQKBgQC6+q31kAi818ciXxvh
|
||||
ZxyEJEwQw/q5x/pTZQ2VRJB3kBpt7Lq570IZfDpaOsPg2wB/4SbE8XHpX7FzJAMd
|
||||
BDCAzkBl8+fREbfL57/KKxV2EoHRfazSx23w8f5N5R+/OcXErgOAGUzcF2T53yXU
|
||||
TXDpzgjTOEU/4p+h7wqceSenNwKBgQDPzxB0Xk8oYHWejIWVRuLV0US+kTxFiLX4
|
||||
rrRppdk52oEzZFKJ0rosf00fHtxIyqW2NdPQlkphmyMjRUw3fPedK/FvNU8PnTo6
|
||||
3MJ61QRgGSAi6/YMIs9K/Y83iFRKTBynZi36UCOUZbEncpZXuiOmplJWWE17FmHj
|
||||
5IFItd5E/QKBgQCVD/oVVcGRg1iO71HTzZcvRZyalRLSfznyuBIvGN0vZGOdlOd8
|
||||
CeEhXidK/aRhI1bvm/iDc5UDnzVhfKk6vbdJSKSQYvVBeKWVWmlM7DIM0k5KS622
|
||||
0CS2vMWnJe28Tnt7A9toiUL8B26Jwbtv2FkXHBlvAmI6vxnSSDambfQN2wKBgQCm
|
||||
IYqtDUxJIjxFwV91xJLJjyBfHSrLCA06PyjaIQ11c9rAZB6cMkxGEItuKrS+uMsb
|
||||
zRKF+fCC8Yx4wQi6f3xROXUti7el6vNHZX9QxYVW8h8/69XrQ9Tmxai+I44HS6vI
|
||||
pCZzq6eWFmo2+CN7BMNFkkfW4YcntPATSXWV1FdaXQKBgQC3mKzwS/3GZ4NOarCL
|
||||
ISXGef+QZLPYj4eV08ccmRYXjlBR6rA2BNn9vPayB1E/IqG91Rj2tENLiE/NjVkG
|
||||
ZuAss8FdQS19oiPRPEA+u11+pNy0RfJ9uxjrP9l//x8lA0cw/Pv6S/m2c+1DSjVd
|
||||
UD2LwbNvaS6W4Vhy53LNGpbwmQ==
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDLXKbJUo6/xfnj
|
||||
1f6Pt/wKw4Ko4tS0WiK+DSfzXBuEStHtXvcB5PPbnMJ5KNGQiPcFq5rkcwlERg8F
|
||||
Z/+hjhuyn1as4fMxquKTBH7FpYHMRbuURSXtp9aZGMf6oMc1lzWF3aVQEgGPcAi4
|
||||
Pbp9ddFb4vhu/INe+At4WiQvWK0mD+TfX2XFdUcl1cNUQCz0VfeuBGpnjKApIqd3
|
||||
2ed2wF7U7bYBic2p9TA4Fw+VYArng12AbV5f9BQWuUUhjRSM7rYFs/R2bOHhB3y0
|
||||
5EP72jwqwYnXVZMKGOomq4Vhrdj0VmUjxC2r3iui+tH2HteHCNzNMrcoTOn+ag1/
|
||||
lHfTZK41AgMBAAECggEAJ80wtI70suqB09qGeeT5zraAvGK23DyW96j2BH6mwQ/u
|
||||
wd1YDVYc90LZWiLHz1jLNiAlzugH7IWku3tlEB7S43Ulnu0TLsmiEkGrOS5BNvR/
|
||||
989H0tmKWgj8XNx6WM4JMvPUPtVjWkpEXqDwPs1gJjKISpqf8KauAgZsdhrOOrhA
|
||||
w+2qmOd/5w7oZCNu9sm53XoR6pSifdpRl+AjY+XRK+/hfyD3DqLJoZcW5al2ZHsh
|
||||
iUWgfDDexFXVEeSc9OSyh5vTVXweXv8WVbpxAcD3l7Bsi7hltPW4bxyUcXjVfNy4
|
||||
rjITSASeVOgI4Kwguwl4WuTd4iMHgopPsKxZqP+1QQKBgQDs5ka//ie79V0I+wDY
|
||||
Y5vLSRRb9rLg0MDQxNUs9Gsg/+cYiaJrBEh1V+RTKWVEfxHS/hcUvMPgmW73EHRb
|
||||
vVp652bwcGd3RVY0cOoID6267lqoWim8h0hv5yF82tcRVr5TJO/6DUlpXKgDiDyi
|
||||
Zqe1Sf/j3mCE0opnByQrX+2MdQKBgQDbwiR6MryH1xZR0O+OFKmnpcxoda3xSoZi
|
||||
JNxlw/d3U69iPKnV0w7YN4a5ytG2+fLvb2X8FUrvpGBn2TCTOCMvCFHWN9FrAUqA
|
||||
HhTGHq3HGhA1DnGby+sE6Wn1kLfBYTS/PCusnqXgSVb/NpBqV4uSprweLVwfr2mN
|
||||
bt9zHkViwQKBgQDbHIIDwkduCZtrWv2FJ1xJweYaySrZ1TsB3YxucANGGmrcvzCC
|
||||
WwvJvOlqIbeQixcpV+pxO8bQThncWlPFJnYxhyYm7VBFeNQq3OUZX6cIZr1jSUGh
|
||||
Jl9RYS4QFTkmyFxw+pEbbn6f/RtJaRDsBJbJjxAm6t/K+hEZCfniRG+qoQKBgEyb
|
||||
axfmI+6+vhsbWMcQ0OuOUql/jHl2303LR8F6BQRl+denChVuE9iv0pll6KF+lH9/
|
||||
N/AehBbyGGFbRyGrCijVH6IrpydENfJfiiJeg3nKzieQt232MiFuNO/T2Rrihf68
|
||||
PQVZ8L01E8y3+rP3fMJMuXtTmK+6+HLDWcXJoaqBAoGAdHcfcm1S1NNpizSlpAvv
|
||||
WGmCBxSa4qz5/22RnuL0tSnOd59Uiwp0u6SKSSc+fhw7oMpWQYq8QnsAXjsit0P4
|
||||
GRmb5Ox/fHR0oF6IclmWmZin6c5ZeIDYDuGBig1/c6doG1j6WkHJO7xVQ04t7CcA
|
||||
jk4uwg6pRoaTCArAU3+1Pzk=
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCXx+9g4l6QwnUE
|
||||
f2b3mVA73MsQbXnc9m6hIGAS8Innba0mUA+nWij5KALUsJJEtoM7GGUlsijQEgLn
|
||||
+6V7pCYAy1qgL6q357xDNPw8qbshf9LOmPOJXsc0cqUSI0J4YLTjuJhM5a9zzje5
|
||||
RWJwwFl9Ileh3MT1FggLihNmcHzeC+VpWTvFXI/gC6KaDT0Xh1lNCN4jTpNEGCI8
|
||||
0kOfT6KUpZFRfYcazTCcPYlfvAY8H6aRXTPlGy/QXUPsiwhrdN0yzIF3PFfSFrP9
|
||||
tIH9HlnExMdndvNig9Z3lxIp6di7UXIVMod5sWEgXLZXPqRtqRU6CtZkMXHKDx3O
|
||||
5OcpTN1bAgMBAAECggEAC9e4SEVxXnclvTuZk6EdPwZ7u6TnGMQLnrvRczjccbe/
|
||||
hllB12tz/fjOu7ypNP5On/pHzhioEZAONP6QC2Uj5/T19cCyX9YPfOjx82PE65i3
|
||||
IJKTkfjYrzFwyskAgzb8djYtf/Z96ZnCBE0zIJwJf3eCAemhXoQhDZFw8RG+1G5X
|
||||
YtOoItBE5oIAXuUe3pYTaMY/1XnGe/vynFKeIcU9O2v6E3au8oueevqppmhfHkiM
|
||||
a6gtNhjU3wpii3ZJk/L4Cpka752CjbXrZCaU1qMXB4hNkSuOi1Hq9clU91Fz4PXw
|
||||
MHzeAZInlH3J29uxvDlGoMwTvpFIL2iRnrVzr40AfQKBgQC6+q31kAi818ciXxvh
|
||||
ZxyEJEwQw/q5x/pTZQ2VRJB3kBpt7Lq570IZfDpaOsPg2wB/4SbE8XHpX7FzJAMd
|
||||
BDCAzkBl8+fREbfL57/KKxV2EoHRfazSx23w8f5N5R+/OcXErgOAGUzcF2T53yXU
|
||||
TXDpzgjTOEU/4p+h7wqceSenNwKBgQDPzxB0Xk8oYHWejIWVRuLV0US+kTxFiLX4
|
||||
rrRppdk52oEzZFKJ0rosf00fHtxIyqW2NdPQlkphmyMjRUw3fPedK/FvNU8PnTo6
|
||||
3MJ61QRgGSAi6/YMIs9K/Y83iFRKTBynZi36UCOUZbEncpZXuiOmplJWWE17FmHj
|
||||
5IFItd5E/QKBgQCVD/oVVcGRg1iO71HTzZcvRZyalRLSfznyuBIvGN0vZGOdlOd8
|
||||
CeEhXidK/aRhI1bvm/iDc5UDnzVhfKk6vbdJSKSQYvVBeKWVWmlM7DIM0k5KS622
|
||||
0CS2vMWnJe28Tnt7A9toiUL8B26Jwbtv2FkXHBlvAmI6vxnSSDambfQN2wKBgQCm
|
||||
IYqtDUxJIjxFwV91xJLJjyBfHSrLCA06PyjaIQ11c9rAZB6cMkxGEItuKrS+uMsb
|
||||
zRKF+fCC8Yx4wQi6f3xROXUti7el6vNHZX9QxYVW8h8/69XrQ9Tmxai+I44HS6vI
|
||||
pCZzq6eWFmo2+CN7BMNFkkfW4YcntPATSXWV1FdaXQKBgQC3mKzwS/3GZ4NOarCL
|
||||
ISXGef+QZLPYj4eV08ccmRYXjlBR6rA2BNn9vPayB1E/IqG91Rj2tENLiE/NjVkG
|
||||
ZuAss8FdQS19oiPRPEA+u11+pNy0RfJ9uxjrP9l//x8lA0cw/Pv6S/m2c+1DSjVd
|
||||
UD2LwbNvaS6W4Vhy53LNGpbwmQ==
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDLXKbJUo6/xfnj
|
||||
1f6Pt/wKw4Ko4tS0WiK+DSfzXBuEStHtXvcB5PPbnMJ5KNGQiPcFq5rkcwlERg8F
|
||||
Z/+hjhuyn1as4fMxquKTBH7FpYHMRbuURSXtp9aZGMf6oMc1lzWF3aVQEgGPcAi4
|
||||
Pbp9ddFb4vhu/INe+At4WiQvWK0mD+TfX2XFdUcl1cNUQCz0VfeuBGpnjKApIqd3
|
||||
2ed2wF7U7bYBic2p9TA4Fw+VYArng12AbV5f9BQWuUUhjRSM7rYFs/R2bOHhB3y0
|
||||
5EP72jwqwYnXVZMKGOomq4Vhrdj0VmUjxC2r3iui+tH2HteHCNzNMrcoTOn+ag1/
|
||||
lHfTZK41AgMBAAECggEAJ80wtI70suqB09qGeeT5zraAvGK23DyW96j2BH6mwQ/u
|
||||
wd1YDVYc90LZWiLHz1jLNiAlzugH7IWku3tlEB7S43Ulnu0TLsmiEkGrOS5BNvR/
|
||||
989H0tmKWgj8XNx6WM4JMvPUPtVjWkpEXqDwPs1gJjKISpqf8KauAgZsdhrOOrhA
|
||||
w+2qmOd/5w7oZCNu9sm53XoR6pSifdpRl+AjY+XRK+/hfyD3DqLJoZcW5al2ZHsh
|
||||
iUWgfDDexFXVEeSc9OSyh5vTVXweXv8WVbpxAcD3l7Bsi7hltPW4bxyUcXjVfNy4
|
||||
rjITSASeVOgI4Kwguwl4WuTd4iMHgopPsKxZqP+1QQKBgQDs5ka//ie79V0I+wDY
|
||||
Y5vLSRRb9rLg0MDQxNUs9Gsg/+cYiaJrBEh1V+RTKWVEfxHS/hcUvMPgmW73EHRb
|
||||
vVp652bwcGd3RVY0cOoID6267lqoWim8h0hv5yF82tcRVr5TJO/6DUlpXKgDiDyi
|
||||
Zqe1Sf/j3mCE0opnByQrX+2MdQKBgQDbwiR6MryH1xZR0O+OFKmnpcxoda3xSoZi
|
||||
JNxlw/d3U69iPKnV0w7YN4a5ytG2+fLvb2X8FUrvpGBn2TCTOCMvCFHWN9FrAUqA
|
||||
HhTGHq3HGhA1DnGby+sE6Wn1kLfBYTS/PCusnqXgSVb/NpBqV4uSprweLVwfr2mN
|
||||
bt9zHkViwQKBgQDbHIIDwkduCZtrWv2FJ1xJweYaySrZ1TsB3YxucANGGmrcvzCC
|
||||
WwvJvOlqIbeQixcpV+pxO8bQThncWlPFJnYxhyYm7VBFeNQq3OUZX6cIZr1jSUGh
|
||||
Jl9RYS4QFTkmyFxw+pEbbn6f/RtJaRDsBJbJjxAm6t/K+hEZCfniRG+qoQKBgEyb
|
||||
axfmI+6+vhsbWMcQ0OuOUql/jHl2303LR8F6BQRl+denChVuE9iv0pll6KF+lH9/
|
||||
N/AehBbyGGFbRyGrCijVH6IrpydENfJfiiJeg3nKzieQt232MiFuNO/T2Rrihf68
|
||||
PQVZ8L01E8y3+rP3fMJMuXtTmK+6+HLDWcXJoaqBAoGAdHcfcm1S1NNpizSlpAvv
|
||||
WGmCBxSa4qz5/22RnuL0tSnOd59Uiwp0u6SKSSc+fhw7oMpWQYq8QnsAXjsit0P4
|
||||
GRmb5Ox/fHR0oF6IclmWmZin6c5ZeIDYDuGBig1/c6doG1j6WkHJO7xVQ04t7CcA
|
||||
jk4uwg6pRoaTCArAU3+1Pzk=
|
||||
-----END PRIVATE KEY-----
|
||||
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 198 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 56 KiB |
|
|
@ -0,0 +1 @@
|
|||
49a8c9c3-aac6-44fe-bc8d-f295677b96a6
|
||||