# SAP BTP - ABAP in the cloud

### Generate PDF from HTML

{% tabs %}
{% tab title="HTML to PDF" %}

```java
CLASS zgenerate_pdf DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .
*
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
    METHODS: generate_pdf
      IMPORTING
        VALUE(im_url)            TYPE  string
        VALUE(im_api_key)        TYPE  string
        VALUE(im_html)           TYPE  string
        VALUE(im_encryption_key) TYPE  string OPTIONAL
        VALUE(im_landscape)      TYPE  string OPTIONAL
        VALUE(im_format)         TYPE  string OPTIONAL
        VALUE(im_margin_top)     TYPE  string OPTIONAL
        VALUE(im_margin_right)   TYPE  string OPTIONAL
        VALUE(im_margin_bottom)  TYPE  string OPTIONAL
        VALUE(im_margin_left)    TYPE  string OPTIONAL
      EXPORTING
        VALUE(ex_subrc)          TYPE  sysubrc
        VALUE(ex_mess)           TYPE  string
        VALUE(ex_pdf)            TYPE  xstring,
*
      close_client
        CHANGING
          im_client TYPE REF TO if_web_http_client.
*
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.
*
CLASS zgenerate_pdf IMPLEMENTATION.
*
  METHOD if_oo_adt_classrun~main.
*
    DATA: lv_subrc TYPE sysubrc,
          lv_mess  TYPE string,
          lv_xpdf  TYPE xstring.
*
    CALL METHOD generate_pdf
      EXPORTING
        im_url     = 'https://api-eu.renda.io/v2/generatePDF'
        im_api_key = '<your api key>'
        im_html    = '<html>Hello World!</html>'
*       im_encryption_key =
*       im_landscape      =
*       im_format  =
*       im_margin_top     =
*       im_margin_right   =
*       im_margin_bottom  =
*       im_margin_left    =
      IMPORTING
        ex_subrc   = lv_subrc
        ex_mess    = lv_mess
        ex_pdf     = lv_xpdf.
*
    out->write( lv_subrc ).
    IF lv_mess IS NOT INITIAL.
      out->write( lv_mess ).
    ENDIF.
    out->write( lv_xpdf ).
*
  ENDMETHOD.
*
  METHOD close_client.
*
    TRY.
        CALL METHOD im_client->close.
      CATCH cx_web_http_client_error.
    ENDTRY.
    FREE im_client.
*
  ENDMETHOD.
*
  METHOD generate_pdf.
*
    DATA: lo_client      TYPE REF TO if_web_http_client,
          lo_response    TYPE REF TO if_web_http_response,
          lo_destination TYPE REF TO if_http_destination,
          lo_request     TYPE REF TO if_web_http_request,
          lo_resp_status TYPE if_web_http_response=>http_status,
          lv_http_rc     TYPE i,
          lv_response    TYPE string,
          lv_json        TYPE /ui2/cl_json=>json,
          lr_data        TYPE REF TO data,
          lv_req_body    TYPE string.
*
    FIELD-SYMBOLS: <tab>   TYPE ANY TABLE,
                   <data>  TYPE data,
                   <data2> TYPE data,
                   <field> TYPE any.
*
* Setup IF_WEB_HTTP_CLIENT object
*
    TRY.
        CALL METHOD cl_http_destination_provider=>create_by_url
          EXPORTING
            i_url              = im_url
          RECEIVING
            r_http_destination = lo_destination.
      CATCH cx_http_dest_provider_error.
        ex_mess = 'Error creating HTTP destination object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        cl_web_http_client_manager=>create_by_http_destination(
          EXPORTING
            i_destination = lo_destination
          RECEIVING
            r_client      = lo_client
        ).
      CATCH cx_web_http_client_error.
        ex_mess = 'Error creating HTTP client object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Get Request object
*
    lo_client->get_http_request(
      RECEIVING
        r_http_request = lo_request ).
*
* Set protocol version
*
    lo_request->set_version( if_web_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'Accept'
            i_value = 'application/pdf' ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'Content-Type'
            i_value = 'application/x-www-form-urlencoded' ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'x-api-key'
            i_value = im_api_key ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Set request body
*
    CONCATENATE: 'inputPayload=' im_html INTO lv_req_body.
*
    IF im_encryption_key IS NOT INITIAL.
      CONCATENATE: lv_req_body '&encryptionKey=' im_encryption_key INTO lv_req_body.
    ENDIF.
*
    IF im_landscape IS NOT INITIAL.
      CONCATENATE: lv_req_body '&landscape=' im_landscape INTO lv_req_body.
    ENDIF.
*
    IF im_format IS NOT INITIAL.
      CONCATENATE: lv_req_body '&format=' im_format INTO lv_req_body.
    ENDIF.
*
    IF im_margin_top IS NOT INITIAL.
      CONCATENATE: lv_req_body '&marginTop=' im_margin_top INTO lv_req_body.
    ENDIF.
*
    IF im_margin_right IS NOT INITIAL.
      CONCATENATE: lv_req_body '&marginRigth=' im_margin_right INTO lv_req_body.
    ENDIF.
*
    IF im_margin_bottom IS NOT INITIAL.
      CONCATENATE: lv_req_body '&marginBottom=' im_margin_bottom INTO lv_req_body.
    ENDIF.
*
    IF im_margin_left IS NOT INITIAL.
      CONCATENATE: lv_req_body '&marginLeft=' im_margin_left INTO lv_req_body.
    ENDIF.
*
    TRY.
        lo_request->set_text(
          EXPORTING
            i_text   = lv_req_body ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting request body. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Send request
*
    TRY.
        lo_client->execute(
          EXPORTING
            i_method   = if_web_http_client=>post
          RECEIVING
            r_response = lo_response ).
      CATCH cx_web_http_client_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'HTTP Post error. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Read the Response
*
    TRY.
        lo_response->get_status(
        RECEIVING
          r_value = lo_resp_status ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_response->get_text(
          RECEIVING
            r_value = lv_response ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    IF lo_resp_status-code NE '200'.
*
* Get error message back from Renda
*
      ex_subrc = 4.
      lv_json = lv_response.
      IF lv_json+0(1) NE '['.
        CONCATENATE '[' lv_json ']' INTO lv_json.
      ENDIF.
      lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
      IF lr_data IS BOUND.
        ASSIGN lr_data->* TO <tab>.
        LOOP AT <tab> ASSIGNING <data>.
          ASSIGN <data>->* TO <data2>.
          ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data2> TO <field>.
          IF <field> IS ASSIGNED.
            lr_data = <field>.
            ASSIGN lr_data->* TO <data2>.
            IF ex_mess IS INITIAL.
              ex_mess = <data2>.
            ELSE.
              CONCATENATE ex_mess ' \ ' <data2> INTO ex_mess RESPECTING BLANKS.
            ENDIF.
          ENDIF.
        ENDLOOP.
      ENDIF.
*
      IF ex_mess IS INITIAL.
        ex_mess = lv_response.
      ENDIF.
*
    ELSE.
*
      TRY.
          lo_response->get_binary(
            RECEIVING
              r_value  = ex_pdf
          ).
        CATCH cx_web_message_error.
          ex_mess = 'Error reading response. Process aborted'.
          ex_subrc = 4.
      ENDTRY.
*
    ENDIF.
*
    CALL METHOD close_client
      CHANGING
        im_client = lo_client.
*
  ENDMETHOD.
*
ENDCLASS.
```

