docusign_rest 0.0.9 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,23 +2,27 @@
2
2
  require File.expand_path('../lib/docusign_rest/version', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |gem|
5
- gem.authors = ["Jon Kinney"]
6
- gem.email = ["jonkinney@gmail.com"]
5
+ gem.authors = ['Jon Kinney']
6
+ gem.email = ['jonkinney@gmail.com']
7
7
  gem.description = %q{Hooks a Rails app up to the DocuSign service through the DocuSign REST API}
8
8
  gem.summary = %q{Use this gem to embed signing of documents in a Rails app through the DocuSign REST API}
9
- gem.homepage = "https://github.com/j2fly/docusign_rest"
9
+ gem.homepage = "https://github.com/jondkinney/docusign_rest"
10
10
 
11
11
  gem.files = `git ls-files`.split($\)
12
12
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
13
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
- gem.name = "docusign_rest"
15
- gem.require_paths = ["lib"]
14
+ gem.name = 'docusign_rest'
15
+ gem.require_paths = ['lib']
16
16
  gem.version = DocusignRest::VERSION
17
17
 
18
- gem.add_dependency('multipart-post', '>= 1.1.5')
18
+ gem.required_ruby_version = '>= 1.9.2'
19
+
20
+ gem.add_dependency('multipart-post', '>= 1.2')
19
21
  gem.add_dependency('json')
20
22
  gem.add_development_dependency('rake')
21
- gem.add_development_dependency('minitest')
23
+ gem.add_development_dependency('minitest', '~>4.0')
24
+ gem.add_development_dependency('guard-minitest')
25
+ gem.add_development_dependency('rb-fsevent', '~> 0.9')
22
26
  gem.add_development_dependency('turn')
23
27
  gem.add_development_dependency('pry')
24
28
  gem.add_development_dependency('vcr')
@@ -0,0 +1,41 @@
1
+ require_relative '../lib/docusign_rest'
2
+
3
+ DocusignRest.configure do |config|
4
+ config.username = 'jonkinney@gmail.com'
5
+ config.password = 'MnUWneAH3xqL2G'
6
+ config.integrator_key = 'NAXX-93c39e8c-36c4-4cb5-8099-c4fcedddd7ad'
7
+ config.account_id = '327367'
8
+ config.endpoint = 'https://demo.docusign.net/restapi'
9
+ config.api_version = 'v2'
10
+ end
11
+
12
+ client = DocusignRest::Client.new
13
+
14
+ response = client.create_envelope_from_document(
15
+ email: {
16
+ subject: 'Test email subject',
17
+ body: 'This is the email body.'
18
+ },
19
+ # If embedded is set to true in the signers array below, emails don't go out
20
+ # and you can embed the signature page in an iFrame by using the
21
+ # get_recipient_view method
22
+ signers: [
23
+ {
24
+ #embedded: true,
25
+ name: 'Test Guy',
26
+ email: 'someone@example.com'
27
+ },
28
+ {
29
+ #embedded: true,
30
+ name: 'Test Girl',
31
+ email: 'someone+else@example.com'
32
+ }
33
+ ],
34
+ files: [
35
+ { path: 'test.pdf', name: 'test.pdf' },
36
+ { path: 'test2.pdf', name: 'test2.pdf' }
37
+ ],
38
+ status: 'sent'
39
+ )
40
+
41
+ puts response #the response is a parsed JSON string
@@ -0,0 +1,75 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'openssl'
4
+ require 'json'
5
+
6
+ # Token used to terminate the file in the post body. Make sure it is not
7
+ # present in the file you're uploading.
8
+ BOUNDARY = 'myboundary'
9
+
10
+ uri = URI.parse('https://demo.docusign.net/restapi/v2/accounts/327367/envelopes')
11
+ file = 'test.pdf'
12
+
13
+ request_hash = {
14
+ emailBlurb: 'eblurb',
15
+ emailSubject: 'esubj',
16
+ documents: [
17
+ {
18
+ documentId: '1',
19
+ name: "#{File.basename(file)}"
20
+ }
21
+ ],
22
+ recipients: {
23
+ signers: [
24
+ {
25
+ email: 'someone@example.com',
26
+ name: 'Test Guy',
27
+ recipientId: '1'
28
+ }
29
+ ]
30
+ },
31
+ status: 'sent'
32
+ }
33
+
34
+ post_body = ''
35
+ post_body << "\r\n"
36
+ post_body << "--#{BOUNDARY}\r\n"
37
+ post_body << "Content-Type: application/json\r\n"
38
+ post_body << "Content-Disposition: form-data\r\n"
39
+ post_body << "\r\n"
40
+ post_body << request_hash.to_json
41
+ post_body << "\r\n"
42
+ post_body << "--#{BOUNDARY}\r\n"
43
+ post_body << "Content-Type: application/pdf\r\n"
44
+ post_body << "Content-Disposition: file; filename=\"#{File.basename(file)}\"; documentid=1\r\n"
45
+ post_body << "\r\n"
46
+ post_body << IO.read(file) #this includes the %PDF-1.3 and %%EOF wrapper
47
+ post_body << "\r\n"
48
+ post_body << "--#{BOUNDARY}--\r\n"
49
+
50
+ http = Net::HTTP.new(uri.host, uri.port)
51
+ http.use_ssl = true
52
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
53
+
54
+ docusign_headers = %{
55
+ <DocuSignCredentials>
56
+ <Username>jonkinney@gmail.com</Username>
57
+ <Password>MnUWneAH3xqL2G</Password>
58
+ <IntegratorKey>NAXX-93c39e8c-36c4-4cb5-8099-c4fcedddd7ad</IntegratorKey>
59
+ </DocuSignCredentials>
60
+ }
61
+
62
+ headers = {
63
+ 'X-DocuSign-Authentication' => "#{docusign_headers}",
64
+ 'Content-Type' => "multipart/form-data, boundary=#{BOUNDARY}",
65
+ 'Accept' => 'application/json',
66
+ 'Content-Length' => "#{post_body.length}"
67
+ }
68
+
69
+ request = Net::HTTP::Post.new(uri.request_uri, headers)
70
+
71
+ request.body = post_body
72
+
73
+ response = http.request(request)
74
+
75
+ puts response.body
data/lib/docusign_rest.rb CHANGED
@@ -1,15 +1,15 @@
1
- require 'docusign_rest/version'
2
- require 'docusign_rest/configuration'
3
- require 'docusign_rest/client'
4
- require 'docusign_rest/utility'
1
+ require_relative 'docusign_rest/version'
2
+ require_relative 'docusign_rest/configuration'
3
+ require_relative 'docusign_rest/client'
4
+ require_relative 'docusign_rest/utility'
5
5
  require 'multipart_post' #require the multipart-post gem itself
6
6
  require 'net/http/post/multipart' #require the multipart-post net/http/post/multipart monkey patch
7
- require 'multipart_post/parts' #require my monkey patched parts.rb which adjusts the build_part method
7
+ require_relative 'multipart_post/parts' #require my monkey patched parts.rb which adjusts the build_part method
8
8
  require 'net/http'
9
9
  require 'json'
10
10
 
11
11
  module DocusignRest
12
- require "docusign_rest/railtie" if defined?(Rails)
12
+ require_relative "docusign_rest/railtie" if defined?(Rails)
13
13
 
14
14
  extend Configuration
15
15
  end
@@ -1,3 +1,5 @@
1
+ require 'openssl'
2
+
1
3
  module DocusignRest
2
4
 
3
5
  class Client
@@ -17,19 +19,24 @@ module DocusignRest
17
19
 
18
20
  # Set up the DocuSign Authentication headers with the values passed from
19
21
  # our config block
20
- @docusign_authentication_headers = {
21
- "X-DocuSign-Authentication" => "" \
22
- "<DocuSignCredentials>" \
23
- "<Username>#{DocusignRest.username}</Username>" \
24
- "<Password>#{DocusignRest.password}</Password>" \
25
- "<IntegratorKey>#{DocusignRest.integrator_key}</IntegratorKey>" \
26
- "</DocuSignCredentials>"
27
- }
22
+ if access_token.nil?
23
+ @docusign_authentication_headers = {
24
+ 'X-DocuSign-Authentication' => {
25
+ 'Username' => username,
26
+ 'Password' => password,
27
+ 'IntegratorKey' => integrator_key
28
+ }.to_json
29
+ }
30
+ else
31
+ @docusign_authentication_headers = {
32
+ 'Authorization' => "Bearer #{access_token}"
33
+ }
34
+ end
28
35
 
29
36
  # Set the account_id from the configure block if present, but can't call
30
37
  # the instance var @account_id because that'll override the attr_accessor
31
38
  # that is automatically configured for the configure block
32
- @acct_id = DocusignRest.account_id
39
+ @acct_id = account_id
33
40
  end
34
41
 
35
42
 
@@ -38,7 +45,7 @@ module DocusignRest
38
45
  # the X-DocuSign-Authentication header to authorize the request.
39
46
  #
40
47
  # Client can pass in header options to any given request:
41
- # headers: {"Some-Key" => "some/value", "Another-Key" => "another/value"}
48
+ # headers: {'Some-Key' => 'some/value', 'Another-Key' => 'another/value'}
42
49
  #
43
50
  # Then we pass them on to this method to merge them with the other
44
51
  # required headers
@@ -48,11 +55,11 @@ module DocusignRest
48
55
  # headers(options[:headers])
49
56
  #
50
57
  # Returns a merged hash of headers overriding the default Accept header if
51
- # the user passes in a new "Accept" header key and adds any other
58
+ # the user passes in a new 'Accept' header key and adds any other
52
59
  # user-defined headers along with the X-DocuSign-Authentication headers
53
60
  def headers(user_defined_headers={})
54
61
  default = {
55
- "Accept" => "application/json" #this seems to get added automatically, so I can probably remove this
62
+ 'Accept' => 'json' #this seems to get added automatically, so I can probably remove this
56
63
  }
57
64
 
58
65
  default.merge!(user_defined_headers) if user_defined_headers
@@ -68,11 +75,11 @@ module DocusignRest
68
75
  #
69
76
  # Example:
70
77
  #
71
- # build_uri("/login_information")
78
+ # build_uri('/login_information')
72
79
  #
73
80
  # Returns a parsed URI object
74
81
  def build_uri(url)
75
- URI.parse("#{DocusignRest.endpoint}/#{DocusignRest.api_version}#{url}")
82
+ URI.parse("#{endpoint}/#{api_version}#{url}")
76
83
  end
77
84
 
78
85
 
@@ -82,16 +89,63 @@ module DocusignRest
82
89
  # Returns a configured Net::HTTP object into which a request can be passed
83
90
  def initialize_net_http_ssl(uri)
84
91
  http = Net::HTTP.new(uri.host, uri.port)
85
- http.use_ssl = true
86
92
 
87
- # Explicitly verifies that the certificate matches the domain. Requires
88
- # that we use www when calling the production DocuSign API
89
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
93
+ http.use_ssl = uri.scheme == 'https'
94
+
95
+ if defined?(Rails) && Rails.env.test?
96
+ in_rails_test_env = true
97
+ else
98
+ in_rails_test_env = false
99
+ end
100
+
101
+ if http.use_ssl? && !in_rails_test_env
102
+ if ca_file
103
+ if File.exists?(ca_file)
104
+ http.ca_file = ca_file
105
+ else
106
+ raise 'Certificate path not found.'
107
+ end
108
+ end
109
+
110
+ # Explicitly verifies that the certificate matches the domain.
111
+ # Requires that we use www when calling the production DocuSign API
112
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
113
+ http.verify_depth = 5
114
+ else
115
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
116
+ end
90
117
 
91
118
  http
92
119
  end
93
120
 
94
121
 
122
+ # Public: creates an OAuth2 authorization server token endpoint.
123
+ #
124
+ # email - email of user authenticating
125
+ # password - password of user authenticating
126
+ #
127
+ # Examples:
128
+ #
129
+ # client = DocusignRest::Client.new
130
+ # response = client.get_token('someone@example.com', 'p@ssw0rd01')
131
+ #
132
+ # Returns:
133
+ # access_token - Access token information
134
+ # scope - This should always be "api"
135
+ # token_type - This should always be "bearer"
136
+ def get_token(account_id, email, password)
137
+ content_type = { 'Content-Type' => 'application/x-www-form-urlencoded', 'Accept' => 'application/json' }
138
+ uri = build_uri('/oauth2/token')
139
+
140
+ request = Net::HTTP::Post.new(uri.request_uri, content_type)
141
+ request.body = "grant_type=password&client_id=#{integrator_key}&username=#{email}&password=#{password}&scope=api"
142
+
143
+ http = initialize_net_http_ssl(uri)
144
+ response = http.request(request)
145
+ JSON.parse(response.body)
146
+ end
147
+
148
+
95
149
  # Public: gets info necessary to make additional requests to the DocuSign API
96
150
  #
97
151
  # options - hash of headers if the client wants to override something
@@ -111,7 +165,7 @@ module DocusignRest
111
165
  # userId - # TODO determine what this is used for, if anything
112
166
  # userName - Full name provided when signing up for DocuSign
113
167
  def get_login_information(options={})
114
- uri = build_uri("/login_information")
168
+ uri = build_uri('/login_information')
115
169
  request = Net::HTTP::Get.new(uri.request_uri, headers(options[:headers]))
116
170
  http = initialize_net_http_ssl(uri)
117
171
  http.request(request)
@@ -130,21 +184,14 @@ module DocusignRest
130
184
  #
131
185
  # Returns the accountId string
132
186
  def get_account_id
133
- unless @acct_id
187
+ unless acct_id
134
188
  response = get_login_information.body
135
189
  hashed_response = JSON.parse(response)
136
190
  login_accounts = hashed_response['loginAccounts']
137
- @acct_id ||= login_accounts.first['accountId']
191
+ acct_id ||= login_accounts.first['accountId']
138
192
  end
139
193
 
140
- @acct_id
141
- end
142
-
143
-
144
- def check_embedded_signer(embedded, email)
145
- if embedded && embedded == true
146
- "\"clientUserId\" : \"#{email}\","
147
- end
194
+ acct_id
148
195
  end
149
196
 
150
197
 
@@ -158,20 +205,66 @@ module DocusignRest
158
205
  # name - The name of the signer
159
206
  # email - The email of the signer
160
207
  # role_name - The role name of the signer ('Attorney', 'Client', etc.).
208
+ # tabs - Array of tab pairs grouped by type (Example type: 'textTabs')
209
+ # { textTabs: [ { tabLabel: "label", name: "name", value: "value" } ] }
210
+ #
211
+ # NOTE: The 'tabs' option is NOT supported in 'v1' of the REST API
161
212
  #
162
213
  # Returns a hash of users that need to be embedded in the template to
163
214
  # create an envelope
164
215
  def get_template_roles(signers)
165
216
  template_roles = []
166
217
  signers.each_with_index do |signer, index|
167
- template_roles << "{
168
- #{check_embedded_signer(signer[:embedded], signer[:email])}
169
- \"name\" : \"#{signer[:name]}\",
170
- \"email\" : \"#{signer[:email]}\",
171
- \"roleName\" : \"#{signer[:role_name]}\"
172
- }"
218
+ template_role = {
219
+ name: signer[:name],
220
+ email: signer[:email],
221
+ roleName: signer[:role_name],
222
+ tabs: {
223
+ textTabs: get_signer_tabs(signer[:text_tabs]),
224
+ checkboxTabs: get_signer_tabs(signer[:checkbox_tabs])
225
+ }
226
+ }
227
+
228
+ if signer[:email_notification]
229
+ template_role[:emailNotification] = signer[:email_notification]
230
+ end
231
+
232
+ template_role['clientUserId'] = (signer[:client_id] || signer[:email]).to_s if signer[:embedded] == true
233
+ template_roles << template_role
173
234
  end
174
- template_roles.join(",")
235
+ template_roles
236
+ end
237
+
238
+
239
+ # TODO (2014-02-03) jonk => document
240
+ def get_signer_tabs(tabs)
241
+ Array(tabs).map do |tab|
242
+ {
243
+ 'tabLabel' => tab[:label],
244
+ 'name' => tab[:name],
245
+ 'value' => tab[:value],
246
+ 'documentId' => tab[:document_id],
247
+ 'selected' => tab[:selected]
248
+ }
249
+ end
250
+ end
251
+
252
+
253
+ # TODO (2014-02-03) jonk => document
254
+ def get_event_notification(event_notification)
255
+ return {} unless event_notification
256
+ {
257
+ useSoapInterface: event_notification[:use_soap_interface] || false,
258
+ includeCertificatWithSoap: event_notification[:include_certificate_with_soap] || false,
259
+ url: event_notification[:url],
260
+ loggingEnabled: event_notification[:logging],
261
+ 'EnvelopeEvents' => Array(event_notification[:envelope_events]).map do |envelope_event|
262
+ {
263
+ includeDocuments: envelope_event[:include_documents] || false,
264
+ envelopeEventStatusCode: envelope_event[:envelope_event_status_code]
265
+ }
266
+ end
267
+ }
175
268
  end
