Sigueme en Facebook Sigueme en Twitter Sigueme en Instagram Sigueme en Youtube
JC Mouse Bolivia
Index / .Net / Codigo de Control en Visual Basic | Impuestos Bolivia

Codigo de Control en Visual Basic | Impuestos Bolivia

Autor jc mouse martes, mayo 17, 2016

En esta oportunidad dejamos las fuentes del Generador de Código de Control de Impuestos Bolivia (Facturación Virtual), en un lenguaje bastante conocido que es Visual Basic .NET

¿Que es Visual Basic .NET?

VB.NET es un lenguaje de programación orientado a objetos que se puede considerar una evolución de Visual Basic implementada sobre el framework .NET. Su introducción resultó muy controvertida, ya que debido a cambios significativos en el lenguaje VB.NET no es retro compatible con Visual Basic, pero el manejo de las instrucciones es similar a versiones anteriores de Visual Basic, facilitando así el desarrollo de aplicaciones más avanzadas con herramientas modernas. Para mantener eficacia en el desarrollo de las aplicaciones.

Recordemos los algoritmos utilizados por el generador de Código de Control son:

  • Alleged RC4 Un algoritmo de criptografía simétrica, basado en cifrado de flujo (stream cipher), muy utilizado por su rendimiento y simplicidad.
  • Verhoeff Algoritmo de dígito verificador que trabaja con cadenas de dígitos decimales de cualquier tamaño. Además de detectar una amplia gama de errores en datos numéricos, este algoritmo también detecta casos de
    transposición de dígitos adyacentes.
  • Base 64 Algoritmo que convierte cifras en base 10 a base 64, utilizando divisiones sucesivas además de un
    diccionario de 64 caracteres.

Nuestro proyecto es el siguiente:

bolivia visual basic

AllegedRC4.vb

''' <summary>
''' Más información en https://www.jc-mouse.net/
''' </summary>
Public Class AllegedRC4

    ''' <summary>
    ''' Encripta usando AllegedRC4
    ''' </summary>
    ''' <param name="message">mensaje a encriptar</param>
    ''' <param name="key">llave de cifrado</param>
    ''' <param name="unscripted">TRUE sin guion separados</param>
    ''' <returns>mensaje encriptado</returns>
    Public Shared Function encryptMessageRC4(ByVal message As String, ByVal key As String, ByVal unscripted As Boolean) As String

        Dim state(256) As Integer
        Dim x As Integer = 0
        Dim y As Integer = 0
        Dim index1 As Integer = 0
        Dim index2 As Integer = 0
        Dim nmen As Integer
        Dim messageEncryption As String = ""

        For i = 0 To 255
            state(i) = i
        Next

        For i = 0 To 255
            index2 = (Asc(key(index1)) + state(i) + index2) Mod 256
            Dim aux As Integer = state(i)
            state(i) = state(index2)
            state(index2) = aux
            index1 = (index1 + 1) Mod Len(key)
        Next


        For i As Integer = 0 To Len(message) - 1
            x = (x + 1) Mod 256
            y = (state(x) + y) Mod 256
            Dim aux As Integer = state(x)
            state(x) = state(y)
            state(y) = aux
            nmen = Asc(message(i)) Xor state((state(x) + state(y)) Mod 256)
            Dim nmenHex As String = Hex(nmen)
            Dim hyphen As String = ""
            If Not unscripted Then hyphen = "-"
            If Len(nmenHex) = 1 Then nmenHex = "0" & nmenHex
            messageEncryption = messageEncryption & hyphen & nmenHex
        Next

        If unscripted Then
            Return messageEncryption
        Else
            Return messageEncryption.Substring(1, messageEncryption.Length - 1)
        End If
    End Function

End Class

Base64SIN.vb

''' <summary>
''' Más información en https://www.jc-mouse.net/
''' </summary>
Public Class Base64SIN

    ''' <summary>
    ''' Codificador base64
    ''' </summary>
    ''' <param name="value">Numero a codificar</param>                
    ''' <returns>Cadena codificada</returns>
    Public Shared Function convertBase64(ByVal value As Integer) As String

        Dim dictionary = New String() {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
                                "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
                                "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
                                "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d",
                                "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
                                "o", "p", "q", "r", "s", "t", "u", "v", "w", "x",
                                "y", "z", "+", "/"}
        Dim quotient As Integer = 1
        Dim remainder As Integer
        Dim word As String = ""
        While quotient > 0
            quotient = value \ 64
            remainder = value Mod 64
            word = dictionary(remainder) & word
            value = quotient
        End While
        Return word
    End Function

End Class

Verhoeff.vb

''' <summary>
''' For more information cf. http://en.wikipedia.org/wiki/Verhoeff_algorithm
''' Dihedral Group: http://mathworld.wolfram.com/DihedralGroup.html
''' </summary>
''' <remarks></remarks>
Public Class Verhoeff

    'The multiplication table
    Shared ReadOnly d(,) As Integer =
    {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
    {1, 2, 3, 4, 0, 6, 7, 8, 9, 5},
    {2, 3, 4, 0, 1, 7, 8, 9, 5, 6},
    {3, 4, 0, 1, 2, 8, 9, 5, 6, 7},
    {4, 0, 1, 2, 3, 9, 5, 6, 7, 8},
    {5, 9, 8, 7, 6, 0, 4, 3, 2, 1},
    {6, 5, 9, 8, 7, 1, 0, 4, 3, 2},
    {7, 6, 5, 9, 8, 2, 1, 0, 4, 3},
    {8, 7, 6, 5, 9, 3, 2, 1, 0, 4},
    {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}}

    'The permutation table
    Shared ReadOnly p(,) As Integer =
    {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
    {1, 5, 7, 6, 2, 8, 3, 0, 9, 4},
    {5, 8, 0, 3, 7, 9, 6, 1, 4, 2},
    {8, 9, 1, 6, 0, 4, 3, 5, 2, 7},
    {9, 4, 5, 3, 1, 2, 6, 8, 7, 0},
    {4, 2, 8, 6, 5, 7, 3, 9, 0, 1},
    {2, 7, 9, 3, 8, 0, 6, 4, 1, 5},
    {7, 0, 4, 6, 9, 1, 3, 2, 5, 8}}

    'The inverse table
    Shared ReadOnly inv() As Integer = {0, 4, 3, 2, 1, 5, 6, 7, 8, 9}

    ''' <summary>
    ''' Validates that an entered number is Verhoeff compliant.
    ''' </summary>
    ''' <param name="num"></param>
    ''' <returns>True if Verhoeff compliant, otherwise false</returns>
    ''' <remarks>Make sure the check digit is the last one!</remarks>
    Public Shared Function validateVerhoeff(ByVal num As String) As Boolean

        Dim c As Integer = 0
        Dim myArray() As String = StringToReversedIntArray(num)

        For i As Integer = 0 To myArray.Length - 1
            c = d(c, p((i Mod 8), myArray(i)))
        Next i

        Return c.Equals(0)

    End Function

    ''' <summary>
    ''' For a given number generates a Verhoeff digit
    ''' </summary>
    ''' <param name="num"></param>
    ''' <returns>Verhoeff check digit as string</returns>
    ''' <remarks>Append this check digit to num</remarks>
    Public Shared Function generateVerhoeff(ByVal num As String) As String

        Dim c As Integer = 0
        Dim myArray() As String = StringToReversedIntArray(num)

        For i As Integer = 0 To myArray.Length - 1
            c = d(c, p(((i + 1) Mod 8), Convert.ToInt32(myArray(i))))
        Next i

        Return inv(c).ToString

    End Function

    ''' <summary>
    ''' Converts a string to a reversed integer array.
    ''' </summary>
    ''' <param name="str"></param>
    ''' <returns>Reversed integer array</returns>
    ''' <remarks></remarks>
    Private Shared Function StringToReversedIntArray(ByVal str As String) As String()

        Dim myArray(str.Length - 1) As String
        For i As Integer = 0 To str.Length - 1
            myArray(i) = str.Substring(i, 1)
        Next
        Array.Reverse(myArray)
        Return myArray

    End Function
End Class

ControlCode.vb

''' <summary>
''' Más información en https://www.jc-mouse.net/
''' </summary>
Public Class ControlCode

    ''' <summary>
    ''' Genera codigo de control
    ''' </summary>
    ''' <param name="authorizationNumber">Numero de autorizacion</param>        
    ''' <param name="invoiceNumber">Numero de factura</param>        
    ''' <param name="nitci">Número de Identificación Tributaria o Carnet de Identidad</param>        
    ''' <param name="dateOfTransaction">fecha de transaccion de la forma AAAAMMDD</param>        
    ''' <param name="transactionAmount">Monto de la transacción</param>        
    ''' <param name="dosageKey">Llave de dosificación</param>        
    ''' <returns>Codigo de Control generado de la forma 6A-DC-53-05-14</returns>
    Public Shared Function generateControlCode(ByVal authorizationNumber As String, ByVal invoiceNumber As String, ByVal nitci As String,
                           ByVal dateOfTransaction As String, ByVal transactionAmount As String, ByVal dosageKey As String) As String

        ''redondea monto de transaccion 
        transactionAmount = roundUp(transactionAmount)

        '' ======================== PASO 1 =============================
        invoiceNumber = addVerhoeffDigit(invoiceNumber, 2)
        nitci = addVerhoeffDigit(nitci, 2)
        dateOfTransaction = addVerhoeffDigit(dateOfTransaction, 2)
        transactionAmount = addVerhoeffDigit(transactionAmount, 2)

        Dim sumOfVariables As Long
        Try
            sumOfVariables = CLng(invoiceNumber) _
                                      + CLng(nitci) _
                                      + CLng(dateOfTransaction) _
                                      + CLng(transactionAmount)
        Catch ex As FormatException
            If (ex.Source <> vbNull) Then
                Console.WriteLine("FormatException source: {0}", ex.Source)
            End If
        End Try

        ''A la suma total se añde 5 digitos Verhoeff
        Dim sumOfVariables5Verhoeff As String = addVerhoeffDigit(sumOfVariables.ToString(), 5)

        '' ======================== PASO 2 =============================
        Dim fiveDigitsVerhoeff As String = sumOfVariables5Verhoeff.Substring(sumOfVariables5Verhoeff.Length - 5)
        Dim numbers(5) As Integer
        For i = 1 To 5
            numbers(i - 1) = Int32.Parse(fiveDigitsVerhoeff(i - 1).ToString()) + 1
        Next

        Dim string1 As String = dosageKey.Substring(0, numbers(0))
        Dim string2 As String = dosageKey.Substring(numbers(0), numbers(1))
        Dim string3 As String = dosageKey.Substring(numbers(0) + numbers(1), numbers(2))
        Dim string4 As String = dosageKey.Substring(numbers(0) + numbers(1) + numbers(2), numbers(3))
        Dim string5 = dosageKey.Substring(numbers(0) + numbers(1) + numbers(2) + numbers(3), numbers(4))

        Dim authorizationNumberDKey As String = authorizationNumber & string1
        Dim invoiceNumberdKey As String = invoiceNumber & string2
        Dim NITCIDKey As String = nitci & string3
        Dim dateOfTransactionDKey As String = dateOfTransaction & string4
        Dim transactionAmountDKey As String = transactionAmount & string5

        '' ======================== PASO 3 =============================

        Dim stringDKey As String = authorizationNumberDKey & invoiceNumberdKey & NITCIDKey & dateOfTransactionDKey & transactionAmountDKey
        Dim keyForEncryption As String = dosageKey + fiveDigitsVerhoeff
        Dim allegedRC4String As String = AllegedRC4.encryptMessageRC4(stringDKey, keyForEncryption, True)
        ''Console.WriteLine("stringDKey ----------------->" & stringDKey)

        '' ======================== PASO 4 =============================
        Dim totalAmount As Integer = 0
        Dim sp1 As Integer = 0
        Dim sp2 As Integer = 0
        Dim sp3 As Integer = 0
        Dim sp4 As Integer = 0
        Dim sp5 As Integer = 0

        Dim asciiBytes() As Byte = System.Text.Encoding.ASCII.GetBytes(allegedRC4String)
        Dim tmp As Integer = 1
        For i = 0 To asciiBytes.Length - 1
            totalAmount += asciiBytes(i)
            Select Case tmp
                Case 1
                    sp1 += asciiBytes(i)
                Case 2
                    sp2 += asciiBytes(i)
                Case 3
                    sp3 += asciiBytes(i)
                Case 4
                    sp4 += asciiBytes(i)
                Case 5
                    sp5 += asciiBytes(i)
            End Select
            If (tmp < 5) Then tmp += 1 Else tmp = 1
        Next

        '' ======================== PASO 5 =============================
        Dim tmp1 As Integer = totalAmount * sp1 \ numbers(0)
        Dim tmp2 As Integer = totalAmount * sp2 \ numbers(1)
        Dim tmp3 As Integer = totalAmount * sp3 \ numbers(2)
        Dim tmp4 As Integer = totalAmount * sp4 \ numbers(3)
        Dim tmp5 As Integer = totalAmount * sp5 \ numbers(4)

        Dim sumProduct As Integer = tmp1 + tmp2 + tmp3 + tmp4 + tmp5
        Dim base64SIN As String = ControlCodeV7vb.Base64SIN.convertBase64(sumProduct)

        '' ======================== PASO 6 =============================
        Return ControlCodeV7vb.AllegedRC4.encryptMessageRC4(base64SIN, String.Concat(dosageKey, fiveDigitsVerhoeff), False)

    End Function

    ''' <summary>
    ''' Agrega N digitos d Verhoeff a una cadena
    ''' </summary>
    ''' <param name="value">cadena donde agregar digitos de Verhoeff</param>
    ''' <param name="max">cantidad de digitos a agregar</param>
    ''' <returns>cadena original + N digitos de Verhoeff</returns>
    Private Shared Function addVerhoeffDigit(ByVal value As String, ByVal max As Integer) As String
        For i = 1 To max
            value = String.Concat(value, Verhoeff.generateVerhoeff(value))
        Next
        Return value
    End Function


    ''' <summary>
    ''' redonde un numero hacia arriba 
    ''' </summary>
    ''' <param name="value">cadena que contiene el numero a redondear de la forma 123 ; 123.6 123,6</param>
    ''' <returns>el numero redondeado</returns>
    Public Shared Function roundUp(ByVal value As String) As String
        Dim nfi As System.Globalization.NumberFormatInfo = New System.Globalization.CultureInfo("es-ES", False).NumberFormat
        If nfi.CurrencyDecimalSeparator = "," Then
            value = Replace(value, ".", ",")
        ElseIf nfi.CurrencyDecimalSeparator = "." Then
            value = Replace(value, ",", ".")
        End If

        Dim d As Decimal = System.Convert.ToDecimal(value)
        Return Math.Round(d, MidpointRounding.AwayFromZero).ToString
    End Function

End Class

En el proyecto TestControlCode, implementamos el código necesario para testear los 5000 casos que nos brinda Impuestos Bolivia. Por ejemplo para 1 caso podemos hacer lo siguiente:

Dim cc As String = ControlCodeV7vb.ControlCode.generateControlCode("29040011007", "1503", "4189179011", "20070702", "2500", "9rCB7Sv4X29d)5k7N%3ab89p-3(5[A")
Console.WriteLine(cc)

SIN Bolivia

La realización de este código y del resto de de las fuentes en Java, PHP, JavaScript, C#,etc se llevaron a cabo siguiendo los pasos descritos en la documentación brindada por Impuestos Nacionales ¿Que si puede optimizarse? claro que si 🙂 pero ese es tu trabajo, este articulo solo tiene propósitos educativos.

Eso es todo 🙂

Detalles de proyecto

  • Lenguaje: Visual Basic
  • Desarrollado: Visual Studio 2015
  • Framework: .NET Framework 4.5.2
  • Enlace de descarga <<AQUI>>

Llave para mega: !GJlnvrrn9hUipaRbAIHkk78G5hBSpWHNCKw2CZjwWek

enjoy!!!!

Tags

Si te ha gustado podrías compartirlo o dejar un comentario. ¡Muchas gracias!
Autor: JC Mouse

Yo soy yo :) JC Mouse, Soy orgullosamente boliviano soy fundador y CEO de la web jc-Mouse.net uno de las pocas web en emprendimiento y tecnología en Bolivia.

Toda la información que encuentres en este sitio es y sera completamente gratis siempre, puedes copiar, descargar y re-publicar si así lo deseas en otros blogs o sitios web, solo te pido a cambio que dejes una referencia a esta web. Esto nos ayuda a crecer y seguir aportando. Bye

Enjoy! :)

También Te Podría Interesar

Subir imagen a un servidor web con REST/JSON

Subir imagen a un servidor web con REST/JSON

En este tutorial crearemos una sencilla aplicación para android que nos permitirá subir una imagen a un servidor web. La...

Convertir voz a texto con Android

Convertir voz a texto con Android

En este post realizaremos una aplicación que pueda capturar nuestra voz y convertir en texto Pasar voz a texto con Andro...

Personaliza JTable «MetroUI»

Personaliza JTable «MetroUI»

Un JTable es un componente swing de java que nos permite presentar datos en forma tabular, si bien haciendo uso de IDe...

Resolución de pantalla con LibGDX

Resolución de pantalla con LibGDX

En este tutorial, veremos un poco más de lo que son las texturas en libGDX y dos maneras de añadirlas a nuestros juegos,...

Bloquear pantalla cliente

Bloquear pantalla cliente

En este tutorial crearemos una aplicación que bloqueara toda la pantalla de la PC y no nos dejara realizar ninguna tarea...

Código Único de Factura en PHP

Código Único de Factura en PHP

Código Único de Factura para el Nuevo Sistema de Facturación Electrónica en Bolivia desarrollado en el lenguaje PHP 7 (H...

3 comentarios en “Codigo de Control en Visual Basic | Impuestos Bolivia”

  1. Juan carlos dice:

    Muchas gracias por tu aporte. Me pregunta es: como podria utlizar estos modulos para trabajar en VBA para Excel ya que mi sistema de facturacion esta en ese lenguaje. Gracias anticipadas. Un saludo.

  2. Edgar Dorado dice:

    Hola, muchas gracias por el aporte.
    Tengo algunos errores que me salen y me gustaria tu ayuda.
    Deberían haber más personas como tú que contribuyan para mostrar el talento boliviano en programación
    Muchas gracias por tu aporte.

    1. Mouse dice:

      buscame en facebook viejo

Los comentarios estan cerrados

Comparte lo que sabes

Categorias

Últimas entradas

Si trabajas con redes sociales (RRSS) a continuación te muestro tres herramintas gratuitas que te ayudaran a la hora de...

Por lo general se usan transacciones a nivel base de datos y posteriormente se llaman estos a través de procedimientos a...

En este post, aprenderemos como conectar Visual Basic 6 con SQL Server, abrir una tabla, leer su contenido y mostrar est...

Lo que veremos en este post es la configuración del driver para PHP de SQL Server que ha creado Microsoft el cual permit...

Herramientas

Generador de Enlaces a Whatsapp