Caros, Alguém já fez ou sabe como fazer a integração do Suitecrm com o RD Station, preciso receber os leads do RD Station no meu Suitecrm.
Uma alternativa é fazer um webhook dentro do rd station utilizando os gatilhos de conversão, apontando para um entrypoint dentro do SuiteCRM.
No SuiteCRM você cria um custom EntryPoint para receber e tratar os dados do RD station, criando uma oportunidade a partir destes dados!
Veja aqui e pergunte a esse usuário, ele conseguiu
https://suitecrm.com/suitecrm/forum/suitecrm-7-0-discussion/21071-desenvolvimento-de-plugin
O Suitecrm ja possui um entrypoint de forma nativa ou teria que ser desenvolvido?
Voce teria que desenvolver um custom entry point para atender as suas necessidades
O WebTo Person form usa um entry-point já feito.
https://docs.suitecrm.com/user/core-modules/campaigns/#_web_to_person_form
E além disso pode-se usar a API.
Estou usando o Webto Person, irei criar um webhooks por parte do RD Station e tentarei inserir estes dados no web to person.
Ótimo, se conseguir fazer poste a sua resolução! Eu consegui efetuar a integração com o RD Station por meio de um custom EntryPoint, se precisar de alguma ajuda estou a disposição!
gabriells1234 seria de grande ajuda se você me mostrasse como fez esta integração com o custom entrypoint, por que muito provavelmente você encontrou a mesma barreira que eu.
Posso te ajudar sim!
Primeiro voce tera que criar o arquivo MyEntrypoints.php em \custom\Extension\application\Ext\EntryPointRegistry para definir os EntryPoints que serão utilizados:
Entendi, infelizmente eu não programo nada em PHP, sei que é pedir muito mas se você poder postar o código aqui com uma logica onde receberíamos: Nome, e-mail, telefone e identificador acho que resolveria meu problema e de muita gente que tem essa mesma demanda.
Mesmo não sendo possível já te agradeço, pois você já me deu uma grande ajuda.
Certo, irei postar meu código com exemplos de models e arquivos genéricos, voce apenas implementa as outras models necessárias para a sua aplicação seguindo o exemplo e postarei meu entrypoint!
Accoun_model.php -> custom/input/models/
<?php
class Account_model
{
private $Id;
private $Nome;
private $Empresa;
private $Email;
private $Cnpj;
private $Cidade;
private $Telefone;
private $Estado;
private $Tipo;
private $AtribuidoA;
public function __construct()
{
$this->Id = null;
$this->Nome = null;
$this->Email = null;
$this->Empresa = null;
$this->Cnpj = null;
$this->Cidade = null;
$this->Telefone = null;
$this->Estado = null;
$this->Tipo = null;
$this->AtribuidoA = null;
}
public function setId($Id)
{
$this->Id = $Id;
}
public function getId()
{
return $this->Id;
}
public function setNome($Nome)
{
$this->Nome = $Nome;
}
public function getNome()
{
return $this->Nome;
}
public function setEmpresa($Empresa)
{
$this->Empresa = $Empresa;
}
public function getEmpresa()
{
return $this->Empresa;
}
public function setEmail($Email)
{
$this->Email = $Email;
}
public function getEmail()
{
return $this->Email;
}
public function setCnpj($Cnpj)
{
$this->Cnpj = $Cnpj;
}
public function getCnpj()
{
return $this->Cnpj;
}
public function setCidade($Cidade)
{
$this->Cidade = $Cidade;
}
public function getCidade()
{
return $this->Cidade;
}
public function setTelefone($Telefone)
{
$this->Telefone = $Telefone;
}
public function getTelefone()
{
return $this->Telefone;
}
public function setEstado($Estado)
{
$this->Estado = $Estado;
}
public function getEstado()
{
return $this->Estado;
}
public function setTipo($Tipo)
{
$this->Tipo = $Tipo;
}
public function getTipo()
{
return $this->Tipo;
}
public function setAtribuidoA($AtribuidoA)
{
$this->AtribuidoA = $AtribuidoA;
}
public function getAtribuidoA()
{
return $this->AtribuidoA;
}
}
GenericAccount.php -> custom/input/generic
<?php
class GenericAccount
{
private $fileLog;//ponteiro para o arquivo de log
/*!
* RESPONSÁVEL POR CARREGAR AS DIRETRIZES INICIAIS.
*/
public function __construct()
{
date_default_timezone_set('America/Sao_Paulo');//seta o fuso horário correto
$this->fileLog = fopen("C:/xampp/htdocs/crmAlpha/custom/input/logs/exception.log","a");//define o arquivo de log
}
/*!
* RESPONSÁVEL POR CRIAR UMA NOVA CONTA DA REVENDA OU DO CLIENTE FINAL.
*
* $Account -> Objeto que contém os dados de conta a serem cadastrados.
*/
public function CreateAccount($Account)
{
try
{
$bean = BeanFactory::newBean('Accounts');
$bean->name = $Account->getEmpresa();
$bean->email1 = $Account->getEmail();
$bean->cnpj_c = $Account->getCnpj();
$bean->phone_office = $Account->getTelefone();
$bean->billing_address_city = $Account->getCidade();
$bean->shipping_address_city = $Account->getCidade();
$bean->billing_address_state = $Account->getEstado();
$bean->shipping_address_state = $Account->getEstado();
$bean->assigned_user_id = $Account->getAtribuidoA();
$bean->account_type = $Account->getTipo();
$bean->save();
}
catch(Exception $e)
{
$texto = "\r\n----------EXCEPTION CREATE ACCOUNT--------".date("Y/m/d H:i:s")."---\r\n";
$texto .= "Mensagem: ".$e->getMessage()."\r\n";
$texto .= "\r\n";
$texto .= "\r\n----------EXCEPTION CREATE ACCOUNT--------".date("Y/m/d H:i:s")."---\r\n";
$this->WriteFile($texto);
}
}
/*!
* RESPONSÁVEL POR ATUALIZAR OS DADOS DE UMA CONTA (CLIENTE OU REVENDA), TODA VEZ QUE ENTRAR UMA OPORTUNIDADE.
*
* $Account -> Dados da conta a ser atualizada.
*/
public function UpdateAccount($Account)
{
try
{
$bean = BeanFactory::getBean('Accounts', $Account->getId());
$bean->name = $Account->getEmpresa();
$bean->email1 = $Account->getEmail();
$bean->cnpj_c = $Account->getCnpj();
$bean->phone_office = $Account->getTelefone();
$bean->billing_address_city = $Account->getCidade();
$bean->shipping_address_city = $Account->getCidade();
$bean->billing_address_state = $Account->getEstado();
$bean->shipping_address_state = $Account->getEstado();
$bean->assigned_user_id = $Account->getAtribuidoA();
$bean->account_type = $Account->getTipo();
$bean->save();
}
catch(Exception $e)
{
$texto = "\r\n----------EXCEPTION UPDATE ACCOUNT--------".date("Y/m/d H:i:s")."---\r\n";
$texto .= "Mensagem: ".$e->getMessage()."\r\n";
$texto .= "\r\n";
$texto .= "\r\n----------EXCEPTION UPDATE ACCOUNT--------".date("Y/m/d H:i:s")."---\r\n";
$this->WriteFile($texto);
}
}
/*!
* RESPONSÁVEL POR VERIFICAR SE UMA DETERMINADA CONTA JÁ EXISTE NO CRM.
*
* $emailLead -> E-mail do lead a ser procurado em alguma conta.
*
* return -> Se encontra a conta, retorna o objeto referente a ela, caso contrário retorna nulo.
*/
public function GetAccount($emailLead)
{
include(dirname(__FILE__)."\..\settings\conexao.php");
require_once(dirname(__FILE__)."\..\models\Account_model.php");
$Account = new Account_model();
$deletado = 0;
try{
$query = $conexao->prepare("SELECT a.id, a.name, ea.email_address, a.billing_address_city,
a.phone_office, a.billing_address_state, a.account_type, a.assigned_user_id FROM email_addresses ea
INNER JOIN email_addr_bean_rel eabr ON ea.id = eabr.email_address_id AND
UPPER(ea.email_address) = UPPER(?) AND eabr.deleted = ?
INNER JOIN accounts a ON a.id = eabr.bean_id ");
$query->bindParam(1, $emailLead);
$query->bindParam(2, $deletado);
$query->execute();
if($query->rowCount() == 0)
return null;
else
{
$query = $query->fetch(PDO::FETCH_OBJ);
$Account->setId($query->id);
//$Account->setNome($query->name);
$Account->setEmpresa($query->name);
$Account->setEmail($query->email_address);
//$Account->setCnpj($query->cnpj_c);
$Account->setCidade($query->billing_address_city);
$Account->setTelefone($query->phone_office);
$Account->setEstado($query->billing_address_state);
$Account->setTipo($query->account_type);
$Account->setAtribuidoA($query->assigned_user_id);
return $Account;
}
}
catch(PDOException $e)
{
$texto = "\r\n----------EXCEPTION QUERY ACCOUNT--------".date("Y/m/d H:i:s")."---\r\n";
$texto .= "Mensagem: ".$e->getMessage()."\r\n";
$texto .= "\r\n----------EXCEPTION QUERY ACCOUNT--------".date("Y/m/d H:i:s")."---\r\n";
$this->WriteFile($texto);
return null;
}
}
/*!
* RESPONSÁVEL POR ESCREVER O LOG NO ARQUIVO.
*
* $texto -> Contém o texto de log a ser escrito.
*/
function WriteFile($texto)
{
fwrite($this->fileLog, $texto." \r\n");
}
/*!
* RSPONSÁVEL POR DESTRUIR O PONTEIRO QUE CONTÉM A INSTÂNCIA DO ARQUIVO DE LOG.
*/
public function __destruct()
{
fclose($this->fileLog);
}
}
EntryPoint.php -> custom/input
<?php
require_once("settings/defines.php");
require_once("generic/GenericOpportunity.php");
class OportunidadeCotacaoSiteEntryPoint extends GenericOpportunity
{
/*!
* RESPONSÁVEL POR CARREGAR AS DIRETRIZES INICIAIS DA INTEGRAÇÃO.
*/
public function __construct()
{
parent::__construct();
}
/*!
* RESPONSÁVEL POR CARREGAR O OBJETO DE CONTA E ENVIA-LO PARA A CLASSE DE CADASTRO/UPDATE DE CONTAS.
*
* $dados -> Objeto JSON enviado pelo RD Station.
*/
public function CarregaConta($dados)
{
require_once("generic/GenericAccount.php");
require_once("models/Account_model.php");
$AccountG = new GenericAccount();
$AccountBd = $AccountG->GetAccount($dados->leads[0]->last_conversion->content->email_lead);
$Account = new Account_model();
$Account->setEmpresa($dados->leads[0]->last_conversion->content->Empresa);
$Account->setEmail($dados->leads[0]->last_conversion->content->email_lead);
$Account->setCnpj($dados->leads[0]->last_conversion->content->CNPJ);
$Account->setTelefone($dados->leads[0]->last_conversion->content->Telefone);
$Account->setCidade($dados->leads[0]->last_conversion->content->Cidade);
$Account->setEstado($dados->leads[0]->last_conversion->content->Estado);
$Account->setAtribuidoA(ADMIN);
if($AccountBd == null)
{
if($dados->leads[0]->last_conversion->content->Revendedor == "Sim")
$Account->setTipo("Reseller");
else
$Account->setTipo("Customer");
$AccountG->CreateAccount($Account);
$Account = $AccountG->GetAccount($Account->getEmail());
}
else
{
$Account->setId($AccountBd->getId());
$AccountG->UpdateAccount($Account);
}
return $Account;
}
/*!
* RESPONSÁVEL POR CARREGAR OS DADOS DE CONTATO E ENVIA-LO A CLASE CADASTRO DE CONTATO DE CLIENTE/REVENDA.
*
* $dados -> Objeto JSON enviado pelo RD Station.
* $account_id -> Id da conta para associar ao contato.
*/
public function CarregaContato($dados, $account_id)
{
require_once("generic/GenericContact.php");
require_once("models/Contact_model.php");
$ContactG = new GenericContact();
$ContactBd = $ContactG->GetContact($dados->leads[0]->last_conversion->content->email_lead);
$Contact = new Contact_model();
$Contact->setNome($dados->leads[0]->last_conversion->content->Nome);
$Contact->setEmail($dados->leads[0]->last_conversion->content->email_lead);
$Contact->setContaId($account_id);
$Contact->setTelefoneComercial($dados->leads[0]->last_conversion->content->Telefone);
$Contact->setCidade($dados->leads[0]->last_conversion->content->Cidade);
$Contact->setEstado($dados->leads[0]->last_conversion->content->Estado);
$Contact->setOrigem("Buy Prime");
$Contact->setAtribuidoA(ADMIN);
if($ContactBd == null)
{
$ContactG->CreateContact($Contact);
$Contact = $ContactG->GetContact($Contact->getEmail());
}
else
{
$Contact->setId($ContactBd->getId());
$ContactG->UpdateContact($Contact);
}
}
/*!
* RESPONSÁVEL POR RECEBER E TRATAR O FLUXO (CRIAR CONTA, BUSCAR CONTA, CRIAR OPORTUNIDADE).
*/
public function Load()
{
header("Content-Type: application/json");
$dados = json_decode(stripslashes(file_get_contents("php://input")));
require_once("models/Email_model.php");
require_once("models/Opportunity_model.php");
$Account = $this->CarregaConta($dados);
$this->CarregaContato($dados, $Account->getId());
$Email = new Email_model();
$Opportunity = new Opportunity_model();
$Opportunity->setNome("");
$Opportunity->setDescricao($dados->leads[0]->last_conversion->content->Mensagem);
if($dados->leads[0]->last_conversion->content->Revendedor == "Sim")
{
$Email->setNome("");
$Email->setEmail("r");//buscar pelo getUser
$Opportunity->setAtribuidoA();
$Opportunity->setIdRevenda($Account->getId());
}
else
{
$Email->setNome("");
$Email->setEmail("");//buscar pelo getUser
$Opportunity->setAtribuidoA();
$Opportunity->setIdClienteFinal($Account->getId());
}
$Opportunity->setOrigem("");
$Opportunity->setFaseVenda("Prospeccao");
if($this->GetOpportunity($Opportunity) == null)
{
//cadastra
$this->CreateOpportunity($Opportunity);
//recupera a id da oportunidade recém cadastrada.
$op_id = $this->GetOpportunity($Opportunity)->getId();
//coloca a id no objeto de oportunidade.
$Opportunity->setId($op_id);
//envia e-mail
$this->LancaTarefa($Opportunity);
$Email->setAssunto("CRM - Nova oportunidade");
$Email->setModulo($Opportunity);
$mensagem = "Olá ".$Email->getNome().". <br /><br /> Uma nova oportunidade foi registrada no SuiteCRM.<br /><br />";
$mensagem .= "Segue o link abaixo para acessa-la.<br /><br />";
$mensagem .= $this->url."/index.php?action=ajaxui#ajaxUILoc=index.php%3Fmodule%3DOpportunities%26offset%3D1%26stamp%3D1547140384068769300%26return_module%3DOpportunities%26action%3DDetailView%26record%3D".$Email->getModulo()->getId();
$Email->setMensagem($mensagem);
include("Email.php");
$em = new Email();
$em->CriaEmail($Email);
}
}
/*
* RESPONSÁVEL POR ENVIAR OS DADOS DE ATIVIDADE PARA A CLASSE DE LANÇAMENTO DE ATIVIDADES.
*
* $Opportunity -> Oportunidade criada.
*/
private function LancaTarefa($Opportunity)
{
include("models/Task_model.php");
$Task = new Task_model();
$Task->setAssunto("Enviar e-mail de cotação");
$Task->setDescricao("Usar template proposta comercial para inserir produtos, descrição e preços.");
$Task->setPrioridade("High");
$Task->setModuloReferente("Opportunities");
$Task->setModuloId($Opportunity->getId());
$Task->setAtribuidoA($Opportunity->getAtribuidoA());
include("generic/GenericTask.php");
$TaskC = new GenericTask();
$TaskC->CreateTask($Task);
}
}
$r = new OportunidadeCotacaoSiteEntryPoint();
$r->Load();
Muito obrigado, Irei implementar.
Se precisar de alguma ajuda, estou a disposição!! Espero que consiga implementar!!