I am trying to create and send an envelope on the demo environment using the docusign C# API. I am using JWT as my OAuth2 flow. I am able to properly grab the access code needed to authorized my embedded signing.
The function CreateEnvelope fails and throws an exception. The exception shows no information other than that the function failed.
Image of Exception
Has anyone encountered a similar situation before? I have provided a snippet of the code below. Is there anything clearly wrong with how I may be trying to create the envelope?
public static void DocusignFormatter()
{
EnvelopeDefinition envDef = new EnvelopeDefinition();
Document doc = new Document();
doc.DocumentBase64 = System.Convert.ToBase64String(pdfFileInfo.fileBytes);
doc.Name = pdfFileInfo.DocName;
doc.DocumentId = "1";
envDef.Documents = new List<Document>();
envDef.Documents.Add(doc);
envDef.Recipients = new Recipients();
envDef.Recipients.Signers = new List<Signer>();
for (int i = 0; i < signatureFields.Count; i++)
{
Signer signer = new Signer();
signer.Email = docRegistrant.Email;
signer.Name = docApplicants[i].FirstName + " " + docApplicants[i].LastName;
signer.RecipientId = $"{i+1}";
signer.Tabs = new Tabs();
signer.Tabs.SignHereTabs = new List<SignHere>();
List<MyPdfSignatureField> fields;
signatureFields.TryGetValue(i, out fields);
foreach (MyPdfSignatureField field in fields)
{
SignHere signHere = new SignHere();
signHere.DocumentId = "1";
signHere.PageNumber = field.PageNum.ToString();
signHere.RecipientId = i.ToString();
signHere.XPosition = field.XLocation.ToString();
signHere.YPosition = field.YLocation.ToString();
signer.Tabs.SignHereTabs.Add(signHere);
}
envDef.Recipients.Signers.Add(signer);
}
envDef.Status = "created";
ApiClient apiClient = new ApiClient(DocusignHelpers.OAuthBasePath);
Configuration cfi = new Configuration(apiClient);
cfi.AddDefaultHeader("Authorization", "Bearer " + DocusignHelpers.AccessToken);
cfi.AccessToken = DocusignHelpers.AccessToken;
cfi.Password = DocusignHelpers.Password;
EnvelopesApi envelopesApi = new EnvelopesApi(cfi);
EnvelopeSummary envelopeSummary = envelopesApi.CreateEnvelope(DocusignHelpers.AccountId, envDef);
Caught Exception values
you are missing this line:
envDef.EmailSubject = "Test, please sign.";
But that's not the reason for the exception, since you created it as "created" (draft) mode, but it would be the issue once you try to send it.
You may want to confirm the values of all your recipients and ensure you're not sending something that's not an email (for example) in an email field etc.
I solved this friends.
My api url was incorrect.
My key confusion was that the auth endpoints have a separate base url than the rest of the RESTful API.
Authorization url for the demo was: https://account-d.docusign.com
The API client object actually has static fields that contain the urls for the different platforms demo, prod, staging.
I ended up using
ApiClient.Demo_REST_BasePath = "https://demo.docusign.net/restapi"
Thank you all for the replies and help
Related
I am using the Docusign eSign API for an integration. My integration key works fine with building and sending envelopes, and with checking envelope status (using GetEnvelope()). But ListRecipients() doesn't work. I have been following the documentation from here: https://developers.docusign.com/docs/esign-rest-api/how-to/get-envelope-recipients/.
My recipient-checking code is:
apiClient.Configuration.DefaultHeader.Add("Authorization", "Bearer " + authToken.access_token.ToString()); // I am suspicious of this line
var envelopesApi = new EnvelopesApi(apiClient);
foreach (var envelope in envelopes)
{
List<SignerModel> listSigners = new List<SignerModel>();
Recipients results = envelopesApi.ListRecipients(_apiAccountId, envelope.envelopeId.ToString());
// Do something with it...
}
When I run this with the suspicious line in place (un-commented) I get this error message at that line:
GetSigners error: Object reference not set to an instance of an object.
When I comment it out I get the same error message at the ListRecipients() call.
This is how I am getting my access token:
List<string> docusignScopes = new List<string> { "impersonation", "signature" };
apiClient = new ApiClient(_restBasePath);
authToken = apiClient.RequestJWTUserToken(
_clientId,
_impersonatedUserId,
_authServer,
privateKeyBytes, 1, docusignScopes);
Why is the listRecipients call not working?
I tested this code and it works just fine. Make sure to put your envelopeID in there. Try this basic code and let me know:
var apiClient = new ApiClient(basePath);
apiClient.Configuration.DefaultHeader.Add("Authorization", "Bearer " + accessToken);
EnvelopesApi envelopesApi = new EnvelopesApi(apiClient);
var rec = envelopesApi.ListRecipients(accountId, "4f925c10-xxxxxx-xxx-xxxx-xxxxxx");
I'm trying to apply a template (not use a template) using the .NET SDK and I can't seem to get it. I have seen one or two other articles on here but neither is using the SDK. Can anyone help me solve this using the SDK?
My situation is this: I have a template defined that contains all of my anchor tags with placement info. When I apply the template via the UI, it works fine and the tags get placed appropriately. When I upload the same document via the API, the tags are not applied.
I have tried to replicate what is shown in these articles using Composite Templates with no success:
How do I apply a server template to envelope document in DocuSign API?
Docusign API - Create envelope, apply template, prefill values
In one of the articles, the OP said the envelope needed to be a Draft. I tried that, but then I haven't been able to change it to "sent" after that.
Here's some of the relevant code from my ASP.NET Web Forms test project. In this project, I'm using a asp:FileUpload control to grab the file contents and then I call the SendFileToDocusign() method:
private void SendFileToDocusign(byte[] fileData, string accessToken)
{
//Create a signer recipient to sign the document, identified by name and email
//We set the clientUserId to enable embedded signing for the recipient
Signer tmpSigner1 = new Signer {
Email = "me#me.com", Name = "Test Tester",
ClientUserId = "1000", RecipientId = "1", RoleName = "Signer1", CustomFields = new List<string> { "Buyer1" }
};
//Step 1. Create the envelope definition
EnvelopeDefinition tmpEnvDef = MakeEnvelopeAndApplyTemplate(fileData, new List<Signer> { tmpSigner1 });
//Step 2. Call DocuSign to create the envelope
ApiClient tmpClient = new ApiClient(DOCUSIGN_API_BASEPATH);
tmpClient.Configuration.AddDefaultHeader("Authorization", "Bearer " + accessToken);
EnvelopesApi tmpEnvelopesApi = new EnvelopesApi(tmpClient);
EnvelopeSummary tmpResults = tmpEnvelopesApi.CreateEnvelope(DOCUSIGN_ACCOUNTID, tmpEnvDef);
string tmpEnvelopeID = tmpResults.EnvelopeId;
//Step 3. create the recipient view, the Signing Ceremony
RecipientViewRequest tmpViewRequest = MakeRecipientViewRequest(tmpSigner1);
//call the CreateRecipientView API
ViewUrl tmpRecipView = tmpEnvelopesApi.CreateRecipientView(DOCUSIGN_ACCOUNTID, tmpEnvelopeID, tmpViewRequest);
Response.Redirect(tmpRecipView.Url);
}
private EnvelopeDefinition MakeEnvelopeAndApplyTemplate(byte[] fileData, List<Signer> signers)
{
EnvelopeDefinition tmpEnv = new EnvelopeDefinition(EmailSubject:"We don't really use the Subject Line here");
Document tmpDoc = new Document();
Recipients tmpRecipients = new Recipients(Signers:signers);
CompositeTemplate tmpCompTemplate = new CompositeTemplate("1");
string tmpfileDataB64 = Convert.ToBase64String(fileData);
tmpDoc.DocumentBase64 = tmpfileDataB64;
tmpDoc.Name = "Test file";//can be different from actual file name
tmpDoc.FileExtension = "pdf";
tmpDoc.DocumentId = "1";
InlineTemplate tmpInlineTemplate = new InlineTemplate();
tmpInlineTemplate.Sequence = "1";
tmpInlineTemplate.Recipients = tmpRecipients;
ServerTemplate tmpServerTemplate = new ServerTemplate("2", DOCUSIGN_TEMPLATE_ID);
tmpCompTemplate.ServerTemplates = new List<ServerTemplate>() { tmpServerTemplate };
tmpCompTemplate.InlineTemplates = new List<InlineTemplate>() { tmpInlineTemplate };
tmpCompTemplate.Document = tmpDoc;
tmpEnv.CompositeTemplates = new List<CompositeTemplate>() { tmpCompTemplate };
//Request that the envelope be sent by setting |status| to "sent".
//To request that the envelope be created as a draft, set to "created"
tmpEnv.Status = "sent";
return tmpEnv;
}
Thanks for any help you can offer.
Your code has to handle the recipients correctly.
The roleName must match between recipients pre-defined in the template and the ones you add in your code.
I don't see in your code that part.
The example you use is for composite template. The relevant code for this is in a regular template example but it's the same.
https://github.com/docusign/code-examples-csharp/blob/master/launcher-csharp/eSignature/Controllers/Eg009UseTemplateController.cs
TemplateRole signer1 = new TemplateRole();
signer1.Email = signerEmail;
signer1.Name = signerName;
signer1.RoleName = "signer";
TemplateRole cc1 = new TemplateRole();
cc1.Email = ccEmail;
cc1.Name = ccName;
cc1.RoleName = "cc";
I have the following code for adding a new Envelope with a local file:
EnvelopeDefinition envelope = new EnvelopeDefinition
{
Status = "sent"
};
// Get the contract file
Byte[] bytes = File.ReadAllBytes("[Local Filename]");
// Add a document to the envelope
DocuSign.eSign.Model.Document doc = new DocuSign.eSign.Model.Document();
doc.DocumentBase64 = System.Convert.ToBase64String(bytes);
doc.Name = contract.FileName;
doc.DocumentId = "1";
envelope.Documents = new List<DocuSign.eSign.Model.Document>();
envelope.Documents.Add(doc);
// Add a recipient to sign the documeent
Signer signer = new Signer();
signer.Email = recipientEmail;
signer.Name = recipientName;
signer.RecipientId = "1";
// Create a |SignHere| tab somewhere on the document for the recipient to sign
signer.Tabs = new Tabs();
signer.Tabs.SignHereTabs = new List<SignHere>();
SignHere signHere = new SignHere();
signHere.DocumentId = "1";
signHere.PageNumber = "1";
signHere.RecipientId = "1";
signHere.XPosition = "100";
signHere.YPosition = "150";
signer.Tabs.SignHereTabs.Add(signHere);
envelope.Recipients = new Recipients();
envelope.Recipients.Signers = new List<Signer>();
envelope.Recipients.Signers.Add(signer);
DocuSignAuthentication Creds = new DocuSignAuthentication
{
Username = "[My Username]",
Password = "[My Password]",
IntegratorKey = "[My Integration Key]"
};
ApiClient apiClient = new ApiClient("https://demo.docusign.net/restapi/v2/accounts/XXXXXXX");
string authHeader = JsonConvert.SerializeObject(Creds);
DocuSign.eSign.Client.Configuration cfg = new DocuSign.eSign.Client.Configuration(apiClient);
cfg.AddDefaultHeader("X-DocuSign-Authentication", authHeader);
EnvelopesApi envelopeApi = new EnvelopesApi(cfg);
EnvelopeSummary response = envelopeApi.CreateEnvelope("XXXXXXX", envelope);
The server returns a very little information in the error:
[ApiException: Error calling CreateEnvelope: ]
DocuSign.eSign.Api.EnvelopesApi.CreateEnvelopeWithHttpInfo(String accountId, EnvelopeDefinition envelopeDefinition, CreateEnvelopeOptions options) in
Y:\dev\SDKs\csharp\sdk\src\main\csharp\DocuSign\eSign\Api\EnvelopesApi.cs:2606
DocuSign.eSign.Api.EnvelopesApi.CreateEnvelope(String accountId, EnvelopeDefinition envelopeDefinition, CreateEnvelopeOptions options) in Y:\dev\SDKs\csharp\sdk\src\main\csharp\DocuSign\eSign\Api\EnvelopesApi.cs:2532
[Rest of the stack trace relates to our code]
If we try to use fiddler to capture any error messages from the server, the error becomes:
Could not establish trust relationship for the SSL/TLS secure channel
Is there anyway to get a more information about what's wrong with our request? Or is there an un-encrypted developer endpoint available to work through these kinds of issues? Any help you can spare would be greatly appreciated.
The error "Could not establish trust relationship for the SSL/TLS secure channel" means that the HTTPRequest call from the client (which can be your server, but is a client in the sense that it made the HTTPRequest) to the server (DocuSign in this case) could not use TLS over SSL (https:// address) to ensure that there's a certificate that allows to encrypt the information in the HTTPRequest and HttpResponse. This can happen for a variety of reasons including not having the current version of TLS on the client as well as having the wrong certificate or other issues with the network. I would recommend trying to make this call from a different server, potentially outside your corporate network to isolate the problem. Also, check the version of TLS to ensure it's at least 1.1
I'm just trying to change a password of the main account and a sub user in RackSpaceCloud using C# but I keep running into a UserNotAuthorized exception. Its weird because I can do anything else without this error, reset Api keys, list users and userID's(etc.). Sample Code
net.openstack.Core.Domain.CloudIdentity cloudIdentity = new CloudIdentity()//Admin Credits
{
Username = "me",
APIKey = "blahblahblah",
};
CloudIdentityProvider cloudIdentityProvider = new CloudIdentityProvider(cloudIdentity);
cloudIdentityProvider.SetUserPassword("correctUserID", "newP#ssw0rd", cloudIdentity);
And then I error which is confusing because methods like,
cloudIdentityProvider.ListUsers(cloudIdentity)
cloudIdentityProvider.ResetApiKey("UserID", cloudIdentity);
Work Perfectly. Any Help or Ideas would be appreciated.
Oh and Btw the addition info on the exception is always the same. "Unable to authenticate user and retrieve authorized service endpoints"
This is a bug. I have opened issue 528 but in the meantime here is a workaround.
var cloudIdentity = new CloudIdentity
{
Username = "{username}",
APIKey = "{api-key}"
};
var cloudIdentityProvider = new CloudIdentityProvider(cloudIdentity);
var userAccess = cloudIdentityProvider.Authenticate(cloudIdentity);
var request = new HttpRequestMessage(HttpMethod.Post, string.Format("https://identity.api.rackspacecloud.com/v2.0/users/{0}", userAccess.User.Id));
request.Headers.Add("X-Auth-Token", userAccess.Token.Id);
var requestBody = JObject.FromObject(new { user = new { username = userAccess.User.Name } });
((JObject)requestBody["user"]).Add("OS-KSADM:password", "{new-password}");
request.Content = new StringContent(requestBody.ToString(), Encoding.UTF8, "application/json");
using (var client = new HttpClient())
{
var response = client.SendAsync(request).Result;
}
The cloud identity used must be an admin if you need to change another user's password, otherwise non-admins may only change their own password.
I'm attempting to consume a 3rd party WSDL. I have added it as a service reference. I initalize the client and query paramaters like this:
var ltRequest = new SearchEmailAddressStatus
{
EmailAddress = emailAddressList.ToArray()
};
var ltClient = new CommunicationPreferenceServiceClient
{
ClientCredentials =
{
UserName =
{
UserName = ltProperties.CompanyCredential.UserName,
Password = ltProperties.CompanyCredential.Password
}
}
};
var ltResponse = ltClient.searchEmailAddressStatusWS(ltRequest);
After watching the packets in Fiddler, I've noticed the Auth header is never sent to the server. Is there any way to manually insert an authorization header in my request?
Okay, after a lot of digging I found the answer. After declaring the client, I used the following code:
using (var scope = new OperationContextScope(ltClient.InnerChannel))
{
var reqProperty = new HttpRequestMessageProperty();
reqProperty.Headers[HttpRequestHeader.Authorization] = "Basic "
+ Convert.ToBase64String(Encoding.ASCII.GetBytes(
ltClient.ClientCredentials.UserName.UserName + ":" +
ltClient.ClientCredentials.UserName.Password));
OperationContext.Current
.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = reqProperty;
var ltResponse = ltClient.searchEmailAddressStatusWS(ltRequest);
}
I believe this is the least-dirty means of getting a customized header inside wsdl request. If someone has a better method, I'd love to hear it.