176
269
 
177
270
 
@@ -207,102 +300,124 @@ module DocusignRest
207
300
  # tab_label - TODO: figure out what this is
208
301
  def get_signers(signers, options={})
209
302
  doc_signers = []
303
+
210
304
  signers.each_with_index do |signer, index|
211
- # Build up a string with concatenation so that we can append the full
212
- # string to the doc_signers array as the last step in this block
213
- doc_signer = ""
214
- doc_signer << "{
215
- \"email\":\"#{signer[:email]}\",
216
- \"name\":\"#{signer[:name]}\",
217
- \"accessCode\":\"\",
218
- \"addAccessCodeToEmail\":false,
219
- #{check_embedded_signer(signer[:embedded], signer[:email])}
220
- \"customFields\":null,
221
- \"emailNotification\":#{signer[:email_notification] || 'null'},
222
- \"iDCheckConfigurationName\":null,
223
- \"iDCheckInformationInput\":null,
224
- \"inheritEmailNotificationConfiguration\":false,
225
- \"note\":\"\",
226
- \"phoneAuthentication\":null,
227
- \"recipientAttachment\":null,
228
- \"recipientId\":\"#{index+1}\",
229
- \"requireIdLookup\":false,
230
- \"roleName\":\"#{signer[:role_name]}\",
231
- \"routingOrder\":#{index+1},
232
- \"socialAuthentications\":null,
233
- "
305
+ doc_signer = {
306
+ email: signer[:email],
307
+ name: signer[:name],
308
+ accessCode: '',
309
+ addAccessCodeToEmail: false,
310
+ customFields: nil,
311
+ iDCheckConfigurationName: nil,
312
+ iDCheckInformationInput: nil,
313
+ inheritEmailNotificationConfiguration: false,
314
+ note: '',
315
+ phoneAuthentication: nil,
316
+ recipientAttachment: nil,
317
+ recipientId: "#{index + 1}",
318
+ requireIdLookup: false,
319
+ roleName: signer[:role_name],
320
+ routingOrder: index + 1,
321
+ socialAuthentications: nil
322
+ }
323
+
324
+ if signer[:email_notification]
325
+ doc_signer[:emailNotification] = signer[:email_notification]
326
+ end
327
+
328
+ if signer[:embedded]
329
+ doc_signer[:clientUserId] = signer[:client_id] || signer[:email]
330
+ end
234
331
 
