Getting error while using DocuSign in DotNet application - asp.net-mvc

I am implementing the DocuSign functionality in my application to sign the PDF.
I am following the below link:
https://www.docusign.com/developer-center/api-overview
We are able to add signature in the PDF while using the steps mentioned in the above link but while calling the same method for second time to signed a new PDF we are getting error message at the line of CreateEnvelope()
Error Response: { "errorCode": "UNSPECIFIED_ERROR", "message":
"Input string was not in a correct format." }
it generate an error while Creating envelop. at this line
EnvelopeSummary envelopeSummary = envelopesApi.CreateEnvelope(accountId, envDef);
Below is the code which i use
static string userName = Utility.GetConfigValue("docSignUserName");
static string password = Utility.GetConfigValue("docSignPassword");
static string integratorKey = Utility.GetConfigValue("docSignIntegratorKey");
static string baseURL = "";
public static SignedPDF SignDocument(UserViewModel user, StateViewModel state, string signFilePath, string newFilePath, string controlSign)
{
PdfReader pdfReader = new PdfReader(signFilePath);
PdfReader newpdfReader = new PdfReader(newFilePath);
PdfStamper pdfStamper = new PdfStamper(newpdfReader, new FileStream(HttpContext.Current.Server.MapPath(Utility.GetConfigValue("StateTaxForms")) + "Test.pdf", FileMode.Create));
AcroFields pdfFormFields = pdfStamper.AcroFields;
IList<AcroFields.FieldPosition> fieldPositions = pdfFormFields.GetFieldPositions(controlSign);
try
{
AcroFields.FieldPosition fieldPosition = fieldPositions[0];
// Enter recipient (signer) name and email address
string recipientName = user.FirstName + " " + user.LastName;
string recipientEmail = user.Email;
// instantiate api client with appropriate environment (for production change to www.docusign.net/restapi)
string basePath = Utility.GetConfigValue("docSignInstantiateClient");
// instantiate a new api client
ApiClient apiClient = new ApiClient(basePath);
// set client in global config so we don't need to pass it to each API object
Configuration.Default.ApiClient = apiClient;
string authHeader = "{\"Username\":\"" + userName + "\", \"Password\":\"" + password + "\", \"IntegratorKey\":\"" + integratorKey + "\"}";
Configuration.Default.AddDefaultHeader("X-DocuSign-Authentication", authHeader);
// we will retrieve this from the login() results
string accountId = null;
// the authentication api uses the apiClient (and X-DocuSign-Authentication header) that are set in Configuration object
AuthenticationApi authApi = new AuthenticationApi();
LoginInformation loginInfo = authApi.Login();
// user might be a member of multiple accounts
accountId = loginInfo.LoginAccounts[0].AccountId;
// Read a file from disk to use as a document
byte[] fileBytes = File.ReadAllBytes(signFilePath);
EnvelopeDefinition envDef = new EnvelopeDefinition();
envDef.EmailSubject = "Please sign this document";
// Add a document to the envelope
Document doc = new Document();
doc.DocumentBase64 = System.Convert.ToBase64String(fileBytes);
doc.Name = "SignedFile.pdf";
doc.DocumentId = "1";
envDef.Documents = new List<Document>();
envDef.Documents.Add(doc);
// Add a recipient to sign the documeent
Signer signer = new Signer();
signer.Name = recipientName;
signer.Email = recipientEmail;
signer.RecipientId = "1";
// must set |clientUserId| to embed the recipient
signer.ClientUserId = "1234";
// 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();
var height = pdfReader.GetPageSize(1).Height;
signHere.DocumentId = "1";
signHere.RecipientId = "1";
signHere.PageNumber = Convert.ToInt32(fieldPosition.page).ToString();
signHere.XPosition = Convert.ToInt32(fieldPosition.position.Left).ToString();
if (state.Abbreviation == "DC" && controlSign != "Signature of Employee")
{
signHere.YPosition = (height - Convert.ToInt32(fieldPosition.position.Top - 5)).ToString();
}
else
{
signHere.YPosition = (height - Convert.ToInt32(fieldPosition.position.Top + 35)).ToString();
}
if (state.Abbreviation == "NC" && controlSign != "Signature of Employee")
{
signHere.YPosition = (height - Convert.ToInt32(fieldPosition.position.Top + 25)).ToString();
}
signer.Tabs.SignHereTabs.Add(signHere);
envDef.Recipients = new Recipients();
envDef.Recipients.Signers = new List<Signer>();
envDef.Recipients.Signers.Add(signer);
// set envelope status to "sent" to immediately send the signature request
envDef.Status = "sent";
// Use the EnvelopesApi to create and send the signature request
EnvelopesApi envelopesApi = new EnvelopesApi();
EnvelopeSummary envelopeSummary = envelopesApi.CreateEnvelope(accountId, envDef);
RecipientViewRequest viewOptions = new RecipientViewRequest()
{
ReturnUrl = Utility.GetConfigValue("docSignReturnURL"),
ClientUserId = "1234", // must match clientUserId set in step #2!
AuthenticationMethod = "email",
UserName = recipientName,
Email = recipientEmail
};
// create the recipient view (aka signing URL)
ViewUrl recipientView = envelopesApi.CreateRecipientView(accountId, envelopeSummary.EnvelopeId, viewOptions);
// Start the embedded signing session!
//var value = System.Diagnostics.Process.Start(recipientView.Url);
SignedPDF signedPDF = new SignedPDF();
signedPDF.URL = recipientView.Url;
signedPDF.EnvelopeID = envelopeSummary.EnvelopeId;
return signedPDF;
}
catch (Exception ex)
{
throw new PDFSignException(ErrorConstants.THERE_WAS_AN_ERROR_WHILE_SIGNING_PDF);
}
finally
{
pdfStamper.Close();
pdfReader.Close();
}
}
Hi CodingDawg this is the JSON
{
"documents": [
{
"documentBase64": "",
"documentId": "1",
"name": "SignedFile.pdf"
}
],
"emailSubject": "Please sign this document",
"recipients": {
"signers": [
{
"clientUserId": "1234",
"email": "sagar.mali#tudip.com",
"name": "Sagar Mali",
"recipientId": "1",
"tabs": {
"signHereTabs": [
{
"documentId": "1",
"pageNumber": "1",
"recipientId": "1",
"xPosition": "192",
"yPosition": "679.968"
}
]
}
}
]
},
"status": "sent"
}
We have removed the base 64 string as the length was not supporting.

