Showing posts with label instantgame. Show all posts
Showing posts with label instantgame. Show all posts

Sunday, March 10, 2019

facebook instant game custom server communication Nodejs, PHP

game.js

const BACKEND_URL = "https://localhost/quizbattle";
const BACKEND_URL_API = BACKEND_URL + "/api";
var game = {};
var gameData = {};
var gameOptions = {
    width: 0,
    height: 0,
    backgroundColor: 0xFFFFFF,
    localStorageName: "__ab__"
};
var gameStuff = {
    playerId: "",
    playerName: "",
    playerPic: "",
    locale: ""
};

window.onload = function () {
    $('#home-section').hide();

    FBInstant.initializeAsync().then(function () {
        FBInstant.startGameAsync().then(function () {
            gameStuff.playerId = FBInstant.player.getID();
            gameStuff.playerName = FBInstant.player.getName();
            gameStuff.playerPic = FBInstant.player.getPhoto();
            gameStuff.locale = FBInstant.getLocale();
            gameStuff.contextType = FBInstant.context.getType();

            gameOptions.height = window.innerHeight;
            gameOptions.width = window.innerWidth / 2;

            $('#u-photo-field').attr('src', gameStuff.playerPic);
            $('#u-name-field').html(gameStuff.playerName);
            $('#context-type').html(gameStuff.contextType);

            $('#home-section').show();
           
            loadingInitialData();
        });
    });
};

function getOrCreateContextId() {
    var contextType = FBInstant.context.getType();
    var contextId = FBInstant.context.getID();
   
    console.log(contextType);
    if (contextType == 'SOLO') {
        contextId = FBInstant.player.getID() + '_SOLO';
    }
    return contextId;
}

function showMessage(div, message) {
    document.getElementById(div).innerHTML = message;
}

function loadingInitialData() {
    var contextId = getOrCreateContextId();

    FBInstant.player.getSignedPlayerInfoAsync(contextId)
            .then(function (signedPlayerInfo) {
                // Requesting data from backend passing the signature as an argument
                // The backend APP can retrieve contextId from the signature
                var signature = signedPlayerInfo.getSignature();
                return new backendClient(BACKEND_URL_API).load(contextId, signature);
            })
            .then(function (response) {
                // Got successful response from backend
                console.log('Loaded from backend', response);
                if (response.empty) {
                    showMessage('test', 'No data');
                } else {
                    showMessage('test', JSON.stringify(response.data));
                }
            }.bind(this))
            .catch(function (error) {
                // Got error response from backend
                console.error('Not loaded from backend', error);
                showMessage('error-messages', 'Error loading backend data:' + error.message);
            }.bind(this));
}

function singlePlayBoot() {

}

function multiPlayBoot() {

}

function leaderBoardBoot() {

}

function helpBoot() {

}


node.js server side


var pg = require('pg');
var crypto = require('crypto-js');

module.exports = function(app) {

app.post('/get-match', function(request, response) {
        var signature = request.body.signature;
       
        var isValid = validate(signature);
       
        if (isValid) {
            var contextId = getEncodedData(signature);
            loadMatchDataAsync(contextId)
            .then(function(result){
                if (result) {
                    response.json({'success':true, 'contextId':contextId, 'empty': false, 'data':result});
                } else {
                    response.json({'success':true, 'contextId':contextId, 'empty': true});
                }
            })
            .catch(function(err){
                response.json({'success':false, 'error':err});
            });
        } else {
            console.log('encoded data', getEncodedData(signature));
            response.json({'success':false, 'error':'invalid signature'});
        }
       
    })

loadMatchDataAsync = function(contextId) {
        return new Promise(function(resolve, reject){
            pg.connect(process.env.DATABASE_URL, function(err, client, done) {
                client.query('SELECT * FROM matches WHERE context = $1::text', [contextId], function(err, result) {
                    done();
                    if (err) {
                        reject(err);
                    }
                    if (result.rows.length > 0) {
                        resolve(result.rows[0].data);
                    } else {
                        resolve();
                    }
                });
            });
        });
    };
   
    validate = function(signedRequest) {
        try{
           
            var firstpart = signedRequest.split('.')[0];
            var replaced = firstpart.replace(/-/g, '+').replace(/_/g, '/');
            var signature = crypto.enc.Base64.parse(replaced).toString();
            const dataHash = crypto.HmacSHA256(signedRequest.split('.')[1], process.env.APP_SECRET).toString();
            var isValid = signature === dataHash;
            if (!isValid) {
                console.log('Invalid signature');
                console.log('firstpart', firstpart);
                console.log('replaced ', replaced);
                console.log('Expected', dataHash);
                console.log('Actual', signature);
            }
           
            return isValid;
        } catch (e) {
            return false;
        }
    };
   
    getEncodedData = function(signedRequest) {
        try {
           
            const json = crypto.enc.Base64.parse(signedRequest.split('.')[1]).toString(crypto.enc.Utf8);
            const encodedData = JSON.parse(json);
           
            /*
            Here's an example of encodedData can look like
            {
                algorithm: 'HMAC-SHA256',
                issued_at: 1520009634,
                player_id: '123456789',
                request_payload: 'backend_save'
            }
            */
           
            return encodedData.request_payload;
        } catch (e) {
            return null;
        }
    };
}


PHP server side


private function _validate($signedRequest) {
        try {
            list($encoded_signature, $payload) = explode('.', $signedRequest, 2);

            // decode the data
            $signature = base64_url_decode($encoded_signature);
            //$data = json_decode(base64_url_decode($payload), true);
           
            // confirm the signature
            $expected_signature = hash_hmac('sha256', $payload, $this->facebook_config['app_secret'], $raw = true);
            $isValid = $signature === $expected_signature;

            if (!$isValid) {
                error_log('Bad Signed JSON signature!');
                return null;
            }

            return $isValid;
        } catch (Exception $ex) {
            return false;
        }
    }

    private function _getEncodedData($signedRequest) {
        try {
            $encodedData = json_decode(base64_url_decode(explode('.', $signedRequest)[1]), true);
            /*
            $encodedData = {
                "status":true,
                "data":{
                    "algorithm":"HMAC-SHA256",
                    "issued_at":1552157956,
                    "player_id":"2522121991191915",
                    "request_payload":"2522121991191915_SOLO"
                }
            }
             */

            return $encodedData;
        } catch (Exception $ex) {
            return null;
        }
    }


function load_post() {

$signature = $this->post('signature');

            $isValid = $this->_validate($signature);

            if ($isValid) {
                $edata = $this->_getEncodedData($signature);
                $this->success($edata->data);
            } else {
                $this->error('Invalid Request!');
            }
..........................
}

Tuesday, March 5, 2019

how-to-integrate-facebook-instant-games tutorial Phaser

1.

https://www.emanueleferonato.com/2018/03/28/how-to-integrate-facebook-instant-games-api-in-your-phaser-game/


2.

https://www.emanueleferonato.com/2018/04/05/how-to-integrate-facebook-instant-games-api-in-your-phaser-game-displaying-player-name-and-profile-picture/


3.
https://www.facebook.com/embed/instantgames/<app_id>/player?game_url=https://localhost/mygame