GameStick: Purchases implemented

The PlayJam GameStick community server software got another feature: Purchases. You are now able to buy games (instead of having all of them available for free) and in-game products like levels and powerups.

Your wallet has an infinite amount of money, so you don't risk going broke :)

Purchasing games

All games - even already installed ones - have to be bought now. After buying, the game download starts automatically.

The purchase dialog is a web view, displaying a HTML page delivered by the server. I had no idea how it looked like - there were no screenshots to find with my Google-Fu. In the end I found a video of Lee Chapman demoing the Gamestick, and near the end he buys Riptide.

I took screenshots, resized and warped them until they had the correct aspect ratio and size. Then I re-built the layout in HTML and CSS that a 2013 browser understands.

There was no documentation about the purchase requests and responses. The requests were easy to document since I could see them in the server logs, but the responses were hard: Some of them are handled in the Java library, while others are passed to the Marmalade UI and parsed there. The important things like "success, download now" were of course in the compiled C code, and I was forced to use Ghidra to make a bit sense of it.

The magic words are:

{
    "body": {
        "success": true,
        "message": null,
        "action": "CLOSEPAYMENT"
    }
}

Purchasing a game

Implementing purchases fixed a long-standing bug: The "uninstalled apps" view in the settings crashed, probably the Marmalade interface was never meant to handle 188 games. Now only the purchased games are listed there - without crashing.

Uninstalled apps

In-game products

A number of games have in-game products: "Top Gear: Stunt School" allows to buy nuts, dollars and permits. In "Pacman Tournaments" you can buy tokens (3500 for 99.99USD!), "Rise of Glory" lets you spend money on airplane packs and in Prince of Persia you can buy coins (1000 for 1.99, 100000 for 99.99$).

Of course we did not have backups and I had to decompile the game apk files to find the product IDs that they used. Products had to be registered at the server, and the game only asks the server which products are available.

More often than not, decompiling did not work because the game was made with Unity or some other engine, and I miss the tools to unpack those files. In this cases I let the server return all products ids from 1 to 1000, with prices from 0.01€ to 10.00€, and could immediately see which products were used. This did of course only work on some games; others crashed when they received more than 15 products.

OUYA games were much easier in this regard: They send all supported product keys to the server, making it a breeze to quickly add products for unsupported games. Although, easier only after I broke their DRM :)

At one point I was finished and had only find products for the last game, Repulze. Then I saw that - instead of sending integer number product IDs, just as all other games do - this game sends string keys like com.pixelbite.repulze.iap.toolkit_pack1! I had to modify the database, parts of the purchase API and the game data schema to support that :(

But now this feature is really complete, and you can purchase things in the following games:

Start buying in-game product Confirm Purchase successful

Game archival status

In 2024-09 we had 163 of 188 games archived. Thanks to GameStick fans Kazdan, Krzysiu, Ryo and TheMartinMess22 we have 170 now, a whopping 90.4%!

Newly rescued games:

Also on: Mastodon, Twitter.

Written by Christian Weiske.

Comments? Please send an e-mail.