terça-feira, 26 de setembro de 2017

CRM-GT - Consumo de Web Api usando Javascript

Este artigo tem como objetivo documentar o uso de um importante recurso do meu sistema de gerenciamento com o cliente, o CRM-GT. Este recurso se chama Web Api, e serve como um [conector] entre o sistema CRMGT e qualquer sistema legado.

Esta é a URL principal de consumo REST: /api/CRMGT/QueryXML

Com este conector, você pode efetuar todo CRUD de operações. Portanto, segue abaixo o uso prático deste recurso, usando Javascript/JQuery.


Para obter o Token de acesso (OAuth)
function getToken() {
	var param = {
		"orgName": "CRMGT1",
		"clientId": "+n8c++NABWZrkldVUaf0XYH2T2lG5xvUhZEVxFz46/4=__5@_",
		"clientSecret": "7RclDz1Ilbp3jyOuXJNnyfaK3bW+MIt5fU0BL1f46to=__0@_"
	};

	$.ajax({
		type: 'GET',
		url: 'https://crm-gt.com:82/api/CRMGT/GetToken',
		data: param,
		dataType: 'json',
		async: false,
		beforeSend: function(xmlHttpRequest) {
			xmlHttpRequest.withCredentials = true;
		},
		success: function (data, textStatus, jqXHR) {
			token = data.token;
		},
		error: function (jqXHR, textStatus, errorThrown) {
			debugger;
		}
	});
}

Considerações importantes sobre o token.
- Ele expira a cada 3 horas.
- O [clientId] e o [clientSecret] são criados por Organização. O administrador da organização cria estas chaves e as disponibiliza para obtenção do Token.

Para Renovar o Token de acesso (OAuth)
function renewToken() {
    var param = {
        'orgName': 'CRMGT1',
        'clientId': '73ySJQsDnHDYugLRRYmtATjCxVmcNo2/Alz8RG9D+VQ=__5|@_11|4_13|._',
        'clientSecret': 'EPkMdqQcm0XgDxpn4lDcKKpEz0WPDQhgbXN6Nkl0JWw='
    };

    $.ajax({
        type: 'GET',
        url: 'https://crm-gt.com:82/api/CRMGT/RenewToken',
        data: param,
        dataType: 'json',
        async: false,
        beforeSend: function (xmlHttpRequest) {
            xmlHttpRequest.withCredentials = true;
        },
        success: function (data, textStatus, jqXHR) {
            if (data == null) {
                return 0;
            } else {
                token = data.token;
            }
        },
        error: function (jqXHR, textStatus, errorThrown) {
            console.log(errorThrown);
        }
    });
}

Como saber se o token de acesso expirou? Ao executar o endpoint /GetToken, o sistema retorna um atributo informando que o tempo expirou ("expires_in" : "0").

Para os métodos de CREATE e UPDATE, no momento da configuração da tag [fields/field] atributo [TYPE], informe os tipos correspondentes aos do [SQL SERVER].
Segue os principais:
bit
char
nchar
varchar
nvarchar
datetime
int
decimal
text
uniqueidentifier
Desta forma, se precisar adicionar um campo do tipo [string], informe [varchar].
Se precisar adicionar um campo do tipo [valor ou moeda], informe [decimal], e assim por diante.


Para efetuar um SELECT

