Technical Articles
Printing QR Code and Digital Signature in Adobe Forms
Dear Friends,
I am writing this blog post, keeping in mind the current scenario, where we have to digitally sign e-invoices, which has both QR code and Digital signature on the same form. The problem with Digitally signing the document via the ADS server is, it removes the QR code from the form.
Introduction
SAP has given a solution for this, via note 2901700. But uses the concept of Job profiles, which works after SP-13. Please refer to note 1743567, to see how to use Job profiles.
In this blog post, we will see how we can get QR code and Digital signature on Adobe Form without using Job profiles. We will basically convert the QR code into the image (BMP) and then Digitally sign the form via ADS Server.
Before implementing the solution please check if you have SAP note 2790500 implemented in your system so that we can use class CL_RSTX_BARCODE_RENDERER. Go to SE24 and check if you have the above class in your system. If not then implement the given note for the same.
Use Case
We are creating an interactive adobe form with 2 fields QR Code and Digital Signature.
Steps
Open transaction SFP
Create Form Interface
Give Description and select interface type as ABAP Dictionary.
Create an importing parameter as IV_QRCODE of type XSTRING. This will be getting QR code image from the driver program as XSTRING. Save and activate the interface.
Create an Adobe Form
Assign Form Interface created above and give the description to the form. Save the form
Create a graphic node QR_CODE
Link Graphic node QR_CODE variable with XSTRING variable IV_QRCODE. Open design view
Create 2 fields in design view:
- Signature field (SignatureField1)
- Drag and drop QR_CODE image node
Save and Activate the form
Create Driver program for the form created via SE38 transaction (Executable Program)
Copy and paste the code given below
REPORT zqrdg_dp.
DATA :
lv_fname TYPE rs38l_fnam ,
lv_formname TYPE tdsfname VALUE 'ZQRDG_F',
ls_fpformout TYPE fpformoutput,
lo_fp TYPE REF TO if_fp,
lo_pdfobj TYPE REF TO if_fp_pdf_object,
lv_len TYPE i,
lt_tab TYPE TABLE OF solix,
lv_file_name TYPE string,
lv_timestamps TYPE string,
lv_qrcode TYPE xstring,
iv_barcode_text TYPE string VALUE 'Test QR Data'.
cl_rstx_barcode_renderer=>qr_code(
EXPORTING
i_module_size = 20
i_mode = 'A'
i_error_correction = 'H'
i_barcode_text = iv_barcode_text
IMPORTING
e_bitmap = lv_qrcode
).
DATA(l_control) = VALUE ssfctrlop( no_dialog = 'X' preview = 'X' no_open = '' no_close = '' device = 'Z_ADS' ).
DATA(ls_outputparams) = VALUE sfpoutputparams( getpdf = 'X' dest = 'ZADS' ).
DATA(ls_docparams) = VALUE sfpdocparams( fillable = 'X' ).
CALL FUNCTION 'FP_JOB_OPEN'
CHANGING
ie_outputparams = ls_outputparams
EXCEPTIONS
cancel = 1
usage_error = 2
system_error = 3
internal_error = 4
OTHERS = 5.
CALL FUNCTION 'FP_FUNCTION_MODULE_NAME'
EXPORTING
i_name = lv_formname
IMPORTING
e_funcname = lv_fname.
CALL FUNCTION lv_fname
EXPORTING
/1bcdwb/docparams = ls_docparams
iv_qrcode = lv_qrcode
IMPORTING
/1bcdwb/formoutput = ls_fpformout
EXCEPTIONS
usage_error = 1
system_error = 2
internal_error = 3
OTHERS = 4.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
CALL FUNCTION 'FP_JOB_CLOSE'
EXCEPTIONS
usage_error = 1
system_error = 2
internal_error = 3
OTHERS = 4.
lo_fp = cl_fp=>get_reference( ).
lo_pdfobj = lo_fp->create_pdf_object( connection = CONV #('ADS') ).
CALL METHOD lo_pdfobj->set_document
EXPORTING
pdfdata = ls_fpformout-pdf.
CALL METHOD lo_pdfobj->set_template
EXPORTING
xftdata = ls_fpformout-pdf
fillable = 'X'.
CALL METHOD lo_pdfobj->set_signature
EXPORTING
keyname = 'STTGlobal' "'ReaderRights' "Signature name from solution manager
fieldname = 'SignatureField1'
reason = 'TEST'
location = 'Mumbai'
contactinfo = 'Rajesh'.
TRY.
CALL METHOD lo_pdfobj->execute( ).
CATCH cx_fp_runtime_internal INTO DATA(lc_interanl).
MESSAGE lc_interanl->get_longtext( ) TYPE 'I'.
CATCH cx_fp_runtime_system INTO DATA(lc_runtime).
MESSAGE lc_runtime->get_longtext( ) TYPE 'I'.
CATCH cx_fp_runtime_usage INTO DATA(lc_usage).
MESSAGE lc_usage->get_longtext( ) TYPE 'I'.
ENDTRY.
* get result -> l_out
CALL METHOD lo_pdfobj->get_document
IMPORTING
pdfdata = DATA(lv_out).
CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
EXPORTING
buffer = lv_out
* buffer = l_pdf
IMPORTING
output_length = lv_len
TABLES
binary_tab = lt_tab.
GET TIME STAMP FIELD DATA(lv_timestamp).
lv_timestamps = lv_timestamp.
CONCATENATE 'C:\temp\' lv_timestamps '.pdf' INTO lv_file_name.
CALL METHOD cl_gui_frontend_services=>gui_download
EXPORTING
bin_filesize = lv_len "bitmap2_size "l_len
filename = lv_file_name
filetype = 'BIN'
CHANGING
data_tab = lt_tab
EXCEPTIONS
OTHERS = 1.
Activate the code and run the same. We will get the Form saved at the path given in the code
We can see both QR Code and Digital signature in the form
Conclusion
E-signing the document is a common requirement. The above process will help us in achieving the same. In the future SAP may release notes, wherein we can directly print QR Code and Digital signature without many hurdles. But till that time this code will work.
Nice article Vikas, but I am not getting QR code instead of that displaying grey colour image with no QR code. What should I do.
Hi Yugandhar,
I think you have placed your QR Code on the master page. Usually, if you place your QR code on the master page then it will print as a grey image and if you put the same on the body then instead of QR code you will get the value of the code in print.
To resolve the above issue, try to use job profiles and still of you are not able to resolve, then follow the blog to print QR code as image
Hi Vikas,
I am not getting QR Code in Print preview instead of a blank page. What should I do? Please help
SFP setting
The solution which he has mentioned here is not by making use of the BarCode Object, in-fact its by making use of 'Image Field' Object. By making use of below class
which helps in rendering BarCode as bmp Image format.
Please check it again.
Good write up and as you have already mentioned this would be really helpful for E-Invoicing QR Code related scenarios.
Thanks,
Sijin
Hi, Vikas,
I try with the same code as u written in a blog for printing the digital signature automatically in adobe form but i unable to get the digital signature in adobe form . please check above code as i written .
FORM ADOBE_FORM.
CALL FUNCTION 'FP_JOB_OPEN'
CHANGING
ie_outputparams = wa_output
* EXCEPTIONS
* CANCEL = 1
* USAGE_ERROR = 2
* SYSTEM_ERROR = 3
* INTERNAL_ERROR = 4
* OTHERS = 5
.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
DATA : LV_FNAME TYPE FUNCNAME.
CALL FUNCTION 'FP_FUNCTION_MODULE_NAME'
EXPORTING
i_name = 'ZADOBE_ITEM'
IMPORTING
E_FUNCNAME = LV_FNAME
* E_INTERFACE_TYPE =
* EV_FUNCNAME_INBOUND =
.
IF LV_FNAME IS NOT INITIAL .
CALL FUNCTION LV_FNAME
EXPORTING
/1bcdwb/docparams = gs_fp_docparams
i_vbeln = p_vbeln
i_option = GV_OPTIONS
IMPORTING
/1bcdwb/formoutput = fp_formoutput.
*********************** Digitla signature
l_fp = cl_fp=>get_reference( ).
try.
* create PDF Object
l_pdfobj = l_fp->create_pdf_object( connection = CONV #('ADS') ).
CALL METHOD L_PDFOBJ->SET_DOCUMENT
EXPORTING
PDFDATA = fp_formoutput-pdf.
CALL METHOD l_pdfobj->set_template
EXPORTING
xftdata = fp_formoutput-pdf
fillable = 'X'.
CALL METHOD L_PDFOBJ->SET_SIGNATURE
EXPORTING
KEYNAME = 'SHUBHAM'
FIELDNAME = S_FIELD.
CLEAR: L_OUT.
TRY.
CALL METHOD l_pdfobj->execute( ).
CATCH cx_fp_runtime_internal INTO DATA(lc_interanl).
MESSAGE lc_interanl->get_longtext( ) TYPE 'I'.
CATCH cx_fp_runtime_system INTO DATA(lc_runtime).
* MESSAGE lc_runtime->get_longtext( ) TYPE 'I'.
CATCH cx_fp_runtime_usage INTO DATA(lc_usage).
MESSAGE lc_usage->get_longtext( ) TYPE 'I'.
ENDTRY.
*L_PDFOBJ->SET_USAGERIGHTS( DEFAULT_RIGHTS = ABAP_FALSE ).
CALL METHOD L_PDFOBJ->GET_DOCUMENT
IMPORTING
PDFDATA = L_OUT.
endtry.
ENDIF.
CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
EXPORTING
buffer = L_OUT"fp_formoutput-pdf "L_OUTfp_formoutput-pdf
* APPEND_TO_TABLE = ' '
IMPORTING
OUTPUT_LENGTH = lv_len
TABLES
binary_tab = t_att_content_hex.
CALL FUNCTION 'FP_JOB_CLOSE'
* IMPORTING
* E_RESULT =
* EXCEPTIONS
* USAGE_ERROR = 1
* SYSTEM_ERROR = 2
* INTERNAL_ERROR = 3
* OTHERS = 4
.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
ENDFORM.
Nice Job Vikas , do you print directly on label printer from SAP ? do we need to design specific to label printers . thanks for sharing .
Superb Vikas.
Vikas Kumar Zha Thanks for sharing this!
Hi Vikas,
Thanks for the blog. This works fine for me. I have a small query. The PDF with DS gets generated this way. But, now I want the PDF to be printed from standard output management(NACE). The issue I face is the spool is already getting generated after FP_JOB_CLOSE. We are bringing up the resulting PDF and then putting on the DS. How do we make this happen from NACE
Dear Vikas,
We are getting Dump on Code mentioned by you. Can you please help.
Dump Details
Category ABAP programming error
Runtime Errors UNCAUGHT_EXCEPTION
Except. CX_FP_RUNTIME_USAGE
ABAP Program CL_FP_PDF_OBJECT==============CP
Application Component BC-SRV-FP
Date and Time 30.07.2022 13:38:39 (INDIA)
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
|Short Text |
| An exception has occurred that was not caught. |
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
|What happened? |
| The exception of class "CX_FP_RUNTIME_USAGE" was triggered but not caught |
| anywhere in the |
| call hierarchy. |
| |
| Since exceptions represent error situations, and this error was not |
| adequately responded to, ABAP program "CL_FP_PDF_OBJECT==============CP" had |
| to be terminated. |
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
|Error analysis |
| An exception has occurred in class "CX_FP_RUNTIME_USAGE". As this exception |
| was not |
| caught, a runtime error occurred. The reason for the exception |
| occurring was: |
| Not enough information for output or processing |
| |
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
|Missing handling of application exception |
| (Program) ZDIG_REP |
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
|Trigger Location of Exception |
| (Program) CL_FP_PDF_OBJECT==============CP |
| (Include) CL_FP_PDF_OBJECT==============CM00N |
| (Row) 5 |
| (Module Type) (METHOD) |
| (Module Name) IF_FP_PDF_OBJECT~SET_DOCUMENT |
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
|Source Code Extract |
----------------------------------------------------------------------------------------------------
|Line |Code |
----------------------------------------------------------------------------------------------------
| 1|method if_fp_pdf_object~set_document. |
| 2|data: l_errstr type string. |
| 3| |
| 4| if pdffile is initial and pdfdata is initial. |
|>>>>>| raise exception type cx_fp_runtime_usage |
| 6| exporting |
| 7| textid = cx_fp_runtime_usage=>nothing_to_do. |
| 8| endif. |
| 9| |
| 10| if not pdffile is initial and not pdfdata is initial. |
| 11| concatenate 'PDFFILE' ',' 'PDFDATA' into l_errstr. |
| 12| raise exception type cx_fp_runtime_usage |
| 13| exporting |
| 14| textid = cx_fp_runtime_usage=>conflicting_arguments |
| 15| errmsg = l_errstr |
| 16| errcode = cpdfe_pdf_setdocument_conflict. |
| 17| endif. |
| 18| |
| 19| _pdffile = pdffile. |
| 20| _pdfdata = pdfdata. |
| 21| |
| 22|endmethod. |
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
|Active Calls/Events |
----------------------------------------------------------------------------------------------------
|No. Ty. Program Include Line |
| Name |
----------------------------------------------------------------------------------------------------
| 2 METHOD CL_FP_PDF_OBJECT==============CP CL_FP_PDF_OBJECT==============CM00N 5 |
| CL_FP_PDF_OBJECT=>IF_FP_PDF_OBJECT~SET_DOCUMENT |
| 1 EVENT ZDIG_REP ZDIG_REP 80 |
| START-OF-SELECTION |
----------------------------------------------------------------------------------------------------
Awaiting Reply
Hello,
I solved this dump by writing 'PDF1' instead 'ZADS' in this line:
Regards,
Hi Vikas Kumar Zha,
I'm getting dump when I use your code for digital signature. The dump is coming when method lo_pdfobj->execute() is executed.
Could please help me I have a same requirement to print digital signature automatically.
Regards,
Satish P
Hi,
Is your issue resolved. If yes please share how it worked for you. Thanks.
Regards,
Chakradhar.