[#125] Meta Data Error -32000

Migrated from Redmine #125 | Author: Anonymous
Status: Closed | Priority: Normal | Created: 2018-03-08


This is an undocumented error. It is intermittent on page reloads. Sometimes it occurs sometimes it does not. When it does occur it blocks all my calls to the API from working.

Here’s my simply book me access code. It is javascript. (see attached image)

import { sbm, JSONRpcClient } from ‘./sbmConfig’;

let SBM = {
client: null
}

const companyLogin = ‘cyno’;
const sbmApiKey = sbm.apiKey;
let tokenExpired = null;

const getToken = () => {
let loginClient = getLoginClient();
return loginClient.getToken(companyLogin, sbmApiKey);
}

const getSbmClient = () => {
console.log(‘Getting SBM client.’);
SBM.client = getJSONRpcClient();

if (tokenExpired) {
    // This doesn't work
    SBM.client = getJSONRpcClient();
    console.log('Token Expired: Getting new token.', );
}
return SBM.client;

}

const getAsyncSbmClient = ({refreshTokenCallback, stopAutoRefresh}) => {
console.log(‘Getting Async SMB RPC Client’);
return new Promise(function(resolve, reject) {
SBM.client = getJSONRpcClient();
if (SBM.client) {
resolve(SBM.client);
console.log('SBM client has been obtained: ', SBM.client);
return;
}
let autoRefresh;
if (!stopAutoRefresh) {
autoRefresh = setInterval(
() => {
const sbmClient = getJSONRpcClient();
refreshTokenCallback(sbmClient);
resolve(sbmClient);
}, 3480000
);
} else {
clearInterval(autoRefresh);
}
});
}

// LOGIN TO SBM
const getLoginClient = () => {
return new JSONRpcClient({
url: ‘//user-api.simplybook.me/login’,
onerror: function (error) {
alert(error);
console.log(‘Client Login Error @Calendar Actions’);
}
});
}

const getJSONRpcClient = () => {
let token = getToken();
return new JSONRpcClient({
‘url’: ‘//user-api.simplybook.me’,
‘headers’: {
‘X-Company-Login’: companyLogin,
‘X-Token’: token
},
‘onerror’: function (error) {
alert(‘Error: ‘+ error + ’ Message: ’ + error.message + ’ Code: ’ + error.code + ’ Token: ’ + token);
console.log(’%cGETTING CLIENT ERROR @SBM Calendar Actions’,‘color: greenyellow’);
if (error.code == -32600){
tokenExpired = true;
let newLoginClient = new JSONRpcClient({
url: ‘//user-api.simplybook.me/login’,
onerror: function (error) {
alert(error);
console.log(‘Client Login Error @Calendar Actions’);
}
});
let newToken = getToken();
SBM.client = new JSONRpcClient({
‘url’: ‘//user-api.simplybook.me’,
‘headers’: {
‘X-Company-Login’: companyLogin,
‘X-Token’: newToken
},
‘onerror’: function (error) {
alert('Error: ‘+ error + ’ Message: ’ + error.message + ’ was fired from repeat call to sbmLogin ’ + ‘Code: ’ + error.code + ’ Token: ’ + newToken);
console.log(’%cGETTING CLIENT ERROR @SBM Calendar Actions’,‘color: greenyellow’);
}
});
}
}
});
}

export {getSbmClient as default, getAsyncSbmClient};

declare var jQuery: any;
declare var Exception: any;

export const sbm = {
apiKey: ‘cc92801171ff01c1d45d7675ef77300c4dd92909a795fbd81165b95b9284b4eb’
}

/**

  • JSON-RPC Client Exception class

  • @param String code

  • @param String message
    */
    var JSONRpcClientException = function (code, message) {
    this.code = code;
    this.message = message;
    }
    JSONRpcClientException.prototype = jQuery.extend(JSONRpcClientException.prototype, {

    /**

    • Magic method. COnvert object to string.
    • @return String
      */
      toString: function () {
      return ‘[’ + this.code + '] ’ + this.message;
      }

});

/**

  • JSON-RPC Client

  • @param Object options
    */
    export const JSONRpcClient = function (options) {
    this.setOptions(options);
    this.init();
    }
    JSONRpcClient.prototype = jQuery.extend(JSONRpcClient.prototype, {

    /**

    • Default options
      */
      options: {
      ‘onerror’: function () {},
      ‘onsuccess’: function () {},
      ‘url’: ‘’,
      ‘headers’: {}
      },
      current: 1,
      onerror: null,
      onsuccess: null,
      onstart: null,

    /**

    • Init client
      */
      init: function () {
      this.onerror = this.getParam(‘onerror’);
      this.onsuccess = this.getParam(‘onsuccess’);

      this.initMethods();
      },

    /**

    • Init API methiods by url
      */
      initMethods: function () {
      var instance = this;
      // get all methods
      jQuery.ajax(this.getParam(‘url’), {
      ‘async’: false,
      ‘success’: function (data) {
      if (data.methods) {
      // create method
      jQuery.each(data.methods, function(methodName, methodParams) {
      var method = function () {
      var params = new Array();
      for(var i = 0; i < arguments.length; i++){
      params.push(arguments[i]);
      }
      var id = (instance.current++);
      var callback = params[params.length - 1];
      var request = {jsonrpc: ‘2.0’, method: methodName, params: params, id: id};

                       var async = false;
                       if (jQuery.type(callback) == 'function') {
                       	async = true;
                       	params.pop();
                       }
                       
                       var res = null;
                       // API request
                       jQuery.ajax(instance.getParam('url'), {
                           'contentType': 'application/json',
                           'type': methodParams.transport,
                           'processData': false,
                           'dataType': 'json',
                           'cache': false,
                           'data': JSON.stringify(request),
                           'headers': instance.getParam('headers'),
                           'async': async,
                           'success': function (result) {
                               if (jQuery.type(result.error) == 'object') {
                                   res = new JSONRpcClientException(result.error.code, result.error.message);
                                   instance.onerror(res);
                               } else {
                                   res = result.result;
                                   if (jQuery.type(callback) == 'function') {
                               	    callback(res);
                                   }
                               }
                               instance.onsuccess(res, id, methodName);
                           }
           	        });
                       if (!async) {
                       	return res;
                       }
           	    }
      
           	    instance[methodName] = method;
           	});
           } else {
               throw Exception("Methods could not be found");
           }
       }
      

      });
      },

    /**

    • Set client options
    • @param Object options
      */
      setOptions: function (options) {
      this.options = jQuery.extend({}, this.options, options);
      },

    /**

    • Get client param, if param is not available in this.options return defaultValue
    • @param String key
    • @param mixed defaultValue
    • @return mixed
      */
      getParam: function (key, defaultValue) {
      if (jQuery.type(this.options[key]) != ‘undefined’) {
      return this.options[key];
      }
      return defaultValue;
      }

});

var SimplybookWidget = function(options) {
this.options = {
// common options
‘widget_type’: ‘iframe’,
‘theme’: ‘default’,
‘theme_settings’: {},
‘app_config’: {},
‘timeline’: null,
‘datepicker’: null,
‘url’: ‘’,
// iframe widget options
‘iframe_postpone’: false,
// button widget options
‘button_position’: ‘right’,
‘button_position_offset’: ‘auto’,
‘button_background_color’: ‘#06acee’,
‘button_text_color’: ‘#ffffff’,
‘button_title’: ‘Book Now’,
‘button_preload’: true,
‘button_custom_id’: null,
‘navigate’: ‘book’
};
this.name = ‘widget_’ + Math.random();
this.frame = null;
for (var name in options) {
if (!options.hasOwnProperty(name)) {
continue;
}
this.options[name] = options[name];
}
this.init();
};
SimplybookWidget.prototype.init = function() {
if (!this.options.postpone) {
switch (this.options.widget_type) {
case ‘iframe’:
this.displayIframe();
break;
case ‘reviews’:
this.options.navigate = ‘reviews’;
this.displayIframe();
break;
case ‘button’:
this.addButton();
break;
case ‘contact-button’:
this.addContactButton();
break;
}
}
};
SimplybookWidget.prototype.onReceiveMessage = function(message) {
if (typeof message.data === ‘object’) {
if (!this.frame || message.source !== this.frame.contentWindow) {
return;
}
switch (message.data.event) {
case ‘appReady’:
this.setSettings(message.data);
break;
case ‘updateWidgetSize’:
this.updateWidgetSize(message.data);
break;
case ‘closeWidget’:
this.closePopup();
break;
case ‘modalShown’:
if (this.options.widget_type === ‘iframe’) {
this.changeModalPosition(message.data.listener_id);
}
break;
case ‘stepChanged’:
if (this.options.widget_type === ‘iframe’) {
this.scrollToContent(message.data.content_position);
}
break;
}
}
};
SimplybookWidget.prototype.setSettings = function() {
var win = this.frame.contentWindow || this.frame;
var postData = {
‘update_config’: true,
‘update_theme_vars’: true,
‘theme_vars’: this.options.theme_settings,
‘config_vars’: this.options.app_config,
};
if (this.options.navigate) {
postData[‘navigate’] = this.options.navigate;
this.options.navigate = null;
}
if (this.options.reviews_count || this.options.hide_add_reviews) {
postData[‘reviews_vars’] = {
“reviews_count”: this.options.reviews_count,
“hide_add_reviews”: parseInt(this.options.hide_add_reviews)
};
}
win.postMessage(postData, ‘');
};
SimplybookWidget.prototype.navigate = function(to) {
var win = this.frame.contentWindow || this.frame;
win.postMessage({
‘navigate’: to
}, '
’);
};
SimplybookWidget.prototype.scrollToContent = function(contentPos) {
var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
var iframePosition = this.frame.getBoundingClientRect();
var top = scrollTop + iframePosition.top + contentPos;
if (scrollTop > top) {
window.scrollTo(0, top);
}
};
SimplybookWidget.prototype.changeModalPosition = function(listenerId) {
var win = this.frame.contentWindow || this.frame;
var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
var iframePosition = this.frame.getBoundingClientRect();
var top = scrollTop + iframePosition.top;
var scrollTo = scrollTop - top;
win.postMessage({
‘update_modal_position’: true,
‘listener_id’: listenerId,
‘top’: Math.max(scrollTo, 0)
}, ‘*’);
};
SimplybookWidget.prototype.getUrl = function() {
var widget_type = this.options.widget_type;
if (widget_type == ‘contact-button’) {
widget_type = ‘button’;
}
var url = this.options.url + ‘/v2/?widget-type=’ + widget_type + ‘&theme=’ + this.options.theme;
if (this.options.theme) {
url += ‘&theme=’ + this.options.theme;
}
if (this.options.theme_id) {
url += ‘&theme_id=’ + this.options.theme_id;
}
if (this.options.timeline) {
url += ‘&timeline=’ + this.options.timeline;
}
if (this.options.datepicker) {
url += ‘&datepicker=’ + this.options.datepicker;
}
if (this.options.is_rtl) {
url += ‘&is_rtl=1’;
}
return url;
};
SimplybookWidget.prototype.subscribeMessages = function() {
var instance = this;
window.addEventListener(“message”, function(data) {
instance.onReceiveMessage(data);
}, false);
};
// iframe widget methods
SimplybookWidget.prototype.updateWidgetSize = function(data) {
if (this.options.widget_type !== ‘iframe’ && this.options.widget_type !== ‘reviews’) {
return;
}
this.frame.height = data.height;
};
SimplybookWidget.prototype.displayIframe = function() {
document.write(
‘’
);
this.frame = document.getElementById(this.name);
this.subscribeMessages();
};
// button widget methods
SimplybookWidget.prototype.addButton = function() {
this.addButtonWidgetStyles();
var btn;
if (this.options.button_custom_id) {
btn = document.getElementById(this.options.button_custom_id);
} else {
btn = this.getButtonNode();
}
var instance = this;
btn.addEventListener(‘click’, function() {
instance.showPopupFrame(‘book’);
});
document.body.appendChild(btn);
};
SimplybookWidget.prototype.addContactButton = function() {
this.addButtonWidgetStyles();
var btn;
if (this.options.button_custom_id) {
btn = document.getElementById(this.options.button_custom_id);
} else {
btn = this.getButtonNode();
}
var instance = this;
btn.addEventListener(‘click’, function() {
instance.showPopupFrame(‘contact-widget’);
});
document.body.appendChild(btn);
};
SimplybookWidget.prototype.getButtonNode = function() {
this.btn = document.createElement(‘div’);
this.btnLabel = document.createElement(‘div’);
this.btnLabel.innerText = this.options.button_title;
this.btn.appendChild(this.btnLabel);
this.updateButtonStyles();
return this.btn;
};
SimplybookWidget.prototype.updateButtonStyles = function(options) {
if (!this.btn) {
return;
}
if (options) {
this.options.button_position = options.button_position;
this.options.button_background_color = options.button_background_color;
this.options.button_text_color = options.button_text_color;
this.options.button_position_offset = options.button_position_offset;
this.options.button_title = options.button_title;
}
this.btn.className = ‘simplybook-widget-button ’ + this.options.button_position;
this.btn.style.backgroundColor = this.options.button_background_color;
this.btn.style.color = this.options.button_text_color;
if (this.options.button_position === ‘top’ || this.options.button_position === ‘bottom’) {
this.btn.style.right = this.options.button_position_offset;
this.btn.style.bottom = ‘’;
} else {
this.btn.style.bottom = this.options.button_position_offset;
this.btn.style.right = ‘’;
}
this.btnLabel.innerText = this.options.button_title;
};
SimplybookWidget.prototype.resetWidget = function(options) {
this.options = options;
this.updateButtonStyles(options);
this.container = null;
this.frame = null;
};
SimplybookWidget.prototype.showPopupFrame = function(navigateTo) {
if (navigateTo === undefined) {
navigateTo = ‘book’;
}
if (!this.container) {
this.container = document.createElement(‘div’);
this.container.className = ‘simplybook-widget-container active’;
this.options.navigate = navigateTo;
this.container.appendChild(this.getIframeNode());
document.body.appendChild(this.container);
} else {
this.container.className = ‘simplybook-widget-container active’;
this.navigate(navigateTo);
}
this.showOverlay();
};
SimplybookWidget.prototype.closePopup = function() {
this.hideOverlay();
this.container.className = ‘simplybook-widget-container’;
};
SimplybookWidget.prototype.showOverlay = function() {
if (!this.overlay) {
this.overlay = document.createElement(‘div’);
this.overlay.className = ‘simplybook-widget-overlay’;
var instance = this;
this.overlay.addEventListener(‘click’, function() {
instance.closePopup();
});
}
document.body.appendChild(this.overlay);
var instance = this;
// to show animated appear
setTimeout(function() {
instance.overlay.className = instance.overlay.className + ’ active’;
}, 10);
};
SimplybookWidget.prototype.hideOverlay = function() {
if (this.overlay) {
this.overlay.className = ‘simplybook-widget-overlay’;
var instance = this;
setTimeout(function() {
document.body.removeChild(instance.overlay);
}, 300);
}
};
SimplybookWidget.prototype.addButtonWidgetStyles = function() {
var link = document.createElement(‘link’);
link.setAttribute(‘rel’, ‘stylesheet’);
link.setAttribute(‘type’, ‘text/css’);
link.setAttribute(‘href’, this.options.url + ‘/v2/widget/widget.css’);
document.getElementsByTagName(‘head’)[0].appendChild(link);
};
SimplybookWidget.prototype.getIframeNode = function() {
if (!this.frame) {
this.frame = document.createElement(‘iframe’);
this.frame.border = ‘0’;
this.frame.frameBorder = ‘0’;
this.frame.name = this.name;
this.frame.id = this.name;
this.frame.src = this.getUrl();
this.subscribeMessages();
}
return this.frame;
};

Redmine Admin wrote:

this problem will be fixed with next system update withing few weeks

Anonymous wrote:

My users will have no booking capacity for “a few weeks”…? My app is a booking app. This renders my app useless… This error didn’t exist a week ago. Everything worked great.

Anonymous wrote:

Is there any way it can be done in less than a few weeks I have a hard launch date of March 21 and many companies will be using our app!! I’m sure every user says that but I’m just hoping this can get fixed or I’m going to have significant pressure from the higher ups to stop using your API for our app ecosystem if it is not stable with good reason. Thanks!