
Introduction:
This blog provides an extensive overview of the steps required to implement a Scan QR functionality in a module pool program by triggering an HTML QR service with a pushbutton and returning the retrieved data to the screen after scanning, ensuring seamless integration between the SAP module pool program and the HTML QR scanning service to enable efficient QR code processing.
Steps:
Step 1: Create a class using transaction se24 and specify IF_HTTP_EXTENSION in the interface section. This class is intended to handle HTTPS requests and responses in the context of web-based applications or services, particularly custom handlers in the Internet Communication Framework.
Step 2: Declare IF_HTTP_EXTENSION~HANDLE_REQUEST in the methods section by keeping it in public visibility.
Step 3: Click on the method and go to source code to deploy the HTML QR scan code in it.
Step 4: To retrieve the HTTP request method of an incoming request in SAP's ICF (Internet Communication Framework) service, attach the below available HTML code for scan QR functionality.
METHOD IF_HTTP_EXTENSION~HANDLE_REQUEST.
DATA: lv_request_method TYPE string,
lv_html TYPE string,
lt_html_table TYPE TABLE OF string,
gv_json TYPE char250, "string,
gs_session TYPE zpp_tab_sess_id,
lv_var1 TYPE string,
lv_var2 TYPE string,
lv_var3 TYPE string,
lv_var4 TYPE string,
lv_var5 TYPE string,
lv_var6 TYPE string,
lv_var7 TYPE string,
lv_var8 TYPE string,
lv_var9 TYPE string.
lv_request_method = server->request->get_method( ).
CASE lv_request_method.
WHEN 'GET'.
CLEAR : gv_json.
lt_html_table = VALUE #(
( CONV string( '<!DOCTYPE html>' ) )
( CONV string( '<html lang="en">' ) )
( CONV string( '<head>' ) )
( CONV string( '<meta charset="UTF-8">' ) )
( CONV string( '<meta name="viewport" content="width=device-width, initial-scale=1.0">' ) )
( CONV string( '<link rel="stylesheet" href="style.css">' ) )
( CONV string( '<title>QR Code Scanner</title>' ) )
( CONV string( '<style>' ) )
( CONV string( ' .message-container {' ) )
( CONV string( ' display: flex; flex-direction: column; align-items: center; justify-content: center; margin-top: 20px;' ) )
( CONV string( ' }' ) )
( CONV string( ' #statusMessage {' ) )
( CONV string( ' text-align: center; font-size: 15px; margin-bottom: 5px;' ) )
( CONV string( ' }' ) )
( CONV string( ' #rescanButton {' ) )
( CONV string( ' display: none; margin: 0 auto; padding: 5px 10px; font-size: 10px; cursor: pointer;' ) )
( CONV string( ' }' ) )
( CONV string( '</style>' ) )
( CONV string( '</head>' ) )
( CONV string( '<body>' ) )
( CONV string( '<div class="container">' ) )
( CONV string( ' <h1>Scan QR Codes</h1>' ) )
( CONV string( ' <div class="section">' ) )
( CONV string( ' <div style="width: 500px" id="reader" name="QRCodeData"></div>' ) )
( CONV string( ' <div class="message-container">' ) )
( CONV string( ' <p id="statusMessage"></p>' ) )
( CONV string( ' <button id="rescanButton" onclick="rescan()">Rescan</button>' ) )
( CONV string( ' </div>' ) )
( CONV string( ' </div>' ) )
( CONV string( '</div>' ) )
( CONV string( '<script src="https://unpkg.com/html5-qrcode"></script>' ) )
( CONV string( '<script>' ) )
( CONV string( ' function onScanSuccess(decodedText, decodedResult) {' ) )
( CONV string( ' const barcodetxt = decodedText;' ) )
( CONV string( ' console.log(decodedText);' ) )
( CONV string( ' const urlParams = new URLSearchParams(window.location.search);' ) )
( CONV string( ' const sessionID = urlParams.get("SESSION_ID") || '''';' ) )
( CONV string( ' const port = window.location.port;' ) )
( CONV string( ' const senddata = async (barcodetxt, sessionID, port) => {' ) )
( CONV string( ' try {' ) )
( CONV string( ' const res = await fetch(`https://<server>:${port}/sap/bc/zsrv_evp_qrscan`, {' ) )
( CONV string( ' method: "POST",' ) )
( CONV string( ' headers: {' ) )
( CONV string( ' "Content-Type": "application/json"' ) )
( CONV string( ' },' ) )
( CONV string( ' body: JSON.stringify({ barcodetxt, sessionID })' ) )
( CONV string( ' });' ) )
( CONV string( ' if (res.ok) {' ) )
( CONV string( ' document.getElementById("statusMessage").innerText = "Updated Successfully!";' ) )
( CONV string( ' document.getElementById("statusMessage").style.color = "green";' ) )
( CONV string( ' setTimeout(() => {' ) )
( CONV string( ' window.open("", "_self", "");' ) )
( CONV string( ' window.close();' ) )
( CONV string( ' }, 2000);' ) )
( CONV string( ' } else {' ) )
( CONV string( ' showErrorMessage();' ) )
( CONV string( ' }' ) )
( CONV string( ' } catch (error) {' ) )
( CONV string( ' showErrorMessage();' ) )
( CONV string( ' console.error("Error updating data:", error);' ) )
( CONV string( ' }' ) )
( CONV string( ' };' ) )
( CONV string( ' senddata(barcodetxt, sessionID, port);' ) )
( CONV string( ' html5QrcodeScanner.clear();' ) )
( CONV string( ' }' ) )
( CONV string( ' function showErrorMessage() {' ) )
( CONV string( ' const statusMessage = document.getElementById("statusMessage");' ) )
( CONV string( ' statusMessage.innerText = "Request failed. Please try again.";' ) )
( CONV string( ' statusMessage.style.color = "red";' ) )
( CONV string( ' const rescanButton = document.getElementById("rescanButton");' ) )
( CONV string( ' rescanButton.style.display = "inline-block";' ) )
( CONV string( ' }' ) )
( CONV string( ' function rescan() {' ) )
( CONV string( ' document.getElementById("statusMessage").innerText = "";' ) )
( CONV string( ' document.getElementById("rescanButton").style.display = "none";' ) )
( CONV string( ' html5QrcodeScanner.render(onScanSuccess);' ) )
( CONV string( ' }' ) )
( CONV string( ' var html5QrcodeScanner = new Html5QrcodeScanner(' ) )
( CONV string( ' "reader", { fps: 10, qrbox: 250 });' ) )
( CONV string( ' html5QrcodeScanner.render(onScanSuccess);' ) )
( CONV string( '</script>' ) )
( CONV string( '</body>' ) )
( CONV string( '</html>' ) )
).
CONCATENATE LINES OF lt_html_table INTO lv_html SEPARATED BY cl_abap_char_utilities=>cr_lf.
server->response->set_cdata( lv_html ).
server->response->set_status( code = 200 reason = 'OK' ).
WHEN 'POST'.
server->request->get_cdata( RECEIVING data = gv_json ).
lv_html = gv_json.
server->response->set_content_type( 'text/html' ).
server->response->set_cdata( lv_html ).
SPLIT gv_json AT '"' INTO lv_var1 lv_var2 lv_var3 lv_var4 lv_var5
lv_var6 lv_var7 lv_var8 lv_var9.
IF lv_var4 IS NOT INITIAL AND lv_var8 IS NOT INITIAL.
gs_session = VALUE #( session_id = lv_var8
qr_value = lv_var4
created_on = sy-datum
created_at = sy-uzeit
created_by = sy-uname ).
IF gs_session IS NOT INITIAL.
MODIFY zpp_tab_sess_id FROM gs_session.
IF sy-subrc = 0.
COMMIT WORK AND WAIT.
ELSE.
ROLLBACK WORK.
ENDIF.
ENDIF.
ENDIF.
CLEAR : gv_json,gs_session.
ENDCASE.
ENDMETHOD.
Step 5: After building the logic in se24, bind the class in SICF transaction by giving hierarchy name as SERVICE.
Step 6: Create a service name in the below navigated hierarchy.
Step 7: Assign the class in which the HTML code has been embedded in the handler list of the created service by double clicking on the service.
Step 8: Create a z-table to store the session id and its data while scanning the QR to avoid the data mismatch.
Step 7: Create a pushbutton in your required screen by using module pool program and name it as Scan QR by keeping its function code as ‘SCAN’
Step 9: In the PAI part write the logic to scan the QR
Code Explanation:
9.1: cl_system_uuid=>create_uuid_c32_static( RECEIVING uuid = gv_uuid ) will be used to create GUID’s for the new session while triggering the scan pushbutton.
9.2: gc_srv refers to the service path which is created in SICF t-code along with the session ID .
9.3: gc_host is the HTTPS host link lv_post is the port for the particular server and gv_uuid is the created guid for each session.
gc_srv TYPE string VALUE '/sap/bc/zsrv_evp_qrscan?SESSION_ID=',
gv_qr TYPE char50,
gv_uuid TYPE guid_32.
gv_url TYPE char200,
WHEN 'SCAN'.
CLEAR : gv_qr, gv_uuid.
*****************To get GUID for each new session***********************
cl_system_uuid=>create_uuid_c32_static( RECEIVING uuid = gv_uuid ).
****************Changing the URL according to development and production client*******************
zcl_ril_constant=>fetch_constant_data(
EXPORTING
iv_program_name = 'EVP_PORT'
iv_field = 'PORT'
iv_active_flag = ''
IMPORTING
et_table = DATA(lt_const)
).
DATA(lv_port) = VALUE #( lt_const[ field_name = 'PORT']-zlow OPTIONAL ).
CONCATENATE gc_host lv_port gc_srv gv_uuid INTO gv_url.
********************Call Browser triggers the browser for QR scan*********************************
CALL FUNCTION 'CALL_BROWSER'
EXPORTING
url = gv_url
window_name = 'NEW'
EXCEPTIONS
frontend_not_supported = 1
frontend_error = 2
prog_not_found = 3
no_batch = 4
unspecified_error = 5
OTHERS = 6.
IF sy-subrc = 0.
CLEAR : gv_url.
MESSAGE text-069 TYPE 'I'.
ELSE.
MESSAGE text-072 TYPE 'S' DISPLAY LIKE 'E'.
ENDIF.
*******************Mapping the GUID to the Scan QR field*******************************
SELECT * FROM zpp_tab_sess_id
INTO TABLE (lt_id)
WHERE session_id = _uuid.
IF sy-subrc = 0.
DATA(lv_qr_data) = VALUE #( lt_id[ session_id = gv_uuid ]-qr_value OPTIONAL ).
IF lv_qr_data IS NOT INITIAL .
gv_qr = lv_qr_data.
ENDIF.
ELSE.
MESSAGE text-072 TYPE 'S' DISPLAY LIKE 'E'.
ENDIF.
Conclusion:
Incorporating QR Code Scanning in a SAP Module Pool with HTML Service offers easy data capture and real-time processing within the SAP GUI. Users can efficiently scan and process QR codes by embedding an HTML page in a Custom Container, using SAP SICF services, and storing scanned data through ABAP methods. This method improves user experience, eliminates human data entry, and enhances system automation.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
3 | |
3 | |
2 | |
2 | |
2 | |
2 | |
2 | |
1 | |
1 | |
1 |