Reputation: 43
I'm receiving an HTTP Post with the following JSON object:
{"notification":{"version":6.0,"attemptCount":0,"role":"VENDOR","site":"nicholeen","receipt":"********","currency":"USD","transactionType":"TEST","transactionTime":1406070122781,"paymentMethod":"VISA","totalProductAmount":1.00,"totalTaxAmount":0.00,"totalShippingAmount":0.00,"customer":{"shipping":{"firstName":"TEST","lastName":"USER","fullName":"Test User","email":"[email protected]","address":{}},"billing":{"firstName":"TEST","lastName":"USER","fullName":"Test User","email":"[email protected]","address":{}}},"lineItems":[{"itemNo":"1","productTitle":"A passed in title","shippable":false,"recurring":false,"customerProductAmount":1.00,"customerTaxAmount":0.00}]},"verification":"2745A502"}
I need to Convert the "notification" JSON object into a JSON string assigned to a PHP variable without losing any data, including the decimals.
Currently I'm receiving the IPN using $ipn_raw = file_get_contents('php://input');
.
Then I json_decode the JSON to a PHP variable, then re-encode the notification portion using json_encode. Here's the code:
$ipn_raw = file_get_contents('php://input');
$ipn = json_decode($ipn_raw);
$notification = $ipn['notification'];
$result = json_encode($notification);
However, the result strips some values giving me the following:
{"version":6,"attemptCount":0,"role":"VENDOR","site":"nicholeen","receipt":"********","currency":"USD","transactionType":"TEST","transactionTime":1406095846441,"paymentMethod":"VISA","totalProductAmount":1,"totalTaxAmount":0,"totalShippingAmount":0,"customer":{"shipping":{"firstName":"TEST","lastName":"USER","fullName":"Test User","email":"[email protected]","address":[]},"billing":{"firstName":"TEST","lastName":"USER","fullName":"Test User","email":"[email protected]","address":[]}},"lineItems":[{"itemNo":"1","productTitle":"A passed in title","shippable":false,"recurring":false,"customerProductAmount":1,"customerTaxAmount":0}]}
You can see that version 6.0 is now just version 6, totalProductAmount was 1.00 and is now 1, etc.
How can I do this without any values changing in the result?
Thanks!
Per request, here's some extra background information for why I need everything to be unchanged from the original. Clickbank has given me the following information in order to create the necessary SHA 1 hash to validate the Version 6 IPN I receive from them (see https://support.clickbank.com/entries/22803622-Instant-Notification-Service)
1) Use a JSON library/DSL to extract the “notification” JSON object from the IPN. 2) Convert the "notification" JSON object into a JSON string. The string should begin with a curly brace { and end with a curly brace } as it is a representation of a JSON object. 3) Append the secret key directly onto the string after the end curly brace of the notification object. No spaces or separator characters. 4) SHA 1 hash the string created in step 3. 5) Take the first 8 characters of the hash created in step 4. That’s the value of the "verification" field in the v6 IPN.
If needed I could provide all my code for the rest of the steps, but at this point the only part I'm having problems with is getting the notification object in a string by itself.
Upvotes: 4
Views: 833
Reputation: 43
For anyone who's interested, here's what I ended up using:
$json_ipn = preg_replace('({"notification":|,"verification"([\s\S]*))', '', $ipn_raw);
Upvotes: 0
Reputation: 265241
What you are asking (given the fact that you are hashing the string representation of the JSON object), you'd need to extract the relevant portion of your JSON by string manipulation methods (e.g. regex):
$result = preg_replace(array('^\{[^{]', '[^}]\}$'), '', $in);
This will strip everything up to the second curly brace in the beginning, and everything from the second last curly brace from the end. (But it will obviously only work if your JSON has this exact format, i.e. notification is the only nested object, the first object, and everything that comes after that contains no }
(especially the verification code))
There seems to be a "bug" report about this: https://bugs.php.net/bug.php?id=50224, although it seems that stringifying 6.0
is expected behavior and JavaScript does the same thing. Also see this related question: PHP function json_decode decodes float value with zeros after point as int
Upvotes: 2
Reputation: 37365
The problem is: both 6.0
and 6
are same floats from viewpoint of values. Thus, while decoding, PHP will lose this decimal format points. So on your first json_decode()
call you'll already lose your data about how many decimal points were there.
The way to resolve may be to enclose your values in-place in raw source json with quites, to turn them into strings and store them in PHP in that format. It's like:
$jsonRaw = '{"notification":{"version":6.0,"attemptCount":0,"role":"VENDOR","site":"nicholeen","receipt":"********","currency":"USD","transactionType":"TEST","transactionTime":1406070122781,"paymentMethod":"VISA","totalProductAmount":1.00,"totalTaxAmount":0.00,"totalShippingAmount":0.00,"customer":{"shipping":{"firstName":"TEST","lastName":"USER","fullName":"Test User","email":"[email protected]","address":{}},"billing":{"firstName":"TEST","lastName":"USER","fullName":"Test User","email":"[email protected]","address":{}}},"lineItems":[{"itemNo":"1","productTitle":"A passed in title","shippable":false,"recurring":false,"customerProductAmount":1.00,"customerTaxAmount":0.00}]},"verification":"2745A502"}';
$jsonRaw = preg_replace('/(\b)([0-9]+\.[0-9]+)(\b)/', '$1"$2"$3', $jsonRaw);
$jsonObj = json_decode($jsonRaw);
So now your object will store your values as strings and that won't cause losing of decimal points. Of course, with decoding you'll need to do reverse thing:
$notification = $jsonObj->notification;
$result = json_encode($notification);
$result = preg_replace('/"([0-9]+\.[0-9]+)"/', '$1', $result);
But this has a flaw: because you'll lose data about what were actual strings and what were floats. So if your original json contains string like "6.00"
and it's intended to be string, such conversion will lose that information and make that value float. So if your data contain such strings in this form, then - yes, it's not the way to go (but then I doubt there is an easy way to go without implementing your own json parser)
Upvotes: 1