Skip to main content

¡Firma tus peticiones a la DIAN: rangos de numeración o facturas con CodeFlex!

Project description

MIT License


Logo

CODEFLEX CLOUD S.A.S

Firmar Petición SOAP a la DIAN | NIT: 901829324-9
Explore the docs »

About The Project

miniatura

Installation

pip install codeflexDian

Usage

  • Example 1 | Lambda Function (AWS) | GetNumberingRange

    import lxml.etree as ET
    from codeflexDian.SOAPSing import SOAPSing
    from codeflexDian.Signing import Signing
    import boto3
    import os
    from string import Template
    
    def lambda_handler(event, context):
    
      # VARIABLES
      ProviderSub = event['ProviderSub'] # Bucket S3
      accountCode = event['accountCode'] # Código de cuenta del proveedor
      accountCodeT = event['accountCodeT'] # Código de cuenta del proveedor para el conjunto de pruebas
      softwareCode = event['softwareCode'] # Código del software del proveedor
      ProviderEmail = event['ProviderEmail'] # Correo electrónico
    
      s3subir = boto3.client('s3')
      s3 = boto3.resource('s3')
    
      pathCert = "/tmp/" + ProviderSub + "/certificado.pfx"
      pathClave = "/tmp/" + ProviderSub + "/clave.txt"
      
      metodo = "GetNumberingRange"
    
      # CREA DIRECTORIO DE TRABAJO SI NO EXISTE
      directory = "/tmp/" + ProviderSub
      if not os.path.exists(directory):
          os.makedirs(directory)
      
      # Descarga el certificado
      s3.Bucket(ProviderSub).download_file("certificado.pfx", pathCert)
      
      # Descarga la clave
      s3.Bucket(ProviderSub).download_file("clave.txt", pathClave)
      
      # Lee la clave
      with open(pathClave) as f:
          passwordCert = f.readline().strip()
    
      # Si la clave es NA entonces la clave será un blanco
      if (passwordCert == "NA"):
          passwordCert = ""
      
      signing = Signing(pathCert, passwordCert)
      signer = SOAPSing(signing, metodo)
      template = Template('''<wcf:GetNumberingRange xmlns:wcf="http://wcf.dian.colombia"><wcf:accountCode>${accountCode}</wcf:accountCode><wcf:accountCodeT>${accountCodeT}</wcf:accountCodeT><wcf:softwareCode>${softwareCode}</wcf:softwareCode></wcf:GetNumberingRange>''')      
      value = {
          'accountCode': accountCode,
          'accountCodeT': accountCodeT,
          'softwareCode': softwareCode
      }
      templateOk = template.substitute(value)
      element = ET.fromstring(templateOk)
      soapSigned = signer.sing(element)
      soapSingedStrin = ET.tostring(soapSigned)
    
      # Escribe Request firmado en /tmp
      open('/tmp/' + ProviderSub + '/' + 'RANGOS-SIGN.xml', 'wb').write(soapSingedStrin)
      
      # Sube Request firmado de /tmp a s3
      s3subir.upload_file('/tmp/' + ProviderSub + '/' + 'RANGOS-SIGN.xml', ProviderSub, 'RANGOS-SIGN.xml')
      
      # Retorno de información de destino
      return {
          'ProviderSub': ProviderSub,
          'ProviderEmail': ProviderEmail
      }
    
  • Example 2 | Lambda Function (AWS) | SendBillSync

    import lxml.etree as ET
    from codeflexDian.SOAPSing import SOAPSing
    from codeflexDian.Signing import Signing
    import base64
    import boto3
    import os
    import json
    from string import Template
    
    def lambda_handler(event, context):
    
      """
      Antes de ejecutar este código, asegúrate de zippear la factura XML firmada.
      El código del ejemplo: Example 1 | Lambda Function (AWS) | GetNumberingRange solo 
      se utiliza para consultar los rangos de numeración.
      """
      # Para saber cómo zippear la factura XML firmada con el formato deseado, 
      # consulta el código que está abajo como 'zipfile'.
    
      #---------------------------------------------------------------------------------------#
    
      # VARIABLES
      ProviderSub = event['ProviderSub'] # Bucket S3
      ProviderEmail = event['ProviderEmail'] # Correo electrónico
      Invoice = event['Invoice'] # Número de la factura EJ: B77404
      IssueDate = event['IssueDate'] # Fecha de emisión de la factura
      TestSetId = event['TestSetId'] # ID del conjunto de pruebas
      Ambiente = event['Ambiente'] # Ambiente de la solicitud (1 para pruebas, 2 para producción)
      
      if Ambiente == "2":
          metodo = "SendTestSetAsync"
      
      if Ambiente == "1":
          metodo = "SendBillSync"
    
      s3subir = boto3.client('s3')
      s3 = boto3.resource('s3')
    
      pathCert = "/tmp/" + ProviderSub + "/certificado.pfx"
      pathClave = "/tmp/" + ProviderSub + "/clave.txt"
    
      # CREA DIRECTORIO DE TRABAJO SI NO EXISTE
      directory = "/tmp/" + ProviderSub
      if not os.path.exists(directory):
          os.makedirs(directory)
    
      # Descarga el certificado
      s3.Bucket(ProviderSub).download_file("certificado.pfx", pathCert)
    
      # Descarga la clave
      s3.Bucket(ProviderSub).download_file("clave.txt", pathClave)
    
      # Lee la clave
      with open(pathClave) as f:
          passwordCert = f.readline().strip()
    
      # Si la clave es NA entonces la clave será un blanco
      if passwordCert == "NA":
          passwordCert = "" 
    
      # Descarga la factura xml firmada
      s3.Bucket(ProviderSub).download_file(Invoice + "-ZIP.zip", "/tmp/" + ProviderSub + "/" + Invoice + "-ZIP.zip")
    
      with open("/tmp/" + ProviderSub + "/" + Invoice + "-ZIP.zip", "rb") as f:
          bytes = f.read()
          encode_string = base64.b64encode(bytes).decode('ascii')
    
      signing = Signing(pathCert, passwordCert)
      signer = SOAPSing(signing, metodo)
      template = Template('''<wcf:${metodo} xmlns:wcf="http://wcf.dian.colombia"><wcf:fileName>${fileName}</wcf:fileName><wcf:contentFile>${contentFile}</wcf:contentFile><wcf:testSetId>${TestSetId}</wcf:testSetId></wcf:${metodo}>''')
      value = {
          'fileName': Invoice+'.zip',
          'contentFile': encode_string,
          'TestSetId': TestSetId,
          'metodo': metodo
      }
    
      templateOk = template.substitute(value)
      element = ET.fromstring(templateOk)
      soapSigned = signer.sing(element)
      soapSignedString = ET.tostring(soapSigned)
    
      # Escribe Request firmado en /tmp
      open('/tmp/' + ProviderSub + '/' + Invoice + '-REQ-SIGN.xml', 'wb').write(soapSignedString)
    
      # Sube Request firmado de /tmp a s3
      s3subir.upload_file('/tmp/' + ProviderSub + '/' + Invoice + '-REQ-SIGN.xml', ProviderSub, Invoice+'-REQ-SIGN.xml')
    
      # Retorno de información de destino
      return {
          'ProviderSub': ProviderSub,
          'ProviderEmail': ProviderEmail,
          'Invoice': Invoice,
          'IssueDate': IssueDate,
          'Ambiente': Ambiente
      }
    
  • zipfile | Lambda Function (AWS)

    import zipfile
    import zlib
    import boto3
    import botocore
    import base64
    import os
    import json
    
    try:
      import zlib
      compression = zipfile.ZIP_DEFLATED
    except:
      compression = zipfile.ZIP_STORED
    
    def lambda_handler(event, context):
    
      # VARIABLES
      ProviderSub = event['ProviderSub'] # Bucket S3
      Factura = event['Factura'] # Número de la factura EJ: B77404
    
      # TODO implement
      Invoice = Factura
      bucket_name = ProviderSub
      s3subir = boto3.client('s3')
      s3 = boto3.resource('s3') 
      
      #CREA DIRECTORIO DE TRABAJO SI NO EXISTE
      directory = "/tmp/"+Invoice
      if not os.path.exists(directory):
          os.makedirs(directory)
    
      # DESCARGA DE S3 LA FACTURA FIRMADA
      s3.Bucket(bucket_name).download_file(Factura + "-SIGN.xml", directory+'/SIGN.xml')
      
      #COMPRIMIR EN /TMP
      zf = zipfile.ZipFile('/tmp/' + Invoice + '/zip.zip', mode='w')
      try:
          zf.write('/tmp/' + Invoice + '/SIGN.xml', arcname='firmado.xml', compress_type=compression)
      finally:
          zf.close()
      
      # Sube el archivo a s3
      s3subir.upload_file('/tmp/' + Invoice + '/zip.zip', bucket_name, Factura + "-ZIP.zip")
    
      return {
          'statusCode': 200,
          'body': json.dumps(Invoice + ".zip, Subido correctamente a S3.")
      }
    

