Skip to content

Latest commit

 

History

History
218 lines (182 loc) · 14.8 KB

Compose-Envelope.md

File metadata and controls

218 lines (182 loc) · 14.8 KB

DocuSign iOS SDK Compose Envelope

Compose Envelope - using EnvelopeDefinition

Using EnvelopeBuilder & Resuming composed envelope

DSMEnvelopeBuilder allows adding Signers, PDF-documents and Tabs among other customizable options to compose an envelope definition object and cache it with DSMEnvelopeManager. Afterwards, envelope definition object can be used to directly launch signing ceremony in offline mode using resumeSigningEnvelopeWithPresentingController:... method on DSMEnvelopeManager. This new flow to compose and resume envelope allows client apps to skip the DocuSign SDK UI components entirely to get documents signed with preassigned tabs and provides an alternative to using Compose-UI or using Envelope Templates.

Compose EnvelopeDefinition

DSMEnvelopesManager has the following interface defined that takes an DSMEnvelopeDefinition object to launch signing.

/*!
 * @discussion Creates an envelope programmatically using DSMEnvelopeBuilder.
 * @param signingMode compose envelope in either online or offline mode, see DSMSigningMode
 * @param completion completion block to be executed after envelope is successfully created.
 * @warning passing nil to a presentationController will not be able to load the offline envelope flow.
 * @see DSMEnvelopeBuilder
 */
- (void)composeEnvelopeWithEnvelopeDefinition:(DSMEnvelopeDefinition *)envelope
                                  signingMode:(DSMSigningMode)signingMode
                                   completion:(nullable void(^)(NSString *_Nullable envelopeId, NSError *error))completion;

Load Signing

Once the envelope has been composed and saved on the local device, resume envelope interface can be used to start the signing ceremony for local signers.

/*!
 * @discussion Resume signing with a cached envelope. This call can be made when device is offline.
 * @param presentingController controller will be presented on top of the given presentingController passed.
 * @param envelopeId An Id of the envelope to be resumed.
 * @param completion completion block to be executed after envelope signing has been resumed.
 */
- (void)resumeSigningEnvelopeWithPresentingController:(UIViewController *)presentingController
                                           envelopeId:(NSString *)envelopeId
                                           completion:(void(^)(UIViewController *_Nullable presentedController, NSError *_Nullable error))completion;

Syncing Signed Envelopes with DocuSign Server

Finally, once the signing is complete the signed envelope is cached on device. The cached envelopes can be synced with syncEnvelopes method on DSMEnvelopesManager.

Note: Offline Signing account feature must be enabled to perform Sync successfully. Please connect DocuSign Support in order to get Offline Signing enabled.

/*!
 * @discussion Sync the pending envelopes on the device to create remote envelopes.
 * An envelope can be in pending Sync state when
 * a) created envelope's local InPersonSigner(s) or self-Signer have finished signing,
 *   and either has no pending local InPersonSigner(s) or only has pending remote
 *   signer(s) in next signing order.
 * b) created envelope only has pending remote signer(s) in next signing order.
 * @use When device is online and there has been sign and send Offline and pending sync to server.
 * @use Data validation or extraction for an offline completed envelope should be done before invoking the sync. Once an envelope is successfully synced, it's deleted from the cache on the device.
 * @discussion Relevant Notifications that can be used to track the progress of an envelope sync task: DSMEnvelopeSyncingStartedNotification, DSMEnvelopeSyncingSucceededNotification, DSMEnvelopeSyncingEndedNotification, DSMEnvelopeSyncingFailedNotification.
 * @see DSMNotificationCodes
 */
- (void)syncEnvelopes;

Tracking Events

Client apps may register for various notification, such as DSMEnvelopeSyncingSucceededNotification, to receive the details on various stages of signing & envelope syncing. Notification object with userInfo contains envelopeId of synced document on server. It’s recommended to implement other relevant notifications (header file) to capture and log details. Take a look at header file for the important notifications to achieve desired results, some are:

  • DSMSigningCompletedNotification
  • DSMSigningCancelledNotification
  • DSMEnvelopeSyncingFailedNotification

An example of another notification DSMEnvelopeCachedNotification from the header file.

/*!
 * @brief Notification sent when caching is enabled for a given record (envelope).
 * @discussion Returned userInfo contains envelopeId associated with DSMEnvelopeIdKey, templateId associated with DSMTemplateIdKey. This can be posted on a thread other than MainThread.
 * [[NSNotificationCenter defaultCenter] postNotificationName:DSMEnvelopeCachedNotification object:nil userInfo:userInfo];
 * Note: Enabling setup configuration `DSM_SETUP_ENABLE_OFFLINE_SIGNING_SAVE_ENVELOPE_PROGRESS_KEY` would result in this notification being sent every time a local offline envelope is saved after local signer finishes signing.
 */
extern NSString * const DSMEnvelopeCachedNotification;

Customizing DSMEnvelopeDefinition: Adding Signers, PDFs and Tabs using Builders

The newly exposed interface in DSMEnvelopesManager uses DSMEnvelopeBuilder to customize the envelope definition. Commonly used builders with DSMEnvelopeBuilder are DSMDocumentBuilder, DSMTabBuilder, DSMRecipientBuilder, DSMTextCustomFieldBuilder and DSMListCustomFieldBuilder.

Here are some of the snippets that can be used to compose the DSMEnvelopeDefinition.

// Create a envelope with email and message
DSMEnvelopeDefinition *envelope = [[[[DSMEnvelopeBuilder builder]
                                          addEmailSubject: @"DocuSign: NDA.pdf"]
                                          addEmailMessage: @"Hi Jane Wood, I'm sending you an NDA to sign and return, ...."]
                                        build];

// Create a document with pdf file and assign a name and id
DSMEnvelopeDocument *document = [[[[[DSMDocumentBuilder builder]
                                          addName: @"NDADocument"]
                                          addDocumentId: @"1"]
                                          addFilePath: [[NSBundle mainBundle] pathForResource: @"NDA" ofType: @"pdf"]] 
                                        build];

// Create an envelope recipient with name and email and assign an id and type with routing order
DSMEnvelopeRecipient *recipient = [[[[[[DSMRecipientBuilder builderForType: DSMRecipientTypeSigner]
                                          addRecipientId: @"FirstRecipient"]
                                          addSignerName: @"Jane Wood"]
                                          addSignerEmail: @"[email protected]"]
                                          addRoutingOrder: 1] 
                                        build];

// Create a signature tab at a given position on a document page
DSMEnvelopeTab *signTab = [[[[[[[DSMTabBuilder builderForType: DSMTabTypeSignHere]
                                                          addName: @"Signature"]
                                                          addRecipientId: @"FirstRecipient"]
                                                          addDocumentId: @"1"]
                                                          addFrame: CGRectMake(100, 300, 40, 50)]
                                                          addPageNumber: 1
                                                  ] build]

// Create a text based tab at a given postion on a document page
DSMEnvelopeTab *nameTab = [[[[[[[DSMTabBuilder builderForType:DSMTabTypeText]
                                          addName: @"Name"]
                                          addRecipientId: @"FirstRecipient"]
                                          addFrame: CGRectMake(100, 200, 120, 30)]
                                          addDocumentId: @"1"]
                                          addPageNumber: 1] 
                                        build];

// Alternatively, all these could be chained with multiple builders.
@try {
  DSMEnvelopeDefinition *envelope = [[[[[[[DSMEnvelopeBuilder builder]
                      addEnvelopeName: @"DocuSign NDA"]
                      addEmailSubject: @"DocuSign: NDA.pdf"]
                      addEmailMessage: @"Hi Jane Wood, I'm sending you an NDA to sign and return, ...."]
                      addRecipient:[[[[[[DSMRecipientBuilder builderForType: DSMRecipientTypeSigner]
                                          addRecipientId: @"FirstRecipient"]
                                          addSignerName: @"Jane Wood"]
                                          addSignerEmail: @"[email protected]"]
                                          addTab: [[[[[[[DSMTabBuilder builderForType: DSMTabTypeSignHere]
                                                          addName: @"Signature"]
                                                          addRecipientId: @"FirstRecipient"]
                                                          addDocumentId: @"1"]
                                                          addFrame: CGRectMake(100, 300, 40, 50)]
                                                          addPageNumber: 1
                                                  ] build]
                                    ] build]] 
                      addDocument:[[[[[DSMDocumentBuilder builder]
                                          addName: @"NDADocument"]
                                          addDocumentId: @"1"]
                                          addFilePath: [[NSBundle bundleForClass: [self class]] pathForResource: @"NDA" ofType: @"pdf"]
                                  ] build]
                ] build];
  if (envelope) {
    // Compose the envelope to automatically cache it
    [self.envelopesManager composeEnvelopeWithEnvelopeDefinition: envelope
                              signingMode: DSMSigningModeOffline
                              completion: ^(NSString * _Nullable envelopeId, NSError * _Nonnull error) {
                                    // error checks in case envelope compose failed. Also use notifications for caching related events.
                                    if (error) { ... }

                                    // Resume the envelope to start the signing process
                                    [self.envelopesManager resumeSigningEnvelopeWithPresentingController: self
                                            envelopeId: envelopeId
                                            completion: ^(UIViewController * _Nullable presentedController, NSError * _Nullable error) {
                                        // error checks in case UI presentation failed. Use notifications for other events.
                                        if (error) { ... }
                                    }];                                
                                }
    ];
  }
} @catch (NSException *exception) {
  // Handle exception
}

Compose Envelope - UI Components

The Compose Envelope flow allows user the ability to create an envelope (adding documents, recipients, and tags) without previously downloading any templates, both online or offline where behaviour will differentiate the two after an envelope has been created.

The client app is responsible for detecting when network connectivity is available, require a user to be logged in, and present the appropriate flow. To do this, invoke the following method in DSMEnvelopesManager.h.

/*!
* @discussion Start creating an envelope to manually add documents, recipients and tags. Client app is responsible for detecting network to present appropriate online/offline flow.
* @param presentingController controller will be presented on top of the given presentingController passed.
* @param signingMode compose envelope in either online or offline mode, see DSMSigningMode
* @param resumeWithDraft determines whether to initialize flow with a previously saved draft (if any)
* @param animated if the presentation of sign and send be animated or not.
* @param completion completion block to be executed after compose envelope controller is presented
* @warning passing nil to a presentationController will not be able to load the offline envelope flow.
* @discussion Relevant Notifications that can be used to track the progress of an envelope sync task: DSMOnlineEnvelopeSendFailedNotification.
* @see DSMNotificationCodes
*/
- (void)presentComposeEnvelopeControllerWithPresentingController:(UIViewController *)presentingController
                                                     signingMode:(DSMSigningMode)signingMode
                                                 resumeWithDraft:(BOOL)resumeWithDraft
                                                        animated:(BOOL)animated
                                                      completion:(void(^)(UIViewController *viewController))completion;

If resumeWithDraft is set to false, the previously cached draft envelope, if any, will be removed. You are able to determine whether there is a previously cached draft envelope (there can only be one at a time) by invoking:

/*!
* @discussion Returns whether there is a current cached envelope in draft status. Once an envelope is successfully synced, it's deleted from the cache on the device. This can be used to determine whether presenting compose envelope flow should be resumed with the draft envelope. There can only be one draft cached envelope at a given time.
* @return BOOL, true if there is a cached draft envelope
*/
- (BOOL)hasCachedDraftEnvelope;

Requirements


  • the setup constant DSM_SETUP_ICLOUD_DOCUMENT_ENABLED must be set to DSM_SETUP_TRUE_VALUE in order for document selection to work. Depending the iOS version, the following must also be done:
  • For iOS10 and below, iCloud entitlement must be added along with iCloud documents in order for document selection to work
  • For iOS11+, the Compose Envelope flow requires the use of the Files app (to select documents on the device, iCloud, or other third-party apps) and will work without any further configuration