DocGen & eSign

Docgen & Signing Flow — Technical Architecture & Reference

Overview

A signer receives an email containing a signing link. Signer clicks the link, which routes through a Salesforce Site to PDFESigningScreen.page. The page decodes the link parameter and loads documentSigningScreen LWC. The LWC orchestrates the signing workflow: OTP verification (if enabled), form field population, document display in iframe (via PDFSigningScreen.page or AutoPopulatedSigningScreen.page or AutoPopulatedSigningScreenWord.page), field validation, signature capture, and final PKCS7 digital signing. On success, the LWC displays status confirmation and optionally downloads the signing certificate. The signing flow is the final user-facing layer that bridges OTP → Document Viewing → Signing → Workflow Completion.

Five Visualforce pages orchestrate signing:

Page

Purpose

Context

PDFESigningScreen.page

Entry point (Salesforce Site). Parses URL params, loads LWC.

Public-facing (unauthenticated)

documentSigningScreen (LWC)

Orchestrator. Handles OTP, status, iframe routing.

Lightning component (embedded)

PDFSigningScreen.page

PDF form signing. Nutrient Web SDK + field validation + PKCS7.

Iframe inside LWC

AutoPopulatedSigningScreen.page

Alternative PDF signing. Auto-populated form fields.

Iframe inside LWC (variant)

AutoPopulatedSigningScreenWord.page

Alternative PDF signing. Auto-populated form fields on Word Documents.

Iframe inside LWC (variant)


Architecture.

