Facebook Credits, the Order ID, and dealing with large integers in 32 bit PHP

So, currently at work I’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, as well as the Application ID is too long for a 32 Bit PHP installation to handle when treating it as an Integer.

So a number like “239724439419867” was ending up as “1.7592246582797E+14” when stored/processed, or converted to a string.
Now 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’t handle.

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).

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.

If you look at a Raw JSON packet you can easily spot whats a string, integer, object or array.

Take this example Facebook Credits JSON Packet, (wrapped for readability):

{"order_id":239724439419867,"buyer":197803678,"app":148748711865470,
"receiver":197803678,"amount":5,"update_time":1320075413,
"time_placed":1320075408,"data":"","items":[{"item_id":"<item_id>","title":"Post",
"description":"A New Purchasable Post",
"image_url":"<some url>","product_url":"<some other url>",
"price":5,"data":"<data>"}],"status":"<status>"}
  • order_id is an integer as it has no ” around it
  • status is a string as its surrounded by “
  • Items is an array as its surrounded by [, in this case containing a single object, entries/items are comma separated.

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.

In pseudo code.

Lop off the { and } from the start and end
Explode around ,
array walk each item
split on :
check if there are no " in the second bit
if none wrap in "
glue back together

Something alone the lines of:

function largeint($rawjson) {
  $rawjson = substr($rawjson, 1, -1);
  $rawjson = explode(',' , $rawjson);
  array_walk($rawjson, 'strfun');
  $rawjson = implode(',', $rawjson);
  $rawjson = '{', . $rawjson . '}';
  $json = json_decode($rawjson);
  return $json;
}

function strfun(&$entry, $key) {
  $data = explode(':', $entry);
  if (FALSE === strpos($data[1], '"')) {
    $data[1] = '"' . $data[1] . '"';
    $entry = implode(':', $data);
  }
}

I’m not sure in terms of memory footprint if its cheaper to do a substr of $data[1] and check if its a ” or not.
I 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.

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’m not using it for math, but if I did, we probably need to do some bizarre unpack-ing or something.

Any opinions or improvements give us a comment below 😀

Some Random Useful Things

Some random useful things:

Twitter, is scrapping Basic Auth! Which means no more simple curl calls, its on to OAuth.

Check out http://dev.twitter.com/pages/basic_to_oauth for how to update your Apps/Usage, and http://countdowntooauth.com/ for a handy countdown.

In other twitter news, I use Notifo to forward my twitter replies to my iPhone, which uses Push.ly to grab the stream. Twitter has currently borked @Replies both in apps and on the website, however Notifo announced they have updated their website with a new design, (hurrah), and a desktop client (further hurrah).
So with my mac and growl I now get Growl @ Responses….. SUCCESS!

Thats enough twitter! I was linked in a random IRC channel to http://jsfiddle.net/, which is a sort of real time code and run/test interface for several different javascript libs, including MooTools, and jQuery. Its currently in Alpha and under “heavy development”, so far I have found it quite useful, since it saves a lot of time in prototyping something. Looking forward to when they add user accounts, will be easier to track my own fiddles, heres the 5th version of me fiddling with jQuery UI tabs yes it has basic version control!

Facebook next, came across this today: http://developers.facebook.com/roadmap pretty much nails the coffin shut on FBML and suggests that we will all be using iFrames instead….

Not sure if this is a good thing or a bad thing, since iFrames are not always the most secure of things, but will make sending more upto date stuff to a Facebook page easier. And no longer stuck with Facebook caching, which in itself is a useful thing….

Also they are moving to a larger oauth setting with the use of oauth version 2! And scrapping their Rest API.

So there is a lot of change going on within two of the larger things I have been involved with (in terms of building things for clients), so in this vein when is the Last.FM api moving to oAuth too, tho it does use a token based Auth now?!

I’m gonna need to do a lot of recoding/refactoring for things that use FBML and basic Auth….

Is oAuth the future for all API’s? What do you think?

Edit:

O and I am going to invest in one of these!