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; 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 := .(...);
Result.FIdHTTP1.IOHandler := Result.FIdSSLIOHandlerSocketOpenSSL1;
{$IFNDEF VER230}
Result.FIdHTTP1.Compressor := Result.FIdCompressorZLib1; {$ENDIF}
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; 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
if Pos('Content-Encoding: gzip', FIdHTTP1.Response.RawHeaders.Text) < 1 then begin
strStream.LoadFromStream(srcStream);
end else begin
deco := TZDecompressionStream.Create(srcStream, 31); strStream.LoadFromStream(deco); 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