rightsignature-railstyle 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,15 @@
1
+ require 'httparty'
2
+ require 'xml-fu'
3
+ require 'oauth'
4
+ require 'rightsignature/errors'
5
+ require 'rightsignature/helpers/normalizing'
6
+ require 'rightsignature/helpers/refine_hash_to_indifferent_access'
7
+ require 'rightsignature/document'
8
+ require 'rightsignature/template'
9
+ require 'rightsignature/account'
10
+ require 'rightsignature/connection/oauth_connection'
11
+ require 'rightsignature/connection/token_connection'
12
+ require 'rightsignature/connection'
13
+ require 'rightsignature/rails_style'
14
+
15
+ XmlFu.config.symbol_conversion_algorithm = :none
@@ -0,0 +1,37 @@
1
+ module RightSignature
2
+ module Account
3
+ # Return account information about API user
4
+ #
5
+ # Ex.
6
+ # @rs_connection.user_details
7
+ #
8
+ def user_details
9
+ get "/api/users/user_details.xml"
10
+ end
11
+
12
+ # Creates a user on API user's account
13
+ # * name: User's name
14
+ # * email: User's email
15
+ #
16
+ # Ex.
17
+ # @rs_connection.add_user("John Bellingham", "john@example.com")
18
+ #
19
+ def add_user(name, email)
20
+ post "/api/users.xml", {:user => {:name => name, :email => email}}
21
+ end
22
+
23
+ # Return account's usage report (# of documents sent)
24
+ # * <b>since</b>: ("month"/"week"/"day") only count documents sent within a certain time
25
+ # * <b>signed</b>: (true/false) only count signed document
26
+ #
27
+ # Ex. Return count of signed documents sent this month
28
+ # @rs_connection.usage_report("month", true)
29
+ #
30
+ def usage_report(since=nil, signed=nil)
31
+ options = {}
32
+ options[:since] = since if since && ["month", "week", "day"].include?(since)
33
+ options[:signed] = signed.to_s unless signed.nil?
34
+ get "/api/account/usage_report.xml", options
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,207 @@
1
+ module RightSignature
2
+ class Connection
3
+ include RightSignature::Document
4
+ include RightSignature::Account
5
+ include RightSignature::Template
6
+
7
+ attr_accessor :configuration
8
+ attr_accessor :oauth_connection
9
+ attr_accessor :token_connection
10
+
11
+ # Creates new instance of RightSignature::Connection to make API calls
12
+ # * <b>creds</b>: Hash of credentials for API Token or OAuth. If both are specified, it uses API Token
13
+ # * Hash key for API Token:
14
+ # * :api_token
15
+ # * Hash keys for OAuth:
16
+ # * :consumer_key
17
+ # * :consumer_secret
18
+ # * :access_token
19
+ # * :access_secret
20
+ #
21
+ # Example for Api Token:
22
+ # @rs_connection = RightSignature::Connection.new(:api_token => "MYTOKEN")
23
+ #
24
+ # Example for OAuth:
25
+ # @rs_connection = RightSignature::Connection.new(:consumer_key => "ckey", :consumer_secret => "csecret", :access_token => "atoken", :access_secret => "asecret")
26
+ #
27
+ def initialize(creds={})
28
+ @configuration = {}
29
+ RightSignature::Connection.oauth_keys.each do |key|
30
+ @configuration[key] = creds[key].to_s
31
+ end
32
+
33
+ RightSignature::Connection.api_token_keys.each do |key|
34
+ @configuration[key] = creds[key].to_s
35
+ end
36
+
37
+ @token_connection = RightSignature::TokenConnection.new(*RightSignature::Connection.api_token_keys.map{|k| @configuration[k]})
38
+ @oauth_connection = RightSignature::OauthConnection.new(@configuration)
39
+
40
+ @configuration
41
+ end
42
+
43
+ # Checks if credentials are set for either API Token or for OAuth
44
+ #
45
+ def check_credentials
46
+ raise "Please set load_configuration with #{RightSignature::Connection.api_token_keys.join(',')} or #{RightSignature::Connection.oauth_keys.join(',')}" unless has_api_token? || has_oauth_credentials?
47
+ end
48
+
49
+ # Checks if API Token credentials are set. Does not validate creds with server.
50
+ #
51
+ def has_api_token?
52
+ return false if @configuration.nil?
53
+ RightSignature::Connection.api_token_keys.each do |key|
54
+ return false if @configuration[key].nil? || @configuration[key].match(/^\s*$/)
55
+ end
56
+
57
+ return true
58
+ end
59
+
60
+ # Checks if OAuth credentials are set. Does not validate creds with server.
61
+ #
62
+ def has_oauth_credentials?
63
+ return false if @configuration.nil?
64
+ RightSignature::Connection.oauth_keys.each do |key|
65
+ return false if @configuration[key].nil? || @configuration[key].match(/^\s*$/)
66
+ end
67
+
68
+ return true
69
+ end
70
+
71
+ # :nodoc:
72
+ def self.oauth_keys
73
+ [:consumer_key, :consumer_secret, :access_token, :access_secret].freeze
74
+ end
75
+
76
+ # :nodoc:
77
+ def self.api_token_keys
78
+ [:api_token].freeze
79
+ end
80
+
81
+ # :nodoc:
82
+ def site
83
+ if has_api_token?
84
+ RightSignature::TokenConnection.base_uri
85
+ else
86
+ @oauth_connection.oauth_consumer.site
87
+ end
88
+ end
89
+
90
+ # PUT request to server
91
+ #
92
+ # Arguments:
93
+ # url: Path of API call
94
+ # body: XML body in hash format
95
+ # url: Hash of HTTP headers to include
96
+ #
97
+ # Example:
98
+ # @rs_connection.put("/api/documents.xml", {:documents=> {}}, {"User-Agent" => "My Own"})
99
+ #
100
+ def put(url, body={}, headers={})
101
+ if has_api_token?
102
+ options = {}
103
+ options[:headers] = headers
104
+ options[:body] = XmlFu.xml(body)
105
+
106
+ parse_response(@token_connection.request(:put, url, options))
107
+ else
108
+ parse_response(@oauth_connection.request(:put, url, XmlFu.xml(body), headers))
109
+ end
110
+ end
111
+
112
+ # DELETE request to server
113
+ #
114
+ # Arguments:
115
+ # url: Path of API call
116
+ # url: Hash of HTTP headers to include
117
+ #
118
+ # Example:
119
+ # @rs_connection.delete("/api/users.xml", {"User-Agent" => "My Own"})
120
+ #
121
+ def delete(url, headers={})
122
+ if has_api_token?
123
+ options = {}
124
+ options[:headers] = headers
125
+
126
+ parse_response(@token_connection.request(:delete, url, options))
127
+ else
128
+ parse_response(@oauth_connection.request(:delete, url, headers))
129
+ end
130
+ end
131
+
132
+ # GET request to server
133
+ #
134
+ # Arguments:
135
+ # url: Path of API call
136
+ # params: Hash of URL parameters to include in request
137
+ # url: Hash of HTTP headers to include
138
+ #
139
+ # Example:
140
+ # @rs_connection.get("/api/documents.xml", {:search => "my term"}, {"User-Agent" => "My Own"})
141
+ #
142
+ def get(url, params={}, headers={})
143
+ check_credentials
144
+
145
+ if has_api_token?
146
+ options = {}
147
+ options[:headers] = headers
148
+ options[:query] = params
149
+ parse_response(@token_connection.request(:get, url, options))
150
+ else
151
+ unless params.empty?
152
+ url = "#{url}?#{params.sort.map{|param| URI.escape("#{param[0]}=#{param[1]}")}.join('&')}"
153
+ end
154
+ parse_response(@oauth_connection.request(:get, url, headers))
155
+ end
156
+ end
157
+
158
+ # POST request to server
159
+ #
160
+ # Arguments:
161
+ # url: Path of API call
162
+ # url: Hash of HTTP headers to include
163
+ #
164
+ # Example:
165
+ # @rs_connection.post("/api/users.xml", {"User-Agent" => "My Own"})
166
+ #
167
+ def post(url, body={}, headers={})
168
+ check_credentials
169
+
170
+ if has_api_token?
171
+ options = {}
172
+ options[:headers] = headers
173
+ options[:body] = XmlFu.xml(body)
174
+ parse_response(@token_connection.request(:post, url, options))
175
+ else
176
+ parse_response(@oauth_connection.request(:post, url, XmlFu.xml(body), headers))
177
+ end
178
+ end
179
+
180
+ # Attempts to parse response from a connection and return it as a hash.
181
+ # If response isn't a success, an RightSignature::ResponseError is raised
182
+ #
183
+ # Arguments:
184
+ # url: Path of API call
185
+ # url: Hash of HTTP headers to include
186
+ #
187
+ # Example:
188
+ # @rs_connection.delete("/api/users.xml", {"User-Agent" => "My Own"})
189
+ #
190
+ def parse_response(response)
191
+ if response.is_a? Net::HTTPResponse
192
+ unless response.is_a? Net::HTTPSuccess
193
+ raise RightSignature::ResponseError.new(response)
194
+ end
195
+
196
+ MultiXml.parse(response.body)
197
+ else
198
+ unless response.success?
199
+ raise RightSignature::ResponseError.new(response)
200
+ end
201
+
202
+ response.parsed_response
203
+ end
204
+ end
205
+
206
+ end
207
+ end
@@ -0,0 +1,109 @@
1
+ module RightSignature
2
+ class OauthConnection
3
+ attr_reader :request_token
4
+ attr_reader :consumer_key, :consumer_secret, :oauth_access_token, :oauth_access_secret
5
+
6
+ # Creates new instance of RightSignature::OauthConnection to make API calls
7
+ # * <b>creds</b>: Hash of credentials for OAuth.
8
+ # * Hash keys for OAuth:
9
+ # * :consumer_key
10
+ # * :consumer_secret
11
+ # * :access_token
12
+ # * :access_secret
13
+ #
14
+ # Example:
15
+ # @rs_oauth = RightSignature::OauthConnection.new(:consumer_key => "ckey", :consumer_secret => "csecret", :access_token => "atoken", :access_secret => "asecret")
16
+ #
17
+ def initialize(credentials={})
18
+ @consumer_key = credentials[:consumer_key]
19
+ @consumer_secret = credentials[:consumer_secret]
20
+ @oauth_access_token = credentials[:access_token]
21
+ @oauth_access_secret = credentials[:access_secret]
22
+ end
23
+
24
+ # Oauth consumer
25
+ def oauth_consumer
26
+ check_credentials unless @consumer_key && @consumer_secret
27
+ @oauth_consumer ||= OAuth::Consumer.new(
28
+ @consumer_key,
29
+ @consumer_secret,
30
+ {
31
+ :site => "https://rightsignature.com",
32
+ :scheme => :header,
33
+ :http_method => :post,
34
+ :authorize_path =>'/oauth/authorize',
35
+ :access_token_path =>'/oauth/access_token',
36
+ :request_token_path=>'/oauth/request_token'
37
+ }
38
+ )
39
+ end
40
+
41
+ # Access token
42
+ def access_token
43
+ check_credentials
44
+ @access_token ||= OAuth::AccessToken.new(oauth_consumer, @oauth_access_token, @oauth_access_secret)
45
+ end
46
+
47
+ # Replaces access token
48
+ # * <b>access_token</b>: access token key
49
+ # * <b>access_secret</b>: access token secret
50
+ #
51
+ def set_access_token(access_token, access_secret)
52
+ @oauth_access_token = access_token
53
+ @oauth_access_secret = access_secret
54
+ @access_token = OAuth::AccessToken.new(oauth_consumer, @oauth_access_token, @oauth_access_secret)
55
+ end
56
+
57
+ # Uses consumer to generate a request token.
58
+ # * <b>o</b>: options hash. Use this to set the :oauth_callback
59
+ def new_request_token(o = {})
60
+ @request_token = oauth_consumer.get_request_token(o)
61
+ end
62
+
63
+ # Sets request token.
64
+ # * <b>request_token</b>: request token key
65
+ # * <b>request_token_secret</b>: request token secret
66
+ #
67
+ def set_request_token(request_token, request_token_secret)
68
+ @request_token = OAuth::RequestToken.new(oauth_consumer, request_token, request_token_secret)
69
+ end
70
+
71
+ # Uses request token and given OAuth verifier to generate an access token. Requires a request token to be set.
72
+ # * <b>oauth_verifier</b>: OAuth verifier
73
+ #
74
+ def generate_access_token(oauth_verifier)
75
+ raise "Please set request token with new_request_token" unless @request_token
76
+ @access_token = @request_token.get_access_token(:oauth_verifier => oauth_verifier)
77
+ @oauth_access_token = @access_token.token
78
+ @oauth_access_secret = @access_token.secret
79
+ @access_token
80
+ end
81
+
82
+ # Generates HTTP request with oauth credentials. Require access_token to be set.
83
+ # * <b>method</b>: HTTP Method. Ex. ('get'/'post'/'delete'/'put')
84
+ # * <b>options</b>: OAuth::AccessToken options to pass. Last option should be headers
85
+ #
86
+ def request(method, *options)
87
+ options.last ||= {}
88
+ options.last["Accept"] ||= "*/*"
89
+ options.last["content-type"] ||= "application/xml"
90
+
91
+ self.access_token.__send__(method, *options)
92
+ end
93
+
94
+ private
95
+ # Raises exception if OAuth credentials are not set.
96
+ def check_credentials
97
+ raise "Please set #{RightSignature::Connection.oauth_keys.join(', ')}" unless has_oauth_credentials?
98
+ end
99
+
100
+ # Checks if OAuth credentials are set.
101
+ def has_oauth_credentials?
102
+ [@consumer_key, @consumer_secret, @oauth_access_token, @oauth_access_secret].each do |cred|
103
+ return false if cred.nil? || cred.match(/^\s*$/)
104
+ end
105
+
106
+ true
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,36 @@
1
+ module RightSignature
2
+ class TokenConnection
3
+ include HTTParty
4
+ base_uri 'https://rightsignature.com'
5
+ format :xml
6
+
7
+ attr_reader :api_token
8
+
9
+ # Creates new instance of RightSignature::TokenConnection to make API calls
10
+ # * <b>api_token</b>: API Token.
11
+ #
12
+ # Example:
13
+ # @rs_token = RightSignature::TokenConnection.new("APITOKEN")
14
+ #
15
+ def initialize(api_token)
16
+ @api_token = api_token
17
+ end
18
+
19
+ # Generates HTTP request with token credentials. Require api_token to be set.
20
+ # * <b>method</b>: HTTP Method. Ex. ('get'/'post'/'delete'/'put')
21
+ # * <b>url</b>: request path/url of request
22
+ # * <b>options</b>: HTTPary options to pass. Last option should be headers
23
+ #
24
+ def request(method, url, options)
25
+ raise "Please set api_token" if @api_token.nil? || @api_token.empty?
26
+
27
+ options[:headers] ||= {}
28
+ options[:headers]['api-token'] = @api_token
29
+ options[:headers]["Accept"] ||= "*/*"
30
+ options[:headers]["content-type"] ||= "application/xml"
31
+ self.class.__send__(method, url, options)
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,333 @@
1
+ using RefineHashToIndifferentAccess
2
+
3
+ module RightSignature
4
+ module Document
5
+ include RightSignature::Helpers
6
+
7
+ # Lists documents
8
+ # * <b>options</b>: (optional) search filters
9
+ # * <b>:state</b> - (completed/trashed/pending) filter by state
10
+ # * <b>:page</b> - page offset
11
+ # * <b>:per_page</b> - # of entries per page to return
12
+ # * <b>:search</b> - search term filter
13
+ # * <b>:tags</b> - tags filter. Array of ["single_tag", {"tag_key" => "tag_value"}]
14
+ # * <b>:sort</> - sort documents by given attribute.
15
+ # API supports 'created', 'completed', and 'activity'
16
+ # * <b>:range</b> - ('today'/'thisweek'/'thismonth'/'alltime'/Date) return documents with a certain date range.
17
+ # * <b> :recipient_email</b> - filter document where it has a recipient with given email and involves the current OAuth user.
18
+ # * <b> :account</b> - (true/false) include all documents in current account if true.
19
+ #
20
+ # Ex.
21
+ # options = {
22
+ # :state => ['completed', 'trashed'],
23
+ # :page => 1,
24
+ # :per_page => 20,
25
+ # :search => "me",
26
+ # :tags => ["single_tag", "key" => "with_value"]
27
+ # }
28
+ #
29
+ # @rs_connection.documents_list(options)
30
+ #
31
+ def documents_list(options={})
32
+ if options[:metadata]
33
+ options[:tags] = TagsHelper.array_and_metadata_to_string_array(options[:tags], options.delete(:metadata))
34
+ elsif options[:tags]
35
+ options[:tags] = TagsHelper.mixed_array_to_string_array(options[:tags])
36
+ end
37
+ options[:state] = options[:state].join(',') if options[:state] && options[:state].is_a?(Array)
38
+ get "/api/documents.xml", options
39
+ end
40
+
41
+ # Gets details for a document
42
+ # * <b>guids</b>: Array of document GUIDs
43
+ #
44
+ # Ex. Get details for document GUID123
45
+ # @rs_connection.document_details("GUID123")
46
+ #
47
+ def document_details(guid)
48
+ get "/api/documents/#{guid}.xml"
49
+ end
50
+
51
+ # Gets details for multiple documents.
52
+ # * <b>guids</b>: Array of document GUIDs
53
+ #
54
+ # Ex. Get details for documents GUID123 and GUID345
55
+ # @rs_connection.documents_batch_details(["GUID123","GUID345"])
56
+ #
57
+ def documents_batch_details(guids)
58
+ get "/api/documents/#{guids.join(',')}/batch_details.xml"
59
+ end
60
+
61
+ # Sends a reminder for a document
62
+ # * <b>guid</b>: Document GUID
63
+ #
64
+ # Ex. Sends reminder for document GUID123
65
+ # @rs_connection.send_reminder("GUID123")
66
+ #
67
+ def send_reminder(guid)
68
+ post "/api/documents/#{guid}/send_reminders.xml", {}
69
+ end
70
+
71
+ # Extends a document's expiration date by 7 days
72
+ # * <b>guid</b>: Document GUID
73
+ #
74
+ # Ex. Extend expiration for document GUID123 by 7 days
75
+ # @rs_connection.trash_document("GUID123")
76
+ #
77
+ def trash_document(guid)
78
+ post "/api/documents/#{guid}/trash.xml", {}
79
+ end
80
+
81
+
82
+ # Extends a document's expiration date by 7 days
83
+ # * <b>guid</b>: Document GUID
84
+ #
85
+ # Ex. Extend expiration for document GUID123 by 7 days
86
+ # @rs_connection.extend_document_expiration("GUID123")
87
+ #
88
+ def extend_document_expiration(guid)
89
+ post "/api/documents/#{guid}/extend_expiration.xml", {}
90
+ end
91
+
92
+ # <b>REPLACE</b> the tags on a document
93
+ # tags are an array of 'tag_name' or {'tag_name' => 'value'}
94
+ #
95
+ # Ex. Replaces document GUID123 with tags "single_tag", "hello:bye"
96
+ # @rs_connection.update_document_tags("GUID123", ["single_tag", {"hello" => "bye"}])
97
+ def update_document_tags(guid, tags)
98
+ post "/api/documents/#{guid}/update_tags.xml", { :tags => TagsHelper.array_to_xml_hash(tags) }
99
+ end
100
+
101
+ # Creates a document from a raw data
102
+ # * <b>file</b>: file binary. Ex. File.read('myfile.pdf')
103
+ # * <b>filename</b>: original filename
104
+ # * <b>subject</b>: subject of the document that'll appear in email
105
+ # * <b>recipients</b>: Recipients of the document, should be an array of hashes with :name, :email, and :role ('cc' or 'signer').
106
+ # One of the recipients requires <b>:is_sender</b> (true/false) to reference the API User and won't need to supply :name and :email
107
+ # Ex. CC to support@rightsignature.com, with sender and john@rightsignature.com as a signer
108
+ # [
109
+ # {:name => "RightSignature", :email => "support@rightsignature.com", :role => 'cc'},
110
+ # {:name => "John Bellingham", :email => "john@rightsignature.com", :role => 'signer'},
111
+ # {'is_sender' => true, :role => 'signer'},
112
+ # ]
113
+ # * <b>options</b>: other optional values
114
+ # - <b>description</b>: document description that'll appear in the email
115
+ # - <b>action</b>: 'send' or 'redirect'. Redirect will return a token that will allow another person to send the document under API user's account
116
+ # - <b>expires_in</b>: number of days before expiring the document. API only allows 2,5,15, or 30.
117
+ # - <b>tags</b>: document tags, an array of string or hashes 'single_tag' (for simple tag) or {'tag_name' => 'tag_value'} (for tuples pairs)
118
+ # Ex. ['sent_from_api', {"user_id" => "32"}]
119
+ # - <b>callback_location</b>: A URI encoded URL that specifies the location for API to POST a callback notification to when the document has been created and signed.
120
+ # Ex. "http://yoursite/callback"
121
+ # - <b>use_text_tags</b>: Document has special Text Tags that RightSignature parse. true or false.
122
+ # More info: https://rightsignature.com/apidocs/text_tags
123
+ def send_document_from_data(file_data, filename, subject, recipients, options={})
124
+ send_document(subject, recipients, {:type => "base64", :filename => filename, :value => Base64::encode64(file_data)}, options)
125
+ end
126
+
127
+ # Creates a document from a File or path to file
128
+ # * <b>file</b>: Path to file or File object
129
+ # * <b>subject</b>: subject of the document that'll appear in email
130
+ # * <b>recipients</b>: Recipients of the document, should be an array of hashes with :name, :email, and :role ('cc' or 'signer').
131
+ # One of the recipients requires <b>:is_sender</b> (true/false) to reference the API User and won't need to supply :name and :email
132
+ # Ex. CC to support@rightsignature.com, with sender and john@rightsignature.com as a signer
133
+ # [
134
+ # {:name => "RightSignature", :email => "support@rightsignature.com", :role => 'cc'},
135
+ # {:name => "John Bellingham", :email => "john@rightsignature.com", :role => 'signer'},
136
+ # {'is_sender' => true, :role => 'signer'},
137
+ # ]
138
+ # * <b>options</b>: other optional values
139
+ # - <b>description</b>: document description that'll appear in the email
140
+ # - <b>action</b>: 'send' or 'redirect'. Redirect will return a token that will allow another person to send the document under API user's account
141
+ # - <b>expires_in</b>: number of days before expiring the document. API only allows 2,5,15, or 30.
142
+ # - <b>tags</b>: document tags, an array of string or hashes 'single_tag' (for simple tag) or {'tag_name' => 'tag_value'} (for tuples pairs)
143
+ # Ex. ['sent_from_api', {"user_id" => "32"}]
144
+ # - <b>callback_location</b>: A URI encoded URL that specifies the location for API to POST a callback notification to when the document has been created and signed.
145
+ # Ex. "http://yoursite/callback"
146
+ # - <b>use_text_tags</b>: Document has special Text Tags that RightSignature parse. true or false.
147
+ # More info: https://rightsignature.com/apidocs/text_tags
148
+ #
149
+ # Example:
150
+ # recipients = [
151
+ # {:name => "RightSignature", :email => "support@rightsignature.com", :role => 'cc'},
152
+ # {:name => "John Bellingham", :email => "john@rightsignature.com", :role => 'signer'},
153
+ # {'is_sender' => true, :role => 'signer'}
154
+ # ]
155
+ # options={
156
+ # :tags => [{:tag => {:name => 'sent_from_api'}}, {:tag => {:name => 'user_id', :value => '12345'}}],
157
+ # :expires_in => '5 days',
158
+ # :action => "redirect",
159
+ # 'callback_location' => "http://example.com/doc_callback",
160
+ # 'use_text_tags' => false
161
+ # }
162
+ # @rs_connection.send_document_from_file("here/is/myfile.pdf", 'My Subject', recipients, options)
163
+ #
164
+ def send_document_from_file(file, subject, recipients, options={})
165
+ send_document(subject, recipients, {:type => "base64", :filename => File.basename(file), :value => Base64::encode64(File.read(file)) }, options)
166
+ end
167
+
168
+ # Creates a document from URL
169
+ # * <b>url</b>: URL to file
170
+ # * <b>subject</b>: subject of the document that'll appear in email
171
+ # * <b>recipients</b>: Recipients of the document, should be an array of hashes with :name, :email, and :role ('cc' or 'signer').
172
+ # One of the recipients requires <b>:is_sender</b> (true/false) to reference the API User and won't need to supply :name and :email
173
+ # Ex. CC to support@rightsignature.com, with sender and john@rightsignature.com as a signer
174
+ # [
175
+ # {:name => "RightSignature", :email => "support@rightsignature.com", :role => 'cc'},
176
+ # {:name => "John Bellingham", :email => "john@rightsignature.com", :role => 'signer'},
177
+ # {'is_sender' => true, :role => 'signer'},
178
+ # ]
179
+ # * <b>options</b>: other optional values
180
+ # - <b>description</b>: document description that'll appear in the email
181
+ # - <b>action</b>: 'send' or 'redirect'. Redirect will return a token that will allow another person to send the document under API user's account
182
+ # - <b>expires_in</b>: number of days before expiring the document. API only allows 2,5,15, or 30.
183
+ # - <b>tags</b>: document tags, an array of string or hashes 'single_tag' (for simple tag) or {'tag_name' => 'tag_value'} (for tuples pairs)
184
+ # Ex. ['sent_from_api', {"user_id" => "32"}]
185
+ # - <b>callback_location</b>: A URI encoded URL that specifies the location for API to POST a callback notification to when the document has been created and signed.
186
+ # Ex. "http://yoursite/callback"
187
+ # - <b>use_text_tags</b>: Document has special Text Tags that RightSignature parse. true or false.
188
+ # More info: https://rightsignature.com/apidocs/text_tags
189
+ #
190
+ # Example:
191
+ # recipients = [
192
+ # {:name => "RightSignature", :email => "support@rightsignature.com", :role => 'cc'},
193
+ # {:name => "John Bellingham", :email => "john@rightsignature.com", :role => 'signer'},
194
+ # {'is_sender' => true, :role => 'signer'}
195
+ # ]
196
+ # options={
197
+ # :tags => [{:tag => {:name => 'sent_from_api'}}, {:tag => {:name => 'user_id', :value => '12345'}}],
198
+ # :expires_in => '5 days',
199
+ # :action => "redirect",
200
+ # 'callback_location' => "http://example.com/doc_callback",
201
+ # 'use_text_tags' => false
202
+ # }
203
+ # @rs_connection.send_document_from_url("http://myfile/here", 'My Subject', recipients, options)
204
+ #
205
+ def send_document_from_url(url, subject, recipients, options={})
206
+ send_document(subject, recipients, {:type => "url", :filename => File.basename(url), :value => url }, options)
207
+ end
208
+
209
+ # Creates a document from a base64 encoded file or publicly available URL
210
+ # * <b>document_data</b>: hash of document source :type ('base64' or 'url'), :filename to be used, :value of source (url or base64 encoded binary)
211
+ # * <b>subject</b>: subject of the document that'll appear in email
212
+ # * <b>recipients</b>: Recipients of the document, should be an array of hashes with :name, :email, and :role ('cc' or 'signer').
213
+ # One of the recipients requires <b>:is_sender</b> (true/false) to reference the API User and won't need to supply :name and :email
214
+ # Ex. CC to support@rightsignature.com, with sender and john@rightsignature.com as a signer
215
+ # [
216
+ # {:name => "RightSignature", :email => "support@rightsignature.com", :role => 'cc'},
217
+ # {:name => "John Bellingham", :email => "john@rightsignature.com", :role => 'signer'},
218
+ # {'is_sender' => true, :role => 'signer'},
219
+ # ]
220
+ # * options: other optional values
221
+ # - <b>description</b>: document description that'll appear in the email
222
+ # - <b>action</b>: 'send' or 'redirect'. Redirect will return a token that will allow another person to send the document under API user's account
223
+ # - <b>expires_in</b>: number of days before expiring the document. API only allows 2,5,15, or 30.
224
+ # - <b>tags</b>: document tags, an array of string or hashes 'single_tag' (for simple tag) or {'tag_name' => 'tag_value'} (for tuples pairs)
225
+ # Ex. ['sent_from_api', {"user_id" => "32"}]
226
+ # - <b>callback_location</b>: A URI encoded URL that specifies the location for API to POST a callback notification to when the document has been created and signed.
227
+ # Ex. "http://yoursite/callback"
228
+ # - <b>use_text_tags</b>: Document has special Text Tags that RightSignature parse. true or false.
229
+ # More info: https://rightsignature.com/apidocs/text_tags
230
+ # Ex.
231
+ # recipients = [
232
+ # {:name => "RightSignature", :email => "support@rightsignature.com", :role => 'cc'},
233
+ # {:name => "John Bellingham", :email => "john@rightsignature.com", :role => 'signer'},
234
+ # {'is_sender' => true, :role => 'signer'},
235
+ # ]
236
+ # document_data = {:type => 'base64', :filename => "originalfile.pdf", :value => Base64.encode64(File.read('myfile.pdf','r'))}
237
+ # options = {
238
+ # :tags => ['sent_from_api', 'user_id' => '12345'],
239
+ # :expires_in => '5 days',
240
+ # :action => "redirect",
241
+ # 'callback_location' => "http://example.com/doc_callback",
242
+ # 'use_text_tags' => false
243
+ # }
244
+ # @rs_connection.send_document( "My Subject", recipients, document_data, options)
245
+ #
246
+ def send_document(subject, recipients, document_data, options={})
247
+ document_hash = {:document => {
248
+ :subject => subject,
249
+ :action => "send",
250
+ :document_data => document_data
251
+ }}
252
+
253
+ document_hash[:document][:recipients] = []
254
+ recipients.each do |recipient_hash|
255
+ document_hash[:document][:recipients] << { :recipient => recipient_hash}
256
+ end
257
+
258
+ document_hash[:document].merge!(options)
259
+ post "/api/documents.xml", document_hash
260
+ end
261
+
262
+ # Prefills a document from a base64 encoded file or publicly available URL and returns a url that allows someone to send as the API User
263
+ # * <b>document_data</b>: hash of document source :type ('base64' or 'url'), :filename to be used, :value of source (url or base64 encoded binary)
264
+ # * <b>subject</b>: subject of the document that'll appear in email
265
+ # * <b>recipients</b>: Recipients of the document, should be an array of hashes with :name, :email, and :role ('cc' or 'signer').
266
+ # One of the recipients requires <b>:is_sender</b> (true/false) to reference the API User and won't need to supply :name and :email
267
+ # Ex. CC to support@rightsignature.com, with sender and john@rightsignature.com as a signer
268
+ # [
269
+ # {:name => "RightSignature", :email => "support@rightsignature.com", :role => 'cc'},
270
+ # {:name => "John Bellingham", :email => "john@rightsignature.com", :role => 'signer'},
271
+ # {'is_sender' => true, :role => 'signer'},
272
+ # ]
273
+ # * <b>options</b>: other optional values
274
+ # - <b>description</b>: document description that'll appear in the email
275
+ # - <b>action</b>: 'send' or 'redirect'. Redirect will return a token that will allow another person to send the document under API user's account
276
+ # - <b>expires_in</b>: number of days before expiring the document. API only allows 2,5,15, or 30.
277
+ # - <b>tags</b>: document tags, an array of string or hashes 'single_tag' (for simple tag) or {'tag_name' => 'tag_value'} (for tuples pairs)
278
+ # Ex. ['sent_from_api', {"user_id" => "32"}]
279
+ # - <b>callback_location</b>: A URI encoded URL that specifies the location for API to POST a callback notification to when the document has been created and signed.
280
+ # Ex. "http://yoursite/callback"
281
+ # - <b>use_text_tags</b>: Document has special Text Tags that RightSignature parse. true or false.
282
+ # More info: https://rightsignature.com/apidocs/text_tags
283
+ # Ex.
284
+ # recipients = [
285
+ # {:name => "RightSignature", :email => "support@rightsignature.com", :role => 'cc'},
286
+ # {:name => "John Bellingham", :email => "john@rightsignature.com", :role => 'signer'},
287
+ # {'is_sender' => true, :role => 'signer'},
288
+ # ]
289
+ # document_data = {:type => 'base64', :filename => "originalfile.pdf", :value => Base64.encode64(File.read('myfile.pdf','r'))}
290
+ # options = {
291
+ # :tags => ['sent_from_api', 'user_id' => '12345'],
292
+ # :expires_in => '5 days',
293
+ # :action => "redirect",
294
+ # 'callback_location' => "http://example.com/doc_callback",
295
+ # 'use_text_tags' => false
296
+ # }
297
+ # @rs_connection.generate_document_redirect_url( "My Subject", recipients, document_data, options)
298
+ #
299
+ def generate_document_redirect_url(subject, recipients, document_data, options={})
300
+ options[:action] = "redirect"
301
+ response = send_document(subject, recipients, document_data, options)
302
+
303
+ "#{site}/builder/new?rt=#{response['document']['redirect_token']}"
304
+ end
305
+
306
+ # Generates signer links for a Document with signers with email of "noemail@rightsignature.com"
307
+ # * <b>guid</b>: Document GUID
308
+ # * <b>redirect_location</b>: (Optional) URL to redirect each signer after it is completed
309
+ #
310
+ # Ex. Generate signer links for document GUID123 that redirects users to http://mysite/done_signing after signing
311
+ # @rs_connection.get_document_signer_links_for("GUID123", "http://mysite/done_signing")
312
+ #
313
+ # Note that ONLY recipients with an email of "noemail@rightsignature.com" will have a signer link
314
+ def get_document_signer_links_for(guid, redirect_location = nil)
315
+ params = {}
316
+ params[:redirect_location] = URI.encode(redirect_location) if redirect_location
317
+ response = get "/api/documents/#{guid}/signer_links.xml", params
318
+
319
+ signer_links = []
320
+
321
+ if response["document"]["signer_links"] && response["document"]["signer_links"]["signer_link"].is_a?(Array)
322
+ response["document"]["signer_links"]["signer_link"].each do |signer_link|
323
+ signer_links << {"name" => signer_link["name"], "url" => "#{site}/signatures/embedded?rt=#{signer_link["signer_token"]}"}
324
+ end
325
+ elsif response["document"]["signer_links"]
326
+ signer_link = response["document"]["signer_links"]["signer_link"]
327
+ signer_links << {"name" => signer_link["name"], "url" => "#{site}/signatures/embedded?rt=#{signer_link["signer_token"]}"}
328
+ end
329
+ signer_links
330
+ end
331
+
332
+ end
333
+ end