
En este blog, me gustaría presentar algunos fragmentos de código que podrían ayudar a otros a consumir API REST basadas en tokens en ABAP.
Obtención de los datos pertinentes para obtener el Token
Para obtener el token, el proveedor debe proporcionar detalles como la identificación de la aplicación, el secreto de la aplicación, la identificación del cliente y el extremo del token.
El ejemplo de cómo se ven estos detalles es el siguiente:
La identificación de la aplicación, la identificación del cliente y el secreto son simplemente cadenas de datos y el punto final del token es una URL.
Fragmento de código para obtener un Token
El proveedor de la API debe proporcionar la definición de qué parámetros de encabezado se necesitan para llamar con éxito al punto final del token.
METHOD get_token.
DATA: lo_http_token TYPE REF TO if_http_client,
l_response_token TYPE string.
DATA: l_status_code TYPE i.
DATA: lv_bas64enc TYPE string.
DATA: lv_url_token TYPE string,
lv_client_id TYPE string.
DATA: lo_root TYPE REF TO cx_root.
TRY.
*Url to access token
lv_url_token = IS_API_CREDENTI-token_endpoint. "Token Endpoint
* create http client Object
CALL METHOD cl_http_client=>create_by_url
EXPORTING
url = lv_url_token
IMPORTING
client = lo_http_token
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4.
IF sy-subrc <> 0.
* MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
* WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
*Close the client in case of Error
lo_http_token->close( ).
ENDIF.
* Set Method POST
IF lo_http_token IS BOUND.
lo_http_token->request->set_method( if_http_entity=>co_request_method_post ).
ENDIF.
*Set header parameter
*Convert string to base64
CONCATENATE IS_API_CREDENTI-APPLICATION_ID ':' IS_API_CREDENTI-APPLICATION_SEC INTO lv_bas64enc .
cl_http_utility=>encode_base64( EXPORTING
unencoded = lv_bas64enc
RECEIVING
encoded = lv_bas64enc ).
CONCATENATE 'Basic ' lv_bas64enc INTO lv_bas64enc RESPECTING BLANKS.
lo_http_token->request->set_header_field(
EXPORTING
name="Authorization"
value = lv_bas64enc
).
lo_http_token->request->set_header_field(
EXPORTING
name="Content-Type"
value="application/x-www-form-urlencoded"
).
lo_http_token->request->set_header_field(
EXPORTING
name="Accept"
value="application/json"
).
*Set all the form parameters
lo_http_token->request->set_form_field(
EXPORTING
name="grant_type"
value="client_credentials"
).
lo_http_token->request->set_form_field(
EXPORTING
name="scope"
value="client"
).
lv_client_id = IS_API_CREDENTI-client_id.
lo_http_token->request->set_form_field(
EXPORTING
name="client_id"
value = lv_client_id
).
* Turn off logon popup. detect authentication errors.
lo_http_token->propertytype_logon_popup = 0.
* Send / Receive Token Request
CALL METHOD lo_http_token->send
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
http_invalid_timeout = 4
OTHERS = 5.
IF sy-subrc <> 0.
* MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
* WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
CALL METHOD lo_http_token->receive
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
OTHERS = 4.
IF sy-subrc <> 0.
* MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
* WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
CALL METHOD lo_http_token->response->get_status
IMPORTING
code = l_status_code.
*Json response needs to be converted to abap readable format
CALL METHOD lo_http_token->response->get_cdata
RECEIVING
data = l_response_token.
/ui2/cl_json=>deserialize(
EXPORTING
json = l_response_token
CHANGING
data = is_token "Token will be stored in the instance structure, for retrieval in other methods.
).
lo_http_token->close( ).
CATCH cx_root INTO lo_root.
ENDTRY.
ENDMETHOD.
Los datos is_token son del siguiente tipo
BEGIN OF ts_token,
token_type TYPE string,
access_token TYPE string,
expires_in TYPE string,
END OF ts_token .
Llamar a una API con operación PUT utilizando el token obtenido, incluida la gestión de errores
En el siguiente código, se llama a una API utilizando el token obtenido anteriormente para escribir algunos datos en el lado del proveedor de API. También se han procesado varios códigos de estado de devolución que podrían venir como devolución.
Los detalles de los parámetros que deben proporcionarse para realizar una llamada deben provenir del proveedor de API. También los detalles sobre la estructura de los datos de error deben provenir del proveedor de API.
METHOD put_employee_call.
DATA: lv_url_api TYPE string.
DATA: lo_http_put_empl TYPE REF TO if_http_client.
DATA: lo_root TYPE REF TO cx_root.
DATA: lv_access_token TYPE string.
DATA: l_response_put TYPE string.
DATA: l_status_code TYPE i.
DATA: ls_mitarbeiter_put_resp_422 TYPE ts_put_resp_unprocessable,
ls_mitarbeiter_put_resp_400_4 TYPE ts_put_resp_400_4.
DATA: ls_errors_422 TYPE ts_put_errors,
ls_msg TYPE bal_s_msg,
lv_text TYPE char200,
ls_emp_put_resp_200_201 TYPE ts_put.
TRY.
lv_url_api = is_api_credenti-api_endpoint_new .
*Create http client Object
CALL METHOD cl_http_client=>create_by_url
EXPORTING
url = lv_url_api
IMPORTING
client = lo_http_put_empl
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4.
IF sy-subrc <> 0.
* MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
* WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
*Close the client in case of Error
lo_http_put_empl->close( ).
ENDIF.
*Set Method POST
IF lo_http_put_empl IS BOUND.
lo_http_put_empl->request->set_method( 'PUT' ).
ENDIF.
*Set Header fields
lo_http_put_empl->request->set_header_field(
EXPORTING
name="Accept"
value="application/json"
).
lo_http_put_empl->request->set_header_field(
EXPORTING
name="Content-Type"
value="application/json"
).
CONCATENATE is_token-token_type is_token-access_token INTO lv_access_token SEPARATED BY space.
lo_http_put_empl->request->set_header_field(
EXPORTING
name="Authorization"
value = lv_access_token
).
*Set body Parameter
lo_http_put_empl->request->append_cdata( data = iv_empl_json ).
* Turn off logon popup. detect authentication errors.
lo_http_put_empl->propertytype_logon_popup = 0.
*Send / Receive PUT Request
CALL METHOD lo_http_put_empl->send
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
http_invalid_timeout = 4
OTHERS = 5.
IF sy-subrc <> 0.
* MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
* WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
CALL METHOD lo_http_put_empl->receive
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3
OTHERS = 4.
IF sy-subrc <> 0.
* MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
* WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
*Get status code
CALL METHOD lo_http_put_empl->response->get_status
IMPORTING
code = l_status_code.
*Obtain Json response
CALL METHOD lo_http_put_empl->response->get_cdata
RECEIVING
data = l_response_put.
*deserializing json response
CASE l_status_code.
WHEN '422' . " Unprocessable Entry
/ui2/cl_json=>deserialize(
EXPORTING
json = l_response_put
CHANGING
data = ls_mitarbeiter_put_resp_422
).
*Add log for every Error Entry
LOOP AT ls_mitarbeiter_put_resp_422-errors INTO ls_errors_422.
CONCATENATE ls_errors_422-field ls_errors_422-code ls_errors_422-message INTO lv_text SEPARATED BY space.
me->return_log_variables( EXPORTING iv_text = lv_text CHANGING cs_msg = ls_msg ).
ls_msg-msgty = 'E'.
ls_msg-msgid = const_freetext_msgid.
ls_msg-msgno = const_freetext_msgno.
me->add_log_record( is_msg = ls_msg ).
CLEAR: ls_msg,ls_errors_422,lv_text.
ENDLOOP.
WHEN '400' OR '404'.
/ui2/cl_json=>deserialize(
EXPORTING
json = l_response_put
CHANGING
data = ls_mitarbeiter_put_resp_400_4
).
*Add one log Entry for 400 or 404
CONCATENATE ls_mitarbeiter_put_resp_400_4-message ls_mitarbeiter_put_resp_400_4-code INTO lv_text SEPARATED BY space.
me->return_log_variables( EXPORTING iv_text = lv_text CHANGING cs_msg = ls_msg ).
ls_msg-msgty = 'E'.
ls_msg-msgid = const_freetext_msgid.
ls_msg-msgno = const_freetext_msgno.
me->add_log_record( is_msg = ls_msg ).
CLEAR: ls_msg,lv_text.
*Add one Success entry for Update
WHEN '200'.
/ui2/cl_json=>deserialize(
EXPORTING
json = l_response_put
CHANGING
data = ls_emp_put_resp_200_201
).
CONCATENATE ls_emp_put_resp_200_201-external_id TEXT-002 INTO lv_text SEPARATED BY space.
me->return_log_variables( EXPORTING iv_text = lv_text CHANGING cs_msg = ls_msg ).
ls_msg-msgty = 'S'.
ls_msg-msgid = const_freetext_msgid.
ls_msg-msgno = const_freetext_msgno.
me->add_log_record( is_msg = ls_msg ).
CLEAR: ls_msg,lv_text.
*Add one Success entry for Creation
WHEN '201'.
/ui2/cl_json=>deserialize(
EXPORTING
json = l_response_put
CHANGING
data = ls_emp_put_resp_200_201
).
CONCATENATE ls_emp_put_resp_200_201-external_id TEXT-003 INTO lv_text SEPARATED BY space.
me->return_log_variables( EXPORTING iv_text = lv_text CHANGING cs_msg = ls_msg ).
ls_msg-msgty = 'S'.
ls_msg-msgid = const_freetext_msgid.
ls_msg-msgno = const_freetext_msgno.
me->add_log_record( is_msg = ls_msg ).
CLEAR: ls_msg,lv_text.
ENDCASE.
lo_http_put_empl->close( ).
CATCH cx_root INTO lo_root.
ENDTRY.
ENDMETHOD.
Gracias
Ketán
Calle Eloy Gonzalo, 27
Madrid, Madrid.
Código Postal 28010
Paseo de la Reforma 26
Colonia Juárez, Cuauhtémoc
Ciudad de México 06600
Real Cariari
Autopista General Cañas,
San José, SJ 40104
Av. Jorge Basadre 349
San Isidro
Lima, LIM 15073