235
332
  if options[:template] == true
236
- doc_signer << "
237
- \"templateAccessCodeRequired\":false,
238
- \"templateLocked\":#{signer[:template_locked] || true},
239
- \"templateRequired\":#{signer[:template_required] || true},
240
- "
333
+ doc_signer[:templateAccessCodeRequired] = false
334
+ doc_signer[:templateLocked] = signer[:template_locked].nil? ? true : signer[:template_locked]
335
+ doc_signer[:templateRequired] = signer[:template_required].nil? ? true : signer[:template_required]
241
336
  end
242
337
 
243
- doc_signer << "
244
- \"autoNavigation\":false,
245
- \"defaultRecipient\":false,
246
- \"signatureInfo\":null,
247
- \"tabs\":{
248
- \"approveTabs\":null,
249
- \"checkboxTabs\":null,
250
- \"companyTabs\":null,
251
- \"dateSignedTabs\":null,
252
- \"dateTabs\":null,
253
- \"declineTabs\":null,
254
- \"emailTabs\":null,
255
- \"envelopeIdTabs\":null,
256
- \"fullNameTabs\":null,
257
- \"initialHereTabs\":null,
258
- \"listTabs\":null,
259
- \"noteTabs\":null,
260
- \"numberTabs\":null,
261
- \"radioGroupTabs\":null,
262
- \"signHereTabs\":[
263
- "
264
- signer[:sign_here_tabs].each do |sign_here_tab|
265
- doc_signer << "{
266
- \"anchorString\":\"#{sign_here_tab[:anchor_string]}\",
267
- \"anchorXOffset\": \"#{sign_here_tab[:anchor_x_offset] || '0'}\",
268
- \"anchorYOffset\": \"#{sign_here_tab[:anchor_y_offset] || '0'}\",
269
- \"anchorIgnoreIfNotPresent\": #{sign_here_tab[:ignore_anchor_if_not_present] || false},
270
- \"anchorUnits\": \"pixels\",
271
- \"conditionalParentLabel\": null,
272
- \"conditionalParentValue\": null,
273
- \"documentId\":\"#{sign_here_tab[:document_id] || '1'}\",
274
- \"pageNumber\":\"#{sign_here_tab[:page_number] || '1'}\",
275
- \"recipientId\":\"#{index+1}\",
276
- "
277
- if options[:template] == true
278
- doc_signer << "
279
- \"templateLocked\":#{sign_here_tab[:template_locked] || true},
280
- \"templateRequired\":#{sign_here_tab[:template_required] || true},
281
- "
282
- end
283
- doc_signer << "
284
- \"xPosition\":\"#{sign_here_tab[:x_position] || '0'}\",
285
- \"yPosition\":\"#{sign_here_tab[:y_position] || '0'}\",
286
- \"name\":\"#{sign_here_tab[:sign_here_tab_text] || 'Sign Here'}\",
287
- \"optional\":false,
288
- \"scaleValue\":1,
289
- \"tabLabel\":\"#{sign_here_tab[:tab_label] || 'Signature 1'}\"
290
- },"
291
- end
292
- doc_signer << "],
293
- \"signerAttachmentTabs\":null,
294
- \"ssnTabs\":null,
295
- \"textTabs\":null,
296
- \"titleTabs\":null,
297
- \"zipTabs\":null
298
- }
299
- }"
338
+ doc_signer[:autoNavigation] = false
339
+ doc_signer[:defaultRecipient] = false
340
+ doc_signer[:signatureInfo] = nil
341
+ doc_signer[:tabs] = {
342
+ approveTabs: nil,
343
+ checkboxTabs: get_tabs(signer[:checkbox_tabs], options, index),
344
+ companyTabs: nil,
345
+ dateSignedTabs: get_tabs(signer[:date_signed_tabs], options, index),
346
+ dateTabs: nil,
347
+ declineTabs: nil,
348
+ emailTabs: get_tabs(signer[:email_tabs], options, index),
349
+ envelopeIdTabs: nil,
350
+ fullNameTabs: get_tabs(signer[:full_name_tabs], options, index),
351
+ listTabs: get_tabs(signer[:list_tabs], options, index),
352
+ noteTabs: nil,
353
+ numberTabs: nil,
354
+ radioGroupTabs: nil,
355
+ initialHereTabs: get_tabs(signer[:initial_here_tabs], options.merge!(initial_here_tab: true), index),
356
+ signHereTabs: get_tabs(signer[:sign_here_tabs], options.merge!(sign_here_tab: true), index),
357
+ signerAttachmentTabs: nil,
358
+ ssnTabs: nil,
359
+ textTabs: get_tabs(signer[:text_tabs], options, index),
360
+ titleTabs: get_tabs(signer[:title_tabs], options, index),
361
+ zipTabs: nil
362
+ }
363
+
300
364
  # append the fully build string to the array
301
365
  doc_signers << doc_signer
302
366
  end
303
- doc_signers.join(",")
367
+ doc_signers
368
+ end
369
+
370
+
371
+ # TODO (2014-02-03) jonk => document
372
+ def get_tabs(tabs, options, index)
373
+ tab_array = []
374
+
375
+ Array(tabs).map do |tab|
376
+ tab_hash = {}
377
+
378
+ if tab[:anchor_string]
379
+ tab_hash[:anchorString] = tab[:anchor_string]
380
+ tab_hash[:anchorXOffset] = tab[:anchor_x_offset] || '0'
381
+ tab_hash[:anchorYOffset] = tab[:anchor_y_offset] || '0'
382
+ tab_hash[:anchorIgnoreIfNotPresent] = tab[:ignore_anchor_if_not_present] || false
383
+ tab_hash[:anchorUnits] = 'pixels'
384
+ end
385
+
386
+ tab_hash[:conditionalParentLabel] = nil
387
+ tab_hash[:conditionalParentValue] = nil
388
+ tab_hash[:documentId] = tab[:document_id] || '1'
389
+ tab_hash[:pageNumber] = tab[:page_number] || '1'
390
+ tab_hash[:recipientId] = index + 1
391
+ tab_hash[:required] = tab[:required] || false
392
+
393
+ if options[:template] == true
394
+ tab_hash[:templateLocked] = tab[:template_locked].nil? ? true : tab[:template_locked]
395
+ tab_hash[:templateRequired] = tab[:template_required].nil? ? true : tab[:template_required]
396
+ end
397
+
398
+ if options[:sign_here_tab] == true || options[:initial_here_tab] == true
399
+ tab_hash[:scaleValue] = tab_hash[:scaleValue] || 1
400
+ end
401
+
402
+ tab_hash[:xPosition] = tab[:x_position] || '0'
403
+ tab_hash[:yPosition] = tab[:y_position] || '0'
404
+ tab_hash[:name] = tab[:name] if tab[:name]
405
+ tab_hash[:optional] = false
406
+ tab_hash[:tabLabel] = tab[:label] || 'Signature 1'
407
+ tab_hash[:width] = tab[:width] if tab[:width]
408
+ tab_hash[:height] = tab[:height] if tab[:width]
409
+ tab_hash[:value] = tab[:value] if tab[:value]
410
+
411
+ tab_hash[:locked] = tab[:locked] || false
412
+
413
+ tab_hash[:list_items] = tab[:list_items] if tab[:list_items]
414
+
415
+ tab_array << tab_hash
416
+ end
417
+ tab_array
304
418
  end
