Migrated from Redmine #124 | Author: Anonymous
Status: Closed | Priority: Normal | Created: 2018-03-08
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://user-api.simplybook.me/. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
I keep getting this error when trying to access the API. It is random. Sometimes it comes up and sometimes not. Other times I get a 503 “Service Temporarily Unavailable.” with this message.
Below is my code to access the API:
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;
}
// 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};
THIS IS THE JSONRPC SETUP CODE
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;
}
- Default options
});
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;
};