{% endtab %}
{% endtabs %}

### Generate QR Code&#x20;

{% tabs %}
{% tab title="ABAP" %}

```java
CLASS zgenerate_qr_code DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .
*
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
    METHODS: generate_qr_code
      IMPORTING
        VALUE(im_url)            TYPE  string
        VALUE(im_api_key)        TYPE  string
        VALUE(im_data)           TYPE  string
      EXPORTING
        VALUE(ex_subrc)          TYPE  sysubrc
        VALUE(ex_mess)           TYPE  string
        VALUE(ex_qr_code)            TYPE  xstring,
*
      close_client
        CHANGING
          im_client TYPE REF TO if_web_http_client.
*
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.
*
CLASS zgenerate_qr_code IMPLEMENTATION.
*
  METHOD if_oo_adt_classrun~main.
*
    DATA: lv_subrc   TYPE sysubrc,
          lv_mess    TYPE string,
          lv_qr_code TYPE xstring.
*
    CALL METHOD generate_qr_code
      EXPORTING
        im_url     = 'https://api-eu.renda.io/totp/generateQRCode'
        im_api_key = '<your API key>'
        im_data    = 'www.google.com'
      IMPORTING
        ex_subrc   = lv_subrc
        ex_mess    = lv_mess
        ex_qr_code = lv_qr_code.
*
    out->write( lv_subrc ).
    IF lv_mess IS NOT INITIAL.
      out->write( lv_mess ).
    ENDIF.
    out->write( lv_qr_code ).
*
  ENDMETHOD.
*
  METHOD close_client.
*
    TRY.
        CALL METHOD im_client->close.
      CATCH cx_web_http_client_error.
    ENDTRY.
    FREE im_client.
*
  ENDMETHOD.
*
  METHOD generate_qr_code.
*
    DATA: lo_client      TYPE REF TO if_web_http_client,
          lo_response    TYPE REF TO if_web_http_response,
          lo_destination TYPE REF TO if_http_destination,
          lo_request     TYPE REF TO if_web_http_request,
          lo_resp_status TYPE if_web_http_response=>http_status,
          lv_http_rc     TYPE i,
          lv_response    TYPE string,
          lv_json        TYPE /ui2/cl_json=>json,
          lr_data        TYPE REF TO data,
          lv_req_body    TYPE string.
*
    FIELD-SYMBOLS: <tab>   TYPE ANY TABLE,
                   <data>  TYPE data,
                   <data2> TYPE data,
                   <field> TYPE any.
*
* Setup IF_WEB_HTTP_CLIENT object
*
    TRY.
        CALL METHOD cl_http_destination_provider=>create_by_url
          EXPORTING
            i_url              = im_url
          RECEIVING
            r_http_destination = lo_destination.
      CATCH cx_http_dest_provider_error.
        ex_mess = 'Error creating HTTP destination object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        cl_web_http_client_manager=>create_by_http_destination(
          EXPORTING
            i_destination = lo_destination
          RECEIVING
            r_client      = lo_client
        ).
      CATCH cx_web_http_client_error.
        ex_mess = 'Error creating HTTP client object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Get Request object
*
    lo_client->get_http_request(
      RECEIVING
        r_http_request = lo_request ).
*
* Set protocol version
*
    lo_request->set_version( if_web_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'Accept'
            i_value = '*/*' ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'Content-Type'
            i_value = 'application/x-www-form-urlencoded' ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'x-api-key'
            i_value = im_api_key ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Set request body
*
    CONCATENATE: 'data=' im_data INTO lv_req_body.
*
    TRY.
        lo_request->set_text(
          EXPORTING
            i_text   = lv_req_body ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting request body. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Send request
*
    TRY.
        lo_client->execute(
          EXPORTING
            i_method   = if_web_http_client=>post
          RECEIVING
            r_response = lo_response ).
      CATCH cx_web_http_client_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'HTTP Post error. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Read the Response
*
    TRY.
        lo_response->get_status(
        RECEIVING
          r_value = lo_resp_status ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_response->get_text(
          RECEIVING
            r_value = lv_response ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    IF lo_resp_status-code NE '200'.
*
* Get error message back from Renda
*
      ex_subrc = 4.
      lv_json = lv_response.
      IF lv_json+0(1) NE '['.
        CONCATENATE '[' lv_json ']' INTO lv_json.
      ENDIF.
      lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
      IF lr_data IS BOUND.
        ASSIGN lr_data->* TO <tab>.
        LOOP AT <tab> ASSIGNING <data>.
          ASSIGN <data>->* TO <data2>.
          ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data2> TO <field>.
          IF <field> IS ASSIGNED.
            lr_data = <field>.
            ASSIGN lr_data->* TO <data2>.
            IF ex_mess IS INITIAL.
              ex_mess = <data2>.
            ELSE.
              CONCATENATE ex_mess ' \ ' <data2> INTO ex_mess RESPECTING BLANKS.
            ENDIF.
          ENDIF.
        ENDLOOP.
      ENDIF.
*
      IF ex_mess IS INITIAL.
        ex_mess = lv_response.
      ENDIF.
*
    ELSE.
*
      TRY.
          lo_response->get_binary(
            RECEIVING
              r_value  = ex_qr_code ).
        CATCH cx_web_message_error.
          ex_mess = 'Error reading response. Process aborted'.
          ex_subrc = 4.
      ENDTRY.
*
    ENDIF.
*
    CALL METHOD close_client
      CHANGING
        im_client = lo_client.
*
  ENDMETHOD.
*
ENDCLASS.
```

