alexacrm/dynamics-webapi-toolkit
Laravel/PHP toolkit for working with Microsoft Dynamics 365 Web API. Simplifies authentication, building requests, and performing CRUD operations with entities, queries, and batch actions. Handy wrapper to integrate CRM data into your app with less boilerplate.
Installation
composer require alexacrm/dynamics-webapi-toolkit
Ensure your project meets PHP 7.4+ requirements.
Basic Configuration
Create a config file (e.g., config/dynamics.php) and define your Dynamics 365 Web API endpoint, client ID, and client secret:
return [
'auth' => [
'client_id' => env('DYNAMICS_CLIENT_ID'),
'client_secret' => env('DYNAMICS_CLIENT_SECRET'),
],
'endpoint' => env('DYNAMICS_ENDPOINT', 'https://yourorg.crm.dynamics.com'),
'version' => env('DYNAMICS_API_VERSION', '9.2'),
];
First Use Case: Authentication Initialize the client in a service or controller:
use Alexacrm\DynamicsWebapiToolkit\Client;
$client = new Client(config('dynamics'));
$accessToken = $client->authenticate();
First API Call Fetch an account record:
$account = $client->get('accounts(12345678-1234-1234-1234-123456789012)');
CRUD Operations
$newAccount = $client->create('accounts', [
'name' => 'Acme Corp',
'revenue' => 1000000
]);
$client->update('accounts(12345678-...)', ['name' => 'Updated Acme Corp']);
$client->delete('accounts(12345678-...)');
Querying Data Use OData queries for filtering, sorting, and pagination:
$accounts = $client->get('accounts?$select=name,revenue&$filter=revenue gt 1000000');
Associations Fetch related records (e.g., contacts for an account):
$accountWithContacts = $client->get('accounts(12345678-...)?$expand=contacts($select=fullname)');
Bulk Operations
Use $batch for multiple operations in a single request:
$batch = $client->batch();
$batch->create('accounts', ['name' => 'Batch Account 1']);
$batch->create('accounts', ['name' => 'Batch Account 2']);
$results = $batch->execute();
Webhooks Subscribe to entity changes (e.g., account updates):
$client->subscribe('accounts', 'https://your-app.com/webhook-endpoint', ['created', 'updated']);
Laravel Service Provider Bind the client to the container for dependency injection:
$this->app->singleton(Client::class, function ($app) {
return new Client($app['config']['dynamics']);
});
Middleware for Authentication Create middleware to handle token refresh:
public function handle($request, Closure $next) {
$client = app(Client::class);
if (!$client->isAuthenticated()) {
$client->authenticate();
}
return $next($request);
}
Eloquent Models Extend Eloquent models to interact with Dynamics 365:
class Account extends Model {
public static function fetch($id) {
$client = app(Client::class);
return $client->get("accounts({$id})");
}
}
Event Handling Listen for Dynamics 365 webhook events:
Route::post('/webhook', function (Request $request) {
$payload = $request->json()->all();
// Process payload (e.g., update local cache)
});
Token Expiry
401 Unauthorized responses by refreshing the token:
try {
$response = $client->get('accounts');
} catch (\Alexacrm\DynamicsWebapiToolkit\Exception\UnauthorizedException $e) {
$client->authenticate(); // Refresh token
$response = $client->get('accounts');
}
Entity Names
accounts, contacts), but the API may require singular names for some operations. Verify with the Dynamics 365 API documentation.Large Data Sets
$top and $skip:
$accounts = $client->get('accounts?$top=100&$skip=0');
Concurrency Conflicts
If-Match headers for optimistic concurrency control:
$client->update('accounts(12345678-...)', ['name' => 'Updated'], [
'headers' => ['If-Match' => '*']
]);
Case Sensitivity
Enable Verbose Logging Configure the client to log requests/responses:
$client = new Client(config('dynamics'), [
'logger' => new \Monolog\Logger('dynamics', [
new \Monolog\Handler\StreamHandler(storage_path('logs/dynamics.log'))
])
]);
Common HTTP Errors
Schema Exploration
Use the $metadata endpoint to explore available entities and attributes:
$metadata = $client->get('$metadata');
Custom Headers Add custom headers to requests:
$client->setDefaultHeaders(['X-Custom-Header' => 'value']);
Request Interceptors Extend the client to modify requests before they’re sent:
$client->setRequestInterceptor(function ($request) {
$request->headers->set('X-Request-ID', uniqid());
});
Response Transformers Transform responses before they’re returned:
$client->setResponseTransformer(function ($response) {
return json_decode($response->getBody(), true);
});
Custom Entities Dynamically register custom entities or attributes:
$client->registerEntity('custom_entities', [
'name' => 'Custom Entity',
'attributes' => ['custom_field' => 'String']
]);
Webhook Validation
Validate incoming webhook payloads using the validateWebhook method:
$isValid = $client->validateWebhook($payload, 'accounts', 'https://your-app.com/webhook-endpoint');
How can I help you explore Laravel packages today?