function selectRecords() {
    var xmlSELECT = 
	"<select>" +
		"<organization name='CRMGT1' />" +
		"<table name='User' alias='tb1' />" +
		"<fields>" +
		"	<field name='tb1.UserId' label='ID' />" +
		"	<field name='tb1.Name' />" +
		"	<field name='tb1.Email' />" +
		"	<field name='tb2.Name' />" +
		"	<field name='tb3.Name' />" +
		"</fields>" +
		"<join isLeftJoin='false' name='Status' alias='tb2' fieldFrom='statuscode' fieldTo='statuscode'>" +
		"	<filter type='and'>" +
		"		<condition field='tb2.name' operator='=' value='Ativo' />" +
		"	</filter>" +
		"</join>" +
		"<join isLeftJoin='true' name='salesorder' alias='tb3' fieldFrom='userid' fieldTo='ownerid'>" +
		"	<filter type='and'>" +
		"		<condition field='tb3.name' operator='like' value='%ped%' />" +
		"	</filter>" +
		"</join>" +
		"<filter type='and'>" +
		"	<condition field='tb1.name' operator='like' value='%usr%' />" +
		"</filter>" +
		"<order>" +
		"	<field name='tb1.Name ASC'/>" +
		"	<field name='tb1.Email DESC'/>" +
		"</order>" +
	"</select>";

    var param = {
        "Type": "GET",
        "xmlContent": xmlSELECT
    };

    $.ajax({
        type: 'POST',
        url: "https://crm-gt.com:82/api/CRMGT/QueryXML",
        data: param,
        dataType: 'json',
        contentType: "application/x-www-form-urlencoded; charset=utf-8",
        beforeSend: function (xhr) {
            xhr.setRequestHeader("Authorization", "Bearer " + token);
        },
        success: function (data, textStatus, jqXHR) {
            if (textStatus == "success") {
                // JSON que representa os [registros] retornados
                var json = JSON.parse(data.Result);
            }
        },
        error: function (jqXHR, textStatus, errorThrown) {
            debugger;
        }
    });
}

Para efetuar um CREATE

function createRecord() {
    var xmlINSERT =
        "<insert>" +
        "<organization name='CRMGT1' />" +
        "<table name='account' isNN='false' setInternalFields='true' setWorkflowTrigger='false' />" +
        "<records>" +
        "    <record>" +
        "        <fields>" +
        "            <field name='accountid' type='uniqueidentifier' value='NEWID' />" +
        "            <field name='name' type='varchar' value='Create sample 1...' />" +
        "            <field name='AccountNumber' type='varchar' value='1' />" +
        "            <field name='ownerid' type='uniqueidentifier' lookuptable='user' lookupsearchfield='name' value='system' />" +
        "        </fields>" +
        "    </record>" +
        "    <record>" +
        "        <fields>" +
        "            <field name='accountid' type='uniqueidentifier' value='NEWID' />" +
        "            <field name='name' type='varchar' value='Create sample 2...' />" +
        "            <field name='AccountNumber' type='varchar' value='2' />" +
        "        </fields>" +
        "    </record>" +
        "</records>" +
        "</insert>";

    var param = {
        "Type": "SET",
        "xmlContent": xmlINSERT
    };

    $.ajax({
        type: 'POST',
        url: "https://crm-gt.com:82/api/CRMGT/QueryXML",        
        data: param,
        dataType: 'json',
        contentType: "application/x-www-form-urlencoded; charset=utf-8",
        beforeSend: function (xhr) {
            xhr.setRequestHeader("Authorization", "Bearer " + token);
        },
        success: function (data, textStatus, jqXHR) {
        },
        error: function (jqXHR, textStatus, errorThrown) {
        }
    });
}

Se precisar definir uma regra antes da criação dos registros, você pode adicionar a seguinte tag [rules] depois da tag [table]:
<rules>
	<rule action="insert_ignoreifexists" actionoperator="AND">
		<fields>
			<field name="protocol" type="VarChar" />
			<field name="incidentNumber" type="Int" />
		</fields>
	</rule>
</rules>

Desta forma, através da regra [insert_ignoreifexists] você não permite a inclusão do registro se os campos especificados na tag [fields] existirem na tabela.
Mas se você quiser [atualizar] o registro se ele for encontrado, use a regra [insert_updateifexists]. Para esta regra, o update será realizado usando na cláusula [where] a [chave primária] da tabela.

Formato de Campo Data
Sempre que passar um valor de data, passar no seguinte formato:


yyyyMMddTHHmmssZ


Exemplo: 20230616T095600Z


Se precisar [atualizar] o campo no CRM com valor Nulo:
<field name='dtFieldName' type='datetime' value='NULL' />


