Esta biblioteca PHP contiene
También contiene varios ejemplos/clases parciales que implementan un proceso de sincronización de datos de contacto desde un sistema fuente a la base de datos de contactos/clientes potenciales de Sharpspring. Esto funciona con un caché local de clientes potenciales de Sharpspring, para minimizar las llamadas de actualización a la API REST de Sharpspring.
La clase de cliente se puede utilizar de forma independiente, aunque esta biblioteca no fue escrita para eso. Si desea encargarse de crear sus propios parámetros y decodificar el resultado usted mismo: adelante. Crear una instancia; llamar al método call(). No necesitas el resto de la biblioteca.
El objetivo de la clase Connection es ayudarle a no confundirse acerca de la comunicación con la API REST de Sharpspring. Intenta ayudar con esto de las siguientes maneras:
(La clase LocalLeadCache no se analiza aquí).
use SharpSpring RestApi Connection ;
use SharpSpring RestApi CurlClient ;
// One thing this library does not make super easy: starting. Separation of
// concerns is considered more important, so (since the actual API call was
// abstracted into CurlClient) creating a new connection takes 2 lines instead
// of 1:
$ client = new CurlClient ([ ' account_id ' => . . . , ' secret_key ' => . . . ]);
$ api = new Connection ( $ client );
// Get all leads updated after a certain time (notation in 'local' timezone,
// though there is no formal definition of what 'local' entails).
$ leads = $ api -> getLeadsDateRange ( ' 2017-01-15 10:00:00 ' );
El código arroja excepciones por cualquier cosa extraña que encuentre... excepto por una cosa: propiedades adicionales que ve en la respuesta, además de los valores de matriz esperados por el método API/Conexión específico que está llamando. Estos se ignoran de forma predeterminada; no se espera que alguna vez se encuentren. Si desea registrarlos, pase un objeto registrador compatible con PSR-3 como segundo argumento al constructor de Connection.
En los 'objetos' (matrices) de la API REST de Sharpspring, se hace referencia a los campos personalizados por su nombre de sistema, que cambia según la cuenta. Para permitir la escritura de código más general, el objeto Conexión tiene una asignación de propiedad personalizada al nombre del sistema de campo. Cuando se establece esta asignación (con su propia elección de nombres de propiedad), los nombres de propiedad personalizados de cualquier parámetro de 'objeto' en las llamadas a la API REST se traducirán automáticamente a los nombres de sistema de campo correspondientes.
Supongamos que tiene clientes potenciales para su zapatería, con un campo personalizado para el tamaño del zapato que creó a través de la interfaz de usuario de Sharpspring, cuyo nombre del sistema apareció como shoe_size_384c1e3eacbb3. Los dos ejemplos siguientes son equivalentes:
$ api -> createLead ([
' firstName ' => ' Roderik ' ,
' emailAddress ' => ' [email protected] ' ,
' shoe_size_384c1e3eacbb3 ' => 12 ,
]);
$ api -> setCustomProperties ( ' lead ' , [ ' shoeSize ' => ' shoe_size_384c1e3eacbb3 ' ]);
$ api -> createLead ([
' firstName ' => ' Roderik ' ,
' emailAddress ' => ' [email protected] ' ,
' shoeSize ' => 12 ,
]);
// Note that system names will still be OK; after setCustomProperties is called,
// you can still send in [...,'shoe_size_384c1e3eacbb3' => 12, ...]. Just don't
// set values for _both_ the field name _and_ its property alias, because then
// the library does not guarantee which of the two will be used.
La conversión automática solo se realiza para 'objetos' en los parámetros de llamada API. Los resultados devueltos por las llamadas a la API no se modifican. Si desea que los nombres del sistema de campos personalizados en los resultados de la API se vuelvan a convertir a los nombres de sus propiedades personalizadas, deberá hacer esto explícitamente:
$ api -> setCustomProperties ( ' lead ' , [ ' shoeSize ' => ' shoe_size_384c1e3eacbb3 ' ]);
$ leads = $ api -> getLeads ([ ' emailAddress ' => ' [email protected] ' ]);
$ lead = reset ( $ leads );
$ my_lead = $ api -> convertSystemNames ( ' lead ' , $ lead );
Usar matrices para la representación de 'objetos' de API está bien. Pero es posible que prefiera utilizar objetos/clases para ellos. (Le brinda autocompletado IDE, lo que también minimiza la posibilidad de que los nombres de propiedades estén mal escritos en mayúsculas y que la API REST no maneja).
La clase base es ValueObject y en este momento hay una clase Lead que implementa todos los campos conocidos (con comentarios sobre dónde está desactualizada la documentación API de Sharpspring).
El siguiente ejemplo es igual al anterior:
/**
* If you have custom fields, you will want to define your own subclass:
*/
class ShoeStoreLead extends Lead
{
// Define your own properties:
public $ shoeSize ;
}
$ api -> setCustomProperties ( ' lead ' , [ ' shoeSize ' => ' shoe_size_384c1e3eacbb3 ' ]);
// This is the create call from above. Note createLead() accepts ValueObjects as
// well as arrays.
$ lead = new ShoeStoreLead ();
$ lead -> firstName = ' Roderik ' ;
$ lead -> emailAddress = [email protected]';
$ lead -> shoeSize = 12 ;
$ api -> createLead ( $ lead );
// And this is the 'get' call which puts the result into a new object:
$ leads = $ api -> getLeads ([ ' emailAddress ' => ' [email protected] ' ]);
$ lead = reset ( $ leads );
$ my_lead = $ api -> convertSystemNames ( ' lead ' , $ lead );
$ my_lead_obj = new ShoeStoreLead ( $ my_lead );
Obviamente, si no tiene ningún campo personalizado, este ejemplo se vuelve mucho más simple (porque no necesita crear una subclase de Lead ni usar setCustomProperties() / convertSystemNames()).
En el ejemplo anterior, ValueObject no sabe nada sobre la asignación de sus propiedades a los nombres del sistema de campos; el objeto Connection maneja esto para las operaciones de creación/actualización, y después de las operaciones 'obtener', debe volver a convertirlas explícitamente en nombres de propiedades personalizados antes de construir el objeto.
También hay otra forma: puede configurar la asignación en ValueObject en lugar de en Connection.
$ mapping = [ ' shoeSize ' => ' shoe_size_384c1e3eacbb3 ' ];
// $api->setCustomProperties('lead', $mapping) is not called here.
// For create:
$ lead = new ShoeStoreLead ([], $ mapping );
$ lead -> firstName = ' Roderik ' ;
$ lead -> emailAddress = [email protected]';
$ lead -> shoeSize = 12 ;
$ api -> createLead ( $ lead );
// Note you could also add all the properties in the first argument of the
// constructor, instead of setting them individually - although that more or
// less defeats the purpose of using a ValueObject in the first place. Setting
// 'shoeSize' works just as well as 'shoe_size_384c1e3eacbb3', in that first
// argument. Just don't set values for _both_ the field name _and_ its property
// alias, because then the library does not guarantee which of the two will be
// used.
// For 'get':
$ leads = $ api -> getLeads ([ ' emailAddress ' => ' [email protected] ' ]);
$ lead = reset ( $ leads );
$ my_lead_obj = new ShoeStoreLead ( $ my_lead , $ mapping );
Entonces: para ValueObjects que tienen campos personalizados, existe la opción de configurar un mapeo de la conexión o configurarlo en ValueObject. Este último tiene la ventaja de que los datos recuperados de la API REST se convierten automáticamente en el constructor, pero la desventaja de que es necesario establecer el mapeo cada vez que se construye un objeto.
Hay otra forma: codificar el mapeo dentro del objeto, como:
// Override the parent's (empty) property mapping variable:
protected $_customProperties = ['shoeSize' => 'shoe_size_384c1e3eacbb3'];
...o hacer que el constructor de su subclase ValueObject personalizado lo configure (o lo derive de algún lugar). Probablemente será un código específico para su propia situación.
Elija su propio enfoque preferido.
Esta biblioteca ha documentado o parcialmente mitigado/ocultado el comportamiento más extraño de la API REST de Sharpspring. Sin embargo, si va a realizar un trabajo serio basado en la API, hay un par de cosas que al menos debe tener en cuenta y decidir si necesita tenerlas en cuenta.
Los valores con caracteres no estándar (aproximadamente: caracteres que serían codificados por htmlspecialchars()) se almacenan en Sharpspring de manera diferente dependiendo de si se insertan a través de la API REST o se ingresan a través de la interfaz de usuario. (Y para la interfaz de usuario, las cosas también difieren entre los campos estándar y personalizados). El '<' es aún más extraño: a veces se almacena con doble codificación. Los detalles sangrientos están en encoding.md. La única forma en que esta biblioteca ha podido mitigar ese comportamiento es que CurlClient siempre decodifique en HTML cualquier campo, sea necesario o no. Debido a que la decodificación HTML se realiza de forma transparente, es probable que no vea este comportamiento, pero una aplicación seria aún debería considerar si esto es un problema.
La llamada updateLead puede cambiar las direcciones de correo electrónico de un cliente potencial existente enviando (al menos) el valor de 'id' existente junto con la dirección de correo electrónico modificada. Sin embargo, si el correo electrónico modificado ya se utiliza en otro cliente potencial existente, la API descartará silenciosamente la actualización pero aún así informará que se realizó correctamente . Este es un problema potencial si está reflejando en Sharpspring una base de datos de contactos existente donde las direcciones de correo electrónico no son necesariamente únicas. Deberá volver a verificar sus actualizaciones para ver si tuvieron éxito. (Un ejemplo de dicho código se encuentra en SharpspringSyncJob::finish().)
(Agradecería cualquier informe sobre la corrección de estos errores. Es posible que así sea; consulte "advertencia").
Aparentemente, Sharpspring a veces cambia el comportamiento de su API sin anuncio ni documentación/registro de cambios (ninguno de los cuales hace, que yo sepa), e incluso sin aumentar la versión de API mencionada en la documentación de API en línea que se puede encontrar detrás de un inicio de sesión en el sitio de su cliente.
Al parecer, la conclusión de esto es que, como desarrollador de aplicaciones, debe probar constantemente su aplicación porque no puede confiar en que Sharpspring no romperá su "contrato implícito" con usted. Porque aparentemente Sharpspring no siente que tenga un "contrato implícito" con los desarrolladores de aplicaciones.
(Tuve algunos sentimientos sospechosos sobre esto mientras desarrollaba esta biblioteca en el transcurso de medio año, pero en lo que me baso es en su cambio en el comportamiento de la llamada getLeadsDateRange (con el parámetro 'marca de tiempo' establecido en "update") - que cambió tanto el formato de las fechas en los parámetros y la salida, como el contenido de la salida. Consulte el código fuente. Esto tuvo un efecto inmediato (se informaron errores) en los sistemas de producción que usaban la clase SharpspringSyncJob, que tenía. ser Parcheado de emergencia. La versión de API publicada sigue siendo 1.117 y lo ha sido desde al menos noviembre de 2016.
El cambio de comportamiento puede haber sido causado por inconsistencias que informé (tuve un breve intercambio de correos electrónicos, que terminó enviándole una lista de problemas encontrados con su API), y me alegro de que estén solucionando inconsistencias, pero la falta de respuesta, registro de cambios o cambio de versión de API aún conduce a la conclusión anterior. Por supuesto, espero que esto cambie en el futuro y que esta advertencia se elimine, pero realmente parece pertinente ahora).
¡Ay mira! https://help.sharpspring.com/hc/en-us/articles/115001069228-Open-API-Overview ahora menciona que tienen una API 'v1' y una API 'v1.2'. El segundo aparentemente acepta la entrada de fecha como UTC (que es lo que hizo su API v1 hasta aproximadamente el 26 de julio de 2017). No se menciona el formato de las fechas de salida (que también se cambiaron en la versión 1), por lo que sería necesario probarlo. Actualmente, esta biblioteca solo incluye API v1 y debería ampliarse. No está en mi lista corta, por lo que las relaciones públicas (o una tarea remunerada;)) son bienvenidas.
Este código ha sido probado con Leads y ListMembers. Hay más llamadas a la API, pero no todas se han probado exhaustivamente y faltan algunas. Es de esperar que agregar nuevas llamadas no suponga mucho trabajo; Las solicitudes de extracción son bienvenidas.
Simplemente envíe un PR o contácteme.
El 'proceso de compilación' (ver ícono en la parte superior; aparecerá un mensaje similar de aprobado/fallido en los PR) solo verifica los estándares de codificación con PHP5.6/PSR2. Todavía no hay pruebas unitarias, ya que es solo una fina capa de código que envuelve Sharpspring. Dime si crees que deberían hacerse pruebas y cuáles/por qué. (Obviamente, sería bueno tener un conjunto completo de pruebas con la API de Sharpspring activa , pero supongo que es un tema diferente y/o al menos requiere una mayor coordinación con ellos...)
Me gusta contribuir con software de código abierto al mundo y me gusta abrir sistemas semicerrados y poco documentados. Avísame si esto es útil o si tienes una contribución. Contáctame si necesitas realizar un trabajo de integración. (Tengo experiencia con varios otros sistemas).
Esta biblioteca tiene la licencia MIT; consulte el archivo LICENSE.md para obtener más detalles.