{% endtab %}
{% endtabs %}

### Onboard user for TOTP

{% tabs %}
{% tab title="ABAP" %}

```java
CLASS zonboard_user DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .
*
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
    METHODS: onboard_user
      IMPORTING
        VALUE(im_url)            TYPE  string
        VALUE(im_api_key)        TYPE  string
        VALUE(im_user_id)        TYPE  string
        VALUE(im_application_id) TYPE  string
        VALUE(im_token_validity) TYPE  string OPTIONAL
        VALUE(im_token_length)   TYPE  string OPTIONAL
      EXPORTING
        VALUE(ex_secret_key)     TYPE  string
        VALUE(ex_otp_url)        TYPE  string
        VALUE(ex_qr_code)        TYPE  string
        VALUE(ex_token)          TYPE  string
        VALUE(ex_mess)           TYPE  string
        VALUE(ex_subrc)          TYPE  sysubrc,
*
      close_client
        CHANGING
          im_client TYPE REF TO if_web_http_client.
*
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.
*
CLASS zonboard_user IMPLEMENTATION.
*
  METHOD if_oo_adt_classrun~main.
*
    DATA: lv_subrc      TYPE sysubrc,
          lv_mess       TYPE string,
          lv_secret_key TYPE string,
          lv_otp_url    TYPE string,
          lv_qr_code    TYPE string,
          lv_token      TYPE string.
*
    CALL METHOD onboard_user
      EXPORTING
        im_url            = 'https://api-eu.renda.io/totp/onboardUser'
        im_api_key        = '<your API key>'
        im_user_id        = 'johnSmith@gmail.com'
        im_application_id = 'Renda.io'
        im_token_validity = '120'
        im_token_length   = '7'
      IMPORTING
        ex_secret_key     = lv_secret_key
        ex_otp_url        = lv_otp_url
        ex_qr_code        = lv_qr_code
        ex_token          = lv_token
        ex_mess           = lv_mess
        ex_subrc          = lv_subrc.
*
    out->write( lv_subrc ).
    IF lv_mess IS NOT INITIAL.
      out->write( lv_mess ).
    ENDIF.
    out->write( lv_secret_key ).
    out->write( lv_otp_url ).
    out->write( lv_qr_code ).
    out->write( lv_token ).
*
  ENDMETHOD.
*
  METHOD close_client.
*
    TRY.
        CALL METHOD im_client->close.
      CATCH cx_web_http_client_error.
    ENDTRY.
    FREE im_client.
*
  ENDMETHOD.
*
  METHOD onboard_user.
*
    TYPES: BEGIN OF ltyp_response,
             secretkey TYPE string,
             otpurl    TYPE string,
             qrcode    TYPE string,
             token     TYPE string,
           END OF ltyp_response.
*
    DATA: lo_client      TYPE REF TO if_web_http_client,
          lo_response    TYPE REF TO if_web_http_response,
          lo_destination TYPE REF TO if_http_destination,
          lo_request     TYPE REF TO if_web_http_request,
          lo_resp_status TYPE if_web_http_response=>http_status,
          lv_http_rc     TYPE i,
          lv_response    TYPE string,
          lv_json        TYPE /ui2/cl_json=>json,
          lr_data        TYPE REF TO data,
          lv_req_body    TYPE string,
          ls_response    TYPE ltyp_response.
*
    FIELD-SYMBOLS: <tab>   TYPE ANY TABLE,
                   <data>  TYPE data,
                   <data2> TYPE data,
                   <field> TYPE any.
*
* Setup IF_WEB_HTTP_CLIENT object
*
    TRY.
        CALL METHOD cl_http_destination_provider=>create_by_url
          EXPORTING
            i_url              = im_url
          RECEIVING
            r_http_destination = lo_destination.
      CATCH cx_http_dest_provider_error.
        ex_mess = 'Error creating HTTP destination object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        cl_web_http_client_manager=>create_by_http_destination(
          EXPORTING
            i_destination = lo_destination
          RECEIVING
            r_client      = lo_client
        ).
      CATCH cx_web_http_client_error.
        ex_mess = 'Error creating HTTP client object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Get Request object
*
    lo_client->get_http_request(
      RECEIVING
        r_http_request = lo_request ).
*
* Set protocol version
*
    lo_request->set_version( if_web_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'Content-Type'
            i_value = 'application/x-www-form-urlencoded' ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'x-api-key'
            i_value = im_api_key ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Set request body
*
    CONCATENATE: 'userID=' im_user_id '&applicationID=' im_application_id INTO lv_req_body.
    IF im_token_validity IS NOT INITIAL.
      CONCATENATE lv_req_body '&tokenValidity=' im_token_validity INTO lv_req_body.
    ENDIF.
    IF im_token_length IS NOT INITIAL.
      CONCATENATE lv_req_body '&tokenLength=' im_token_length INTO lv_req_body.
    ENDIF.
*
    TRY.
        lo_request->set_text(
          EXPORTING
            i_text   = lv_req_body ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting request body. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Send request
*
    TRY.
        lo_client->execute(
          EXPORTING
            i_method   = if_web_http_client=>post
          RECEIVING
            r_response = lo_response ).
      CATCH cx_web_http_client_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'HTTP Post error. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Read the Response
*
    TRY.
        lo_response->get_status(
        RECEIVING
          r_value = lo_resp_status ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_response->get_text(
          RECEIVING
            r_value = lv_response ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    IF lo_resp_status-code NE '200'.
*
* Get error message back from Renda
*
      ex_subrc = 4.
      lv_json = lv_response.
      IF lv_json+0(1) NE '['.
        CONCATENATE '[' lv_json ']' INTO lv_json.
      ENDIF.
      lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
      IF lr_data IS BOUND.
        ASSIGN lr_data->* TO <tab>.
        LOOP AT <tab> ASSIGNING <data>.
          ASSIGN <data>->* TO <data2>.
          ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data2> TO <field>.
          IF <field> IS ASSIGNED.
            lr_data = <field>.
            ASSIGN lr_data->* TO <data2>.
            IF ex_mess IS INITIAL.
              ex_mess = <data2>.
            ELSE.
              CONCATENATE ex_mess ' \ ' <data2> INTO ex_mess RESPECTING BLANKS.
            ENDIF.
          ENDIF.
        ENDLOOP.
      ENDIF.
*
      IF ex_mess IS INITIAL.
        ex_mess = lv_response.
      ENDIF.
*
    ELSE.
*
      /ui2/cl_json=>deserialize( EXPORTING json = lv_response pretty_name = /ui2/cl_json=>pretty_mode-camel_case CHANGING data = ls_response ).
      ex_secret_key = ls_response-secretkey.
      ex_otp_url = ls_response-otpurl.
      ex_qr_code = ls_response-qrcode.
      ex_token = ls_response-token.
*
    ENDIF.
*
    CALL METHOD close_client
      CHANGING
        im_client = lo_client.
*
  ENDMETHOD.
*
ENDCLASS.
```