305
419
 
420
+
306
421
  # Internal: sets up the file ios array
307
422
  #
308
423
  # files - a hash of file params
@@ -326,8 +441,8 @@ module DocusignRest
326
441
  #
327
442
  # Usage:
328
443
  #
329
- # UploadIO.new("file.txt", "text/plain")
330
- # UploadIO.new(file_io, "text/plain", "file.txt")
444
+ # UploadIO.new('file.txt', 'text/plain')
445
+ # UploadIO.new(file_io, 'text/plain', 'file.txt')
331
446
  # ********************************************************************
332
447
  #
333
448
  # There is also a 4th undocumented argument, opts={}, which allows us
@@ -338,9 +453,9 @@ module DocusignRest
338
453
  files.each_with_index do |file, index|
339
454
  ios << UploadIO.new(
340
455
  file[:io] || file[:path],
341
- file[:content_type] || "application/pdf",
456
+ file[:content_type] || 'application/pdf',
342
457
  file[:name],
343
- "Content-Disposition" => "file; documentid=#{index+1}"
458
+ 'Content-Disposition' => "file; documentid=#{index + 1}"
344
459
  )
345
460
  end
346
461
  ios
@@ -357,25 +472,23 @@ module DocusignRest
357
472
  # multi-doc uploading capabilities, each doc needs to be it's own param
358
473
  file_params = {}
359
474
  ios.each_with_index do |io,index|
360
- file_params.merge!("file#{index+1}" => io)
475
+ file_params.merge!("file#{index + 1}" => io)
361
476
  end
362
477
  file_params
363
478
  end
364
479
 
365
480
 
366
481
  # Internal: takes in an array of hashes of documents and calculates the
367
- # documentId then concatenates all the hashes with commas
482
+ # documentId
368
483
  #
369
484
  # Returns a hash of documents that are to be uploaded
370
485
  def get_documents(ios)
371
- documents = []
372
- ios.each_with_index do |io, index|
373
- documents << "{
374
- \"documentId\" : \"#{index+1}\",
375
- \"name\" : \"#{io.original_filename}\"
376
- }"
486
+ ios.each_with_index.map do |io, index|
487
+ {
488
+ documentId: "#{index + 1}",
489
+ name: io.original_filename
490
+ }
377
491
  end
378
- documents.join(",")
379
492
  end
380
493
 
381
494
 
@@ -398,12 +511,12 @@ module DocusignRest
398
511
  #
399
512
  request = Net::HTTP::Post::Multipart.new(
400
513
  uri.request_uri,
401
- {post_body: post_body}.merge(file_params),
514
+ { post_body: post_body }.merge(file_params),
402
515
  headers
403
516
  )
404
517
 
405
518
  # DocuSign requires that we embed the document data in the body of the
406
- # JSON request directly so we need to call ".read" on the multipart-post
519
+ # JSON request directly so we need to call '.read' on the multipart-post
407
520
  # provided body_stream in order to serialize all the files into a
408
521
  # compatible JSON string.
409
522
  request.body = request.body_stream.read
@@ -442,18 +555,17 @@ module DocusignRest
442
555
  ios = create_file_ios(options[:files])
443
556
  file_params = create_file_params(ios)
444
557
 
445
- post_body = "{
446
- \"emailBlurb\" : \"#{options[:email][:body] if options[:email]}\",
447
- \"emailSubject\" : \"#{options[:email][:subject] if options[:email]}\",
448
- \"documents\" : [#{get_documents(ios)}],
449
- \"recipients\" : {
450
- \"signers\" : [#{get_signers(options[:signers])}]
558
+ post_body = {
559
+ emailBlurb: "#{options[:email][:body] if options[:email]}",
560
+ emailSubject: "#{options[:email][:subject] if options[:email]}",
561
+ documents: get_documents(ios),
562
+ recipients: {
563
+ signers: get_signers(options[:signers])
451
564
  },
452
- \"status\" : \"#{options[:status]}\"
453
- }
454
- "
565
+ status: "#{options[:status]}"
566
+ }.to_json
455
567
 
456
- uri = build_uri("/accounts/#{@acct_id}/envelopes")
568
+ uri = build_uri("/accounts/#{acct_id}/envelopes")
457
569
 
458
570
  http = initialize_net_http_ssl(uri)
459
571
 
@@ -461,9 +573,8 @@ module DocusignRest
461
573
  uri, post_body, file_params, headers(options[:headers])
462
574
  )
463
575
 
464
- # Finally do the Net::HTTP request!
465
576
  response = http.request(request)
466
- parsed_response = JSON.parse(response.body)
577
+ JSON.parse(response.body)
467
578
  end
468
579
 
469
580
 
@@ -499,34 +610,45 @@ module DocusignRest
499
610
  ios = create_file_ios(options[:files])
500
611
  file_params = create_file_params(ios)
501
612
 
