Static cToken 聽 聽
Static cSign 聽 聽
Static cCuit 聽 聽
Static nUltCmpAut
//----------------------------------------------------------------------------//
Function Main()
聽 聽 * Declaro Las Variables De Trabajo
聽 聽 Local nOpc := 1
聽 聽 * Declaro estas Variables como privadas para poder usarlas en todas las funciones
聽 聽 cToken 聽 聽 := ''
聽 聽 cSign 聽 聽 聽:= ''
聽 聽 cCuit 聽 聽 聽:= '20267565393' // CUIT de la Empresa
聽 聽 nUltCmpAut := 0
聽 聽 //Private CRLF 聽 聽 聽 := chr( 13 ) + chr( 10 ) // Retorno de carro y avance de linea
聽 聽 * Leo los valores del Ultimo Ticket De Acceso -> cSign
聽 聽 Leo_Ultimo_Ticket_de_Acceso()
聽 聽 Cls
聽 聽 nOpc := 1
聽 聽 While( nOpc # 0 )
聽 聽 聽 聽 @ 04, 18 Prompt Padr( '1) Consultar el Estado de los Servidores', 44, ' ' )
聽聽 聽聽 聽 @ 06, 18 Prompt Padr( '2) Pedir el Ticket de Acceso', 44, ' ' )
聽聽 聽聽 聽 @ 08, 18 Prompt Padr( '3) Consultar el Nro de la Ultima FACTURA', 44, ' ' )
聽聽 聽聽 聽 @ 10, 18 Prompt Padr( '4) Pedir el CAE de una FACTURA', 44, ' ' )
聽聽 聽聽 聽 Menu to nOpc
聽 聽 聽 聽 聽If( nOpc == 1 )
聽 聽 聽 聽 聽 聽 Opc_FEDummy()
聽聽 聽聽 聽 ElseIf( nOpc == 2 )
聽 聽 聽 聽 聽 聽 Opc_PidoElTicketDeAcceso()
聽聽 聽聽 聽 ElseIf( nOpc == 3 )
聽 聽 聽 聽 聽 聽 Opc_FECompUltimoAutorizado( cToken, cSign, cCUIT )
聽聽 聽聽 聽 ElseIf( nOpc == 4 )
聽 聽 聽 聽 聽 聽 Opc_FECAESolicitar( cToken, cSign, cCUIT )
聽聽 聽聽 聽 End
聽 聽 Enddo
聽 聽 Return( .t. )
//----------------------------------------------------------------------------//
*: Leo_Ultimo_Ticket_de_Acceso 聽 聽 聽 聽 聽:
*: Leo El Ultimo Ticket De Acceso Para Leer El Token Y El Sign Y Validar Si :
*: Esta Dentro De Las 12 Horas De Que Fue Emitido. 聽 聽 聽 :
*: Estado: OK (funcionando) 聽 聽 聽 聽 聽:
//----------------------------------------------------------------------------//
聽 聽 Function Leo_Ultimo_Ticket_de_Acceso()
聽 聽 Local nIdx 聽聽 聽 聽 聽 聽 聽 聽:= 0
聽 聽 Local cXml 聽 聽 聽 聽 聽 聽:= ''
聽 聽 Local aRespuesta 聽 聽 聽:= {}
聽 聽 Local cFechaHoraDesde := ''
聽 聽 Local cFechaHoraHasta := ''
聽 聽 聽 聽
聽 聽 * Si NO existe el archivo TA.xml es porque NO tengo un Ticket de Acceso (TA)
聽 聽 * Dejo las variables vacias con lo cual obligo a pedir el TA desde el menu ==
聽 聽 If( !File( 'TA.xml' ) )
聽聽 聽聽 聽 MsgStop( 'NO existe TA.xml;Pida un Nuevo TICKET DE ACCESO' )
聽聽 聽聽 聽 Return( .f. )
聽 聽 End
聽 聽 cXml 聽 聽 聽 := MemoRead( 'TA.xml' )
聽 聽 aRespuesta := Opc_LeeRespuesta( cXml, 'TA' )
聽 聽 If( !Empty( aRespuesta ) )
聽聽 聽聽 聽 nIdx := Ascan( aRespuesta, { | aAux | aAux[ 1 ] = 'token' } )
聽聽 聽聽 聽 If( nIdx # 0 )
聽 聽 聽 聽 聽 聽 cToken := aRespuesta[ nIdx, 2 ]
聽聽 聽聽 聽 End
聽聽 聽聽 聽 nIdx := Ascan( aRespuesta, { | aAux | aAux[ 1 ] = 'sign' } )
聽 聽 聽 聽 If( nIdx # 0 )
聽 聽 聽 聽 聽 聽 cSign := aRespuesta[ nIdx, 2 ]
聽聽 聽聽 聽 End
聽 聽 End
聽 聽 * Valido que TA todavia sea VALIDO
聽 聽 nIdx := Ascan( aRespuesta, { | aAux | aAux[ 1 ] = 'generationtime' } )
聽 聽 If( nIdx # 0 )
聽聽 聽聽 聽 cFechaHoraDesde := CToD( aRespuesta[ nIdx, 2 ] )
聽 聽 End
聽 聽 nIdx := Ascan( aRespuesta, { | aAux | aAux[ 1 ] = 'expirationtime' } )
聽 聽 If( nIdx # 0 )
聽聽 聽聽 聽 cFechaHoraHasta := aRespuesta[ nIdx, 2 ]
聽 聽 End
聽 聽 Return( .t. )
//-----------------------------------------------------------------------------//
*: LlamoAlWSAA Llamo al WS de AUTENTICACION para pedir el Ticket de Acceso :
*: Estado: OK (funcionando) 聽 聽 聽 聽 聽:
//----------------------------------------------------------------------------//
Function LlamoAlWSAA( c_CMS_Base64 )
聽 聽 Local cXml 聽 聽 聽 := ''
聽 聽 Local oWSAA 聽 聽 聽:= ''
聽 聽 Local cWSAA_URL 聽:= 'https://wsaahomo.afip.gov.ar/ws/services/LoginCms'
聽 聽 Local cRespuesta := ''
聽 聽 oWSAA 聽:= Win_OleCreateObject( 'MSXML2.XMLHTTP' )
聽 聽 If( Empty( oWSAA ) )
聽聽 聽聽 聽 MsgStop( 'NO se Pudo Crear el Objeto oWSAA;se Cancela el Programa' )
聽聽 聽聽 聽 Return( .f. )
聽 聽 End
聽 聽 * Armo el XML con el TRA
聽 聽 cXml += '<?xml version="1.0" encoding="UTF-8"?>' 聽 聽+ CRLF
聽 聽 cXml += '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' + CRLF
聽 聽 cXml += '<soap:Body>' 聽 聽 聽 + CRLF
聽 聽 cXml += ' 聽 聽<loginCms xmlns="http://wsaa.view.sua.dvadac.desein.afip.gov">' + CRLF
聽 聽 cXml += ' 聽 聽<in0>' + c_CMS_Base64 + '</in0>' 聽 聽+ CRLF
聽 聽 cXml += ' 聽 聽</loginCms>' 聽 聽 聽 + CRLF
聽 聽 cXml += '</soap:Body>' 聽 聽 聽 + CRLF
聽 聽 cXml += '</soap:Envelope>' 聽 聽 聽 + CRLF
聽 聽 * Llamo al Webservice y defino Opciones
聽 聽 oWSAA : Open( 'POST', cWSAA_URL, .f. )
聽 聽 oWSAA : SetRequestHeader( "SOAPAction:", "None" )
聽 聽 oWSAA : SetRequestHeader( "Content-Type", "text/xml;charset=UTF-8" )
聽 聽 * Envio el Archivo y Recibo la Respuesta del WS
聽 聽 oWSAA : Send( cXml )
聽 聽 * Si el status es diferente a 200, ocurri垄 alg拢n error de conectividad con el WS ---
聽聽 聽cRespuesta := oWSAA : ResponseText
聽 聽 if( Empty( cRespuesta ) )
聽聽 聽聽 聽 MsgStop( "Error; cRespuesta esta VACIO" )
聽 聽 End
聽 聽 * Por las Dudas de que la Respuesta venga en Formato RAW
聽 聽 If( !Empty( cRespuesta ) )
聽聽 聽聽 聽 If( '<' $ cRespuesta ) // <
聽 聽 聽 聽 聽 聽 cRespuesta := StrTran( cRespuesta, '<', '<' )
聽聽 聽聽 聽 End
聽聽 聽聽 聽 If( '>' $ cRespuesta ) // >
聽 聽 聽 聽 聽 聽 cRespuesta := StrTran( cRespuesta, '>', '>' )
聽聽 聽聽 聽 End
聽聽 聽聽 聽 If( '"' $ cRespuesta ) // "
聽 聽 聽 聽 聽 聽 cRespuesta := StrTran( cRespuesta, '"', '"' )
聽聽 聽聽 聽 End
聽聽 聽聽 聽 If( ''' $ cRespuesta ) // \
聽 聽 聽 聽 聽 聽 cRespuesta := StrTran( cRespuesta, ''', '\' )
聽聽 聽聽 聽 End
聽聽 聽聽 聽 If( '&' $ cRespuesta ) // &
聽 聽 聽 聽 聽 聽 cRespuesta := StrTran( cRespuesta, '&', '&' )
聽聽 聽聽 聽 End
聽 聽 End
聽 聽 * Hago mas legible el XML
聽 聽 cRespuesta := StrTran( cRespuesta, '><', '>' + CRLF + '<' )
聽 聽 * Dicen que si no se borra el Objeto, despues de un tiempo se incrementa mucho
聽 聽 * el uso de memoria por parte del programa. No lo constate, pero por las dudas
聽 聽 oWSAA 聽:= NIL
聽 聽 Release oWSAA
聽 聽 Return( cRespuesta )
//----------------------------------------------------------------------------//
*: LlamoAlWSFE Llamo al WS de Negocios para Procesar el Requerimiento 聽 聽 :
*: Estado: OK (funcionando) 聽 聽 聽 聽 聽:
//----------------------------------------------------------------------------//
Function LlamoAlWSFE( c_Xml, c_ServicioLlamado )
聽 聽 Local oWSFE 聽:= ''
聽 聽 Local cWSFE_URL := 'https://wswhomo.afip.gov.ar/wsfev1/service.asmx' // Modo HOMOLOGACION
聽 聽 *Local cWSFE_URL := 'https://servicios1.afip.gov.ar/wsfev1/service.asmx' // Modo PRODUCCION
聽 聽 Local cRespuesta := ''
聽 聽 * Creo y Valido el Objeto oWSFE
聽 聽 oWSFE 聽:= Win_OleCreateObject( 'MSXML2.XMLHTTP' )
聽 聽 If( empty( oWSFE ) )
聽聽 聽聽 聽 MsgStop( 'NO se Pudo Crear el Objeto oWSFE;se Cancela el Programa' )
聽聽 聽聽 聽 Return( .f. )
聽 聽 End
聽 聽 * Llamo al Webservice y Defino Opciones
聽 聽 oWSFE聽 聽: Open( 'POST', cWSFE_URL, .f. )
聽 聽 oWSFE : SetRequestHeader( 'SOAPAction', 'http://ar.gov.afip.dif.FEV1/' + c_ServicioLlamado )
聽 聽 oWSFE : SetRequestHeader( "Content-Type", "text/xml;charset=UTF-8" )
聽 聽 oWSFE : SetRequestHeader( 'Connection', 'Keep-Alive' )
聽 聽 * Envio el Archivo y Recibo la Respuesta del WS
聽 聽 oWSFE聽 聽: Send( c_Xml )
聽 聽 * Si el status es diferente a 200, ocurri垄 alg拢n error de conectividad con el WS
聽 聽 cRespuesta := oWSFE : ResponseText
聽 聽 If( Empty( cRespuesta ) )
聽聽 聽聽 聽 MsgStop( "Error;cRespuesta esta VACIO" )
聽 聽 End
聽 聽 * Por las Dudas de que la Respuesta venga en Formato RAW
聽 聽 If( !Empty( cRespuesta ) )
聽聽 聽聽 聽 If( '<' 聽$ 聽cRespuesta ) // <
聽 聽 聽 聽 聽 聽 cRespuesta := StrTran( cRespuesta, '<', '<' )
聽聽 聽聽 聽 End
聽聽 聽聽 聽 If( '>' 聽$ 聽cRespuesta ) // >
聽 聽 聽 聽 聽 聽 cRespuesta := StrTran( cRespuesta, '>', '>' )
聽聽 聽聽 聽 End
聽聽 聽聽 聽 If( '"' 聽$ 聽cRespuesta ) // "
聽 聽 聽 聽 聽 聽 cRespuesta := StrTran( cRespuesta, '"', '"' )
聽聽 聽聽 聽 End
聽聽 聽聽 聽 If( ''' 聽$ 聽cRespuesta ) // \
聽 聽 聽 聽 聽 聽 cRespuesta := StrTran( cRespuesta, ''', '\' )
聽聽 聽聽 聽 End
聽聽 聽聽 聽 If( '&' 聽$ 聽cRespuesta ) // &
聽 聽 聽 聽 聽 聽 cRespuesta := StrTran( cRespuesta, '&', '&' )
聽聽 聽聽 聽 End
聽 聽 End
聽 聽 * Hago mas legible el XML
聽 聽 cRespuesta := StrTran( cRespuesta, '><', '>' + CRLF + '<' )
聽 聽 oWSFE 聽:= NIL
聽 聽 Release oWSFE
聽 聽 Return( cRespuesta )
//----------------------------------------------------------------------------//
*: Opc_FEDummy Verifica el funcionamiento de los servidores de la afip 聽 聽 :
*: Estado: OK (funcionando) 聽 聽 聽 聽 聽:
//----------------------------------------------------------------------------//
Function Opc_FEDummy()
聽 聽
聽 聽 Local nHandle
聽 聽 Local cXml 聽 聽 聽 := ''
聽 聽 Local aRespuesta := {}
聽 聽 Local cRespuesta := ''
聽 聽 * Armo El Archivo Xml con el Pedido
聽 聽 cXml += '<?xml version="1.0" encoding="UTF-8"?>' 聽 + CRLF
聽 聽 cXml += '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' + CRLF
聽 聽 cXml += '<soap:Body> ' 聽 聽 聽+ CRLF
聽 聽 cXml += ' 聽 <FEDummy xmlns="http://ar.gov.afip.dif.FEV1/" />' + CRLF
聽 聽 cXml += '</soap:Body>' 聽 聽 聽+ CRLF
聽 聽 cXml += '</soap:Envelope>' 聽 聽 聽+ CRLF
聽 聽
聽 聽 * Esto NO hace falta, pero lo hago para controlar como se formo el XML
聽 聽 If( ( nHandle := fCreate( 'FEDummy_Req.xml', 0 ) ) == -1 )
聽聽 聽聽 聽 MsgStop( 'NO se pudo crear FEDummy_Req.xml' )
聽聽 聽聽 聽 Return( .f. )
聽 聽 Else
聽 聽 聽聽 聽fWrite( nHandle, cXml )
聽聽 聽聽 聽 fClose( nHandle )
聽 聽 End
聽 聽 * Llamo al WS
聽 聽 cRespuesta := LlamoAlWSFE( cXml, 'FEDummy' )
聽 聽 hb_MemoWrit( 'FEDummy_Res.xml', cRespuesta )
聽 聽 MsgStop( 'FINALIZO la CONSULTA DEL ESTADO;DE LOS SERVIDORES DE LA AFIP;EL PEDIDO SE GRABO COMO: FEDummy_Req; LA RESPUESTA RECIBIDA SE GRABO COMO: FEDummy_Res' )
聽 聽 * Muestro el contenido del Xml Recibido
聽 聽 aRespuesta := Opc_LeeRespuesta( cRespuesta, 'FEDummy' )
聽 聽 MuestroRespuesta( aRespuesta )
聽 聽 Return( .t. )
//----------------------------------------------------------------------------//
*: PidoElTicketDeAcceso Funci垄n para Pedir el Tique de Acceso a los 聽 聽 :
*: 聽 Servidores de la AFIP 聽 聽 聽 聽:
*: Estado: OK (funcionando) 聽 聽 聽 聽 聽:
//----------------------------------------------------------------------------//
Function Opc_PidoElTicketDeAcceso()
聽 聽 Local cBat
聽 聽 Local nHandle
聽 聽 Local aRespuesta
聽 聽 Local cCert 聽聽 聽聽 聽 聽 聽 聽:= 'c:\pyrece\reingart\reingart.crt' // The X.509 obtained from Seg. Inf.
聽 聽 Local cPrivateKey 聽 聽:= 'c:\pyrece\reingart\reingart.key' // The private key correspoding to CERT
聽 聽 Local cSource 聽聽聽 聽 聽:= 'C=AR, O=PyAfipWs-Sistemas Agiles, SERIALNUMBER=CUIT 20267565393, CN=Mariano Reingart'
聽 聽 Local cDestinationDn 聽:= 'cn=wsaahomo,o=afip,c=ar,serialNumber=CUIT 33693450239'
聽 聽 Local cUniqueId 聽 聽 聽 聽 聽:= '1432505199' // > VER DE DONDE LO OBTENGO 聽 * NUMERO QUE IDENTIFICA EL REQUERIMIENTO, TIENE QUE SER DISTINTO CADA VEZ
聽 聽 Local cGenerationTime := TimeFMT( HB_DateTime(), -1 ) // - 1Hs
聽 聽 Local cExpirationTime := TimeFMT( HB_DateTime(), 1 ) // + 1Hs
聽 聽 Local cService 聽聽 聽 聽:= 'wsfe' // The WS service name you are asking a TA for ( "wdepmovimientos", "wsfe" )
聽 聽 Local cXML 聽聽 聽 聽 聽 聽 聽 聽:= '' 聽// Variable donde Armo el XML
聽 聽 Local cCMS 聽聽 聽 聽 聽 聽 聽 聽:= '' 聽// Variable donde esta el XML y su Firma Electronica
聽 聽 Local cTRA 聽聽 聽 聽 聽 聽 聽 聽:= '' 聽// Ticket de requerimiento de Acceso
聽 聽 Local cCMS_Base64 聽 聽:= '' 聽// Variable donde esta el CMS Codificado en Base64
聽 聽 Local cCmdSign 聽聽 聽 聽:= '' 聽// Comando para llamar a OpenSsl y Generar la Firma del Archivo XML
聽 聽 Local cPathOpenSsl 聽 聽:= 'C:\OpenSsl-Win32\Bin' // Donde Tengo Instalado OpenSsl
聽 聽 Local cRespuesta 聽 聽 聽:= ''
聽 聽 * Armo El Archivo Xml con el mensaje del TRA (LoginTicketRequest.xml)
聽 聽 cXml += '<?xml version="1.0" encoding="UTF-8"?>' + CRLF
聽 聽 cXml += '<loginTicketRequest version="1.0">' + CRLF
聽 聽 cXml += ' 聽<header>' 聽+ CRLF
聽 聽 cXml += ' 聽 聽<source>' + cSource + '</source>' + CRLF
聽 聽 cXml += ' 聽 聽<destination>' + cDestinationDn + '</destination>' + CRLF
聽 聽 cXml += ' 聽 聽<uniqueId>' + cUniqueId + '</uniqueId>' + CRLF
聽 聽 cXml += ' 聽 聽<generationTime>' + cGenerationTime + '</generationTime>' + CRLF
聽 聽 cXml += ' 聽 聽<expirationTime>' + cExpirationTime + '</expirationTime>' + CRLF
聽 聽 cXml += ' 聽</header>' + CRLF
聽 聽 cXml += ' 聽<service>' + cService + '</service>' + CRLF
聽 聽 cXml += '</loginTicketRequest>' + CRLF
聽 聽 * Grabo el Archivo XML con el Nombre TRA.xml
聽 聽 If( ( nHandle := fcreate( 'TRA.xml', 0 ) ) == -1 )
聽聽 聽聽 聽 MsgStop( 'NO se pudo crear TRA.xml' )
聽聽 聽聽 聽 Return( .f. )
聽 聽 Else
聽聽 聽fWrite( nHandle, cXml )
聽聽 聽fClose( nHandle )
聽 聽 End
聽 聽 * Genero la Firma Electronica de TRA.xml en el Archivo TRA.tmp
聽 聽 * Creo un Archivo BAT, con los comandos para llamar a OpenSsl y lo ejecuto.
聽 聽 * Preferiria Hacer Lo Siguiente Usando Funciones De Harbour.
聽 聽 * SI Bien Harbour Tiene La Libreria Hbssl Que Creo Que Sirve Para Firmar El
聽 聽 * Archivo Como Lo Pide La Afip, No Tengo Conocimientos De Encriptacion Y No
聽 聽 * Se Cual De Sus Funciones Usar.
聽 聽 * Ademas, Tube Muchos Problemas Para Crear La Libreria Y No Quedo Funcional.
聽 聽 * Por Lo Tanto, Si OpenSsl Funciona, No Pierdo Mas Tiempo Y Lo Uso.
聽 聽 * SI Alguien Se Anima A Cambiarlo Por Funciones Propias De Harbour, Bienvenido
聽 聽 * Al Barco :-)
聽 聽 * Otro Pedido, Usando Otros Lenguajes, Vi Que La Salida De Openssl, Se Puede
聽 聽 * Enviar A Pantalla Y De Ahi Tomar Esa Respuesta En Una Variable.
聽 聽 * DE Poder Hacerse Eso En Harbour, SE Evita La Grabacion Y Posterior Lectura
聽 聽 * Del Archivo Tra.tmp
聽 聽 cCmdSign := 'openssl smime' +;
聽 聽 聽聽 聽聽 聽 聽 聽 聽 聽 ' -sign' +;
聽 聽 聽聽 聽聽 聽 聽 聽 聽 聽 ' -in ' + 'TRA.xml' +; 聽 聽 聽 // Archivo XML a Firmar
聽 聽 聽聽 聽聽 聽 聽 聽 聽 聽 ' -out ' + 'TRA.tmp' +; 聽 聽 聽// Archivo con la Firma
聽 聽 聽聽 聽聽 聽 聽 聽 聽 聽 ' -signer ' + cCert +; 聽 聽 聽 //
聽 聽 聽聽 聽聽 聽 聽 聽 聽 聽 ' -inkey ' + cPrivateKey + ; //
聽 聽 聽聽 聽聽 聽 聽 聽 聽 聽 ' -outform ' + 'DER' 聽+; 聽 聽 // Lo Graba en Binario ('PEM' lo graba como numeros con 4 lineas de titulos)
聽 聽 聽聽 聽聽 聽 聽 聽 聽 聽 ' -nodetach' 聽 聽 聽 聽 聽 聽 聽 聽 // NO se Incluye el Archivo Original en la Salida
聽 聽 cBat := ''
聽 聽 cBat += 'path ' + cPathOpenSsl + CRLF
聽 聽 cBat += cCmdSign 聽 + CRLF
聽 聽 MemoWrit( 'FirmoXML.bat', cBat )
聽 聽 * Ejecuto el BAT para Generar TRA.tmp con la Firma
聽 聽 HB_run( 'FirmoXML.bat' ) 聽 聽 聽// HB_run() -> Funci垄n de Harbour para llamar progrmas externos
聽 聽 cCMS := MemoRead( 'TRA.tmp' ) // Leo el Archivo Firmado
聽 聽 * Codifico en base64
聽 聽 cCMS_Base64 := hb_base64Encode( cCMS ) // Funci垄n de Harbour
聽 聽 * Llamo al WS de Autenticaci垄n (WSAA)
聽 聽 cRespuesta := LlamoAlWSAA( cCMS_Base64 )
聽 聽 MemoWrit( 'TA.xml', cRespuesta )
聽 聽 MsgStop( 'FINALIZO EL PEDIDO DEL TICKET DE ACCESO;EL PEDIDO SE GRABO COMO: TRA.xml;LA RESPUESTA RECIBIDA SE GRABO COMO: TA.xml' )
聽 聽 * Muestro el contenido del XML RECIBIDO
聽 聽 aRespuesta := Opc_LeeRespuesta( cRespuesta, 'TA' )
聽 聽 MuestroRespuesta( aRespuesta )
聽 聽 Return( .t. )
//----------------------------------------------------------------------------//
*: Opc_FECompUltimoAutorizado 聽
*: Consulto el Nro. de la ULTIMA FACTURA AUTORIZADA
*: Estado: OK (funcionando)
//----------------------------------------------------------------------------//
Function Opc_FECompUltimoAutorizado( c_Token, c_Sign, c_CUIT )
聽 聽 Local nIdx
聽 聽 Local nHandle
聽 聽 Local cRespuesta
聽 聽 Local aRespuesta
聽 聽 Local cXml 聽:= ''
聽 聽 Local cPtoVta 聽:= Alltrim( Str( 0001 ) ) // Punto de Venta
聽 聽 Local cCbteTipo := Alltrim( Str( 001 ) ) // 1=FACTURA
聽 聽 If( Empty( cToken ) .or. Empty( cSign ) )
聽聽 聽聽 聽 MsgStop( 'Antes de usar esta opci垄n;Pida un Nuevo TICKET DE ACCESO' )
聽聽 聽聽 聽 Return( .f. )
聽 聽 End
聽 聽 * Armo El Archivo XML con el Pedido
聽 聽 cXml += '<?xml version="1.0" encoding="UTF-8"?>' 聽 + CRLF
聽 聽 cXml += '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' + CRLF
聽 聽 cXml += '<soap:Body> ' 聽 聽 聽+ CRLF
聽 聽 cXml += ' 聽 <FECompUltimoAutorizado xmlns="http://ar.gov.afip.dif.FEV1/">' + CRLF
聽 聽 cXml += ' 聽 聽 聽<Auth>' 聽 聽 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 <Token>' + c_Token + '</Token>' 聽 + CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 <Sign>' + c_Sign + '</Sign>' 聽 + CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 <Cuit>' + c_Cuit + '</Cuit>' 聽 + CRLF
聽 聽 cXml += ' 聽 聽 聽</Auth>' 聽 聽 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽<PtoVta>' + cPtoVta + '</PtoVta>' 聽 + CRLF
聽 聽 cXml += ' 聽 聽 聽<CbteTipo>' + cCbteTipo + '</CbteTipo>' 聽+ CRLF
聽 聽 cXml += ' 聽 </FECompUltimoAutorizado>' 聽 聽+ CRLF
聽 聽 cXml += '</soap:Body>' 聽 聽 聽+ CRLF
聽 聽 cXml += '</soap:Envelope>' 聽 聽 聽+ CRLF
聽 聽
聽 聽 * Esto NO hace falta, pero lo hago para controlar como se formo el XML
聽 聽 If( ( nHandle := fCreate( 'FECompUltimoAutorizado_Req.xml', 0 ) ) == -1 )
聽聽 聽聽 聽 MsgStop( 'NO se pudo crear FECompUltimoAutorizado_Req.xml' )
聽聽 聽聽 聽 Return( .f. )
聽 聽 Else
聽聽 聽聽 聽 fWrite( nHandle, cXml )
聽聽 聽聽 聽 fClose( nHandle )
聽 聽 End
聽 聽 * Llamo al WS
聽 聽 cRespuesta := LlamoAlWSFE( cXml, 'FECompUltimoAutorizado' )
聽 聽 MemoWrit( 'FECompUltimoAutorizado_Res.xml', cRespuesta )
聽 聽 MsgStop( 'FINALIZO la CONSULTA DEL ULTIMO;NUMERO DE FACTURA AUTORIZADO;EL PEDIDO SE GRABO COMO: FECompUltimoAutorizado_Req; LA RESPUESTA RECIBIDA SE GRABO COMO: FECompUltimoAutorizado_Res' )
聽 聽
聽 聽 * Muestro el contenido del XML RECIBIDO
聽 聽 aRespuesta := Opc_LeeRespuesta( cRespuesta, 'FECompUltimoAutorizado' )
聽 聽 MuestroRespuesta( aRespuesta )
聽 聽 * Actualizo el Numero del Ultimo Comprobante Autorizado
聽 聽 nIdx := AScan( aRespuesta, { |aAux| aAux[ 1 ] = 'CbteNro' } )
聽 聽 If( nIdx <> 0 )
聽 聽 聽聽 聽nUltCmpAut := val( aRespuesta[ nIdx, 2 ] )
聽 聽 End
聽 聽 Return( .t. )
//----------------------------------------------------------------------------//
*: Opc_FECAESolicitar Pido la CAE para una FACTURA 聽 聽 聽 :
*: Estado: OK (funcionando) 聽 聽 聽 聽 聽:
//----------------------------------------------------------------------------//
Function Opc_FECAESolicitar( c_Token, c_Sign, c_CUIT )
聽 聽 Local cXml 聽:= ''
聽 聽 Local nhandle
聽 聽 Local cRespuesta
聽 聽 Local aRespuesta
聽 聽 * Estas Variables tienen que Salir del Sistema de Gesti垄n.
聽 聽 * Aca las pongo como valores fijos para probar el WS.
聽 聽 Local cCantReg 聽 聽 聽:= Str( 0001 ) 聽 //
聽 聽 Local cPtoVta 聽 聽 聽 := Alltrim( Str( 0001 ) ) // Punto de Venta
聽 聽 Local cCbteTipo 聽 聽 := Alltrim( Str( 001 ) ) // 1=FACTURA
聽 聽 Local cConcepto 聽 聽 := Alltrim( Str( 01 ) ) 聽// 1=
聽 聽 Local cDocTipo 聽 聽 聽:= Alltrim( Str( 80 ) ) 聽// 80=CUIT
聽 聽 Local cDocNro 聽 聽 聽 := '30651704657' 聽 聽 聽 聽 聽 聽 聽 聽// CUIT del Comprador
聽 聽 Local cCbteDesde 聽 聽:= Alltrim( Str( 4794 + 1 ) ) // Nro de la 1er. 聽Factura a Autorizar
聽 聽 Local cCbteHasta 聽 聽:= Alltrim( Str( 4794 + 1 ) ) // Nro de la Ultima Factura a Autorizar
聽 聽 Local cCbteFch 聽 聽 聽:= DToS( date() ) 聽聽聽 聽 聽 聽 聽 聽 聽 // Fecha de la Factura
聽 聽 Local cImpTotal 聽 聽 := Alltrim( Str( 14.93 ) ) 聽 聽 // Importe Total de la Factura
聽 聽 Local cImpTotConc 聽 := Alltrim( Str( 0 ) ) 聽 聽 聽 // Neto NO Gravado
聽 聽 Local cImpNeto 聽 聽 聽:= Alltrim( Str( 12.34 ) ) 聽 聽 聽// Importe Neto (Sin Iva)
聽 聽 Local cImpOpEx 聽 聽 聽:= Alltrim( Str( 0 ) ) 聽 聽 聽 聽 聽// Importe Exento
聽 聽 Local cImpTrib 聽 聽 聽:= Alltrim( Str( 0 ) ) 聽 聽 聽 聽 聽// Suma de los importes del array de tributos
聽 聽 Local cImpIVA 聽 聽 聽 := Alltrim( Str( 2.59 ) ) 聽 聽 聽 聽 //
聽 聽 Local cFchServDesde := '' 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽// Cuando cConcepto = 2 o 3
聽 聽 Local cFchServHasta := '' 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽// Cuando cConcepto = 2 o 3
聽 聽 Local cFchVtoPago 聽 := '' 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽// Cuando cConcepto = 2 o 3
聽 聽 Local cMonId 聽 聽 聽 聽:= 'PES' 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 // C垄digo de Moneda (sale de consultar el WS Respectivo)
聽 聽 Local cMonCotiz 聽 聽 := Alltrim( Str( 1 ) ) 聽 聽 聽 聽 // Cotizaci垄n de la Moneda. Para cMonId='PES' es 1.
聽 聽 * Es un array que se repite tantas veces como tasas de iva haya en la factura
聽 聽 Local cId 聽 聽 聽:= Alltrim( Str( 5 ) ) 聽// 21% de IVA
聽 聽 Local cBaseImp := Alltrim( Str( 12.34 ) ) // Base Imponible
聽 聽 Local cImporte := Alltrim( Str( 2.59 ) ) // Importe de Iva
聽 聽
聽 聽 If( empty( cToken ) 聽.or. 聽empty( cSign ) )
聽聽 聽聽 聽 MsgStop( 'Antes de usar esta opci垄n;Pida un Nuevo TICKET DE ACCESO' )
聽聽 聽聽 聽 Return( .f. )
聽 聽 End
聽 聽 * ARMO EL ARCHIVO XML con el Pedido de CAE
聽 聽 cXml += '<?xml version="1.0" encoding="UTF-8"?>' 聽 + CRLF
聽 聽 cXml += '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' + CRLF
聽 聽 cXml += '<soap:Header/>' 聽 聽 聽+ CRLF
聽 聽 cXml += '<soap:Body>' 聽 聽 聽+ CRLF
聽 聽 cXml += ' 聽 <FECAESolicitar xmlns="http://ar.gov.afip.dif.FEV1/">' + CRLF
聽 聽 cXml += ' 聽 聽 聽<Auth>' 聽 聽 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 <Token>' + c_Token + '</Token>' 聽 + CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 <Sign>' + c_Sign + '</Sign>' 聽 + CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 <Cuit>' + c_Cuit + '</Cuit>' 聽 + CRLF
聽 聽 cXml += ' 聽 聽 聽</Auth>' 聽 聽 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽<FeCAEReq>' 聽 聽 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 <FeCabReq>' 聽 聽 + CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽<CantReg>' + cCantReg + '</CantReg>' 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽<PtoVta>' + cPtoVta + '</PtoVta>' 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽<CbteTipo>' + cCbteTipo + '</CbteTipo>' 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 </FeCabReq>' 聽 聽 + CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 <FeDetReq>' 聽 聽 + CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽<FECAEDetRequest>' 聽 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <Concepto>' + cConcepto + '</Concepto>' + CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <DocTipo>' + cDocTipo + '</DocTipo>' 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <DocNro>' + cDocNro + '</DocNro>' 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <CbteDesde>' + cCbteDesde + '</CbteDesde>' + CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <CbteHasta>' + cCbteHasta + '</CbteHasta>' + CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <CbteFch>' + cCbteFch + '</CbteFch>' 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <ImpTotal>' + cImpTotal + '</ImpTotal>' + CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <ImpTotConc>' + cImpTotConc + '</ImpTotConc>'+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <ImpNeto>' + cImpNeto + '</ImpNeto>' 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <ImpOpEx>' + cImpOpEx + '</ImpOpEx>' 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <ImpTrib>' + cImpTrib + '</ImpTrib>' 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <ImpIVA>' + cImpIVA + '</ImpIVA>' 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <FchServDesde>' + cFchServDesde + '</FchServDesde>' + CRLF // Cuando cConcepto = 2 o 3
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <FchServHasta>' + cFchServHasta + '</FchServHasta>' + CRLF // Cuando cConcepto = 2 o 3
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <FchVtoPago>' + cFchVtoPago + '</FchVtoPago>' + CRLF // Cuando cConcepto = 2 o 3
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <MonId>' + cMonId + '</MonId>' 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <MonCotiz>' + cMonCotiz + '</MonCotiz>' + CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 <Iva>' 聽 聽 + CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 聽 聽<AlicIva>' 聽 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 <Id>' + cId + '</Id>' 聽 + CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 聽 聽<BaseImp>' + cBaseImp + '</BaseImp>' + CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 <Importe>' + cImporte + '</Importe>' + CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 聽 聽</AlicIva>' 聽 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽 聽 </Iva>' 聽 聽 + CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 聽 聽</FECAEDetRequest>' 聽 聽+ CRLF
聽 聽 cXml += ' 聽 聽 聽 聽 </FeDetReq>' 聽 聽 + CRLF
聽 聽 cXml += ' 聽 聽 聽</FeCAEReq>' 聽 聽 聽+ CRLF
聽 聽 cXml += ' 聽 </FECAESolicitar>' 聽 聽 + CRLF
聽 聽 cXml += '</soap:Body>' 聽 聽 聽+ CRLF
聽 聽 cXml += '</soap:Envelope>' 聽 聽 聽+ CRLF
聽 聽 If( ( nHandle := fCreate( 'FECAESolicitar_Req.xml', 0 ) ) == -1 )
聽聽 聽聽 聽 MsgStop( 'NO se pudo crear FECAESolicitar_Req.xml' )
聽聽 聽聽 聽 Return( .f. )
聽 聽 Else
聽聽 聽聽 聽 fWrite( nHandle, cXml )
聽聽 聽聽 聽 fClose( nHandle )
聽 聽 End
聽 聽 * Llamo al WS
聽 聽 cRespuesta := LlamoAlWSFE( cXml, 'FECAESolicitar' )
聽 聽 MemoWrit( 'FECAESolicitar_Res.xml', cRespuesta )
聽 聽 MsgStop( 'FINALIZO EL PEDIDO DE CAE;EL PEDIDO SE GRABO COMO: FECAESolicitar_Req; LA RESPUESTA RECIBIDA SE GRABO COMO: FECAESolicitar_Res' )
聽 聽 * Muestro el contenido del XML RECIBIDO
聽 聽 aRespuesta := Opc_LeeRespuesta( cRespuesta, 'FECAESolicitar' )
聽 聽 MuestroRespuesta( aRespuesta )
聽 聽 Return( .t. )
//----------------------------------------------------------------------------//
*: Opc_LeeRespuesta Toma el Archivo XML devuelto por la AFIP y muestra 聽:
*: 聽 su contenido. 聽 聽 聽 聽 :
*: 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽:
*: Estado: FALTA MEJORARLA MUCHOOOOOO 聽 聽 聽 聽 :
//----------------------------------------------------------------------------//
Function Opc_LeeRespuesta( c_XmlRecibido, c_ServicioLlamado )
聽 聽 Local oXMLDoc
聽 聽 Local oXMLNode
聽 聽 Local cXml 聽:= c_XmlRecibido
聽 聽 Local aRespuesta := {}
聽 聽 Local cText 聽:= ''
聽 聽 Local cName 聽:= ''
聽 聽 Local cData 聽:= ''
聽 聽 Local aText 聽:= {}
聽 聽 Local nIdx 聽:= 0
聽 聽 * Proceso el XML (TXMLDocument sale de la contrib xHb)
聽 聽 oXMLDoc 聽:= TXMLDocument() : New()
聽 聽 cText 聽 聽:= oXMLDoc : Read( cXML )
聽 聽 oXMLNode := oXMLDoc : FindFirst()
聽 聽 While( Valtype( oXMLNode ) == 'O' )
聽聽 聽聽 聽 cName := oXMLNode:cName // Nombre del Nodo
聽聽 聽聽 聽 cData := oXMLNode:cData // Datos dentro del Nodo
聽聽 聽聽 聽 If( valtype( cData ) = 'N' )
聽 聽 聽 聽 聽 聽 cData := Str( cData )
聽聽 聽聽 聽 ElseIf( valtype( cData ) = 'D' )
聽 聽 聽 聽 聽 聽 cData := DTOC( cData )
聽聽 聽聽 聽 ElseIf( valtype( cData ) = 'C' )
聽 聽 聽 聽 聽 聽 cData := Alltrim( cData )
聽 聽 聽 聽 聽 聽 If( subs( cData, 5, 1 ) = '-' .And. Subs( cData, 8, 1 ) = '-' )
聽 聽聽聽 聽 聽 聽 If( len( cData ) = 10 )
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 cData := SubStr( cData, 9, 2 ) + '/' + SubStr( cData, 6, 2 ) + '/' + SubStr( cData, 1, 4 )
聽 聽聽聽 聽 聽 聽 Else
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 cData := SubStr( cData, 9, 2 ) + '/' + SubStr( cData, 6, 2 ) + '/' + SubStr( cData, 1, 4 ) + ' - ' + SubStr( cData, 11 )
聽 聽聽聽 聽 聽 聽 End
聽 聽 聽 聽 聽 聽 End
聽聽 聽聽 聽 Else
聽 聽 聽 聽 聽 聽 cData := ''
聽聽 聽聽 聽 End
聽聽 聽聽 聽 If( valtype( cName ) = 'C' )
聽 聽 聽 聽 聽 聽 Aadd( aText , { Alltrim( cName ), Alltrim( cData ) } )
聽聽 聽聽 聽 End
聽聽 聽聽 聽 oXmlNode := oXMLDoc : FindNext()
聽 聽 Enddo
聽 聽 * Proceso los Valores Obtenidos, Esta Parte Da Lastima, Pero Estaba Apurado Asi Que No Tuve Tiempo De Mejorarla.
聽 聽 For nIdx := 1 to Len( aText )
聽聽 聽聽 聽 If( c_ServicioLlamado = 'FEDummy' )
聽 聽 聽 聽 聽 聽 if( aText[ nIdx, 1 ] == 'AppServer' .or. 聽;
聽 聽 聽聽 聽聽 聽 聽 聽 聽aText[ nIdx, 1 ] == 'DbServer' .or. 聽;
聽 聽 聽聽 聽聽 聽 聽 聽 聽aText[ nIdx, 1 ] == 'AuthServer' .or. 聽;
聽 聽 聽聽 聽聽 聽 聽 聽 聽aText[ nIdx, 1 ] == 'Code' 聽.or. 聽;
聽聽 聽聽 聽 聽 聽 聽 聽 聽aText[ nIdx, 1 ] == 'Msg' )
聽 聽聽聽 聽 聽 聽 Aadd( aRespuesta, aText[ nIdx ] )
聽 聽 聽 聽 聽 聽 End
聽聽 聽聽 聽 ElseIf( c_ServicioLlamado = 'FECompUltimoAutorizado' )
聽 聽 聽 聽 聽 聽 If( aText[ nIdx, 1 ] == 'CbteNro' .or. 聽;
聽 聽 聽聽 聽聽 聽 聽 聽 聽aText[ nIdx, 1 ] == 'Code' 聽.or. 聽;
聽 聽 聽聽 聽聽 聽 聽 聽 聽aText[ nIdx, 1 ] == 'Msg' )
聽 聽聽聽 聽 聽 聽 Aadd( aRespuesta, aText[ nIdx ] )
聽 聽 聽 聽 聽 聽 End
聽聽 聽聽 聽 ElseIf( c_ServicioLlamado = 'TA' )
聽 聽 聽 聽 聽 聽 If( aText[ nIdx, 1 ] == 'generationTime' .or. 聽;
聽 聽 聽聽 聽聽 聽 聽 聽 聽aText[ nIdx, 1 ] == 'expirationTime' .or. 聽;
聽 聽 聽聽 聽聽 聽 聽 聽 聽aText[ nIdx, 1 ] == 'token' 聽.or. 聽;
聽 聽 聽聽 聽聽 聽 聽 聽 聽aText[ nIdx, 1 ] == 'sign' )
聽 聽聽聽 聽 聽 聽 Aadd( aRespuesta, aText[ nIdx ] )
聽 聽 聽 聽 聽 聽 End
聽聽 聽聽 聽 ElseIf( c_ServicioLlamado = 'FECAESolicitar' )
聽 聽 聽 聽 聽 聽 If( aText[ nIdx, 1 ] == 'Resultado' .or. 聽;
聽 聽 聽聽 聽聽 聽 聽 聽 聽aText[ nIdx, 1 ] == 'Reproceso' .or. 聽;
聽 聽 聽聽 聽聽 聽 聽 聽 聽aText[ nIdx, 1 ] == 'CAE' 聽.or. 聽;
聽 聽 聽聽 聽聽 聽 聽 聽 聽aText[ nIdx, 1 ] == 'CAEFchVto' .or. 聽;
聽 聽 聽聽 聽聽 聽 聽 聽 聽aText[ nIdx, 1 ] == 'Code' 聽.or. 聽;
聽 聽 聽聽 聽聽 聽 聽 聽 聽aText[ nIdx, 1 ] == 'Msg' )
聽 聽聽聽 聽 聽 聽 Aadd( aRespuesta, aText[ nIdx ] )
聽 聽 聽 聽 聽 聽 End
聽 聽 聽 聽 End
聽 聽 Next
聽 聽 Return( aRespuesta )
//----------------------------------------------------------------------------//
*: TimeFMT Devuelve la fecha y hora recibida en forma de texto
//----------------------------------------------------------------------------//
Static Function TimeFMT( dt, n_Horas )
聽 聽 Local c 聽 聽 聽 聽 聽:= ''
聽 聽 Local cFechaHora := ''
聽 聽 dt := dt + ( n_Horas / 24 )
聽 聽 c := hb_TToS( dt )
聽 聽 cFechaHora := SubStr( c, 01, 4 ) + '-' + SubStr( c, 05, 2 ) + '-' + SubStr( c, 07, 2 ) + 聽;
聽 聽 聽 聽 聽 聽 聽 聽 聽'T' + 聽;
聽 聽 聽聽 聽聽 聽 聽 聽 聽 聽 聽 SubStr( c, 09, 2 ) + ':' + SubStr( c, 11, 2 ) + ':' + SubStr( c, 13, 2 ) 聽// + 聽'-' + '03:00'
聽 聽 Return( cFechaHora )
//----------------------------------------------------------------------------//
*: MuestroRespuesta 聽 聽 聽 聽 聽 :
*: Muestra informaci垄n recibida del WS correspondiente 聽 聽 聽 :
*: Estado: OK (funcionando) 聽 聽 聽 聽 聽:
//----------------------------------------------------------------------------//
Function MuestroRespuesta( a_Respuesta )
聽 聽 Local nIdx := 0
聽 聽 Cls
聽 聽 If( !Empty( a_Respuesta ) )
聽聽 聽聽 聽 ? 'COMIENZA LA VISUALIZACION DE LA RESPUESTA'
聽 聽 聽 聽 ?
聽聽 聽聽 聽 For nIdx := 1 to Len( a_Respuesta )
聽 聽 聽 聽 聽 聽 ? a_Respuesta[ nIdx, 01 ], a_Respuesta[ nIdx, 02 ]
聽聽 聽聽 聽 Next
聽 聽 聽 聽 ?
聽聽 聽聽 聽 ? 'FINALIZO LA VISUALIZACION DE LA RESPUESTA'
聽聽 聽聽 聽 ? 'PRESIONE CUALQUIER TECLA PARA CONTINUAR'
聽 聽 Else
聽 聽 聽 聽 ? '****************************************************'
聽聽 聽聽 聽 ? ' HUBO ALGUN TIPO DE ERROR, NO HAY NADA PARA MOSTRAR '
聽聽 聽聽 聽 ? '****************************************************'
聽 聽 End
聽 聽 //Inkey( 0, 128 ) // 128 para que si muevo el mouse no me saque del inkey
聽 聽 Return( .t. )Saludos