question

SimkinTas avatar image
SimkinTas asked

Using Gameon from Alexa via Javascript

Has anyone tried to use Gameon from Javascript and Alexa yet? I would like to use Gameon from an Alexa skill, and some parameters like "advertisingId" may not exist on Alexa in the same manner that they do on phones, so wondering if I can just make up a value for that.

Also, any existing Javascript code libraries that work would be appreciated, otherwise I will try and create a new JS library. Seems like a JS library should be created and put on NPM so that it could be easy for all NodeJS programs to use it in the future.

Thanks everyone for any advice.

alexa skills kitgameon
10 |3000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

SimkinTas avatar image
SimkinTas answered

So, I got Gameon working via Javascript and also for an Alexa Skill, the basic part of the REST requests was easy after I figured out the signing code. Copy/Pasting the following parts of some NodeJS code that may be helpful, I am sure there are better ways/RSA modules to use than the ones used below. Hope this helps someone.

const request = require('request');
const crypto = require("crypto");
const RSAKey = require('rsa-key');

// Encrypt the client public key using the game's public key
function getEncryptedPayload() {

    /* Import the key in any format*/
    var key = new RSAKey(GAME_PUBLIC_KEY);   
    /* Export key in default format (PEM PKCS8) */
    var pemKey = key.exportKey();

    let buffer = new Buffer(CLIENT_PUBLIC_KEY);
    let encrypted = crypto.publicEncrypt({key: pemKey, padding: crypto.constants.RSA_PKCS1_PADDING}, buffer);

    let encryptedPayload = encrypted.toString("base64");
    return encryptedPayload;
}

// Now decrypt the player token using the client private key
function decryptPlayerToken(encryptedPlayerToken) {

    let privateKey = new RSAKey(CLIENT_PRIVATE_KEY);
    let privatePemKey = privateKey.exportKey();

    let newBuffer = new Buffer(encryptedPlayerToken, "base64");

    let decryptedPlayerToken = crypto.privateDecrypt({key: privatePemKey, padding: crypto.constants.RSA_PKCS1_PADDING}, newBuffer);
    let playerToken = decryptedPlayerToken.toString();

    return playerToken;
}

// Now encrypt the player token using the game's public key
function encryptPlayerToken(playerToken) {
    /* Import the key in any format*/
    var key = new RSAKey(GAME_PUBLIC_KEY);   
    /* Export key in default format (PEM PKCS8) */
    var pemKey = key.exportKey();

    let buffer = new Buffer(playerToken);
    let encrypted = crypto.publicEncrypt({key: pemKey, padding: crypto.constants.RSA_PKCS1_PADDING}, buffer);

    let encryptedPayload = encrypted.toString("base64");
    return encryptedPayload;
}

exports.adminRegisterPlayer = function adminRegisterPlayer(options, callback) {
    let vendorPlayerId = options.playerId || "";  // Pass in your id for the player here
    let encryptedPayload = getEncryptedPayload();

    let uri = "/players/register";
    let requestUrl = "https://admin-api.amazongameon.com/v1" + uri;

    let requestHeaders = {"Content-Type": "application/json",
                            "X-Api-Key": ADMIN_KEY
                            };
    let bodyObj = {
        "advertisingId": "blahblahblah",
        "encryptedPayload": encryptedPayload,
        "vendorPlayerId": vendorPlayerId
    };
                        
    let body = JSON.stringify(bodyObj);

    request.post({url: requestUrl, headers: requestHeaders, body: body}, function(error, response, body) {

        if(error) {
            console.log("Error:");
            console.log(error);
    
            console.log("Response:");
            console.log(response);
    
            console.log("Body:");
            console.log(body);
        }

        let responseObj = JSON.parse(body);

        // Now decrypt the player token
        let playerToken = decryptPlayerToken(responseObj.encryptedPlayerToken);

        if(callback) {
            callback(playerToken, responseObj.externalPlayerId);
        }
    });
    return;
}

exports.authPlayer = function authPlayer(options, callback) {

    let uri = "/players/auth";    
    let requestUrl = "https://api.amazongameon.com/v1" + uri;

    var requestHeaders = {"Content-Type": "application/json",
                            "X-Api-Key": PUBLIC_API_KEY
                            };

    let encryptedPayload = encryptPlayerToken(options.playerToken);

    let bodyObj = {
        "advertisingId": "blahblahblah", // Looks like could be anything
        "appBuildType": "development",
        "deviceOSType": "html",  // Type 'alexa' is not allowed
        "encryptedPayload": encryptedPayload,
        "playerName": "testName"
    };
                        
    let body = JSON.stringify(bodyObj);
                        
    request.post({url: requestUrl, headers: requestHeaders, body: body}, function(error, response, body) {
        if(error) {
            console.log("Error:");
            console.log(error);

            console.log("Response:");
            console.log(response);

            console.log("Body:");
            console.log(body);
        }

        let responseObj = JSON.parse(body);

        if(callback) {
            callback(responseObj);
        }

    });
    return;
}
1 comment
10 |3000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Thanks a lot for sharing! Glad you got it working, and I'm sure it will be useful for other developers. Thanks!

0 Likes 0 ·
Levon@Amazon avatar image
Levon@Amazon answered

Edited 03/22

Hi there,

Thanks for posting! As for libraries, GameOn is provided as a set of Rest APIs, and you should be able to generate libraries for any framework you want. We don't provide those at the moment, but you can build your own. Thanks!

Reference: https://developer.amazon.com/gameon

10 |3000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.