502
- post_body = "{
503
- \"emailBlurb\" : \"#{options[:email][:body] if options[:email]}\",
504
- \"emailSubject\" : \"#{options[:email][:subject] if options[:email]}\",
505
- \"documents\" : [#{get_documents(ios)}],
506
- \"recipients\" : {
507
- \"signers\" : [#{get_signers(options[:signers], template: true)}]
613
+ post_body = {
614
+ emailBlurb: "#{options[:email][:body] if options[:email]}",
615
+ emailSubject: "#{options[:email][:subject] if options[:email]}",
616
+ documents: get_documents(ios),
617
+ recipients: {
618
+ signers: get_signers(options[:signers], template: true)
508
619
  },
509
- \"envelopeTemplateDefinition\" : {
510
- \"description\" : \"#{options[:description]}\",
511
- \"name\" : \"#{options[:name]}\",
512
- \"pageCount\" : 1,
513
- \"password\" : \"\",
514
- \"shared\" : false
620
+ envelopeTemplateDefinition: {
621
+ description: options[:description],
622
+ name: options[:name],
623
+ pageCount: 1,
624
+ password: '',
625
+ shared: false
515
626
  }
516
- }
517
- "
518
-
519
- uri = build_uri("/accounts/#{@acct_id}/templates")
627
+ }.to_json
520
628
 
629
+ uri = build_uri("/accounts/#{acct_id}/templates")
521
630
  http = initialize_net_http_ssl(uri)
522
631
 
523
632
  request = initialize_net_http_multipart_post_request(
524
633
  uri, post_body, file_params, headers(options[:headers])
525
634
  )
526
635
 
527
- # Finally do the Net::HTTP request!
528
636
  response = http.request(request)
529
- parsed_response = JSON.parse(response.body)
637
+ JSON.parse(response.body)
638
+ end
639
+
640
+
641
+ # TODO (2014-02-03) jonk => document
642
+ def get_template(template_id, options = {})
643
+ content_type = { 'Content-Type' => 'application/json' }
644
+ content_type.merge(options[:headers]) if options[:headers]
645
+
646
+ uri = build_uri("/accounts/#{acct_id}/templates/#{template_id}")
647
+
648
+ http = initialize_net_http_ssl(uri)
649
+ request = Net::HTTP::Get.new(uri.request_uri, headers(content_type))
650
+ response = http.request(request)
651
+ JSON.parse(response.body)
530
652
  end
531
653
 
532
654
 
@@ -553,18 +675,19 @@ module DocusignRest
553
675
  # templateId - The auto-generated ID provided by DocuSign
554
676
  # Uri - the URI where the template is located on the DocuSign servers
555
677
  def create_envelope_from_template(options={})
556
- content_type = {'Content-Type' => 'application/json'}
678
+ content_type = { 'Content-Type' => 'application/json' }
557
679
  content_type.merge(options[:headers]) if options[:headers]
558
680
 
559
- post_body = "{
560
- \"status\" : \"#{options[:status]}\",
561
- \"emailBlurb\" : \"#{options[:email][:body]}\",
562
- \"emailSubject\" : \"#{options[:email][:subject]}\",
563
- \"templateId\" : \"#{options[:template_id]}\",
564
- \"templateRoles\" : [#{get_template_roles(options[:signers])}],
565
- }"
681
+ post_body = {
682
+ status: options[:status],
683
+ emailBlurb: options[:email][:body],
684
+ emailSubject: options[:email][:subject],
685
+ templateId: options[:template_id],
686
+ eventNotification: get_event_notification(options[:event_notification]),
687
+ templateRoles: get_template_roles(options[:signers])
688
+ }.to_json
566
689
 
567
- uri = build_uri("/accounts/#{@acct_id}/envelopes")
690
+ uri = build_uri("/accounts/#{acct_id}/envelopes")
568
691
 
569
692
  http = initialize_net_http_ssl(uri)
570
693
 
@@ -572,7 +695,29 @@ module DocusignRest
572
695
  request.body = post_body
573
696
 
574
697
  response = http.request(request)
575
- parsed_response = JSON.parse(response.body)
698
+ JSON.parse(response.body)
699
+ end
700
+
701
+
702
+ # Public returns the names specified for a given email address (existing docusign user)
703
+ #
704
+ # email - the email of the recipient
705
+ # headers - optional hash of headers to merge into the existing
706
+ # required headers for a multipart request.
707
+ #
708
+ # Returns the list of names
709
+ def get_recipient_names(options={})
710
+ content_type = { 'Content-Type' => 'application/json' }
711
+ content_type.merge(options[:headers]) if options[:headers]
712
+
713
+ uri = build_uri("/accounts/#{acct_id}/recipient_names?email=#{options[:email]}")
714
+
715
+ http = initialize_net_http_ssl(uri)
716
+
717
+ request = Net::HTTP::Post.new(uri.request_uri, headers(content_type))
718
+
719
+ response = http.request(request)
720
+ JSON.parse(response.body)
576
721
  end
577
722
 
578
723
 
@@ -588,18 +733,45 @@ module DocusignRest
588
733
  #
589
734
  # Returns the URL string for embedded signing (can be put in an iFrame)
590
735
  def get_recipient_view(options={})
591
- content_type = {'Content-Type' => 'application/json'}
736
+ content_type = { 'Content-Type' => 'application/json' }
737
+ content_type.merge(options[:headers]) if options[:headers]
738
+
739
+ post_body = {
740
+ authenticationMethod: 'email',
741
+ clientUserId: options[:client_id] || options[:email],
742
+ email: options[:email],
743
+ returnUrl: options[:return_url],
744
+ userName: options[:name]
745
+ }.to_json
746
+
747
+ uri = build_uri("/accounts/#{acct_id}/envelopes/#{options[:envelope_id]}/views/recipient")
748
+
749
+ http = initialize_net_http_ssl(uri)
750
+
751
+ request = Net::HTTP::Post.new(uri.request_uri, headers(content_type))
752
+ request.body = post_body
753
+
754
+ response = http.request(request)
755
+ JSON.parse(response.body)
756
+ end
757
+
758
+
759
+ # Public returns the URL for embedded console
760
+ #
761
+ # envelope_id - the ID of the envelope you wish to use for embedded signing
762
+ # headers - optional hash of headers to merge into the existing
763
+ # required headers for a multipart request.
764
+ #
765
+ # Returns the URL string for embedded console (can be put in an iFrame)
766
+ def get_console_view(options={})
767
+ content_type = { 'Content-Type' => 'application/json' }
592
768
  content_type.merge(options[:headers]) if options[:headers]
593
769
 
594
- post_body = "{
595
- \"authenticationMethod\" : \"email\",
596
- \"clientUserId\" : \"#{options[:email]}\",
597
- \"email\" : \"#{options[:email]}\",
598
- \"returnUrl\" : \"#{options[:return_url]}\",
599
- \"userName\" : \"#{options[:name]}\",
600
- }"
770
+ post_body = {
771
+ envelopeId: options[:envelope_id]
772
+ }.to_json
601
773
 
