SAP BTP - ABAP in the cloud
Generate PDF from HTML
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.
Generate QR Code
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.
Onboard user for TOTP
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.
Validate OTP using secret key
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.
Retrieve OTP for a secret key
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.
Send SMS
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.
Last updated