[ABAP] Google-API: QR-Code generieren und Bild herunterladen/speichern

* Dateiname der Bilddatei zum hochladen
PARAMETERS: p_fname TYPE file_table-filename OBLIGATORY.

START-OF-SELECTION.
* URL zur Google-API für die Erstellung des QR-Codes
  DATA(lv_url) = |http://chart.apis.google.com/chart?chs=200x200&cht=qr&chld=\|1&chl=viele%20lustige%20Zeichen/chart.png|.

  TRY.
      DATA: o_client TYPE REF TO if_http_client.
* Client-Objekt erzeugen
      cl_http_client=>create_by_url( EXPORTING
                                       url     = lv_url
                                     IMPORTING
                                       client  = o_client ).
      IF sy-subrc = 0.
* HTTP GET senden
        o_client->send( ).

* Response lesen
        o_client->receive( ).

        DATA: lv_http_status TYPE i.
        DATA: lv_status_text TYPE string.

* HTTP Return Code holen
        o_client->response->get_status( IMPORTING
                                          code   = lv_http_status
                                          reason = lv_status_text ).

* Wenn Status 200 (Ok)
        IF lv_http_status = 200.

* Binärdaten (QR-Code) auslesen
          DATA(lv_xdata) = o_client->response->get_data( ).

          o_client->close( ).

* xstring -> solix
          DATA(it_img_conv_data) = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_xdata ).

          WRITE: / |{ p_fname }.png|.

* Image lokal speichern
          cl_gui_frontend_services=>gui_download( EXPORTING
                                                    filename     = |{ p_fname }.png|
                                                    filetype     = 'BIN'
                                                    bin_filesize = xstrlen( lv_xdata )
                                                  CHANGING
                                                    data_tab     = it_img_conv_data ).

        ENDIF.
      ENDIF.
    CATCH cx_root INTO DATA(e_txt).
      WRITE: / e_txt->get_text( ).
  ENDTRY.

[JavaScript] JSON-Datei per HTTP-Request holen und parsen

// Link zur JSON-Datei
let sURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';
// Request-Object
let request = new XMLHttpRequest();
// MIME-Typen
// txt: "text/plain"
// html: "text/html"
// json: "application/json"
request.overrideMimeType('application/json');
// Requestmethode
request.open('GET', sURL, true);
// Datentyp
request.responseType = 'text';
// Handler für asyncrone Antwort des Requests
// wenn Daten erfolgreich geladen
request.onload = function() {
  console.log('onload()');
  // gesamte Response ausgeben
  let sJSON = request.response;
  console.log(sJSON);
  
  // JSON-Daten parsen
  let oJSON = JSON.parse(sJSON);
  // Wert eines Attributes ausgeben
  console.log(oJSON.homeTown);
};
// bei Änderung des Ready-States
request.onreadystatechange = function () {
  console.log('onreadystatechange()');
  console.log(request.readyState);
  console.log(request.status);
  console.log(request.statusText);
};
// Request absenden
request.send();

[ABAP] HTML-Email versenden

DATA: lv_recipient TYPE adr6-smtp_addr.
DATA: lv_subject TYPE string.

lv_recipient = 'email@email.com'.
lv_subject = 'Testemail'.

DATA(lv_html_text) = VALUE string( ).

lv_html_text = |<BODY> | &&
               |<P><B>Test</B></BR>| &&
               |</BODY>|.

DATA(it_body_txt) = cl_document_bcs=>string_to_soli( ip_string = lv_html_text ).

TRY.
* it_body_txt beinhaltet die Zeilen des Body-Textes
* die Zeilen sind jeweils char255 Zeichen lang
* eine Zeile (line) ist vom Typ SOLI

* Document (Mail) erzeugen
* Email-Subject (i_subject) darf hier max. 50 Zeichen lang sein (Subject-Darstellung in der SOST)
* die "richtige" Übergabe des Email-Subjects erfolgt weiter unten in der Funktion set_message_subject( )
    DATA(o_document) = cl_document_bcs=>create_document( i_type    = 'HTM'
                                                         i_text    = it_body_txt
                                                         i_subject = CONV so_obj_des( lv_subject ) ).

* Sendrequest erzeugen
    DATA(o_send_request) = cl_bcs=>create_persistent( ).
* Email-Subject festlegen, ip_subject ist vom Typ String
    o_send_request->set_message_subject( ip_subject = lv_subject ).