Make sure the signHere.XPosition & signHere.YPosition values are passed correctly.
The following statement could evaluate to a decimal value. Make sure it is an integer.
signHere.YPosition = (height - Convert.ToInt32(fieldPosition.position.Top + 25)).ToString();
Troubleshooting Step
Please run envelopeDefinition.ToJson() (Sdk documentation) and make sure the final Json posted to the DocuSign api is correct.

Related

Bad request when posting to OData Data Entity in Dynamics 365

I've created a public Data Entity in dynamics with the following fields:
I keep getting a bad request response, but I'm not sure why.
I've tried to make a POST request in two ways:
1.
HireAction hireAction = new HireAction() { CompanyName = "DEMF", MovieId = "DEMF-000000014", HireActionStatus = "Created" };
string jsonMessage = JsonConvert.SerializeObject(hireAction);
using (HttpClient client = new HttpClient())
{
HttpRequestMessage requestMessage = new
HttpRequestMessage(HttpMethod.Post, "MyDynamicsEnvironmentName/data/HireActions?cross-company=true");
requestMessage.Content = new StringContent(jsonMessage, Encoding.UTF8, "application/json");
requestMessage.Headers.Add("Authorization", AuthResult.AuthorizationHeader);
HttpResponseMessage response = client.SendAsync(requestMessage).Result;
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
//Logic
}
}
var url = "MyDynamicsEnvironmentName/data/HireActions?cross-company=true";
var req = HttpWebRequest.Create(url);
req.Method = "POST";
req.ContentType = "application/json";
req.Headers["Authorization"] = AuthResult.AuthorizationHeader;
HireAction hireAction = new HireAction() { CompanyName = "DEMF", MovieId = "DEMF-000000014", HireActionId = "12345", HireActionStatus = "Created" };
var jsonSettings = new JsonSerializerSettings
{
DateTimeZoneHandling = DateTimeZoneHandling.Local
};
var postString = "CompanyName='DEMF'" + "&MovieId='DEMF-000000014'" + "&HireActionId=132&HireActionStatus='Created'";
var data = JsonConvert.SerializeObject(postString, jsonSettings);
var bytes = Encoding.Default.GetBytes(postString);
var newStream = req.GetRequestStream();
newStream.Write(bytes, 0, bytes.Length);
newStream.Close();
using (var resp = req.GetResponse())
{
var results = new StreamReader(resp.GetResponseStream()).ReadToEnd();
}
Some keypoints:
-Of course you'd replace MyDynamicsEnvironmentName with the URL for the environment. The URL is correct and verified however, by the fact that GET requests do work
-The Authresult.AuthorizationHeader contains a valid token, also validated by working GET requests
As said before, both of these result in a bad request. Does someone know what is wrong or missing?

MS Graph create event 400 bad request

I have code that get's the default calendar and stores the id in a variable called calendar id. I then I then get a list of availabilities (which are events in our system) the end time and the start time are recorded in utc and I want to put those events into an office 365 calendar.
This is my code which is generating and 400 Bad request. Does anyone have any idea what I am doing wrong?
using (HttpClient httpClient = new HttpClient())
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", msBearerToken);
var callJson = new
{
Subject = "Booking",
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = "Available"
},
Start = new DateTimeTimeZone
{
DateTime = availabilitySummery.StartDateUTC.ToString(),
TimeZone = "Europe/London"
},
End = new DateTimeTimeZone
{
DateTime = availabilitySummery.EndDateUTC.ToString(),
TimeZone = "Europe/London"
}
};
string path = $"/me/calendars/{calendarId}/events";
// string path = "/me/calendars/events";
path = "https://graph.microsoft.com/v1.0" + path;
HttpResponseMessage responseMessage = await httpClient.PostAsJsonAsync(path, callJson);}
Date should be ISO8601 formatted.
Replace .ToString() by .ToString("o") when you want to convert dates to string.
Ref: The round-trip ("O", "o") format specifier
And createdDateTime property of event object
Update: This worked:
using (HttpClient httpClient = new HttpClient())
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", msBearerToken);
var callJson = new
{
Subject = "Booking",
Body = new
{
ContentType = BodyType.Html.ToString(),
Content = "Available"
},
Start = new
{
DateTime = availabilitySummery.StartDateUTC.ToString("yyyy-MM-ddTHH:mm:ss"),
TimeZone = "GMT Standard Time"
},
End = new
{
DateTime = availabilitySummery.EndDateUTC.ToString("yyyy-MM-ddTHH:mm:ss"),
TimeZone = "GMT Standard Time"
}
};
string path = $"/me/calendars/{calendarId}/events";
string jsoncall = JsonConvert.SerializeObject(callJson);
path = "https://graph.microsoft.com/v1.0" + path;
HttpResponseMessage responseMessage = await httpClient.PostAsJsonAsync(path, callJson);
string content = await responseMessage.Content.ReadAsStringAsync();
if (!responseMessage.IsSuccessStatusCode)
{
return false;
}
}

How to get certificate for Azure Automation Client

I need to create automaion client for Azure webhook.
Following code is written by me to get AutomationManagementClient Value.
var cert = new X509Certificate2(Convert.FromBase64String(ConfigurationManager.AppSettings["CertBase64String"]));
var creds[![enter image description here][1]][1] = new CertificateCloudCredentials(ConfigurationManager.AppSettings["SubscriptionId"], cert);
AutomationManagementClient automationManagementClient = new AutomationManagementClient(creds);
I need that certificate string i.e. CertBase64String value as I don't know from where I will get that value.
Help me...
This error I am getting after updating as per your answer.
If you want to create the automation client, I suggest you try to use the ARM way to operate the automation. The following is the demo code works correctly on my side.
Prepare: Registry an AD application and assign role to applcation, more details please refer to Azure official tutorials. After that we can get tenantId, appId, secretKey from the Azure Portal.
We could use the following code to get the token
var tenantId = "tenantId";
var context = new AuthenticationContext($"https://login.windows.net/{tenantId}");
var clientId = "application Id";
var clientSecret = "client secret";
var resourceGroup = "resource group";
var automationAccount = "automationAccount";
var subscriptionId = "susbscriptionId";
var token = context.AcquireTokenAsync(
"https://management.azure.com/",
new ClientCredential(clientId, clientSecret)).Result.AccessToken;
if you use the Microsoft.Azure.Management.Automation Version <= 2.0.4 please try the following code.
var automationClient = new AutomationManagementClient(new TokenCloudCredentials(subscriptionId,token));
var webhook = automationClient.Webhooks.CreateOrUpdate(resourceGroup, automationAccount,new WebhookCreateOrUpdateParameters
{
Properties = new WebhookCreateOrUpdateProperties
{
ExpiryTime = DateTimeOffset.Now.AddDays(1),
IsEnabled = false,
Parameters = parameters,
Runbook = new RunbookAssociationProperty
{
Name = "xxxx"
},
Name = "xxxx",
Uri = "https://xxxx.xx"
}
});
if use the Microsoft.Azure.Management.Automation Version 3.0.0-preview, please try to the following case.
var automationClient = new AutomationClient(new TokenCredentials(token)) {SubscriptionId = subscriptionId};
var webhook = automationClient.Webhook.CreateOrUpdate(resourceGroup, automationAccount, "webhookName",
new WebhookCreateOrUpdateParameters
{
ExpiryTime = DateTime.Now.AddDays(1),
IsEnabled = false,
Parameters = parameters,
Name = "xxxxx",
Runbook = new RunbookAssociationProperty
{
Name = "xxxxx"
},
Uri = "https://xxx.xxx"
});
Update:
You could set the Parameters = null or if you have parameter, you could define the parameters as dictionary. Please also add the Name = "xxxx" in the code.
var parameters = new Dictionary<string, string> {{"test", "test"}};
var webhook = automationClient.Webhooks.CreateOrUpdate(resourceGroup, automationAccount,new WebhookCreateOrUpdateParameters
{
Properties = new WebhookCreateOrUpdateProperties
{
ExpiryTime = DateTimeOffset.Now.AddDays(1),
IsEnabled = false,
Parameters = parameters,
Runbook = new RunbookAssociationProperty
{
Name = "xxxx"
},
Name = "xxxx",
Uri = "https://xxxx.xx"
}
});
I test it on my side, it works correctly
"CertBase64String" will get by passing thumb-print of that certificate to following fucntion.
internal static X509Certificate2 GetCertificateFromthumbPrint(String certThumbPrint) {
X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
certStore.Open(OpenFlags.ReadOnly);
//Find the certificate that matches the thumbprint.
X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, certThumbPrint, false);
certStore.Close();
//Get the first cert with the thumbprint
X509Certificate2 cert = (certCollection.Count > 0) ? certCollection[0] : null;
return cert;
}

FCM custom notification for ios

I know this question have been ask a lot of time in android but not ios. So I already test out push notification with FCM it work fine. Mine problem is wether it's a way to create custom notification rather than letting the system to handle the notification with the notification payload?
-Users can send data messages with FCM.What you have to send is,
Sample PostMan Json data:
{ "data": {
"any key": "any value",
"any key 2": "any value 2"
},
"to" : "token received to mobile from FCM"
}
Payload inside "data" can change according to the requirement.
Mobile end:
application(_:didReceiveRemoteNotification:) override method will get fire.So it is unto developer to extract data from the userInfo property in iOS and use it.
For ios using c# working code:-
public bool NotificationToiosDevice()
{
bool str;
try
{
//Create the web request with fire base API
WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
tRequest.Method = "post";
//serverKey - Key from Firebase cloud messaging server
tRequest.Headers.Add(string.Format("Authorization: key={0}", "AAAALNl-P7o:APA91bE38khU73UTdIj7L6LvVS3uI6f47REmxl.................................."));
//Sender Id - From firebase project setting
tRequest.Headers.Add(string.Format("Sender: id={0}", "12345"));
tRequest.ContentType = "application/json";
var payload = new
{
to = "dDDbFltwE5o:APA91bFmZZ-c1pNp................",
priority = "high",
content_available = true,
notification = new
{
title = "Title Of Notification",
},
data = new
{
body = new { Parameter1 = "FirstParameterValue", Parameter2 = "SecondParameterValue" },
},
};
string jsonNotificationFormat = Newtonsoft.Json.JsonConvert.SerializeObject(payload);
Byte[] byteArray = Encoding.UTF8.GetBytes(jsonNotificationFormat);
tRequest.ContentLength = byteArray.Length;
using (Stream dataStream = tRequest.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
using (WebResponse tResponse = tRequest.GetResponse())
{
using (Stream dataStreamResponse = tResponse.GetResponseStream())
{
if (dataStreamResponse != null) using (StreamReader tReader = new StreamReader(dataStreamResponse))
{
String sResponseFromServer = tReader.ReadToEnd();
// str = sResponseFromServer;
}
}
}
}
str = true;
}
catch (Exception ex)
{
str = false;
}
return str;
}

IMAP OAuth2 with Chilkat

I was looking for a way to Authenticate an IMAP session with google's Service account
But Since we already use Chilkat how do we do it, I found the following:
http://www.cknotes.com/imap-authentication-using-oauth/
allowing me to send a raw command:
imap.SendRawCommand("AUTHENTICATE XOAUTH <base64_data>");
This shows how to strucure the command:
https://developers.google.com/gmail/xoauth2_protocol
But having trouble putting it all together.
limilabs puts things together nicely in this example:
http://www.limilabs.com/blog/oauth2-gmail-imap-service-account
They have a neat imap.LoginOAUTH2(userEmail, credential.Token.AccessToken); that wraps things up into a command. How do I do this as a raw command for Chilkat?
const string serviceAccountEmail = "service-account-xxxxxx#developer.gserviceaccount.com";
const string serviceAccountCertPath = #"service-xxxxxx.p12";
const string serviceAccountCertPassword = "notasecret";
const string userEmail = "user#domain.com";
X509Certificate2 certificate = new X509Certificate2(
serviceAccountCertPath,
serviceAccountCertPassword,
X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { "https://mail.google.com/" },
User = userEmail
}.FromCertificate(certificate));
bool success = credential.RequestAccessTokenAsync(CancellationToken.None).Result;
using (Chilkat.Imap imap = new Chilkat.Imap())
{
imap.UnlockComponent("unlock-code");
imap.Ssl = true;
imap.Port = 993;
imap.Connect("imap.gmail.com");
var authString = String.Format("user={0}" + "\x001" + "auth=Bearer {1}" + "\x001" + "\x001",userEmail, credential.Token.AccessToken);
var encoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(authString));
string response = imap.SendRawCommand("AUTHENTICATE XOAUTH2 " + encoded);
imap.SelectMailbox("Inbox");
bool bUid;
bUid = false;
string mimeStr;
int i;
int n;
n = imap.NumMessages;
for (i = 1; i <= n; i++)
{
// Download the email by sequence number.
mimeStr = imap.FetchSingleAsMime(i, bUid);
Chilkat.Email chilkatEmail = new Chilkat.Email();
chilkatEmail.SetFromMimeText(mimeStr);
Console.WriteLine(chilkatEmail.Subject);
}
imap.CloseMailbox("Inbox");
Console.ReadLine();
}
}

Resources