docusign_rest 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 92bb23605a44e60594996854cb04b263c5cc397d
4
- data.tar.gz: 33e9b608604ed47694349b903fc6f5b2c4e0725a
3
+ metadata.gz: 0e077e5af78df26b9158e39d0a37b138693f9634
4
+ data.tar.gz: 566af05a3a7a3c1fe7dc351f7e25a168f62a2b5a
5
5
  SHA512:
6
- metadata.gz: 9fe5a2cf482885160b5ae8d7be4c407c974143f1fe96053150ae7d066272ef940241521b62f38e7f217d64ba4e7f8f1bf38439930a0245e07656362b740aacec
7
- data.tar.gz: 3f62f142674060910756a1b0098d2d4ad243c6641e8817139563a23a0777de8ede821ca98d04709ede350721cc9990c1607354f20c468acef208fa3043c54dd6
6
+ metadata.gz: d2710846c68cc0cb9a9f09b5b77b9645e57d36dac7a679247f8792fe51f277a3af372bee303a72cb3e853cebd36348b8899483df1cdd6d8e7fbb782fa8cb1ce5
7
+ data.tar.gz: 326e18ab520f022027393a9648953bc5046a7aae5d03fea5924e9d06294168b825825642c6a6a7ee7d1811e8cb24300ea77a03e8c574fb76d6343c442ff46ca8
data/.gitignore CHANGED
@@ -12,6 +12,7 @@ lib/bundler/man
12
12
  pkg
13
13
  rdoc
14
14
  spec/reports
15
+ test/docsign_login_config.rb
15
16
  test/tmp
16
17
  test/version_tmp
