Announcements
Hi, can any experts here have any idea or guidance how can I develop CRC16 (checksum) calculation from a given string by using code? Many thanks.
Example in Javascript
I'm not claiming that I know which implementation you need. My point was that you can reuse existing implementation written in languages like C#, instead of implementing it by yourself in X++. There are many of them; decide yourself which one works for you.
If you want, you can debug the code or statically compare the algorithm in JavaScript with the one in C#. But that's exactly what I would avoid. :-)
By the way, please always use Insert > Insert Code (in the rich-formatting view) to paste source code. It preserves indentation, making code much easier to read.
I did not change much on the crc16 calculation. Mainly copy from this link you shared to me sanity-free.org/.../crc_16_ccitt_in_csharp.html
I only change to accept string instead of byte array. Here is the C# code:
public enum InitialCrcValue { Zeros, NonZero1 = 0xffff, NonZero2 = 0x1D0F }
public class Crc16Ccitt
{
const ushort poly = 4129;
ushort[] table = new ushort[256];
ushort initialValue = 0;
public ushort ComputeChecksum(byte[] bytes)
{
ushort crc = this.initialValue;
for (int i = 0; i < bytes.Length; ++i)
{
crc = (ushort)((crc << 8) ^ table[((crc >> 8) ^ (0xff & bytes[i]))]);
}
return crc;
}
public static string ComputeChecksumBytes(string _str)
{
Crc16Ccitt Crc16Ccitt = new Crc16Ccitt(InitialCrcValue.NonZero1);
byte[] bytes = Encoding.ASCII.GetBytes(_str);
ushort crc = Crc16Ccitt.ComputeChecksum(bytes);
byte[] crcByte = BitConverter.GetBytes(crc);
string crcStr = BitConverter.ToString(crcByte.Reverse().ToArray()).Replace("-", "");
return crcStr;
}
public Crc16Ccitt(InitialCrcValue initialValue)
{
this.initialValue = (ushort)initialValue;
ushort temp, a;
for (int i = 0; i < table.Length; ++i)
{
temp = 0;
a = (ushort)(i << 8);
for (int j = 0; j < 8; ++j)
{
if (((temp ^ a) & 0x8000) != 0)
{
temp = (ushort)((temp << 1) ^ poly);
}
else
{
temp <<= 1;
}
a <<= 1;
}
table[i] = temp;
}
}
}
An interesting thing is that it isn't simply reversed, because it would be 48AA and not 84AA.
Your code for displaying the data looks correct to me, therefore I believe that the problem is in ComputeChecksumBytes() and not in your code above.
Hi Martin, I manage to get the result, for example AA84, one question any idea why the order is reverse? Meaning the result I'm getting is 84AA.
I've created a sample Main method for testing:
static void Main(string[] args)
{
string s = "00020101021226490009SG.PAYNOW010120210200905428D0301004082026020652040000530370254041.005802SG5920AXIONSPLUS PTE. LTD.6009Singapore62140110FTI00000306304";
byte[] crcStr = ChecksumGeneratorCrc16Ccitt.Crc16Ccitt.ComputeChecksumBytes(s);
StringBuilder hex = new StringBuilder(crcStr.Length * 2);
foreach (byte b in crcStr)
hex.AppendFormat("{0:x2}", b);
Console.WriteLine(hex.ToString());
Console.WriteLine(BitConverter.ToString(crcStr).Replace("-", ""));
}
It will help if you tell us more about those weird characters.
Isn't it Byte Order Mark (BOM)?
Hi Martin, I did implement Crc16Ccitt codes mentioned in this link sanity-free.org/.../crc_16_ccitt_in_csharp.html
and in my test runnable job I have this codes to test out but the result i'm getting is 2 weird symbol. Am I doing it correctly from D365 FO?
str postData = "00020101021226490009SG.PAYNOW010120210200905428D0301004082026020652040000530370254041.005802SG5920AXIONSPLUS PTE. LTD.6009Singapore62140110FTI00000306304";
System.Byte[] byteArray;
System.Text.Encoding encodingUTF8;
encodingUTF8 = System.Text.Encoding::get_UTF8();
byteArray = encodingUTF8.GetBytes(postData);
byteArray = ChecksumGeneratorCrc16Ccitt.Crc16Ccitt::ComputeChecksumBytes(byteArray);
info(strFmt("Text CRC: %1", encodingUTF8.GetString(byteArray)));
How should I display the return byte array if is not as below?
There are many CRC-16 algorithms and you seem to want a particular one, but you didn't specify which one.
If I put your input to crccalc.com, I get AA8A from the algorithm called CRC-16/CCITT-FALSE. Therefore that seems to be what you need.
At the bottom of the page I mention before, you'll find links to implementation of CCITT algorithms - you can try them. Or look for other implementations on the internet.
Hi Martin, the required string format that will be translated into QR code is in ASCII format for example,
00020101021226490009SG.PAYNOW010120210200905428D0301004082026020652040000530370254041.005802SG5920AXIONSPLUS PTE. LTD.6009Singapore62140110FTI00000306304AA84
The last 4 characters "AA84" is the checksum of the whole string exclude "AA8A". I've implement the C# library from the given link and pass in the string and encode it with UTF8 but I'm not able to get the same checksum "AA84". I also did try using ASCII encoding which does not work as well.
The checksum "AA84" is generated from a javascript code but I would assume crc16 check is the same regardless of what code platform.
l'm sorry, but I don't know why you chose ASCII and whether it's correct in your case, how the result you got differ from the expected result and so on. I also don't undestand what you mean by "the QR code is valid but not with the logic I refer from the link".
Please try to collect more information and share it with us.
Hi Martin,
I try using ASCII encoding for a given string text but the result of the checksum is not correct as the whole string return with the checksum is not recognize by the payment scanning. I'm trying to append a 4 char checksum to a string of given format in order to generate the QR code.
From this sample in Github github.com/.../PaynowQR by running their sample JS program the QR code is valid but not with the logic I refer from the link you shared to me. I'm not sure whether is the checksum calculation or something else.
André Arnaud de Cal...
294,208
Super User 2025 Season 1
Martin Dráb
232,970
Most Valuable Professional
nmaenpaa
101,158
Moderator