The company that currently uses our library is: FacturaDian

Download the list of layers to use in Lambda AWS: Python

OFFICIAL WEBSITE: CODEFLEX CLOUD S.A.S.

License

Distributed under the MIT License. See LICENSE for more information.

Contact

Phone: +57 3008130562 | E-mail: info@codeflex.com.co

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

codeflexdian-1.3.0.tar.gz (12.7 kB view details)

Uploaded Source

Built Distribution

codeflexDian-1.3.0-py3-none-any.whl (10.1 kB view details)

Uploaded Python 3

File details

Details for the file codeflexdian-1.3.0.tar.gz.

File metadata

  • Download URL: codeflexdian-1.3.0.tar.gz
  • Upload date:
  • Size: 12.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.11.9

File hashes

Hashes for codeflexdian-1.3.0.tar.gz
Algorithm Hash digest
SHA256 4453bb619355f7140a3c9f109810490dbaad7e592060707badb02179549ee592
MD5 662c85a2b0545806750e9958dc535472
BLAKE2b-256 d278883834f0d0009a9bc8a613be980fdce1734a09aa0a64e9a5475610aedb5d

See more details on using hashes here.

File details

Details for the file codeflexDian-1.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for codeflexDian-1.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 58424616446c729034e39f6f064a9feccedd22beb10b527573acf6508e5e3072
MD5 20a37b0655f0e914a4f57fb99d09a29c
BLAKE2b-256 ec04de7a2a4c9117723e09808dee0f108c1a995c950d6518c5bf5265b42fe0bf

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page