Skip to Content
Technical Articles
Author's profile photo Vikas Kumar Zha

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%20transaction%20SFP

Open transaction SFP

Create%20Interface%20for%20the%20form

Create Form Interface

Give%20Deta

Give Description and select interface type as ABAP Dictionary.

cc

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%20Adobe%20Form

Create an Adobe Form

Assign%20Form%20Interface%20created%20above%20and%20give%20description%20to%20the%20form

Assign Form Interface created above and give the description to the form. Save the form

ff

Create a graphic node QR_CODE

ffff

Link Graphic node QR_CODE variable with XSTRING variable IV_QRCODE. Open design view

ffff

Create 2 fields in design view:

  • Signature field (SignatureField1)
  • Drag and drop QR_CODE image node

Save and Activate the form

ddd

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%20can%20see%20both%20QR%20Code%20and%20Digital%20signature%20in%20the%20form

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.

Assigned Tags

      15 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Yugandhar Kotha
      Yugandhar Kotha

      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.

      Author's profile photo Vikas Kumar Zha
      Vikas Kumar Zha
      Blog Post Author

      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

      Author's profile photo Santanu Nayek
      Santanu Nayek

      Hi Vikas,

      I am not getting QR Code in Print preview instead of a blank page. What should I do? Please help

      SFP%20setting

      SFP setting

      Author's profile photo Sijin Chandran
      Sijin Chandran

      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

      cl_rstx_barcode_renderer=>qr_code

      which helps in rendering BarCode as bmp Image format.

      Please check it again.

      Author's profile photo Sijin Chandran
      Sijin Chandran

      Good  write up and as you have already mentioned this would be really helpful for E-Invoicing QR Code related scenarios.

      Thanks,

      Sijin

      Author's profile photo SHUBhAM TAKLIKAR
      SHUBhAM TAKLIKAR

      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_objectconnection 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.

      CLEARL_OUT.
      TRY.
      CALL METHOD l_pdfobj->execute).

      CATCH cx_fp_runtime_internal INTO DATA(lc_interanl).
      MESSAGE lc_interanl->get_longtextTYPE '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_longtextTYPE '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.

       

      Author's profile photo SIRIGIRI KISHORE
      SIRIGIRI KISHORE

      Nice Job Vikas , do you print directly on label printer from SAP ? do we need to design specific to label printers . thanks for sharing .

      Author's profile photo Gourab Dey
      Gourab Dey

      Superb Vikas.

      Author's profile photo Jigang Zhang 张吉刚
      Jigang Zhang 张吉刚

      Vikas Kumar Zha Thanks for sharing this!

      Author's profile photo Shilpi Gupta
      Shilpi Gupta

      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

      Author's profile photo Abhishek Aserkar
      Abhishek Aserkar

      Dear Vikas,

       

      We are getting Dump on Code mentioned by you. Can you please help.

       

      REPORT ZDIG_REP.
      
      DATA :
        lv_fname        TYPE rs38l_fnam ,
        lv_formname     TYPE tdsfname VALUE 'ZQR_CODEF',
        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.

       

      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 |
      ----------------------------------------------------------------------------------------------------

      Author's profile photo Abhishek Aserkar
      Abhishek Aserkar

      Awaiting Reply 

      Author's profile photo Silvana Paredes
      Silvana Paredes

      Hello,

      I solved this dump by writing 'PDF1' instead 'ZADS' in this line:

      DATA(ls_outputparams) = VALUE sfpoutputparams( getpdf = 'X' dest = 'ZADS' ).

      Regards,

       

      Author's profile photo Satish P
      Satish P

      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.

      CALL METHOD lo_pdfobj->execute( ).

      Regards,

      Satish P

      Author's profile photo Sakshi Khanna
      Sakshi Khanna

      Hi,

      Is your issue resolved. If yes please share how it worked for you. Thanks.

       

      Regards,

      Chakradhar.