OK, a diferencia de muchos de ustedes no uso OPEN SSL ni la clase CFD v9, porque cuando me uní al grupo ya estaba usando “firmasat” y desconocía la existencia de OPEN SSL y la clase CFD, además ya había hecho una clase para usar “firmasat” que me funciona bastante bien, también uso un framework (CODEMINE) en mi programa, en el ejemplo verán algunas llamadas a algunos métodos que corresponden al framework pero ustedes podrán diferenciarlo y sustituirlo.
Basándonos en el hecho que ya has creado el contenido del XML que se va a enviar y lo tienes dentro de una variable de tipo texto. Por ejemplo la siguiente factura.
<?xml version="1.0" encoding="UTF-8"?>
<cfdi:Comprobante xsi:schemaLocation="http://www.sat.gob.mx/cfd/3cfdv3.xsd" xmlns:cfdi="http://www.sat.gob.mx/cfd/3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0" fecha="2011-02-25T22:34:29" sello="" total="22229.97" subTotal="19163.77" certificado="" formaDePago="Pago en una sola exhibición" noCertificado="" tipoDeComprobante="ingreso">
<cfdi:Emisor rfc="GAAT525461KPA" nombre="RICARDO GOMEZ ACOSTA">
<cfdi:DomicilioFiscal calle="PROL. MIGUEL ALEMAN KM 3.5" codigoPostal="91799" colonia="PEDRO I. MATA" estado="VERACRUZ" localidad="VERACRUZ" municipio="VERACRUZ" noExterior="4910" pais="MEXICO"></cfdi:DomicilioFiscal>
</cfdi:Emisor>
<cfdi:Receptor rfc="BIMO11108DJ5" nombre="BIMBO S.A. DE C.V.">
<cfdi:Domicilio calle="MIMOSAS NO. 117 COL. SANTA MARIA INSURGENTES DELEGACION CUAUHTEMOC" codigoPostal="CP6430" colonia="SANTA MARIA INSURGENTES" estado="DISTRITO FEDERAL" localidad="MEXICO" municipio="MEXICO" noExterior="117" pais="México"></cfdi:Domicilio>
</cfdi:Receptor>
<cfdi:Conceptos>
<cfdi:Concepto cantidad="1" descripcion="DESMONTAR DIFERENCIAL PARA SU REPARACION" importe="2800.00" unidad="Unidad" valorUnitario="2800.00" noIdentificacion="DESMDIF"></cfdi:Concepto>
<cfdi:Concepto cantidad="1.00" descripcion="KIT DE DUAL CON BALEROS DE CARGA" importe="15448.77" unidad="Unidad" valorUnitario="15448.77" noIdentificacion="KITDU"></cfdi:Concepto>
<cfdi:Concepto cantidad="1.00" descripcion="SILICON" importe="35.00" unidad="Unidad" valorUnitario="35.00" noIdentificacion="SILICON"></cfdi:Concepto>
<cfdi:Concepto cantidad="16.00" descripcion="ACEITE PARA DIFERENCIAL" importe="880.00" unidad="Unidad" valorUnitario="55.00" noIdentificacion="ACEDIF"></cfdi:Concepto>
</cfdi:Conceptos>
<cfdi:Impuestos totalImpuestosTrasladados="3066.20">
<cfdi:Traslados>
<cfdi:Traslado impuesto="IVA" importe="3066.20" tasa="16"></cfdi:Traslado>
</cfdi:Traslados>
</cfdi:Impuestos>
<cfdi:Complemento></cfdi:Complemento>
</cfdi:Comprobante>
Este es un CFDI típico, las diferencias con en CFD no son muchas pero las más resaltantes es que no tiene nodos de “Folio”, “Serie” ni nada que haga referencia a folios, además, al final tiene un nodo de complemento. Consulten el ANEXO 20 para los detalles. Al principio yo pensaba que el XML se debía enviar así mismo al PAC, pero no, primero hay que firmarlo con el certificado del cliente y su firma digital.
Bien, supongamos que tienes este código XML de tu CFDI en una variable String.
*** cfd_xml = varible string con el XML, la guardamos en un campo de tipo memo de una tabla.
REPLACE cfd_xml WITH STRCONV(m.cfd_xml_mx,9) IN facturas_cfd
m.cCFDFileNameTMP = m.cCFDPath + "NombreXML.TMP" && Ruta y Nombre del XML temporal
m.cCFDFileNameXML = m.cCFDPath + "NombreXML.XML" && Ruta y Nombre del XML final
SET SAFETY OFF
WAIT "Generando el CFDI, espere un momento." WINDOW NOWAIT
COPY MEMO facturas_cfd.cfd_xml TO (cCFDFileNameTMP) && Guardamos en XML en un archivo temporal
&&********** FIRMADO DEL ARCIVO XML **************&&
* Yo uso el DLL “firmasat” para firmar los XML *
* En la forma esta la clase como un objeto llamado “Firmasat1” *
* m.cPassword = Contraseña del cliente para su firma digital *
* m.cFileFirmaDigital = Ruta y nombre del archivo .key *
* m.cFileCertificado = Ruta y nombre del archivo .cer *
IF THISFORM.Firmasat1.satsignxml(m.cCFDFileNameXML,m.cCFDFileNameTMP,m.cFileFirmaDigital,m.cPassword,m.cFileCertificado,1) = 0
DELETE FILE (cCFDFileNameTMP)
ELSE
THISFORM.Displaywarning("Error firmando digitalmente el archivo de comprobante fiscal digital: "+THISFORM.firmasat1.cLasterror)
WAIT CLEAR
RETURN .F.
ENDIF
SET SAFETY ON
IF !THISFORM.Firmasat1.satvalidatexml(cCFDFileNameXML) = 0
THISFORM.Displaywarning("Error validando el archivo de comprobante XML: "+THISFORM.firmasat1.cLasterror)
DELETE FILE (cCFDFileNameXML)
WAIT CLEAR
RETURN .F.
ENDIF
* *
* *
&&*****************************************************************&&
&&********** PROCEDIMIENTO DE ENVIO DE CFDI A EDICOM **************&&
* *
* *
* Este código te lo puedes traer arrastrando desde el Toolbox *
* En la pestaña “My XML Web Services”, si registras el *
* Web service con el “XML Web Services Registration” de FoxPro *
LOCAL loCFDi AS "XML Web Service"
* LOCAL loCFDi AS "MSSOAP.SoapClient30"
* Do not remove or alter following line. It is used to support IntelliSense for your XML Web service.
*__VFPWSDef__: loCFDi = https://cfdiws.sedeb2b.com/EdiwinWS/services/CFDi?wsdl , CFDiService , CFDi
LOCAL loException, lcErrorMsg, loWSHandler
m.lcErrorMsg = ""
TRY
loWSHandler = NEWOBJECT("WSHandler",IIF(VERSION(2)=0,"",HOME()+"FFC\")+"_ws3client.vcx")
loCFDi = loWSHandler.SetupClient("https://cfdiws.sedeb2b.com/EdiwinWS/services/CFDi?wsdl", "CFDiService", "CFDi")
* Call your XML Web service here. ex: leResult = loCFDi.SomeMethod()
CATCH TO loException
lcErrorMsg="Error: "+TRANSFORM(loException.Errorno)+" - "+loException.Message
DO CASE
CASE VARTYPE(loCFDi)#"O"
* Handle SOAP error connecting to web service
CASE !EMPTY(loCFDi.FaultCode)
* Handle SOAP error calling method
lcErrorMsg=lcErrorMsg+CHR(13)+loCFDi.Detail
OTHERWISE
* Handle other error
ENDCASE
* Use for debugging purposes
THISFORM.Displaywarning("ERROR: "+lcErrorMsg)
FINALLY
ENDTRY
IF !EMPTY(m.lcErrorMsg)
DELETE FILE (cCFDFileNameXML)
WAIT CLEAR
RETURN .F.
ENDIF
**** Creamos el ZIP que contiene el XML sin timbrar *****
m.fzip = CREATEOBJECT("zbitz.zzip") && Utiliza zbitz.dll para crear el archivo zip
m.zipFileName = LEFT(m.cCFDFileNameXML,RAT('.',m.cCFDFileNameXML,1)-1)+".zip"
IF TYPE('fzip') = 'O'
m.fzip.KeepDirNames = .F.
m.Resp = fzip.ZipFile(m.cCFDFileNameXML, m.zipFileName) && Crea el archivo zip
fzip = NULL
RELEASE fzip
ELSE
THISFORM.Displaywarning("Error en la compresión del CFDi")
DELETE FILE (cCFDFileNameXML)
WAIT CLEAR
RETURN .F.
ENDIF
IF m.Resp != 0
THISFORM.Displaymessage("ERROR #"+ALLTRIM(STR(m.Resp))+": No se pudo crear el archivo comprimido del CFDi.")
DELETE FILE (cCFDFileNameXML)
WAIT CLEAR
RETURN .F.
ENDIF
REPLACE cfdi_byte_file WITH FILETOSTR(m.zipFileName) IN facturas_cfd && Guarda el zip dentro del campo tipo Blod
DELETE FILE (zipFileName) && Se elimina el archivo zip
m.lCFDi_Sellado = ""
m.lcErrorMsg = ""
m.cEDICOM_User = 'TESTCFDI3' && Usuario de EDICOM
m.cEDICOM_Password = '**********' && Password de EDICOM
TRY
m.lCFDi_Sellado = loCFDi.getCfdiTest(m.cEDICOM_User,m.cEDICOM_Password,facturas_cfd.cfdi_byte_file) && Llama el Metodo getCfdiTest
*** Revisa el manula de EDICOM para el resto de los metodos especialmente para los de producción que son los que se van a usar al final ****
CATCH TO loException
m.lcErrorMsg = loException.Message
m.lcErrorMsg = RIGHT(lcErrorMsg,LEN(lcErrorMsg)-RAT(':',lcErrorMsg,1)-1) && se simplifica el mensaje de error para que se entienda por el usuario
m.lcErrorMsg = "ERROR: "+m.lcErrorMsg
THISFORM.Displaywarning(m.lcErrorMsg)
FINALLY
ENDTRY
IF !EMPTY(m.lcErrorMsg)
DELETE FILE (cCFDFileNameXML)
WAIT CLEAR
RETURN .F.
ENDIF
* *
* *
&&*****************************************************************&&
&&********** EXTRACCION DE LA RESPUESTA DEL WEB SERVICE ***********&&
* *
* *
m.zipFileName = LEFT(m.cCFDFileNameXML,RAT('.',m.cCFDFileNameXML,1)-1)+".zip" && Nombre del archivo ZIP que se recibe como respuesta
STRTOFILE(m.lCFDi_Sellado,m.zipFileName) && Guardamos el zip en el disco
**** Descompresión del Zip. ****
m.funzip = CREATEOBJECT("zbitz.zzip") && Utiliza zbitz.dll para descomprimir el archivo zip
IF TYPE('funzip') = 'O'
**** PRUEBA PARA VERIFICAR QUE NO HAY ERRORES *****
funzip.TestMode = 1
m.Resp = funzip.unzipfile(m.zipfilename,m.cCFDPath)
funzip.TestMode = 0
IF !EMPTY(funzip.LastMsg)
THISFORM.Displaymessage("ERROR #"+ALLTRIM(STR(m.Resp))+": "+funzip.LastMsg)
DELETE FILE (cCFDFileNameXML)
WAIT CLEAR
RETURN .F.
ENDIF
**** SI NO HAY ERRORES CONTINUA ****
m.Resp = funzip.unzipfile(m.zipfilename,m.cCFDPath)
funzip = NULL
RELEASE funzip
ELSE
THISFORM.Displaywarning("Error en la descompresión del CFDi")
DELETE FILE (cCFDFileNameXML)
WAIT CLEAR
RETURN .F.
ENDIF
IF m.Resp != 0
THISFORM.Displaymessage("ERROR #"+ALLTRIM(STR(m.Resp))+": No se pudo descomprimir el archivo CFDi.")
DELETE FILE (cCFDFileNameXML)
WAIT CLEAR
RETURN .F.
ENDIF
DELETE FILE (zipFileName) && Se elimina el archivo zip
** Nombre del archivo XML que se recibió ya firmado por el PAC **
m.SIGN_cCFDFileNameXML = m.cCFDPath + "SIGN_"+ "NombreXML.xml"
* *
* *
&&*****************************************************************&&
Al final del código, tienes ya la ruta y nombre del archivo XML del CFDI timbrado por el PAC, para que ya lo manipules para generar la representación impresa, pasarlo a .PDF, enviarlo por email, etc.
Lo único que no he podido resolver hasta ahora es que en la prueba no me regresa el número de folio ni la serie, hasta ahora supongo que es porque estoy usando una cuenta de prueba que me dio de alta EDICOM y esa cuenta no tiene folios asignados, pero estoy a la espera de que ellos me confirmen esto. Pero mi duda también viene porque en la estructura del timbre fiscal que aparece en el ANEXO 20 no se contempla ningún nodo para el folio y serie.
Si saben algo de esto me avisan.
Un gran saludos a todos.
Firmo Lopez
Alejandro Castrejón Torres
Teléfono: (662) 218-1194 Email: alejandro...@smartfactura.com Sitio: http://www.smartfactura.com |
|
— This message was sent by Alejandro Castrejón. If you really want to know more about me, you can visit my social services profiles |
--
Has recibido este mensaje porque estás suscrito al grupo "vfp-factura-electronica-mexico" de Grupos de Google.
Para publicar una entrada en este grupo, envía un correo electrónico a vfp-factura-ele...@googlegroups.com.
Para anular tu suscripción a este grupo, envía un correo electrónico a vfp-factura-electroni...@googlegroups.com
Para tener acceso a más opciones, visita el grupo en http://groups.google.com/group/vfp-factura-electronica-mexico?hl=es.
Alejandro Castrejón T
Consultor Teléfono: (662) 168-1424 Email: acast...@consultant.com Site: http://www.consultant.com |
— This message was sent by Alejandro Castrejón. If you really want to know more about me, you can visit my social services profiles |
--
Has recibido este mensaje porque estás suscrito al grupo "vfp-factura-electronica-mexico" de Grupos de Google.
Para anular la suscripción a este grupo y dejar de recibir sus correos electrónicos, envía un correo electrónico a vfp-factura-electroni...@googlegroups.com.
Para publicar una entrada en este grupo, envía un correo electrónico a vfp-factura-ele...@googlegroups.com.
Visita este grupo en http://groups.google.com/group/vfp-factura-electronica-mexico.
Para obtener más opciones, visita https://groups.google.com/groups/opt_out.
Algun ejemplo con lo del complemento para pagos 2017??
--
Has recibido este mensaje porque estás suscrito al grupo "vfp-factura-electronica-mexico" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a vfp-factura-electronica-mexico+unsubscribe@googlegroups.com.
Para publicar una entrada en este grupo, envía un correo electrónico a vfp-factura-electronica-mex...@googlegroups.com.
Visita este grupo en https://groups.google.com/group/vfp-factura-electronica-mexico.
Para obtener más opciones, visita https://groups.google.com/d/optout.