我正在寻找一种构建 Angular 应用程序的方法,该应用程序可以发送请求并从 Zoho CRM 接收响应。我尝试了 Zoho CRM 文档中记录的所有可能性,但没有任何效果:
我遵循的步骤:
我在 https://api-console.zoho.com/ 上注册了该应用程序,作为基于客户端、基于服务器、自客户端。
我按照文档 https://www.zoho.com/accounts/protocol/oauth/web-server-applications.html 处理每种情况(客户端、服务器、自身)。
请求授权请求以获取代码并生成令牌以访问 CRM API https://accounts.zoho.com/oauth/v2/auth?response_type=code&client_id=1000.GMB0YULZHJK411284S8I5GZ4CHUEX0&scope=AaaServer.profile.Read&redirect_uri=https://www.zylker.com/oauthredirect&prompt=consent
我在重定向的URL中获得了代码
https://www.zylker.com/oauthredirect?code=1000.9c3a2a6a5362125efc9f7666224313b6.d44f4b5b63e71fc682cdf20c771efead&location=我们
从应用程序生成令牌失败,甚至在使用上面的 URL 生成的代码从邮递员那里获取令牌后,任何请求也是如此。
并且总是遇到 CORS 政策问题,即使我在请求标头中添加了
"Access-Control-Allow-Origin":"*"
或将 *
替换为我的来源:
var libBase, headers, HTTP_METHODS, version;
version = 2;
HTTP_METHODS = {
GET: "GET",//No I18N
POST: "POST",//No I18N
PUT: "PUT",//No I18N
DELETE: "DELETE"//No I18N
};
function promiseResponse(request) {
return new Promise(function (resolve, reject) {
var body, baseUrl, xhr, i, formData;
libBase = localStorage.api_domain + "/crm/v" + version + "/";
// console.log("libbase", libBase)
baseUrl = libBase + request.url;
var token = ZCRM.API.AUTH.getAccess();
if (token == null) {
return resolve('{}'); // in case of no ticket, returns empty json
}
if (request.params) {
baseUrl = baseUrl + '?' + request.params;
}
xhr = new XMLHttpRequest();
xhr.withCredentials = true
xhr.open(request.type, baseUrl);
xhr.setRequestHeader("Authorization", "Zoho-oauthtoken " + token)
for (i in headers) {
xhr.setRequestHeader(i, headers[i]);
}
if (request.download_file) {
xhr.responseType = "blob";//No I18N
}
if (request.x_file_content) {
formData = new FormData();
formData.append('file', request.x_file_content);//No I18N
xhr.send(formData);
}
else {
body = request.body || null;
xhr.send(body);
}
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 204) {
var respObj = {
"message": "no data", //No I18N
"status_code": "204" //No I18N
}
resolve(JSON.stringify(respObj));
}
else {
if (request.download_file) {
var filename;
var disposition = xhr.getResponseHeader("Content-Disposition");//No I18N
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) {
filename = matches[1].replace(/['"]/g, '');
filename = filename.replace('UTF-8', '');
}
}
var blob = xhr.response;
var url = URL.createObjectURL(blob);
var ttt = document.createElement('a');
ttt.href = url;
ttt.download = filename;
ttt.click();
}
else {
resolve(xhr.response);
}
}
}
}
})
};
function createParams(parameters) {
var params, key;
for (key in parameters) {
if (parameters.hasOwnProperty(key)) {
params = parameters;
}
}
return params;
};
function constructRequestDetails(input, url, type, isModuleParam) {
var requestDetails = {};
requestDetails.type = type;
if (input != undefined) {
if (input.id) {
// console.log("IAM HERE 1");
url = url.replace("{id}", input.id);
// url = url + "/" + input.id;
}
else {
// console.log("IAM HERE 2");
url = url.replace("/{id}", "");
}
if (input.params) {
// console.log("IAM HERE1 3", input.params, "then", input.module, "hh", isModuleParam);
requestDetails.params = createParams(input.params) + (input.module && isModuleParam ? "module=" + input.module : "");//No I18N
}
if (!requestDetails.params && isModuleParam) {
// console.log("IAM HERE 4");
requestDetails.params = "module=" + input.module;//No I18N
}
if (input.body && (type == HTTP_METHODS.POST || type == HTTP_METHODS.PUT)) {
// console.log("IAM HERE 5");
requestDetails.body = JSON.stringify(input.body);
}
if (input.x_file_content) {
// console.log("IAM HERE 6");
requestDetails.x_file_content = input.x_file_content;
}
if (input.download_file) {
requestDetails.download_file = input.download_file;
}
}
requestDetails.url = url;
return requestDetails;
};
function getParameterByName(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)");
var results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
function sdk() {
return {
initialize: function (configuration) {
if (document.getElementById("zes_client_scope") == null) {
var elem = document.createElement('div');
elem.setAttribute("data-scope", configuration.scopes);
elem.setAttribute("data-clientid", configuration.clientId);
elem.setAttribute("data-accounts-url", configuration.accountUrl);
elem.setAttribute("id", "zes_client_scope");
document.body.appendChild(elem);
}
// console.log("initialize", document.body)
var input = {};
ZCRM.API.USERS.get(input).then(function (resp) {
});
}
}
}
function actions() {
return {
convert: function (input) {
return promiseResponse(constructRequestDetails(input, "Leads/{id}/actions/convert", HTTP_METHODS.POST, false));//No I18N
}
}
}
function attachments() {
return {
uploadFile: function (input) {
return promiseResponse(constructRequestDetails(input, input.module + "/{id}/Attachments", HTTP_METHODS.POST, false));//No I18N
},
deleteFile: function (input) {
return promiseResponse(constructRequestDetails(input, input.module + "/{id}/Attachments/" + input.relatedId, HTTP_METHODS.DELETE, false));//No I18N
},
downloadFile: function (input) {
input.download_file = true;
return promiseResponse(constructRequestDetails(input, input.module + "/{id}/Attachments/" + input.relatedId, HTTP_METHODS.GET, false));//No I18N
},
uploadLink: function (input) {
return promiseResponse(constructRequestDetails(input, input.module + "/{id}/Attachments", HTTP_METHODS.POST, false));//No I18N
},
uploadPhoto: function (input) {
return promiseResponse(constructRequestDetails(input, input.module + "/{id}/photo", HTTP_METHODS.POST, false));//No I18N
},
downloadPhoto: function (input) {
input.download_file = true;
return promiseResponse(constructRequestDetails(input, input.module + "/{id}/photo", HTTP_METHODS.GET, false));//No I18N
},
deletePhoto: function (input) {
return promiseResponse(constructRequestDetails(input, input.module + "/{id}/photo", HTTP_METHODS.DELETE, false));//No I18N
}
}
}
function org() {
return {
get: function (input) {
return promiseResponse(constructRequestDetails(input, "org", HTTP_METHODS.GET, true));//No I18N
}
}
}
function records() {
return {
get: function (input) {
// console.log("zcrm", input);
return promiseResponse(constructRequestDetails(input, input.module + "/{id}", HTTP_METHODS.GET, false));//No I18N
},
post: function (input) {
return promiseResponse(constructRequestDetails(input, input.module + "/{id}", HTTP_METHODS.POST, false));//No I18N
},
put: function (input) {
return promiseResponse(constructRequestDetails(input, input.module + "/{id}", HTTP_METHODS.PUT, false));//No I18N
},
delete: function (input) {
return promiseResponse(constructRequestDetails(input, input.module + "/{id}", HTTP_METHODS.DELETE, false));//No I18N
},
getNotes: function (input) {
return promiseResponse(constructRequestDetails(input, input.module + "/{id}/Notes", HTTP_METHODS.GET, false));//No I18N
},
getRelated: function (input) {
return promiseResponse(constructRequestDetails(input, input.module + "/{id}/" + input.relatedModule, HTTP_METHODS.GET, false));//No I18N
},
getAllDeletedRecords: function (input) {
if (input.params) {
input.params.type = "all";
}
else {
input.params = {
"type": "all"//No I18N
};
}
return promiseResponse(constructRequestDetails(input, input.module + "/deleted", HTTP_METHODS.GET, false));//No I18N
},
getRecycleBinRecords: function (input) {
if (input.params) {
input.type = "recycle";
}
else {
input.params = {
"type": "recycle"//No I18N
};
}
return promiseResponse(constructRequestDetails(input, input.module + "/deleted", HTTP_METHODS.GET, false));//No I18N
},
getPermanentlyDeletedRecords: function (input) {
if (input.params) {
input.type = "permanent";
}
else {
input.params = {
"type": "permanent"//No I18N
};
}
return promiseResponse(constructRequestDetails(input, input.module + "/deleted", HTTP_METHODS.GET, false));//No I18N
},
search: function (input) {
return promiseResponse(constructRequestDetails(input, input.module + "/search", HTTP_METHODS.GET, false));//No I18N
}
}
}
function settings() {
return {
getFields: function (input) {
return promiseResponse(constructRequestDetails(input, "settings/fields/{id}", HTTP_METHODS.GET, true));//No I18N
},
getLayouts: function (input) {
return promiseResponse(constructRequestDetails(input, "settings/layouts/{id}", HTTP_METHODS.GET, true));//No I18N
},
getCustomViews: function (input) {
return promiseResponse(constructRequestDetails(input, "settings/custom_views/{id}", HTTP_METHODS.GET, true));//No I18N
},
updateCustomViews: function (input) {
return promiseResponse(constructRequestDetails(input, "settings/custom_views/{id}", HTTP_METHODS.PUT, true));//No I18N
},
getModules: function (input) {
return promiseResponse(constructRequestDetails(input, "settings/modules" + ((input && input.module) ? "/" + input.module : ""), HTTP_METHODS.GET, false));//No I18N
},
getRoles: function (input) {
return promiseResponse(constructRequestDetails(input, "settings/roles/{id}", HTTP_METHODS.GET, true));//No I18N
},
getProfiles: function (input) {
return promiseResponse(constructRequestDetails(input, "settings/profiles/{id}", HTTP_METHODS.GET, true));//No I18N
},
getRelatedLists: function (input) {
return promiseResponse(constructRequestDetails(input, "settings/related_lists/{id}", HTTP_METHODS.GET, true));//No I18N
}
}
}
function users() {
return {
get: function (input) {
return promiseResponse(constructRequestDetails(input, "users/{id}", HTTP_METHODS.GET, true));//No I18N
}
}
}
var listener = 0;
function auth() {
return {
getAccess: function () {
// console.log("inside auth");
if (listener == 0) {
// console.log("inside auth 1");
window.addEventListener("storage", function (e) {
if (e.key === 'access_token' && e.oldValue != e.newValue && e.oldValue == null) {
location.reload();
}
if (e.key === 'access_token') {
localStorage.removeItem('__auth_process');
}
}, false);
listener = 1;
if (localStorage.getItem('__auth_process')) {
// console.log("inside auth 2", localStorage.getItem('__auth_process'));
localStorage.removeItem('__auth_process');
}
}
var valueInStore = localStorage.getItem('access_token');
// console.log("inside auth 3", valueInStore);
var token_init = localStorage.getItem('__token_init');
// console.log("inside auth 4", token_init);
if (token_init != null && valueInStore != null && Date.now() >= parseInt(token_init) + 55 * 60 * 1000) { // check after 55 mins
// console.log("inside auth 5");
valueInStore = null;
localStorage.removeItem('access_token');
}
var auth_process = localStorage.getItem('__auth_process');
// console.log("inside auth 6", auth_process);
if (valueInStore == null && auth_process == null) {
// console.log("inside auth 7");
var accountsUrl = document.getElementById("zes_client_scope").getAttribute("data-accounts-url");
// console.log("inside auth 8", accountsUrl);
var endPoint = "/oauth/v2/auth";
var full_grant = localStorage.getItem('full_grant');
// console.log("inside auth 9", full_grant);
if (full_grant != null && 'true' == full_grant && localStorage.getItem('__token_init') != null) {
// console.log("inside auth 10");
endPoint += '/refresh';
}
var client_id = document.getElementById("zes_client_scope").getAttribute("data-clientid");
var scope = document.getElementById("zes_client_scope").getAttribute("data-scope");
// console.log("inside auth 10", client_id, scope);
var path = window.location.pathname;
// console.log("inside auth 11", path);
// console.log(location.hostname)
var redirect_url = window.location.origin;
// console.log("inside auth 12", redirect_url);
var pathSplit = path.split('/');
var length = pathSplit.length
for (var i = 0; i < length - 2; i++) {
redirect_url += pathSplit[i] + "/";
}
if (location.hostname == "127.0.0.1" || location.hostname == "") {
if (length - 2 == 0) {
redirect_url += "/";
}
redirect_url += "app/"
}
// if ( location.hostname == "localhost" ){
// }
redirect_url = redirect_url + "/redirect";
// console.log("rediret", redirect_url);
if (client_id && scope) {
// console.log("inside auth 13", valueInStore)
localStorage.setItem('__token_init', Date.now());
localStorage.removeItem('access_token');
localStorage.setItem('__auth_process', 'true');
// var popup =
window.open(accountsUrl + endPoint + "?scope=" + scope + "&client_id=" + client_id + "&response_type=token&state=zohocrmclient&redirect_uri=" + redirect_url);//,'', 'width:' + window.innerWidth + ',height:' + window.innerHeight);
// popup.focus();
}
else {
throw 'missing auth params[clientId, redirectUri, scope]';
}
}
return valueInStore;
},
revokeAccess: function () {
localStorage.removeItem('crm_access_token');
}
}
}
var ZCRM = (function (argument) {
return {
API: (function (argument) {
return {
SDK: new sdk(),
AUTH: new auth(),
RECORDS: new records(),
SETTINGS: new settings(),
ACTIONS: new actions(),
USERS: new users(),
ORG: new org(),
ATTACHMENTS: new attachments()
}
})(this),
init: function (data) {
if (data.constructor === {}.constructor && data.hasOwnProperty('full_grant') && data['full_grant'] == true) {
localStorage.setItem('full_grant', 'true');
}
}
}
})(this)
将 Zoho CRM SDK 包含在您的资产中并将其添加到 index.html:
<script src="/assets/js/zcrmsdk.js"></script>
在根路径中创建一个globals.d.ts并声明SDK:
declare var ZCRM : any;
现在您可以在项目中访问SDK了。
在您的app.component.ts中,您需要在ngOnInit中使用正确的配置初始化SDK:
var configuration = {};
configuration.client_id = CLIENT_ID;
configuration.scopes = SCOPES;
configuration.accounts_url = ACCOUNTS_URL;
ZCRM.API.SDK.initialize(configuration);
继续下一个答案
运行您的项目,您应该会被重定向到 zoho 以授予您访问权限。
您还应该被重定向到您在 zoho 控制台中设置的重定向 URL,请添加以下内容以便将参数保存到您的本地存储,redirect.component.ts:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-redirect',
templateUrl: './redirect.component.html',
styleUrls: ['./redirect.component.css']
})
export class RedirectComponent implements OnInit {
constructor() { }
ngOnInit(): void {
this.setAccessToken();
}
getPropertiesFromURL() {
var props: any = {};
var propertyString = window.location.hash || window.location.search;
if (propertyString && typeof propertyString === 'string') {
propertyString = propertyString.slice(1);
if (propertyString) {
propertyString
.split('&')
.forEach(function (prop) {
var key = prop.split('=')[0], value = prop.split('=')[1];
props[key] = value;
});
}
}
return props;
}
// set the access token and grant access to localstorage
setAccessToken() {
var hashProps = this.getPropertiesFromURL();
console.log("hashprops", hashProps)
if (hashProps) {
for (var k in hashProps) {
if (hashProps.hasOwnProperty(k)) {
var key = (k === 'access_toke' || k === 'access_token') ? 'access_token' : k;
var value = (k === 'api_domain') ? decodeURIComponent(hashProps[k]) : hashProps[k];
localStorage.setItem(key, value);
}
}
}
setTimeout(function () { window.close(); }, 0);
}
}
var input = {'module' : 'Leads'};
ZCRM.API.RECORDS.get(input).then(function(resp){
var data = JSON.parse(resp).data;
console.log("data", data)
});
var libBase, headers, HTTP_METHODS, version;
version = 2;
HTTP_METHODS = {
GET : "GET",//No I18N
POST : "POST",//No I18N
PUT : "PUT",//No I18N
DELETE : "DELETE"//No I18N
};
function promiseResponse(request) {
return new Promise(function (resolve, reject) {
var body, baseUrl, xhr, i, formData;
libBase = localStorage.api_domain+"/crm/v"+version+"/";
baseUrl = libBase + request.url;
var token = ZCRM.API.AUTH.getAccess();
if(token == null){
return resolve('{}'); // in case of no ticket, returns empty json
}
if (request.params)
{
baseUrl = baseUrl + '?' + request.params;
}
xhr = new XMLHttpRequest();
xhr.withCredentials = true
xhr.open(request.type, baseUrl);
xhr.setRequestHeader("Authorization", "Zoho-oauthtoken "+token)
for (i in headers)
{
xhr.setRequestHeader(i, headers[i]);
}
if (request.download_file){
xhr.responseType = "blob";//No I18N
}
if (request.x_file_content) {
formData = new FormData();
formData.append('file', request.x_file_content);//No I18N
xhr.send(formData);
}
else{
body = request.body || null;
xhr.send(body);
}
xhr.onreadystatechange = function() {
if(xhr.readyState == 4){
if (xhr.status == 204)
{
var respObj = {
"message" : "no data", //No I18N
"status_code" : "204" //No I18N
}
resolve(JSON.stringify(respObj));
}
else
{
if (request.download_file){
var filename;
var disposition = xhr.getResponseHeader("Content-Disposition");//No I18N
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) {
filename = matches[1].replace(/['"]/g, '');
filename = filename.replace('UTF-8','');
}
}
var blob = xhr.response;
var url = URL.createObjectURL(blob);
var ttt = document.createElement('a');
ttt.href = url;
ttt.download = filename;
ttt.click();
}
else{
resolve(xhr.response);
}
}
}
}
})
};
function createParams(parameters)
{
var params, key;
for (key in parameters)
{
if (parameters.hasOwnProperty(key)) {
if (params)
{
params = params + key + '=' + parameters[key] + '&';
}
else
{
params = key + '=' + parameters[key] + '&';
}
}
}
return params;
};
function constructRequestDetails(input, url, type, isModuleParam)
{
var requestDetails = {};
requestDetails.type = type;
if (input != undefined)
{
if (input.id)
{
url = url.replace("{id}", input.id);
// url = url + "/" + input.id;
}
else
{
url = url.replace("/{id}", "");
}
if (input.params)
{
requestDetails.params = createParams(input.params) + (input.module && isModuleParam ? "module=" + input.module : "");//No I18N
}
if (!requestDetails.params && isModuleParam)
{
requestDetails.params = "module=" + input.module;//No I18N
}
if (input.body && (type == HTTP_METHODS.POST || type == HTTP_METHODS.PUT))
{
requestDetails.body = JSON.stringify(input.body);
}
if (input.x_file_content)
{
requestDetails.x_file_content = input.x_file_content;
}
if (input.download_file)
{
requestDetails.download_file = input.download_file;
}
}
requestDetails.url = url;
return requestDetails;
};
function getParameterByName(name, url)
{
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)");
var results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
function sdk()
{
return {
initialize : function (configuration)
{
if(document.getElementById("zes_client_scope") == null){
var elem = document.createElement('div');
elem.setAttribute("data-scope",configuration.scopes);
elem.setAttribute("data-clientid",configuration.client_id);
elem.setAttribute("data-accounts-url",configuration.accounts_url);
elem.setAttribute("id","zes_client_scope");
document.body.appendChild(elem);
}
var input = {};
ZCRM.API.USERS.get(input).then(function(resp){
});
}
}
}
function actions()
{
return {
convert : function (input)
{
return promiseResponse(constructRequestDetails(input, "Leads/{id}/actions/convert", HTTP_METHODS.POST, false));//No I18N
}
}
}
function attachments()
{
return {
uploadFile : function (input)
{
return promiseResponse(constructRequestDetails(input, input.module+ "/{id}/Attachments", HTTP_METHODS.POST, false));//No I18N
},
deleteFile : function (input)
{
return promiseResponse(constructRequestDetails(input, input.module+ "/{id}/Attachments/"+input.relatedId, HTTP_METHODS.DELETE, false));//No I18N
},
downloadFile : function (input)
{
input.download_file = true;
return promiseResponse(constructRequestDetails(input, input.module+ "/{id}/Attachments/"+input.relatedId, HTTP_METHODS.GET, false));//No I18N
},
uploadLink : function (input)
{
return promiseResponse(constructRequestDetails(input, input.module+ "/{id}/Attachments", HTTP_METHODS.POST, false));//No I18N
},
uploadPhoto : function (input)
{
return promiseResponse(constructRequestDetails(input, input.module+ "/{id}/photo", HTTP_METHODS.POST, false));//No I18N
},
downloadPhoto : function (input)
{
input.download_file = true;
return promiseResponse(constructRequestDetails(input, input.module + "/{id}/photo", HTTP_METHODS.GET, false));//No I18N
},
deletePhoto : function (input)
{
return promiseResponse(constructRequestDetails(input, input.module + "/{id}/photo", HTTP_METHODS.DELETE, false));//No I18N
}
}
}
function org()
{
return {
get : function (input)
{
return promiseResponse(constructRequestDetails(input, "org", HTTP_METHODS.GET, true));//No I18N
}
}
}
function records()
{
return {
get : function(input)
{
return promiseResponse(constructRequestDetails(input, input.module + "/{id}", HTTP_METHODS.GET, false));//No I18N
},
post : function(input)
{
return promiseResponse(constructRequestDetails(input, input.module + "/{id}", HTTP_METHODS.POST, false));//No I18N
},
put : function(input)
{
return promiseResponse(constructRequestDetails(input, input.module + "/{id}", HTTP_METHODS.PUT, false));//No I18N
},
delete : function (input)
{
return promiseResponse(constructRequestDetails(input, input.module + "/{id}", HTTP_METHODS.DELETE, false));//No I18N
},
getNotes : function (input)
{
return promiseResponse(constructRequestDetails(input, input.module + "/{id}/Notes", HTTP_METHODS.GET, false));//No I18N
},
getRelated : function (input)
{
return promiseResponse(constructRequestDetails(input, input.module + "/{id}/"+input.relatedModule, HTTP_METHODS.GET, false));//No I18N
},
getAllDeletedRecords : function (input)
{
if (input.params)
{
input.params.type = "all";
}
else
{
input.params = {
"type" : "all"//No I18N
};
}
return promiseResponse(constructRequestDetails(input, input.module + "/deleted", HTTP_METHODS.GET, false));//No I18N
},
getRecycleBinRecords : function (input)
{
if (input.params)
{
input.type = "recycle";
}
else
{
input.params = {
"type" : "recycle"//No I18N
};
}
return promiseResponse(constructRequestDetails(input, input.module + "/deleted", HTTP_METHODS.GET, false));//No I18N
},
getPermanentlyDeletedRecords : function (input)
{
if (input.params)
{
input.type = "permanent";
}
else
{
input.params = {
"type" : "permanent"//No I18N
};
}
return promiseResponse(constructRequestDetails(input, input.module + "/deleted", HTTP_METHODS.GET, false));//No I18N
},
search : function (input)
{
return promiseResponse(constructRequestDetails(input, input.module + "/search", HTTP_METHODS.GET, false));//No I18N
}
}
}
function settings()
{
return {
getFields : function (input)
{
return promiseResponse(constructRequestDetails(input, "settings/fields/{id}", HTTP_METHODS.GET, true));//No I18N
},
getLayouts : function (input)
{
return promiseResponse(constructRequestDetails(input, "settings/layouts/{id}", HTTP_METHODS.GET, true));//No I18N
},
getCustomViews : function (input)
{
return promiseResponse(constructRequestDetails(input, "settings/custom_views/{id}", HTTP_METHODS.GET, true));//No I18N
},
updateCustomViews : function (input)
{
return promiseResponse(constructRequestDetails(input, "settings/custom_views/{id}", HTTP_METHODS.PUT, true));//No I18N
},
getModules : function (input)
{
return promiseResponse(constructRequestDetails(input, "settings/modules" + ((input && input.module) ? "/" + input.module : ""), HTTP_METHODS.GET, false));//No I18N
},
getRoles : function (input)
{
return promiseResponse(constructRequestDetails(input, "settings/roles/{id}", HTTP_METHODS.GET, true));//No I18N
},
getProfiles : function (input)
{
return promiseResponse(constructRequestDetails(input, "settings/profiles/{id}", HTTP_METHODS.GET, true));//No I18N
},
getRelatedLists : function (input)
{
return promiseResponse(constructRequestDetails(input, "settings/related_lists/{id}", HTTP_METHODS.GET, true));//No I18N
}
}
}
function users()
{
return {
get : function (input)
{
return promiseResponse(constructRequestDetails(input, "users/{id}", HTTP_METHODS.GET, true));//No I18N
}
}
}
var listener = 0;
function auth()
{
return {
getAccess : function(){
if(listener == 0){
window.addEventListener("storage", function(e){
if(e.key === 'access_token' && e.oldValue!=e.newValue && e.oldValue == null){
location.reload();
}
if(e.key === 'access_token'){
localStorage.removeItem('__auth_process');
}
}, false);
listener = 1;
if(localStorage.getItem('__auth_process')){ localStorage.removeItem('__auth_process'); }
}
var valueInStore = localStorage.getItem('access_token');
var token_init = localStorage.getItem('__token_init');
if(token_init != null && valueInStore != null && Date.now() >= parseInt(token_init)+55*60*1000){ // check after 55 mins
valueInStore = null;
localStorage.removeItem('access_token');
}
var auth_process = localStorage.getItem('__auth_process');
if (valueInStore == null && auth_process == null)
{
var accountsUrl =document.getElementById("zes_client_scope").getAttribute("data-accounts-url");
var endPoint = "/oauth/v2/auth";
var full_grant = localStorage.getItem('full_grant');
if(full_grant != null && 'true' == full_grant && localStorage.getItem('__token_init') != null){
endPoint += '/refresh';
}
var client_id = document.getElementById("zes_client_scope").getAttribute("data-clientid");
var scope = document.getElementById("zes_client_scope").getAttribute("data-scope");
var path = window.location.pathname;
var redirect_url = window.location.origin;
var pathSplit = path.split('/');
var length=pathSplit.length
for (var i=0;i<length-2;i++){
redirect_url +=pathSplit[i]+"/";
}
if(location.hostname=="127.0.0.1" ||location.hostname=="localhost" ||location.hostname=="" ){
if(length-2 == 0)
{
redirect_url += "/";
}
redirect_url += "app/"
}
redirect_url = redirect_url + "redirect.html";
if (client_id && scope){
localStorage.setItem('__token_init', Date.now());
localStorage.removeItem('access_token');
localStorage.setItem('__auth_process', 'true');
var popup = window.open(accountsUrl+endPoint+"?scope="+scope+"&client_id="+client_id+"&response_type=token&state=zohocrmclient&redirect_uri="+redirect_url);//,'', 'width:' + window.innerWidth + ',height:' + window.innerHeight);
//popup.focus();
}
else{
throw 'missing auth params[clientId, redirectUri, scope]';
}
}
return valueInStore;
},
revokeAccess : function (){
localStorage.removeItem('crm_access_token');
}
}
}
var ZCRM = (function (argument) {
return {
API : (function (argument) {
return{
SDK : new sdk(),
AUTH : new auth(),
RECORDS : new records(),
SETTINGS : new settings(),
ACTIONS : new actions(),
USERS : new users(),
ORG : new org(),
ATTACHMENTS : new attachments()
}
})(this),
init: function(data){
if(data.constructor === {}.constructor && data.hasOwnProperty('full_grant') && data['full_grant'] == true){
localStorage.setItem('full_grant', 'true');
}
}
}
})(this)
我希望这能让别人的生活更轻松,如果有人有更好的解决方案,我很乐意检查
如果您正在寻找更简单的解决方案,您可以探索类似于 Meetanshi 的
Magento 2 Zoho CRM 集成 的专用集成工具,它简化了 Magento 平台的 CRM 集成。以下是查看链接:Magento 2 Zoho CRM 集成。