{% endtab %}
{% endtabs %}

### Validate OTP using secret key

{% tabs %}
{% tab title="ABAP" %}

```java
CLASS zverify_otp DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .
*
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
    METHODS: verify_otp
      IMPORTING
        VALUE(im_url)            TYPE  string
        VALUE(im_api_key)        TYPE  string
        VALUE(im_secret)         TYPE  string
        VALUE(im_token)          TYPE  string
        VALUE(im_token_validity) TYPE  string OPTIONAL
      EXPORTING
        VALUE(ex_is_valid)       TYPE  abap_boolean
        VALUE(ex_token)          TYPE  string
        VALUE(ex_time_used)      TYPE  string
        VALUE(ex_time_remaining) TYPE  string
        VALUE(ex_mess)           TYPE  string
        VALUE(ex_subrc)          TYPE  sysubrc,
*
      close_client
        CHANGING
          im_client TYPE REF TO if_web_http_client.
*
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.
*
CLASS zverify_otp IMPLEMENTATION.
*
  METHOD if_oo_adt_classrun~main.
*
    DATA: lv_subrc          TYPE sysubrc,
          lv_mess           TYPE string,
          lv_is_valid       TYPE abap_boolean,
          lv_token          TYPE string,
          lv_time_used      TYPE string,
          lv_time_remaining TYPE string.
*
    CALL METHOD verify_otp
      EXPORTING
        im_url            = 'https://api-eu.renda.io/totp/verifyOTP'
        im_api_key        = '<your API key>'
        im_secret         = '<secret>'
        im_token          = '<token>'
        im_token_validity = '120'
      IMPORTING
        ex_is_valid       = lv_is_valid
        ex_token          = lv_token
        ex_time_used      = lv_time_used
        ex_time_remaining = lv_time_remaining
        ex_mess           = lv_mess
        ex_subrc          = lv_subrc.
*
    out->write( lv_subrc ).
    IF lv_mess IS NOT INITIAL.
      out->write( lv_mess ).
    ENDIF.
    IF lv_subrc IS INITIAL.
      IF lv_is_valid IS INITIAL.
        out->write( 'Token is not valid' ).
      ELSE.
        out->write( 'Token is valid' ).
      ENDIF.
    ENDIF.
    out->write( lv_token ).
    out->write( lv_time_used ).
    out->write( lv_time_remaining ).
*
  ENDMETHOD.
*
  METHOD close_client.
*
    TRY.
        CALL METHOD im_client->close.
      CATCH cx_web_http_client_error.
    ENDTRY.
    FREE im_client.
*
  ENDMETHOD.
*
  METHOD verify_otp.
*
    TYPES: BEGIN OF ltyp_response,
             isvalid       TYPE abap_boolean,
             token         TYPE string,
             timeused      TYPE string,
             timeremaining TYPE string,
           END OF ltyp_response.
*
    DATA: lo_client      TYPE REF TO if_web_http_client,
          lo_response    TYPE REF TO if_web_http_response,
          lo_destination TYPE REF TO if_http_destination,
          lo_request     TYPE REF TO if_web_http_request,
          lo_resp_status TYPE if_web_http_response=>http_status,
          lv_http_rc     TYPE i,
          lv_response    TYPE string,
          lv_json        TYPE /ui2/cl_json=>json,
          lr_data        TYPE REF TO data,
          lv_req_body    TYPE string,
          ls_response    TYPE ltyp_response.
*
    FIELD-SYMBOLS: <tab>   TYPE ANY TABLE,
                   <data>  TYPE data,
                   <data2> TYPE data,
                   <field> TYPE any.
*
* Setup IF_WEB_HTTP_CLIENT object
*
    TRY.
        CALL METHOD cl_http_destination_provider=>create_by_url
          EXPORTING
            i_url              = im_url
          RECEIVING
            r_http_destination = lo_destination.
      CATCH cx_http_dest_provider_error.
        ex_mess = 'Error creating HTTP destination object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        cl_web_http_client_manager=>create_by_http_destination(
          EXPORTING
            i_destination = lo_destination
          RECEIVING
            r_client      = lo_client
        ).
      CATCH cx_web_http_client_error.
        ex_mess = 'Error creating HTTP client object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Get Request object
*
    lo_client->get_http_request(
      RECEIVING
        r_http_request = lo_request ).
*
* Set protocol version
*
    lo_request->set_version( if_web_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'Content-Type'
            i_value = 'application/x-www-form-urlencoded' ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'x-api-key'
            i_value = im_api_key ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Set request body
*
    CONCATENATE: 'secret=' im_secret '&token=' im_token INTO lv_req_body.
    IF im_token_validity IS NOT INITIAL.
      CONCATENATE lv_req_body '&tokenDuration=' im_token_validity INTO lv_req_body.
    ENDIF.
*
    TRY.
        lo_request->set_text(
          EXPORTING
            i_text   = lv_req_body ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting request body. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Send request
*
    TRY.
        lo_client->execute(
          EXPORTING
            i_method   = if_web_http_client=>post
          RECEIVING
            r_response = lo_response ).
      CATCH cx_web_http_client_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        "ex_mess = 'HTTP Post error. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Read the Response
*
    TRY.
        lo_response->get_status(
        RECEIVING
          r_value = lo_resp_status ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_response->get_text(
          RECEIVING
            r_value = lv_response ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    IF lo_resp_status-code NE '200'.
*
* Get error message back from Renda
*
      ex_subrc = 4.
      lv_json = lv_response.
      IF lv_json+0(1) NE '['.
        CONCATENATE '[' lv_json ']' INTO lv_json.
      ENDIF.
      lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
      IF lr_data IS BOUND.
        ASSIGN lr_data->* TO <tab>.
        LOOP AT <tab> ASSIGNING <data>.
          ASSIGN <data>->* TO <data2>.
          ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data2> TO <field>.
          IF <field> IS ASSIGNED.
            lr_data = <field>.
            ASSIGN lr_data->* TO <data2>.
            IF ex_mess IS INITIAL.
              ex_mess = <data2>.
            ELSE.
              CONCATENATE ex_mess ' \ ' <data2> INTO ex_mess RESPECTING BLANKS.
            ENDIF.
          ENDIF.
        ENDLOOP.
      ENDIF.
*
      IF ex_mess IS INITIAL.
        ex_mess = lv_response.
      ENDIF.
*
    ELSE.
*
      /ui2/cl_json=>deserialize( EXPORTING json = lv_response pretty_name = /ui2/cl_json=>pretty_mode-camel_case CHANGING data = ls_response ).
      ex_is_valid = ls_response-isvalid.
      ex_token = ls_response-token.
      ex_time_used = ls_response-timeused.
      ex_time_remaining = ls_response-timeremaining.
*
    ENDIF.
*
    CALL METHOD close_client
      CHANGING
        im_client = lo_client.
*
  ENDMETHOD.
*
ENDCLASS.
```

