Docusign Integration - docusignapi

I can't see Recipients in view(ListStatusChange), just the list of envelopes.
when I write (model.Recipients.Signers.First().Name) returns null
Just I can see model.envelopeId, Status, StatusDateChange. I passed the model IEnumerable (Envelope)
I used templates for send my documents, here is the envelope definition:
public void GenerateDocument(string name, string email)
{
var docuSignClient = new DocuSignClient();
var accountId = docuSignClient.LoginApi(username, password, integratorkey);
var templateRoles = templateRoleNames.Select(m => new TemplateRole
{
Email = email,
Name = name,
RoleName = m
}).ToList();
var envelope = new EnvelopeDefinition
{
EmailSubject = subject,
EmailBlurb = messageBody,
TemplateId = templateId,
TemplateRoles = templateRoles,
Status = "sent"
};
var envelopesApi = new EnvelopesApi();
var envelopesSummary = envelopesApi.CreateEnvelope(accountId, envelope);

You need to include recipients in the options for the ListStatusChanges request.
You didn't show this code, but here is what it may look like:
var apiClient = new ApiClient(basePath);
apiClient.Configuration.DefaultHeader.Add("Authorization", "Bearer " + accessToken);
var envelopesApi = new EnvelopesApi(apiClient);
ListStatusChangesOptions options = new ListStatusChangesOptions { include = "recipients" };
options.fromDate = DateTime.Now.AddDays(-30).ToString("yyyy/MM/dd");
// Call the API method:
EnvelopesInformation results = envelopesApi.ListStatusChanges(accountId, options);
return results;

Related

DocuSign createEnvelope Request Failed with 404 Error

I have been trying to create an envelope from a template using the Docusign SDK in Node.js, but no matter what API I try run, I get the error 404, with this Html code as a response.
I am including the code here:
const {email, name, templateId} = body;
const token = await DocuSign.token();
const dsAPIClient = new ApiClient();
dsAPIClient.setBasePath(DOCUSIGN_BASE_PATH as string);
dsAPIClient.addDefaultHeader('Authorization', `Bearer ${token}`);
const envelopeApi = new docusign.EnvelopesApi(dsAPIClient);
const envelope = this.makeEnvelope({email, name, templateId});
console.log(envelope);
// const result = await envelopeApi.createEnvelope(ACCOUNT_ID as string, {
// envelopeDefinition: {},
// });
const result = await axios.post(
`${DOCUSIGN_BASE_PATH}/v2.1/accounts/${ACCOUNT_ID}/envelopes`,
envelope,
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
// console.log('This is the result', result);
return result.data;
This is the error that I am getting, I get the same error on SDK and Axios both.
Symbol(kOutHeaders)]: [Object: null prototype]
' <h2>404 - File or directory not found.</h2>\r\n' +
' <h3>The resource you are looking for might have been removed, had its name changed, or is temporarily unavailable.</h3>\r\n' +
' </fieldset></div>\r\n' +
'</div>\r\n' +
'</body>\r\n' +
'</html>\r\n'
},
isAxiosError: true,
toJSON: [Function: toJSON]
Your code has the SDK code commented, so I'm not sure why you did this.
Here is code that works, you can find it in GitHub.
An even easier option is to use the quickstart.
let dsApiClient = new docusign.ApiClient();
dsApiClient.setBasePath(args.basePath);
dsApiClient.addDefaultHeader("Authorization", "Bearer " + args.accessToken);
let envelopesApi = new docusign.EnvelopesApi(dsApiClient),
results = null;
let envelope = makeEnvelope(args.envelopeArgs);
function makeEnvelope(args) {
let docPdfBytes;
docPdfBytes = fs.readFileSync(args.docFile);
let env = new docusign.EnvelopeDefinition();
env.emailSubject = "Please sign this document";
let doc1 = new docusign.Document(),
doc1b64 = Buffer.from(docPdfBytes).toString("base64");
doc1.documentBase64 = doc1b64;
doc1.name = "Lorem Ipsum"; // can be different from actual file name
doc1.fileExtension = "pdf";
doc1.documentId = "3";
env.documents = [doc1];
email
let signer1 = docusign.Signer.constructFromObject({
email: args.signerEmail,
name: args.signerName,
clientUserId: args.signerClientId,
recipientId: 1,
});
let signHere1 = docusign.SignHere.constructFromObject({
anchorString: "/sn1/",
anchorYOffset: "10",
anchorUnits: "pixels",
anchorXOffset: "20",
});
let signer1Tabs = docusign.Tabs.constructFromObject({
signHereTabs: [signHere1],
});
signer1.tabs = signer1Tabs;
let recipients = docusign.Recipients.constructFromObject({
signers: [signer1],
});
env.recipients = recipients;
env.status = "sent";
return env;
}

