Insightly CRM Ajax API代理

时间:2015-11-23 03:50:19

标签: jquery python ajax cors crm

更新

您好我在尝试连接到Insightlys CRM的API时遇到CORS错误。我通过POSTMAN成功检索了Insightly CRM数据。

Insightly不支持用于AJAX请求的CORS(http://support.insight.ly/hc/en-us/community/posts/206961417-Using-the-API-with-AJAX),您必须设置API代理脚本。我在python中使用了下面提供的代理脚本并上传到我的专用主机。但我仍然收到401错误?

我对API代理很陌生,所以不确定我在这里遗漏了什么?

GET https://api.insight.ly/v2.2/Contacts 401 (Unauthorized)

apiproxy.py

#
# Insightly API Proxy for Python / App Engine
# Brian McConnell <brian@insightly.com>
#
# This utility is designed to act as an API proxy server. It is written in  Python 2.7
# and will run without modification on Google App Engine. Just serve your JavaScript
# from the /js directory in this project, and AJAX requests should be relayed through
# to the Insightly service. This should also run on any webapp2 compatible server platform
#

import base64
import os
import string
import types
import urllib
import urllib2
import webapp2
import wsgiref.handlers

#
# import google app engine libraries, replace these with standard 
#

try:
    from google.appengine.ext import webapp
except:
# skip Google App Engine webapp library
    pass

base_url = 'https://api.insight.ly/v2.2'

def authenticate():
#
# add user validation logic here, be careful to do this in a way that does not expose user secrets such as
# the user API key (this is why we do not allow CORS in the first place)
#

# hardcoding API key for now

apikey = 'fillinhere'
return base64.encode(apikey)

def generateRequest(url, method, data, alt_auth=None, test=False, headers=None):
"""
This method is used by other helper functions to generate HTTPS requests and parse server responses. This will minimize the amount of work developers need to do to integrate with the Insightly API, and will also eliminate common sources of errors such as authentication issues and malformed requests. Uses the urllib2 standard library, so it is not dependent on third party libraries like Requests
"""
if type(url) is not str: raise Exception('url must be a string')
if type(method) is not str: raise Exception('method must be a string')
valid_method = False
response = None
text = ''
if method == 'GET' or method == 'PUT' or method == 'DELETE' or method == 'POST':
valid_method = True
else:
raise Exception('parameter method must be GET|DELETE|PUT|UPDATE')
request = urllib2.Request(url)
request.get_method = lambda: method
request.add_header('Content-Type', 'application/json')
if headers is not None:
headerkeys = headers.keys()
for h in headerkeys:
    request.add_header(h, headers[h])
# open the URL, if an error code is returned it should raise an exception
if method == 'PUT' or method == 'POST':
result = urllib2.urlopen(request, data)
else:
result = urllib2.urlopen(request)
text = result.read()
return text

class APIProxyHandler(webapp2.RequestHandler):

def delete(self):
    apikey = authenticate()
    path_qs = self.request.headers['path_qs']
    url = base_url + path_qs
    headers = {'Authorization','Basic ' + api_key}
    text = generateRequest(url, 'DELETE', None, headers=headers)
    self.response.headers['Content-Type']='application/json'
    self.response.out.write(text)
def get(self):
    apikey = authenticate()
    path_qs = self.request.headers['path_qs']
    url = base_url + path_qs
    headers = {'Authorization','Basic ' + api_key}
    text = generateRequest(url, 'GET', None, headers=headers)
    self.response.headers['Content-Type']='application/json'
    self.response.out.write(text)
def post(self):
    body = self.request.headers['body']
    path_qs = self.request.headers['path_qs']
    url = base_url + path_qs
    headers = {'Authorization','Basic ' + api_key}
    text = generateRequest(url, 'POST', body, headers=headers)
    self.response.headers['Content-Type']='application/json'
    self.response.out.write(text)
def put(self):
    body = self.request.headers['body']
    path_qs = self.request.headers['path_qs']
    url = base_url + path_qs
    headers = {'Authorization','Basic ' + api_key}
    text = generateRequest(url, 'PUT', body, headers=headers)
    self.response.headers['Content-Type']='application/json'
    self.response.out.write(text)

app = webapp2.WSGIApplication([("r/(.*)", APIProxyHandler)], debug=True)
# map generic page server request handler

jQuery / Ajax调用:

Insightly = function () {
var _t = this;

this.events = function () {
    $(".contactsform").submit(_t.searchContacts);
};
this.searchContacts = function (event) {
event.preventDefault();
var $search = $(this);
console.log('[ Search contacts event ]');

$.ajaxPrefilter( function( options ) {
    if ( options.crossDomain ) {
    var newData = {};

    newData.data = $.extend({}, options.data);
    newData.url = options.url;

    options = {};

    // Set the proxy URL
    options.url = "http://www.blahblah.comm/apiproxy.py";
    console.log("ajaxprefilter");
    options.data = $.param(newData);
    console.log(options);
    options.crossDomain = false;
}
});
// How to use the cross domain proxy
$.ajax({         
    url: 'https://api.insight.ly/v2.2/Contacts',
    crossDomain: true, 
    processData: false 
    }).success(function(data) { 
    var jsonData = JSON.parse(data); 
    console.log(jsonData); 
});
};//End SearchContacts
this.init = function () {
    _t.events();
};
this.init();
return (this);   
};//End main function
var LZ = new Insightly();

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

这意味着您无法使用来自客户端的AJAX或javascript http请求直接访问其API。你需要做的是创建一个&#34;代理&#34; API。

A&#34;代理&#34; API是您在自己的域中托管客户端代码所需的服务。您需要使用您喜欢的服务器端语言向Insightly CRM API编写经过身份验证的服务器端API调用,并使用您的jquery AJAX调用它。

所以下面的代码将是:

var searchNotesUrl = "https://myowndomain.com/your/api/proxy/notes"

换句话说,您的服务器端脚本将是将CRM API中的数据传递给您的客户端的脚本。

如果它仍然获得401响应,那么如果用户和API密钥凭证正确,您可能需要检查它们。

<强>更新

你现在完全改变了这个问题。我上面的答案是针对您的最后一个问题版本。

对于新答案,您遇到此代码的问题:

$.ajaxPrefilter( function( options ) {
    if ( options.crossDomain ) {
    var newData = {};

    newData.data = $.extend({}, options.data);
    newData.url = options.url;

    options = {};

    // Set the proxy URL
    options.url = "http://www.blahblah.comm/apiproxy.py";
    console.log("ajaxprefilter");
    options.data = $.param(newData);
    console.log(options);
    options.crossDomain = false;
}
});
// How to use the cross domain proxy
$.ajax({         
    url: 'https://api.insight.ly/v2.2/Contacts',
    crossDomain: true, 
    processData: false 
    }).success(function(data) { 
    var jsonData = JSON.parse(data); 
    console.log(jsonData); 
});

首先,您仍然要求'https://api.insight.ly/v2.2/Contacts'。您不再需要请求此URL,因为您已拥有代理API。代理api("http://www.blahblah.comm/apiproxy.py")是您应该直接调用的代理api而不是向insight.ly发送请求。

您的Proxy API应该处理可以在insight.ly中发送的所有api请求。这意味着"http://www.blahblah.comm/apiproxy.py"可以支持notesContacts等等。

其次,正如您可以阅读python脚本一样,它实际上会查找请求标头密钥'path_qs'path_qs值应该类似于/Contacts。原因是因为path_qs正在通过base_url = 'https://api.insight.ly/v2.2'脚本中与url = base_url + path_qs连接。

所以代码就像:

$.ajax({ 
   method: 'GET', //this is because it is supposed to be GET
   crossDomain: true,
   dataType: 'json',
   url: 'http://www.blahblah.comm/apiproxy/that/executes', 
   headers: { 'path_qs': '/Contacts' },
   success : function(data, status, xhr) {
      console.log(data);
   }
});

您需要在Google应用引擎云中设置Python脚本作为应用程序。要了解更多信息,这是一个全新的主题: https://cloud.google.com/appengine/docs/python/gettingstartedpython27/helloworld