{% endtab %}
{% endtabs %}

### Retrieve OTP for a secret key

{% tabs %}
{% tab title="ABAP" %}

```java
CLASS zget_otp DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .
*
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
    METHODS: get_otp
      IMPORTING
        VALUE(im_url)            TYPE  string
        VALUE(im_api_key)        TYPE  string
        VALUE(im_secret)         TYPE  string
        VALUE(im_token_validity) TYPE  string OPTIONAL
        VALUE(im_token_length)   TYPE  string OPTIONAL
      EXPORTING
        VALUE(ex_current_token)  TYPE  string
        VALUE(ex_time_used)      TYPE  string
        VALUE(ex_time_remaining) TYPE  string
        VALUE(ex_previous_token) TYPE  string
        VALUE(ex_next_token)     TYPE  string
        VALUE(ex_subrc)          TYPE  sysubrc
        VALUE(ex_mess)           TYPE  string,
*
      close_client
        CHANGING
          im_client TYPE REF TO if_web_http_client.
*
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.
*
CLASS zget_otp IMPLEMENTATION.
*
  METHOD if_oo_adt_classrun~main.
*
    DATA: lv_subrc          TYPE sysubrc,
          lv_mess           TYPE string,
          lv_current_token  TYPE string,
          lv_time_used      TYPE string,
          lv_time_remaining TYPE string,
          lv_previous_token TYPE string,
          lv_next_token     TYPE string.
*
    CALL METHOD get_otp
      EXPORTING
        im_url            = 'https://api-eu.renda.io/totp/getOTP'
        im_api_key        = '<your API key>'
        im_secret         = '<your secret>'
        im_token_validity = '120'
        im_token_length   = '7'
      IMPORTING
        ex_current_token  = lv_current_token
        ex_time_used      = lv_time_used
        ex_time_remaining = lv_time_remaining
        ex_previous_token = lv_previous_token
        ex_next_token     = lv_next_token
        ex_subrc          = lv_subrc
        ex_mess           = lv_mess.
*
    out->write( lv_subrc ).
    IF lv_mess IS NOT INITIAL.
      out->write( lv_mess ).
    ENDIF.
    out->write( lv_current_token ).
    out->write( lv_time_used ).
    out->write( lv_time_remaining ).
    out->write( lv_previous_token ).
    out->write( lv_next_token ).
*
  ENDMETHOD.
*
  METHOD close_client.
*
    TRY.
        CALL METHOD im_client->close.
      CATCH cx_web_http_client_error.
    ENDTRY.
    FREE im_client.
*
  ENDMETHOD.
*
  METHOD get_otp.
*
    TYPES: BEGIN OF ltyp_response,
             currenttoken  TYPE string,
             timeused      TYPE string,
             timeremaining TYPE string,
             previoustoken TYPE string,
             nexttoken     TYPE string,
           END OF ltyp_response.
*
    DATA: lo_client      TYPE REF TO if_web_http_client,
          lo_response    TYPE REF TO if_web_http_response,
          lo_destination TYPE REF TO if_http_destination,
          lo_request     TYPE REF TO if_web_http_request,
          lo_resp_status TYPE if_web_http_response=>http_status,
          lv_http_rc     TYPE i,
          lv_response    TYPE string,
          lv_json        TYPE /ui2/cl_json=>json,
          lr_data        TYPE REF TO data,
          lv_req_body    TYPE string,
          ls_response    TYPE ltyp_response.
*
    FIELD-SYMBOLS: <tab>   TYPE ANY TABLE,
                   <data>  TYPE data,
                   <data2> TYPE data,
                   <field> TYPE any.
*
* Setup IF_WEB_HTTP_CLIENT object
*
    TRY.
        CALL METHOD cl_http_destination_provider=>create_by_url
          EXPORTING
            i_url              = im_url
          RECEIVING
            r_http_destination = lo_destination.
      CATCH cx_http_dest_provider_error.
        ex_mess = 'Error creating HTTP destination object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        cl_web_http_client_manager=>create_by_http_destination(
          EXPORTING
            i_destination = lo_destination
          RECEIVING
            r_client      = lo_client
        ).
      CATCH cx_web_http_client_error.
        ex_mess = 'Error creating HTTP client object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Get Request object
*
    lo_client->get_http_request(
      RECEIVING
        r_http_request = lo_request ).
*
* Set protocol version
*
    lo_request->set_version( if_web_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'Content-Type'
            i_value = 'application/x-www-form-urlencoded' ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'x-api-key'
            i_value = im_api_key ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Set request body
*
    CONCATENATE: 'secret=' im_secret INTO lv_req_body.
    IF im_token_validity IS NOT INITIAL.
      CONCATENATE lv_req_body '&tokenValidity=' im_token_validity INTO lv_req_body.
    ENDIF.
    IF im_token_length IS NOT INITIAL.
      CONCATENATE lv_req_body '&tokenLength=' im_token_length INTO lv_req_body.
    ENDIF.
*
    TRY.
        lo_request->set_text(
          EXPORTING
            i_text   = lv_req_body ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting request body. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Send request
*
    TRY.
        lo_client->execute(
          EXPORTING
            i_method   = if_web_http_client=>post
          RECEIVING
            r_response = lo_response ).
      CATCH cx_web_http_client_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'HTTP Post error. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Read the Response
*
    TRY.
        lo_response->get_status(
        RECEIVING
          r_value = lo_resp_status ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_response->get_text(
          RECEIVING
            r_value = lv_response ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    IF lo_resp_status-code NE '200'.
*
* Get error message back from Renda
*
      ex_subrc = 4.
      lv_json = lv_response.
      IF lv_json+0(1) NE '['.
        CONCATENATE '[' lv_json ']' INTO lv_json.
      ENDIF.
      lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
      IF lr_data IS BOUND.
        ASSIGN lr_data->* TO <tab>.
        LOOP AT <tab> ASSIGNING <data>.
          ASSIGN <data>->* TO <data2>.
          ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data2> TO <field>.
          IF <field> IS ASSIGNED.
            lr_data = <field>.
            ASSIGN lr_data->* TO <data2>.
            IF ex_mess IS INITIAL.
              ex_mess = <data2>.
            ELSE.
              CONCATENATE ex_mess ' \ ' <data2> INTO ex_mess RESPECTING BLANKS.
            ENDIF.
          ENDIF.
        ENDLOOP.
      ENDIF.
*
      IF ex_mess IS INITIAL.
        ex_mess = lv_response.
      ENDIF.
*
    ELSE.
*
      /ui2/cl_json=>deserialize( EXPORTING json = lv_response pretty_name = /ui2/cl_json=>pretty_mode-camel_case CHANGING data = ls_response ).
      ex_current_token = ls_response-currenttoken.
      ex_time_used = ls_response-timeused.
      ex_time_remaining = ls_response-timeremaining.
      ex_previous_token = ls_response-previoustoken.
      ex_next_token = ls_response-nexttoken.
*
*
    ENDIF.
*
    CALL METHOD close_client
      CHANGING
        im_client = lo_client.
*
  ENDMETHOD.
*
ENDCLASS.
```

