Ver Mensaje Individual
  #12  
Antiguo 16-01-2020
xebas123 xebas123 is offline
Registrado
 
Registrado: dic 2019
Posts: 4
Reputación: 0
xebas123 Va por buen camino
Pasos para integrar MercadoPago y Mercadolibre con Delphi XE1, XE2 y espero que XE3

Para integrar mi aplicación Delphi XE/XE2 con MercadoLibre/MercadoPago yo seguí estos pasos.
Parece que aún no soy digno de postear links, armadlos vosotros.

Ingredientes:
-Indy versión Indy10_5461 o superior (buscar IndyProject Indy10Installation)
-OpenSSL versión (buscar indy fulgan barra SSL)
-ISuperObject tuneado (github |xebas123|superobject)
-JsonToDelphiClass 0.65 (PKGeorgiev|Delphi-JsonToDelphiClass|releases)

Configuraciones:
-ISuperObject:
Tuve que tocar ISuperObject para que me funque como yo quería.
Por defecto, al convertir un TObject a json lista las todos los "fields" que no es lo mismo que properties, sino que son todas las variables de la clase.
Esto me sirve, lo cambié para que trabaje solo sobre las Properties.
En teoría XSuperObject (otro proyecto de sourceforge) funcionaría bien, pero sólo es para XE2 en adelante y yo uso principalmente XE1.

-Uso de JsonToDelphiClass:
Ajuste del Json:
Los campos que pueden venir como "null" tienen que ser string en la clase que vayamos a generar y en todo caso se agregan funciones para obtener lo que se necesite necesitamos (ej: datetimes, boolean o números).
Usar Json Simples, si hay un array, que tenga un solo elemento (así no repite clases delphi)
No puede haber null ni arrays vacíos en el json de ejemplo. Sacarlos, o convertirlos en array de strings o info dummy.

Usando la aplicación:
1- Pegar a la derecha el json válido!
2- Presionar Visualize para armar el arbol a la izquierda.
3- El arbol permite renombrar las clases (al menos la Root conviene renombrarla).
También permite renombrar los tipos de dato (pero todo termina con Class) yo prefiero hacer busca/reemplaza en el .pas final.
Hay algunos "extended" que en realidad son long o longword. de nuevo, ojo que si son opcionales puede que haya que ponerlos como string.
4- [opcional] Ingresar el nombre de la unit
5- Presionar PreviewUnit
6- MUY IMPORTANTE: el botón Save no hace nada!!! hay que copiar el texto y guardarlo en un .pas
7- Abrir la Unit y ajustarla para que use ISuperObject modificado por mi. (ver sección de ISuperObject)
7a- Cambiar referencia a Rest.Json por SuperObject
7b- Los métodos "ToJsonString" se cambian por exactamente esto:
Result := Self.ToJson().AsJSon(false, false);
7c- Los métodos "FromJsonString" se cambian por exactamente esto:
Result := Self.FromJson(AJsonString);

8- Las fechas vienen como string con formato 2017-11-04T12:51:51-04:00, para obtener una fecha delphi hay que:
8a- Agregar funciones tipo GetFechaCreacion en cada clase y dentro poner:
if not ISO8601DateToDelphiDateTime( created_at , Result) then Result := 0;
8b- sino, hay que usar esa función en cada lugar que se necesite.
8c- Algo similar para las funciones Setters.

9- Con el .pas acomodar nombres de clases, sacar clases repetidas.

-Indy:
Se puede instalar o se puede dejar en un directorio a mano.
Para XE y XE2 no es posible instalarlo porque hay dependencias en el core de Delphi, conviene descomprimirlo en algún directorio y configurar el proyecto para que Search Path referencie al directorio donde hayamos dejado los .dcu (luego de haber compilado todo el paquete de Indy).

Inicializando componentes:
Código Delphi [-]
    FIdHTTP1 := TIdHTTP.Create(nil);
    FIdSSLIOHandlerSocketOpenSSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
    FIdCompressorZLib1 := TIdCompressorZLib.Create(nil);

    FIdHTTP1.AllowCookies := True;
    FIdHTTP1.Request.ContentLength := -1;
    FIdHTTP1.Request.ContentRangeEnd := -1;
    FIdHTTP1.Request.ContentRangeStart := -1;
    FIdHTTP1.Request.ContentRangeInstanceLength := -1;
    FIdHTTP1.Request.Accept := 'application/json';
    FIdHTTP1.Request.ContentType := 'application/json';
    FIdHTTP1.Request.AcceptEncoding := 'gzip';
    FIdHTTP1.Request.BasicAuthentication := True;
    FIdHTTP1.Request.UserAgent := 'Mozilla/3.0 (compatible; Indy Library)';
    FIdHTTP1.Request.Ranges.Units := 'bytes';
    FIdHTTP1.HandleRedirects := False;    //OJO Si es true algunos PUT pueden fallar y va a loopear 15 veces para nada
    FIdHTTP1.HTTPOptions := [hoForceEncodeParams];

    FIdSSLIOHandlerSocketOpenSSL1.Port := 0;
    FIdSSLIOHandlerSocketOpenSSL1.DefaultPort := 0;
    FIdSSLIOHandlerSocketOpenSSL1.SSLOptions.Mode := sslmUnassigned;
    FIdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyMode := [];
    FIdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyDepth := 0;
    FIdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method  := sslvTLSv1_2;
    FIdSSLIOHandlerSocketOpenSSL1.SSLOptions.Mode := sslmUnassigned;
    FIdSSLIOHandlerSocketOpenSSL1.OnStatus := .(...);  //muy util para ver hasta dónde llega con SSL cuando hay errores.

    Result.FIdHTTP1.IOHandler := Result.FIdSSLIOHandlerSocketOpenSSL1;
    {$IFNDEF VER230}
    Result.FIdHTTP1.Compressor := Result.FIdCompressorZLib1; //En Delphi XE 2 (VER230) falla el descompresor.
    {$ENDIF}
//    Result.FIdHTTP1.OnWorkEnd := Result.IdHttp1WorkEnd; //Esto sirve para obtener el mensaje real que llegó antes del parseo de códigos de error de Indy

function xxxx.GETSample(const PaymentId: cardinal): string;
var
  reqURL, rsp: string;
  rspStream: TMemoryStream;
begin
    reqURL := 'aca va la url segura de mercadopago /v1/payments/' + IntToStr(PaymentId) + '?access_token=' + ACCESS_TOKEN
    if FIdHTTP1.Compressor <> nil then begin
        rsp := FIdHTTP1.Get(reqURL);
    end else begin
        rspStream := TMemoryStream.Create; //stream comprimido de respuesta
        try
            FIdHTTP1.Get(reqURL, rspStream);
            rsp := UngzipStream(rspStream);
        finally
            rspStream.Free;
        end;
    end;
    SetLastResult(rsp);

    Result := rsp;
end;

Este String de respuesta se convierte en clase de Delphi usando:
Código Delphi [-]
TMiClaseDeMercadoPagoParaPayment.FromJsonString(rsp);

Código Delphi [-]
function xxxx.UngzipStream(srcStream: TStream): string;
var
  strStream: TStringStream;
  deco : TZDecompressionStream;
begin
    srcStream.Position := 0;
    strStream := TStringStream.Create;
    deco := nil;
    try
        //Resulta que no siempre viene comprimido, verificamos
        if Pos('Content-Encoding: gzip', FIdHTTP1.Response.RawHeaders.Text) < 1 then begin
            strStream.LoadFromStream(srcStream);
        end else begin
            deco := TZDecompressionStream.Create(srcStream, 31); //stream para descomprimir, el 31 es para que se de cuenta que es gzip
            strStream.LoadFromStream(deco); //a medida que va copiando va descomprimiendo, very cheto
        end;
        Result := strStream.DataString;
    finally
        strStream.Free;
        if deco <> nil then deco.Free;
    end;
end;

Recomendación:
atrapar globalmenet las excepciones y loguear especialmente las EIdHTTPProtocolException
Código Delphi [-]
    if e is EIdHTTPProtocolException then
       Logueo( EIdHTTPProtocolException(e).ErrorMessage );

Otros:
También tengo integrado MercadoLibre.
Si necesitan algunos tips para obtener el bendito token, me avisan y posteo.
También tengo info de qué funciona y qué no para buscar pagos.
No integré mucho más que buscar buscar pagos, pero dado que la comunicación (ida y vuelta de jsons) funciona, no debería ser problemático.


Saludos

Última edición por Casimiro Notevi fecha: 16-01-2020 a las 17:57:38.
Responder Con Cita