-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathRightSignatureAPI.cs
More file actions
435 lines (373 loc) · 18.8 KB
/
RightSignatureAPI.cs
File metadata and controls
435 lines (373 loc) · 18.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Net;
using System.IO;
using System.Text;
namespace RightSignature
{
public class RightSignatureAPI
{
string baseUrl;
string apiToken;
// response buffer
StringBuilder sb;
byte[] buf;
public static Boolean debug;
public RightSignatureAPI(string inputApiToken) {
// initialize response buffer
sb = new StringBuilder();
buf = new byte[8192];
baseUrl = "https://rightsignature.com";
apiToken = inputApiToken;
}
/*****************************************************************************
* Structs to help filing out documents
****************************************************************************/
// A Signer or CC of a Document
// name - name of the Person for the role
// email - email of the Person for the role
// locked - values can be changed
public struct RoleUser
{
public string name, email;
public Boolean locked; // If true, not allow the redirected user to modify the value
public RoleUser(string uName, string uEmail, Boolean isLocked) {
name = uName;
email = uEmail;
locked = isLocked;
}
}
public struct MergeField {
public string name, value;
public Boolean locked; // If true, not allow the redirected user to modify the value
public MergeField(string mName, string mValue, Boolean isLocked){
name = mName;
value = mValue;
locked = isLocked;
}
}
/******************************************************************************
* PRIVATE FUNCTIONS
******************************************************************************/
/******************************************************************************
* Gets Documents from API and returns response as XDocument
*
* query (optional) = Search term to narrow results. Should be URI encoded.
* ex. "State Street"
* state (optional) - Comma-joined Document states to filter results. States should be 'completed', 'pending', 'expired'.
* ex. "completed,pending"
* page (optional) - Page number offset. Default is 1.
* ex. 1
* perPage (optional) - number of result per page to return.
* Valid values are 10, 20, 30, 40, and 50. Default is 10.
* ex. 20
* recipientEmail (optional) = Narrow results to documents sent by RightSignature API User to the given Recipient Email.
* ex. "a@abc.com"
* tags (optional) - Dictionary tag names and values that are associated with documents.
* ex. Dictionary<string, string> tags = new Dictionary;
* tags.Add('customized', '')
* tags.Add('user id', '123')
******************************************************************************/
public XDocument GetDocuments(string query, string docStates, int? page, int? perPage, string recipientEmail, Dictionary<string, string> tags)
{
string urlPath = "/api/documents.xml";
string requestPath;
List<string> queryParams = new List<string>();
// Build up the URL request path parameters
if (query != null)
queryParams.Add("search=" + query);
if (docStates != null)
queryParams.Add("state=" + docStates);
if (page.HasValue)
queryParams.Add("page=" + page.ToString());
if (perPage.HasValue)
queryParams.Add("per_page=" + perPage.ToString());
if (recipientEmail != null)
queryParams.Add("recipient_email=" + recipientEmail.ToString());
// Creates parameter string for tags
if (tags != null)
queryParams.Add(CreateTagsParameter(tags));
// Creates URL path with query parameters in it
requestPath = CreateRequestPath(urlPath, queryParams);
// Creates HTTP Request and parses it as XDocument
return ParseResponseAsXML(HttpRequest(requestPath, "GET", null));
}
/******************************************************************************
* Gets Document details from API and returns response as XDocument
*
* guid - RightSignature Document GUID
* ex. 'J1KHD2NX4KJ5S6X7S8'
******************************************************************************/
public XDocument GetDocumentDetails(string guid)
{
return ParseResponseAsXML(HttpRequest("/api/documents/" + guid + ".xml", "GET", null));
}
/******************************************************************************
* Gets Documents from API and returns response as string
******************************************************************************/
public string GetDocumentsString()
{
return ParseResponseAsString(HttpRequest("/api/documents.xml", "GET", null));
}
/******************************************************************************
* Gets Templates from API and returns response as XDocument
*
* query (optional) = Search term to narrow results. Should be URI encoded.
* ex. "State Street"
* page (optional) - Page number offset. Default is 1.
* ex. 1
* perPage (optional) - number of result per page to return.
* Valid values are 10, 20, 30, 40, and 50. Default is 10.
* ex. 20
* tags (optional) - Dictionary tag names and values that are associated with documents.
* ex. Dictionary<string, string> tags = new Dictionary;
* tags.Add('test', null)
* tags.Add('user id', '123')
******************************************************************************/
public XDocument GetTemplates(string query, int? page, int? perPage, Dictionary<string, string> tags)
{
string urlPath = "/api/templates.xml";
string requestPath;
List<string> queryParams = new List<string>();
// Build up the URL request path parameters
if (query != null)
queryParams.Add("search=" + query);
if (page.HasValue)
queryParams.Add("page=" + page.ToString());
if (perPage.HasValue)
queryParams.Add("per_page=" + perPage.ToString());
// Creates parameter string for tags
if (tags != null)
queryParams.Add(CreateTagsParameter(tags));
// Creates URL path with query parameters in it
requestPath = CreateRequestPath(urlPath, queryParams);
// Creates HTTP Request and parses it as XDocument
return ParseResponseAsXML(HttpRequest(requestPath, "GET", null));
}
/******************************************************************************
* Gets Template details from API and returns response as XDocument
*
* guid - RightSignature Template GUID
* ex. 'A_123_J1KHD2NX4KJ5S6X7S8'
******************************************************************************/
public XDocument GetTemplateDetails(string guid)
{
return ParseResponseAsXML(HttpRequest("/api/templates/" + guid + ".xml", "GET", null));
}
/******************************************************************************
* Prepackages 1 or more Templates so it creates a RightSignature Document from the RightSignature Templates.
* Returns GUID for new Document
*
* guids - RightSignature Template GUID
* ex. 'A_123_J1KHD2NX4KJ5S6X7S8'
* callbackURL (optional) - URL to callback when the Document is created.
* If none is specified, the default in RightSignature's Account settings will be used
* ex. "http://mysite/template_callback.php"
******************************************************************************/
public string PrepackageTemplate(string[] guids, string callbackURL)
{
string guidsString = "";
foreach (string guid in guids) {
guidsString += guid;
guidsString += ",";
}
// XML body to POST to RightSignature API
string data = "<?xml version='1.0' encoding='UTF-8'?><template>";
if (callbackURL != null)
data += "<callback_location>" + callbackURL + "</callback_location>";
data += "</template>";
XDocument response = ParseResponseAsXML(HttpRequest("/api/templates/" + guidsString + "/prepackage.xml", "POST", data));
RightSignatureAPI.log("Prepackage Response\n" + response.ToString());
// TODO: Need to Check if there's an Error response in XML
return response.Element("template").Element("guid").Value;
}
/******************************************************************************
* Sends Document from API and returns response as XDocument
*
* guid - RightSignature's Dcoument GUID
* ex. "AKJ8CUID2D34TFS"
* roles - Dictionary of RoleUser structs with the Key being the Role Name in the Document:
* ex. Dictionary<string, string> roles = new Dictionary;
* tags.Add('Client', RoleUser("Tim Tam Timmy", "tim@example.com", true))
* tags.Add('CoSigner', RoleUser("Jim Jam Jammy", "jim@example.com", false))
* mergeFields - Array of MergeField structs the name must map to MergeField names in the Document.
* ex. [MergeField('Address', "123 Maple Lane", false)]
* tags (optional) - Dictionary tag names and values to associate with Document.
* ex. Dictionary<string, string> tags = new Dictionary;
* tags.Add('test', null)
* tags.Add('user id', '123')
* description (Optional) - description of document for signer to see
* callbackURL (Optional) - string of URL for RightSignature to POST document details to after Template gets created, viewed, and completed (all parties have signed).
* Tip: add a unique parameter in the URL to distinguish each callback, like the template_id.
* NULL will use the default callback url set in the RightSignature Account settings page (https://rightsignature.com/oauth_clients).
* ex. 'http://mysite/document_callback.php?template_id=123'
* expires_in (Optional) - integer of days to expire document, allowed values are 2, 5, 15, or 30.
******************************************************************************/
public XDocument SendDocument(string guid, string subject, Dictionary<string, RoleUser> roles, MergeField[] mergeFields, Dictionary<string, string> tags, string description, string callbackURL, int? expires_in)
{
string urlPath = "/api/templates.xml";
string requestPath;
List<string> queryParams = new List<string>();
XElement rootNode = new XElement("template");
XDocument xml = new XDocument(rootNode);
// Creates the xml body to send to API
rootNode.Add(new XElement("guid", guid));
rootNode.Add(new XElement("subject", subject));
rootNode.Add(new XElement("action", "send")); // Action can be 'send' or 'prefill'
if (description != null)
rootNode.Add(new XElement("description", description));
if (expires_in != null)
rootNode.Add(new XElement("expires_in", expires_in.ToString())); // Must be 2, 5, 15, or 30. Otherwise, API will default it to 30 days
// Create Roles XML
XElement rolesNode = new XElement("roles");
foreach (KeyValuePair<string, RoleUser> role in roles) {
XElement roleNode = new XElement("role");
roleNode.SetAttributeValue("role_name", role.Key);
roleNode.Add(new XElement("name", role.Value.name));
roleNode.Add(new XElement("email", role.Value.email));
roleNode.Add(new XElement("locked", role.Value.locked.ToString().ToLower()));
rolesNode.Add(roleNode);
}
rootNode.Add(rolesNode);
// Create mergefields XML
if (mergeFields != null)
{
XElement mfsNode = new XElement("merge_fields");
foreach (MergeField mergeField in mergeFields)
{
XElement mfNode = new XElement("merge_field");
mfNode.SetAttributeValue("merge_field_name", mergeField.name);
mfNode.Add(new XElement("value", mergeField.value));
mfNode.Add(new XElement("locked", mergeField.locked.ToString().ToLower()));
mfsNode.Add(mfNode);
}
rootNode.Add(mfsNode);
}
if (tags != null)
rootNode.Add(CreateTagsXML(tags));
if (callbackURL != null)
rootNode.Add(new XElement("callback_location", callbackURL));
RightSignature.RightSignatureAPI.log("Generated xml:\n~~~~~~~~~~~~\n" + xml.ToString() + "\n~~~~~~~~~~~~\n");
// Creates URL path with query parameters in it
requestPath = CreateRequestPath(urlPath, queryParams);
// Creates HTTP Request and parses it as XDocument
return ParseResponseAsXML(HttpRequest(requestPath, "POST", xml.ToString()));
}
/******************************************************************************
* STATIC FUNCTIONS
******************************************************************************/
private static void log(string message) {
if (debug)
Console.WriteLine(message);
}
/******************************************************************************
* PRIVATE FUNCTIONS
******************************************************************************/
// Converts a List and request path into one request path with paramters
private string CreateRequestPath(string path, List<string> parameters)
{
for (int i = 0; i < parameters.Count; i++)
{
path += i == 0 ? "?" : "&";
path += parameters[i];
}
return path;
}
// Converts Dictionary into tags parameter
private string CreateTagsParameter(Dictionary<string,string> tags) {
string tagsParam = "tags=";
int i = 0;
foreach (KeyValuePair<string, string> tag in tags)
{
if (i > 0)
tagsParam += ',';
if (tag.Value == null)
tagsParam += tag.Key;
else
tagsParam += tag.Key + ":" + tag.Value;
i++;
}
return tagsParam;
}
// Converts Dictionary into tags XML Element
private XElement CreateTagsXML(Dictionary<string, string> tags)
{
XElement tagsNode = new XElement("tags");
foreach (KeyValuePair<string, string> tag in tags)
{
XElement tagNode = new XElement("tag");
tagNode.Add(new XElement("name", tag.Key));
if (tag.Value != null)
tagNode.Add(new XElement("value", tag.Value));
tagsNode.Add(tagNode);
}
return tagsNode;
}
private XDocument ParseResponseAsXML(HttpWebResponse response) {
XmlReader xmlReader = XmlReader.Create(response.GetResponseStream());
XDocument xdoc = XDocument.Load(xmlReader);
xmlReader.Close();
return xdoc;
}
private string ParseResponseAsString(HttpWebResponse response) {
Stream resStream;
string tempString = null;
int count = 0;
RightSignatureAPI.log("Reading stream");
// we will read data via the response stream
resStream = response.GetResponseStream();
// fill the buffer with data
count = resStream.Read(buf, 0, buf.Length);
RightSignatureAPI.log("got " + count + " bytes of data");
do {
// read buffer
count = resStream.Read(buf, 0, buf.Length);
// make sure we read some data
if (count != 0)
{
// translate from bytes to ASCII text
tempString = Encoding.UTF8.GetString(buf, 0, count);
// continue building the string
sb.Append(tempString);
}
} while (count > 0); // any more data to read?
return sb.ToString();
}
/******************************************************************************
* Sends given path, method, and body to API and returns response.
* path - URL path
* ex. "/api/documents.xml"
* method - HTTP method
* ex. "GET"
* body - Request Body as string
* ex. "<document><guid>ZNMSDFLK1JBFD</guid></document>"
******************************************************************************/
private HttpWebResponse HttpRequest(string path, string method, string body) {
// Creates Request
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(baseUrl + path);
HttpWebResponse response;
// Adds Secure Token to Header
request.Headers.Add("api-token", apiToken);
request.Method = method;
if (method.Equals("POST")) {
request.ContentType = "text/xml;charset=utf-8";
if (body != null) {
request.ContentLength = body.Length;
// Writes data to request
using (Stream writeStream = request.GetRequestStream()) {
UTF8Encoding encoding = new UTF8Encoding();
byte[] bytes = encoding.GetBytes(body);
writeStream.Write(bytes, 0, bytes.Length);
}
}
}
// execute the request
RightSignatureAPI.log("Getting Request");
response = (HttpWebResponse)request.GetResponse();
return response;
}
}
}