Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Document Signer Docusign Laravel Package

la-souris/document-signer-docusign

DocuSign driver for la-souris/document-signer that lets Laravel and PHP apps send documents for eSignature, track envelope signing status, and retrieve completed, signed files through one consistent, framework-agnostic signing API.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is the DocuSign driver for la-souris/document-signer-sdk. You do not call DocuSign directly — you call the SDK's SignatureProvider contract, bind DocuSignProvider in the container, and swap it for the ValidSign (or another) implementation without touching call sites.

Minimum steps:

  1. Check your platform first. PHP 8.3+ and la-souris/document-signer-sdk ^1.0 are hard requirements. If you're on PHP 8.2, or Laravel 10 on an older CI image, bump those before anything else — this is the single most likely reason an install fails on day one.
  2. Install the package alongside the SDK (composer require <vendor>/<docusign-package> — confirm the exact name in the README).
  3. Publish/define config and populate the four things DocuSign JWT needs: integration key (client id), impersonation user GUID, account/API base URI, and the RSA private key. The private key is multi-line PEM — put it in an env var with escaped newlines or a path on disk, never in a committed config file.
  4. Grant consent once. JWT impersonation requires the user to authorise the integration key one time. Do this against the demo environment, not production.
  5. First use case: send one envelope from an existing Document in the DocuSign demo account, receive the Connect webhook, then call downloadSignedDocument($document->id) and confirm you get the signed PDF back rather than the Summary.pdf certificate.

Where to look first, in order: DocuSignConfig (everything tunable lives here), then DocuSignProvider (contract implementation — the surface you'll actually call), then DocuSignPlaceholderReplacer (the part most likely to need tuning), then DocuSignJwtAuth only if you hit auth errors.

Implementation Patterns

Bind the provider, don't instantiate it. Register DocuSignProvider against the SDK's SignatureProvider interface in a service provider, driven by DocuSignConfig built from config/services.php. This is what makes the package swappable per environment (demo vs. prod account) and lets you fake it in tests.

Anchor-based templating is the core workflow. Placeholders in your source PDF/DOCX are replaced by DocuSign tabs. The package drops each tab's top edge onto the anchor line via anchorYOffset and sends an explicit size for every field type — deliberately matching ValidSign's rendering. That means documents you already templated for ValidSign should land in roughly the same place, which is the main migration story here.

Tune globally before touching code. DocuSignConfig::$anchorYOffsetPixels (positive = down) shifts every tab on every page. When a whole document set drifts uniformly, adjust this value rather than editing each anchor; per-field offsets stay for genuinely per-field corrections. Keep it at 0 until you've compared a rendered envelope against the original.

Download by your own id, not DocuSign's. downloadSignedDocument() takes Document::$id. The mapping to DocuSign's positional ids is persisted in an envelope-level sdkDocumentMap custom field, with a normalised document-name match as fallback. Pass your domain id and let the package resolve it.

Treat SignedDocumentUnavailableException as a retry signal, not a failure. Thrown when the envelope isn't finalised yet. In a queued job, release() with a backoff (30–120s) and a bounded attempt count — never an unbounded retry(). Webhooks are usually faster than polling anyway, so prefer downloading from the webhook handler and keep the exception path for reconciliation jobs.

Webhook flow. Point a DocuSign Connect subscription at a POST route, map the payload through the package's EventType mapping, and download on the "completed" event. Keep the handler idempotent — Connect retries on non-2xx and duplicates are normal — and store the envelope id as the dedupe key.

Audit trail: two outputs, pick deliberately. downloadAudit() gives DocuSign's Certificate of Completion as .pdf — that's the artefact to attach to a case file or email to a counterparty. DocuSignClient::downloadAuditEventsJson() gives the raw audit_events feed, which is what you want if you're loading timestamps and signer actions into your own tables. Many teams end up storing both: PDF for humans, JSON for querying.

Gotchas and Tips

  • JWT consent is per integration key per user, and it expires if unused for a long period. If you suddenly get auth failures on an integration that worked last quarter, re-grant consent in the DocuSign admin UI before debugging your code. Also cache the access token (~1 hour lifetime) rather than authenticating on every request — repeated JWT auth calls are the usual cause of rate limiting.
  • anchorYOffsetPixels vs. DocuSign's own units. DocuSign documents anchor offsets in points, not pixels. Confirm from the source whether DocuSignPlaceholderReplacer converts before you start dialling in fractions of a pixel — otherwise your fine-tune will be off by a constant factor.
  • Duplicate anchors resolve to the first match only. If a placeholder string appears twice on a page, DocuSign places one tab and silently ignores the rest. Generate unique anchors (e.g. sig_1, sig_2) rather than reusing a generic label.
  • The Summary.pdf skip is name-based. If one of your documents happens to be named Summary.pdf, it will be dropped from downloadSignedDocument() without warning. Namespace your filenames.
  • Name-match fallback is a fallback. It only fires when the sdkDocumentMap custom field is missing or unreadable. If you see it firing repeatedly, envelopes are being created outside the package (manual sends, other tooling) or the custom field is being stripped by a DocuSign template/field setting — fix the root cause rather than relying on the fallback, and make sure the normalised name comparison won't collide on documents like Contract.pdf.
  • The sdkDocumentMap value ships inside the envelope. It's visible to anyone with envelope access. Keep it to id → positional-index mappings and nothing sensitive, and watch DocuSign's custom-field value length limits on envelopes with many documents.
  • Webhook security is on you unless the README says otherwise. The event mapping does not imply signature verification. Check whether the package validates the DocuSign Connect HMAC signature; if not, add it at the route level, and always exclude the endpoint from CSRF and auth middleware.
  • Extension points to keep in mind: DocuSignClient is the seam if you need a raw DocuSign call the SDK doesn't model (it's already exposed for downloadAuditEventsJson()); DocuSignConfig is the seam for environment-specific behaviour; and the SignatureProvider binding is the seam for local testing — implement a trivial fake rather than mocking DocuSignClient internals.
  • Debugging order for "wrong position" bugs: confirm the anchor string is unique and present in the sent document, then check anchorYOffsetPixels, then per-field anchorYOffset, then whether the tab has an explicit size being overridden by a template. Render the same document through the ValidSign provider and diff visually — the package is explicitly aiming for parity, so any gap is a bug worth reporting.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource