In order for this site to work correctly we need to store a small file (called a cookie) on your computer. Most every site in the world does this, however since the 25th of May 2011, by law we have to get your permission first. Please abandon the forum if you disagree.

Para que este foro funcione correctamente es necesario guardar un pequeño fichero (llamado cookie) en su ordenador. La mayoría de los sitios de Internet lo hacen, no obstante desde el 25 de Marzo de 2011 y por ley, necesitamos de su permiso con antelación. Abandone este foro si no está conforme.

Integracion de App YPF - API Azure (Solucionado)

Foro público de Xailer en español
Responder
ryder1912
Mensajes: 29
Registrado: Jue Jul 09, 2015 8:17 pm

Integracion de App YPF - API Azure (Solucionado)

Mensaje por ryder1912 »

Buenas a todos. Estamos realizando la integracion de xailer con la api de YPF (Azure) pero tenemos problemas con el POST, la integracion consta de 2 procedimientos:

1 - Intencion de Pago (POST):

Código: Seleccionar todo

POST /api/private/payment_intentions
 {   "provider_id": “​YPF351576293dhf9b50ugfyy4crrhb32qz73w​”,  // ​Identity unívoco de la intención de pago, lo envía el PDV para su seguimiento 
     "amount": ​30​, ​//Monto total de la operación. [opcional]    
     "products": [ ​  //Siempre array tiene que contener por lo menos una posición    
      {       
        “id_price_book”: “​432​” // id price book (String, Opcional)      
        “description”: “​pepsi​ ​500cm​”, //requerido      
         "quantity": ​1​, //requerido (1/99)      
         "type": ​"store"​, //valores opessa_store, opessa_fuel, opessa_boxes       
         "unit_price": ​30​,       
         "amount": ​30, //opcional se calcula pxq     
       }   
     ],   
     "fuel_station_id": ​3344​, //Apies   "point_of_sale": ​44637​, //ID del punto de Venta  
      "sale_type": ​"store"​,  
       "meta_data":[ "provider_creation_date": ​"2019-01-17T17:09:45.664Z"​,  //Momento del envío del mensaje desde el PDV      
                             "provider_delivery_date": ​"2019-01-17T17:09:45.664Z"​,   //Momento del envío del mensaje desde el YPF Central  ] 
}
 
Como respuesta nos devuelve un 201 - OK con el id de Pago (payment_id), ademas de otros datos. Con ese id se hace una consulta del pago

2 - Consulta del pago realizado (GET)
GET /api/private/payment_intentions/{payment_id}

Como decia el problema lo tenemos en el POST, al realizar el OpenRequest nos devuelve el siguiente error:

Código: Seleccionar todo

----------------------- Información detallada del error -----------------------

      Subsistema: BASE
 Código de error: 1004
          Estado: .F.
     Descripción: Message not found
       Operación: TINTERNET:OPENREQUEST
      Argumentos: 
         Fichero: 
 Código error SO: 0

Pila de llamadas:
  TFORM1:BTNBMP1CLICK (78)
  TBTNBMP:ONCLICK (0)
  TBTNBMP:CLICK (100)
  (b)XCONTROL:XCONTROL (148)
  TBTNBMP:COMMAND (0)
  TSCROLLINGWINCONTROL:WMCOMMAND (282)
  TFORM1:WMCOMMAND (943)
  RUNFORM (0)
  TAPPLICATION:RUN (276)
  MAIN (15)
Datos de las credenciales y endpoints para la integración

API URL: https://ypfamepcjqa.azure-api.net/mspayments/api/

SECURITY HEADERS
X-ACCESS-TOKEN : 65f76c1a-8475-407c-9f6c-ecd724fca025
Ocp-Apim-Subscription-Key : 8f12b920f95f4e5da21499b317c48b29

OTROS HEADERS
Content-Type : application/json

Aqui dejo el codigo completo y tambien para descargarlo:
APPYPF.zip
(51.24 KiB) Descargado 154 veces

Código: Seleccionar todo

#include "Xailer.ch"
#include "ExStruct.ch"
#include "hbxml.ch"
#include "WinINet.api"

CLASS TForm1 FROM TForm

   COMPONENT oBtnBmp1
   COMPONENT oMemo1
   COMPONENT oBtnBmp2

   DATA cAPIURL             INIT 'https://ypfamepcjqa.azure-api.net/mspayments/api'
   DATA cAccessToken     INIT '65f76c1a-8475-407c-9f6c-ecd724fca025'
   DATA cKey                  INIT '8f12b920f95f4e5da21499b317c48b29'

   METHOD CreateForm()
   METHOD BtnBmp1Click( oSender )
   METHOD BtnBmp2Click( oSender )

ENDCLASS

#include "MenuPrincipal.xfm"

//------------------------------------------------------------------------------
// POST
METHOD BtnBmp1Click( oSender ) CLASS TForm1
LOCAL cJson, cDatos:='', cData, debug:=''
LOCAL cTexto, oInternet, xerror, Connection, File

   cTexto:=''
BEGIN SEQUENCE
   oInternet:= TInternet():New( Self )
   oInternet:nPort := INTERNET_DEFAULT_HTTPS_PORT
   oInternet:nTimeOut:= 60000
   IF !oInternet:Open()
      BREAK "Not Open"
   ENDIF
   Connection:= oInternet:Connect(::cAPIURL)
   IF !Connection
      BREAK "Not Connection"
   ENDIF
      cJson:='{'
      //datos de ejemplo
      cDatos+='"provider_id": "YPF351576293dhf9b50ugfyy4crrhb32qz73w",' //ID ingresa del PDV
      cDatos+='"amount": 30,'                                           //monto total opcional
      cDatos+='"products": [{'
      cDatos+='"id_price_book": "432",'                                 // string opcional
      cDatos+='"description": "50n litros de combustible",'
      cDatos+='"quantity": 26.70,'                                     //decimal
      cDatos+='"type": "fuel",'                                          //store,fuel,boxes
      cDatos+='"code": "Infinia",'                                      //Infinia, Disel, etc
      cDatos+='"unit_price": 30,'
      cDatos+='"title": "product title",'
      cDatos+='"amount": 30}],'                                       //opcional se calcula pxq
      cDatos+='"fuel_station_id": 4321,'                          //id unico de cada QR
      cDatos+='"point_of_sale": 1,'                                 //si es null se enviaYVOSAPP
      cDatos+='"fuel_pump": "1",'
      cDatos+='"fuel_dispenser": "1",'
      cDatos+='"provider_external_gateway_id": "432",'
      cDatos+='"sale_type": "GAS_FLOW",'
      cDatos+='"meta_data": [{'
      cDatos+='"provider_creation_date":"2019-01-17T17:09:45.664Z",'   //envio desde el PDV
      cDatos+='"provider_delivery_date":"2019-01-17T17:09:45.664Z"}]' //envio desde el YPF central
      cDatos+='}'
      cJson+=cDatos     
          
   debug:=::cAPIURL+"/private/payment_intentions/Ocp-Apim-Subscription-Key:"+::cKey+"/X-ACCESS-TOKEN:"+::cAccessToken
   
   File:= oInternet:OpenRequest("POST",::cAPIURL+"/private/payment_intentions/Ocp-Apim-Subscription-Key:"+::cKey+"/X-ACCESS-TOKEN:"+::cAccessToken,INTERNET_FLAG_SECURE,"HTTP/1.0")
   IF !oInternet:SendRequest(File, "Content-type: application/json", cJson )
      BREAK "Not SendRequest"
   ENDIF
   cTexto:=''
   WHILE oInternet:ReadFile( File, @cData, 65536 )
       cTexto += cData
   ENDDO
   cTexto += " *** "+oInternet:GetErrorDescription()+" "+HB_NToS(oInternet:nLastError)+" "+HB_NToS(GetLastError())

   ::oMemo1:Value:= cTexto
   RECOVER USING xerror
     xerror:= oInternet:GetErrorDescription()
   MsgInfo( xerror )
END SEQUENCE

RETURN Nil

//------------------------------------------------------------------------------
// GET
METHOD BtnBmp2Click( oSender ) CLASS TForm1
LOCAL hRequest, cBuffer := Space( 1024 ), cData := ""
LOCAL cUrl1:='/payment_intentions/1'
LOCAL debug:='' 

      WITH OBJECT TInternet():Create()
         IF :Open()
             debug:=:GetErrorDescription(:nLastError())
              IF !Empty( hRequest := :OpenURL(::cAPIURL+cUrl1) )
                  WHILE :ReadFile( hRequest, @cBuffer, 65536 )
                   cData += cBuffer
                  ENDDO
               :CloseURL( hRequest )
              ENDIF
         ENDIF
         debug:=:GetErrorDescription(:nLastError())
         :Close()
         ::oMemo1:Value:= cData
      END
RETURN Nil
Otro ejemplo de POST pero con Curl, devuelve error de Acceso Denegado...

Código: Seleccionar todo

curl -X POST \
  https://ypfamepcjqa.azure-api.net/mspayments/api/private/payment_intentions \
  -H 'Content-Type: application/json' \
  -H 'Ocp-Apim-Subscription-Key: 8f12b920f95f4e5da21499b317c48b29' \
  -H 'X-ACCESS-TOKEN: 65f76c1a-8475-407c-9f6c-ecd724fca025' \
  -d '{
    "provider_id": "1234",
    "products": [
        {
            "id": "432",
            "id_price_book": "432",
            "description": "28 litros de combustible",
            "quantity": 28,
            "type": "fuel",
            "code": "INFINIA",
            "unit_price": 40
        }
    ],
"fuel_station_id": XXX,
"fuel_pump": " XXX ",
"fuel_dispenser": "XXX",
"point_of_sale": XXX ,
    "sale_type": "GAS_FLOW"
}'
Espero que puedan ayudar. slds.
Última edición por ryder1912 el Sab Oct 05, 2019 3:59 am, editado 1 vez en total.
ryder1912
Mensajes: 29
Registrado: Jue Jul 09, 2015 8:17 pm

