signatory 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ \.tmtags
2
+ pkg/*
3
+ *.gem
4
+ .bundle
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use --create --install ruby-1.9.2@signatory
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,42 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ signatory (0.0.2)
5
+ activeresource (>= 2.3.9)
6
+ bundler (= 1.0.0)
7
+ oauth (= 0.4.3)
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ activeresource (2.3.9)
13
+ activesupport (= 2.3.9)
14
+ activesupport (2.3.9)
15
+ addressable (2.2.1)
16
+ crack (0.1.8)
17
+ diff-lcs (1.1.2)
18
+ oauth (0.4.3)
19
+ rspec (2.0.0.beta.22)
20
+ rspec-core (= 2.0.0.beta.22)
21
+ rspec-expectations (= 2.0.0.beta.22)
22
+ rspec-mocks (= 2.0.0.beta.22)
23
+ rspec-core (2.0.0.beta.22)
24
+ rspec-expectations (2.0.0.beta.22)
25
+ diff-lcs (>= 1.1.2)
26
+ rspec-mocks (2.0.0.beta.22)
27
+ rspec-core (= 2.0.0.beta.22)
28
+ rspec-expectations (= 2.0.0.beta.22)
29
+ webmock (1.3.5)
30
+ addressable (>= 2.1.1)
31
+ crack (>= 0.1.7)
32
+
33
+ PLATFORMS
34
+ ruby
35
+
36
+ DEPENDENCIES
37
+ activeresource (>= 2.3.9)
38
+ bundler (= 1.0.0)
39
+ oauth (= 0.4.3)
40
+ rspec (= 2.0.0.beta.22)
41
+ signatory!
42
+ webmock (= 1.3.5)
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ === 0.0.1 2010-08-26
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/README.rdoc ADDED
@@ -0,0 +1,96 @@
1
+ = signatory
2
+
3
+ * http://github.com/profounder/signatory
4
+
5
+ == DESCRIPTION:
6
+
7
+ A library to simplify interactions with the RightSignature API. One of the primary goals of this library is to make the workflow clear to developers for using some of the more interesting features of the RightSignature system, eg: templates, document merges, and embedded signature frames.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * FIX (list of features or problems)
12
+
13
+ == SYNOPSIS:
14
+
15
+ cred = Signatory::Credentials.load(File.open('rs.yml'))
16
+ if cred.oauth_ready? # true if access token is provided by the credential file otherwise false
17
+ # if you don't need to handle the credentials separately you can pass
18
+ # something that Signatory:Credentials can load (hash or file) instead
19
+ Signatory.credentials = cred
20
+
21
+ Signatory::Document.all # => List all documents
22
+ doc = Signatory::Document.find('XXXXXXXXXXX') # => Get document by id
23
+
24
+ ...
25
+
26
+ Signatory::Template.all # => List all templates
27
+ template = Signatory::Template.find('XXXXXXXXX') # => Get a template by id
28
+
29
+ merge_fields = [
30
+ Signatory::MergeField.new(:name => "Company Name", :value => "ABC Corp."),
31
+ Signatory::MergeField.new(:name => "Percentage", :value => "5.8%"),
32
+ Signatory::MergeField.new(:name => "Term", :value => "48 months"),
33
+ Signatory::MergeField.new(:name => "Monthly Payback", :value => "$30.00")
34
+ ]
35
+
36
+ # If you aren't embedding then you should include email addresses. You can
37
+ # also use instances of Signatory::Signer
38
+ roles = [
39
+ Signatory::Role.new(:role_name => 'Issuer', :name => 'Ryan Garver'),
40
+ Signatory::Role.new(:role_name => 'Investor', :name => 'Cary Dunn')
41
+ ]
42
+
43
+ doc = template.build_document(merge_fields, roles)
44
+
45
+ signer = doc.recipients.first # Order matters. Returns a Signatory::Recipient
46
+
47
+ # Can be embedded with:
48
+ #
49
+ # <iframe src ="<%= signer.embed_url(redirect_url, :height => 500, :width => 700) %>"
50
+ # width="700px" height="500px" frameborder="0" scrolling="no">
51
+ # <p>Your browser does not support iframes.</p>
52
+ # </iframe>
53
+ #
54
+ # or use signer.embed_code(redirect_url, :height => 500, :width => 700) to generate the
55
+ # above code. This will throw an exception if signer is not associated
56
+ # with a real document yet.
57
+ else
58
+ ... begin oauth workflow ...
59
+ end
60
+
61
+ == REQUIREMENTS:
62
+
63
+ * FIX (list of requirements)
64
+
65
+ == INSTALL:
66
+
67
+ * FIX (sudo gem install, anything else)
68
+
69
+ == THANKS:
70
+
71
+ Special thanks to Cary Dunn at RightSignature for putting together a sample Rails app that formulated how the API should be used and introduced the embedded signing frame.
72
+
73
+ == LICENSE:
74
+
75
+ (The MIT License)
76
+
77
+ Copyright (c) 2010 Ryan Garver
78
+
79
+ Permission is hereby granted, free of charge, to any person obtaining
80
+ a copy of this software and associated documentation files (the
81
+ 'Software'), to deal in the Software without restriction, including
82
+ without limitation the rights to use, copy, modify, merge, publish,
83
+ distribute, sublicense, and/or sell copies of the Software, and to
84
+ permit persons to whom the Software is furnished to do so, subject to
85
+ the following conditions:
86
+
87
+ The above copyright notice and this permission notice shall be
88
+ included in all copies or substantial portions of the Software.
89
+
90
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
91
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
92
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
93
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
94
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
95
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
96
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ $:.unshift File.expand_path("../lib", __FILE__)
2
+
3
+ require 'rubygems'
4
+ require 'rubygems/specification'
5
+ require 'bundler'
6
+
7
+ require 'rspec/core/rake_task'
8
+ RSpec::Core::RakeTask.new do |t|
9
+ t.rspec_opts = ['--colour', '--format', 'progress']
10
+ end
11
+
12
+ task :default => :spec
@@ -0,0 +1,43 @@
1
+ module Signatory
2
+ module API
3
+ class Base < ActiveResource::Base
4
+ self.site = 'https://rightsignature.com/api/'
5
+
6
+ def id
7
+ guid
8
+ end
9
+
10
+ class << self
11
+ def instantiate_collection(collection, opts)
12
+ if collection.has_key?(formatted_collection_name)
13
+ collection = collection[formatted_collection_name]
14
+ end
15
+ super([collection[formatted_name]].flatten, opts)
16
+ end
17
+
18
+ def formatted_name
19
+ self.name.split('::').last.downcase
20
+ end
21
+
22
+ def formatted_collection_name
23
+ self.name.split('::').last.downcase.pluralize
24
+ end
25
+
26
+ def connection(refresh = false)
27
+ if defined?(@connection) || superclass == Object
28
+ @connection = Signatory::API::Connection.new(site, format) if refresh || @connection.nil?
29
+ @connection.proxy = proxy if proxy
30
+ @connection.user = user if user
31
+ @connection.password = password if password
32
+ @connection.auth_type = auth_type if auth_type
33
+ @connection.timeout = timeout if timeout
34
+ @connection.ssl_options = ssl_options if ssl_options
35
+ @connection
36
+ else
37
+ superclass.connection
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,14 @@
1
+ module Signatory
2
+ module API
3
+ class Connection < ActiveResource::Connection
4
+ private
5
+ def new_http
6
+ Signatory.credentials.token
7
+ end
8
+
9
+ def apply_ssl_options(http)
10
+ http #noop
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,35 @@
1
+ module Signatory
2
+ class Credentials
3
+ attr_accessor :key, :secret, :access_token, :access_secret
4
+
5
+ def initialize(key, secret, access_token, access_secret)
6
+ @key, @secret, @access_token, @access_secret = key, secret, access_token, access_secret
7
+ end
8
+
9
+ def self.load(source)
10
+ h = if source.respond_to?(:read)
11
+ YAML.load(source)
12
+ elsif source.is_a?(Hash)
13
+ source.inject({}){ |acc, (k, v)| acc[k.to_s] = v; acc}
14
+ end
15
+
16
+ new(h['key'], h['secret'], h['access_token'], h['access_secret'])
17
+ end
18
+
19
+ def token
20
+ @consumer ||= OAuth::Consumer.new(key, secret, {
21
+ :site => 'https://rightsignature.com',
22
+ :scheme => :header,
23
+ :http_method => :post,
24
+ :request_token_path => "/oauth/request_token",
25
+ :access_token_path => "/oauth/access_token",
26
+ :authorize_path => "/oauth/authorize"
27
+ })
28
+ @token ||= OAuth::AccessToken.new(
29
+ @consumer,
30
+ access_token,
31
+ access_secret
32
+ )
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,12 @@
1
+ module Signatory
2
+ class Document < API::Base
3
+ private
4
+ def self.instantiate_record(record, opts = {})
5
+ record['recipients'] = [record['recipients']['recipient']].flatten unless record['recipients'].nil? || record['recipients'].is_a?(Array)
6
+
7
+ doc = super(record, opts)
8
+ doc.recipients.each {|r| r.document = doc } if doc.respond_to?(:recipients)
9
+ doc
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,37 @@
1
+ module Signatory
2
+ module API
3
+ class Base < ActiveResource::Base
4
+
5
+ class << self
6
+ # This implementation is pulled directly from ActiveResource 3.0.0
7
+ # http://apidock.com/rails/ActiveResource/Base/all/class
8
+ def all(*args)
9
+ find(:all, *args)
10
+ end
11
+
12
+ # ActiveResource < 3.0.0 does not support auth_type
13
+ def connection(refresh = false)
14
+ if defined?(@connection) || superclass == Object
15
+ @connection = Signatory::API::Connection.new(site, format) if refresh || @connection.nil?
16
+ @connection.proxy = proxy if proxy
17
+ @connection.user = user if user
18
+ @connection.password = password if password
19
+ @connection.timeout = timeout if timeout
20
+ @connection.ssl_options = ssl_options if ssl_options
21
+ @connection
22
+ else
23
+ superclass.connection
24
+ end
25
+ end
26
+ end
27
+
28
+ def to_xml(options={})
29
+ fixed_attrs = attributes.clone
30
+ options[:except].each do |k|
31
+ fixed_attrs.delete(k.to_s)
32
+ end
33
+ fixed_attrs.to_xml({:root => self.class.element_name}.merge(options)){|b| yield(b) if block_given?}
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,28 @@
1
+ module Signatory
2
+ class MergeField < API::Base
3
+ def locked
4
+ attributes['locked'] || true
5
+ end
6
+
7
+ def id; attributes['id']; end
8
+
9
+ def to_xml(options = {})
10
+ identifier = {}
11
+ identifier.merge!({:merge_field_id => id}) unless attributes['id'].nil?
12
+ identifier.merge!({:merge_field_name => name}) unless attributes['name'].nil?
13
+ require 'builder' unless defined? ::Builder
14
+ options[:indent] ||= 2
15
+ xml = options[:builder] ||= ::Builder::XmlMarkup.new(:indent => options[:indent])
16
+ xml.tag!('merge_field', identifier) do
17
+ if attributes['value'].nil?
18
+ xml.page page
19
+ xml.name name
20
+ xml.id id
21
+ else
22
+ xml.value value
23
+ xml.locked locked
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ module Signatory
2
+ class Recipient < API::Base
3
+ def document=(doc)
4
+ @document = doc
5
+ end
6
+
7
+ def embed_url(redirect_url, options={})
8
+ signer_links = @document.get(:signer_links, "redirect_location" => redirect_url)
9
+ signer = [signer_links['signer_links']['signer_link']].flatten.select do |s|
10
+ s['role'] == role_id
11
+ end.first
12
+ options.merge!(:rt => signer['signer_token'])
13
+ params = options.sort.map{|k,v| "#{k}=#{v}"}.flatten.join('&')
14
+ "https://rightsignature.com/signatures/embedded?#{params}"
15
+ end
16
+
17
+ def embed_code(redirect_url, options={})
18
+ args = ['frameborder="0"', 'scrolling="no"']
19
+ args << "width=\"#{options[:width]}px\"" if options.has_key?(:width)
20
+ args << "height=\"#{options[:height]}px\"" if options.has_key?(:height)
21
+ "<iframe src =\"#{embed_url(redirect_url, options)}\" #{args.join(' ')}><p>Your browser does not support iframes.</p></iframe>"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,27 @@
1
+ module Signatory
2
+ class Role < API::Base
3
+ def email
4
+ attributes['email'] || 'noemail@rightsignature.com'
5
+ end
6
+
7
+ def to_xml(options = {})
8
+ identifier = {}
9
+ identifier.merge!({:role_id => role_id}) unless attributes['role_id'].nil?
10
+ identifier.merge!({:role_name => role_name}) unless attributes['role_name'].nil?
11
+ require 'builder' unless defined? ::Builder
12
+ options[:indent] ||= 2
13
+ xml = options[:builder] ||= ::Builder::XmlMarkup.new(:indent => options[:indent])
14
+ xml.role(identifier) do
15
+ if attributes['name'].nil?
16
+ xml.tag!('must-sign', must_sign)
17
+ xml.tag!('document-role-id', document_role_id)
18
+ xml.role role
19
+ xml.tag!('is-sender', is_sender)
20
+ else
21
+ xml.name name
22
+ xml.email email
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,7 @@
1
+ unless Symbol.public_instance_methods.include?(:<=>)
2
+ class Symbol
3
+ def <=>(rhs)
4
+ to_s <=> rhs.to_s
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,43 @@
1
+ module Signatory
2
+ class Template < API::Base
3
+ def prepackage
4
+ record = connection.format.decode(post(:prepackage).body)
5
+ Template.instantiate_record(record)
6
+ end
7
+
8
+ def build_document(merge_fields, roles)
9
+ doc_pkg = prepackage
10
+ doc_pkg.prefill_and_send(merge_fields, roles)
11
+ end
12
+
13
+ def prefill_and_send(merge_fields, roles)
14
+ attributes.merge!({
15
+ 'merge_fields' => merge_fields,
16
+ 'roles' => roles,
17
+ 'action' => 'send'
18
+ })
19
+
20
+ doc = connection.format.decode(connection.post("/api/templates.xml", self.to_xml).body)
21
+ Document.find(doc['guid'])
22
+ end
23
+
24
+ def to_xml(opts = {})
25
+ super(opts.merge(:dasherize => false, :skip_types => true, :except => [:pages, :_type, :redirect_token, :content_type, :size, :tags])) do |b|
26
+ b.tag!(:tags) do
27
+ tags.split(" ").each do |tag|
28
+ b.tag!(:tag) { b.value tag}
29
+ end
30
+ end unless attributes['tags'].blank?
31
+ end
32
+ end
33
+
34
+ private
35
+ def self.instantiate_record(record, opts = {})
36
+ record['_type'] = record.delete('type') if record.has_key?('type')
37
+ record['roles'] = [record['roles']['role']].flatten unless record['roles'].nil? || record['roles'].is_a?(Array)
38
+ record['merge_fields'] = [record['merge_fields']['merge_field']].flatten unless record['merge_fields'].nil? || record['merge_fields'].is_a?(Array)
39
+
40
+ super(record, opts)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,3 @@
1
+ module Signatory
2
+ VERSION = '0.0.3'
3
+ end
data/lib/signatory.rb ADDED
@@ -0,0 +1,36 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'signatory/ruby_hacks'
5
+ require 'rubygems'
6
+ require 'bundler/setup'
7
+ require 'yaml' unless defined?(YAML)
8
+ require 'oauth' unless defined?(OAuth)
9
+ require 'active_resource' unless defined?(ActiveResource)
10
+
11
+ module Signatory
12
+ class << self
13
+ def credentials=(creds)
14
+ if !creds.is_a?(Credentials)
15
+ creds = Credentials.load(creds)
16
+ end
17
+ @credentials = creds
18
+ end
19
+ def credentials; @credentials; end
20
+ end
21
+ end
22
+
23
+ require 'signatory/version'
24
+ require 'signatory/api/connection'
25
+ require 'signatory/api/base'
26
+ require 'signatory/credentials'
27
+ require 'signatory/document'
28
+ require 'signatory/template'
29
+ require 'signatory/role'
30
+ require 'signatory/merge_field'
31
+ require 'signatory/recipient'
32
+
33
+ require 'active_resource/version'
34
+ if ActiveResource::VERSION::STRING < '3.0.0'
35
+ require 'signatory/legacy_active_resource_hacks'
36
+ end
data/signatory.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/signatory/version", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "signatory"
6
+ s.version = Signatory::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["Ryan Garver"]
9
+ s.email = ["ryan@profounder.com"]
10
+ s.homepage = "http://rubygems.org/gems/signatory"
11
+ s.summary = "API wrapper for RightSignature"
12
+ s.description = "Signatory provides a simple wrapper around the RightSignature API."
13
+
14
+ s.required_rubygems_version = ">= 1.3.6"
15
+ s.rubyforge_project = "signatory"
16
+
17
+ s.add_development_dependency "bundler", "= 1.0.0"
18
+ s.add_development_dependency "rspec", "= 2.0.0.beta.22"
19
+ s.add_development_dependency "webmock", "= 1.3.5"
20
+
21
+ s.add_dependency "bundler", "= 1.0.0"
22
+ s.add_dependency "oauth", "= 0.4.3"
23
+ s.add_dependency "activeresource", ">= 2.3.9"
24
+
25
+ s.files = `git ls-files`.split("\n")
26
+ s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
27
+ s.require_path = 'lib'
28
+ end
@@ -0,0 +1,39 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe Signatory::Credentials do
4
+ it "loads credentials from yaml" do
5
+ file = StringIO.new("---\nkey: thekey\nsecret: thesecret\naccess_token: accesstoken\naccess_secret: accesssecret")
6
+ creds = Signatory::Credentials.load(file)
7
+ creds.key.should == 'thekey'
8
+ creds.secret.should == 'thesecret'
9
+ creds.access_token.should == 'accesstoken'
10
+ creds.access_secret.should == 'accesssecret'
11
+ end
12
+
13
+ it "loads credentials from hash" do
14
+ hash = {:key => 'thekey', :secret => 'thesecret', :access_token => 'accesstoken', :access_secret => 'accesssecret'}
15
+ creds = Signatory::Credentials.load(hash)
16
+ creds.key.should == 'thekey'
17
+ creds.secret.should == 'thesecret'
18
+ creds.access_token.should == 'accesstoken'
19
+ creds.access_secret.should == 'accesssecret'
20
+ end
21
+
22
+ it "generates an access token from the credentials" do
23
+ consumer = stub!(:consumer)
24
+ OAuth::Consumer.should_receive(:new).with('thekey', 'thesecret', {
25
+ :site => 'https://rightsignature.com',
26
+ :scheme => :header,
27
+ :http_method => :post,
28
+ :request_token_path => "/oauth/request_token",
29
+ :access_token_path => "/oauth/access_token",
30
+ :authorize_path => "/oauth/authorize"
31
+ }).and_return(consumer)
32
+ access_token = stub!('access_token')
33
+ OAuth::AccessToken.should_receive(:new).with(consumer, 'accesstoken', 'accesssecret').and_return(access_token)
34
+
35
+ hash = {:key => 'thekey', :secret => 'thesecret', :access_token => 'accesstoken', :access_secret => 'accesssecret'}
36
+ creds = Signatory::Credentials.load(hash)
37
+ creds.token.should be(access_token)
38
+ end
39
+ end
@@ -0,0 +1,35 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe Signatory::Document do
4
+ before(:each) do
5
+ Signatory.credentials = {:key => '123', :secret => '321'}
6
+ end
7
+
8
+ describe ".all" do
9
+ it "returns a list of documents" do
10
+ stub_documents(:total_documents => 2)
11
+ documents = Signatory::Document.all
12
+ documents.count.should == 2
13
+ documents.each do |doc|
14
+ doc.should be_a(Signatory::Document)
15
+ end
16
+ end
17
+
18
+ it "returns the right document" do
19
+ stub_documents(:total_documents => 1, :documents => [{:subject => 'This is a test', :guid => 'xxxyyy'}])
20
+ documents = Signatory::Document.all
21
+ documents.count.should == 1
22
+ document = documents.first
23
+ document.subject.should == 'This is a test'
24
+ document.id.should == 'xxxyyy'
25
+ end
26
+ end
27
+
28
+ describe ".find by id" do
29
+ it "returns the document with the specified id" do
30
+ stub_document('xxxyyy', :subject => 'Test number 2')
31
+ doc = Signatory::Document.find('xxxyyy')
32
+ doc.subject.should == 'Test number 2'
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,51 @@
1
+ <document>
2
+ <completed-at>2009-11-01T13:14:28-08:00</completed-at>
3
+ <thumbnail-url>https://thumbnail.png</thumbnail-url>
4
+ <message>Please sign the document.</message>
5
+ <form-fields>
6
+ <form-field>
7
+ <value>asdf</value>
8
+ <page>2</page>
9
+ <role-id>signer_B</role-id>
10
+ <name>Component 1</name>
11
+ <id>a_92208_asdf1234asdf_4709</id>
12
+ </form-field>
13
+ </form-fields>
14
+ <state>signed</state>
15
+ <pdf-url>https://pdfurl.pdf</pdf-url>
16
+ <deleted-at nil="true"></deleted-at>
17
+ <created-at>2009-11-01T12:29:36-08:00</created-at>
18
+ <is-public>false</is-public>
19
+ <signed-pdf-url>https://signedpdf.pdf</signed-pdf-url>
20
+ <original-filename>Application.pdf</original-filename>
21
+ <size>231740</size>
22
+ <recipients>
23
+ <recipient>
24
+ <state>signed</state>
25
+ <role-id>signer_B</role-id>
26
+ <must-sign>true</must-sign>
27
+ <is-sender>false</is-sender>
28
+ <email>support@rightsignature.com</email>
29
+ <name>John Bellingham</name>
30
+ </recipient>
31
+ </recipients>
32
+ <pages>
33
+ <page>
34
+ <original-template-filename>disclosure.pdf</original-template-filename>
35
+ <page-number>1</page-number>
36
+ <original-template-guid>a_154_fqLTIcNgcuIejFdhkVra</original-template-guid>
37
+ </page>
38
+ <page>
39
+ <original-template-filename>Application.pdf</original-template-filename>
40
+ <page-number>2</page-number>
41
+ <original-template-guid>a_311_yDhSZmJDtNEdPoZjfeF</original-template-guid>
42
+ </page>
43
+ </pages>
44
+ <subject><%= options[:subject] || "Employment Application" %></subject>
45
+ <guid><%= options[:guid] || 'ABCXYZ' %></guid>
46
+ <callback-location nil="true"></callback-location>
47
+ <processing-state>done-processing</processing-state>
48
+ <original-url>https://originaldoc.doc</original-url>
49
+ <content-type>package</content-type>
50
+ <expires-on>2009-11-06T16:00:00-08:00</expires-on>
51
+ </document>