Page 1 of 1

Integracion de App YPF - API Azure (Solucionado)

Posted: Tue Sep 17, 2019 11:09 pm
by 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):

Code: Select all

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:

Code: Select all

----------------------- 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) Downloaded 8 times

Code: Select all

#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...

Code: Select all

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.

Re: Integracion de App YPF

Posted: Wed Sep 25, 2019 1:53 am
by 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.

Code: Select all


 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

Code: Select all

{
    "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
}

Re: Integracion de App YPF

Posted: Sat Oct 05, 2019 3:54 am
by ryder1912
Buenas a todos. Aca esta la solucion. By Emilio A.
Slds.

Post

Code: Select all

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)

Code: Select all

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

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

Posted: Sun Oct 06, 2019 2:46 pm
by Claudio C
Gracias emilio por compartirlo.