Download the PHP package smith-carson/prosperworks-sdk without Composer

On this page you can find all versions of the php package smith-carson/prosperworks-sdk. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package prosperworks-sdk


layout: default

Introduction

At the time of implementation, there was no SDK for ProsperWorks, and we needed to do a bunch of operations to transfer data from our old CRM and synchronize information with the other subsystems, so we designed some classes to encapsulate the API operations. It uses Guzzle, but ended up overgrowing and we turned into a standalone library.

This project was originally written by igorsantos07 and is now maintained by smith-carson (website).

Installation

1. Install in your project

You need to be running PHP 7 (yep, it's stable since dec/2015 and packs a bunch of useful features, upgrade now!).

To add it to your project through Composer, run composer require igorsantos07/prosperworks. It will get the most stable version if your min-requirements are "stable" or dev-master otherwise.

2. Configure the package

There's a couple of things to configure to get the SDK running:

API credentials

Currently, there's no "API User" on ProsperWorks, so you need an active user to communicate with the API.

  1. Sign in to ProsperWorks, go to Settings > Preferences / API Keys. There you will be able to generate a new API Key for the logged user. Copy that key, along with the user email.

  2. Create a bootstrap file, or include the following code in the config section of your project: \ProsperWorks\Config::set($email, $token).

Webhooks parameters

[Optional] If you're going to use Webhooks to get updates from ProsperWorks, you'll also need to feed in three more arguments on that method:

  1. A Webhooks Secret, that will be used to avoid unintended calls to your routes. That should be a plain string.
  2. A Root URL. That's probably the same domain/path you use for your systems, and what ProsperWorks will POST to. More information on the Webhooks section.
  3. A Cryptography object. It should respond to encryptBase64() and decryptBase64(), both receiving and returning a string (it can also implement \ProsperWorks\Interfaces\Crypt to make things easier). It will be used to send an encrypted secret, and decrypt it to make sure the call you receive comes from ProsperWorks (or, at least, someone that has the encrypted secret).

Caching object

[Optional] To make some parts faster, you can also feed the sixth argument with a caching layer. It's an object that needs to respond to get() and save(), or implement \ProsperWorks\Interfaces\Cache.

It's mainly used to cache (for an hour) meta-data from the API, such as Custom Fields, Activity and Contact Types, and so on. That's information that rarely changes so it's safe to cache, making calls much faster (otherwise, for every resource with custom fields we would need to retrieve from the custom fields endpoint as well).

3. Debug mode

During import scripts and similar tasks it could be useful to peek into the network traffic and see if what you intended to do is being done correctly. You can enable echo's of debug information from the library by calling ProsperWorks\Config::debugLevel():

ProsperWorks\Config::DEBUG_BASIC
will trigger some messages, such as "POST /people/search" so you know which requests are being sent. It also warns on Rate limits being hit.
ProsperWorks\Config::DEBUG_COMPLETE
does all above plus complete requests payload.
null, false, 0 or ProsperWorks\Config::DEBUG_NONE
will stop printing messages.

This doesn't need to be done together with Config::set(); it can happen anywhere and will change behavior from that part on.

Tip: "sandbox" account

After a while, when implementing this library for the first time, we spoke with a support representative about the lack of a sandbox environment. They suggested us to create a trial account and use that instead of a user on the paying account, and mention to the Support that was being used to test-drive the API implementation - and thus, they would extend the trial of that solo account for as long as it was needed.

API Communication

Most of the operations are done through the \ProsperWorks\CRM abstract class, and the resulting objects from it (you can consider it some sort of Factory class). The exception are Webhooks, that have a special Endpoint class to make it easier.

Tip: ProsperWorks API Documentation
You may want to read the REST API Docs, to get an understanding of the inner pieces that make up this SDK.

With configurations in place, ProsperWorks API calls are done through a simple, fluent API. Most of the endpoints behave the same way, with special cases being the Account and most meta-data endpoints.

On the following examples we'll consider the classes were imported in the current namespace.

Common endpoints

Singular, empty static calls to CRM give an Endpoint object (see saving instances), that allows you to run all common operations:

All success calls will return a BareResource object, with all information from that endpoint, or a list of those. See Response Objects for details.
If it fails, an error message is given. (TODO: option to raise exceptions)

There are also some shortcuts, such as:

Special cases: restricted endpoints

All meta-data resources (called Secondary Resources on the docs), together with the Account endpoint, have only read access. There's no verification of valid operations yet (see #7). Here's a list of those read-only endpoints, accessible through the plural call (e.g. CRM::activityTypes()), except for Account which is singular:

Meta-data shortcuts

As those endpoints are mostly lists, you can also access that data through the cacheable CRM::fieldList() method, which returns the information in a more organized fashion:

Sanity warning: those IDs there are samples; they're different for each ProsperWorks customer.

It's also worth noting that some fields are "translated" from the API into specific objects, such as timestamps, addresses, Custom Fields and more, so you'll probably never have to deal with the Custom Fields endpoint directly. More information about that on the Response Objects sections.

Related Items

There's an unified API to created links between two resources. Thus, every Resource object has its own related method, to manipulate those links. As that's a very simple API, you can only list, create and delete relationships. Take a look on the Documentation for Related Items to see the relation limits - some resources allow for only one link, and not every resource has relationships with every other.

Batch Operations

It's also possible to run batch operations, using Guzzle's concurrency features to speed up with parallel calls. Some single-usage methods have a *Many counterpart, such as:

createMany()
straightforward; instead of a payload, you pass a list of payloads
editMany()
in this case, you got to pass a list of payloads, indexed by IDs.
delete()
is special, as it can handle an arbitrary number of IDs. Its response will vary on the number of arguments.

You can use an array, Interator or Generator on these, and it will take care to run as much as 10 (future: configurable) HTTP calls at the same time.

As an example, let's create a lot of Task entries, based on a query result (that also has low memory usage), and then remove these:

A generator is specially useful in these cases as it will save you a lot of memory, by not storing a long list of payloads/requests in-memory.

Batch Relationship operations

Similar to batch API calls, it's also possible to run a bunch of relation changes. To do that, use relatedBatch()'s methods, with a list of ID + Type (or the Relation helper object), indexed by origin ID:

I don't think all those static calls are performant

Indeed, on a very small scale, they might not be. You can always use the half-way object to run common operations, as when you're running a bunch of operations on the same endpoint. However, the static calls will save you from a couple of config/instances on one-off calls ;)

Rate limiting

There's also a RateLimit blocker built-in to the SDK, so it will sleep() a bit when it notices a limit would be hit, allowing for new operations shortly after the limit is released. That emits some notices on the CLI when Batch operations.

Response objects

Most (all?) responses will be a BareResource object, or a list of those. The biggest advantage is that class's "translation" capabilities: it makes some parts of the payload easier to use by leveraging Objects with simpler / predictable structures, or with some data validation / translation under the hood (AKA SubResources).

SubResources

There are a couple of dependant objects that are not to be used directly on API calls, but make part of the main resources. Most of the times, those are inner documents inside the JSON payload. They're used on responses (see Response Objects), but they're also designed to make your calls easier, "translating" some information back and forth, and making sure you always follow the requested rules for those sub-documents.

In special, a SubResource implementing the TranslateResource trait will allow read-access to some protected fields (listed in $altFields). In short, when you turn an object into an array on PHP (what we do to get the final JSON payload) it creates an array of all public fields. Thus, a TranslateResource is able to give read access to some "hidden" properties while not exposing that to the API. See the list below for behavior examples:

Address

Accepts as the first argument either a complete line (a string called street, because that's how ProsperWorks does), or an array with two address lines (called address and suite). To change between those two formats a there's a "suite" separator (hint: if there's a "suite" on the suite part already, it won't be repeated ok?). The other arguments are pretty standard, such as city, postal code and so on.

Relation

This was shown before: it's a simple holder for id and type, no extra features.

Custom Field

This is the biggest guy. It does the translation between a bare custom field specification (id + value, not really meaningful for humans) and actually readable information. The original field ID (same ID for the same field, even across different types of resources) is stored in custom_field_definition_id, together with the value. There's always a read-only name property, with the field's actual name, and if it's a list, a read-only string valueName will also be filled with the field's readable value.

To create a Custom Field entry, you can use both the field ID or field name as the first argument, and either the value ID or string on the second place. Remember to double-check casing when you use a string instead of the IDs, though!

The following example displays both how to use the class and how it's returned in the SDK responses:

"Categorized" sub-resources

All of these classes inherit from Categorized, giving them a category property and a couple of constants to use as values. If, on a child class, a constant is marked as "deprecated", it means it doesn't really work with that object.

Their signature is the same: value as first argument, category as the second one.

Email

Simplest child: has an email property, together with the category.

Phone

The first argument is the string number. But the trick here is you can feed an extension by using something like this: "123-4444 x123", and it will get separated into two read-only fields: simpleNumber and extension.

URL

Feed a valid url as the first argument and a social URL category will be automatically filled, if any matches. For other cases, you can give the category manually as the second argument, as usual.

Webhooks

On the other hand, if you want to get updates from ProsperWorks, you have to setup your endpoints for them to call with any changes that happen.

Tip: you may want to take a look on [Webhooks guide]; it's still being worked on - that's why it's still a KB article.

Available Events

According to the documentation, there are three types of events that you can subscribe to:

Webhooks::EV_NEW
a new entry was created
Webhooks::EV_UPDATE
an entry got updated
Webhooks::EV_DELETE
an entry got deleted
Webhooks::EV_ALL
catch-all constant that will subscribe you to all events at once

And these are available for any of the main endpoints, listed under Webhooks::ENDPOINTS:

How to interact with the webhooks

There are a couple of methods on the Webhooks class, that you should use on your project's REPL or CLI tool when you configure them, or inside your Controller to manipulate the ProsperWorks calls:

To configure webhooks

You must first instantiate the Webhooks object with the root path for your application's environment, otherwise it will use what's configured as default (if any) by Config. That in-place config ability will come in handy during testing.

Then, you can use a couple of methods to interact with the ProsperWorks Webhooks API:

list(int $id = null)
Returns a list of webhook details, indexed by ID.
create(string $endpoint, $event = self::ALL)
Subscribes a new webhook for the given endpoint and event match, with the secret specified on `Config`. You should use one of the CRM::RES_* constants for the first argument.
delete(int ...$id)
Removes one or more webhooks from the ProsperWorks pool.

To interpret webhook calls

Every time a set event happens on one of the set endpoints, ProsperWorks's servers will make an HTTPS call to an address that is composed like this: <root_path>/prosperworks_hooks/<endpoint>/<event>. Your controllers should somehow be able to interpret that the way best suits your application, but most of that information is also repeated in the payload, so feel free to have a single catch-all action to work on it.

The webhook payload

The payload is plain and simple. It contains the affected/generated IDs (usually a single one, unless that's a batch operation), the affected endpoint and generated event, the webhook subscription ID, a timestamp and our secret.

Before any further operation, you should verify, for security purposes, if the secret is correct. To do that, call validateSecret() with the payload, in array format. It will search for the secret, decrypt and verify it. Returns null when the secret is not present, or false if it's there but isn't valid.

The next step, usually, would be for you to access the ProsperWorks API as usual to gather information on the created / updated resource, and update your database accordingly, or remove whatever needs to be removed.

It's worth saying that, with their current UI, every field change made by the user is automatically saved; that's good for their users, but every of those save calls will make a new webhook call, and that might overwhelm your server.
Thus, a nice idea would be to have some sort of queue system to work on those changes, and maybe even a deboncer that could reduce repeated changes on the same resources - i.e. discarding payloads with the same endpoint, event and IDs that happened in a short period of time.

How to develop with webhooks

An important fact here is that ProsperWorks demands all webhook calls to be encrypted, what means you must provide an HTTPS address for them. Besides that, your webserver must be openly accessible on the web. That might not be the most trivial settings for a development environment, right?

Well, the tip is using ngrok during development. You can run it pretty easily from the command-line and have it open a stable HTTPS tunnel, and give you it's URL; you feed that into the Webhooks object and setup new subscriptions that ProsperWorks can call when you make changes on their UI.
It's also possible to inspect the HTTP traffic using the Ngrok inspector; its URL is also displayed when you run it. That might come in handy so you don't need to edit fields a thousand of times to verify your code is working, as it's able to store and repeat calls it received. Neat, isn't it?


All versions of prosperworks-sdk with dependencies

PHP Build Version
Package Version
Requires php Version ^7.0
guzzlehttp/guzzle Version ^6.3
doctrine/inflector Version ^1.2
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package smith-carson/prosperworks-sdk contains the following files

Loading the files please wait ....