Angular 应用程序授权和 Zoho CRM 问题

问题描述 投票:0回答:3

我正在寻找一种构建 Angular 应用程序的方法,该应用程序可以发送请求并从 Zoho CRM 接收响应。我尝试了 Zoho CRM 文档中记录的所有可能性,但没有任何效果:

我遵循的步骤:

  1. 我在 https://api-console.zoho.com/ 上注册了该应用程序,作为基于客户端、基于服务器、自客户端。

  2. 我按照文档 https://www.zoho.com/accounts/protocol/oauth/web-server-applications.html 处理每种情况(客户端、服务器、自身)。

  3. 请求授权请求以获取代码并生成令牌以访问 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

  4. 我在重定向的URL中获得了代码
    https://www.zylker.com/oauthredirect?code=1000.9c3a2a6a5362125efc9f7666224313b6.d44f4b5b63e71fc682cdf20c771efead&location=我们

  5. 从应用程序生成令牌失败,甚至在使用上面的 URL 生成的代码从邮递员那里获取令牌后,任何请求也是如此。

并且总是遇到 CORS 政策问题,即使我在请求标头中添加了

"Access-Control-Allow-Origin":"*"
或将
*
替换为我的来源:

angular crm zoho
3个回答
1
投票
  1. https://api-console.zoho.com/ 上注册您的应用程序,作为基于客户端的

  1. 在您的 Angular 应用程序中,创建一个 RedirectComponent 并将其包含在您的 app-routing.module.ts

  1. 在您的资产中创建zcrmsdk.js并输入以下代码:

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)

  1. 将 Zoho CRM SDK 包含在您的资产中并将其添加到 index.html

    <script src="/assets/js/zcrmsdk.js"></script>

  2. 在根路径中创建一个globals.d.ts并声明SDK:

    declare var ZCRM : any;

  3. 现在您可以在项目中访问SDK了。

  4. 在您的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);

继续下一个答案


1
投票
  1. 运行您的项目,您应该会被重定向到 zoho 以授予您访问权限。

  2. 您还应该被重定向到您在 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);
    }

}

  1. 现在您可以在 app.component.ts 添加以下内容来获取响应:

var input = {'module' : 'Leads'};

    ZCRM.API.RECORDS.get(input).then(function(resp){
            var data = JSON.parse(resp).data;
      
     
        console.log("data", data)
});

  1. 在第3点上,我在第377行至第387行和第84行对createParams进行了一些修改,以适合我的情况,并且它应该也适用于您,我将发布原始SDK您也可以配置它。
原版SDK:

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)

我希望这能让别人的生活更轻松,如果有人有更好的解决方案,我很乐意检查


0
投票
对于 Angular 应用程序与 Zoho CRM 的集成问题,请考虑使用服务器端组件来安全地处理 OAuth 并在服务器上正确配置 CORS 设置。

如果您正在寻找更简单的解决方案,您可以探索类似于 Meetanshi 的

Magento 2 Zoho CRM 集成 的专用集成工具,它简化了 Magento 平台的 CRM 集成。以下是查看链接:Magento 2 Zoho CRM 集成。

© www.soinside.com 2019 - 2024. All rights reserved.