Search code examples
phpmodulofix-protocol

Calculate Modulo 256 Checksum in PHP


I've searched Stackoverflow already and unfortunately nothing came up. I am working with the FIX protocol and I need to generate a Modulo 256 checksum as described at http://fixwiki.fixprotocol.org/fixwiki/CheckSum.

$count = strlen($message);
$count = $count % 256;
$checksum = 256 - $count;

if(strlen($checksum) == 1) {
    $checksum = '00' . $checksum;   
}

if(strlen($checksum) == 2) {
    $checksum = '0' . $checksum;    
}

Using the FIX string of:

8=FIX.4.2|9=42|35=0|49=A|56=B|34=12|52=20100304-07:59:30

It should return:

8=FIX.4.2|9=42|35=0|49=A|56=B|34=12|52=20100304-07:59:30|10=185|

However my script returns:

8=FIX.4.2|9=42|35=0|49=A|56=B|34=12|52=20100304-07:59:30|10=199|

I'd be grateful if someone could point me in the right direction!


Solution

  • According to http://fixwiki.fixprotocol.org/fixwiki/CheckSum the checksum isn't just the length of the message modulo 256.
    It's the sum of each character (as ascii value) modulo 256.

    <?php
    define('SOH', chr(0x01));
    
    $message = '8=FIX.4.2|9=42|35=0|49=A|56=B|34=12|52=20100304-07:59:30|';
    $message = str_replace('|', SOH, $message);
    echo $message, GenerateCheckSum($message);
    
    function GenerateCheckSum($message) {
        $sum = array_sum(
            array_map(
                'ord', 
                str_split($message, 1)
            )
        );
        $sum %= 256;
        return sprintf('10=%03d%s', $sum, SOH);
    }
    

    prints

    8=FIX.4.2 9=42 35=0 49=A 56=B 34=12 52=20100304-07:59:30 10=185
    

    or to stay closer to the example function in the documentation

    <?php
    define('SOH', chr(0x01));
    
    $message = '8=FIX.4.2|9=42|35=0|49=A|56=B|34=12|52=20100304-07:59:30|';
    $message = str_replace('|', SOH, $message);
    echo $message, '10=', GenerateCheckSum($message, strlen($message)), SOH;
    
    function GenerateCheckSum($buf, $bufLen )
    {
       for( $idx=0, $cks=0; $idx < $bufLen; $cks += ord($buf[ $idx++ ]) );
       return sprintf( "%03d", $cks % 256);
    }