Skip to main content

Notifications

Community site session details

Community site session details

Session Id :
Finance | Project Operations, Human Resources, ...
Answered

CRC16 calculation in AX or D365 FO

(0) ShareShare
ReportReport
Posted on by

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

crc16(s) {
    var crcTable = [0x00000x10210x20420x30630x40840x50a5,
      0x60c60x70e70x81080x91290xa14a0xb16b,
      0xc18c0xd1ad0xe1ce0xf1ef0x12310x0210,
      0x32730x22520x52b50x42940x72f70x62d6,
      0x93390x83180xb37b0xa35a0xd3bd0xc39c,
      0xf3ff0xe3de0x24620x34430x04200x1401,
      0x64e60x74c70x44a40x54850xa56a0xb54b,
      0x85280x95090xe5ee0xf5cf0xc5ac0xd58d,
      0x36530x26720x16110x06300x76d70x66f6,
      0x56950x46b40xb75b0xa77a0x97190x8738,
      0xf7df0xe7fe0xd79d0xc7bc0x48c40x58e5,
      0x68860x78a70x08400x18610x28020x3823,
      0xc9cc0xd9ed0xe98e0xf9af0x89480x9969,
      0xa90a0xb92b0x5af50x4ad40x7ab70x6a96,
      0x1a710x0a500x3a330x2a120xdbfd0xcbdc,
      0xfbbf0xeb9e0x9b790x8b580xbb3b0xab1a,
      0x6ca60x7c870x4ce40x5cc50x2c220x3c03,
      0x0c600x1c410xedae0xfd8f0xcdec0xddcd,
      0xad2a0xbd0b0x8d680x9d490x7e970x6eb6,
      0x5ed50x4ef40x3e130x2e320x1e510x0e70,
      0xff9f0xefbe0xdfdd0xcffc0xbf1b0xaf3a,
      0x9f590x8f780x91880x81a90xb1ca0xa1eb,
      0xd10c0xc12d0xf14e0xe16f0x10800x00a1,
      0x30c20x20e30x50040x40250x70460x6067,
      0x83b90x93980xa3fb0xb3da0xc33d0xd31c,
      0xe37f0xf35e0x02b10x12900x22f30x32d2,
      0x42350x52140x62770x72560xb5ea0xa5cb,
      0x95a80x85890xf56e0xe54f0xd52c0xc50d,
      0x34e20x24c30x14a00x04810x74660x6447,
      0x54240x44050xa7db0xb7fa0x87990x97b8,
      0xe75f0xf77e0xc71d0xd73c0x26d30x36f2,
      0x06910x16b00x66570x76760x46150x5634,
      0xd94c0xc96d0xf90e0xe92f0x99c80x89e9,
      0xb98a0xa9ab0x58440x48650x78060x6827,
      0x18c00x08e10x38820x28a30xcb7d0xdb5c,
      0xeb3f0xfb1e0x8bf90x9bd80xabbb0xbb9a,
      0x4a750x5a540x6a370x7a160x0af10x1ad0,
      0x2ab30x3a920xfd2e0xed0f0xdd6c0xcd4d,
      0xbdaa0xad8b0x9de80x8dc90x7c260x6c07,
      0x5c640x4c450x3ca20x2c830x1ce00x0cc1,
      0xef1f0xff3e0xcf5d0xdf7c0xaf9b0xbfba,
      0x8fd90x9ff80x6e170x7e360x4e550x5e74,
      0x2e930x3eb20x0ed10x1ef0];
  
    var crc = 0xFFFF;
    var ji;
  
    for (i = 0i < s.lengthi++) {
  
      let c = s.charCodeAt(i);
      if (c > 255) {
        throw new RangeError();
      }
      j = (c ^ (crc >> 8)) & 0xFF;
      crc = crcTable[j] ^ (crc << 8);
    }
  
    return ((crc ^ 0) & 0xFFFF).toString(16).toUpperCase();
  }
  • Martin Dráb Profile Picture
    232,970 Most Valuable Professional on at
    RE: CRC16 calculation in AX or D365 FO

    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.

  • Community Member Profile Picture
    on at
    RE: CRC16 calculation in AX or D365 FO

    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;

               }

           }

       }

  • Martin Dráb Profile Picture
    232,970 Most Valuable Professional on at
    RE: CRC16 calculation in AX or D365 FO

    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.

  • Community Member Profile Picture
    on at
    RE: CRC16 calculation in AX or D365 FO

    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("-", ""));
    }

    pastedimage1612838746520v1.png

  • Martin Dráb Profile Picture
    232,970 Most Valuable Professional on at
    RE: CRC16 calculation in AX or D365 FO

    It will help if you tell us more about those weird characters.

    Isn't it Byte Order Mark (BOM)?

  • Community Member Profile Picture
    on at
    RE: CRC16 calculation in AX or D365 FO

    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?

  • Suggested answer
    Martin Dráb Profile Picture
    232,970 Most Valuable Professional on at
    RE: CRC16 calculation in AX or D365 FO

    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.

  • Community Member Profile Picture
    on at
    RE: CRC16 calculation in AX or D365 FO

    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.

  • Martin Dráb Profile Picture
    232,970 Most Valuable Professional on at
    RE: CRC16 calculation in AX or D365 FO

    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.

  • Community Member Profile Picture
    on at
    RE: CRC16 calculation in AX or D365 FO

    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.

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

🌸 Community Spring Festival 2025 Challenge 🌸

WIN Power Platform Community Conference 2025 tickets!

Jonas ”Jones” Melgaard – Community Spotlight

We are honored to recognize Jonas "Jones" Melgaard as our April 2025…

Kudos to the March Top 10 Community Stars!

Thanks for all your good work in the Community!

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 294,208 Super User 2025 Season 1

#2
Martin Dráb Profile Picture

Martin Dráb 232,970 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,158 Moderator

Leaderboard

Product updates

Dynamics 365 release plans