Re: Integracion de App YPF

Mensaje por ryder1912 »

Buenas a todos. Hemos probado algunas configuraciones pero toavia no hemos podido hacer funcionar el POST. Nos sigue dando error en el oInternet:OpenRequest. No sabemos que es lo que estamos haciendo mal.

Código: Seleccionar todo


 DATA cAPIURL          INIT 'http://ypfamepcjqa.azure-api.net/mspayments/api'
 DATA cAccessToken  INIT '65f76c1a-8475-407c-9f6c-ecd724fca025'
 DATA cKey               INIT '8f12b920f95f4e5da21499b317c48b29'
   
METHOD BtnBmp1Click( oSender ) CLASS TForm1
LOCAL cJson, cDatos:='', cData, debug:='', cURL2
LOCAL cTexto, oInternet, xerror, Connection, File

   cTexto:=''
BEGIN SEQUENCE
   oInternet:= TInternet():New( Self )
   oInternet:nPort := INTERNET_DEFAULT_HTTPS_PORT
   oInternet:nTimeOut:= 60000
   IF !oInternet:Open()
      BREAK "Not Open"
   ENDIF
   Connection:= oInternet:Connect(::cAPIURL)
   IF !Connection
      BREAK "Not Connection"
   ENDIF
      cJson:='{'
      //datos de ejemplo
      cDatos+='"provider_id": "YPF351576293dhf9b50ugfyy4crrhb32qz73w",' //ID ingresa del PDV
      cDatos+='"amount": 30,'                                           //monto total opcional
      cDatos+='"products": [{'
      cDatos+='"id_price_book": "432",'                                 // string opcional
      cDatos+='"description": "50n litros de combustible",'
      cDatos+='"quantity": 26.70,'                                     //decimal
      cDatos+='"type": "fuel",'                                          //store,fuel,boxes
      cDatos+='"code": "Infinia",'                                       //Infinia, Disel, etc
      cDatos+='"unit_price": 30,'
      cDatos+='"title": "product title",'
      cDatos+='"amount": 30}],'                                         //opcional se calcula pxq
      cDatos+='"fuel_station_id": 1559,'                                //id unico de cada QR
      cDatos+='"point_of_sale": 1,'                                 //si es null se enviaYVOSAPP
      cDatos+='"fuel_pump": "1",'
      cDatos+='"fuel_dispenser": "1",'
      cDatos+='"provider_external_gateway_id": "432",'
      cDatos+='"sale_type": "GAS_FLOW",'
      cDatos+='"meta_data": ['
      cDatos+='"provider_creation_date":"2019-01-17T17:09:45.664Z",'   //envio desde el PDV
      cDatos+='"provider_delivery_date":"2019-01-17T17:09:45.664Z"]' //envio desde el YPF central
      cDatos+='}'
      cJson+=cDatos
  
   File:= oInternet:OpenRequest("POST",::cAPIURL+"/private/payment_intentions/?Ocp-Apim-Subscription-Key="+::cKey+"&X-ACCESS-TOKEN="+::cAccessToken,INTERNET_FLAG_SECURE,"HTTP/1.0")
   //IF !oInternet:SendRequest(File, "Content-type: application/json", cJson )

   IF !oInternet:SendRequest(File,"Ocp-Apim-Subscription-Key:8f12b920f95f4e5da21499b317c48b29,X-ACCESS-TOKEN:65f76c1a-8475-407c-9f6c-ecd724fca025,content-type:application/json", cJson )

      BREAK "Not SendRequest"
   ENDIF
   cTexto:=''
   WHILE oInternet:ReadFile( File, @cData, 65536 )
       cTexto += cData
   ENDDO
   cTexto += " *** "+oInternet:GetErrorDescription()+" "+HB_NToS(oInternet:nLastError)+" "+HB_NToS(GetLastError())

   ::oMemo1:Value:= cTexto
   RECOVER USING xerror
     xerror:= oInternet:GetErrorDescription()
   MsgInfo( xerror )