Se precisar [atualizar] o campo no CRM com a data [corrente]:
<field name='dtFieldName' type='datetime' value='GETDATE' />


Formato de Campo Decimal
Sempre que passar um valor decimal, usar o formato americano, somente com o separador de centavos:


Ex: 1234.56




Para efetuar um UPDATE

function updateRecord() {
    var xmlUPDATE =
       "<update>" +
       " <organization name='CRMGT1' />" +
       " <table name='account' setWorkflowTrigger='false' />" +
       " <set>" +
       "  <field name='name' type='varchar' value='UPDATED - Create sample 1...' setWorkflowFieldTrigger='false' />" +
       "  <field name='modifiedOn' type='datetime' value='GETDATE' />" +
       " </set>" +
       " <filter type='and'>" +
       "  <condition field='name' operator='=' value='Create sample 1...' />" +
       " </filter>" +
       "</update>";

    var param = {
       "Type": "SET",
       "xmlContent": xmlUPDATE
    };

    $.ajax({
        type: 'POST',
        url: "https://crm-gt.com:82/api/CRMGT/QueryXML",        
        data: param,
        dataType: 'json',
        contentType: "application/x-www-form-urlencoded; charset=utf-8",
        beforeSend: function (xhr) {
            xhr.setRequestHeader("Authorization", "Bearer " + token);
        },
        success: function (data, textStatus, jqXHR) {
        },
        error: function (jqXHR, textStatus, errorThrown) {
        }
    });
}

Para efetuar um DELETE

function deleteRecord() {
    var xmlDELETE =
        "<delete>" +
        " <organization name='CRMGT1' />" +
        " <table name='account' setWorkflowTrigger='false' />" +
        " <filter type='and'>" +
        "  <condition field='name' operator='like' value='%Create sample%' />" +
        " </filter>" +
        "</delete>";

    var param = {
        "Type": "SET",
        "xmlContent": xmlDELETE
    };

    $.ajax({
        type: 'POST',
        url: "https://crm-gt.com:82/api/CRMGT/QueryXML",        
        data: param,
        dataType: 'json',
        contentType: "application/x-www-form-urlencoded; charset=utf-8",
        beforeSend: function (xhr) {
            xhr.setRequestHeader("Authorization", "Bearer " + token);
        },
        success: function (data, textStatus, jqXHR) {
        },
        error: function (jqXHR, textStatus, errorThrown) {
        }
    });
}

Para executar uma [QUERY EXEC]

function executeQE() {
    var xmlQE =
	"<queryexec>" +
	" <organization name='CRMGT1' />" +
	" <queryexecid value='buscarocorrencia' />" +
	" <paramset>" +
	"	<param name='@_id_' type='uniqueidentifier' value='62a9a715-8574-4813-a69f-e732c76313e0' />" +
	" </paramset>" +
	"<filter type='and'>" +
	"	<condition field='inc.StatusCode' operator='=' value='1' />" +
	"</filter>" +
	"</queryexec>";

    var param = {
        "Type": "QueryExec",
        "xmlContent": xmlQE
    };

    $.ajax({
        type: 'POST',
        url: "https://crm-gt.com:82/api/CRMGT/QueryXML",        
        data: param,
        dataType: 'json',
        contentType: "application/x-www-form-urlencoded; charset=utf-8",
        beforeSend: function (xhr) {
            xhr.setRequestHeader("Authorization", "Bearer " + token);
        },
        success: function (data, textStatus, jqXHR) {
        },
        error: function (jqXHR, textStatus, errorThrown) {
        }
    });
}

Obs: As tags <paramset> e <filter> são [opcionais]. Elas são úteis quando precisar passar mais parâmetros de filtro para a Query Exec criada no sistema ou para substituir o valor das macros do sistema (@_id_ por exemplo).

Um comentário:

<< Ao enviar um comentário, favor clicar na opção [Enviar por e-mail comentários de acompanhamento para gtezini@gmail.com] >>