* Die Mail an den Sendrequest hängen
    o_send_request->set_document( o_document ).

* SAP-User als Sender
    DATA(o_sender) = cl_sapuser_bcs=>create( sy-uname ).
* Email-Adresse als Sender
*        DATA(o_sender) = cl_cam_address_bcs=>create_internet_address( i_address_string = 'email@email.com' ).
    o_send_request->set_sender( o_sender ).

* Empfänger -> beachte: u.U. sind Email-Adressen mit Umlauten nicht zulässig -> Exception
    DATA(o_recipient) = cl_cam_address_bcs=>create_internet_address( lv_recipient ).
    o_send_request->add_recipient( i_recipient = o_recipient
                                   i_express = abap_true
                                 " i_copy      = abap_true " CC
                                 " i_blind_copy = abap_true " BCC
                                 ).

* Sofort senden
    o_send_request->set_send_immediately( abap_true ).

* Dokument senden
    IF o_send_request->send( i_with_error_screen = abap_true ) = abap_true.
      WRITE: / 'Email gesendet.'.
    ELSE.
      WRITE: / 'Fehler beim Email-Versand.'.
    ENDIF.

    DATA: lv_in_update_task TYPE sy-subrc.

* Überprüft, ob das Programm im Verbucher abläuft
    CALL FUNCTION 'TH_IN_UPDATE_TASK'
      IMPORTING
        in_update_task = lv_in_update_task.

    IF lv_in_update_task EQ 0.
* Persistenzdienste des Objektes starten, sonst wird ggf. die Mail nicht gesendet
      COMMIT WORK.
    ENDIF.

  CATCH cx_root INTO DATA(e_text).
    WRITE: / e_text->get_text( ).
ENDTRY.

[ABAP] HTTP-Client Anfrage (cl_http_client)

Testprogramm: RSHTTP20

Variante 1 (URL)

TRY.
* URL
    DATA(lv_url) = |https://www.google.de/|.

    DATA: o_client TYPE REF TO if_http_client.

* Client-Objekt erzeugen
    cl_http_client=>create_by_url( EXPORTING
                                     url     = lv_url
                                   IMPORTING
                                     client  = o_client ).

    IF o_client IS BOUND.
* Anmeldedaten übermitteln
      o_client->authenticate( username = ''
                              password = '' ).

* Logon-Popup ein- bzw. ausschalten
      o_client->propertytype_logon_popup = o_client->co_enabled.

* HTTP-Prtotokoll-Version
      o_client->request->set_version( version = if_http_request=>co_protocol_version_1_1 ).
* HTTP-Method
      o_client->request->set_method( if_http_request=>co_request_method_get ).

* Header-Felder explizit setzen
*      o_client->request->set_header_field( name  = '~request_method'
*                                           value = 'GET' ).
*
*      o_client->request->set_header_field( name  = 'Content-Type'
*                                           value = 'text/xml; charset=utf-8' ).
*
*      o_client->request->set_header_field( name  = 'Accept'
*                                           value = 'text/xml, text/html' ).

* Cookies akzeptieren
      o_client->propertytype_accept_cookie = if_http_client=>co_enabled.
* Kompression akzeptieren
      o_client->propertytype_accept_compress = if_http_client=>co_enabled.

* HTTP GET senden, evtl. Timeout angeben
      o_client->send( timeout = if_http_client=>co_timeout_default ).

* Response lesen
      o_client->receive( ).

      DATA: lv_http_status TYPE i.
      DATA: lv_status_text TYPE string.

* HTTP Return Code holen
      o_client->response->get_status( IMPORTING
                                        code   = lv_http_status
                                        reason = lv_status_text ).

      WRITE: / 'HTTP_STATUS_CODE:', lv_http_status.
      WRITE: / 'STATUS_TEXT:', lv_status_text.

* Header-Daten der Übertragung
      WRITE: / 'HEADER_FIELDS:'.
      DATA(it_header_fields) = VALUE tihttpnvp( ).
      o_client->response->get_header_fields( CHANGING fields = it_header_fields ).

      LOOP AT it_header_fields ASSIGNING FIELD-SYMBOL(<f>).
        WRITE: / '[', <f>-name, ']', <f>-value.
      ENDLOOP.