17
18
  test/fixtures/vcr/*
data/CHANGELOG.md ADDED
@@ -0,0 +1,35 @@
1
+ # Changelog
2
+
3
+ ## v0.2.0 April 28 2017
4
+
5
+ ### Features:
6
+ * Implement DocusignRest::Client#get_sender_view (Gonzalo Rodríguez)
7
+ * Implement DocusignRest::Client#add_envelope_signers (Dan Rench)
8
+ * Implement DocusignRest::Client#get_folder_list (Matthew Santeler)
9
+ * Implement DocusignRest::Client#get_composite_template (lbspen)
10
+ * Implement DocusignRest::Client#create_envelope_from_composite_template (lbspen, Ariel Fox)
11
+ * Implement DocusignRest::Client#get_templates_in_envelope (lbspen)
12
+ * Implement DocusignRest::Client#get_combined_document_from_envelope (Patrick Logan)
13
+ * Implement DocusignRest::Client#get_envelope_audit_events (Sean Woojin Kim)
14
+ * Implement DocusignRest::Client#void_envelope (Mike Pence)
15
+ * Implement DocusignRest::Client#delete_envelope_recipient (Mike Pence)
16
+ * DocusignRest::Client#get_template_roles now supports numberTabs (Mike Pence)
17
+ * DocusignRest::Client#get_tabs now supports the "selected" and "optional" options (Shane Stanford, Greg)
18
+ * DocusignRest::Client#get_token now requires an integrationKey argument (Joe Heth)
19
+ * Added support for adding/removing envelope documents (Andrew Porterfield)
20
+ * Added support for adding recipient tabs (Andrew Porterfield)
21
+ * DocusignRest::Client#create_envelope_from_document now supports a customFields options (Jon Witucki)
22
+ * DocusignRest::Client#create_envelope_from_template now supports a customFields option (Tyler Green)
23
+ * DocusignRest::Client#get_signer_tabs now supports locking tabs (Chris Antaki)
24
+ * DocusignRest::Client#get_inline_signers now supports a client id as well as email address (Patrick Logan)
25
+
26
+ ### Bug fixes:
27
+ * A tab's scaleValue can now be set (Jon Witucki)
28
+ * tab height is no longer improperly set to tab width (mesbahmilad)
29
+ * DocusignRest::Client#get_account_id no longer always returns nil (Mark Wilson)
30
+
31
+ ### Misc:
32
+ * More Rubyish variable naming (Chris Doyle)
33
+ * Whitespace cleanup and unnecessary local variable removal (Jon Witucki)
34
+ * Updated setup instructions (entrision)
35
+ * Fixed header syntax in code example (Paulo Abreu)
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- ruby '2.0.0'
3
+ ruby '2.4.0'
4
4
  #ruby-gemset=docusign_rest
5
5
 
6
6
  # Specify your gem's dependencies in docusign_rest.gemspec
data/README.md CHANGED
@@ -34,10 +34,10 @@ outputs:
34
34
 
35
35
  Please do the following:
36
36
  ------------------------
37
- 1) Login or register for an account at demo.docusign.net
38
- ...or their production url if applicable
39
- 2) Click 'Preferences' in the upper right corner of the page
40
- 3) Click 'API' in far lower left corner of the menu
37
+ 1) Login or register for an account at https://demo.docusign.net
38
+ ...or their production url if applicable
39
+ 2) From the Avatar menu in the upper right hand corner of the page, click "Go to Admin"
40
+ 3) From the left sidebar menu, click "API and Keys"
41
41
  4) Request a new 'Integrator Key' via the web interface
42
42
  * You will use this key in one of the next steps to retrieve your 'accountId'
43
43
 
@@ -73,13 +73,13 @@ The above options allow you to change the endpoint (to be able to hit the produc
73
73
 
74
74
  ## Usage
75
75
 
76
- The docusign\_rest gem makes creating multipart POST (aka file upload) requests to the DocuSign REST API dead simple. It's built on top of Net:HTTP and utilizes the [multipart-post](https://github.com/nicksieger/multipart-post) gem to assist with formatting the multipart requests. The DocuSign REST API requires that all files be embedded as JSON directly in the request body (not the body\_stream like multipart-post does by default) so the docusign\_rest gem takes care of [setting that up for you](https://github.com/j2fly/docusign_rest/blob/master/lib/docusign_rest/client.rb#L397).
76
+ The docusign\_rest gem makes creating multipart POST (aka file upload) requests to the DocuSign REST API dead simple. It's built on top of Net:HTTP and utilizes the [multipart-post](https://github.com/nicksieger/multipart-post) gem to assist with formatting the multipart requests. The DocuSign REST API requires that all files be embedded as JSON directly in the request body (not the body\_stream like multipart-post does by default) so the docusign\_rest gem takes care of [setting that up for you](https://github.com/j2fly/docusign_rest/blob/master/lib/docusign_rest/client.rb#L397).
77
77
 
78
- This gem also monkey patches one small part of multipart-post to inject some header values and formatting that DocuSign requires. If you would like to see the monkey patched code please take a look at [lib/multipart-post/parts.rb](https://github.com/j2fly/docusign_rest/blob/master/lib/multipart_post/parts.rb). It's only re-opening one method, but feel free to make sure you understand that code if it concerns you.
78
+ This gem also monkey patches one small part of multipart-post to inject some header values and formatting that DocuSign requires. If you would like to see the monkey patched code please take a look at [lib/multipart-post/parts.rb](https://github.com/j2fly/docusign_rest/blob/master/lib/multipart_post/parts.rb). It's only re-opening one method, but feel free to make sure you understand that code if it concerns you.
79
79
 
80
80
  ### Examples
81
81
 
82
- * These examples assume you have already run the `docusign_rest:generate_config` rake task and have the configure block properly setup in an initializer with your username, password, integrator\_key, and account\_id.
82
+ * These examples assume you have already run the `docusign_rest:generate_config` rake task and have the configure block properly setup in an initializer with your username, password, integrator\_key, and account\_id.
83
83
  * Unless noted otherwise, these requests return the JSON parsed body of the response so you can index the returned hash directly. For example: `template_response["templateId"]`.
84
84
 
85
85
  **Getting account_id:**
@@ -102,7 +102,7 @@ document_envelope_response = client.create_envelope_from_document(
102
102
  body: "this is the email body and it's large!"
103
103
  },
104
104
  # If embedded is set to true in the signers array below, emails
105
- # don't go out to the signers and you can embed the signature page in an
105
+ # don't go out to the signers and you can embed the signature page in an
106
106
  # iFrame by using the client.get_recipient_view method
107
107
  signers: [
108
108
  {
@@ -235,30 +235,26 @@ client = DocusignRest::Client.new
235
235
  name: 'jon',
236
236
  email: 'someone@gmail.com',
237
237
  role_name: 'Issuer',
238
- tabs: {
239
- textTabs: [
240
- {
241
- tabLabel: 'Seller Full Name',
242
- name: 'Seller Full Name',
243
- value: 'Jon Doe'
244
- }
245
- ]
246
- }
238
+ text_tabs: [
239
+ {
240
+ label: 'Seller Full Name',
241
+ name: 'Seller Full Name',
242
+ value: 'Jon Doe'
243
+ }
244
+ ]
247
245
  },
248
246
  {
249
247
  embedded: true,
250
248
  name: 'tim',
251
249
  email: 'someone+else@gmail.com',
252
250
  role_name: 'Attorney',
253
- tabs: {
254
- textTabs: [
255
- {
256
- tabLabel: 'Attorney Full Name',
257
- name: 'Attorney Full Name',
258
- value: 'Tim Smith'
259
- }
260
- ]
261
- }
251
+ text_tabs: [
252
+ {
253
+ label: 'Attorney Full Name',
254
+ name: 'Attorney Full Name',
255
+ value: 'Tim Smith'
256
+ }
257
+ ]
262
258
  }
263
259
  ]
264
260
  )
@@ -304,7 +300,7 @@ client.get_document_from_envelope(
304
300
 
305
301
  In order to return to your application after the signing process is complete it's important to have a way to evaluate whether or not the signing was successful and then do something about each case. The way I set this up was to render the embedded signing iframe for a controller action called 'embedded_signing' and specify the return_url of the `client.get_recipient_view` API call to be something like: http://myapp.com/docusign_response. Then in the same controller as the embedded_signing method, define the docusign_response method. This is where the signing process will redirect to after the user is done interacting with the DocuSign iframe. DocuSign passes a query string parameter in the return_url named 'event' and you can check like so: `if params[:event] == "signing_complete"` then you'll want to redirect to another spot in your app, not in the iframe. To do so, we need to use JavaScript to access the iframe's parent and set it's location to the path of our choosing. To do this, instanciate the DocusignRest::Utility class and call the breakout_path method like this:
306
302
 
307
- ```ruby
303
+ ```ruby
308
304
  class SomeController < ApplicationController
309
305
 
310
306
  # the view corresponding to this action has the iFrame in it with the
@@ -14,17 +14,18 @@ Gem::Specification.new do |gem|
14
14
  gem.name = 'docusign_rest'
15
15
  gem.require_paths = ['lib']
16
16
  gem.version = DocusignRest::VERSION
17
+ gem.licenses = ['MIT']
17
18
 
18
19
  gem.required_ruby_version = '>= 1.9.2'
19
20
 
20
21
  gem.add_dependency('multipart-post', '>= 1.2')
21
22
  gem.add_dependency('json')
22
23
  gem.add_development_dependency('rake')
23
- gem.add_development_dependency('minitest', '~>4.0')
24
+ gem.add_development_dependency('minitest', '~> 4.0')
24
25
  gem.add_development_dependency('guard-minitest')
25
26
  gem.add_development_dependency('rb-fsevent', '~> 0.9')
26
27
  gem.add_development_dependency('turn')
27
28
  gem.add_development_dependency('pry')
28
29
  gem.add_development_dependency('vcr')
29
- gem.add_development_dependency('fakeweb')
30
+ gem.add_development_dependency('webmock')
30
31
  end
@@ -61,7 +61,7 @@ docusign_headers = %{
61
61
 
62
62
  headers = {
63
63
  'X-DocuSign-Authentication' => "#{docusign_headers}",
64
- 'Content-Type' => "multipart/form-data, boundary=#{BOUNDARY}",
64
+ 'Content-Type' => "multipart/form-data; boundary=#{BOUNDARY}",
65
65
  'Accept' => 'application/json',
66
66
  'Content-Length' => "#{post_body.length}"
67
67
  }
@@ -1,4 +1,5 @@
1
1
  require 'openssl'
2
+ require 'open-uri'
2
3
 
3
4
  module DocusignRest
4
5
 
@@ -127,13 +128,13 @@ module DocusignRest
127
128
  # Examples:
128
129
  #
129
130
  # client = DocusignRest::Client.new
130
- # response = client.get_token('someone@example.com', 'p@ssw0rd01')
131
+ # response = client.get_token(integrator_key, 'someone@example.com', 'p@ssw0rd01')
131
132
  #
132
133
  # Returns:
133
134
  # access_token - Access token information
134
135
  # scope - This should always be "api"
135
136
  # token_type - This should always be "bearer"
136
- def get_token(account_id, email, password)
137
+ def get_token(integrator_key, email, password)
137
138
  content_type = { 'Content-Type' => 'application/x-www-form-urlencoded', 'Accept' => 'application/json' }
138
139
  uri = build_uri('/oauth2/token')
139
140
 
@@ -188,7 +189,7 @@ module DocusignRest
188
189
  response = get_login_information.body
189
190
  hashed_response = JSON.parse(response)
190
191
  login_accounts = hashed_response['loginAccounts']
191
- acct_id ||= login_accounts.first['accountId']
192
+ @acct_id ||= login_accounts.first['accountId']
192
193
  end
193
194
 
194
195
  acct_id
@@ -221,7 +222,10 @@ module DocusignRest
221
222
  roleName: signer[:role_name],
222
223
  tabs: {
223
224
  textTabs: get_signer_tabs(signer[:text_tabs]),
224
- checkboxTabs: get_signer_tabs(signer[:checkbox_tabs])
225
+ checkboxTabs: get_signer_tabs(signer[:checkbox_tabs]),
226
+ numberTabs: get_signer_tabs(signer[:number_tabs]),
227
+ fullNameTabs: get_signer_tabs(signer[:fullname_tabs]),
228
+ dateTabs: get_signer_tabs(signer[:date_tabs])
225
229
  }
226
230
  }
227
231
 
@@ -244,7 +248,8 @@ module DocusignRest
244
248
  'name' => tab[:name],
245
249
  'value' => tab[:value],
246
250
  'documentId' => tab[:document_id],
247
- 'selected' => tab[:selected]
251
+ 'selected' => tab[:selected],
252
+ 'locked' => tab[:locked]
248
253
  }
249
254
  end
250
255
  end
@@ -351,7 +356,7 @@ module DocusignRest
351
356
  listTabs: get_tabs(signer[:list_tabs], options, index),
352
357
  noteTabs: nil,
353
358
  numberTabs: nil,
354
- radioGroupTabs: nil,
359
+ radioGroupTabs: get_tabs(signer[:radio_group_tabs], options, index),
355
360
  initialHereTabs: get_tabs(signer[:initial_here_tabs], options.merge!(initial_here_tab: true), index),
356
361
  signHereTabs: get_tabs(signer[:sign_here_tabs], options.merge!(sign_here_tab: true), index),
357
362
  signerAttachmentTabs: nil,
@@ -383,8 +388,8 @@ module DocusignRest
383
388
  tab_hash[:anchorUnits] = 'pixels'
384
389
  end
385
390
 
386
- tab_hash[:conditionalParentLabel] = nil
387
- tab_hash[:conditionalParentValue] = nil
391
+ tab_hash[:conditionalParentLabel] = tab[:conditional_parent_label] if tab.key?(:conditional_parent_label)
392
+ tab_hash[:conditionalParentValue] = tab[:conditional_parent_value] if tab.key?(:conditional_parent_value)
388
393
  tab_hash[:documentId] = tab[:document_id] || '1'
389
394
  tab_hash[:pageNumber] = tab[:page_number] || '1'
390
395
  tab_hash[:recipientId] = index + 1
@@ -396,22 +401,26 @@ module DocusignRest
396
401
  end
397
402
 
398
403
  if options[:sign_here_tab] == true || options[:initial_here_tab] == true
399
- tab_hash[:scaleValue] = tab_hash[:scaleValue] || 1
404
+ tab_hash[:scaleValue] = tab[:scale_value] || 1
400
405
  end
401
406
 
402
407
  tab_hash[:xPosition] = tab[:x_position] || '0'
403
408
  tab_hash[:yPosition] = tab[:y_position] || '0'
404
409
  tab_hash[:name] = tab[:name] if tab[:name]
405
- tab_hash[:optional] = false
410
+ tab_hash[:optional] = tab[:optional] || false
406
411
  tab_hash[:tabLabel] = tab[:label] || 'Signature 1'
407
412
  tab_hash[:width] = tab[:width] if tab[:width]
408
- tab_hash[:height] = tab[:height] if tab[:width]
413
+ tab_hash[:height] = tab[:height] if tab[:height]
409
414
  tab_hash[:value] = tab[:value] if tab[:value]
415
+ tab_hash[:selected] = tab[:selected] if tab[:selected]
410
416
 
411
417
  tab_hash[:locked] = tab[:locked] || false
412
418
 
413
419
  tab_hash[:list_items] = tab[:list_items] if tab[:list_items]
414
420
 
421
+ tab_hash[:groupName] = tab[:group_name] if tab.key?(:group_name)
422
+ tab_hash[:radios] = get_tabs(tab[:radios], options, index) if tab.key?(:radios)
423
+
415
424
  tab_array << tab_hash
416
425
  end
417
426
  tab_array
@@ -491,6 +500,65 @@ module DocusignRest
491
500
  end
492
501
  end
493
502
 
503
+ # Internal: takes in an array of server template ids and an array of the signers
504
+ # and sets up the composite template
505
+ #
506
+ # Takes an optional array of files, which consist of documents to be used instead of templates
507
+ #
508
+ # Returns an array of server template hashes
509
+ def get_composite_template(server_template_ids, signers, files)
510
+ composite_array = []
511
+ index = 0
512
+ server_template_ids.each_with_index do |template_id, idx|
513
+ server_template_hash = {
514
+ sequence: (idx+1).to_s,
515
+ templateId: template_id,
516
+ templateRoles: get_template_roles(signers),
517
+ }
518
+ templates_hash = {
519
+ serverTemplates: [server_template_hash],
520
+ inlineTemplates: get_inline_signers(signers, (idx+1).to_s)
521
+ }
522
+ if files
523
+ document_hash = {
524
+ documentId: (idx+1).to_s,
525
+ name: "#{files[idx][:name] if files[idx]}"
526
+ }
527
+ templates_hash[:document] = document_hash
528
+ end
529
+ composite_array << templates_hash
530
+ end
531
+ composite_array
532
+ end
533
+
534
+
535
+ # Internal: takes signer info and the inline template sequence number
536
+ # and sets up the inline template
537
+ #
538
+ # Returns an array of signers
539
+ def get_inline_signers(signers, sequence)
540
+ signers_array = []
541
+ signers.each do |signer|
542
+ signers_hash = {
543
+ email: signer[:email],
544
+ name: signer[:name],
545
+ recipientId: signer[:recipient_id],
546
+ roleName: signer[:role_name],
547
+ clientUserId: signer[:client_id] || signer[:email],
548
+ tabs: {
549
+ textTabs: get_signer_tabs(signer[:text_tabs]),
550
+ checkboxTabs: get_signer_tabs(signer[:checkbox_tabs]),
551
+ numberTabs: get_signer_tabs(signer[:number_tabs]),
552
+ fullNameTabs: get_signer_tabs(signer[:fullname_tabs]),
553
+ dateTabs: get_signer_tabs(signer[:date_tabs])
554
+ }
555
+ }
556
+ signers_array << signers_hash
557
+ end
558
+ template_hash = {sequence: sequence, recipients: { signers: signers_array }}
559
+ [template_hash]
560
+ end
561
+
494
562
 
495
563
  # Internal sets up the Net::HTTP request
496
564
  #
@@ -544,6 +612,9 @@ module DocusignRest
544
612
  # status - Options include: 'sent', 'created', 'voided' and determine
545
613
  # if the envelope is sent out immediately or stored for
546
614
  # sending at a later time
615
+ # customFields - (Optional) A hash of listCustomFields and textCustomFields.
616
+ # Each contains an array of corresponding customField hashes.
617
+ # For details, please see: http://bit.ly/1FnmRJx
547
618
  # headers - Allows a client to pass in some
548
619
  #
549
620
  # Returns a JSON parsed response object containing:
@@ -562,7 +633,8 @@ module DocusignRest
562
633
  recipients: {
563
634
  signers: get_signers(options[:signers])
564
635
  },
565
- status: "#{options[:status]}"
636
+ status: "#{options[:status]}",
637
+ customFields: options[:custom_fields]
566
638
  }.to_json
567
639
 
568
640
  uri = build_uri("/accounts/#{acct_id}/envelopes")
@@ -684,8 +756,9 @@ module DocusignRest
684
756
  emailSubject: options[:email][:subject],
685
757
  templateId: options[:template_id],
686
758
  eventNotification: get_event_notification(options[:event_notification]),
687
- templateRoles: get_template_roles(options[:signers])
688
- }.to_json
759
+ templateRoles: get_template_roles(options[:signers]),
760
+ customFields: options[:custom_fields]
761
+ }.to_json
689
762
 
690
763
  uri = build_uri("/accounts/#{acct_id}/envelopes")
691
764
 
@@ -699,6 +772,58 @@ module DocusignRest
699
772
  end
700
773
 
701
774
 
775
+ # Public: create an envelope for delivery from a composite template
776
+ #
777
+ # headers - Optional hash of headers to merge into the existing
778
+ # required headers for a POST request.
779
+ # status - Options include: 'sent', or 'created' and
780
+ # determine if the envelope is sent out immediately or
781
+ # stored for sending at a later time
782
+ # email/body - Sets the text in the email body
783
+ # email/subject - Sets the text in the email subject line
784
+ # files - Sets documents to be used instead of inline or server templates
785
+ # template_roles - See the get_template_roles method definition for a list
786
+ # of options to pass. Note: for consistency sake we call
787
+ # this 'signers' and not 'templateRoles' when we build up
788
+ # the request in client code.
789
+ # headers - Optional hash of headers to merge into the existing
790
+ # required headers for a multipart request.
791
+ # server_template_ids - Array of ids for templates uploaded to DocuSign. Templates
792
+ # will be added in the order they appear in the array.
793
+ #
794
+ # Returns a JSON parsed response body containing the envelope's:
795
+ # envelopeId - autogenerated ID provided by Docusign
796
+ # uri - the URI where the template is located on the DocuSign servers
797
+ # statusDateTime - The date/time the envelope was created
798
+ # status - Sent, created, or voided
799
+ def create_envelope_from_composite_template(options={})
800
+ file_params = {}
801
+
802
+ if options[:files]
803
+ ios = create_file_ios(options[:files])
804
+ file_params = create_file_params(ios)
805
+ end
806
+
807
+ post_body = {
808
+ emailBlurb: "#{options[:email][:body] if options[:email]}",
809
+ emailSubject: "#{options[:email][:subject] if options[:email]}",
810
+ status: options[:status],
811
+ compositeTemplates: get_composite_template(options[:server_template_ids], options[:signers], options[:files])
812
+ }.to_json
813
+
814
+ uri = build_uri("/accounts/#{acct_id}/envelopes")
815
+
816
+ http = initialize_net_http_ssl(uri)
817
+
818
+ request = initialize_net_http_multipart_post_request(
819
+ uri, post_body, file_params, headers(options[:headers])
820
+ )
821
+
822
+ response = http.request(request)
823
+ JSON.parse(response.body)
824
+ end
825
+
826
+
702
827
  # Public returns the names specified for a given email address (existing docusign user)
703
828
  #
704
829
  # email - the email of the recipient
@@ -755,6 +880,29 @@ module DocusignRest
755
880
  JSON.parse(response.body)
756
881
  end
757
882
 
883
+ # Public returns the URL for embedded sending
884
+ #
885
+ # envelope_id - the ID of the envelope you wish to use
886
+ # return_url - the URL you want the user to be directed to after he or she
887
+ # closes the view
888
+ # headers - optional hash of headers to merge into the existing
889
+ # required headers for a multipart request.
890
+ #
891
+ # Returns the URL string for embedded sending
892
+ def get_sender_view(options = {})
893
+ content_type = { 'Content-Type' => 'application/json' }
894
+ content_type.merge(options[:headers]) if options[:headers]
895
+
896
+ uri = build_uri("/accounts/#{acct_id}/envelopes/#{options[:envelope_id]}/views/sender")
897
+
898
+ http = initialize_net_http_ssl(uri)
899
+
900
+ request = Net::HTTP::Post.new(uri.request_uri, headers(content_type))
901
+ request.body = { returnUrl: options[:return_url] }.to_json
902
+
903
+ response = http.request(request)
904
+ JSON.parse(response.body)
905
+ end
758
906
 
759
907
  # Public returns the URL for embedded console
760
908
  #
@@ -789,7 +937,7 @@ module DocusignRest
789
937
  #
790
938
  # include_tabs - boolean, determines if the tabs for each signer will be
791
939
  # returned in the response, defaults to false.
792
- # envelope_id - ID of the envelope for which you want to retrive the
940
+ # envelope_id - ID of the envelope for which you want to retrieve the
793
941
  # signer info
794
942
  # headers - optional hash of headers to merge into the existing
795
943
  # required headers for a multipart request.
@@ -915,6 +1063,46 @@ module DocusignRest
915
1063
  end
916
1064
 
917
1065
 
1066
+ # Public retrieves a PDF containing the combined content of all
1067
+ # documents and the certificate for the given envelope.
1068
+ #
1069
+ # envelope_id - ID of the envelope from which the doc will be retrieved
1070
+ # local_save_path - Local absolute path to save the doc to including the
1071
+ # filename itself
1072
+ # headers - Optional hash of headers to merge into the existing
1073
+ # required headers for a multipart request.
1074
+ #
1075
+ # Example
1076
+ #
1077
+ # client.get_combined_document_from_envelope(
1078
+ # envelope_id: @envelope_response['envelopeId'],
1079
+ # local_save_path: 'docusign_docs/file_name.pdf',
1080
+ # return_stream: true/false # will return the bytestream instead of saving doc to file system.
1081
+ # )
1082
+ #
1083
+ # Returns the PDF document as a byte stream.
1084
+ def get_combined_document_from_envelope(options={})
1085
+ content_type = { 'Content-Type' => 'application/json' }
1086
+ content_type.merge(options[:headers]) if options[:headers]
1087
+
1088
+ uri = build_uri("/accounts/#{acct_id}/envelopes/#{options[:envelope_id]}/documents/combined")
1089
+
1090
+ http = initialize_net_http_ssl(uri)
1091
+ request = Net::HTTP::Get.new(uri.request_uri, headers(content_type))
1092
+ response = http.request(request)
1093
+ return response.body if options[:return_stream]
1094
+
1095
+ split_path = options[:local_save_path].split('/')
1096
+ split_path.pop #removes the document name and extension from the array
1097
+ path = split_path.join("/") #rejoins the array to form path to the folder that will contain the file
1098
+
1099
+ FileUtils.mkdir_p(path)
1100
+ File.open(options[:local_save_path], 'wb') do |output|
1101
+ output << response.body
1102
+ end
1103
+ end
1104
+
1105
+
918
1106
  # Public moves the specified envelopes to the given folder
919
1107
  #
920
1108
  # envelope_ids - IDs of the envelopes to be moved
@@ -949,6 +1137,42 @@ module DocusignRest
949
1137
  end
950
1138
 
951
1139
 
1140
+ # Public returns a hash of audit events for a given envelope
1141
+ #
1142
+ # envelope_id - ID of the envelope to get audit events from
1143
+ #
1144
+ #
1145
+ # Example
1146
+ # client.get_envelope_audit_events(
1147
+ # envelope_id: "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx"
1148
+ # )
1149
+ # Returns a hash of the events that have happened to the envelope.
1150
+ def get_envelope_audit_events(options = {})
1151
+ content_type = { 'Content-Type' => 'application/json' }
1152
+ content_type.merge(options[:headers]) if options[:headers]
1153
+
1154
+ uri = build_uri("/accounts/#{acct_id}/envelopes/#{options[:envelope_id]}/audit_events")
1155
+
1156
+ http = initialize_net_http_ssl(uri)
1157
+ request = Net::HTTP::Get.new(uri.request_uri, headers(content_type))
1158
+ response = http.request(request)
1159
+
1160
+ JSON.parse(response.body)
1161
+ end
1162
+
1163
+ # Public retrieves folder information. Helpful to use before client.search_folder_for_envelopes
1164
+ def get_folder_list(options={})
1165
+ content_type = { 'Content-Type' => 'application/json' }
1166
+ content_type.merge(options[:headers]) if options[:headers]
1167
+
1168
+ uri = build_uri("/accounts/#{@acct_id}/folders/")
1169
+
1170
+ http = initialize_net_http_ssl(uri)
1171
+ request = Net::HTTP::Get.new(uri.request_uri, headers(content_type))
1172
+ response = http.request(request)
1173
+ JSON.parse(response.body)
1174
+ end
1175
+
952
1176
  # Public retrieves the envelope(s) from a specific folder based on search params.
953
1177
  #
954
1178
  # Option Query Terms(none are required):
@@ -1053,6 +1277,20 @@ module DocusignRest
1053
1277
  end
1054
1278
 
1055
1279
 
1280
+ # Public: Retrieves a list of templates used in an envelope
1281
+ #
1282
+ # Returns templateId, name and uri for each template found.
1283
+ #
1284
+ # envelope_id - DS id of envelope with templates.
1285
+ def get_templates_in_envelope(envelope_id)
1286
+ uri = build_uri("/accounts/#{acct_id}/envelopes/#{envelope_id}/templates")
1287
+
1288
+ http = initialize_net_http_ssl(uri)
1289
+ request = Net::HTTP::Get.new(uri.request_uri, headers({ 'Content-Type' => 'application/json' }))
1290
+ JSON.parse(http.request(request).body)
1291
+ end
1292
+
1293
+
1056
1294
  # Grabs envelope data.
1057
1295
  # Equivalent to the following call in the API explorer:
1058
1296
  # Get Envelopev2/accounts/:accountId/envelopes/:envelopeId
@@ -1067,5 +1305,190 @@ module DocusignRest
1067
1305
  response = http.request(request)
1068
1306
  JSON.parse(response.body)
1069
1307
  end
1308
+
1309
+
1310
+ # Public deletes a recipient for a given envelope
1311
+ #
1312
+ # envelope_id - ID of the envelope for which you want to retrieve the
1313
+ # signer info
1314
+ # recipient_id - ID of the recipient to delete
1315
+ #
1316
+ # Returns a hash of recipients with an error code for any recipients that
1317
+ # were not successfully deleted.
1318
+ def delete_envelope_recipient(options={})
1319
+ content_type = {'Content-Type' => 'application/json'}
1320
+ content_type.merge(options[:headers]) if options[:headers]
1321
+
1322
+ uri = build_uri("/accounts/#{@acct_id}/envelopes/#{options[:envelope_id]}/recipients")
1323
+ post_body = "{
1324
+ \"signers\" : [{\"recipientId\" : \"#{options[:recipient_id]}\"}]
1325
+ }"
1326
+
1327
+ http = initialize_net_http_ssl(uri)
1328
+ request = Net::HTTP::Delete.new(uri.request_uri, headers(content_type))
1329
+ request.body = post_body
1330
+
1331
+ response = http.request(request)
1332
+ JSON.parse(response.body)
1333
+ end
1334
+
1335
+
1336
+ # Public voids an in-process envelope
1337
+ #
1338
+ # envelope_id - ID of the envelope to be voided
1339
+ # voided_reason - Optional reason for the envelope being voided
1340
+ #
1341
+ # Returns the response (success or failure).
1342
+ def void_envelope(options = {})
1343
+ content_type = { 'Content-Type' => 'application/json' }
1344
+ content_type.merge(options[:headers]) if options[:headers]
1345
+
1346
+ post_body = {
1347
+ "status" =>"voided",
1348
+ "voidedReason" => options[:voided_reason] || "No reason provided."
1349
+ }.to_json
1350
+
1351
+ uri = build_uri("/accounts/#{acct_id}/envelopes/#{options[:folder_id]}")
1352
+
1353
+ http = initialize_net_http_ssl(uri)
1354
+ request = Net::HTTP::Put.new(uri.request_uri, headers(content_type))
1355
+ request.body = post_body
1356
+ http.request(request)
1357
+ end
1358
+
1359
+ # Public deletes a document for a given envelope
1360
+ # See https://www.docusign.com/p/RESTAPIGuide/RESTAPIGuide.htm#REST API References/Remove Documents from a Draft Envelope.htm%3FTocPath%3DREST%2520API%2520References%7C_____54
1361
+ #
1362
+ # envelope_id - ID of the envelope from which the doc will be retrieved
1363
+ # document_id - ID of the document to delete
1364
+ #
1365
+ # Returns the success or failure of each document being added to the envelope and
1366
+ # the envelope ID. Failed operations on array elements will add the "errorDetails"
1367
+ # structure containing an error code and message. If "errorDetails" is null, then
1368
+ # the operation was successful for that item.
1369
+ def delete_envelope_document(options={})
1370
+ content_type = {'Content-Type' => 'application/json'}
1371
+ content_type.merge(options[:headers]) if options[:headers]
1372
+
1373
+ uri = build_uri("/accounts/#{@acct_id}/envelopes/#{options[:envelope_id]}/documents")
1374
+ post_body = {
1375
+ documents: [
1376
+ { documentId: options[:document_id] }
1377
+ ]
1378
+ }.to_json
1379
+
1380
+ http = initialize_net_http_ssl(uri)
1381
+ request = Net::HTTP::Delete.new(uri.request_uri, headers(content_type))
1382
+ request.body = post_body
1383
+
1384
+ response = http.request(request)
1385
+ JSON.parse(response.body)
1386
+ end
1387
+
1388
+ # Public adds a document to a given envelope
1389
+ # See https://www.docusign.com/p/RESTAPIGuide/RESTAPIGuide.htm#REST API References/Add Document.htm%3FTocPath%3DREST%2520API%2520References%7C_____56
1390
+ #
1391
+ # envelope_id - ID of the envelope from which the doc will be added
1392
+ # document_id - ID of the document to add
1393
+ # file_path - Local or remote path to file
1394
+ # content_type - optional content type for file. Defaults to application/pdf.
1395
+ # file_name - optional name for file. Defaults to basename of file_path.
1396
+ # file_extension - optional extension for file. Defaults to extname of file_name.
1397
+ #
1398
+ # The response only returns a success or failure.
1399
+ def add_envelope_document(options={})
1400
+ options[:content_type] ||= 'application/pdf'
1401
+ options[:file_name] ||= File.basename(options[:file_path])
1402
+ options[:file_extension] ||= File.extname(options[:file_name])[1..-1]
1403
+
1404
+ headers = {
1405
+ 'Content-Type' => options[:content_type],
1406
+ 'Content-Disposition' => "file; filename=\"#{options[:file_name]}\"; documentid=#{options[:document_id]}; fileExtension=\"#{options[:file_extension]}\""
1407
+ }
1408
+
1409
+ uri = build_uri("/accounts/#{@acct_id}/envelopes/#{options[:envelope_id]}/documents/#{options[:document_id]}")
1410
+ post_body = open(options[:file_path]).read
1411
+
1412
+ http = initialize_net_http_ssl(uri)
1413
+ request = Net::HTTP::Put.new(uri.request_uri, headers(headers))
1414
+ request.body = post_body
1415
+
1416
+ http.request(request)
1417
+ end
1418
+
1419
+ # Public adds signers to a given envelope
1420
+ # See https://www.docusign.com/p/RESTAPIGuide/RESTAPIGuide.htm#REST%20API%20References/Add%20Recipients%20to%20an%20Envelope.htm%3FTocPath%3DREST%2520API%2520References|_____77
1421
+ #
1422
+ # envelope_id - ID of the envelope to which the recipient will be added
1423
+ # signers - Array of hashes
1424
+ # See https://www.docusign.com/p/RESTAPIGuide/RESTAPIGuide.htm#REST%20API%20References/Recipients/Signers%20Recipient.htm%3FTocPath%3DREST%2520API%2520References|Send%2520an%2520Envelope%2520or%2520Create%2520a%2520Draft%2520Envelope|Recipient%2520Parameters|_____7
1425
+ #
1426
+ # TODO: This could be made more general as an add_envelope_recipient method
1427
+ # to handle recipient types other than Signer
1428
+ # See: https://www.docusign.com/p/RESTAPIGuide/RESTAPIGuide.htm#REST%20API%20References/Recipient%20Parameter.htm%3FTocPath%3DREST%2520API%2520References|Send%2520an%2520Envelope%2520or%2520Create%2520a%2520Draft%2520Envelope|Recipient%2520Parameters|_____0
1429
+ def add_envelope_signers(options = {})
1430
+ content_type = { "Content-Type" => "application/json" }
1431
+ content_type.merge(options[:headers]) if options[:headers]
1432
+
1433
+ uri = build_uri("/accounts/#{@acct_id}/envelopes/#{options[:envelope_id]}/recipients")
1434
+ post_body = { signers: options[:signers] }.to_json
1435
+
1436
+ http = initialize_net_http_ssl(uri)
1437
+ request = Net::HTTP::Put.new(uri.request_uri, headers(content_type))
1438
+ request.body = post_body
1439
+
1440
+ response = http.request(request)
1441
+ JSON.parse(response.body)
1442
+ end
1443
+
1444
+ # Public adds recipient tabs to a given envelope
1445
+ # See https://www.docusign.com/p/RESTAPIGuide/RESTAPIGuide.htm#REST API References/Add Tabs for a Recipient.htm%3FTocPath%3DREST%2520API%2520References%7C_____86
1446
+ #
1447
+ # envelope_id - ID of the envelope from which the doc will be added
1448
+ # recipient - ID of the recipient to add tabs to
1449
+ # tabs - hash of tab (see example below)
1450
+ # {
1451
+ # signHereTabs: [
1452
+ # {
1453
+ # anchorString: '/s1/',
1454
+ # anchorXOffset: '5',
1455
+ # anchorYOffset: '8',
1456
+ # anchorIgnoreIfNotPresent: 'true',
1457
+ # documentId: '1',
1458
+ # pageNumber: '1',
1459
+ # recipientId: '1'
1460
+ # }
1461
+ # ],
1462
+ # initialHereTabs: [
1463
+ # {
1464
+ # anchorString: '/i1/',
1465
+ # anchorXOffset: '5',
1466
+ # anchorYOffset: '8',
1467
+ # anchorIgnoreIfNotPresent: 'true',
1468
+ # documentId: '1',
1469
+ # pageNumber: '1',
1470
+ # recipientId: '1'
1471
+ # }
1472
+ # ]
1473
+ # }
1474
+ #
1475
+ # The response returns the success or failure of each document being added
1476
+ # to the envelope and the envelope ID. Failed operations on array elements
1477
+ # will add the "errorDetails" structure containing an error code and message.
1478
+ # If "errorDetails" is null, then the operation was successful for that item.
1479
+ def add_recipient_tabs(options={})
1480
+ content_type = {'Content-Type' => 'application/json'}
1481
+ content_type.merge(options[:headers]) if options[:headers]
1482
+
1483
+ uri = build_uri("/accounts/#{@acct_id}/envelopes/#{options[:envelope_id]}/recipients/#{options[:recipient_id]}/tabs")
1484
+ post_body = options[:tabs].to_json
1485
+
1486
+ http = initialize_net_http_ssl(uri)
1487
+ request = Net::HTTP::Post.new(uri.request_uri, headers(content_type))
1488
+ request.body = post_body
1489
+
1490
+ response = http.request(request)
1491
+ JSON.parse(response.body)
1492
+ end
1070
1493
  end
1071
1494
  end
@@ -1,3 +1,3 @@
1
1
  module DocusignRest
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -11,10 +11,10 @@ namespace :docusign_rest do
11
11
  STDOUT.puts %Q{
12
12
  Please do the following:
13
13
  ------------------------
14
- 1) Login or register for an account at demo.docusign.net
14
+ 1) Login or register for an account at https://demo.docusign.net
15
15
  ...or their production url if applicable
16
- 2) Click 'Preferences' in the upper right corner of the page
17
- 3) Click 'API' in far lower left corner of the menu
16
+ 2) From the Avatar menu in the upper right hand corner of the page, click "Go to Admin"
17
+ 3) From the left sidebar menu, click "API and Keys"
18
18
  4) Request a new 'Integrator Key' via the web interface
19
19
  * You will use this key in one of the next steps to retrieve your 'accountId'\n\n}
20
20
 
@@ -1,4 +1,4 @@
1
- require 'helper'
1
+ require_relative '../helper'
2
2
 
3
3
  describe DocusignRest::Client do
4
4
 
@@ -82,6 +82,10 @@ describe DocusignRest::Client do
82
82
  @client.must_respond_to :acct_id
83
83
  end
84
84
 
85
+ it "should return the value of acct_id" do
86
+ @client.get_account_id.must_equal @client.acct_id
87
+ end
88
+
85
89
  it "should allow creating an envelope from a document" do
86
90
  VCR.use_cassette("create_envelope/from_document") do
87
91
  response = @client.create_envelope_from_document(
@@ -114,6 +118,7 @@ describe DocusignRest::Client do
114
118
  anchor_x_offset: '10',
115
119
  anchor_y_offset: '-5',
116
120
  label: 'another test',
121
+ selected: true,
117
122
  list_items: [
118
123
  {
119
124
  selected: false,
@@ -261,6 +266,32 @@ describe DocusignRest::Client do
261
266
  # NOTE manually check that this file has the content you'd expect
262
267
  end
263
268
  end
269
+
270
+ it "should add signers to an envelope" do
271
+ VCR.use_cassette("add_envelope_signers") do
272
+ response = @client.add_envelope_signers(
273
+ envelope_id: @envelope_response["envelopeId"],
274
+ signers: [{
275
+ email: "signer@example.com",
276
+ name: "Signer Person",
277
+ recipientId: 2,
278
+ }],
279
+ )
280
+
281
+ response["recipientUpdateResults"].first["errorDetails"]["errorCode"]
282
+ .must_equal "SUCCESS"
283
+ end
284
+ end
285
+ it "should get envelope's sender view" do
286
+ VCR.use_cassette("get_envelope_sender_view") do
287
+ response = @client.get_sender_view(
288
+ envelope_id: @envelope_response["envelopeId"],
289
+ )
290
+
291
+ response['errorCode'].must_be_nil
292
+ response['url'].must_match(/http/)
293
+ end
294
+ end
264
295
  end
265
296
  end
266
297
  end
@@ -1,4 +1,4 @@
1
- require 'helper'
1
+ require_relative '../helper'
2
2
 
3
3
  describe DocusignRest do
4
4
  it "should have a version" do
data/test/helper.rb CHANGED
@@ -9,6 +9,6 @@ require 'pry'
9
9
 
10
10
  VCR.configure do |c|
11
11
  c.cassette_library_dir = "test/fixtures/vcr"
12
- c.hook_into :fakeweb
12
+ c.hook_into :webmock
13
13
  c.default_cassette_options = { record: :all }
14
14
  end
metadata CHANGED
@@ -1,153 +1,153 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docusign_rest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Kinney
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-03 00:00:00.000000000 Z
11
+ date: 2017-04-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multipart-post
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: json
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: minitest
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '4.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '4.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: guard-minitest
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rb-fsevent
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ~>
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0.9'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ~>
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0.9'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: turn
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - '>='
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - '>='
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: pry
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - '>='
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - '>='
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: vcr
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - '>='
129
+ - - ">="
130
130
  - !ruby/object:Gem::Version
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - '>='
136
+ - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  - !ruby/object:Gem::Dependency
140
- name: fakeweb
140
+ name: webmock
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - '>='
143
+ - - ">="
144
144
  - !ruby/object:Gem::Version
145
145
  version: '0'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - '>='
150
+ - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
153
  description: Hooks a Rails app up to the DocuSign service through the DocuSign REST
@@ -158,7 +158,8 @@ executables: []
158
158
  extensions: []
159
159
  extra_rdoc_files: []
160
160
  files:
161
- - .gitignore
161
+ - ".gitignore"
162
+ - CHANGELOG.md
162
163
  - Gemfile
163
164
  - Guardfile
164
165
  - LICENSE
@@ -185,7 +186,8 @@ files:
185
186
  - test/helper.rb
186
187
  - test2.pdf
187
188
  homepage: https://github.com/jondkinney/docusign_rest
188
- licenses: []
189
+ licenses:
190
+ - MIT
189
191
  metadata: {}
190
192
  post_install_message:
191
193
  rdoc_options: []
@@ -193,17 +195,17 @@ require_paths:
193
195
  - lib
194
196
  required_ruby_version: !ruby/object:Gem::Requirement
195
197
  requirements:
196
- - - '>='
198
+ - - ">="
197
199
  - !ruby/object:Gem::Version
198
200
  version: 1.9.2
199
201
  required_rubygems_version: !ruby/object:Gem::Requirement
200
202
  requirements:
201
- - - '>='
203
+ - - ">="
202
204
  - !ruby/object:Gem::Version
203
205
  version: '0'
204
206
  requirements: []
205
207
  rubyforge_project:
206
- rubygems_version: 2.0.6
208
+ rubygems_version: 2.6.8
207
209
  signing_key:
208
210
  specification_version: 4
209
211
  summary: Use this gem to embed signing of documents in a Rails app through the DocuSign