Вход Регистрация
Файл: monst/core/j/oksdk.js
Строк: 559
<?php
"use strict";
var 
OKSDK = (function () {
    const 
OK_CONNECT_URL = 'https://connect.ok.ru/';
    const 
OK_MOB_URL = 'https://m.ok.ru/';
    const 
OK_API_SERVER = 'https://api.ok.ru/';

    var 
state = {
        
app_id: 0, app_key: '',
        
sessionKey: '', accessToken: '', sessionSecretKey: '', apiServer: '', widgetServer: '', mobServer: '',
        
baseUrl: '',
        
container: false, header_widget: ''
    
};
    var 
sdk_success = nop;
    var 
sdk_failure = nop;
    var 
rest_counter = 0;

    
// ---------------------------------------------------------------------------------------------------
    // General
    // ---------------------------------------------------------------------------------------------------

    /**
     * initializes the SDK<br/>
     * If launch parameters are not detected, switches to OAUTH (via redirect)
     *
     * @param args
     * @param {Number} args.app_id application id
     * @param {String} args.app_key application key
     * @param [args.oauth] - OAUTH configuration
     * @param {String} [args.oauth.scope='VALUABLE_ACCESS'] scope
     * @param {String} [args.oauth.url=location.href] return url
     * @param {String} [args.oauth.state=''] state for security checking
     * @param {String} [args.oauth.layout='a'] authorization layout (w - web, m - mobile)
     * @param {Function} success success callback
     * @param {Function} failure failure callback
     */
    
function init(args, success, failure) {
        
args.oauth = args.oauth || {};
        
sdk_success = isFunc(success) ? success : nop;
        
sdk_failure = isFunc(failure) ? failure : nop;

        var 
params = getRequestParameters(args['location_search'] || window.location.search);
        var 
hParams = getRequestParameters(args['location_hash'] || window.location.hash);

        
state.app_id = args.app_id;
        
state.app_key = params["application_key"] || args.app_key;
        
state.sessionKey = params["session_key"];
        
state.accessToken = hParams['access_token'];
        
state.sessionSecretKey = params["session_secret_key"] || hParams['session_secret_key'];
        
state.apiServer = args["api_server"] || params["api_server"] || OK_API_SERVER;
        
state.widgetServer = args["widget_server"] || params['widget_server'] || OK_CONNECT_URL;
        
state.mobServer = args["mob_server"] || params["mob_server"] || OK_MOB_URL;
        
state.baseUrl = state.apiServer + "fb.do";
        
state.header_widget = params['header_widget'];
        
state.container = params['container'];

        if (!
state.app_id || !state.app_key) {
            
sdk_failure('Required arguments app_id/app_key not passed');
            return;
        }

        if (!
params['api_server']) {
            if ((
hParams['access_token'] == null) && (hParams['error'] == null)) {
                
window.location = state.widgetServer + 'oauth/authorize' +
                    
'?client_id=' + args['app_id'] +
                    
'&scope=' + (args.oauth.scope || 'VALUABLE_ACCESS') +
                    
'&response_type=' + 'token' +
                    
'&redirect_uri=' + (args.oauth.url || window.location.href) +
                    
'&layout=' + (args.oauth.layout || 'a') +
                    
'&state=' + (args.oauth.state || '');
                return;
            }
            if (
hParams['error'] != null) {
                
sdk_failure('Error with OAUTH authorization: ' + hParams['error']);
                return;
            }
        }
        
sdk_success();
    }

    
// ---------------------------------------------------------------------------------------------------
    // REST
    // ---------------------------------------------------------------------------------------------------

    
function restLoad(url) {
        var 
script = document.createElement('script');
        
script.src = url;
        
script.async = true;
        var 
done = false;
        
script.onload = script.onreadystatechange = function () {
            if (!
done && (!this.readyState || this.readyState === "loaded" || this.readyState === "complete")) {
                
done = true;
                
script.onload = null;
                
script.onreadystatechange = null;
                if (
script && script.parentNode) {
                    
script.parentNode.removeChild(script);
                }
            }
        };
        var 
headElem = document.getElementsByTagName('head')[0];
        
headElem.appendChild(script);
    }

    function 
restCallPOST(query, callback) {
        const 
xhr = new XMLHttpRequest();
        
xhr.open("POST", state.baseUrl, true);
        
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        
xhr.onreadystatechange = function() {
            if (
xhr.readyState ===  XMLHttpRequest.DONE) {
                if (
xhr.status === 200) {
                    if (
isFunc(callback)) {
                        
callback("ok", xhr.responseText, null);
                    }
                } else {
                    if (
isFunc(callback)) {
                        
callback("error", null, xhr.responseText);
                    }
                }
            }
        };
        
xhr.send(query);
    }

    
/**
     * Calls a REST request
     *
     * @param {String} method
     * @param {Object} [params]
     * @param {restCallback} [callback]
     * @param {Object} [callOpts]
     * @param {boolean} [callOpts.no_session] true if REST method prohibits session
     * @param {boolean} [callOpts.no_sig] true if no signature is required for the method
     * @param {string} [callOpts.app_secret_key] required for non-session requests
     * @param {string} [callOpts.use_post] send request via POST
     * @returns {string}
     */
    
function restCall(method, params, callback, callOpts) {
        
params = params || {};
        
params.method = method;
        
params = restFillParams(params);
        if (
callOpts && callOpts.no_session) {
            
delete params['session_key'];
            
delete params['access_token'];
        }

        for (const 
key in params) {
            if (
params.hasOwnProperty(key)) {
                
let param = params[key];
                if (
typeof param === 'object') {
                    
params[key] = JSON.stringify(param);
                }
            }
        }

        if (!
callOpts || !callOpts.no_sig) {
            var 
secret = (callOpts && callOpts.app_secret_key) ? callOpts.app_secret_key : state.sessionSecretKey;
            
params['sig'] = calcSignature(params, secret);
        }

        
let query = "";
        for (const 
key in params) {
            if (
params.hasOwnProperty(key)) {
                if (
query.length !== 0) {
                    
query += '&';
                }
                
query += key + "=" + encodeURIComponent(params[key]);
            }
        }

        if (
callOpts && callOpts.use_post) {
            return 
restCallPOST(query, callback);
        }

        const 
callbackId = "__oksdk__callback_" + (++rest_counter);
        
window[callbackId] = function (status, data, error) {
            if (
isFunc(callback)) {
                
callback(status, data, error);
            }
            
window[callbackId] = null;
            try {
                
delete window[callbackId];
            } catch (
e) {}
        };
        
restLoad(state.baseUrl + '?' + query + "&js_callback=" + callbackId);
        return 
callbackId;
    }

    
/**
     * Calculates request signature basing on the specified call arguments
     *
     * @param {Object} query
     * @param {string} [secretKey] alternative secret_key (fe: app secret key for non-session requests)
     * @returns {string}
     */
    
function calcSignatureExternal(query, secretKey) {
        return 
calcSignature(restFillParams(query), secretKey);
    }

    function 
calcSignature(query, secretKey) {
        var 
i, keys = [];
        for (
i in query) {
            
keys.push(i.toString());
        }
        
keys.sort();
        var 
sign = "";
        for (
i = 0; i < keys.length; i++) {
            var 
key = keys[i];
            if ((
"sig" != key) && ("access_token" != key)) {
                
sign += keys[i] + '=' + query[keys[i]];
            }
        }
        
sign += secretKey || state.sessionSecretKey;
        
sign = encodeUtf8(sign);
        return 
md5(sign);
    }

    function 
restFillParams(params) {
        
params = params || {};
        
params["application_key"] = state.app_key;
        if (
state.sessionKey) {
            
params["session_key"] = state.sessionKey;
        } else {
            
params["access_token"] = state.accessToken;
        }
        
params["format"] = 'JSON';
        return 
params;
    }

    function 
wrapCallback(success, failure, dataProcessor) {
        return function(
status, data, error) {
            if (
status == 'ok') {
                if (
isFunc(success)) success(isFunc(dataProcessor) ? dataProcessor(data) : data);
            } else {
                if (
isFunc(failure)) failure(error);
            }
        };
    }

    
// ---------------------------------------------------------------------------------------------------
    // Payment
    // ---------------------------------------------------------------------------------------------------

    
function paymentShow(productName, productPrice, productCode, options) {
        var 
params = {};
        
params['name'] = productName;
        
params['price'] = productPrice;
        
params['code'] = productCode;

        
options = options || {};
        const 
host = options['mob_pay_url'] || state.mobServer;

        
params["application_key"] = state.app_key;
        if (
state.sessionKey) {
            
params["session_key"] = state.sessionKey;
        } else {
            
params["access_token"] = state.accessToken;
        }
        
params['sig'] = calcSignature(params, state.sessionSecretKey);

        var 
query = host + 'api/show_payment?';
        for (var 
key in params) {
            if (
params.hasOwnProperty(key)) {
                
query += key + "=" + encodeURIComponent(params[key]) + "&";
            }
        }

        
window.open(query);
    }

    
// ---------------------------------------------------------------------------------------------------
    // Widgets
    // ---------------------------------------------------------------------------------------------------

    
const WIDGET_SIGNED_ARGS = ["st.attachment", "st.return", "st.redirect_uri", "st.state"];

    
/**
     * Returns HTML to be used as a back button for mobile app<br/>
     * If back button is required (like js app opened in browser from native mobile app) the required html
     * will be returned in #onSucсess callback
     * @param {onSuccessCallback} onSuccess
     * @param {String} [style]
     */
    
function widgetBackButton(onSuccess, style) {
        if (
state.container || state.accessToken) return;
        
restCall('widget.getWidgetContent',
            {
wid: state.header_widget || 'mobile-header-small', style: style || null},
            
wrapCallback(onSuccess, null, function(data) {
                return 
decodeUtf8(atob(data))
            }));
    }

    
/**
     * Opens mediatopic post widget
     *
     * @param {String} returnUrl callback url (if null, result will be posted via postmessage and popup closed)
     * @param {Object} options options
     * @param {Object} options.attachment mediatopic (feed) to be posted
     */
    
function widgetMediatopicPost(returnUrl, options) {
        
options = options || {};
        if (!
options.attachment) {
            
options = {attachment: options}
        }
        
options.attachment = btoa(unescape(encodeURIComponent(toString(options.attachment))));
        
widgetOpen('WidgetMediatopicPost', options, returnUrl);
    }

    
/**
     * Opens app invite widget (invite friends to app)
     *
     * @see widgetSuggest widgetSuggest() for more details on arguments
     */
    
function widgetInvite(returnUrl, options) {
        
widgetOpen('WidgetInvite', options, returnUrl);
    }

    
/**
     * Opens app suggest widget (suggest app to friends, both already playing and not yet)
     *
     * @param {String} returnUrl callback url (if null, result will be posted via postmessage and popup closed)
     * @param {Object} [options] options
     * @param {int} [options.autosel] amount of friends to be preselected
     * @param {String} [options.comment] default text set in the suggestion text field
     * @param {String} [options.custom_args] custom args to be passed when app opened from suggestion
     * @param {String} [options.state] custom args to be passed to return url
     * @param {String} [options.target] comma-separated friend IDs that should be preselected by default
     */
    
function widgetSuggest(returnUrl, options) {
        
widgetOpen('WidgetSuggest', options, returnUrl);
    }

    function 
widgetOpen(widget, args, returnUrl) {
        
args = args || {};
        if (
returnUrl !== null) {
            
args.return = returnUrl;
        }

        var 
keys = [];
        for (var 
arg in args) {
            
keys.push(arg.toString());
        }
        
keys.sort();

        var 
sigSource = '';
        var 
query = state.widgetServer + 'dk?st.cmd=' + widget + '&st.app=' + state.app_id;
        for (var 
i = 0; i < keys.length; i++) {
            var 
key = "st." + keys[i];
            var 
val = args[keys[i]];
            if (
WIDGET_SIGNED_ARGS.indexOf(key) != -1) {
                
sigSource += key + "=" + val;
            }
            
query += "&" + key + "=" + encodeURIComponent(val);
        }
        
sigSource += state.sessionSecretKey;
        
query += '&st.signature=' + md5(sigSource);
        if (
state.accessToken != null) {
            
query += '&st.access_token=' + state.accessToken;
        }
        if (
state.sessionKey) {
            
query += '&st.session_key=' + state.sessionKey;
        }
        
window.open(query);
    }

    
// ---------------------------------------------------------------------------------------------------
    // Utils
    // ---------------------------------------------------------------------------------------------------

    /**
     * calculates md5 of a string
     * @param {String} str
     * @returns {String}
     */
    
function md5(str) {
        const 
hex_chr = "0123456789abcdef";

        function 
rhex(num) {
            
let str = "";
            for (
let j = 0; j <= 3; j++) {
                
str += hex_chr.charAt((num >> (j * 8 + 4)) & 0x0F) +
                    
hex_chr.charAt((num >> (j * 8)) & 0x0F);
            }
            return 
str;
        }

        
/*
         * Convert a string to a sequence of 16-word blocks, stored as an array.
         * Append padding bits and the length, as described in the MD5 standard.
         */
        
function str2blks_MD5(str) {
            
let nblk = ((str.length + 8) >> 6) + 1;
            
let blks = new Array(nblk * 16);
            
let i = 0;
            for (
i = 0; i < nblk * 16; i++) {
                
blks[i] = 0;
            }
            for (
i = 0; i < str.length; i++) {
                
blks[i >> 2] |= str.charCodeAt(i) << ((i % 4) * 8);
            }
            
blks[i >> 2] |= 0x80 << ((i % 4) * 8);
            
blks[nblk * 16 - 2] = str.length * 8;
            return 
blks;
        }

        
/*
         * Add integers, wrapping at 2^32. This uses 16-bit operations internally
         * to work around bugs in some JS interpreters.
         */
        
function add(x, y) {
            
let lsw = (x & 0xFFFF) + (y & 0xFFFF);
            
let msw = (x >> 16) + (y >> 16) + (lsw >> 16);
            return (
msw << 16) | (lsw & 0xFFFF);
        }

        
/*
         * Bitwise rotate a 32-bit number to the left
         */
        
function rol(num, cnt) {
            return (
num << cnt) | (num >>> (32 - cnt));
        }

        
/*
         * These functions implement the basic operation for each round of the
         * algorithm.
         */
        
function cmn(q, a, b, x, s, t) {
            return 
add(rol(add(add(a, q), add(x, t)), s), b);
        }

        function 
ff(a, b, c, d, x, s, t) {
            return 
cmn((b & c) | ((~b) & d), a, b, x, s, t);
        }

        function 
gg(a, b, c, d, x, s, t) {
            return 
cmn((b & d) | (c & (~d)), a, b, x, s, t);
        }

        function 
hh(a, b, c, d, x, s, t) {
            return 
cmn(b ^ c ^ d, a, b, x, s, t);
        }

        function 
ii(a, b, c, d, x, s, t) {
            return 
cmn(c ^ (b | (~d)), a, b, x, s, t);
        }

        
let x = str2blks_MD5(str);
        
let a = 1732584193;
        
let b = -271733879;
        
let c = -1732584194;
        
let d = 271733878;

        for (
let i = 0; i < x.length; i += 16) {
            const 
olda = a;
            const 
oldb = b;
            const 
oldc = c;
            const 
oldd = d;

            
a = ff(a, b, c, d, x[i + 0], 7, -680876936);
            
d = ff(d, a, b, c, x[i + 1], 12, -389564586);
            
c = ff(c, d, a, b, x[i + 2], 17, 606105819);
            
b = ff(b, c, d, a, x[i + 3], 22, -1044525330);
            
a = ff(a, b, c, d, x[i + 4], 7, -176418897);
            
d = ff(d, a, b, c, x[i + 5], 12, 1200080426);
            
c = ff(c, d, a, b, x[i + 6], 17, -1473231341);
            
b = ff(b, c, d, a, x[i + 7], 22, -45705983);
            
a = ff(a, b, c, d, x[i + 8], 7, 1770035416);
            
d = ff(d, a, b, c, x[i + 9], 12, -1958414417);
            
c = ff(c, d, a, b, x[i + 10], 17, -42063);
            
b = ff(b, c, d, a, x[i + 11], 22, -1990404162);
            
a = ff(a, b, c, d, x[i + 12], 7, 1804603682);
            
d = ff(d, a, b, c, x[i + 13], 12, -40341101);
            
c = ff(c, d, a, b, x[i + 14], 17, -1502002290);
            
b = ff(b, c, d, a, x[i + 15], 22, 1236535329);

            
a = gg(a, b, c, d, x[i + 1], 5, -165796510);
            
d = gg(d, a, b, c, x[i + 6], 9, -1069501632);
            
c = gg(c, d, a, b, x[i + 11], 14, 643717713);
            
b = gg(b, c, d, a, x[i + 0], 20, -373897302);
            
a = gg(a, b, c, d, x[i + 5], 5, -701558691);
            
d = gg(d, a, b, c, x[i + 10], 9, 38016083);
            
c = gg(c, d, a, b, x[i + 15], 14, -660478335);
            
b = gg(b, c, d, a, x[i + 4], 20, -405537848);
            
a = gg(a, b, c, d, x[i + 9], 5, 568446438);
            
d = gg(d, a, b, c, x[i + 14], 9, -1019803690);
            
c = gg(c, d, a, b, x[i + 3], 14, -187363961);
            
b = gg(b, c, d, a, x[i + 8], 20, 1163531501);
            
a = gg(a, b, c, d, x[i + 13], 5, -1444681467);
            
d = gg(d, a, b, c, x[i + 2], 9, -51403784);
            
c = gg(c, d, a, b, x[i + 7], 14, 1735328473);
            
b = gg(b, c, d, a, x[i + 12], 20, -1926607734);

            
a = hh(a, b, c, d, x[i + 5], 4, -378558);
            
d = hh(d, a, b, c, x[i + 8], 11, -2022574463);
            
c = hh(c, d, a, b, x[i + 11], 16, 1839030562);
            
b = hh(b, c, d, a, x[i + 14], 23, -35309556);
            
a = hh(a, b, c, d, x[i + 1], 4, -1530992060);
            
d = hh(d, a, b, c, x[i + 4], 11, 1272893353);
            
c = hh(c, d, a, b, x[i + 7], 16, -155497632);
            
b = hh(b, c, d, a, x[i + 10], 23, -1094730640);
            
a = hh(a, b, c, d, x[i + 13], 4, 681279174);
            
d = hh(d, a, b, c, x[i + 0], 11, -358537222);
            
c = hh(c, d, a, b, x[i + 3], 16, -722521979);
            
b = hh(b, c, d, a, x[i + 6], 23, 76029189);
            
a = hh(a, b, c, d, x[i + 9], 4, -640364487);
            
d = hh(d, a, b, c, x[i + 12], 11, -421815835);
            
c = hh(c, d, a, b, x[i + 15], 16, 530742520);
            
b = hh(b, c, d, a, x[i + 2], 23, -995338651);

            
a = ii(a, b, c, d, x[i + 0], 6, -198630844);
            
d = ii(d, a, b, c, x[i + 7], 10, 1126891415);
            
c = ii(c, d, a, b, x[i + 14], 15, -1416354905);
            
b = ii(b, c, d, a, x[i + 5], 21, -57434055);
            
a = ii(a, b, c, d, x[i + 12], 6, 1700485571);
            
d = ii(d, a, b, c, x[i + 3], 10, -1894986606);
            
c = ii(c, d, a, b, x[i + 10], 15, -1051523);
            
b = ii(b, c, d, a, x[i + 1], 21, -2054922799);
            
a = ii(a, b, c, d, x[i + 8], 6, 1873313359);
            
d = ii(d, a, b, c, x[i + 15], 10, -30611744);
            
c = ii(c, d, a, b, x[i + 6], 15, -1560198380);
            
b = ii(b, c, d, a, x[i + 13], 21, 1309151649);
            
a = ii(a, b, c, d, x[i + 4], 6, -145523070);
            
d = ii(d, a, b, c, x[i + 11], 10, -1120210379);
            
c = ii(c, d, a, b, x[i + 2], 15, 718787259);
            
b = ii(b, c, d, a, x[i + 9], 21, -343485551);

            
a = add(a, olda);
            
b = add(b, oldb);
            
c = add(c, oldc);
            
d = add(d, oldd);
        }
        return 
rhex(a) + rhex(b) + rhex(c) + rhex(d);
    }

    function 
isFunc(obj) {
        return 
Object.prototype.toString.call(obj) === "[object Function]";
    }

    function 
isString(obj) {
        return 
Object.prototype.toString.call(obj) === "[object String]";
    }

    function 
toString(obj) {
        return 
isString(obj) ? obj : JSON.stringify(obj);
    }

    
/**
     * Parses parameters to a JS map<br/>
     * Supports both window.location.search and window.location.hash)
     * @param {String} [source=window.location.search] string to parse
     * @returns {Object}
     */
    
function getRequestParameters(source) {
        var 
res = {};
        var 
url = source || window.location.search;
        if (
url) {
            
url = url.substr(1);    // Drop the leading '?' / '#'
            
var nameValues = url.split("&");

            for (var 
i = 0; i < nameValues.length; i++) {
                var 
nameValue = nameValues[i].split("=");
                var 
name = nameValue[0];
                var 
value = nameValue[1];
                
value = decodeURIComponent(value.replace(/+/g, " "));
                
res[name] = value;
            }
        }
        return 
res;
    }

    function 
encodeUtf8(string) {
        return 
unescape(encodeURIComponent(string));
    }

    function 
decodeUtf8(utftext) {
        return 
decodeURIComponent(escape(utftext));
    }

    
/** stub func */
    
function nop() {}

    
/**
     * @callback onSuccessCallback
     * @param {String} result
     */

    /**
     * @callback restCallback
     * @param {String} code (either 'ok' or 'error')
     * @param {Object} data success data
     * @param {Object} error error data
     */

    // ---------------------------------------------------------------------------------------------------
    
return {
        
init: init,
        
REST: {
            
call: restCall,
            
calcSignature: calcSignatureExternal
        
},
        
Payment: {
            
show: paymentShow
        
},
        
Widgets: {
            
getBackButtonHtml: widgetBackButton,
            
post: widgetMediatopicPost,
            
invite: widgetInvite,
            
suggest: widgetSuggest
        
},
        
Util: {
            
md5: md5,
            
encodeUtf8: encodeUtf8,
            
decodeUtf8: decodeUtf8,
            
encodeBase64: btoa,
            
decodeBase64: atob,
            
getRequestParameters: getRequestParameters,
            
toString: toString
        
}
    };
})();
?>
Онлайн: 4
Реклама