Docusign List Batch

What is the correct method for listing Batches? I used this method and it returns null.
public IEnumerable<BulkSendBatchSummary> ListBatchs(int numberOfItems)
{
var accessToken = docuSignClient.getTokenAccess(integratorKey, userId, authServer, basePath);
var apiClient = new ApiClient(basePath);
apiClient.Configuration.DefaultHeader.Add("Authorization", "Bearer " + accessToken);
var bulkEnvelopesApi = new BulkEnvelopesApi(apiClient);
var option = new BulkEnvelopesApi.GetBulkSendBatchesOptions
{
status = "all",
count = numberOfItems.ToString(),
};
IEnumerable<BulkSendBatchSummary> listeBatchs = bulkEnvelopesApi.GetBulkSendBatches(accountId, option).BulkBatchSummaries;
return listeBatchs;
}
Here is the correct C# code :
var apiClient = new ApiClient(basePath);
apiClient.Configuration.DefaultHeader.Add("Authorization", "Bearer " + accessToken);
var bulkEnvelopesApi = new BulkEnvelopesApi(apiClient);
bulkEnvelopesApi.GetBulkSendBatches(accountId);

User required to sign in before signing document

I am redirecting the user to docusign to sign their document. This is done with docusigns view request.
I would like the user to be required to sign in before signing.
I have been unable to find this in docusign documentation.
I did find this old stack overflow question Requiring DocuSign login to sign a document but the first link does not work.
Below is my code for the envelope creation
function makeEnvelope(args){
const env = new docusign.EnvelopeDefinition();
env.emailSubject = 'Please sign this document set';
// add 1 day reminder
const notification = new docusign.Notification();
notification.useAccountDefaults = 'false';
const reminders = new docusign.Reminders();
reminders.reminderEnabled = 'true';
reminders.reminderDelay = '1';
reminders.reminderFrequency = '1';
notification.reminders = reminders;
env.notification = notification;
const doc1 = new docusign.Document();
doc1.documentBase64 = Buffer.from(htmlPage(args.htmlArgs)).toString('base64');
doc1.name = args.documentName;
doc1.fileExtension = 'html';
doc1.documentId = '1';
env.documents = [doc1];
const signer1 = docusign.Signer.constructFromObject({
email: args.htmlArgs.submitterEmail,
name: args.htmlArgs.submitterName,
clientUserId: 1,
recipientId: 1,
routingOrder: 1 });
// Signer 2 is the supervisor. Gets sent the document after signer 1 signs
const signer2 = docusign.Signer.constructFromObject({
email: args.htmlArgs.supervisorEmail,
name: args.htmlArgs.supervisorName,
recipientId: 2,
routingOrder: 2 });
const signHere1 = docusign.SignHere.constructFromObject({
anchorString: '**signature_1**',
anchorYOffset: '10', anchorUnits: 'pixels',
anchorXOffset: '20'});
const signHere2 = docusign.SignHere.constructFromObject({
anchorString: '**signature_2**',
anchorYOffset: '10', anchorUnits: 'pixels',
anchorXOffset: '20'});
// Tabs are set per recipient / signer
signer1.tabs = docusign.Tabs.constructFromObject({
signHereTabs: [signHere1]});
signer2.tabs = docusign.Tabs.constructFromObject({
signHereTabs: [signHere2]});
env.recipients = docusign.Recipients.constructFromObject({
signers: [signer1, signer2],
});
env.status = args.status;
return env;
}
Here is the view request code
recipientView.controller = async (args) => {
const viewRequest = new docusign.RecipientViewRequest();
viewRequest.returnUrl = args.dsReturnUrl;
viewRequest.authenticationMethod = 'none';
viewRequest.email = args.signerEmail;
viewRequest.userName = args.signerName;
viewRequest.clientUserId = args.signerClientId;
viewRequest.authenticationMethod = 'Email';
return await recipientView.worker(viewRequest, args);
}
recipientView.worker = async (viewRequest, args) =>{
const dsApiClient = new docusign.ApiClient();
dsApiClient.setBasePath(args.basePath);
dsApiClient.addDefaultHeader('Authorization', 'Bearer ' + args.accessToken);
const envelopesApi = new docusign.EnvelopesApi(dsApiClient)
const results = await envelopesApi.createRecipientView(args.accountId, args.envelopeId, {recipientViewRequest: viewRequest});
return results.url;
}
I have tried different values for viewRequest.authenticationMethod
Nothing seems to work.
If you want signers to authenticate to DocuSign - they must have a membership in some DocuSign account. You cannot know or check if they do, so this method is not useful unless the envelopes are only sent within an organization to a fixed number of individuals that you know are members of the DocuSign account.
However, there are other ways to require recipient authentication and increase security over email. You can use SMS authentication, KBI or IDV for example. Read about how to use them in this blog post about recipient authentication.

How to request OAuth2 token to kong plugin

i am following this tutorial https://medium.com/#far3ns/kong-oauth-2-0-plugin-38faf938a468 and when i request the tokens with
Headers: Content-Type:application/json
Host:api.ct.id
Body:
{
“client_id”: “CLIENT_ID_11”,
“client_secret”: “CLIENT_SECRET_11”,
“grant_type”: “password”,
“provision_key”: “kl3bUfe32WBcppmYFr1aZtXxzrBTL18l”,
“authenticated_userid”: “oneone#gmail.com”,
“scope”: “read”
}
it returns
{
"error_description": "Invalid client authentication",
"error": "invalid_client"
}
no matter what i tried i couldn't fix it, any idea how to make it work properly
You need to create kong developer and it will give you client_id and client_secret_Id. Use those values in generating auth token.
Here is the working c# code.
Option 1
public static string GetOAuthToken(string url, string clientId, string clientSecret, string scope = "all", string grantType = "client_credentials")
{
try
{
string token = "";
if (string.IsNullOrWhiteSpace(url)) throw new ArgumentException("message", nameof(url));
if (string.IsNullOrWhiteSpace(clientId)) throw new ArgumentNullException("message", nameof(clientId));
if (string.IsNullOrWhiteSpace(clientSecret)) throw new ArgumentNullException("message", nameof(clientSecret));
var oAuthClient = new RestClient(new Uri(url));
var request = new RestRequest("Authenticate", Method.POST);
request.AddHeader("Content-Type", "application/json");
var credentials = new
{
grant_type = grantType,
scope = scope,
client_id = clientId,
client_secret = clientSecret
};
request.AddJsonBody(credentials);
var response = oAuthClient?.Execute(request);
var content = response?.Content;
if (string.IsNullOrWhiteSpace(content)) throw new ArgumentNullException("message", nameof(clientSecret));
token = content?.Trim('"');
return token;
}
catch (Exception ex)
{
throw new Exception(ex.Message,ex);
}
}
Option 2
var httpClient = new HttpClient()
var creds = $"client_id={client_id}&client_secret{client_secret}&grant_type=client_credentials";
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
var content = new StringContent(creds, Encoding.UTF8, "application/x-www-form-urlencoded");
var response = httpClient.PostAsync("https://myorg/oauth/oauth2/cached/token", content).Result;
var OAuthBearerToken = response.Content.ReadAsStringAsync().Result;

Update Azure AD Application keys or secrets using Microsoft Graph API - BadRequest Error

I am trying to patch password credentials for an application using Microsoft Graph API beta endpoint for application resource type.
https://graph.microsoft.com/beta/applications/{applicationId}
The content variable is a JSON-serialized representation of something like this:
[{
"customKeyIdentifier":null,
"endDateTime":"2019-11-19T23:16:24.2602448Z",
"keyId":"47fde652-8b60-4384-b630-8e5f8f6e24b1",
"startDateTime":"2018-11-19T23:16:24.2602448Z",
"secretText":"SomeGeneratedPassword",
"hint":null
}]
Calling code is this:
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("https://graph.microsoft.com");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authHeaderValue.Result.AccessToken);
client.DefaultRequestHeaders
.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var method = new HttpMethod("PATCH");
var requestUri = $"https://graph.microsoft.com/beta/applications/{applicationId}";
var content = GeneratePasswordCredentials(passwordHint);
var request = new HttpRequestMessage(method, requestUri)
{
Content = new StringContent(
content,
System.Text.Encoding.UTF8,
"application/json")
};
request.Headers
.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var resultApi = await client.SendAsync(request);
response = await resultApi.Content.ReadAsStringAsync();
}
Auth appears to be working fine, but the response is this (inner error removed for brevity):
{
"error": {
"code": "BadRequest",
"message": "Empty Payload. JSON content expected.",
}
}
What is wrong with the above code?
The body content format should be
{
"passwordCredentials":
[
{"customKeyIdentifier":"YWJjZA==",
"startDateTime":"2018-11-20T02:37:07.3963006Z",
"endDateTime":"2019-11-20T02:37:07.3963006Z",
"secretText":"The passwords must be 16-64 characters in length",
"keyId":"aeda515d-dc58-4ce6-a452-3bc3d84f58a3",
"hint":"xxx"}
]
}
The following the demo code to Generate PasswordCredentials body content
public static string GeneratePasswordCredentials(string passwordHint)
{
var passwordCredential = new JObject
{
new JProperty("customKeyIdentifier",Encoding.UTF8.GetBytes(passwordHint)),
new JProperty("startDateTime",DateTime.UtcNow),
new JProperty("endDateTime", DateTime.UtcNow.AddYears(1)),
new JProperty("secretText", "The passwords must be 16-64 characters in length"),
new JProperty("keyId", Guid.NewGuid().ToString()),
new JProperty("hint", passwordHint)
};
JArray jArray = new JArray
{
passwordCredential
};
var jsonObject = new JObject
{
new JProperty("passwordCredentials",jArray)
};
var json = JsonConvert.SerializeObject(jsonObject);
return json;
}
Note: The request url should be $"https://graph.microsoft.com/beta/applications/{ApplicationObjectId}"
The issue is with JSON string specified for Update Application Microsoft Graph API. It's missing which property you're trying to update for the application. I've added "passwordCredentials" property and given it the JSON as a collection. See jsonContent variable at the very beginning of my code.
/*Only change here from original JSON is to add the passwordCredentials node*/
{
"passwordCredentials":[
{
"customKeyIdentifier": null,
"endDateTime": "2019-11-19T23:16:24.2602448Z",
"keyId": "47fde652-8b60-4384-b630-8e5f8f6e24b1",
"startDateTime": "2018-11-19T23:16:24.2602448Z",
"secretText": "SomeGeneratedPassword",
"hint": null
}
]
}
I started with your code and the 400 bad response error reproduced for me as well.
Below is the final working code and now I get back a 204 response status. I can also see the new key added to Application keys collection from Azure Portal > App Registrations > My app > Settings > Keys
string jsonContent = "{\"passwordCredentials\":[{\"customKeyIdentifier\":null,\"endDateTime\":\"2019-11-19T23:16:24.2602448Z\",\"keyId\":\"47fde652-8b60-4384-b630-8e5f8f6e24b1\",\"startDateTime\":\"2018-11-19T23:16:24.2602448Z\",\"secretText\":\"somegeneratedpassword\",\"hint\":null}]}";
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("https://graph.microsoft.com");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authHeaderValue.Result.AccessToken);
client.DefaultRequestHeaders
.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var method = new HttpMethod("PATCH");
var requestUri = $"https://graph.microsoft.com/beta/applications/{applicationId}";
// I have commented out this method and passed in my JSON instead.
//var content = GeneratePasswordCredentials(passwordHint);
var content = jsonContent;
var request = new HttpRequestMessage(method, requestUri)
{
Content = new StringContent(
content,
System.Text.Encoding.UTF8,
"application/json")
};
request.Headers
.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var resultApi = client.SendAsync(request).GetAwaiter().GetResult();
//response = await resultApi.Content.ReadAsStringAsync();
var response = resultApi.Content.ReadAsStringAsync().GetAwaiter().GetResult();
}

Resources