* Cookies holen
      WRITE: / 'COOKIES:'.
      DATA(it_cookies) = VALUE tihttpcki( ).
      o_client->response->get_cookies( CHANGING cookies = it_cookies ).

      LOOP AT it_cookies ASSIGNING FIELD-SYMBOL(<c>).
        WRITE: / '[', <c>-name, ']', <c>-value, <c>-xdomain, <c>-path, <c>-secure, <c>-expires.
      ENDLOOP.

* vollständige HTTP Nachricht lesen
      DATA(lv_raw_message) = o_client->response->get_raw_message( ).
      DATA: lv_str_msg TYPE string.

* xstring -> string
      DATA(o_conv_r) = cl_abap_conv_in_ce=>create( input    = lv_raw_message
                                                   encoding = 'UTF-8' ).

      o_conv_r->read( IMPORTING data = lv_str_msg ).

      WRITE: / 'RAW MESSAGE:', lv_str_msg.

* Wenn Status 200 (Ok)
      IF lv_http_status = 200.
* HTTP Body als Character-Daten
        DATA(lv_result) = o_client->response->get_cdata( ).

        WRITE: / 'CDATA:'.
        WRITE: / lv_result.
      ENDIF.

* HTTP Connection schließen
      o_client->close( ).
    ENDIF.
  CATCH cx_root INTO DATA(e_txt).
    WRITE: / e_txt->get_text( ).
ENDTRY.

Variante 2 (HTTP-Alias)

* mit SM59 einrichten
DATA: lv_http_dest TYPE rfcdest VALUE 'HTTP_ALIAS'.

DATA: o_client TYPE REF TO if_http_client.

DATA: lv_http_rc TYPE i.
DATA: lv_reason TYPE string.

TRY.
    cl_http_client=>create_by_destination( EXPORTING
                                             destination = lv_http_dest
                                           IMPORTING
                                             client      = o_client ).

    o_client->request->set_method( if_http_request=>co_request_method_get ).

    o_client->send( ).

    o_client->receive( ).

    o_client->response->get_status( IMPORTING
                                      code   = lv_http_rc
                                      reason = lv_reason ).

    IF lv_http_rc = 200.
      DATA(lv_xml) = o_client->response->get_cdata( ).

      cl_abap_browser=>show_xml( xml_string = lv_xml
                                 title      = 'XML-Daten'
                                 size       = cl_abap_browser=>large ).
    ELSE.
      WRITE: / 'Fehler: ', lv_http_rc.
    ENDIF.

    o_client->close( ).

  CATCH cx_root INTO DATA(e_txt).
    WRITE: / e_txt->get_text( ).
ENDTRY.

[ABAP] Email mit PDF-Anhang versenden

* https://www.sapnuts.com/tutorials/Sending-email-with-attachment-in-SAP-ABAP/singlepage.html
* http://www.sapwiki.cl/wiki/index.php?title=SAP_ABAP_CORREO
* http://www.berater-wiki.de/index.php?title=PDF_per_Mail/Fax_verschicken
* https://wiki.scn.sap.com/wiki/display/ABAP/Sending+Mails+-+Home+Page?original_fqdn=wiki.sdn.sap.com#SendingMails-HomePage-CL_BCS
* http://www.apentia-forum.de/viewtopic.php?f=2&t=74925&start=0

PARAMETERS: p_email TYPE adr6-smtp_addr OBLIGATORY DEFAULT 'email@email.com'.     " Email-Adr. des Empfängers
PARAMETERS: p_subj TYPE string DEFAULT 'Testmail.'.                               " Email-Subject
PARAMETERS: p_bdytxt TYPE soli DEFAULT 'Testtext.'.                               " eine Mailtext-Zeile
PARAMETERS: p_pdf TYPE file_table-filename OBLIGATORY DEFAULT 'C:\Temp\Test.pdf'. " PDF-Anhang

* wenn die F4-Hilfe für den Dateinamen aufgerufen wird
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_pdf.
  DATA: lv_rc TYPE i.
  DATA: it_files TYPE filetable.
  DATA: lv_action TYPE i.

* File-Tabelle leeren, da hier noch alte Einträge von vorherigen
* Aufrufen drin stehen können
  CLEAR: it_files.
