Page 1 of 1
Firmar facturae
Posted: Thu Nov 29, 2018 1:04 pm
by manuelcalerosolis
Hola a todos,
Me gustaría automatizar cada el proceso de creación y envió de facturas electrónicas, ya q cada vez se usan mas.
Hasta ahora obligaba a mis clientes a firmar las facturas con el programa externo Autofirma, pero es un proceso manual donde tienen q localizar el XML, y muchos se me pierden.
Ademas q no me parece serio, y quiero preguntaros si alguno, ¿ habéis avanzado en este tema de firmar la factura, desde dentro de la propia aplicación?
Muchas gracias
Re: Firmar facturae
Posted: Thu Nov 29, 2018 2:49 pm
by karinha
Re: Firmar facturae
Posted: Thu Nov 29, 2018 3:57 pm
by José Vicente Beltrán
Yo utilizo una llamada a 'autofirma' desde la línea de comandos, dentro de mi aplicación FW y todo de forma transparente para el usuario
autofirmacommandline sign -i %1 -o %2 -format facturae -store windows -alias %3
%1 -> ruta+nombre del archivo XML sin firmar
%2 -> ruta+nombre del archivo XML una vez firmado
%3 -> alias del certificado obtenido directamente del código proporcionado por DarioFlores en el enlace indicado por Karinha mas arriba.
funciona sorprendentemente bien y con apariencia totalmente profesional, la ventaja es que cuando cambie la normativa de firmaE solo hay que actualizar 'autofirma' y ya está.
Re: Firmar facturae
Posted: Fri Nov 30, 2018 7:01 pm
by manuelcalerosolis
José Vicente y karinha gracias por vuestro interés.
Intento ejecutar el "autofirmacommandline" pero me dice q el alias del certificado no es valido, y realmente lo que le paso al comando es lo q me devuelve, la función publicada por karinha.
No se hay ninguna entrada en el almacen con el alias indicado: XXXXXX XXXXX XXXXXXX - 99999999X
Por el contrario en el programa de autofirma con gui, funciona perfectamente, me solicita el fichero a firmar, y me saca las firmas presentes en mi sistema.
La manera en la q monto el comando es esta, no se si algo esta mal
autofirmacommandline sign -i c:\temp\andrew.xml -o c:\temp\andrew-signed.xml -format facturae -store windows -alias "XXXXXX XXXXX XXXXXXX - 99999999X"
Saludos
Re: Firmar facturae
Posted: Sat Dec 01, 2018 1:19 am
by Tito
Manuel
Mira este link, talvez te resuelve tu problema
https://www.example-code.com/foxpro/xad ... 3_2_es.aspsaludos
Héctor
Re: Firmar facturae
Posted: Sun Dec 02, 2018 10:21 am
by manuelcalerosolis
Hector,
Gracias por tu respuesta, voy a seguir intentado el tema con Autofirma, pq realmente es facturae hay cambios constantes, y me gusta mas la idea de usar el comando.
A ver si logro saber lo q pasa, y acaba reconociendo la el certificado.
Saludos
Re: Firmar facturae
Posted: Sun Dec 02, 2018 8:54 pm
by AngelSalom
Me quedo en el hilo, interesante intentar la automatización con Autofirma.
Re: Firmar facturae
Posted: Mon Dec 03, 2018 10:33 am
by José Vicente Beltrán
Manuel, yo utilizo el siguiente código y funciona sin problemas.
Code: Select all | Expand
...
if FILE
( xFileOrigen
) lChDir
( cFilePath
(xRutaBAT
) ) if file
(cFilePath
(xRutaBAT
)+
"Autofirma.exe") cCertif := SelCertif
(SELCERT
()) cCertif := UPPER
(alltrim
(cCertif
)) else cCertif :=
"" endif if !empty
(cCertif
) WaitRun
( xRutaBAT+
' "'+xFileOrigen+
'" "'+xFileDestino+
'" "'+cCertif+
'"') // firmando la factura con autofirma endif lChDir
( cDirecDatos
) else msgInfo( "Archivo XML no generado",
"Aviso") return .t.
endif//LLamada a la funcion de seleccion de certificados: SelCertif(SELCERT())//*****************************************************************************function SelCertif
( uVal
) local cType := ValType
( uVal
) do case case cType ==
"C" .or. cType ==
"M" return uVal
// devuelve el alias del certificado seleccionado case cType ==
"D" return DToC
( uVal
) case cType ==
"L" return If( uVal,
".T.",
".F." ) case cType ==
"N" return AllTrim
( Str
( uVal
) ) case cType ==
"B" return "{|| ... }" case cType ==
"A" return "{ ... }" case cType ==
"O" return If( __ObjHasData
( uVal,
"cClassName" ), uVal:
cClassName, uVal:
ClassName() ) case cType ==
"H" return "{=>}" otherwise return "" endcasereturn nil//*****************************************************************************//*****************************************************************************#pragma BEGINDUMP
#include <windows.h>
//#include <psapi.h>//#include <hbapi.h>//#include <hbapierr.h>//#include <hbapiitm.h>//#include <wincrypt.h>#define CRYPTUI_SELECT_LOCATION_COLUMN 0x000000010
//Definir el prototipo de las funciones:typedef HCERTSTORE
(WINAPI * PTYPECERTOPEN
) (HCRYPTPROV, LPTSTR
);
typedef PCCERT_CONTEXT
(WINAPI * PTYPECERTSELECTDLG
) (HCERTSTORE, HWND, LPCWSTR, LPCWSTR, DWORD, DWORD, void*
);
typedef PCCERT_CONTEXT
(WINAPI * PTYPECERTENUM
) (HCERTSTORE, PCCERT_CONTEXT
);
typedef DWORD
(WINAPI * PTYPECERTGETNAME
) (PCCERT_CONTEXT, DWORD, DWORD, VOID*, LPTSTR, DWORD
);
typedef DWORD
(WINAPI * PTYPECERTNAMETOSTR
) (DWORD, PCERT_NAME_BLOB, DWORD, LPTSTR, DWORD
);
typedef BOOL
(WINAPI * PTYPECERTFREECC
) (PCCERT_CONTEXT
);
typedef BOOL
(WINAPI * PTYPECERTCLOSESTORE
) (HCERTSTORE, DWORD
);
HB_FUNC(SELCERT
){ // Hay varios ejemplos en: https://msdn.microsoft.com/en-us/librar ... 61(v=vs.85).aspx HCERTSTORE hStore;
PCCERT_CONTEXT PrevContext, CurContext;
PCHAR sNombre;
DWORD cbSize;
PHB_ITEM pArray;
PHB_ITEM pItem;
PCCERT_CONTEXT pCertContext;
// Cargamos las librerías de las que queremos la dirección de las funciones. HMODULE HCrypt = LoadLibrary
("Crypt32.dll");
HMODULE HCrypt2 = LoadLibrary
("Cryptui.dll");
// Declaramos el tipo de puntero a la función, tenemos la definición arriba. PTYPECERTOPEN pCertOpen;
PTYPECERTSELECTDLG pCertSelectDlg;
PTYPECERTGETNAME pCertGetName;
PTYPECERTNAMETOSTR pCertNameToStr;
PTYPECERTFREECC pCertFreeCC;
PTYPECERTCLOSESTORE pCertCloseStore;
if (HCrypt !=
NULL && HCrypt2 !=
NULL){ //Sacamos el puntero todas las funciones que vamos a usar mediante GetProcAddress: #ifdef UNICODE
pCertOpen =
(PTYPECERTOPEN
) GetProcAddress
(HCrypt,
"CertOpenSystemStoreW");
pCertGetName =
(PTYPECERTGETNAME
) GetProcAddress
(HCrypt,
"CertGetNameStringW");
#else
pCertOpen =
(PTYPECERTOPEN
) GetProcAddress
(HCrypt,
"CertOpenSystemStoreA");
pCertGetName =
(PTYPECERTGETNAME
) GetProcAddress
(HCrypt,
"CertGetNameStringA");
#endif
pCertSelectDlg =
(PTYPECERTSELECTDLG
) GetProcAddress
(HCrypt2,
"CryptUIDlgSelectCertificateFromStore");
pCertFreeCC =
(PTYPECERTFREECC
) GetProcAddress
(HCrypt,
"CertFreeCertificateContext");
pCertCloseStore =
(PTYPECERTCLOSESTORE
) GetProcAddress
(HCrypt,
"CertCloseStore");
} if (pCertOpen
){ // Llamada a CertOpenSystemStore: hStore = pCertOpen
(NULL,
TEXT("MY"));
} if (hStore
){ // Diálogo de selección de certificado: pCertContext = pCertSelectDlg
(hStore,
NULL,
NULL,
NULL, CRYPTUI_SELECT_LOCATION_COLUMN,
0,
NULL);
if (pCertContext
){ cbSize = pCertGetName
(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
NULL,
0);
if (cbSize>
0) { //Reservamos la memoria que necesitamos para el texto que recibiremos sNombre =
(LPTSTR
)malloc
(cbSize * sizeof
(TCHAR
));
pCertGetName
(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL, sNombre, cbSize
);
// Llamada a CertFreeCertificateContext: pCertFreeCC
(pCertContext
);
} } // Cerrar el almacen de certificados: // Llamada a CertCloseStore: pCertCloseStore
(hStore,
0);
} FreeLibrary
(HCrypt
);
FreeLibrary
(HCrypt2
);
hb_retc
(sNombre
);
}#pragma ENDDUMP
Re: Firmar facturae
Posted: Mon Dec 03, 2018 9:39 pm
by manuelcalerosolis
Jose Vicente,
Pero no usas Autofirmacommandline.exe ?
Saludos
Re: Firmar facturae
Posted: Tue Dec 04, 2018 11:31 am
by José Vicente Beltrán
Claro que si, la linea de codigo siguiente llama al .bat que ejecuta autofirmacommanline.exe
xRutaBat -> ruta + nombre del .bat
Code: Select all | Expand
WaitRun( xRutaBAT+' "'+xFileOrigen+'" "'+xFileDestino+'" "'+cCertif+'"')
el .BAT contiene la siguiente linea
autofirmacommandline sign -i %1 -o %2 -format facturae -store windows -alias %3
Re: Firmar facturae
Posted: Tue Dec 11, 2018 12:11 pm
by manuelcalerosolis
José Vicente,
Funciono perfecto, el tema era q tenia q instalar otro certificado con el q yo tenia, en mi pc, no funcionaba.
Mil gracias.
Re: Firmar facturae
Posted: Sat Dec 15, 2018 4:20 pm
by Xevi
José Vicente,
compilando y ejecutando tu ejemplo, se lanza correctamente el diálogo de selección de certificado, pero... si salgo del diálogo cancelando, para "abortar" el seguimiento de la firma, el retorno no es Empty(cCertif)... y el proceso sigue pasando igualmente por Waitrun()
El valor que se recibe de SelCertif(SELCERT()) nunca es Empty(), pero no se como hacer o cambiar para poder detectar cuando se pulsa en Cancelar del diálogo de Selección de Certificado.
Alguna ayuda???
Alguien más utiliza esa función y lo puede probar???
Gracias por vuestro tiempo.
Re: Firmar facturae
Posted: Sun Dec 16, 2018 8:36 am
by AngelSalom
Lo he probado y, efectivamente, al pulsar Cancelar en la selección del certificado la variable se carga con caracteres extraños.
Re: Firmar facturae
Posted: Sun Dec 16, 2018 9:24 am
by Xevi
Yo de momento lo soluciono cambiando
if !empty(cCertif)
...
por...
If empty(cCertif) .or. "Ä" $ cCertif .or. "ý" $ cCertif .or. "ô" $ cCertif .or. "€" $ cCertif
Else
...
Pero seria bueno poder cazar ese valor retornado como vacio o nulo para su posterior tratamiento, seria lo correcto.
Re: Firmar facturae
Posted: Wed Dec 19, 2018 3:48 pm
by Xevi
Puestos con el tema de Facturae,...
Cómo o de dónde obteneis/localizais los códigos DIR3 ???
(DIR3 Código de unidad orgánica)
son imprescindibles para el envio de facturas a entidades tales como ayuntamientos, al menos aquí donde yo estoy en fase Beta del envío de facturas electrónicas.
Seria bueno, y seguro que posible, disponer de una consulta a una web donde solicitar los datos DIR3 correspondiente a un CIF.
Como quien solicita la IP!!! jejeje
Demasiado pedir!!!
Gracias por vuestro tiempo.