Resend Docusign envelope using C# - c#

I'm trying to use code I found here to resend an envelope, but no luck. My code is in two parts. Here's the code on my ASPX page to call a method to resend the envelope:
protected void btnResend_Click(object sender, EventArgs e)
{
Signer signer = new Signer();
signer.Email = txtRecipeintEmail.Text;
signer.Name = txtRecipientName.Text;
Manager mgr = new Manager();
mgr.ResendEnvelope(txtEnvelopeID.Text, signer);
}
Here's the code in the Manager class:
public void ResendEnvelope (string envelopeID, Signer signer)
{
// instantiation of recipients as per https://stackoverflow.com/questions/21565765/resend-docusign-emails
Recipients recipients = new Recipients
{
Signers = new List<Signer>()
{
new Signer
{
RecipientId = "1",
RoleName = "Prospect",
Email = signer.Email,
Name = signer.Name,
},
}
};
string accountID = GetAccountID();
EnvelopesApi api = new EnvelopesApi();
EnvelopesApi.UpdateRecipientsOptions options = new EnvelopesApi.UpdateRecipientsOptions();
options.resendEnvelope = "true";
RecipientsUpdateSummary summary = api.UpdateRecipients(accountID, envelopeID, recipients, options);
var responses = summary.RecipientUpdateResults.ToList<RecipientUpdateResponse>();
var errors = responses.Select(rs => rs.ErrorDetails).ToList();
}
My GetAccountID function works fine - I use it to send the envelope. The value in txtEnvelopeID.Text is set from the code used to send the initial email. I get the initial email.
Here's what I see in errors:
?errors[0].Message
"The specified envelope corrections have duplicate recipients."
?errors[0].ErrorCode
"CORRECTION_HAS_DUPLICATE_RECIPIENTS"
When I tried to set the third argument of UpdateRecipients to null, I got a different error. When I left recipients blank (api.UpdateRecipients(accountID, envelopeID, options: = options)), I got an error.
So, I'm out of new ideas to try. Can anyone help?

