WS-Security DGI (Efactura) WebServices

Unofficial Content

Consuming DGI (Efactura) WebServices

The provided services from DGI called Efactura are webservices based on WS-Security. This specification is different from the standards Webservice generated by GeneXus, so in order to communicate with them we must set up some configuration.

Note: These examples contains only an implementation for DGI Service "FACRECEPCIONSOBRE". 

Efactura News

Prerequisites

- Certificate

- RUC Number

 

.NET 

Note: GeneXus X Evolution 2 Upgrade 2 required

1. Install the certificate provided by DGI using mmc.exe from Windows. Install it in "Personal" store on the Computer Account. 

2. DGI signs the response with theirs certificate (DGI RUC PRUEBA CEDE). So in order to work property, DGI certificate must be installed on the server. 

In order to get this certificate go to https://www.efactura.dgi.gub.uy/ (Note2)
Install that certificate in Personal Store on computer account using mmc.exe. This certificate will be used in order to authenticate with DGI web services.

3. Grant Certificate Permission to ASP.NET (or the user that is running the application): How to do it

4. Download and import this NET DGI XPZ WebService Sample that contains the DGI WebService with the SDTs needed.

5. Set property Use Native Soap property = true to .NET Generator in order to use WCF instead of GeneXus SOAP client. 6

6. Set the web.config as the following:

  • Replace: "RUC21XXXXXX" with the Serial Number of your certificate.

<system.serviceModel>
    <client>
      <endpoint address="https://efactura.dgi.gub.uy:6443/ePrueba/ws_eprueba" binding="customBinding" bindingConfiguration="dgiBinding" contract="GeneXus.Programs.ISdtWS_eFactura" name="GeneXus.Programs.SdtWS_eFacturaClient" behaviorConfiguration="ServiceBehavior">
        <identity>
          <dns value="DGI RUC PRUEBA CEDE" />
        </identity>
      </endpoint>
    </client>
    <behaviors>
      <endpointBehaviors>
        <behavior name="ServiceBehavior">
          <clientCredentials>    
            <clientCertificate findValue="RUCXXXXXX" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" />
            <serviceCertificate>
              <authentication certificateValidationMode="PeerOrChainTrust" />             
              <defaultCertificate findValue="DGI RUC PRUEBA CEDE" storeLocation="LocalMachine" x509FindType="FindBySubjectName" storeName="My" />
            </serviceCertificate>
          </clientCredentials>
          <protectionLevel level="Sign" />
          <!-- None, Sign, EncryptAndSign-->
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>
     <customBinding>
        <binding name="dgiBinding">
          <security includeTimestamp="false" allowSerializedSigningTokenOnReply="true" authenticationMode="MutualCertificate" requireDerivedKeys="false" securityHeaderLayout="Lax" messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
            <secureConversationBootstrap />
             <localClientSettings detectReplays="false"/>
          </security>
          <textMessageEncoding messageVersion="Soap11" />
          <httpsTransport />
        </binding>
      </customBinding>
    </bindings>
    <extensions>
      <behaviorExtensions>
        <add name="protectionLevel" type="GeneXus.Wcf.ProtectionLevelBehaviorElement, GxClasses, Version=10.1.0.0, Culture=neutral, PublicKeyToken=6f5bf81c27b6b8aa" />
      </behaviorExtensions>
    </extensions>
  </system.serviceModel>

7. WebPanel "Ejemplo_ServicioSobre" contains an example for calling DGI Service "Envio de mensaje con Sobre". 

You need to replace the certificate that is being used within code: &CryptoUtils.FindCertificate("RUC21XXXXXX")

If there is warning certificate message's, it get a "Certficate with Subject = RUC21XXXXX not found" error.
In order to fix, there are two options
               - install a Certification Autorithy certificate (in order to fix the warning message) or
               - Looking for invalid certificates, it means, setting the parameter validonly = false . It would be replacing &CryptoUtils.FindCertificate("RUC21XXXXXX") for  &CryptoUtils.FindCertificate1("RUC21XXXXXX", storeName, storeLocation, false)

