[https://tibisay.cenditel.gob.ve/murachi/wiki Inicio] > [https://tibisay.cenditel.gob.ve/murachi/wiki/comoUsarElApi Cómo usar el API] [[BR]] = ¿Cómo consumir el servicio web Murachí (API) desde diferentes tipos de lenguajes de programación? = El objetivo es realizar ejercicios prácticos de cómo usar el API del sistema Murachí para consumir los servicios de firma electrónica y verificación de firma, para así tener los conocimientos necesarios a la hora de crear su propio portal web (Fron-end) que consumirá del API Murachí (Back-End). [[br]] == Detalles de seguridad == [[Image(security.jpg,120px)]] Todos los recursos del API requieren autenticación básica HTTP (''Basic Authentication''). Por esta razón, en todas las solicitudes debe estar presente el encabezado ''Authorization'' lleno con los valores {{{app_id}}} y {{{app_key}}} que se generará para su consumo. Por ejemplo si las credenciales de su aplicación son las siguientes: * {{{app_id: murachi.test}}} * {{{app_key: 12345678}}} necesitará codificarlas con el algoritmo Base64: {{{Base64(app_id:app_key)}}}. El resultado debería ser como el siguiente encabezado HTTP: ''Authorization: Basic aG9sYTptdW5kbw==''. Puede convertir credenciales a Base64 con la siguiente línea de comando: {{{ echo -n APP_ID:APP_KEY | base64 }}} reemplazando APP_ID y APP_KEY con sus respectivas credenciales. '''NOTA:''' inicialmente para propósitos de prueba se estarán utilizando las credenciales * {{{app_id: admin}}} * {{{app_key: admin}}} Esto da como resultado: {{{YWRtaW46YWRtaW4=}}}. '''Entonces mientras se habilita el proceso de generación de API_KEY para clientes del API se utilizará lo siguiente:''' {{{ Authorization: Basic YWRtaW46YWRtaW4= }}} ''' al momento de consumir un recurso de Murachi. ''' [[br]] == Documentación del API == [[Image(documentacion.png,link=https://murachi.cenditel.gob.ve/apidoc/,120px)]] Para consumir o hacer llamadas a los recursos del servicio Murachi puede revisar el siguiente enlace: [https://murachi.cenditel.gob.ve/apidoc/]. Allí encontrará todos los recursos disponibles hasta el momento con sus parámetros, respuestas, errores y ejemplos de uso. [[br]] == Prueba básica con Ruby == [[Image(ruby.jpg,120px)]] En el siguiente código se cargan dos (02) archivos de texto y se agregan a un contenedor BDOC a través del recurso {{{https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/bdocs/cargas}}}. Luego se listan los archivos que tiene el contenedor con el recurso {{{https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/bdocs/archivos/lista/%s}}}. Seguidamente se prepara la firma del contenedor BDOC a través del recurso {{{https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/bdocs/firmas/pre}}} que retorna el hash que se debe firmar en el cliente con la clave privada protegida en el dispositivo criptográfico. Luego se completa la firma del contenedor BDOC a través del recurso {{{https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/bdocs/firmas/post}}}. Finalmente se verifica la firma del contenedor BDOC a través del recurso {{{https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/56143d89-1029-4ae4-b023-ca4367a8f34d}}} Para mayor información y documentación de los recursos disponibles siga el enlace: [https://murachi.cenditel.gob.ve/apidoc/]. * Crear el archivo {{{multipart.rb}}} con el siguiente contenido: {{{ require 'net/https' require 'net/http/post/multipart' require "openssl" require "json" # Cargas archivo y crear contenedor BDOC #uri = URI.parse('https://192.168.12.125:8443/Murachi/0.1/archivos/bdocs/cargas') @uri = URI.parse('https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/bdocs/cargas') @req = Net::HTTP::Post::Multipart.new @uri.path, "f1" => UploadIO.new(StringIO.new("cadena de prueba"), "text/plain", "file.txt"), "f2" => UploadIO.new(StringIO.new("SEGUNDA cadena de prueba"), "text/plain", "file2.txt") # Agregar cabezera para autenticación con murachí @req['Authorization'] = 'Basic YWRtaW46YWRtaW4=' @http = Net::HTTP.new(@uri.host, @uri.port) @http.use_ssl = true @http.verify_mode = OpenSSL::SSL::VERIFY_NONE # RESPUESTA --->> @res = @http.request(@req) # Body @json_resp = JSON.parse(@res.body) puts @json_resp['containerId'] # Listar archivos del contenedor registrado en la llamada anterior @container_id = @json_resp['containerId'] @uri = URI.parse 'https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/bdocs/archivos/lista/%s' % @container_id @req = Net::HTTP::Get.new @uri.path @req['Authorization'] = 'Basic YWRtaW46YWRtaW4=' @res = @http.request(@req) @json_resp = JSON.parse(@res.body) @json_resp['dataFiles'].each do |file| puts file['filename'] end # Prepara firma de un contenedor @certificate = "30820512308202FAA003020102020119300D06092A864886F70D01010B05003081AA310B3009060355040613025645310F300D060355040813064D6572696461310F300D060355040713064D65726964613111300F060355040A130843454E444954454C310E300C060355040B13054749445349312E302C06035504030C254175746F7269646164206465204365727469666963616369C3B36E2064656C2047494453493126302406092A864886F70D0109011617616367696473694063656E646974656C2E676F622E7665301E170D3135303930383135333930305A170D3136303930383135333930305A308198310B3009060355040613025645310F300D060355040813064D6572696461310F300D060355040713064D65726964613111300F060355040A130843454E444954454C31133011060355040B130A4465736172726F6C6C6F311630140603550403130D4A6F726765205265646F6E646F3127302506092A864886F70D01090116186A7265646F6E646F4063656E646974656C2E676F622E766530820122300D06092A864886F70D01010105000382010F003082010A0282010100E27AC29BDC3196EFD1F388B6B415F965E7407616448A2A3AF40C7D3E2BFCEA7531A922578B444ACA4386A1744DDCD9507221CCCE9D3A9B81D46FFE274BA378D8413DED29CF596C5F5D7967C9D2E8F1EC1ACDD90582FD8DE055401D9906678DDB4A2F9E4E0FF8041740EAB6A4DFEF308AC1D05824FE4C5CCAA9435F8CAA3C73F937E1BA6F3075CCD2B5D8069BD937B8D9FFD34CB3F8E6B4CFA13BE62110DD677FC4653043ECE4D4E4D9373E01165E6BD33D2B8D1A477AA18E8F1CF68C6476BB30B187BAF2DDC0B8C06DF8292E4C4D57933A44E0B5AA17CC09FE85D4EB9A3F8082F603326FCA407C51691886ED47C15637AE75339F23E8F549F7DCB54CBC6555390203010001A3533051300C0603551D130101FF04023000300E0603551D0F0101FF0404030204F0301106096086480186F84201010404030205A0301E06096086480186F842010D0411160F786361206365727469666963617465300D06092A864886F70D01010B05000382020100556A0C471B30503343A375F54C0DCD345B3BB895A059E734315375B919AEB404C22E897A50D4B983B9480B4BBB48861C8BF27634E185460C95DE010D0DBB0B3091C439AB99ED862134FAD0610F5D7304F0365781FD35FD6340ACBD8EB05866CB44DB02590A06EAAF3978B6EA224F6B226B528DE841273146AFA873A56EE82B149817545074F40B97A26093A76DE174EEBC12285023FAA57A3E24ACC7D3BB0360FFF6D71AB3E3F30EBC07A14F73B974F4623421F762F155E7487F1C44E89F477BAB4A9843FC07DB5AF90943C298DFF5E9B3FDF3358AD145C5138F312170D767F0FEFD2DE7B3BDCD2F54E999A9E10E7B3C7AAF8AACDF65DE9D6FCDBC0E190048623AA494BBB6BA3A0FC0D2E1279D61D36D3B107C48236FA771CD6ED204C97D7AD6369E442DAF8A6E78D7104D4D1C19B0040039CCD20B3A0049236F726AC145AFD37FD54EA0FA44C1CD3131B858DE0D9A904B833DB33F66D75AA7396215561BEB9A0830B4282A08A57944C516F9406A01906D26E6A542861C057ADB34D66BDA2E92A5B62B30DAAD9F27F35348FD3481F18023C2687F8A288BB10B1FBBF5351140DA3BF67AFDFDE805618A355A3BE162C3F93C3F87370B815583EF31CBC68BF1F9CF1B04D6DAA685FD46FF4C5D507BF2C370B9120F07A33F2F9FABA4102A004D8F1CD6136FD63F15E3C26AC73B9ED8BDA930B21DD85F4CF9F778C12DA4B0E459B5BA" @parameters = {"fileId" => @container_id, "certificate" => @certificate, "city" => "Rubio", "state" => "Tachira", "postalCode" => "1234", "country" => "Venezuela", "role" => "Militar", "addSignature" => "false"} @headers = { "Content-Type" => 'application/json', "Authorization" => 'Basic YWRtaW46YWRtaW4='} #@uri = URI.parse("https://192.168.12.125:8443/Murachi/0.1/archivos/bdocs/firmas/pre") @uri = URI.parse("https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/bdocs/firmas/pre") @http = Net::HTTP.new(@uri.host, @uri.port) @http.use_ssl = true @http.verify_mode = OpenSSL::SSL::VERIFY_NONE @res = @http.post(@uri.path,@parameters.to_json,@headers) @hash = JSON.parse(@res.body)["hash"] puts @hash # Completar firma de contenedor @parameters = {"containerId" => @container_id, "signature" => @hash} @headers = { "Content-Type" => 'application/json', "Authorization" => 'Basic YWRtaW46YWRtaW4='} #@uri = URI.parse("https://192.168.12.125:8443/Murachi/0.1/archivos/bdocs/firmas/pre") @uri = URI.parse("https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/bdocs/firmas/post") @http = Net::HTTP.new(@uri.host, @uri.port) @http.use_ssl = true @http.verify_mode = OpenSSL::SSL::VERIFY_NONE @res = @http.post(@uri.path,@parameters.to_json,@headers) puts @res.body # verificacion # Listar archivos del contenedor registrado en la llamada anterior @container_id = '56143d89-1029-4ae4-b023-ca4367a8f34d' @uri = URI.parse 'https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/%s' % @container_id @req = Net::HTTP::Get.new @uri.path @req['Authorization'] = 'Basic YWRtaW46YWRtaW4=' @res = @http.request(@req) @json_resp = @res.body puts @json_resp }}} * Ejecutar: {{{ ruby multipart.rb }}} [[br]] == Prueba básica con Python == [[Image(python.png, 220px)]] A continuación se muestra un código muy básico para ilustrar cómo se pueden consumir recursos de Murachí desde el lenguaje python. Para correr el script python {{{pruebaMurachi.py}}} se requiere instalar el framework [http://docs.python-requests.org/en/latest/ requests], [https://pypi.python.org/pypi/M2Crypto M2Crypto] y el framework web [http://www.tornadoweb.org/en/stable/ tornado]. {{{ #!/usr/bin/env python # -*- coding: utf-8 -*- import os, uuid from M2Crypto import X509 import tornado.httpserver import tornado.ioloop import tornado.options import tornado.web import requests from requests.auth import HTTPBasicAuth from tornado.options import define, options define("port", default=8888, help="run on the given port", type=int) __UPLOADS__ = "/tmp/" # mensaje hola mundo class IndexHandler(tornado.web.RequestHandler): def get(self): greeting = self.get_argument('greeting', 'Hello') self.write(greeting + ', friendly user!\n') # para obtener la version del servicio web class VersionHandler(tornado.web.RequestHandler): def get(self): # verify=False para no verificar el certificado del servidor web # auth=() para la autenticacion basica de HTTP r = requests.get('https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/version', verify=False, auth=('admin', 'admin')) #r = requests.get('https://192.168.12.125:8443/Murachi/0.1/archivos/version', verify=False, auth=('admin', 'admin')) self.write(r.text) #r.json() #self.write(r.raise_for_status()) # para subir un archivo class UploadHandler(tornado.web.RequestHandler): def get(self): #files = {'file': open('/tmp/reports.txt', 'rb')} # subir un pdf files = {'file': open('/home/cenditel/desarrollo/murachi/convenioSUSCERTE-CENDITEL.pdf', 'rb')} r = requests.post('https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/cargar', verify=False, auth=('admin', 'admin'), files=files) #r = requests.post('https://192.168.12.125:8443/Murachi/0.1/archivos/cargar', verify=False, auth=('admin', 'admin'), files=files) #self.write(r.text) r.json() fileId = r.json()['fileId'] self.write(fileId) self.write('\n') #verificar si el documento esta firmado #r2 = requests.get('https://192.168.12.125:8443/Murachi/0.1/archivos/'+fileId, verify=False, auth=('admin', 'admin'), files=files) r2 = requests.get('https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/'+fileId, verify=False, auth=('admin', 'admin'), files=files) self.write(r2.text) # para obtener estadisticas basicas class StatisticsHandler(tornado.web.RequestHandler): def get(self): r = requests.get('https://murachi.cenditel.gob.ve/Murachi/0.1/archivos/estadisticas', verify=False, auth=('admin', 'admin')) self.write(r.text) # manejador principal class MainHandler(tornado.web.RequestHandler): def get(self): self.write("""
archivo:
""") def write_error(self, status_code, **kwargs): self.write("Gosh darnit, user! You caused a %d error." % status_code) class LoadHandler(tornado.web.RequestHandler): def post(self): #print self.request.arguments #self.write(self.request.arguments) #self.write("hola") #archivo = self.get_argument("file",'') fileinfo = self.request.files['fileToUpload'][0] fname = fileinfo['filename'] self.write(fname+'\n') extn = os.path.splitext(fname)[1] cname = str(uuid.uuid4()) + extn fh = open(__UPLOADS__ +cname, 'w') fh.write(fileinfo['body']) self.write('archivo subido: '+cname+'\n') #self.finish(cname + " is uploaded! Check %s folder" %__UPLOADS__) mypage = u"""Hola mundo""" self.write(mypage) if __name__ == "__main__": tornado.options.parse_command_line() #app = tornado.web.Application(handlers=[(r"/", IndexHandler)]) app = tornado.web.Application(handlers=[(r"/", MainHandler), (r"/index", IndexHandler), (r"/version", VersionHandler), (r"/upload", UploadHandler), (r"/estadisticas", StatisticsHandler), (r"/loadfile", LoadHandler) # (r"/loadCertificate", LoadCertificateHandler) ]) http_server = tornado.httpserver.HTTPServer(app, ssl_options={"certfile": "server.crt", "keyfile": "server.key"}) http_server.listen(options.port) tornado.ioloop.IOLoop.instance().start() }}} Para ejecutar el script python: {{{ # python pruebaMurachi.py }}} [[br]] Luego en un navegador web se pueden probar algunos recursos: * Para obtener la versión del servicio: [[Image(pruebaMurachiVersion.png,500px)]] [[br]] * Para cargar un archivo al servicio y verificar firmas: [[Image(pruebaMurachiCarga.png,800px)]] [[br]] * Para obtener estadísticas básicas de firmas y verifcaciones: [[Image(pruebaMurachiEstadisticas.png,800px)]]