┌──────────────────────────────────────────────────┐
│   Signer clicks email link                       │
│   (Document_Workflow_Item__c.Signer_URL_New__c) │
└────────────────────┬─────────────────────────────┘
                     │
          Via Salesforce Site
                     │
                     ▼
        ┌────────────────────────┐
        │ PDFESigningScreen.page │
        │  (public VF wrapper)   │
        │                        │
        │ Parse URL params:      │
        │ ?sign=encoded_link     │
        └────────────┬───────────┘
                     │
        Load documentSigningScreen LWC
        (into #LightningComponent div)
                     │
        ┌────────────▼───────────────┐
        │ documentSigningScreen LWC  │
        │  (orchestrator)            │
        │                            │
        │ • Decode urlParam          │
        │ • Check OTP requirements   │
        │ • Query workflow state     │
        │ • Verify signer status     │
        └────────────┬───────────────┘
                     │
        ┌────────────▼───────────────┐
        │  OTP Verification?         │
        └────────┬──────────┬────────┘
                 │ (yes)    │ (no)
                 ▼          ▼
           c-document-  Load Signing
           signing-o-t-p-  Page Iframe
           screen          │
                 │          │
        User enters OTP     ▼
                 │     ┌─────────────────────┐
                 │     │ PDFSigningScreen.page│
                 │     │ OR                   │
                 │     │ AutoPopulated...page │
                 │     │                      │
                 │     │ Nutrient Web SDK     │
                 │     │ renders PDF          │
                 │     │ + form fields        │
                 │     │                      │
                 │     │ User fills/signs     │
                 │     │ invokeSignatureService│
                 │     │ → PKCS7 hash         │
                 │     │ → ContentVersion     │
                 │     │ → Status update      │
                 │     └─────────┬────────────┘
                 │               │
                 └───────┬───────┘
                         │
         documentSigningScreen receives
            signing result from iframe
                     │
        ┌────────────▼───────────────┐
        │  Show Status Screen        │
        │  • Success / Declined      │
        │  • Error / Verification    │
        │  • Certificate download    │
        │  • Redirect (if configured)│
        └────────────────────────────┘

Signing starts via a public link (unauthenticated Salesforce Site). PDFESigningScreen.page acts as a router: it parses the URL-encoded signing link parameter, then loads documentSigningScreen LWC into a Lightning container. The LWC decodes the link, queries the Document_Workflow__c and Document_Workflow_Item__c to verify signer status, check OTP requirements, and determine the signing method (PDF vs Word, auto-populated vs manual). Based on configuration, the LWC either:

  1. Shows OTP verification screen (c-document-signing-o-t-p-screen child component)

  2. Directly loads a VF page (PDFSigningScreen or AutoPopulatedSigningScreen) in an iframe

After OTP (if required), the iframe loads PDFSigningScreen.page (or variant), which calls its Apex controller to fetch field config and PDF blob. The user fills form fields and signs. The VF page calls invokeSignatureService(), which PKCS7-signs server-side, then posts the result back to the LWC via postMessage. The LWC receives the signing result and displays the final status screen (success, declined, error, etc.). This architecture allows guest link sharing (unauthenticated) + OTP gating + flexible signing methods (PDF/Word, auto-populated/manual) + certificate management.


VF Page — PDFESigningScreen.page

public with sharing (Salesforce Site accessible). Entry point for all signing links. No Apex controller. Uses Lightning Out to load LWC components.

Feature

Implementation

Container

<div id="LightningComponent" />

Lightning App

docgen_esign:DocumentGenerationAuraApplication

Components

Loads either documentSigningScreen or generateAndCreateRecord

URL Routing

Checks ?sign=encoded_link (OTP + signing flow) or ?templateId=id (record creation)

Error Handling

Shows red alert div if no query params or invalid params

Favicon

Sets Cloud Maven favicon from static resource

Query Parameter Routing:

Param

Component

Purpose

?sign=URLEncodedSigningLink

documentSigningScreen

Routes to signing workflow

?templateId=TemplateId

generateAndCreateRecord

Routes to document generation workflow

(none)

alert div

Shows error message


LWC — documentSigningScreen

Orchestrator component. Receives @api urlParam (URL-encoded signing link). Handles OTP verification, document status checking, iframe routing, and final status display.

Tracked state

Property

Purpose

@api urlParam

Injected by PDFESigningScreen. URL-encoded Document_Workflow_Item__c signing link.

showLoading

Spinner during initialization and link decoding.

showOTPScreen

Toggles OTP verification screen (child component c-document-signing-o-t-p-screen).

documentGenerated

Toggles between OTP screen and document-signing screen.

generatedDocumentURL

URL to PDFSigningScreen.page or AutoPopulatedSigningScreen.page (loaded in iframe).

alreadySigned

If Document_Workflow_Item__c status = Document Signed.

workflowExpired

If Document_Workflow__c expiry date passed.

showDeclineMessage

If signer declines document.

bOtpVerificationFailed

If OTP verification fails (max attempts exceeded).

otpMethods

Array of OTP delivery methods (SMS, Email, etc.).

otpResendTime

Countdown timer for OTP resend.

statusConfig

Status screen config (type: success/declined/error/verified, message, icon).

dWorkFlowId

Document_Workflow__c ID (parsed from urlParam).

currentSigner

Signer name (from Document_Workflow_Item__c).

isLastSigner

Boolean. If true, shows "completion email" message after signing.

bAutoDownloadCertificate

If configured, auto-downloads signing certificate on success.

consentAccepted

If signer consent modal required + accepted.

Key functions

Function

Behavior

connectedCallback()

Decodes urlParam via UtilityClass.encodeDecodeURLString(). Queries workflow + signer. Calls checkifUserAlreadySigned(), getWorkflowStatus(). Populates OTP methods if required.

initializeSigningLink()

Decodes URL parameter. Validates signing link exists and is not expired. Sets dWorkFlowId + currentSigner.

handleSigningLinkValidation()

Queries Document_Workflow_Item__c by encoded link. Checks status (if already signed, declined, etc.). Checks workflow expiry. Sets appropriate status/flags.

userVerified(event)

Fired when OTP verification succeeds (from child c-document-signing-o-t-p-screen). Sets showOTPScreen = false, documentGenerated = true. Calls loadSigningFrame().

verificationFailed(event)

Fired when OTP fails (max attempts). Sets bOtpVerificationFailed = true, shows error status screen.

loadSigningFrame()

Determines signing page type: if PDF → PDFSigningScreen.page, if Word → AutoPopulatedSigningScreenWord.page. If auto-populate enabled → AutoPopulatedSigningScreen.page. Constructs URL with workflowId. Sets generatedDocumentURL (triggers iframe load).

handleSigningResult(event)

Listens for postMessage from iframe (PDFSigningScreen.page). Receives { Success, signedHash, errorMessage, signatureTimeStamps }. If success: calls saveDocument() (if needed), then displays success status screen. If error: shows error status screen.

saveDocument()

Apex call to SigningScreenController.saveDocument(). Saves signed PDF. Called if document not auto-saved in iframe.

declineDocument()

Calls SigningScreenController.declineDocument() on workflow + signer. Updates status to declined, shows declined status screen.

downloadSigningCertificate()

Calls SigningScreenController.downloadSignerCertificate(). Auto-downloads certificate if configured.

handleAutoDownload()

Checks bAutoDownloadCertificate flag. If true and signing succeeded: auto-triggers certificate download.

recordSignerConsent()

If consent modal required: calls SigningScreenController.recordSignerConsent() to log acceptance.

showMessageScreen(event)

Displays custom message/status on signing screen.

Child Components

Component

Usage

c-document-signing-o-t-p-screen

OTP verification. Takes otpMethods, urlParam, otpResendTime, otpAttempts. Fires userVerified/verificationFailed events.

c-status-screen

Status display. Takes statusConfig (type, message, icon, buttons). Shows success/error/declined/expired.


VF Page — PDFSigningScreen.page

Controller: SigningScreenController. Hosts Nutrient Web SDK iframe for PDF signing. Loaded inside documentSigningScreen LWC iframe.

Method

Returns

What it does

getTemplateData()

String

VF page getter. Reads page params: signerURLId, workflowId (alternative: templateId, recordId). Queries workflow item + workflow + template. Calls DocumentGenerationService.getFormData(). Sets VF properties: base64String (PDF), dataMap, readOnlyFields, requiredFields, dateFields, picklistMap, fieldNameLabelMap, licensekey. Returns 'Success' or 'Error'.

invokeSignatureService(String digest, String workflowId)

String

Receives PDF blob (digest) + workflowId. Calls SigningService.signDocument(). Generates PKCS7, creates ContentVersion, updates workflow status, creates audit events. Returns { Success, signedHash, signatureTimeStamps }. Posts back to LWC via window.parent.postMessage().

Key VF Properties:

Property

Purpose

base64String

Base64-encoded PDF blob. Passed to NutrientViewer.load().

dataMap

JSON field→value map for pre-population.

readOnlyFields

Fields that cannot be edited. Set widget.readOnly = true.

requiredFields

Fields required before signing. Validated before sign click.

dateFields

Date fields for formatting (MM/DD/YYYY).

picklistMap

Field name → options array for dropdown population.

licensekey

Nutrient Web SDK license key from org config.

nullFieldsError

If true, shows error overlay (required fields null).

signedHash

PKCS7 signature hash returned by invokeSignatureService().


VF Page — AutoPopulatedSigningScreen.page

Controller: AutoPopulatedSigningScreenController. Alternative signing page where form fields are auto-populated from template mappings and workflow configuration. User signs without manually filling fields.

Method

Returns

What it does

getTemplateData()

String

VF page getter. Reads workflowId from page params. Queries Document_Workflow__c, Document_Template__c. Fetches field config from DocumentGenerationService.getFormData(). Auto-populates dataMap with workflow values. Sets VF properties (same as PDFSigningScreen). Returns 'Success' or 'Error'.

invokeSignatureService(String digest, String workflowId)

String

Same as PDFSigningScreen. Receives PDF + workflowId, PKCS7-signs, saves, updates status.


VF Page — AutoPopulatedSigningScreenWord.page

Controller: AutoPopulatedSigningScreenController (same). Used for Word document (.docx) signing instead of PDF. Processes Word field merges before signing.


Apex — SigningScreenController

public with sharing. Backs PDFSigningScreen and AutoPopulatedSigningScreen VF pages. Handles signing workflow invocation.

Method

Returns

What it does

encodeDecodeURLString(String input, String action)

String

Encodes/decodes signing link for URL safety. Called by documentSigningScreen LWC to decode urlParam.

checkifUserAlreadySigned(String encodedLink)

Boolean

Checks if Document_Workflow_Item__c already signed (Event_Type = Document Signed).

getWorkflowStatus(String encodedLink)

Map

Queries workflow status (Awaiting Signature, Signature Completed, Workflow Completed, Failed, Expired).

getOtpFailCount(String encodedLink)

Integer

Returns OTP attempt count for rate-limiting.

declineDocument(String encodedLink)

void

Updates workflow + signer item status to declined. Creates audit event.

downloadSigningCertificate()

Blob

Returns signer certificate (.pfx or .cer) for download.

autoDownloadCertificate()

void

Auto-downloads certificate (browser-side JavaScript trigger).

recordSignerConsent(String encodedLink, Boolean bAccepted)

void

Logs signer consent acceptance for compliance.

logLinkVisit(String encodedLink)

void

Logs that signer clicked link (audit trail).

getSignerMessages()

Map

Returns custom messages (decline reason, success text, etc.).


Apex — DocumentSigningUtility

Helper class for signing operations.

Method

Purpose

sendEmail(EmailWrapper)

Constructs and sends email (used for signing confirmations).


Apex — WS_EoriginalService / WS_DigitalSigning

Web service integration classes. Handle e-signature service callouts (DocuSign, Adobe Sign, or eOriginal vaulting).

Class

Purpose

WS_EoriginalService

Callout to eOriginal service for document vaulting/notarization.

WS_DigitalSigning

Callout to digital signature provider for PKCS7/eIDAS signing.

EOriginalVaultCalloutQueueable

Queued async job for e-Original vaulting (doesn't block signing).


Data Flow — Signing Workflow Start to Completion

  1. Signer receives email with Document_Workflow_Item__c.Signer_URL_New__c link.

  2. Signer clicks link. Redirects via Salesforce Site (public).

  3. Salesforce Site routes to PDFESigningScreen.page with ?sign=URLEncodedLink param.

  4. PDFESigningScreen.page loads documentSigningScreen LWC via Lightning Out.

  5. documentSigningScreen LWC connectedCallback() executes.

  6. Calls UtilityClass.encodeDecodeURLString(urlParam, 'decode') → decodes link.

  7. Queries Document_Workflow_Item__c by decoded link.

  8. Queries linked Document_Workflow__c.

  9. Calls SigningScreenController.checkifUserAlreadySigned() → if already signed, sets alreadySigned=true, shows status screen. Return.

  10. Calls SigningScreenController.getWorkflowStatus() → checks expiry, status, etc. If expired, shows expiry screen. Return.

  11. Calls SigningScreenController.getOtpFailCount() → retrieves OTP attempt count.

  12. Queries Document_Template__c to check OTP requirement (Enable_OTP_On_Signing__c, OTP_Methods__c).

  13. If OTP required: calls SigningScreenController.getTemplateConfigs() → retrieves OTP methods. Populates otpMethods array. Sets showOTPScreen=true.

  14. Renders c-document-signing-o-t-p-screen child component.

  15. Signer enters OTP. c-document-signing-o-t-p-screen calls UtilityClass.verifyOTP() (server-side). On success: fires userVerified event. On fail: fires verificationFailed event + increments OTP attempt counter.

  16. documentSigningScreen LWC receives userVerified event.

  17. Sets showOTPScreen=false, documentGenerated=true.

  18. Calls loadSigningFrame().

  19. Determines signing page: if PDF → PDFSigningScreen.page. If Word → AutoPopulatedSigningScreenWord.page. If auto-populate → AutoPopulatedSigningScreen.page. (Check Document_Template__c.Is_Document_PDF__c and Disable_Form_Field_Editing__c).

  20. Constructs URL: /apex/PDFSigningScreen?workflowId={workflowId} (or similar).

  21. Sets generatedDocumentURL. HTML renders <iframe src="{generatedDocumentURL}" />.

  22. Iframe loads PDFSigningScreen.page.

  23. PDFSigningScreen.page controller calls getTemplateData() getter.

  24. Reads page param workflowId. Queries workflow + signer + template.

  25. Calls DocumentGenerationService.getFormData() → returns dataMap, readOnlyFields, requiredFields, dateFields, picklistMap, base64String (PDF).

  26. Sets VF properties.

  27. VF page renders. JavaScript calls loadConfigurations() → builds Maps.

  28. JavaScript calls loadPDF() → NutrientViewer.load(base64String, licensekey).

  29. Nutrient renders PDF + form fields in container.

  30. JavaScript calls configureFormFields() → sets read-only on readOnlyFields, applies date formatting, populates picklists.

  31. Signer views PDF + form fields.

  32. Signer fills fields + adds signature via Nutrient signature widget.

  33. Signer clicks "Sign" button.

  34. JavaScript calls signDocument().

  35. validateMissingFields() → checks all requiredFields filled. If any null: applyFieldBorder() highlights red, blocks sign.

  36. If all filled: signatureProcess().

  37. Validates at least one signature field has ink/image/text.

  38. Calls instance.exportPDF() → captures PDF with form values + user signatures.

  39. Encodes PDF as base64.

  40. Calls generatePKCS7() → prepares PKCS7 structure.

  41. POSTs to callSigningMethod (apex:actionFunction) with base64 digest + workflowId.

  42. SigningScreenController.invokeSignatureService(digest, workflowId) executes server-side.

  43. Calls SigningService.signDocument(digest, workflowId).

  44. SigningService generates PKCS7 hash using org certificate.

  45. Creates ContentVersion with signed PDF.

  46. Updates Document_Workflow__c status → Signature Completed.

  47. Creates Document_Workflow_Item__c event (Document Signed) with Digitally_Signed_Timestamp__c.

  48. Checks if last signer. If yes: updates Document_Workflow__c status → Workflow Completed.

  49. Returns { Success: true, signedHash (PKCS7 hex), signatureTimeStamps (JSON array) }.

  50. JavaScript receives response via oncomplete callback of apex:actionFunction.

  51. Calls window.parent.postMessage({ type: 'SigningResult', payload: { Success, signedHash, ... } }, vfOrigin).

  52. documentSigningScreen LWC (in parent) receives postMessage.

  53. Calls handleSigningResult(event).

  54. If Success: calls saveDocument() (if needed). Calls SigningScreenController.recordSignerConsent() (if consent required).

  55. Checks if bAutoDownloadCertificate. If yes: calls downloadSigningCertificate() → auto-downloads .pfx or .cer.

  56. Sets statusConfig = { type: 'success', message: 'Document signed successfully!', icon: success_image, buttons: [Download, Close/Redirect] }.

  57. Sets documentGenerated=true, showSpinner=false.

  58. Renders c-status-screen child component (displays status).

  59. Signer clicks Download Certificate (or auto-downloaded).

  60. SigningScreenController.downloadSigningCertificate() returns blob.

  61. Browser downloads certificate file.

  62. Signer clicks Close or page auto-redirects (if bRedirectionRequired and redirectionUrl set).

  63. Sends confirmation email to signer + next signer (if exists) or document owner.