Note: DGI does not accept SOAP messages with empty element tags (example: <cantidad/>). XML Null Serialization property (SDT) property must be set to "No tag" in every SDT attribute. 

Note2: Another way to Get the DGI certificate is from the SOAP header in the response:

<wsse:BinarySecurityToken >MIIFvjCC.............</wsse:BinarySecurityToken>.

Copy the text inside tags BinarySecurityToken, then save as "cert.cer".

JAVA (tested Apache Tomcat 6 and 7)

Note: GeneXus X Evolution 1 Upgrade 6 required

1. Download JAVA_DGI_WS.zip  and extract to your hard drive.

2. DGIWS.xpz. Import into GeneXus.

3. Add "java_dgiWS_EOs.jar" to classpath in GeneXus. 

3. Copy and merge all folders and files inside folder "webapp" to your Tomcat\WebApp directory.

4. Create your Java Key Store (JKS) from your Certificate:

For generating a .jks the following command can be executed: 

keytool -v -importkeystore -srckeystore RUC2XXXXXXX.pfx -srcstoretype PKCS12 -destkeystore RUC2XXXXXXX.jks -deststoretype JKS. Refer to this link for more info.

(Temporary Limitation: Set the Java Key Store Password as the private key password). 

In order to obtain certifcate alias (needed for the next step), run the following command:

keytool -list -v -keystore RUC2XXXXXXX.jks

5. Download the Server certificate and import it into the Java cacerts. For example, suppose the downloaded certificate is dgi_ssl_cert.cer, a sample command is:

keytool -import -alias dgi_efactura_https -file "E:\DGI_HTTP_CERT.cer" -keystore "C:\Program Files\Java\jre6\lib\security\cacerts"             (default cacert password: changeit)

Check this article for further information. By default the WebService address is https://efactura.dgi.gub.uy:6443/ePrueba/ws_eprueba, check the ServicioSobre WebPanel reference:

&DGIWSWrapper.Address = "https://efactura.dgi.gub.uy:6443/ePrueba/ws_eprueba"

6. Open "ServicioSobre" to see how the DGI WebService is being called. You will need to edit the following code in order to specify the certificate information:

Sub 'SetConfigurationOptions'

&keyStoreFile = "C:\\RUC2XXXXXXX.jks"
&keyStorePassword = "desarrollo" //Current Limitation: keystorepassword must be equal to private key password
&keyStoreType = "JKS"
&privateKeyAlias = "xx-xxxx-xx-xxx-xxxx-xxxxx"

//Setting Certificate information in order to sign XML
&xmlSignatureutil.keyStoreFile = &keyStoreFile
&xmlSignatureutil.keyStorePassword = &keyStorePassword
&xmlSignatureutil.keyStoreType = &keyStoreType
&xmlSignatureutil.privateKeyAlias = &privateKeyAlias
&xmlSignatureutil.privateKeyPassword = &keyStorePassword

//Setting Certificate information in order to sign the SOAP message
&DGIWSWrapper.keyStoreFile = &keyStoreFile
&DGIWSWrapper.keyStorePassword = &keyStorePassword
&DGIWSWrapper.keyStoreType = &keyStoreType
&DGIWSWrapper.privateKeyAlias = &privateKeyAlias
&DGIWSWrapper.privateKeyPassword = &keyStorePassword

Endsub

and make sure to change the RUCEmisor and associated information in the GenerateSDT subroutine.

Logging

By default, logging is placed in C:\Temp\log4j.log

Note: For production environment you should turn off logging by opening "java_dgiWS_EOs.jar" with Winrar and deleting "java_  log4j.properties".

 

Troubleshooting

Problem: ErrorDsc: "No se pudo inicializar el módulo Axis Rampart -Connection has been shutdown: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target"

Solution1:  Check again the step 5, the server side certificate is not imported in the local truststore or not referenced using the Java variables (javax.net.ssl.trustStorePassword and javax.net.ssl.trustStore).

Solution2:  Add the server certificate to the Java Runtime Environment used by the Application Server. Link