la-souris / document-signer-validsign
ValidSign implementation of the document signer SDK.
Package info
github.com/la-souris/package-document-signer-validsign
pkg:composer/la-souris/document-signer-validsign
Requires
- php: ^8.3
- guzzlehttp/guzzle: ^7.8 || ^8.0
- la-souris/document-signer-sdk: ^1.0
Requires (Dev)
- phpunit/phpunit: ^11.0 || ^13.0
This package is not auto-updated.
Last update: 2026-07-22 23:08:26 UTC
README
ValidSign implementation of the
SignatureProvider contract from
la-souris/document-signer-sdk.
Install
composer require la-souris/document-signer-validsign
Quick start
use LaSouris\DocumentSigner\Sdk\Document\Document; use LaSouris\DocumentSigner\Sdk\Envelope\Envelope; use LaSouris\DocumentSigner\Sdk\Signer\Signer; use LaSouris\DocumentSigner\ValidSign\ValidSignConfig; use LaSouris\DocumentSigner\ValidSign\ValidSignProvider; $provider = new ValidSignProvider(new ValidSignConfig( apiKey: getenv('VALIDSIGN_API_KEY'), baseUrl: 'https://my.validsign.nl/api', )); $receipt = $provider->send(new Envelope( name: 'NDA', documents: [new Document( id: 'nda', name: 'NDA', html: '<p>{[signature:counterparty:sig]} on {[date:counterparty:signdate]}</p>', )], signers: [new Signer(key: 'counterparty', name: 'Jane Doe', email: 'jane@example.com')], emailSubject: 'Please sign the NDA', )); echo $receipt->provider; // "validsign" (ValidSignProvider::NAME) echo $receipt->providerEnvelopeId; // ValidSign packageId
What it does
For every document in the envelope, this package:
- Parses
{[type:signer:name]}placeholders out of the HTML. - Substitutes each one with a hidden ValidSign text-tag
— e.g.
{{esl_sig:Signer1:Signature:size(200,50)}}. The SDK translates the arbitrary signer key from the envelope (counterparty,customer, …) into ValidSign's positionalSigner1,Signer2, … tokens. - Renders the HTML to PDF via the SDK's
PdfRenderer(Browsershot by default). - POSTs the PDFs + a
packageJSON toPOST /packageswithdocuments[].extract = true. ValidSign discovers the text-tags in the PDF server-side and places the matching fields on the corresponding signer — no per-field configuration in the API payload. - Returns an
EnvelopeReceiptcontaining the ValidSign package id and a normalisedEnvelopeStatus.
Downloads
downloadSigned(), downloadSignedDocument(), and downloadAudit() all
write to a temp file and hand you an \SplFileInfo — check the extension:
$archive = $provider->downloadSigned($packageId); // $archive->getExtension() === 'zip' // A ZIP with one signed PDF per document in the package (endpoint: /packages/{id}/documents/zip) $pdf = $provider->downloadSignedDocument($packageId, 'nda'); // $pdf->getExtension() === 'pdf' // The signed PDF for a single document (endpoint: /packages/{id}/documents/{documentId}) // $documentId is the same id you set on Document::$id when calling send(). $audit = $provider->downloadAudit($packageId); // $audit->getExtension() === 'pdf' // The Evidence Summary Report (endpoint: /packages/{id}/evidence/summary)
Callers own the file lifecycle — copy or @unlink() when done.
Webhook events
ValidSign\Webhook\EventType is a string-backed enum covering every
callback event ValidSign can emit — PACKAGE_COMPLETE, PACKAGE_DECLINE,
SIGNER_COMPLETE, KBA_FAILURE, and so on. Values match ValidSign's
vocabulary verbatim.
use LaSouris\DocumentSigner\ValidSign\Webhook\EventType; use LaSouris\DocumentSigner\Laravel\Events\DocumentSignerWebhookReceived; public function handle(DocumentSignerWebhookReceived $event): void { if ($event->provider::NAME !== 'validsign') { return; } $type = EventType::tryFromPayload($event->payload); match ($type) { EventType::PackageComplete => $this->onCompleted($event->payload), EventType::PackageDecline => $this->onDeclined($event->payload), EventType::KbaFailure => $this->onKbaFailure($event->payload), EventType::Unknown => Log::info('unknown ValidSign event', ['payload' => $event->payload]), default => null, // don't care about this event }; }
tryFromPayload() scans the payload for the first recognised event key
(name, event, type, eventName, eventType) — ValidSign has been
observed to key it under different names across tenants — and resolves
anything it doesn't recognise to EventType::Unknown (it never returns
null).
The enum implements the SDK's
WebhookEvent
interface, so listeners can also dispatch on the semantic category
(isCompleted(), isDeclined(), isFailure(), isProgress()) without
matching on individual cases — useful when the same handler needs to serve
multiple providers.
Field mapping
Each SDK FieldType becomes a ValidSign text-tag with a default size. The
optional * prefix marks a field as required — signatures and initials are
implicitly required per ValidSign, so no prefix is applied for them.
SDK FieldType |
Emitted text-tag |
|---|---|
Signature |
{{esl_<name>:SignerN:Signature:size(200,50)}} |
Initials |
{{esl_<name>:SignerN:initials:size(100,30)}} |
Text |
{{*esl_<name>:SignerN:TextField:size(200,20)}} |
Date |
{{esl_<name>:SignerN:SigningDate:size(120,20)}} |
Checkbox |
{{*esl_<name>:SignerN:Checkbox:size(20,20)}} |
<name> is your placeholder's field name; SignerN is the signer's positional
index in Envelope::$signers (1-based).
Requirements
- PHP 8.3
la-souris/document-signer-sdk- A ValidSign tenant + API key
- Node.js + Puppeteer (for the default Browsershot renderer)
Documentation
The full provider guide — credentials, endpoint mapping, status mapping, sequential signing, injecting a custom HTTP client, troubleshooting — lives in the SDK's docs: