Technical Articles
QR Code in Base64 encoding for KSA E-Invoicing
As per Zakat, Tax and Customs Authority (ZATCA) of Saudi Arabia, one of the main requirements is the implementation of QR codes on tax invoices in the e-invoicing project (Fatoora), which will be mandatory starting December 4, 2021
As per the ZATCA instructions(Page No. 23), the minimum requirements that must be shown after scanning a QR code are the following fields, which should be represented in form of based64 encoding:
- Seller’s name.
- VAT registration number of the seller.
- Time stamp of the invoice (date and time).
- Invoice total (with VAT).
- VAT total.
In this blog, I will show how to encode the QR data in base64 format using ABAP and then using it in SAPScript/SmartForms to print QR code on Invoice layouts.
1st Step is to prepare each of the five values in TLV (Tag-Length-Value) structure
Tag is fixed (1 for Seller’s name, 2 for VAT No……5 for VAT Total)
Length is the size of the value field in bytes (it’s not the count of characters but how many bytes the value represents)
Value is the data against each of the five fields.
Let’s take an example to clarify TLV
-
- Seller name; for example, “Firoz Ashraf”
- Tag = 1 (1 as a type represents the seller name)
- Length = 12 (The number of the bytes in “Firoz Ashraf” word)
- Value = Firoz Ashraf
- VAT Number; for example, 1234567891
- Tag = 2 (2 as a type represents the VAT number)
- Length = 10
- Value = 1234567891
- Time Stamp; for example, 2021-11-17 08:30:00
- Tag = 3 (3 as a type represents invoice time stamp)
- Length = 19
- Value = 2021-11-17 08:30:00
- Invoice Total; for example, 100.00
- Tag = 4 (4 as a type represents the invoice amount)
- Length = 6
- Value = 100.00
- VAT Total; for example, 15.00
- Tag = 5 (5 as a type represents the tax amount)
- Length = 5
- Value = 15.00
- Seller name; for example, “Firoz Ashraf”
2nd Step is to convert ‘Tag’ and ‘Length’ to Hexadecimal and then to string. Then concatenate these two strings with ‘Value’ (stored as string)
concatenate all the five TLVs into one string
‘##Firoz Ashraf##1234567891##2021-11-17 08:30:00##115.00##15.00’
3rd Step is to convert the concatenated string to Base64 format
From the above example we get the following Base64 encoded value
AQxGaXJveiBBc2hyYWYCCjEyMzQ1Njc4OTEDEzIwMjEtMTEtMTcgMDg6MzA6MDAEBjExNS4wMAUFMTUuMDA=
Now let’s see how we can do this in ABAP
To get the ‘Length’ in the TLV structure, we will use the Function Module SCMS_STRING_TO_XSTRING to convert the text to xString and then we will use xstrlen to get the length.
FORM tag_length USING p_string
CHANGING p_length.
DATA: v_xstr TYPE xstring.
*First Convert string to xString
CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
EXPORTING
text = p_string
* MIMETYPE = ' '
* ENCODING =
IMPORTING
buffer = v_xstr
EXCEPTIONS
failed = 1
OTHERS = 2.
IF sy-subrc <> 0.
* Implement suitable error handling here
ELSE.
p_length = xstrlen( v_xstr ).
ENDIF.
ENDFORM.
To convert the string to Base64 we have two ways in ABAP:
The first one is using Class CL_HTTP_UTILITY method ENCODE_BASE64
The second one is using Function Module SCMS_STRING_TO_XSTRING to Convert String to Xstring and the using another Function Module SCMS_BASE64_ENCODE_STR to Convert the Xstring to Base64.
You can choose either of the ways (either Class or FM)
I have used the Class method to convert string to Base64.
To start with, I created a custom FM which takes invoice number as input and gives QR code values in text as well as in Base64.
I use this FM in SAPScript/SmartForms to print the QR Code.
FUNCTION z_einvoice_base64_qrcode_value.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" REFERENCE(INVOICE_NO) TYPE VBELN_VF
*" EXPORTING
*" REFERENCE(QRCODE_STRING) TYPE STRING
*" REFERENCE(QRCODE_BASE64) TYPE STRING
*" EXCEPTIONS
*" NO_INVOICE
*" XSTR_ERROR
*"----------------------------------------------------------------------
*-----------------------------------------------------------------------
* The QR code fields shall be encoded in Tag-Length-Value (TLV) format
* The TLV encoding shall be as follows:
* Tag : the tag value (1 to 5) stored in one byte
* Length : the length of the byte array resulted from the UTF8 encoding of the field value.
* Value : the byte array resulting from the UTF8 encoding of the field value.
*----------------------------------------------------------------------
DATA: wa_vbrk TYPE vbrk,
v_t1_cname TYPE string,
v_t2_vatno TYPE string, v_date(10), v_time(8),
v_t3_tstmp TYPE string,
v_t4_invamt TYPE vbrk-netwr, v_t4_invamx TYPE string,
v_t5_vatamt TYPE vbrk-netwr, v_t5_vatamx TYPE string,
v_t1_len TYPE i,v_t2_len TYPE i,v_t3_len TYPE i,
v_t4_len TYPE i,v_t5_len TYPE i,
v_t1_lenx TYPE xstring,v_t2_lenx TYPE xstring,v_t3_lenx TYPE xstring,
v_t4_lenx TYPE xstring,v_t5_lenx TYPE xstring,
v_t1_lent TYPE string,v_t2_lent TYPE string,v_t3_lent TYPE string,
v_t4_lent TYPE string,v_t5_lent TYPE string,
v_t1_tag TYPE string, v_t2_tag TYPE string, v_t3_tag TYPE string,
v_t4_tag TYPE string, v_t5_tag TYPE string.
SELECT SINGLE * FROM vbrk INTO wa_vbrk
WHERE vbeln = invoice_no.
IF sy-subrc = 0.
* Company Name & VAT No.
SELECT SINGLE butxt stceg FROM t001 INTO ( v_t1_cname, v_t2_vatno )
WHERE bukrs = wa_vbrk-bukrs.
* Invoice Time Stamp
CONCATENATE wa_vbrk-fkdat(4) '-' wa_vbrk-fkdat+4(2) '-' wa_vbrk-fkdat+6(2)
INTO v_date.
CONCATENATE wa_vbrk-erzet(2) ':' wa_vbrk-erzet+2(2) ':' wa_vbrk-erzet+4(2)
INTO v_time.
CONCATENATE v_date v_time INTO v_t3_tstmp SEPARATED BY space.
* Invoice Total (with VAT)
v_t4_invamt = wa_vbrk-netwr + wa_vbrk-mwsbk.
v_t4_invamx = v_t4_invamt. CONDENSE v_t4_invamx.
* VAT Total
v_t5_vatamt = wa_vbrk-mwsbk.
v_t5_vatamx = v_t5_vatamt. CONDENSE v_t5_vatamx.
**********Tag & Length (T&L from TLV) should be first converted to
* Hexadecimal format then it should be converted to string.
* Finally these two strings should be concatenated with 'Value' (of TLV).
* Since tags are 1 to 5. We take the hexa values as 01 to 05
PERFORM convert_hex_to_str USING '01' CHANGING v_t1_tag.
PERFORM convert_hex_to_str USING '02' CHANGING v_t2_tag.
PERFORM convert_hex_to_str USING '03' CHANGING v_t3_tag.
PERFORM convert_hex_to_str USING '04' CHANGING v_t4_tag.
PERFORM convert_hex_to_str USING '05' CHANGING v_t5_tag.
PERFORM tag_length USING v_t1_cname CHANGING v_t1_len.
v_t1_lenx = v_t1_len. " Convert to hexadecial value
PERFORM convert_hex_to_str USING v_t1_lenx CHANGING v_t1_lent.
PERFORM tag_length USING v_t2_vatno CHANGING v_t2_len.
v_t2_lenx = v_t2_len.
PERFORM convert_hex_to_str USING v_t2_lenx CHANGING v_t2_lent.
PERFORM tag_length USING v_t3_tstmp CHANGING v_t3_len.
v_t3_lenx = v_t3_len.
PERFORM convert_hex_to_str USING v_t3_lenx CHANGING v_t3_lent.
PERFORM tag_length USING v_t4_invamx CHANGING v_t4_len.
v_t4_lenx = v_t4_len.
PERFORM convert_hex_to_str USING v_t4_lenx CHANGING v_t4_lent.
PERFORM tag_length USING v_t5_vatamx CHANGING v_t5_len.
v_t5_lenx = v_t5_len.
PERFORM convert_hex_to_str USING v_t5_lenx CHANGING v_t5_lent.
***************Concatenate all TLV data********************
CONCATENATE v_t1_tag v_t1_lent v_t1_cname
v_t2_tag v_t2_lent v_t2_vatno
v_t3_tag v_t3_lent v_t3_tstmp
v_t4_tag v_t4_lent v_t4_invamx
v_t5_tag v_t5_lent v_t5_vatamx
INTO qrcode_string.
***************Encode String to Base64*********************
CALL METHOD cl_http_utility=>if_http_utility~encode_base64
EXPORTING
unencoded = qrcode_string
RECEIVING
encoded = qrcode_base64.
ELSE.
RAISE no_invoice.
ENDIF.
ENDFUNCTION.
PERFORM convert_hex_to_str
*&---------------------------------------------------------------------*
*& Form CONVERT_HEX_TO_STR
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* -->P_HEX text
* <--P_STR text
*----------------------------------------------------------------------*
FORM convert_hex_to_str USING p_hex
CHANGING p_str.
* CALL FUNCTION 'HR_RU_CONVERT_HEX_TO_STRING'
* EXPORTING
* xstring = p_hex
* IMPORTING
* cstring = p_str.
**Note: Above FM was sometimes not giving correct **
** conversion. Hence we have changed it to **
** class based explicitly using UTF-8 **
DATA: loc_conv TYPE REF TO cl_abap_conv_in_ce.
CALL METHOD cl_abap_conv_in_ce=>create
EXPORTING
input = p_hex
encoding = 'UTF-8'
replacement = '?'
ignore_cerr = abap_true
RECEIVING
conv = loc_conv.
TRY.
CALL METHOD loc_conv->read
IMPORTING
data = p_str.
CATCH cx_sy_conversion_codepage.
*-- Should ignore errors in code conversions
CATCH cx_sy_codepage_converter_init.
*-- Should ignore errors in code conversions
CATCH cx_parameter_invalid_type.
CATCH cx_parameter_invalid_range.
ENDTRY.ENDFORM.
Setting up the QR Code font
Using SE73, create a new ‘System Bar Code’
Once this is done, create a Character format say QR in your SAPScript using the Bar Code (QR Code) created above.
You can then use this in your Window
Here I am calling the subroutine ZEDOC_KSA_QRBASE64 in ABAP program ZSDLINCLUDE which actually has our custom FM Z_EINVOICE_BASE64_QRCODE_VALUE
Note that a single text variable in SAPScript has a capacity to hold 80 characters and our QR code value is more than 80 hence I had to spilt the values in two variables V_QRCODE1 & V_QRCODE2.
FORM zedoc_ksa_qrbase64 TABLES in_tab STRUCTURE itcsy
out_tab STRUCTURE itcsy.
DATA: v_vbeln TYPE vbeln,
v_qrb64 TYPE string,
v_len TYPE i,
v_rem TYPE i.
READ TABLE in_tab INDEX 1.
IF sy-subrc = 0.
v_vbeln = in_tab-value.
CALL FUNCTION 'Z_EINVOICE_BASE64_QRCODE_VALUE'
EXPORTING
invoice_no = v_vbeln
IMPORTING
* QRCODE_STRING =
qrcode_base64 = v_qrb64
EXCEPTIONS
no_invoice = 1
xstr_error = 2
OTHERS = 3.
IF sy-subrc <> 0.
* Implement suitable error handling here
ELSE.
v_len = strlen( v_qrb64 ).
READ TABLE out_tab INDEX 1.
IF sy-subrc = 0.
IF v_len GT 80. "Split into two variables
out_tab-value = v_qrb64(80).
v_rem = v_len - 80.
MODIFY out_tab INDEX 1.CLEAR out_tab.
READ TABLE out_tab INDEX 2.
IF sy-subrc = 0.
out_tab-value = v_qrb64+80(v_rem).
MODIFY out_tab INDEX 2.CLEAR out_tab.
ENDIF.
ELSE.
out_tab-value = v_qrb64.
MODIFY out_tab INDEX 1.CLEAR out_tab.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
ENDFORM.
After doing this when you call the layout you will get the QR Code
If you scan this QR code then you will get the the following Base64 coded text
AQxGaXJveiBBc2hyYWYCCjEyMzQ1Njc4OTEDEzIwMjEtMTEtMTcgMDg6MzA6MDAEBjExNS4wMAUFMTUuMDA=
When decoded this will give the following text value (as shown below )
You may go through the following blogs and links which were quite helpful in getting the pieces together.
- https://blogs.sap.com/2019/03/29/base64-function-modules-in-sap-abap/
- https://sapintegrationhub.com/abap/base64/base64-encoding-and-decoding-in-sap-abap/
- https://blogs.sap.com/2020/10/12/display-qr-code-for-gst-india-e-invoicing-on-script-and-smartform/
- https://salla.dev/blog/qr-code-fatoora-e-invoicing-zatca/
- https://www.textencode.com/decoder/decodeBase64
Note: if you have set up EDOC_COCKPIT then you can directly get the QR code data in base64 encoding without bothering about TLV conversion. You may follow my another blog where I have explained how you can use the data stored in field QR_CODE from table EDOSAINV.
Enjoy coding !!
Firoz Ashraf.
Hi brother,
Can you check following encoded data.
"AQVTYWxsYQIKMTIzNDU2Nzg5MQMUMjAyMS0wNy0xMlQxNDoyNTowOVoEBjEwMC4wMAUFMTUuMDA=" Encryption method is little bit different than you mentioned. Tags are not visible while decoding base64. Ref. https://github.com/SallaApp/ZATCA
https://topnotepad.com/sa/qr-code-in-e-invoice
Yes, one conversion was missing due to which encryption was not proper. The correct base64 encoded value is
AQxGaXJveiBBc2hyYWYCCjEyMzQ1Njc4OTEDEzIwMjEtMTEtMTcgMDg6MzA6MDAEBjExNS4wMAUFMTUuMDA=
Missing Part - Conversion of 'Tag' and 'Length' to Hexadecimal and then to string.
So, the correct order is ..
Convert 'Tag' to Hexadecimal, then convert it to strings of characters with the corresponding ASCII code. Similarly convert 'Length' to Hexadecimal, and to string. Then concatenate these two strings with 'Value' (stored as string). Do this for all the TLVs and concatenate into one string. Finally this single string is to be converted to Base64 using METHOD cl_http_utility=>if_http_utility~encode_base64
I have updated my codes of the custom FM.
Thanks.
Brother Asharf,
I am able to generate Base64 QRCODE perfectly and scannable on screen also no issue, but when print the invoice from VF03 using
device type ( PDFUC :pdf unicode 1:3) printer :EPSON LQ-690 printer print(Adobe Form) the generated QR code unable to read
in zatca app or any QRSCANer.
do you have any idea what is the issue why its not scanning , please give any input to solve this issue.
Thanks,
Nawazuddin.
Dear Firoz Ashraf, I am really impress your work. I want to ask one question. When I convert TAG 1 to Hexa it is giving 1 and after that i convert it to ascci string it is giving 31. in case of len "Firoz Ashraf" len is 12 When i convert it it is giving 3128. then concatenate the string is '313128Firoz ashraf. is it correct? if not pls guide me about this. or pls tel us the comp concatenated string
Dear Abdul Mateen,
Hexa of 1 will be '01' and then converting it to text using METHOD cl_abap_conv_in_ce=>create and METHOD loc_conv->read will give you '#'
Hi S M Firoz
I am facing a problem if the name of the resource is Arabic in the base64 site is working, but through the scanner it does not work
ASDZhdi12YbYuSDYsdmI2LYg2KfZhNij2LXZitmEINmE2YTYqti52KjYptipINmI2KfZhNiq2LrZhNmK2YECDzMwMDc4NjMxMjcwMDAwMwMKMjAyMS8xMS8yNgQGOTIwLjAwBQYxMjAuMDA=
Base64
مصنع روض الأصيل للتعبئة والتغليف3007863127000032021/11/26920.00120.00
can you help me
Dear Ahmed,
Try to convert the single concatenated string value into hex with UTF-8 encoding and then use this hex to finally convert to base64.
Additionally, please make sure the 'Mode' of the QR Code created in SE73 is 'A'
Regards,
Firoz.
Hi Firoz,
I am following the same steps but still arabic text is not getting scanned.
After concatenating into final string, called below code before base64 conversion.
Also, Bar code Mode is to 'A' only.
S M Firoz Ashraf
Kindly help on this problem as it is very important for us to go live with this Arabic QR code.
Regards,
Vishal Solanki
Try with Mode 'U'
Hi Firoz,
Done the same setting but still error remains same.
Barcode
Please try to check the print preview & actual print of the QR code that you are using from SE73. See if you are getting the Arabic letters in the preview/print.
Hi Firoz,
I am facing issue if Seller name value is having '.' ( 'Test Co. Main Branch.') . FM HR_RU_CONVERT_HEX_TO_STRING is giving strange character when I pass value '15'.
Are you facing issue if Seller name value is having '.' ?
Hi Aamir,
It is perfectly fine to get 'Strange Character' in ABAP, for example '§' when you pass the hexadecimal value 15 in the FM HR_RU_CONVERT_HEX_TO_STRING.
Please go ahead and concatenate it to the final string.
Once you convert it to base64 you will get the value as AadUZXN0IENvLiBNYWluIEJyYW5jaC4CCjEyMzQ1Njc4OTEDEzIwMjEtMTEtMjMgMTM6MDE6MDEEBjExNS4wMAUFMTUuMDA=
which can be decoded as
Test Co. Main Branch.
12345678912021-11-23 13:01:01115.0015.00
You can see that that the Seller name is 'Test Co. Main Branch.' with two dots.
Regards,
Firoz.
Dear Firoz,
Below are final strings
When using Test Co. Main Branch.
ASNUZXN0IENvLiBNYWluIEJyYW5jaC4CDjMwMDI0MDg4NTgxMTExAxMyMDIxLTA3LTE1IDE2OjEwOjA4BAgxMjI2Mi40NQUHMTU5OS40NQ==
When using Test Co Main Branch ( removing .)
ASNUZXN0IENvIE1haW4gQnJhbmNoAg4zMDAyNDA4ODU4MTExMQMTMjAyMS0wNy0xNSAxNjoxMDowOAQIMTIyNjIuNDUFBzE1OTkuNDU=
QR code generated by first one is showing not compliance on E-invoice QR Reader tool, where as for second QR, it is showing as complaint.
Hello Aamir,
Which E-invoice QR Reader tool are you using?
I can see that both your code results in the same output on https://www.base64decode.org/
Hi Firoz,
You can scan QR Code and check compliance by below ZATCA app
for Android https://play.google.com/store/apps/details?id=com.posbankbh.einvoiceqrreader
For Iphone https://apps.apple.com/us/app/e-invoice-qr-reader-ksa/id1580793042
Last time I put some wrong value ( testing with so many data). Below is where i am facing issue.
Test Co. Main Branch. ( With dots)
AadUZXN0IENvLiBNYWluIEJyYW5jaC4CDjMwMDI0MDg4NTgxMTExAxMyMDIxLTA3LTE1IDE2OjEwOjA4BAgxMjI2Mi40NQUHMTU5OS40NQ==
Test Co Main Branch
ARNUZXN0IENvIE1haW4gQnJhbmNoAg4zMDAyNDA4ODU4MTExMQMTMjAyMS0wNy0xNSAxNjoxMDowOAQIMTIyNjIuNDUFBzE1OTkuNDU=
As you see below value is slight different in case of first data. I am attaching QR code .
issue
Original
dots_removed
Hi Aamir,
I have changed the hexadecimal conversion in my subroutine convert_hex_to_str from FM HR_RU_CONVERT_HEX_TO_STRING to Class CL_ABAP_CONV_IN_CE explicitly utilizing UTF-8 encoding. Now the results seems to be fine.
Kindly use my updated code and create the QR code. Hopefully the ZATCA app will give you the correct result.
ARVUZXN0IENvLiBNYWluIEJyYW5jaC4CDjMwMDI0MDg4NTgxMTExAxMyMDIxLTA3LTE1IDE2OjEwOjA4BAgxMjI2Mi40NQUHMTU5OS40NQ==
Regards,
Firoz.
Dear Firoz,
If you have string of length 32, then corresponding hex value is '20'. when you pass this value to your method, again this QR code will fail as method will return blank value for hex = '20'. You can verify by changing Seller name of length 32 in debug mode and scanning the generated barcode.
I done it in slight different way. We have 3 parts. TAG LENGTH and VALUE.
TAG you already giving hex value as '01' '02'....
LENGTH you are getting in hex by passing xtrlen output to variable of type xstring.
VALUE you are converting in hex by calling FM 'SCMS_STRING_TO_XSTRING'.
Now you have all 3 parts in hex. No need to convert to string, Just concatenate all in variable of type xstring using CONCATENATE INTO lv_xstring IN BYTE MODE.
Now you have hex string. Use cl_http_utility=>if_http_utility~encode_x_base64 to convert to base 64.
This is working with all length of values as we are not converting hex to str and then back to hex.
Thanks
Mr. Firoz,
Really it is appreciated, and was very helpful. First Phase was very Smooth we completed.
As of now QRCODE is taking 256 Character and in Second phase we have to add more Strings,
How we can achieve it.
hi mr/ashraf
we do every this as yoy say
but still tag and length
can you give me exampe for first tag,first length whicj will add it in the begining of string?
Hi Taha,
I have updated my code for hexadecimal conversion. Kindly follow it as explained.
Regards,
Firoz.
Hi,
It is not matching with what they specified in the document https://zatca.gov.sa/ar/E-Invoicing/SystemsDevelopers/Documents/20210528_ZATCA_Electronic_Invoice_Security_Features_Implementation_Standards_vShared.pdf
As per the document (section 4.1), Tag should be stored in first byte, Length is the length of the byte array of UTF8 encoded value string stored as single byte. You are converting tag and length into hex values and then to string. Which one is correct?
Hi Murty,
I believe, ABAP is taking care of what has been specified.
Since we have to concatenate the TLV strings therefore we are doing this hexa and then string conversion.
At the end... conversion to base64 should be correct and readable by any ZATCA approved QR reader app. like this Android App or Apple App
You can build your QR code and check the result.
Hi Firoz,
Thanks for your quick response. It didn't work for me because I was including the '$' sign to the total amount. It is working now and nothing to do with hex or byte. Thanks again.
Murty
Thanks, It is working fine and also, validated it using ZATCA QR scanner
Can you please share the tag length raw value for any column against the variable "
I am doing this method in Oracle but want to know what value you are returning against tag length in string. Thanks in advance.
Raza
It's #
can you explain this function as example value. for example your first tag is company. and you passed the value to function "Firoz Ashraf" so first you are converting it to hex value and then to calculate the length of hex or actual string?
We are passing the string 'Firoz Ashraf' to the FM which basically converts it to hexadecimal value in the variable v_xstr. Next we are calculating the length (as a number of bytes) of v_xstr using the predefined ABAP function xstrlen.
Brother Asharf,
I am able to generate Base64 QRCODE perfectly and scannable on screen also no issue, but when print the invoice from VF03 using
device type ( PDFUC :pdf unicode 1:3) printer :EPSON LQ-690 printer print(Adobe Form) the generated QR code unable to read
in zatca app or any QRSCANer.
do you have any idea what is the issue why its not scanning , please give any input to solve this issue.
Thanks,
Nawazuddin.
Dear Nawazuddin,
For printing QR Code on DotMatrix printer EPSON LQ-690 you may try device type SWIN instead of PDFUC.
Take help of BASIS guy if needed.
Regards,
If needed, you may simplify the code a little bit, here is a test code with test data as above in the comments, which gives the exact same result, with full standard ABAP API (cl_abap_codepage for UTF-8 encoding and call transformation for transforming bytes into base64) :
Thanks for your suggestion Sandra.
Definitely it's simpler and cleaner code.
However, the base64 code resulted from CALL TRANSFORMATION is not readable from tax authority compliant app.
But when method IF_HTTP_UTILITY~ENCODE_X_BASE64 is used as shown below, the result is readable.
Regards,
Firoz.
Hi
Please I write this code it is working right and tested on
https://www.base64decode.org/
My issue when I put it on Adobe form it is empty when I scanned it
Can you help me
Hi Eman,
If you are getting the base64 value and it's showing the result on any decoder then please check the QR Code created from SE73 which you are using on your forms.
It is Adobe form not smart form
you may check your data binding or the inserted QR Code type in Adobe Forms.
I tried on Adobe Forms and it is working for me.
Dear AShar ,
Did you tried arabic with this code , when i am passing the arabic value to this code to convert in Base64 not working.
Thanks,
Nawazuddin.
Dear Eman,
Increase the size of QR code it will work not only layout you need to increase size of QRCODE in XML.
XML
Thanks,
Nawazuddin
Thanks for your replay
It is solved
Hello every body
Dear Firoz Ashraf thank you very much for helping us in e invoice problem
I have the same problem in arabic name in seller name
I use vb.net
For Arabic name make sure your text is converted to UTF-8 encoding
Dear Ashraf,
I tried like this .
CALL METHOD cl_http_utility=>if_http_utility~encode_utf8
EXPORTING
unencoded = v_t1_cname " string arabic
receiving
encoded = v_t1_cnamex. " xstring
clear :v_t1_cnames.
CALL METHOD cl_http_utility=>if_http_utility~decode_utf8
EXPORTING
encoded = v_t1_cnamex " xstring
RECEIVING
unencoded = v_t1_cnames. "string arabic
its generating string like this.
الجواهري العربي##310122393500003##2022-04-25T15:30:00Z##1000.00##150.00
arabic text comming in between.
Thanks,
Nawazuddin
Just try to generate the QR code from the base64 data that you get even if the display of arabic is at the end or in the middle.
if that does not works then use the below code
I tried with your data and following is the result
QRCODE_STRING
##الجواهري العربي##310122393500003##2021-12-01 14:40:20##1150.00##150.00
QRCODE_XSTRING
011DD8A7D984D8ACD988D8A7D987D8B1D98A20D8A7D984D8B9D8B1D8A8D98A020F3331303132323339333530303030330313323032312D31322D30312031343A34303A3230040731313530
QRCODE_BASE64 AR3Yp9mE2KzZiNin2YfYsdmKINin2YTYudix2KjZigIPMzEwMTIyMzkzNTAwMDAzAxMyMDIxLTEyLTAxIDE0OjQwOjIwBAcxMTUwLjAwBQYxNTAuMDA=
Brother Asharaf,,
Thanks for your reply but that generated QRCODE is not compataible with E-invoice QR Reader application actully i am looking same like what they given QRCODE in example zatca site.
Thanks,
Nawazuddin.
Try the code suggested in
https://blogs.sap.com/2021/11/18/qr-code-in-base64-encoding-for-ksa-e-invoicing/comment-page-1/#comment-601245
The generated base64 value is
AR3Yp9mE2KzZiNin2YfYsdmKINin2YTYudix2KjZigIPMzEwMTIyMzkzNTAwMDAzAxMyMDIxLTEyLTAxIDEwOjIwOjMwBAcxMTUwLjAwBQYxNTAuMDA=
same problem
this is my code
Dim qrCode As New QRCodeEncoder
qrCode.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE
qrCode.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.L
Me.PictureBox1.Image = qrCode.Encode(Me.lblQR_CODE.Text, System.Text.Encoding.UTF8)
Hi Firoz Ashraf,
Can you please explain more about 2nd step?
after step one I am getting this result
112Firoz Ashraf21012345678913192021-11-17 08:30:0046115.005515.00
how to convert this to
‘##Firoz Ashraf##1234567891##2021-11-17 08:30:00##115.00##15.00’
As you mentioned to convert tag and length to hexadecimal. I tried but got a different result. Please guide for the 2nd and 3rd steps. Thank You.
Use the following code:
Subroutine TLV is
Brother Ashraf,
using the above code I am unable to print QR code with arabic text "الجواهري العربي" my base64 is comming like this.
Base64>AR3Yp9mE2KzZiNin2YfYsdmKINin2YTYudix2KjZigIPMzEwMTIyMzkzNTAwMDAzAxMyMDIxLTExLTE3IDA4OjMwOjAwBAcxMDAwLjAwBQYxNTAuMDA=
after decode:الجواهري العربي3101223935000032021-11-17 08:30:001000.00150.00
and Adobe not generating QR code with english text every thing fine.
Thanks in advance for your support and help.
Mohammad Nawazuddin FWIW, the base 64 which you indicate is fully valid (whatever it's generated by code from blog post or by code from alternative I proposed with subroutine TLV, both produce the exact same code), the error is probably only an issue in your Adobe form. You'd better ask a question in the Adobe forum, with all details (no need to indicate the ABAP code you used to generate, just indicate the final xstring or base 64 of the QR code).
Mohammad Nawazuddin As I said, I think your issue is more about how to generate the QR code in Adobe with Arabic text (for whatever reason I don't understand, because QR code deals only with bytes, not fonts). Your issue is not about the content of the QR code.
FYI, I get a different decode from your Base64>AR3Yp9mE2KzZiNin2YfYsdmKINin2YTYudix2KjZigIPMzEwMTIyMzkzNTAwMDAzAxMyMDIxLTExLTE3IDA4OjMwOjAwBAcxMDAwLjAwBQYxNTAuMDA=
but I guess it's just a matter of rendering texts from right-to-left or left-to-right.
your decode:الجواهري العربي3101223935000032021-11-17 08:30:001000.00150.00
my decode (from tag 1 at the top, to tag 5 at the bottom):
S M Firoz Ashraf whatever it's generated by code from your blog post or by code from alternative I proposed with subroutine TLV, both produce the exact same xstring or base 64, both are fully valid.
Ishaan Tabish For your information, the character # is only a replacement character for characters which are not displayable. Depending on the tool you choose to display the contents, it may appear with # or any other way, or even be invisible. The ABAP debugger tools show it in various ways.
For information, all five pairs of ## characters have the same meaning. In each pair, the first # character is the Tag part of TLV (Tag-Length-Value), which contains a value between binary 1 and 5 represented with one byte, the length is also represented in binary on one byte.
If you display the contents with the hexadecimal viewer of the ABAP debugger, you will see the actual content of these "#" characters.
Brother,
kindly can you generate base64 with this values , if possible try to generate QRCODE also .
v_t1_cname = 'الجواهري العربي'.
v_t2_vatno = '310122393500003'.
v_t3_tstmp = '2022-04-25T15:30:00Z'.
v_t4_invamx = '1000.00'.
v_t5_vatamx = '150.00'.
Thanks,
Nawazuddin.
AR3Yp9mE2KzZiNin2YfYsdmKINin2YTYudix2KjZigIPMzEwMTIyMzkzNTAwMDAzAxQyMDIyLTA0LTI1VDE1OjMwOjAwWgQHMTAwMC4wMAUGMTUwLjAw
Brother AShraf,
kindly can you send me the code for this from which you generated.
Thanks,
Thanks brother Ashraf its working now..
Dear Nawazuddin,
As Sandra said your issue is not with the QR code content. It seems more to do with the generation of QR code in Adobe form.
Hello,
Can you also help me generate base64 and QR Code with the this info?
v_t1_cname = ‘مجمع عيادات جاما لطب الأسنان’
v_t2_vatno = '300056403300003’
v_t3_tstmp = '22/12/2021 04:25:03'
v_t4_invamx = '10000.00'
v_t5_vatamx = '1500.00'
if sometimes length is more, then QR code is not coming. In this case, please increase the width and height of QR code size.
Mr. Firoz,
Thanks a lot for this wonderful blog. It really helped us reached our goal of implementing the E-Invoicing in our organization.
Great work. Keep it up!
Thanks,
TZahaque
Nice job. If you use Crystal Reports, my CUT Light UFL (User Function Library) provides a uflZatcaEncode() function, allowing you to generate the encoding and pass it to a uflBBarcodeQR() function to generate the QR Code (without a dependency on special fonts):
hello sir,
I want to ask how to implement this method using opencart for the invoice? appreciate your answer, thank you
The above solution is in ABAP to be used in layouts generated from SAP.
hello, dear
m_Ashraf, can you contact me in private, send me a message or a way to communicate
Thank you
Hello Froez Ashraf, I followed the content and I worked on a simple sample in the .NET language
hex encryption :
23234669726F7A204173687261662323313233343536373839312323323032312D31312D31372030383A33303A303023233131352E3030232331352E3030
Base64 :
IyNGaXJveiBBc2hyYWYjIzEyMzQ1Njc4OTEjIzIwMjEtMTEtMTcgMDg6MzA6MDAjIzExNS4wMCMjMTUuMDA=
I have a problem, I can't read the code correctly
It seems that the problem of "TAG" = ##
Thanks
In this blog post, # is used to represent any non-displayable (non-printable) "character". # could be U+0001, U+0002, etc. (see Unicode Characters in the 'Other, Control' Category (fileformat.info))
You should not confuse with the hash character U+0023 (Unicode Character 'NUMBER SIGN' (U+0023) (fileformat.info))
Dear Fahad,
Don' t just take the single string
"##Firoz Ashraf##1234567891##2021-11-17 08:30:00##115.00##15.00"
and convert it to hex & then to Base64
For each tag first convert it to hexa, then concatenate the hexa value into one string. Use this single string to convert to base64.
For example,
Tag1: convert 1, 12 (length of 'Firoz Ashraf') & 'Firoz Ashraf' itself to hexa. Store this in variable tlv1
(01 for 1, 0C for 12, 4669726F7A20417368726166 for Firoz Ashraf)
So the hexa value in tlv1 will be 010C4669726F7A20417368726166
Tag2: convert 2, 10 (length of '1234567891') & '1234567891' itself to hexa. Store this in variable tlv2
(02 for 2, 0A for 10, 31323334353637383931 for 1234567891)
So the hexa value in tlv2 will be 020A31323334353637383931
Do this for remaining tags. Then concatenate tlv1 tlv2 tlv3 tlv4 tlv5 into a single variable say qrcode_xstring
As per above example the value in variable qrcode_xstring will be
010C4669726F7A20417368726166020A313233343536373839310313323032312D31312D31372030383A33303A303004063131352E3030050531352E3030
Now convert this to base64, which will become(for the value above)
AQxGaXJveiBBc2hyYWYCCjEyMzQ1Njc4OTEDEzIwMjEtMTEtMTcgMDg6MzA6MDAEBjExNS4wMAUFMTUuMDA=
Hope this helps.
Regards,
hi Firoz Ashraf
I would like to point out that I applied all the above and succeeded in converting the string correctly
Hi Fahad,
I haven't tried my hands much on .NET
However, I have used the following code in excel to convert hexa to base64.
Hi Ashraf,
Please help me for the base64 string
AQxGaXJveiBBc2hyYWYCCjEyMzQ1Njc4OTEDEzIwMjEtMTEtMTcgMDg6MzA6MDAEBjExNS4wMAUFMTUuMDA=
the above value is not getting for the string
Dim str As String = "010C4669726F7A20417368726166020A313233343536373839310313323032312D31312D31372030383A33303A303004063131352E3030050531352E3030"
' Dim byt1 As Byte() = System.Text.Encoding.UTF8.GetBytes("")
txtCode.Text = Convert.ToBase64String(Encoding.UTF8.GetBytes(str))
Private Function EncodeBase64(ByRef arrData() As Byte) As String
Dim objXML As MSXML2.DOMDocument
Dim objNode As MSXML2.IXMLDOMElement
'Dim objXML As Variant
'Dim objNode As Variant
Set objXML = CreateObject("MSXML2.DOMDocument")
Set objNode = objXML.createElement("b64")
objNode.DataType = "bin.base64"
objNode.nodeTypedValue = arrData
EncodeBase64 = objNode.text
Set objNode = Nothing
Set objXML = Nothing
End Function
There must be refence to XML 3.0
and you must use the below function to get results
Puublic Sub Main()
Base64Data = EncodeBase64(StrConv(strData, vbFromUnicode))
End sub
where strdata is the string you are passing to get base64 encoding
Hello FAHAD SHAMARI
I was facing same problme in vba. I solved the problem today in VBA.
Do you want to discuss this problem or problem is already solved for you.
HI ASHRAF,
STRING TO HEX AS TLV BELOW
010C4669726F7A20417368726166
020B2031323334353637383931
031420323032312D31312D31372030383A33303A30300407203131352E3030050531352E3030
COULD YOU PLEASE HELP ME ON THE STEP HEXADECIMAL TO BASE64 STRING
IN .NET ITS NOT RETURNING THE DIFFRENT STRING
MDEwQzQ2Njk3MjZGN0EyMDQxNzM2ODcyNjE2NjAyMEEzMTMyMzMzNDM1MzYzNzM4MzkzMTAzMTMzMjMwMzIzMTJEMzEzMTJEMzEzNzIwMzAzODNBMzMzMDNBMzAzMDA0MDYzMTMxMzUyRTMwMzAwNTA1MzEzNTJFMzAzMA==
You may try the code suggested in
https://blogs.sap.com/2021/11/18/qr-code-in-base64-encoding-for-ksa-e-invoicing/#comment-602235
Hi Firoz,
I got the result to make the conversion in the other language c# than I build as a dll.
thanks for your support and the suggestion.
static string gethexstring(Int32 TagNo, string TagValue)
{
string decString = TagValue;
byte[] bytes = Encoding.UTF8.GetBytes(decString);
string hexString = BitConverter.ToString(bytes);
string StrTagNo = String.Format("0{0:X}", TagNo);
String TagNoVal = StrTagNo.Substring(StrTagNo.Length - 2, 2);
string StrTagValue_Length = String.Format("0{0:X}", bytes.Length);
String TagValue_LengthVal = StrTagValue_Length.Substring(StrTagValue_Length.Length - 2, 2);
hexString = TagNoVal + TagValue_LengthVal + hexString.Replace("-", "");
return hexString;
}
The comments turned your ABAP blog post into questions about programming languages - next comments will be for Python, Javascript, Perl and so on. Good luck! 😀
Hello firoz sir.
Is there any code available for qr code ksa in c#.net
static string gethexstring(Int32 TagNo, string TagValue)
{
string decString = TagValue;
byte[] bytes = Encoding.UTF8.GetBytes(decString);
string hexString = BitConverter.ToString(bytes);
string StrTagNo = String.Format("0{0:X}", TagNo);
String TagNoVal = StrTagNo.Substring(StrTagNo.Length - 2, 2);
string StrTagValue_Length = String.Format("0{0:X}", bytes.Length);
String TagValue_LengthVal = StrTagValue_Length.Substring(StrTagValue_Length.Length - 2, 2);
hexString = TagNoVal + TagValue_LengthVal + hexString.Replace("-", "");
return hexString;
}
Please edit your comment, indicate what programming language it is, and format your code using the {;} button. Thank you.
C# .Net
QR code Arabic in Base64 encoding for KSA E-Invoicing
QR code Arabic in Base64 encoding for KSA E-Invoicing
Dear Firoz
Have a good day!
Waiting for your help.
As a matter of fact, once serial TAG 1,2,3,4,5 is used to identify columns, why length tag is required.
What is the standard set by GAZT to read information from QR Code.
As per their training videos, information shall be readable from any QR Code reader.
Why this shall be compatible with e-invoice reader developed by third party only?
Best regards.
You may convert all the tags into hexa and directly convert the hexa to base64 (without converting first to string and then to base64).
Kindly follow the code mentioned below.
https://blogs.sap.com/2021/11/18/qr-code-in-base64-encoding-for-ksa-e-invoicing/comment-page-1/#comment-601842
As per ZATCA the QR code should be in base64 format. Any QR code reader can read it (which will not be understandable since it is coded). Hence you need a special QR code application (not a general QR code reader) which can decode the base64 and displays the data in text format.
Please find below link of "Guide to develop ZATCA compliant QR code"
https://zatca.gov.sa/en/E-Invoicing/SystemsDevelopers/Documents/QRCodeCreation.pdf
Dear Firoz
Good Afternoon,
Thank you very much. After you sent
https://zatca.gov.sa/en/E-Invoicing/SystemsDevelopers/Documents/QRCodeCreation.pdf
Now this is more clear to formulate and construct QR Code.
Best regards
Can you help me to do this in JAVA ? i am unable to find any source / help to generate this thing in java. thanks in advance
Can you pleaes help me out to write in java ? any code or git repo ?
QRCodeCreation.pdf (zatca.gov.sa)
Please check page no 11 of the pdf file provided by ZATCA
There is already code and example available for Java NodeJS.
You must have NodeJS installed on your computer.
Using Visual Studio Code.
Below Image is only for reference
We shall have any kind of zoom, MS-Teams meeting to work practically and to understand whole procedure as many drawbacks/mis leading information found in all documentations.
As reading and writing makes confusion for everything.
I can arrange a zoom meeting, if we all are agreed.
tried in Angular Typescript but unable to convert.
basically i am using java to create base64 string and jasper report to convert that string into image (QR).
so that i am unable to find any way to conclude
Or we will request Mr. Firoz to have a zoom meeting.
https://www.rapidtables.com/convert/number/ascii-hex-bin-dec-converter.html
Excellent Site for conversion and verification purpose only.
Hexa string is done in JAVA that is same as you have S M Firoz Ashraf
but when i convert it to base64 string, base64 string is different from your base64 converted.
can anybody help me out what is special in conversion of base64? using BTOA javascript string is also different from Ashraf's string.
Final Code in Java:
Hello every one,
Is there any way to convert the arabic string to Hexadecimal in DOT NET?
https://social.msdn.microsoft.com/Forums/en-US/09ef6f6b-288c-4590-a53f-1f43c31238ac/arabic-text-to-hex?forum=aspgettingstarted
Hello,
I am using oracle 11g and reports 6i
is there a way To do this simply?
I already have the qr but doesn’t comply with zatco
thank you
Dear Firoz
Good Day!
What is the next step after completeing QR Code? How to do next step?
Best regards
Are you Completed ZATCA 2nd Phase QR? We want to integrate 2nd phase .
No Harisul, haven't yet started on the 2nd phase development.
Dear Firoz,
I was am able to generate QR Code as you mentioned and it is readable by E-Invoice QR Reader,
First APP
But now they have introduced a new APP, In which this QR code is not readable.
VAT App
Couldn't find any guidelines regarding what are the changes that we need to incorporate. Not sure how to analyze what is issue is.
Could you please help me with this regards.
Dear All,
The above mentioned issue is resolved. It was an issue with the date format.
Best Regards.
Good to know Pradeep
Hi Firoz Ashraf,
Greetings!!
Did you completed the ZATCA 2nd Phase QR code implementation,
with the following tags included
thanks.
Hi Naresh,
Yes we have implemented the 2nd phase of ZATCA.We have purchaseed the SAP CPI and the package itself is taking care of all the integrations as well as QR code.Regards,
Firoz
Hello Naresh,
Did you find any Solution from Tag6 to Tag9 ?
I have all the values above in Place for all the tag, but when trying to convert the TLV is showing error from Tag 8 and 9.
Any help will be helpfull.
Mehul.
zatca phase 2 rules and regulations will now come from January 2023, since now in KSA e invoicing is mandatory.
I think extended upto June 2023.
Firoz may confirm this.
Thanks Firoz Ashraf You describe whole scenario smoothly. I had developed KSA e-invoice QR code in Oracle Apex 23.1.0. Hopefully this will be helpful for oracle apex developers
Demo link: https://apex.oracle.com/pls/apex/r/jasmr/sarafuddin000/qr-code
Guide link: https://github.com/Sarafuddin000/Encoded-QR