END SEQUENCE

RETURN Nil
Tambien probamos enviar un POST con el POSTMAN y fciona ya que nos devuelve el id del pago. Dejo la respuesta y las imagenes del POST (con POSTMAN)
Este es el response (respuesta) con los datos de la venta. Slds

Código: Seleccionar todo

{
    "data": {
       [color=#FF0000] "id": 500315, // ID del PAGO[/color]
        "amount": 771,
        "sub_total": 771,
        "fuel_station_id": 1559,
        "buyer_email": null,
        "buyer_dni": null,
        "products": [
            {
                "id": 0,
                "quantity": 25.7,
                "done": 0,
                "type": "fuel",
                "code": "Infinia",
                "unit_price": 30,
                "amount": 771,
                "title": "product title",
                "description": "50n litros de combustible",
                "pictureurl": null,
                "category": null,
                "id_price_book": "433"
            }
        ],
        "fuel_pump": 1,
        "point_of_sale": 1,
        "creation_date": "2019-09-24T05:24:05.263",
        "delivery_date": null,
        "is_paid": false,
        "is_active": false,
        "payment_intention_geohash": "4xb52gpj1",
        "payment_intention_latitude": -45.8176,
        "payment_intention_longitude": -67.45735,
        "is_pre_purchase": false,
        "universal_id": null,
        "creation_timestamp": 1569302645100,
        "sale_type": "GAS_FLOW",
        "network": "OLEUM",
        "payment_intention_status": 4,
        "serviclub_id": null,
        "fuel_dispenser": 1,
        "full_name": null,
        "qr_provider": null,
        "serviclub_card": null,
        "validation_time_response": 0,
        "initialize_time_response": 0.0228,
        "validation_eess_time_response": 4.3298000000000005,
        "search_payment_intention_time_response": 62.787800000000004,
        "initialize_merge_time_response": 0.0207,
        "search_fuel_station_time_response": 0.0092,
        "search_products_time_response": 0,
        "updated_date": "2019-09-24T14:27:19.9928443+00:00",
        "device_serial": null,
        "device_uuid": null,
        "device_manufacturer": null,
        "device_model": null,
        "device_platform": null,
        "device_version": null,
        "context_creation_time_response": 98.07300000000001,
        "provider_id": "YPF351576293dhf9b50ugfyy4crrhb32qz73w",
        "meta_data": {},
        "payment_id": null,
        "error_owner": null,
        "error_category": null,
        "error_code": null,
        "error_description": null,
        "fuel_station_request": null,
        "fuel_station_response": null,
        "payment_intention_internal_status": 0,
        "provider_external_gateway_id": null
    },
    "time_response": 432
}
Adjuntos
05 -ok.png
05 -ok.png (24.81 KiB) Visto 2725 veces
01 -POST.png
01 -POST.png (24.33 KiB) Visto 2725 veces
ryder1912
Mensajes: 29
Registrado: Jue Jul 09, 2015 8:17 pm

Re: Integracion de App YPF

Mensaje por ryder1912 »

Buenas a todos. Aca esta la solucion. By Emilio A.
Slds.

Post

Código: Seleccionar todo

METHOD BtnBmp1Click( oSender ) CLASS TForm1
LOCAL cJson, cDatos:='', cData, debug:='', cURL2
LOCAL cTexto, oInternet, xerror, Connection, File, oWinHttp
Local cFechaAct:= transf(DToS(Date()),'@R 9999-99-99')+'T'+time()+'Z'

cTexto:=''
BEGIN SEQUENCE
   oInternet:= TInternet():New( Self )
   oInternet:nPort := INTERNET_DEFAULT_HTTPS_PORT
   oInternet:nTimeOut:= 60000
   IF !oInternet:Open()
      BREAK "Not Open"
   ENDIF
   Connection:= oInternet:Connect(::cAPIURL)
   IF !Connection
      BREAK "Not Connection"
   ENDIF
      cJson:='{'
      //datos de ejemplo
      cDatos+='"provider_id": "YPF351576293dhf9b50ugfyy4crrhb32qz73w",' 
      cDatos+='"amount": 30,'                                         
      cDatos+='"products":[{'
      cDatos+='"id_price_book": "432",'                                
      cDatos+='"description": "50n litros de combustible",'
      cDatos+='"quantity": 26.70,'                                    
      cDatos+='"type": "fuel",'                                         
      cDatos+='"code": "Infinia",'                                      
      cDatos+='"unit_price": 30,'
      cDatos+='"title": "product title",'
      cDatos+='"amount": 30'
      cDatos+='}],'                                       
      cDatos+='"fuel_station_id": 1111,'                          
      cDatos+='"point_of_sale": 1,'                               
      cDatos+='"fuel_pump": "1",'
      cDatos+='"fuel_dispenser": "1",'
      cDatos+='"provider_external_gateway_id": "432",'
      cDatos+='"sale_type": "GAS_FLOW"'
      cDatos+= '"meta_data":[{'
      cDatos+= '"provider_creation_date":"'+cFechaAct+'"'
      cDatos+='},'
      cDatos+='{"provider_delivery_date":"'+cFechaAct+'"}'
      cDatos+=']}'
      cDatos+='}'
      cJson+=cDatos

oWinHttp := CreateObject( "MSXML2.serverXMLHTTP.6.0" )
oWinHttp:open("POST",::cAPIURL,.f.)
oWinHttp:SetRequestHeader("content-type","application/json")
oWinHttp:SetRequestHeader("X-ACCESS-TOKEN","65f76c1a-8475-407c-9f6c-ecd724fca025")
oWinHttp:SetRequestHeader("Ocp-Apim-Subscription-Key","8f12b920f95f4e5da21499b317c48b29")

oWinHttp:send(cJson)
::oMemo1:Value =+ oWinHttp:ResponseText
::oMemo2:Value := oWinHttp:Status
END SEQUENCE

RETURN Nil
Este es el Get - (Con el post se obtiene el Id del Pago)

Código: Seleccionar todo

METHOD BtnBmp2Click( oSender ) CLASS TForm1
LOCAL hRequest, cBuffer := Space( 1024 ), cData := ""
LOCAL cUrl1:='/payment_intentions/500314'  
LOCAL debug:='' ,oWinHttp

     	oWinHttp := CreateObject( "MSXML2.serverXMLHTTP.6.0" )
	oWinHttp:open("GET",::cAPIURL,.f.)
	oWinHttp:SetRequestHeader("content-type","application/json")
	oWinHttp:SetRequestHeader("X-ACCESS-TOKEN","65f76c1a-8475-407c-9f6c-ecd724fca025")
        oWinHttp:send()

::oMemo1:Value =+ oWinHttp:ResponseText
::oMemo2:Value := oWinHttp:Status

RETURN Nil
Claudio C
Mensajes: 60
Registrado: Dom Sep 20, 2015 8:13 pm
Ubicación: Buenos Aires

Re: Integracion de App YPF - API Azure (Solucionado)

Mensaje por Claudio C »

Gracias emilio por compartirlo.
Responder