Installation:
composer require cyllene-web/docusign-bundle
Register the bundle in config/bundles.php:
return [
// ...
CylleneWeb\DocuSignBundle\DocuSignBundle::class => ['all' => true],
];
Configuration:
Add DocuSign credentials to config/packages/cyllene_web_docusign.yaml:
cyllene_web_docusign:
client_id: '%env(DOCUSIGN_CLIENT_ID)%'
client_secret: '%env(DOCUSIGN_CLIENT_SECRET)%'
redirect_uri: '%env(DOCUSIGN_REDIRECT_URI)%'
account_id: '%env(DOCUSIGN_ACCOUNT_ID)%'
First Use Case:
Create a DocuSignService instance and send an envelope:
use CylleneWeb\DocuSignBundle\Service\DocuSignService;
$docuSign = $container->get(DocuSignService::class);
$envelope = $docuSign->createEnvelope($documentPath, $signerEmail, $recipientName);
config/packages/cyllene_web_docusign.yaml (default config)src/Service/DocuSignService.php (core service)src/Entity/Envelope.php (envelope definition)Prepare Document:
Upload the document to a FlySystem-compatible storage (e.g., S3 via flysystem-bundle).
$fileAdapter = $container->get('oneup_flysystem.document_storage.service_file_adapter');
$fileAdapter->write('contract.pdf', file_get_contents('local_contract.pdf'));
Create Envelope: Define recipients, tabs (signatures), and routing order:
$envelope = new Envelope();
$envelope->setDocument('contract.pdf');
$envelope->addRecipient(
new Signer('signer@example.com', 'John Doe'),
['tabs' => ['signHereTabs' => [['documentId' => 1, 'pageNumber' => 1, 'recipientId' => '1']]]]
);
Send Envelope: Use the service to trigger DocuSign:
$docuSign->sendEnvelope($envelope);
Handle Callback:
Configure a route to handle DocuSign’s complete or declined callbacks:
// src/Controller/DocuSignCallbackController.php
public function callback(Request $request, DocuSignService $docuSign): Response
{
$docuSign->handleCallback($request);
return new Response('Callback processed');
}
FlySystem Integration:
Use oneup_flysystem-bundle to store documents. Configure the bundle to point to your storage:
# config/packages/oneup_flysystem.yaml
oneup_flysystem:
adapters:
document_storage:
aws_s3:
service: 'aws_s3'
bucket: 'your-bucket'
region: 'us-east-1'
Event Listeners:
Subscribe to DocuSign events (e.g., EnvelopeSent, EnvelopeCompleted) via Symfony’s event dispatcher:
// src/EventListener/DocuSignListener.php
public static function getSubscribedEvents()
{
return [
DocuSignEvents::ENVELOPE_SENT => 'onEnvelopeSent',
DocuSignEvents::ENVELOPE_COMPLETED => 'onEnvelopeCompleted',
];
}
Testing:
Use the DocuSignService with a mock client for unit tests:
$mockClient = $this->createMock(DocuSignClient::class);
$docuSign = new DocuSignService($mockClient, $config);
OAuth Flow:
redirect_uri matches DocuSign’s registered callback URL.Invalid redirect URI → Verify DOCUSIGN_REDIRECT_URI in .env and DocuSign’s admin console.File Size Limits:
File too large → Compress the document or split it into multiple files.Recipient ID Mismatch:
tabs must match the recipientId in the addRecipient call.Recipient not found → Double-check recipientId values (e.g., '1' for the first signer).FlySystem Misconfiguration:
flysystem-bundle, ensure the adapter is properly configured. The bundle expects files to be accessible via FlySystem.File not found → Verify the adapter name in DocuSignService matches your FlySystem config.Enable Debug Mode:
Set debug: true in the config to log OAuth tokens and API responses:
cyllene_web_docusign:
debug: true
Logs appear in var/log/dev.log.
Token Expiry: Tokens expire after 1 hour. The bundle auto-refreshes tokens, but long-running processes may fail.
Custom Tabs:
Extend Tab classes (e.g., SignHereTab, InitialHereTab) to add custom logic:
class CustomSignHereTab extends SignHereTab
{
public function __construct(string $documentId, int $pageNumber, string $recipientId, string $customField)
{
parent::__construct($documentId, $pageNumber, $recipientId);
$this->customField = $customField;
}
}
Webhook Handling: Override the default callback handler to integrate with your workflow:
// src/Service/CustomDocuSignService.php
class CustomDocuSignService extends DocuSignService
{
public function handleCallback(Request $request): void
{
$data = json_decode($request->getContent(), true);
if (isset($data['event']) && $data['event'] === 'envelope_completed') {
$this->dispatchEvent('custom.envelope.completed', $data);
}
parent::handleCallback($request);
}
}
Document Preprocessing:
Use Symfony’s kernel.request event to preprocess documents (e.g., add headers/footers) before sending:
// src/EventListener/DocumentPreprocessor.php
public function onKernelRequest(GetResponseEvent $event)
{
if ($event->isMasterRequest() && $event->getRequest()->attributes->has('docusign_document')) {
$document = $event->getRequest()->attributes->get('docusign_document');
$processed = $this->addWatermark($document);
$event->getRequest()->attributes->set('docusign_document', $processed);
}
}
Account ID:
The account_id in config must match the user account ID, not the integration key. Find it in DocuSign’s Admin Settings.
Account not found → Verify account_id is correct (e.g., 12345678-9abc-def0-1234-567890abcdef).Environment Variables: The bundle expects these variables by default:
DOCUSIGN_CLIENT_ID=your_client_id
DOCUSIGN_CLIENT_SECRET=your_secret
DOCUSIGN_REDIRECT_URI=https://your-app.com/docusign/callback
DOCUSIGN_ACCOUNT_ID=your_account_id
Override in .env or config.
How can I help you explore Laravel packages today?