The issue you are encountering is that you are creating again a signer that already exists, except that you don't assign the same RecipientId, hence the duplicate error.
Instead of
RecipientId = "1"
You need to make sure you assign the original signer ID, see below :
Signers = new List<Signer>()
{
new Signer
{
RecipientId = signer.RecipientId
},
}
In order to re-send the DocuSign email to your recipients, you can use the UpdateRecipient() method as such (see my C# example below). This will re-trigger the signing email to be sent one more time to the transaction recipients you specify in the recipients parameter :
RecipientsUpdateSummary recipientsUpdateSummary =
envelopeApi.UpdateRecipients(
accountId,
EnvelopeId,
RecipientsToNotifyAgain,
new EnvelopesApi.UpdateRecipientsOptions { resendEnvelope = "true" });
Here is what the official documentation states :

Related

How to use SMS-Authentication in DocuSign

I'm trying to implement the SMS authentication with the aid of the DocuSign-SDK library.
var signer = new Signer {...};
signer.RequireIdLookup = "true";
signer.IdCheckConfigurationName = "SMS Auth $";
signer.SmsAuthentication = new RecipientSMSAuthentication {
SenderProvidedNumbers = new List<string> {
"0171*******"
}
};
When I try to send this envelope to the DocuSign API it will reply with the following error message:
Error calling CreateEnvelope:
{"errorCode":"INVALIDAUTHENTICATIONSETUP","message":"Recipient phone
number is invalid. Phone number for SMS Authentication: provided is
invalid. }
INVALIDAUTHENTICATIONSETUP: Authentication is not setup correctly for the recipient.
Is there something I have to enable on the DocuSign Admin page? I couldn't find any feature or something like that I need to enable.
Did I implement it the wrong way? Maybe someone can give me some suggestions.
Thanks
BTW: The given phone number should be valid.
EDIT:
When I'm using the new method as #Inbar wrote, I can't get the needed workflowId from the AccountsApi.
var client = new ApiClient(ApiClient.Demo_REST_BasePath);
var token = "eyJ1...";
client.Configuration.DefaultHeader.Add("Authorization", "Bearer " + token);
var accountsApi = new AccountsApi(client);
var response = accountsApi.GetAccountIdentityVerification(accountId);
var result = response.IdentityVerification; // Is empty. Why?
It seems that I have no IdentityVerification options which I can use for the authentication.
How can I enable such IdentityVerification options?
Or what else do I need to pay attention to?
Your code is using the older method, the new method code is provided in GitHub, I'll post it here too. You can find the article on Dev Center.
string workflowId = phoneAuthWorkflow.WorkflowId;
EnvelopeDefinition env = new EnvelopeDefinition()
{
EnvelopeIdStamping = "true",
EmailSubject = "Please Sign",
EmailBlurb = "Sample text for email body",
Status = "Sent"
};
byte[] buffer = System.IO.File.ReadAllBytes(docPdf);
// Add a document
Document doc1 = new Document()
{
DocumentId = "1",
FileExtension = "pdf",
Name = "Lorem",
DocumentBase64 = Convert.ToBase64String(buffer)
};
// Create your signature tab
env.Documents = new List<Document> { doc1 };
SignHere signHere1 = new SignHere
{
AnchorString = "/sn1/",
AnchorUnits = "pixels",
AnchorXOffset = "10",
AnchorYOffset = "20"
};
// Tabs are set per recipient/signer
Tabs signer1Tabs = new Tabs
{
SignHereTabs = new List<SignHere> { signHere1 }
};
string workflowId = workflowId;
RecipientIdentityVerification workflow = new RecipientIdentityVerification()
{
WorkflowId = workflowId,
InputOptions = new List<RecipientIdentityInputOption> {
new RecipientIdentityInputOption
{
Name = "phone_number_list",
ValueType = "PhoneNumberList",
PhoneNumberList = new List<RecipientIdentityPhoneNumber>
{
new RecipientIdentityPhoneNumber
{
Number = phoneNumber,
CountryCode = countryAreaCode,
}
}
}
}
};
Signer signer1 = new Signer()
{
Name = signerName,
Email = signerEmail,
RoutingOrder = "1",
Status = "Created",
DeliveryMethod = "Email",
RecipientId = "1", //represents your {RECIPIENT_ID},
Tabs = signer1Tabs,
IdentityVerification = workflow,
};
Recipients recipients = new Recipients();
recipients.Signers = new List<Signer> { signer1 };
env.Recipients = recipients;
I've created a new developer account on DocuSign and created a small test app in order to request identity verification options. Fortunately, that was working now and I got all available options but I do not understand why this is not working for my other developer account ("old").
When I compare both accounts I don't see the "Identity Verification" setting in the "old" account.
It is possible to activate this "Identity Verification" setting for my "old" dev account?
I guess that enabling this feature would solve the problem.
EDIT:
Ok, I've solved the problem.
I figured out that no IDV was configured for my developer account. In that case, the identity_verification call will return an empty array.
see: https://developers.docusign.com/docs/esign-rest-api/how-to/id-verification/
Also, I have read the following note in the DocuSign documentation:
Note: Phone authentication may not be enabled for some older developer
accounts. If you cannot choose to use phone authentication for your
account, contact support to request access. see:
https://developers.docusign.com/docs/esign-rest-api/esign101/concepts/recipients/auth/#id-verification-idv
So I contacted DocuSign support and they give me access to the IDV accordingly.
Now it is working fine.

DocuSign: Signer Tabs are lost when updating an envelope

When I initially create and sent a DocuSign envelope, I define the tabs where to recipients needs to sign and where the signed date will be placed. This works great with the eSignatures REST API.
When some changes are done in the document (and the envelope status is sent or delivered), the document of the envelope can still be updated.
With the code below I'm able to update the document and email subject/body. After resend, I get the changes made to the email and document correctly.
In the 'new' DocuSign email the signer tabs are lost and I don't have a place to sign.
What I have tried, is to define the signerTabs again and bound it to the recipient.
Update document and email subject/body
envDef.EmailSubject = env.EmailSubject = "Updated documents";
envDef.EmailBlurb = env.EmailBlurb = "Changes were made to the document(s)";
env.Status = EnumHelper.GetDescription(DSStatus.Sent);
envDef.Documents = new List<Document>() { doc };
apiClient.UpdateDocuments(_accountId, envelopeId, envDef);
//resend
apiClient.Update(_accountId, envelopeId, env, new EnvelopesApi.UpdateOptions() { resendEnvelope = true.ToString() });
Signer signer1 = new Signer
{
RecipientId = "1"
};
SignHere signHere1 = new SignHere
{
AnchorString = "/sn1/"
};
Tabs signer1Tabs = new Tabs
{
SignHereTabs = new List<SignHere> { signHere1 },
DateSignedTabs = new List<DateSigned> { dateSigned1 },
FullNameTabs = new List<FullName> { fullName1 }
};
signer1.Tabs = signer1Tabs;
Recipients recipients = new Recipients
{
Signers = new List<Signer> { signer1 },
};
env.Recipients = recipients;
EDIT
This is my request body when sending an envelope. The signer tabs are added with anchorString, in this case /sn1/. So it seems that the updated document no longer has these tabs.
"recipients" : {
"signers" : [ {
"routingOrder" : "1",
"name" : "Recipient Name",
"email" : "Recipient Email Address",
"recipientId" : "1",
"tabs" : {
"signHereTabs" : [ {
"anchorString" : "/sn1/",
} ]
How comes that those signer details are lost, but the envelope is resend to the correct signers again?
so your tabs, how were they created? manually by dragging dropping in the tagger?
You can define them using the API as well. You can GET them for an existing envelope and then "rehydrate" them back to the envelope after you updated it.
Probably, it is common in DocuSign that the tabs of the recipients are lost when updating a document.
To solve this I got the recipients with the tabs included with following call:
apiClient.ListRecipients(_accountId, envelopeId, new EnvelopesApi.ListRecipientsOptions(){ includeTabs = true.ToString() });
This result can be placed in envDef.Recipients.

Adding Witness functionality Calling DocuSign

I am using DocuSign(methods in DocuSign.eSign.dll) in c# to implement electronic signature functionality.
I want to add Witness feature similar to the way we do it physically when signing any document.
As per guidelines suggested by DocuSign ,I am using Signer Role as "Specify Recipients" and routing order as "2".
I am using SignHere object as
below
Signer signer = new Signer
{
RoleName = "Specify Recipients",
RoutingOrder = "2"
};
Whenever I call "CreateEnvelope" method exposed by DocuSign, It should give options in email to the recipient to add witness for his documents. Can I know what properties to be set of "Signer" object to achieve this. Or is there any other way to achieve this.
You will need to add that recipient twice, in two separate roles.
A Signer is only able to act on the document. You'll need to create an Agent role for them to be able to specify later recipients.
If you haven't already, you'll also need to add the placeholder Witness role with no name/email defined so that they have a role to fill in.
Signer signer = new Signer
{
Name = signerName,
Email = signerEmail,
RecipientId = "1",
RoutingOrder = "1"
};
Agent agent = new Agent
{
Name = signerName,
Email = signerEmail,
RecipientId = "2",
RoutingOrder = "2"
};
Signer witness = new Signer
{
RoleName = "Witness",
RecipientId = "3",
RoutingOrder = "3",
};
Signer[] signers = new Signer[] { signer, witness };
Agent[] agents = new Agent[] { agent };
Recipients recipients = new Recipients { Signers = new List<Signer>(signers), Agents = new List<Agent>(agents) };
with this setup, the recipient will first get an email invitation to sign the document. Once they complete that, they'll get another invitation to act as the Agent and specify the final recipient. Then the Witness that the user defined will receive their invitation.

Microsoft.Graph SDK SendMail As User - 400 - Unexpected Exception or Open navigation properties are not supported

I'm working on an application that needs to send email notifications and reminders to users when they have actions to complete. A user submits data, then the app notifies other users to perform actions in a specific order (i.e. User 1: Task 1, after Task 1 is complete, User 2: Task 2, etc.) - if a user is taking too long to perform their action, the system will remind them then defer to their manager (via a Windows service or similar). Due to this, I can't send messages on behalf of the current signed in user - it needs to be able to send messages on its own. It is preferred to send on behalf of the user that submitted the data, so subsequent users can reply directly to them.
I'm using the Microsoft Graph Client Library v1.10.0. Running my code yields an aggregate exception ultimately boiling down to a code 400, code "generalException", message "Unexpected exception returned from the service." I've used LinqPad to look into the Graph objects, and attempted to reproduce the call in Postman, which yields a 400 with a message of "Open navigation properties are not supported on OpenTypes. Property name: 'microsoft.graph.sendmail'."
More thorough details:
Application has Microsoft Graph -> Send mail as any user, Read all groups, Read all users' full profiles permissions.
Calling GraphServiceClient.Client.Users["MyUPN"].SendMail(email, true).Request().PostAsync() yields a 400 general exception with Unexpected exception returned from the service. (Full code below)
Looking at the request, I found it's calling https://graph.windows.net:443/{{tenantId}}/users/{{MyUPN}}/microsoft.graph.sendMail?api-version=1.6 and attempted to make the same call via Postman (with a valid token), which yielded a 400 bad request with message Open navigation properties are not supported on OpenTypes. Property name: 'microsoft.graph.sendMail'.
Full Code:
String MyEmailAddress = "";
String MyUpn = "";
String TenantId = "";
String AppGuid = "";
String AppKey = "";
var sender = new Microsoft.Graph.Recipient()
{
EmailAddress = new Microsoft.Graph.EmailAddress() { Address = MyEmailAddress }
};
var email = new Microsoft.Graph.Message
{
Sender = sender,
From = sender,
Subject = "Test",
Body = new Microsoft.Graph.ItemBody()
{
Content = "Test Body",
ContentType = Microsoft.Graph.BodyType.Text
}
};
email.ToRecipients = new List<Microsoft.Graph.Recipient>(){ sender };
email.BodyPreview = "Test Summary";
GraphSdk _Sdk = new GraphSdk(TenantId, AppGuid, AppKey);
// Where the error throws
await _Sdk.Client.Users[MyUpn].SendMail(email, true).Request().PostAsync();
As a test, I also tried await _Sdk.Client.Users[MyUpn].Messages.Request().Top(20).GetAsync(); which yielded the same error. Other Graph calls, like getting a user's groups or manager, work fine - this error only appears on email-related calls.
Update 9/19/2018 AM
It looks like I can get emails working if I use a certificate to generate the token instead of the Key -> Password; and call the Outlook API instead. Unfortunately, that doesn't work through the GraphServiceClient and Graph API - it can use the certificate, and use the Outlook API base URL, but the microsoft.graph.sendMail action is just sendMail in the Outlook API.
For maintainability, I'd still like to get it all working under the Graph API so I'm still looking for an answer to the original question.
At some point I had set the BaseUrl for the client to https://graph.windows.net:443/{{tenantId}}, possibly due to the varying branding over the past few years (Microsoft Graph vs Azure Graph). Under current recommendations for the Microsoft.Graph it should be https://graph.microsoft.com/v1.0/ - which also appears to be the default value.
Additionally, I had to switch to using a certificate instead of the Azure-generated Key -> Password for the app.
Total working code is:
String AADTenantId = "";
String AppGuid = "";
String SenderAddress = "";
String SenderId = "";
String ToAddress = "";
String SubjectText = "";
String BodyText = "";
Byte[] Certificate = ...GetCertBytes...
String CertPassword = "";
var client = new GraphServiceClient(new DelegateAuthenticationProvider(
async requestMessage =>
{
var authContext = new AuthenticationContext($"https://login.microsoftonline.com/{AADTenantId}");
var cert = new X509Certificate2(Certificate, CertPassword);
var clientAssertion = new ClientAssertionCertificate(AppGuid, cert);
AuthenticationResult authresult = await authContext.AcquireTokenAsync("https://graph.microsoft.com", clientAssertion);
// Append the access token to the request
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authresult.AccessToken);
}));
var sender = new Recipient()
{
EmailAddress = new EmailAddress() { Address = SenderAddress }
};
var email = new Message
{
Sender = sender,
From = sender,
Subject = SubjectText,
Body = new ItemBody()
{
Content = BodyText,
ContentType = BodyType.Text
},
ToRecipients = new List<Recipient>() {
new Recipient() { EmailAddress = new EmailAddress { Address = ToAddress }}
}
};
await client.Users[SenderId].SendMail(email, true).Request().PostAsync();
According to your description, you want send an email but get an 400 error.
Based on my test, we can use the following steps to send an email.
step1, we should get a graphClient which is a authenticated HttpClient.
The code like this:
GraphServiceClient graphServiceClient = new GraphServiceClient(
new DelegateAuthenticationProvider(
async (requestMessage) =>
{
string accessToken = await MsalAuthProvider.Instance.GetUserAccesstokenAsync();
requestMessage.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", accessToken);
}));
return graphServiceClient;
We can refer to the simple code in the official document.
step2, we can use the following code to send a mail:
public async Task<bool> SendAsync(EmailAddress toaddress)
{
var email = new Message
{
Body = new ItemBody
{
Content = "Test for sending eamil ",
ContentType = BodyType.Text,
},
Subject = "Test for sending eamil",
ToRecipients = new List<Recipient>
{
new Recipient
{
EmailAddress = toaddress
}
},
};
try
{
await _serviceClient.Me.SendMail(email).Request().PostAsync(); // the _serviceClient is the result in the step1.
return true;
}
catch (Exception ex)
{
return false;
}

Get text custom field returns null in DocuSign

I have an account ID and also a template ID, but I am getting null in text custom and list fields. I am using DocuSign's REST api for getting custom fields and listed fields.
configureApiClient("https://demo.docusign.net/restapi");
// Step 1: Login()
// call the Login() API which sets the user's baseUrl and returns their accountId
AccountId = loginApi(username, password);
TemplatesApi envelopesApi2 = new TemplatesApi();
CustomFields cfe = envelopesApi2.ListCustomFields(AccountId, templateId);
Console.WriteLine("Get Custom Fields Information:\n{0}",
JsonConvert.SerializeObject(cfe));
Could you please help me to solve my problem?
Thanks in advance
I see that you are adding the custom fields to an envelope and not template. You should use the EnvelopesApi to retrieve the CustomFields. You are incorrectly using the TemplateId.
Use the following code and pass the envelopeId that is returned from the envelopesApi.CreateEnvelope() call
var envelopesApi2 = new EnvelopesApi();
CustomFields cfe = envelopesApi2.ListCustomFields(AccountId, envelopeId);
Console.WriteLine("Get Custom Fields Information:\n{0}",
JsonConvert.SerializeObject(cfe));
Please see my below code to create custom field in templates.
public EnvelopeSummary requestSignatureFromTemplateTest(DocuSignData data)
{
// instantiate api client with appropriate environment (for production change to www.docusign.net/restapi)
configureApiClient("https://demo.docusign.net/restapi");
//===========================================================
// Step 1: Login()
//===========================================================
// call the Login() API which sets the user's baseUrl and returns their accountId
AccountId = loginApi(username, password);
//===========================================================
// Step 2: Signature Request from Template
//===========================================================
EnvelopeDefinition envDef = new EnvelopeDefinition();
envDef.EmailSubject = "Please sign this sample template document11111111111";
// assign recipient to template role by setting name, email, and role name. Note that the
// template role name must match the placeholder role name saved in your account template.
TemplateRole tRole = new TemplateRole();
tRole.Email = recipientEmail;
tRole.Name = recipientName;
tRole.RoleName = templateRoleName;
List<TemplateRole> rolesList = new List<TemplateRole>() { tRole };
// add the role to the envelope and assign valid templateId from your account
envDef.TemplateRoles = rolesList;
envDef.TemplateId = templateId;
// set envelope status to "sent" to immediately send the signature request
envDef.Status = "sent";
List<TextCustomField> customFieldsTextList = new List<TextCustomField>();
if (data.CustomFieldsText != null)
{
//custom text fields
foreach (DocuSignCustomField customField in data.CustomFieldsText)
{
TextCustomField newField = new TextCustomField();
newField.Name = customField.Name;
newField.Value = customField.Value;
newField.Show = customField.Show;
newField.Required = customField.Required;
customFieldsTextList.Add(newField);
}
}
CustomFields customFields = new CustomFields();
customFields.TextCustomFields = customFieldsTextList;
envDef.CustomFields = customFields;
// |EnvelopesApi| contains methods related to creating and sending Envelopes (aka signature requests)
EnvelopesApi envelopesApi = new EnvelopesApi();
EnvelopeSummary envelopeSummary = envelopesApi.CreateEnvelope(AccountId, envDef);
// print the JSON response
//Console.WriteLine("Envelope Template Summary:\n{0}", JsonConvert.SerializeObject(envelopeSummary));
return envelopeSummary;
} // end requestSignatureFromTemplateTest()
this code for getting custom fields from template
configureApiClient("https://demo.docusign.net/restapi");
// Step 1: Login()
// call the Login() API which sets the user's baseUrl and returns their accountId
AccountId = loginApi(username, password);
TemplatesApi envelopesApi2 = new TemplatesApi();
CustomFields cfe = envelopesApi2.ListCustomFields(AccountId, templateId);
Console.WriteLine("Get Custom Fields Information:\n{0}",
JsonConvert.SerializeObject(cfe));

Categories

Resources