{"id":51042,"date":"2011-11-01T20:55:36","date_gmt":"2011-11-01T20:55:36","guid":{"rendered":"http:\/\/barrycarlyon.co.uk\/wordpress\/?p=51042"},"modified":"2015-02-11T03:46:33","modified_gmt":"2015-02-11T03:46:33","slug":"facebook-credits-the-order-id-and-dealing-with-large-integers-in-32-bit-php","status":"publish","type":"post","link":"https:\/\/barrycarlyon.co.uk\/wordpress\/2011\/11\/01\/facebook-credits-the-order-id-and-dealing-with-large-integers-in-32-bit-php\/","title":{"rendered":"Facebook Credits, the Order ID, and dealing with large integers in 32 bit PHP"},"content":{"rendered":"<p>So, currently at work I&#8217;ve been rewriting all our Payment Gateways for Your Members. Making them more better Class based an abstracting out the common functions to a base class, to save memory footprint and code etc.<\/p>\n<p>And came across a problem when rewriting the Facebook Credits handler.<\/p>\n<p>The order ID that gets passed around, as well as the Application ID is too long for a 32 Bit PHP installation to handle when treating it as an Integer.<\/p>\n<p>So a number like &#8220;239724439419867&#8221; was ending up as &#8220;1.7592246582797E+14&#8221; when stored\/processed, or converted to a string.<br \/>\nNow the obvious way to process this is to convert it to a string another way, which is somewhat difficult since before you even start it is in a format that you can&#8217;t handle.<\/p>\n<p>The saving grace here is the fact that data is passed to you as a JSON packet (aside from the fact the Order ID is in the $_POST variable and thus a string, so I could of used it from there).<\/p>\n<p>This led to me to look at the JSON packet, which starts as a string but when decoded the large integers are still a larger integer than can be processed (whether you json_decode to a Array or to an Object, the problem persists). So I thought about how to process the raw JSON packet and make sure the order ID, and other large integers are treated as strings.<\/p>\n<p>If you look at a Raw JSON packet you can easily spot whats a string, integer, object or array.<\/p>\n<p>Take this example Facebook Credits JSON Packet, (wrapped for readability):<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n{&quot;order_id&quot;:239724439419867,&quot;buyer&quot;:197803678,&quot;app&quot;:148748711865470,\r\n&quot;receiver&quot;:197803678,&quot;amount&quot;:5,&quot;update_time&quot;:1320075413,\r\n&quot;time_placed&quot;:1320075408,&quot;data&quot;:&quot;&quot;,&quot;items&quot;:&#x5B;{&quot;item_id&quot;:&quot;&lt;item_id&gt;&quot;,&quot;title&quot;:&quot;Post&quot;,\r\n&quot;description&quot;:&quot;A New Purchasable Post&quot;,\r\n&quot;image_url&quot;:&quot;&lt;some url&gt;&quot;,&quot;product_url&quot;:&quot;&lt;some other url&gt;&quot;,\r\n&quot;price&quot;:5,&quot;data&quot;:&quot;&lt;data&gt;&quot;}],&quot;status&quot;:&quot;&lt;status&gt;&quot;}\r\n<\/pre>\n<ul>\n<li>order_id is an integer as it has no &#8221; around it<\/li>\n<li>status is a string as its surrounded by &#8220;<\/li>\n<li>Items is an array as its surrounded by [, in this case containing a single object, entries\/items are comma separated.<\/li>\n<\/ul>\n<p>So after thinking about this I decided the best way to sort this out was to convert the integers in the raw JSON packet to strings before decoding.<\/p>\n<p>In pseudo code.<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nLop off the { and } from the start and end\r\nExplode around ,\r\narray walk each item\r\nsplit on :\r\ncheck if there are no &quot; in the second bit\r\nif none wrap in &quot;\r\nglue back together\r\n<\/pre>\n<p>Something alone the lines of:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\nfunction largeint($rawjson) {\r\n  $rawjson = substr($rawjson, 1, -1);\r\n  $rawjson = explode(',' , $rawjson);\r\n  array_walk($rawjson, 'strfun');\r\n  $rawjson = implode(',', $rawjson);\r\n  $rawjson = '{', . $rawjson . '}';\r\n  $json = json_decode($rawjson);\r\n  return $json;\r\n}\r\n\r\nfunction strfun(&amp;$entry, $key) {\r\n  $data = explode(':', $entry);\r\n  if (FALSE === strpos($data&#x5B;1], '&quot;')) {\r\n    $data&#x5B;1] = '&quot;' . $data&#x5B;1] . '&quot;';\r\n    $entry = implode(':', $data);\r\n  }\r\n}\r\n<\/pre>\n<p>I&#8217;m not sure in terms of memory footprint if its cheaper to do a substr of $data[1] and check if its a &#8221; or not.<br \/>\nI suppose it could test the string length of the detected integer to see if its invalid\/unable to process, but then you would be performing a string function on an integer and again the problem would arise.<\/p>\n<p>But as a block of code is does the job, its obviously not ideal for all situations, since in this case I want the integer as a string, I&#8217;m not using it for math, but if I did, we probably need to do some bizarre unpack-ing or something.<\/p>\n<p>Any opinions or improvements give us a comment below \ud83d\ude00<\/p>\n","protected":false},"excerpt":{"rendered":"<p>So, currently at work I&#8217;ve been rewriting all our Payment Gateways for Your Members. Making them more better Class based an abstracting out the common functions to a base class, to save memory footprint and code etc. And came across a problem when rewriting the Facebook Credits handler. The order ID that gets passed around, &hellip; <a href=\"https:\/\/barrycarlyon.co.uk\/wordpress\/2011\/11\/01\/facebook-credits-the-order-id-and-dealing-with-large-integers-in-32-bit-php\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Facebook Credits, the Order ID, and dealing with large integers in 32 bit PHP&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[88,198,175,45,27,177],"tags":[220,219,210,82,172,224,222,221,84,223],"class_list":["post-51042","post","type-post","status-publish","format-standard","hentry","category-code-geekery","category-code-snippets","category-codingfutures","category-geekery","category-work","category-ym","tag-32-bit","tag-64-bit","tag-api","tag-code","tag-facebook-2","tag-facebook-credits","tag-json","tag-large-int","tag-php","tag-string-manipulation"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/posts\/51042","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/comments?post=51042"}],"version-history":[{"count":1,"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/posts\/51042\/revisions"}],"predecessor-version":[{"id":51695,"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/posts\/51042\/revisions\/51695"}],"wp:attachment":[{"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/media?parent=51042"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/categories?post=51042"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/barrycarlyon.co.uk\/wordpress\/wp-json\/wp\/v2\/tags?post=51042"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}