Buenas tardes, dejo aqu铆 la versi贸n definitiva en forma de clase.
#include "Fivewin.ch"
class TApiBBVA
聽 聽 data oWnd 聽 聽聽 聽 聽 聽&& Ventana Padre
聽 聽 data cNomObjOLE 聽 聽 && Nombre del objeto OLE para hacer GET y POST
聽 聽 data cAppID聽 聽 聽 聽 聽&& Informaci垄n APP creada en BBVAMarket
聽 聽 data cSecretID聽 聽 聽 && Informaci垄n C垄digo secreto de BBVAMarket
聽 聽 data cURL聽 聽聽 聽 聽 聽 && URL de BBVA
聽 聽 data cRedirect_Uri聽 && Url a la que se redige la respuesta de ConnectBBVA
聽 聽 data cToken聽聽 聽 聽聽 聽&& Access_Token devuelto por oAuth
聽 聽 data cCode聽 聽 聽 聽 聽聽&& Authorization_Code necesario para solicitar access_token
聽 聽 data cFicTok聽 聽 聽 聽 && Nombre de fichero para almacenar Token
聽 聽 data cFicJSon聽 聽聽 聽 && Nombre de fichero para almacenar respuesta JSon
聽 聽 data oTimer聽聽 聽 聽聽 聽&& Timer para comprobar cada 3 segundos que ha respondido ConnectBBVA
聽 聽 method New (oWnd)
聽 聽 method EXTRACTO ()聽 聽 聽 聽 聽 聽 聽聽 聽聽 && Devuelve JSon con los extractos de las cuentas del cliente BBVA
聽 聽 method PEDIR_CODE ()聽 聽 聽 聽 聽 聽 聽 聽 && Si el usuario a rellenado sus datos correctos en ConnecBBVA, rellena ::cCode
聽 聽 method IniTimer ( oDlg, oActiveX )聽 && Iniciar ::oTimer
聽 聽 method TENGO_CODE ( oActiveX )聽 聽 聽 && Comprueba que la cUrl contiene en ::cCode, lo rellena y devuelve true
聽 聽 method PEDIR_TOKEN ()聽 聽聽 聽 聽 聽 聽 聽 && Petici垄n de access_Token usando ::cCode y si hay respuesta devuelve true
聽 聽 method PEDIR_EXTRACTO ()聽 聽 聽 聽 聽 聽 && Petici垄n de Extracto usando ::cToken, devuelve Json son los datos
endclass
method New (oWnd)聽 聽聽 聽 聽 聽 聽 聽 聽 聽 class TApiBBVA
聽 聽 ::oWnd聽 聽 聽 聽:= oWnd
聽 聽 ::cNomObjOLE := "Microsoft.XMLHTTP" 聽 聽 && "WINHTTP.WINHTTPREQUEST.5.1"
聽 聽 ::cAppID 聽 聽 := '' 聽 聽 聽 聽 聽 && Hay que darse de alta en BBVAMarket
聽 聽 ::cSecretID 聽:= "" 聽 聽 聽 聽
聽 聽 ::cURL聽 聽 聽 聽:= "https://connect.bbva.com/token"
聽 聽 ::cRedirect_Uri := "http://localhost"
聽 聽 ::cToken 聽 聽 := ""
聽 聽 ::cCode 聽 聽 聽:= ""
聽 聽 ::cFicTok 聽 聽:= '.\TOK_BBV.TXT'
聽 聽 ::cFicJSon 聽 := '.\EXT_BBV.JSON'
return Self
method EXTRACTO ()聽 聽 聽 聽 聽 聽 聽 聽 聽 class TApiBBVA
聽 聽 if ::PEDIR_CODE ()
聽 聽 聽 聽 if ::PEDIR_TOKEN ()
聽 聽 聽 聽 聽 聽 ::PEDIR_EXTRACTO ()
聽 聽 聽 聽 endif
聽 聽 endif
return Nil
method PEDIR_CODE ()聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 class TApiBBVA
聽 聽 local oDlg, oActiveX, nPos, oTimer, oApi
聽 聽 oApi := Self
聽 聽 define dialog oDlg from 100, 100 to 950,1000 title "Navegar" pixel ;
聽 聽 聽 聽 聽 聽 聽 of ::oWnd
聽 聽 activate dialog oDlg on init ;
聽 聽 聽 聽 聽 聽( oActiveX := ShowPageWeb( oDlg, ;
聽 聽 聽 聽 聽 聽 聽 聽 "https://connect.bbva.com/sandboxconnect?scope=" + ;
聽 聽 聽 聽 聽 聽 聽 聽 "&client_id=" 聽 聽+ oApi:cAppID 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽+ ;
聽 聽 聽 聽 聽 聽 聽 聽 "&redirect_uri=" + oApi:cRedirect_Uri 聽 聽 聽 聽 聽 聽 聽 + ;
聽 聽 聽 聽 聽 聽 聽 聽 "&response_type=code", 0, 0, 825, 950 ) 聽 聽 聽 聽 聽, ;
聽 聽 聽 聽 聽oApi:IniTimer (oDlg, oActiveX ) )
聽 聽 release ::oTimer
return oDlg:nResult = ID_OK
method IniTimer ( oDlg, oActiveX )聽 聽 聽 聽 聽 class TApiBBVA
聽 聽 define Timer ::oTimer of oDlg interval 3000 ;
聽 聽 聽 聽 action IF ( ::TENGO_CODE (oActiveX), oDlg:End (ID_OK), )
聽 聽 activate Timer ::oTimer
return Nil
method TENGO_CODE ( oActiveX )聽 聽 聽 聽 聽 聽 聽 class TApiBBVA
聽 聽 local oDOM := oActiveX:GetProp( "Document" ), ; // -> Object Document
聽 聽 聽 聽 聽 Retorno := .f., nPos
聽 聽 local cUrl := oDOM:Url
聽 聽 if (nPos := AT ( "?code=", cUrl )) # 0
聽 聽 聽 聽 ::cCode := SUBSTR ( cUrl, nPos + 6 )
聽 聽 聽 聽 Retorno := .t.
聽 聽 endif
return Retorno
Function ShowPageWeb( oParent, cUrl, nT, nL, nH, nW )
聽 聽 local oActiveX, oHttp, oActiveXdo
聽 聽 oActiveX := TActiveX():New( oParent, "Shell.Explorer.2", nT, nL, nW, nH )
聽 聽 oActivex:Silent := .T. // aqui silence... en el script.
聽 聽 oActiveX:Do( "Navigate2", cUrl )
聽 聽 oActivex:SetFocus()
聽 聽 WHILE oActivex:Busy
聽 聽 聽 聽 SysWait(.2)
聽 聽 ENDDO
聽 聽 oActiveXdo := oActiveX:Document()
聽 聽 oHttp := oActiveX:GetProp( "Document" ) // -> Object Document
聽 聽 if Empty( oHttp )
聽 聽 聽 聽 MsgInfo( "Problemas en el Site...", ;
聽 聽 聽 聽 聽 聽 聽"Problemas en el Site..." )
聽 聽 聽 聽 RETURN( .F. )
聽 聽 endif
Return oActiveX
method PEDIR_TOKEN ()聽 聽聽 聽 聽 聽 聽 聽 聽 聽 class TApiBBVA
聽 聽 local oHttp, cCadena, aRespuesta
聽 聽 try
聽 聽 聽 聽 oHttp := CreateObject (::cNomObjOLE)
聽 聽 catch
聽 聽 聽 聽 ? 'Error de creacion oHttp'
聽 聽 聽 聽 return .t.
聽 聽 end
聽 聽 oHttp:Open ( "POST" , ::cUrl + "?grant_type=authorization_code" + ;
聽 聽 聽 聽 聽 聽 聽"&code=" + ALLTRIM (::cCode) 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 + ;
聽 聽 聽 聽 聽 聽 聽"&redirect_uri=" + ::cRedirect_Uri, .f. )
聽 聽 oHttp:SetRequestHeader ( "Authorization", ;
聽 聽 聽 聽 聽 聽 聽"Basic " + cMimeEnc(::cAppID + ':' + ::cSecretID) )
聽 聽 try
聽 聽 聽 聽 oHttp:Send ()
聽 聽 catch
聽 聽 聽 聽 ? 'Error en Send Token'
聽 聽 聽 聽 return .t.
聽 聽 end
聽 聽 cCadena := oHttp:responseText
*聽 聽HB_MemoWrit ( ::cFicTok, cCadena, .f. )
聽 聽 aRespuesta := hb_jsonDecode (cCadena)
聽 聽 if hb_HHaskey ( aRespuesta, 'access_token' )
聽 聽 聽 聽 ::cToken := aRespuesta ['access_token']
聽 聽 endif
聽 聽 oHttp := Nil
return ! EMPTY ( ::cToken )
method PEDIR_EXTRACTO ()聽 聽 聽 聽 聽 聽 聽 聽 class TApiBBVA
聽 聽 local oHttp, cUrl, cCadena
聽 聽 cURL聽 聽 聽 聽:= "https://apis.bbva.com/business-accounts-sbx/v1/statements/aeb43"
聽 聽 try
聽 聽 聽 聽 oHttp := CreateObject (::cNomObjOLE)
聽 聽 catch
聽 聽 聽 聽 ? 'Error de creacion oHttp'
聽 聽 聽 聽 return .t.
聽 聽 end
聽 聽 oHttp:Open ( "GET" , cUrl, .f. )
聽 聽 oHttp:SetRequestHeader ( "Content-Type", "application/json")
聽 聽 oHttp:SetRequestHeader ( "Accept", "application/json")
聽 聽 oHttp:SetRequestHeader ( "Authorization", "jwt " + ::cToken )
聽 聽 oHttp:SetRequestHeader ( "Host", "apis.bbva.com" )
聽 聽 try
聽 聽 聽 聽 oHttp:Send ()
聽 聽 catch
聽 聽 聽 聽 ? 'Error en Send'
聽 聽 聽 聽 return .t.
聽 聽 end
聽 聽 cCadena := oHttp:responseText
聽 聽 HB_MemoWrit ( ::cFicJSon, cCadena, .f. )
聽 聽 oHttp := Nil
return Nil
La clase se usar铆a as铆 :
聽 聽 oApiBBVA := TApiBBVA():new () 聽 聽 聽 聽 聽 聽&& Pasar como par谩metro la ventana padre
聽 聽 oApiBBVA:EXTRACTO ()
La pantalla de identificaci贸n de ConnectBBVA con los datos de usuario de pruebas (contrase帽a:123456)

El resultado final es el fichero EXT_BBV.JSON con el siguiente contenido :
{"result":{"code":200,"info":"OK"},"data":{"AEB43file":"110182241902008000282104202104201000019193174009783CARLOS BANANERO RUIZ \n 2201822419210420210420028972000000000551180000000000ABONO COMP. TRU 30/1/2017 \n 2201822419210420210420021731000000000003500000000000LIQUID.ABONO COM \n 3301822419020080002800010000000025535350001000000002553535100001919317400978 \n 88999999999999999999000035 "}}