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.
- checksums.yaml +7 -0
- data/.gitignore +5 -2
- data/Gemfile +3 -0
- data/Guardfile +10 -0
- data/LICENSE +2 -2
- data/README.md +68 -4
- data/cacert.pem +3895 -0
- data/docusign_rest.gemspec +11 -7
- data/examples/request_via_gem.rb +41 -0
- data/examples/request_via_raw_net_http.rb +75 -0
- data/lib/docusign_rest.rb +6 -6
- data/lib/docusign_rest/client.rb +588 -195
- data/lib/docusign_rest/configuration.rb +7 -3
- data/lib/docusign_rest/utility.rb +2 -4
- data/lib/docusign_rest/version.rb +1 -1
- data/lib/multipart_post/parts.rb +10 -3
- data/test/docusign_login_config.rb +14 -0
- data/test/docusign_rest/client_test.rb +53 -18
- data/test/docusign_rest/configuration_test.rb +1 -1
- data/test/helper.rb +4 -2
- metadata +61 -46
- data/example.rb +0 -40
data/docusign_rest.gemspec
CHANGED
@@ -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 = [
|
6
|
-
gem.email = [
|
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/
|
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 =
|
15
|
-
gem.require_paths = [
|
14
|
+
gem.name = 'docusign_rest'
|
15
|
+
gem.require_paths = ['lib']
|
16
16
|
gem.version = DocusignRest::VERSION
|
17
17
|
|
18
|
-
gem.
|
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
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
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
|
-
|
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
|
-
|
12
|
+
require_relative "docusign_rest/railtie" if defined?(Rails)
|
13
13
|
|
14
14
|
extend Configuration
|
15
15
|
end
|
data/lib/docusign_rest/client.rb
CHANGED
@@ -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
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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 =
|
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: {
|
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
|
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
|
-
|
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(
|
78
|
+
# build_uri('/login_information')
|
72
79
|
#
|
73
80
|
# Returns a parsed URI object
|
74
81
|
def build_uri(url)
|
75
|
-
URI.parse("#{
|
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
|
-
|
88
|
-
|
89
|
-
|
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(
|
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
|
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
|
-
|
191
|
+
acct_id ||= login_accounts.first['accountId']
|
138
192
|
end
|
139
193
|
|
140
|
-
|
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
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
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
|
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
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
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
|
-
|
238
|
-
|
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
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
signer[:
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
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
|
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(
|
330
|
-
# UploadIO.new(file_io,
|
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] ||
|
456
|
+
file[:content_type] || 'application/pdf',
|
342
457
|
file[:name],
|
343
|
-
|
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
|
482
|
+
# documentId
|
368
483
|
#
|
369
484
|
# Returns a hash of documents that are to be uploaded
|
370
485
|
def get_documents(ios)
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
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
|
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
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
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
|
-
|
453
|
-
}
|
454
|
-
"
|
565
|
+
status: "#{options[:status]}"
|
566
|
+
}.to_json
|
455
567
|
|
456
|
-
uri = build_uri("/accounts/#{
|
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
|
-
|
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
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
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
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
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
|
-
|
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
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
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/#{
|
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
|
-
|
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
|
-
|
596
|
-
|
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/#{
|
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[
|
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/#{
|
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
|
-
|
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[
|
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/#{
|
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
|