简体   繁体   中英

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);
  }

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.

It looks like ClickBank they always send it in the same format with only the two top level fields "notification" and "verification". So you can just use substr to remove the first 16 characters ( {"notification": ) and the last 27 characters ( ,"verification":"XXXXXXXX"} ) from the raw JSON and then proceed from there:

$notification = substr($json, 16, -27);
$verification = strtoupper( substr( hash('sha1', $notification . $secret), 0, 8) );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM