Embedded signing with the Native iOS SDK
The newest releases of the Docusign Native iOS SDK offer embedded signing for the first time.
Docusign is pleased to announce the release of embedded signing capabilities on our mobile SDKs in our continued pursuit to empower app developers to achieve a robust signing experience on mobile devices. Embedded signing is a departure from the usual Remote Recipients pattern, in which a Docusign SDK brokers the communication with envelope recipients via native UI components to select the recipient and accept legal disclosures to sign the document. Embedded signing, in contrast, enables a mobile app to maintain its connection with envelope recipients by incorporating the Docusign signing service directly into its process flow. The functional result is a more fluid document transaction and a more transparent user experience to view and sign documents seamlessly within the client app. The new Captive Signing APIs on mobile SDKs improve on the signing experience by providing a robust wrapper around the Signing API. The SDK also handles all of the URL navigation requests and associated events that the online signing components generate, along with the detailed telemetry to capture all the required events.
Setting up the Native iOS SDK
Within the Native iOS SDK, the DSMManager component provides an API, setup
, to prepare the Native iOS SDK for signing experience. For advance usage, the setupWithConfiguration
API allows custom configurations to fine-tune the signing experience. An example below in Swift calls setup
with the extra configuration DSM_SETUP_CAPTIVE_SIGNING_USE_LANGUAGE_CODE
to customize the language for the signing experience.
// Invoke sdk setup with custom configurations
var configurations = DSMManager.defaultConfigurations()
// Set the language as Japanese - "ja" for Signing Session
configurations[DSM_SETUP_CAPTIVE_SIGNING_USE_LANGUAGE_CODE] = DSM_LANGUAGE_CODE_FOR_JAPANESE
DSMManager.setup(withConfiguration: configurations)
The supported languages codes for Signing are listed in the DSMLanguageConstants header.
Authentication with the Native iOS SDK
Users, authenticating through the Native iOS SDK, authorize a client app to access all of the features available as part of the SDK. Once a client app is authorized, components such as templates, captive signing, and offline signing become accessible to the app. Client apps explicitly looking to use the Captive Signing flow may skip user authentication and directly use the Signing URL variant flow to launch the embedded signing session, as detailed in the Captive Signing without SDK authentication section below. For any other integrations, which rely on the SDK to handle interactions with Docusign APIs, this section details the steps involved in authentication.
DSMManager defines the interface to login with Docusign OAuth when the client app has a valid access token retrieved independently of the iOS SDK. Once authenticated, the app performs a userinfo
request to fetch the additional properties, such as userId
, username
, host
, and more, required for the login API, loginWithAccessToken:accountId:userId:userName:email:host:integratorKey
, as defined in DSMManager. This Swift sample demonstrates how to perform login.
// Retrieve all of the required parameters for login
let accessToken = <client-access-token> // AccessToken as fetched with auth API "userinfo"
let accountId = <client-account-id> // Account ID as per user-info
let userId = <user-id> // User ID as per user-info
let userName = <user-name> // User name as fetched with user-info
let email = <email> // Email as fetched with user-info
let hostUrl = <host> // Host URL as fetched with user-info request
// Log in with Docusign SDK
DSMManager.login(
withAccessToken: accessToken,
accountId: accountId,
userId: userId,
userName: userName,
email: email,
host: hostUrl,
integratorKey: integratorKey) { accountInfo, error in
if let error = error {
// Handle and log sdk login error
...
return
}
// login is successful, process `accountInfo` as needed
...
}
To clear the credentials and persisted data on the device, including offline signed envelopes and downloaded templates, use the DSMManager:logout
method.
if DSMManager.logout() {
print ("Successfully logged out user and cleared local data.")
}
For additional details, our Swift sample app implements the authentication flow for a hypothetical financial services company: TGK Capital. The TGK Capital app allows investors to sign agreements seamlessly when integrated with the Native iOS SDK.
Retrieving the signing URL and presenting the signing session
Embedded signing enables users to view and sign documents within the app using generated signing URLs for each sent envelope. To present the signing request in the app UI, the logged-in SDK user must be the document sender and have access to the sent envelope to retrieve the signing URL. Additional details are available on the eSignature REST API 101 page Embedded signing and sending and the how-to guide How to request a signature through your app. The SwiftUI-based sample app also contains detail on the required steps.
The following interfaces on the DSMEnvelopesManager component enable client apps to retrieve the signing URL and load the captive signing session for an authenticated user. The envelope creation process described in the how-to guide contains the clientUserId
and other recipient view details. Note that the first variant makes an extra API call to fetch the recipientUserName
and recipientEmail
associated with the recipient view.
Captive Signing with the envelope ID and recipient's client user ID:
presentCaptiveSigningWithPresentingController:envelopeId:recipientClientUserId:animated:completion:
Captive Signing with the envelope ID and recipient's client user ID, user name, and email:
presentCaptiveSigningWithPresentingController:envelopeId:recipientUserName:recipientEmail:recipientClientUserId:animated:completion:
let presentingViewController = self
let envelopeId = ? // GUID of the captive (embedded) envelope ready to sign
let clientUserId = ? // The client user ID as configured during envelope creation
DSMEnvelopesManager().presentCaptiveSigning(withPresenting: presentingViewController,
envelopeId: envelopeId,
recipientClientUserId: clientUserId,
animated: true { viewController, error in
if let error = error {
// Handle error
...
return
}
// Use viewController as needed (for instance force-dismiss if the client app needs to exit the Docusign signing experience)
...
}
Additionally, the following method overload is available if the integrated app already has recipient details. Using this method would avoid making an additional API call to DSMEnvelopesManager.
...
DSMEnvelopesManager().presentCaptiveSigning(withPresenting: presentingViewController,
envelopeId: envelopeId,
recipientUserName: "John Wood",
recipientEmail: "john.wood@dsxtr.com",
recipientClientUserId: clientUserId,
animated: true { viewController, error in
...
}
Captive signing without SDK authentication
The Native iOS SDK untethers Captive Signing from authentication and directly launches the signing experience using the Captive Recipient Signing URL. This method relies on the integrating client application to independently retrieve the signing URL for the given envelope and recipient in order to view and capture signatures once the Native SDK setup
call is complete. When using this interface, there is no need to perform login or logout for the SDK user. One caveat is to use the signing URL within a short span of time (five minutes) before it expires.
This sample Swift code demonstrates retrieving the signing URL and presenting the signing experience using the presentCaptiveSigningWithPresentingController:signingUrl:envelopeId:recipientId:animated:completion:
API on DSMEnvelopesManager.
let presentingViewController = self
let signingUrl = <signing-url> // the embedded signing url as retrieved with client backend integration
let envelopeId = <created-envelope-id> // captive (embedded) envelope guid
let recipientId = <custom-recipient-id> // captive (embedded) recipient id used to create envelope
DSMEnvelopesManager().presentCaptiveSigning(withPresenting: presentingViewController,
signingUrl: signingUrl,
envelopeId: envelopeId,
recipientId: recipientId,
animated: true { viewController, error in
if let error = error {
// handle error
...
return
}
// Use viewController as needed (for instance, force-dismiss if the client app needs to exit Docusign signing experience)
...
}
This variant allows performing Captive Signing without user authentication, an additional method DSMManager allows, optionally, to remove all Docusign-related cookies generated in a signing experience with clearAllWebCookies
after each signing session.
DSMManager().clearAllWebCookies()
Processing events and handling errors
The Native iOS SDK dismisses the signing experience and handles the redirection required to return control to the client app when it's successfully completed. In case of presentation errors with the signing experience launch, the completion
block would return an error with a message indicating the reason for the failure. The client app may dismiss the presentedController
component to discard the signing in progress at any time to regain control.
The Native iOS SDK uses notifications to relay information related to errors and events. Client apps may register for various notifications, such as DSMEnvelopeSyncingSucceededNotification
, to receive the details on various stages of signing. The Notification object included in the userInfo
API response contains envelopeId
and other relevant information. Relevant notifications for online signing and SDK events can be found in the header file. Some of the important notifications are:
DSMSigningCompletedNotification
DSMSigningCancelledNotification
In this Swift example, a view is registering and handling signing notifications. Once signing is completed, in the case of Captive Signing with a recipientURL
parameter, clearAllWebCookies
is used for additional control.
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(onSigningCompleted(_:)), name: NSNotification.Name(rawValue: "DSMSigningCompletedNotification"), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(onSigningCancelled(_:)), name: NSNotification.Name(rawValue: "DSMSigningCancelledNotification"), object: nil)
}
@objc func onSigningCompleted(_ notification:Notification) {
// Handle the notification
guard let envelopeId = notification.userInfo?[DSMEnvelopeIdKey] as? String else {
// log the envelopeId for signing completed event
...
DSMManager.clearAllWebCookies()
}
...
}
@objc func onSigningCancelled(_ notification:Notification) { ... }
userInfo notification keys and signing event details
DSMEnvelopeIdKey
is added touserInfo
with any of the online signing notifications.DSMAdditionalInfo
is added touserInfo
when the user views a completed document and exits signing.DSMErrorKey
is added touserInfo
when signing encounters an error. In the case of embedded signing, for example, it would contain an API-returned error whenget /envelopes/{envelopeId}/recipients
fails.DSMSigningExitReasonKey
is added touserInfo
when the signer decides to decline or cancel using Finish Later**.** The value containscancel
ordecline
.DSMSigningModeKey
is added touserInfo
with all of the signing notifications. In the case of embedded signing,online
is the defined value.DSMNotificationCodes
contains more details on Notification Keys.
Additional resources
Ashok Meena is a Senior Software Engineer in the Docusign Mobile team, where he leads the Native iOS SDK engineering effort and contributes to our top-rated iOS apps. Since the first mobile SDK release, he has built many features from the ground up and incorporated telemetry and performance reports to capture events, alerts, and various metrics around customer-centric integrations.
Related posts