* FileOpen-Dialog aufrufen
  TRY.
      cl_gui_frontend_services=>file_open_dialog( EXPORTING
                                                    file_filter = |PDF (*.pdf)\|*.pdf\|{ cl_gui_frontend_services=>filetype_all }|
                                                  CHANGING
                                                    file_table  = it_files     " ausgewählte Dateien
                                                    rc          = lv_rc        " Anzahl ausgewählte Dateien, -1 bei Fehler
                                                    user_action = lv_action ).

      IF lv_action = cl_gui_frontend_services=>action_ok.
* wenn Datei ausgewählt wurde
        IF lines( it_files ) > 0.
* ersten Tabelleneintrag lesen
          p_pdf = it_files[ 1 ]-filename.
        ENDIF.
      ENDIF.
    CATCH cx_root INTO DATA(e_text).
      MESSAGE e_text->get_text( ) TYPE 'S'.
  ENDTRY.

START-OF-SELECTION.
  DATA: lv_pdf_size TYPE i.
  DATA: it_pdf_data_tab TYPE solix_tab.

  TRY.
* PDF-Datei vom lokalen Rechner auf den Appl.-Server hochladen
      cl_gui_frontend_services=>gui_upload( EXPORTING
                                              filename   = |{ p_pdf }|
                                              filetype   = 'BIN'
                                            IMPORTING
                                              filelength = lv_pdf_size
                                            CHANGING
                                              data_tab   = it_pdf_data_tab ).

      IF sy-subrc = 0.
* it_body_txt beinhaltet die Zeilen des Body-Textes
* die Zeilen sind jeweils char255 Zeichen lang
* eine Zeile (line) ist vom Typ SOLI
        DATA(it_body_txt) = VALUE soli_tab( ( line = p_bdytxt ) ).

* Document (Mail) erzeugen
* Email-Subject (i_subject) darf hier max. 50 Zeichen lang sein (Subject-Darstellung in der SOST)
* die "richtige" Übergabe des Email-Subjects erfolgt weiter unten in der Funktion set_message_subject( )
        DATA(o_document) = cl_document_bcs=>create_document( i_type    = 'RAW'
                                                             i_text    = it_body_txt
                                                             i_subject = CONV so_obj_des( p_subj ) ).

* Attachement hinzufügen -> Typen siehe Tabelle TSOTD
* siehe auch: http://www.apentia-forum.de/viewtopic.php?f=2&t=74925&start=0
        o_document->add_attachment( i_attachment_type    = 'EXT'
                                    i_attachment_subject = |{ p_pdf }|
                                    i_att_content_hex    = it_pdf_data_tab ).

* Sendrequest erzeugen
        DATA(o_send_request) = cl_bcs=>create_persistent( ).
* Email-Subject festlegen, ip_subject ist vom Typ String
        o_send_request->set_message_subject( ip_subject = p_subj ).
* Die Mail an den Sendrequest hängen
        o_send_request->set_document( o_document ).

* Sender
* SAP-User als Sender
        DATA(o_sender) = cl_sapuser_bcs=>create( sy-uname ).
* Email-Adresse als Sender
*        DATA(o_sender) = cl_cam_address_bcs=>create_internet_address( i_address_string = 'email@email.com' ).
        o_send_request->set_sender( o_sender ).

* Empfänger -> beachte: u.U. sind Email-Adressen mit Umlauten nicht zulässig -> Exception
        DATA(o_recipient) = cl_cam_address_bcs=>create_internet_address( p_email ).
        o_send_request->add_recipient( i_recipient = o_recipient
                                       i_express = abap_true
                                     " i_copy      = abap_true " CC
                                     " i_blind_copy = abap_true " BCC
                                     ).

* Sofort senden
        o_send_request->set_send_immediately( abap_true ).

* Dokument senden
        IF o_send_request->send( i_with_error_screen = abap_true ) = abap_true.
          WRITE: / 'Email gesendet.'.
        ELSE.
          WRITE: / 'Fehler beim Email-Versand.'.
        ENDIF.

        DATA: lv_in_update_task TYPE sy-subrc.

* Überprüft, ob das Programm im Verbucher abläuft
        CALL FUNCTION 'TH_IN_UPDATE_TASK'
          IMPORTING
            in_update_task = lv_in_update_task.

        IF lv_in_update_task EQ 0.
* Persistenzdienste des Objektes starten, sonst wird ggf. die Mail nicht gesendet
          COMMIT WORK.
        ENDIF.

      ENDIF.
    CATCH cx_root INTO DATA(e_text).
      WRITE: / e_text->get_text( ).
  ENDTRY.