Search code examples
phpjsonvalidationclickbank

json_decode Preservation of Type


I'm using the json_decode function to decode (and verify a postback from a payment processor). the json object received looks as follow

{
   "notification":{
      "version":6.0,
      "attemptCount":0,
      "role":"VENDOR",
      .....
      "lineItems":[
         {
            "itemNo":"1",
            "productTitle":"A passed in title",
            "shippable":false,
            "recurring":false,
            "customerProductAmount":1.00,
            "customerTaxAmount":0.00
         }
      ]
   },
   "verification":"9F6E504D"
}

The verification works as follows, one takes the notification node and append a secret key. The first eight characters of the SHA1 hash of this string should match the content of the validation node.

However, I noticed that whilst using json_decode, the double value 6.0, 0.00 etc are truncated to integers (6, 0 ,etc). This messes up the string (in terms of it not generating the correct SHA1-hash). Do note, I cannot use the depth limit to prevent decoding of the notification branch, since I need to support PHP 5.0. How can I tackle this issue. The (defect) validation code I wrote is:

  public function IPN_Check(){
    $o = (json_decode($this->test_ipn));
    $validation_string = json_encode($o->notification);
  }

Solution

  • I tried the following:

    <?php
    
    var_dump(json_decode('
    {
       "notification":{
          "version":6.0,
          "attemptCount":0
       }
    }
    '));
    

    and got this output:

    object(stdClass)#1 (1) {
      ["notification"]=>
      object(stdClass)#2 (2) {
        ["version"]=>
        float(6)
        ["attemptCount"]=>
        int(0)
      }
    }
    

    PHP does make a difference between float and int, maybe you could do something like gettype($o->notification[$i]) == 'float' to check whether you need to add a zero using a string.

    UPD. PHP does make a difference between float and int, but json_encode() - may not. To be sure, that you encode all values as they are - use json_encode() with JSON_PRESERVE_ZERO_FRACTION parameter, and all your float/double types will be saved correctly.