{% endtab %}
{% endtabs %}

### Send SMS&#x20;

{% tabs %}
{% tab title="ABAP" %}

```java
CLASS zsend_sms DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .
*
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
    METHODS: send_sms
      IMPORTING
        VALUE(im_url)         TYPE  string
        VALUE(im_api_key)     TYPE  string
        VALUE(im_number)      TYPE  string
        VALUE(im_message)     TYPE  string
        VALUE(im_sender_name) TYPE  string OPTIONAL
      EXPORTING
        VALUE(ex_subrc)       TYPE  sysubrc
        VALUE(ex_mess)        TYPE  string,
*
      close_client
        CHANGING
          im_client TYPE REF TO if_web_http_client.
*
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.
*
CLASS zsend_sms IMPLEMENTATION.
*
  METHOD if_oo_adt_classrun~main.
*
    DATA: lv_subrc TYPE sysubrc,
          lv_mess  TYPE string.
*
    CALL METHOD send_sms
      EXPORTING
        im_url         = 'https://api-eu.renda.io/communication/sendSMS'
        im_api_key     = '<your api key>'
        im_number      = '<mobile number>'
        im_message     = 'Hello world'
        im_sender_name = 'Renda.io'
      IMPORTING
        ex_mess        = lv_mess
        ex_subrc       = lv_subrc.
*
    out->write( lv_subrc ).
    IF lv_mess IS NOT INITIAL.
      out->write( lv_mess ).
    ENDIF.
*
  ENDMETHOD.
*
  METHOD close_client.
*
    TRY.
        CALL METHOD im_client->close.
      CATCH cx_web_http_client_error.
    ENDTRY.
    FREE im_client.
*
  ENDMETHOD.
*
  METHOD send_sms.
*
    TYPES: BEGIN OF ltyp_response,
             secretkey TYPE string,
             otpurl    TYPE string,
             qrcode    TYPE string,
             token     TYPE string,
           END OF ltyp_response.
*
    DATA: lo_client      TYPE REF TO if_web_http_client,
          lo_response    TYPE REF TO if_web_http_response,
          lo_destination TYPE REF TO if_http_destination,
          lo_request     TYPE REF TO if_web_http_request,
          lo_resp_status TYPE if_web_http_response=>http_status,
          lv_http_rc     TYPE i,
          lv_response    TYPE string,
          lv_json        TYPE /ui2/cl_json=>json,
          lr_data        TYPE REF TO data,
          lv_req_body    TYPE string,
          ls_response    TYPE ltyp_response.
*
    FIELD-SYMBOLS: <tab>   TYPE ANY TABLE,
                   <data>  TYPE data,
                   <data2> TYPE data,
                   <field> TYPE any.
*
* Setup IF_WEB_HTTP_CLIENT object
*
    TRY.
        CALL METHOD cl_http_destination_provider=>create_by_url
          EXPORTING
            i_url              = im_url
          RECEIVING
            r_http_destination = lo_destination.
      CATCH cx_http_dest_provider_error.
        ex_mess = 'Error creating HTTP destination object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        cl_web_http_client_manager=>create_by_http_destination(
          EXPORTING
            i_destination = lo_destination
          RECEIVING
            r_client      = lo_client
        ).
      CATCH cx_web_http_client_error.
        ex_mess = 'Error creating HTTP client object. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Get Request object
*
    lo_client->get_http_request(
      RECEIVING
        r_http_request = lo_request ).
*
* Set protocol version
*
    lo_request->set_version( if_web_http_request=>co_protocol_version_1_1 ).
*
* Set request header fields
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'Content-Type'
            i_value = 'application/x-www-form-urlencoded' ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_request->set_header_field(
          EXPORTING
            i_name  = 'x-api-key'
            i_value = im_api_key ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting header field. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Set request body
*
    CONCATENATE: 'number=' im_number '&message=' im_message INTO lv_req_body.
    IF im_sender_name IS NOT INITIAL.
      CONCATENATE lv_req_body '&senderName=' im_sender_name INTO lv_req_body.
    ENDIF.
*
    TRY.
        lo_request->set_text(
          EXPORTING
            i_text   = lv_req_body ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error setting request body. Process aborted.'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Send request
*
    TRY.
        lo_client->execute(
          EXPORTING
            i_method   = if_web_http_client=>post
          RECEIVING
            r_response = lo_response ).
      CATCH cx_web_http_client_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'HTTP Post error. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
* Read the Response
*
    TRY.
        lo_response->get_status(
        RECEIVING
          r_value = lo_resp_status ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    TRY.
        lo_response->get_text(
          RECEIVING
            r_value = lv_response ).
      CATCH cx_web_message_error.
        CALL METHOD close_client
          CHANGING
            im_client = lo_client.
        ex_mess = 'Error reading response. Process aborted'.
        ex_subrc = 4.
        RETURN.
    ENDTRY.
*
    IF lo_resp_status-code NE '200'.
*
* Get error message back from Renda
*
      ex_subrc = 4.
      lv_json = lv_response.
      IF lv_json+0(1) NE '['.
        CONCATENATE '[' lv_json ']' INTO lv_json.
      ENDIF.
      lr_data = /ui2/cl_json=>generate( json = lv_json ).
*
      IF lr_data IS BOUND.
        ASSIGN lr_data->* TO <tab>.
        LOOP AT <tab> ASSIGNING <data>.
          ASSIGN <data>->* TO <data2>.
          ASSIGN COMPONENT 'MESSAGE' OF STRUCTURE <data2> TO <field>.
          IF <field> IS ASSIGNED.
            lr_data = <field>.
            ASSIGN lr_data->* TO <data2>.
            IF ex_mess IS INITIAL.
              ex_mess = <data2>.
            ELSE.
              CONCATENATE ex_mess ' \ ' <data2> INTO ex_mess RESPECTING BLANKS.
            ENDIF.
          ENDIF.
        ENDLOOP.
      ENDIF.
*
      IF ex_mess IS INITIAL.
        ex_mess = lv_response.
      ENDIF.
*
    ENDIF.
*
    CALL METHOD close_client
      CHANGING
        im_client = lo_client.
*
  ENDMETHOD.
*
ENDCLASS.
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://documentation.renda.io/code-samples/abap-code-samples-cloud.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