602
- uri = build_uri("/accounts/#{@acct_id}/envelopes/#{options[:envelope_id]}/views/recipient")
774
+ uri = build_uri("/accounts/#{acct_id}/views/console")
603
775
 
604
776
  http = initialize_net_http_ssl(uri)
605
777
 
@@ -607,10 +779,12 @@ module DocusignRest
607
779
  request.body = post_body
608
780
 
609
781
  response = http.request(request)
782
+
610
783
  parsed_response = JSON.parse(response.body)
611
- parsed_response["url"]
784
+ parsed_response['url']
612
785
  end
613
786
 
787
+
614
788
  # Public returns the envelope recipients for a given envelope
615
789
  #
616
790
  # include_tabs - boolean, determines if the tabs for each signer will be
@@ -623,19 +797,64 @@ module DocusignRest
623
797
  # Returns a hash of detailed info about the envelope including the signer
624
798
  # hash and status of each signer
625
799
  def get_envelope_recipients(options={})
626
- content_type = {'Content-Type' => 'application/json'}
800
+ content_type = { 'Content-Type' => 'application/json' }
627
801
  content_type.merge(options[:headers]) if options[:headers]
628
802
 
629
803
  include_tabs = options[:include_tabs] || false
630
804
  include_extended = options[:include_extended] || false
631
- uri = build_uri("/accounts/#{@acct_id}/envelopes/#{options[:envelope_id]}/recipients?include_tabs=#{include_tabs}&include_extended=#{include_extended}")
805
+ uri = build_uri("/accounts/#{acct_id}/envelopes/#{options[:envelope_id]}/recipients?include_tabs=#{include_tabs}&include_extended=#{include_extended}")
632
806
 
633
807
  http = initialize_net_http_ssl(uri)
634
808
  request = Net::HTTP::Get.new(uri.request_uri, headers(content_type))
635
809
  response = http.request(request)
636
- parsed_response = JSON.parse(response.body)
810
+ JSON.parse(response.body)
811
+ end
812
+
813
+
814
+ # Public retrieves the envelope status
815
+ #
816
+ # envelope_id - ID of the envelope from which the doc will be retrieved
817
+ def get_envelope_status(options={})
818
+ content_type = { 'Content-Type' => 'application/json' }
819
+ content_type.merge(options[:headers]) if options[:headers]
820
+
821
+ uri = build_uri("/accounts/#{acct_id}/envelopes/#{options[:envelope_id]}")
822
+
823
+ http = initialize_net_http_ssl(uri)
824
+ request = Net::HTTP::Get.new(uri.request_uri, headers(content_type))
825
+ response = http.request(request)
826
+ JSON.parse(response.body)
827
+ end
828
+
829
+
830
+ # Public retrieves the statuses of envelopes matching the given query
831
+ #
832
+ # from_date - Docusign formatted Date/DateTime. Only return items after this date.
833
+ #
834
+ # to_date - Docusign formatted Date/DateTime. Only return items up to this date.
835
+ # Defaults to the time of the call.
836
+ #
837
+ # from_to_status - The status of the envelope checked for in the from_date - to_date period.
838
+ # Defaults to 'changed'
839
+ #
840
+ # status - The current status of the envelope. Defaults to any status.
841
+ #
842
+ # Returns an array of hashes containing envelope statuses, ids, and similar information.
843
+ def get_envelope_statuses(options={})
844
+ content_type = { 'Content-Type' => 'application/json' }
845
+ content_type.merge(options[:headers]) if options[:headers]
846
+
847
+ query_params = options.slice(:from_date, :to_date, :from_to_status, :status)
848
+ uri = build_uri("/accounts/#{acct_id}/envelopes?#{query_params.to_query}")
849
+
850
+ http = initialize_net_http_ssl(uri)
851
+ request = Net::HTTP::Get.new(uri.request_uri, headers(content_type))
852
+ response = http.request(request)
853
+
854
+ JSON.parse(response.body)
637
855
  end
638
856
 
857
+
639
858
  # Public retrieves the attached file from a given envelope
640
859
  #
641
860
  # envelope_id - ID of the envelope from which the doc will be retrieved
@@ -648,21 +867,23 @@ module DocusignRest
648
867
  # Example
649
868
  #
650
869
  # client.get_document_from_envelope(
651
- # envelope_id: @envelope_response["envelopeId"],
870
+ # envelope_id: @envelope_response['envelopeId'],
652
871
  # document_id: 1,
653
- # local_save_path: 'docusign_docs/file_name.pdf'
872
+ # local_save_path: 'docusign_docs/file_name.pdf',
873
+ # return_stream: true/false # will return the bytestream instead of saving doc to file system.
654
874
  # )
655
875
  #
656
876
  # Returns the PDF document as a byte stream.
657
877
  def get_document_from_envelope(options={})
658
- content_type = {'Content-Type' => 'application/json'}
878
+ content_type = { 'Content-Type' => 'application/json' }
659
879
  content_type.merge(options[:headers]) if options[:headers]
660
880
 
661
- uri = build_uri("/accounts/#{@acct_id}/envelopes/#{options[:envelope_id]}/documents/#{options[:document_id]}")
881
+ uri = build_uri("/accounts/#{acct_id}/envelopes/#{options[:envelope_id]}/documents/#{options[:document_id]}")
662
882
 
663
883
  http = initialize_net_http_ssl(uri)
664
884
  request = Net::HTTP::Get.new(uri.request_uri, headers(content_type))
665
885
  response = http.request(request)
886
+ return response.body if options[:return_stream]
666
887
 
667
888
  split_path = options[:local_save_path].split('/')
668
889
  split_path.pop #removes the document name and extension from the array
@@ -673,6 +894,178 @@ module DocusignRest
673
894
  output << response.body
674
895
  end
675
896
  end
676
- end
677
897
 
898
+
899
+ # Public retrieves the document infos from a given envelope
900
+ #
901
+ # envelope_id - ID of the envelope from which document infos are to be retrieved
902
+ #
903
+ # Returns a hash containing the envelopeId and the envelopeDocuments array
904
+ def get_documents_from_envelope(options={})
905
+ content_type = { 'Content-Type' => 'application/json' }
906
+ content_type.merge(options[:headers]) if options[:headers]
907
+
908
+ uri = build_uri("/accounts/#{acct_id}/envelopes/#{options[:envelope_id]}/documents")
909
+
910
+ http = initialize_net_http_ssl(uri)
911
+ request = Net::HTTP::Get.new(uri.request_uri, headers(content_type))
912
+ response = http.request(request)
913
+
914
+ JSON.parse(response.body)
915
+ end
916
+
917
+
918
+ # Public moves the specified envelopes to the given folder
919
+ #
920
+ # envelope_ids - IDs of the envelopes to be moved
921
+ # folder_id - ID of the folder to move the envelopes to
922
+ # headers - Optional hash of headers to merge into the existing
923
+ # required headers for a multipart request.
924
+ #
925
+ # Example
926
+ #
927
+ # client.move_envelope_to_folder(
928
+ # envelope_ids: ["xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx"]
929
+ # folder_id: "xxxxx-2222xxxxx",
930
+ # )
931
+ #
932
+ # Returns the response.
933
+ def move_envelope_to_folder(options = {})
934
+ content_type = { 'Content-Type' => 'application/json' }
935
+ content_type.merge(options[:headers]) if options[:headers]
936
+
937
+ post_body = {
938
+ envelopeIds: options[:envelope_ids]
939
+ }.to_json
940
+
941
+ uri = build_uri("/accounts/#{acct_id}/folders/#{options[:folder_id]}")
942
+
943
+ http = initialize_net_http_ssl(uri)
944
+ request = Net::HTTP::Put.new(uri.request_uri, headers(content_type))
945
+ request.body = post_body
946
+ response = http.request(request)
947
+
948
+ response
949
+ end
950
+
951
+
952
+ # Public retrieves the envelope(s) from a specific folder based on search params.
953
+ #
954
+ # Option Query Terms(none are required):
955
+ # query_params:
956
+ # start_position: Integer The position of the folder items to return. This is used for repeated calls, when the number of envelopes returned is too much for one return (calls return 100 envelopes at a time). The default value is 0.
957
+ # from_date: date/Time Only return items on or after this date. If no value is provided, the default search is the previous 30 days.
958
+ # to_date: date/Time Only return items up to this date. If no value is provided, the default search is to the current date.
959
+ # search_text: String The search text used to search the items of the envelope. The search looks at recipient names and emails, envelope custom fields, sender name, and subject.
960
+ # status: Status The current status of the envelope. If no value is provided, the default search is all/any status.
961
+ # owner_name: username The name of the folder owner.
962
+ # owner_email: email The email of the folder owner.
963
+ #
964
+ # Example
965
+ #
966
+ # client.search_folder_for_envelopes(
967
+ # folder_id: xxxxx-2222xxxxx,
968
+ # query_params: {
969
+ # search_text: "John Appleseed",
970
+ # from_date: '7-1-2011+11:00:00+AM',
971
+ # to_date: '7-1-2011+11:00:00+AM',
972
+ # status: "completed"
973
+ # }
974
+ # )
975
+ #
976
+ def search_folder_for_envelopes(options={})
977
+ content_type = { 'Content-Type' => 'application/json' }
978
+ content_type.merge(options[:headers]) if options[:headers]
979
+
980
+ q ||= []
981
+ options[:query_params].each do |key, val|
982
+ q << "#{key}=#{val}"
983
+ end
984
+
985
+ uri = build_uri("/accounts/#{@acct_id}/folders/#{options[:folder_id]}/?#{q.join('&')}")
986
+
987
+ http = initialize_net_http_ssl(uri)
988
+ request = Net::HTTP::Get.new(uri.request_uri, headers(content_type))
989
+ response = http.request(request)
990
+ JSON.parse(response.body)
991
+ end
992
+
993
+
994
+ # TODO (2014-02-03) jonk => document
995
+ def create_account(options)
996
+ content_type = { 'Content-Type' => 'application/json' }
997
+ content_type.merge(options[:headers]) if options[:headers]
998
+
999
+ uri = build_uri('/accounts')
1000
+
1001
+ post_body = convert_hash_keys(options).to_json
1002
+
1003
+ http = initialize_net_http_ssl(uri)
1004
+ request = Net::HTTP::Post.new(uri.request_uri, headers(content_type))
1005
+ request.body = post_body
1006
+ response = http.request(request)
1007
+ JSON.parse(response.body)
1008
+ end
1009
+
1010
+
1011
+ # TODO (2014-02-03) jonk => document
1012
+ def convert_hash_keys(value)
1013
+ case value
1014
+ when Array
1015
+ value.map { |v| convert_hash_keys(v) }
1016
+ when Hash
1017
+ Hash[value.map { |k, v| [k.to_s.camelize(:lower), convert_hash_keys(v)] }]
1018
+ else
1019
+ value
1020
+ end
1021
+ end
1022
+
1023
+
1024
+ # TODO (2014-02-03) jonk => document
1025
+ def delete_account(account_id, options = {})
1026
+ content_type = { 'Content-Type' => 'application/json' }
1027
+ content_type.merge(options[:headers]) if options[:headers]
1028
+
1029
+ uri = build_uri("/accounts/#{account_id}")
1030
+
1031
+ http = initialize_net_http_ssl(uri)
1032
+ request = Net::HTTP::Delete.new(uri.request_uri, headers(content_type))
1033
+ response = http.request(request)
1034
+ json = response.body
1035
+ json = '{}' if json.nil? || json == ''
1036
+ JSON.parse(json)
1037
+ end
1038
+
1039
+
1040
+ # Public: Retrieves a list of available templates
1041
+ #
1042
+ # Example
1043
+ #
1044
+ # client.get_templates()
1045
+ #
1046
+ # Returns a list of the available templates.
1047
+ def get_templates
1048
+ uri = build_uri("/accounts/#{acct_id}/templates")
1049
+
1050
+ http = initialize_net_http_ssl(uri)
1051
+ request = Net::HTTP::Get.new(uri.request_uri, headers({ 'Content-Type' => 'application/json' }))
1052
+ JSON.parse(http.request(request).body)
1053
+ end
1054
+
1055
+
1056
+ # Grabs envelope data.
1057
+ # Equivalent to the following call in the API explorer:
1058
+ # Get Envelopev2/accounts/:accountId/envelopes/:envelopeId
1059
+ #
1060
+ # envelope_id- DS id of envelope to be retrieved.
1061
+ def get_envelope(envelope_id)
1062
+ content_type = { 'Content-Type' => 'application/json' }
1063
+ uri = build_uri("/accounts/#{acct_id}/envelopes/#{envelope_id}")
1064
+
1065
+ http = initialize_net_http_ssl(uri)
1066
+ request = Net::HTTP::Get.new(uri.request_uri, headers(content_type))
1067
+ response = http.request(request)
1068
+ JSON.parse(response.body)
1069
+ end
1070
+ end
678
1071
  end