anvil-ruby 0.1.0
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.
- checksums.yaml +7 -0
- data/AGENTS.md +123 -0
- data/API_COVERAGE.md +294 -0
- data/CHANGELOG.md +34 -0
- data/CLAUDE_README.md +98 -0
- data/GITHUB_ACTIONS_QUICKREF.md +174 -0
- data/Gemfile.lock +112 -0
- data/Gemfile.minimal +9 -0
- data/LICENSE +21 -0
- data/PROJECT_CONTEXT.md +196 -0
- data/README.md +445 -0
- data/anvil-ruby.gemspec +66 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/create_signature_direct.rb +142 -0
- data/create_signature_packet.rb +232 -0
- data/debug_env.rb +28 -0
- data/examples/create_signature.rb +194 -0
- data/examples/fill_pdf.rb +89 -0
- data/examples/generate_pdf.rb +347 -0
- data/examples/verify_webhook.rb +281 -0
- data/lib/anvil/client.rb +216 -0
- data/lib/anvil/configuration.rb +87 -0
- data/lib/anvil/env_loader.rb +30 -0
- data/lib/anvil/errors.rb +95 -0
- data/lib/anvil/rate_limiter.rb +66 -0
- data/lib/anvil/resources/base.rb +100 -0
- data/lib/anvil/resources/pdf.rb +171 -0
- data/lib/anvil/resources/signature.rb +517 -0
- data/lib/anvil/resources/webform.rb +154 -0
- data/lib/anvil/resources/webhook.rb +201 -0
- data/lib/anvil/resources/workflow.rb +169 -0
- data/lib/anvil/response.rb +98 -0
- data/lib/anvil/version.rb +5 -0
- data/lib/anvil.rb +88 -0
- data/quickstart_signature.rb +220 -0
- data/test_api_connection.rb +143 -0
- data/test_etch_signature.rb +230 -0
- data/test_gem.rb +72 -0
- data/test_signature.rb +281 -0
- data/test_signature_with_template.rb +112 -0
- metadata +247 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Create an Anvil E-Signature Packet
|
|
5
|
+
# Based on the official Anvil API documentation
|
|
6
|
+
|
|
7
|
+
$LOAD_PATH.unshift File.expand_path('lib', __dir__)
|
|
8
|
+
require 'anvil'
|
|
9
|
+
require 'anvil/env_loader'
|
|
10
|
+
require 'net/http'
|
|
11
|
+
require 'uri'
|
|
12
|
+
require 'json'
|
|
13
|
+
require 'base64'
|
|
14
|
+
|
|
15
|
+
# Load .env file
|
|
16
|
+
Anvil::EnvLoader.load(File.expand_path('.env', __dir__))
|
|
17
|
+
|
|
18
|
+
puts '=' * 50
|
|
19
|
+
puts 'Anvil E-Signature Packet Creation'
|
|
20
|
+
puts '=' * 50
|
|
21
|
+
|
|
22
|
+
api_key = ENV.fetch('ANVIL_API_KEY', nil)
|
|
23
|
+
puts "\nUsing API Key: #{api_key[0..10]}..."
|
|
24
|
+
|
|
25
|
+
# Step 1: Create a simple PDF to use for signing
|
|
26
|
+
def create_test_pdf(api_key)
|
|
27
|
+
puts "\nš Creating a test PDF document..."
|
|
28
|
+
|
|
29
|
+
uri = URI('https://app.useanvil.com/api/v1/generate-pdf')
|
|
30
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
31
|
+
http.use_ssl = true
|
|
32
|
+
|
|
33
|
+
request = Net::HTTP::Post.new(uri.path)
|
|
34
|
+
request.basic_auth(api_key, '')
|
|
35
|
+
request['Content-Type'] = 'application/json'
|
|
36
|
+
|
|
37
|
+
html = <<~HTML
|
|
38
|
+
<!DOCTYPE html>
|
|
39
|
+
<html>
|
|
40
|
+
<body style="padding: 40px; font-family: Arial;">
|
|
41
|
+
<h1>Test Agreement</h1>
|
|
42
|
+
<p>This is a test document for e-signature.</p>
|
|
43
|
+
|
|
44
|
+
<p>I, the undersigned, agree to the terms of this test agreement.</p>
|
|
45
|
+
|
|
46
|
+
<div style="margin-top: 100px; border-top: 2px solid black; width: 300px; padding-top: 10px;">
|
|
47
|
+
Signature
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<div style="margin-top: 50px; border-top: 2px solid black; width: 300px; padding-top: 10px;">
|
|
51
|
+
Date
|
|
52
|
+
</div>
|
|
53
|
+
</body>
|
|
54
|
+
</html>
|
|
55
|
+
HTML
|
|
56
|
+
|
|
57
|
+
request.body = {
|
|
58
|
+
type: 'html',
|
|
59
|
+
data: {
|
|
60
|
+
html: html,
|
|
61
|
+
css: 'body { font-size: 14px; }'
|
|
62
|
+
}
|
|
63
|
+
}.to_json
|
|
64
|
+
|
|
65
|
+
response = http.request(request)
|
|
66
|
+
|
|
67
|
+
if response.code == '200'
|
|
68
|
+
puts ' ā
PDF created successfully'
|
|
69
|
+
response.body # Return the PDF binary data
|
|
70
|
+
else
|
|
71
|
+
puts " ā Failed to create PDF: #{response.code}"
|
|
72
|
+
nil
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Step 2: Create an e-signature packet using REST API (simpler than GraphQL)
|
|
77
|
+
def create_etch_packet_rest(api_key, _pdf_data = nil)
|
|
78
|
+
puts "\nš Creating e-signature packet via REST API..."
|
|
79
|
+
|
|
80
|
+
# For now, create a simple packet without a file
|
|
81
|
+
# In production, you'd upload the PDF or use a template
|
|
82
|
+
|
|
83
|
+
uri = URI('https://app.useanvil.com/api/v1/etch-packets')
|
|
84
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
85
|
+
http.use_ssl = true
|
|
86
|
+
|
|
87
|
+
request = Net::HTTP::Post.new(uri.path)
|
|
88
|
+
request.basic_auth(api_key, '')
|
|
89
|
+
request['Content-Type'] = 'application/json'
|
|
90
|
+
|
|
91
|
+
# Basic packet structure
|
|
92
|
+
packet_data = {
|
|
93
|
+
name: "Test Agreement #{Time.now.strftime('%Y-%m-%d %H:%M')}",
|
|
94
|
+
isDraft: false,
|
|
95
|
+
isTest: true, # Test mode - won't send real emails
|
|
96
|
+
signers: [
|
|
97
|
+
{
|
|
98
|
+
id: 'signer1',
|
|
99
|
+
name: 'Test User',
|
|
100
|
+
email: 'test@example.com',
|
|
101
|
+
signerType: 'email'
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
request.body = packet_data.to_json
|
|
107
|
+
|
|
108
|
+
response = http.request(request)
|
|
109
|
+
result = begin
|
|
110
|
+
JSON.parse(response.body)
|
|
111
|
+
rescue StandardError
|
|
112
|
+
response.body
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
if %w[200 201].include?(response.code)
|
|
116
|
+
puts ' ā
Packet created successfully!'
|
|
117
|
+
if result.is_a?(Hash)
|
|
118
|
+
puts " Packet ID: #{result['eid'] || result['id']}"
|
|
119
|
+
puts " Status: #{result['status']}"
|
|
120
|
+
end
|
|
121
|
+
result
|
|
122
|
+
else
|
|
123
|
+
puts " ā Failed to create packet: #{response.code}"
|
|
124
|
+
puts " Response: #{result}"
|
|
125
|
+
nil
|
|
126
|
+
end
|
|
127
|
+
rescue StandardError => e
|
|
128
|
+
puts " ā Error: #{e.message}"
|
|
129
|
+
nil
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Step 3: Try GraphQL mutation with correct structure
|
|
133
|
+
def create_etch_packet_graphql(api_key)
|
|
134
|
+
puts "\nš Creating e-signature packet via GraphQL..."
|
|
135
|
+
|
|
136
|
+
uri = URI('https://app.useanvil.com/graphql')
|
|
137
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
138
|
+
http.use_ssl = true
|
|
139
|
+
|
|
140
|
+
request = Net::HTTP::Post.new(uri.path)
|
|
141
|
+
request.basic_auth(api_key, '')
|
|
142
|
+
request['Content-Type'] = 'application/json'
|
|
143
|
+
|
|
144
|
+
# GraphQL mutation based on docs
|
|
145
|
+
mutation = {
|
|
146
|
+
query: <<~GRAPHQL,
|
|
147
|
+
mutation CreateEtchPacket($variables: JSON) {
|
|
148
|
+
createEtchPacket(variables: $variables) {
|
|
149
|
+
eid
|
|
150
|
+
name
|
|
151
|
+
status
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
GRAPHQL
|
|
155
|
+
variables: {
|
|
156
|
+
variables: {
|
|
157
|
+
name: "Test Agreement via GraphQL #{Time.now.to_i}",
|
|
158
|
+
isDraft: false,
|
|
159
|
+
isTest: true,
|
|
160
|
+
signers: [
|
|
161
|
+
{
|
|
162
|
+
id: 'signer1',
|
|
163
|
+
name: 'Test Signer',
|
|
164
|
+
email: 'test@example.com',
|
|
165
|
+
signerType: 'email'
|
|
166
|
+
}
|
|
167
|
+
]
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
request.body = mutation.to_json
|
|
173
|
+
|
|
174
|
+
response = http.request(request)
|
|
175
|
+
result = begin
|
|
176
|
+
JSON.parse(response.body)
|
|
177
|
+
rescue StandardError
|
|
178
|
+
response.body
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
if response.code == '200'
|
|
182
|
+
if result['data'] && result['data']['createEtchPacket']
|
|
183
|
+
packet = result['data']['createEtchPacket']
|
|
184
|
+
puts ' ā
Packet created via GraphQL!'
|
|
185
|
+
puts " EID: #{packet['eid']}"
|
|
186
|
+
puts " Name: #{packet['name']}"
|
|
187
|
+
puts " Status: #{packet['status']}"
|
|
188
|
+
packet
|
|
189
|
+
else
|
|
190
|
+
puts ' ā ļø GraphQL returned no data'
|
|
191
|
+
puts " Errors: #{result['errors']}" if result['errors']
|
|
192
|
+
nil
|
|
193
|
+
end
|
|
194
|
+
else
|
|
195
|
+
puts " ā GraphQL request failed: #{response.code}"
|
|
196
|
+
puts " Response: #{result}"
|
|
197
|
+
nil
|
|
198
|
+
end
|
|
199
|
+
rescue StandardError => e
|
|
200
|
+
puts " ā Error: #{e.message}"
|
|
201
|
+
nil
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Main execution
|
|
205
|
+
puts "\nAttempting to create an e-signature packet..."
|
|
206
|
+
|
|
207
|
+
# Try REST API first (usually simpler)
|
|
208
|
+
packet = create_etch_packet_rest(api_key)
|
|
209
|
+
|
|
210
|
+
# Also try GraphQL
|
|
211
|
+
graphql_packet = create_etch_packet_graphql(api_key)
|
|
212
|
+
|
|
213
|
+
puts "\n#{'=' * 50}"
|
|
214
|
+
puts 'Summary'
|
|
215
|
+
puts '=' * 50
|
|
216
|
+
|
|
217
|
+
if packet || graphql_packet
|
|
218
|
+
puts 'ā
Successfully created e-signature packet!'
|
|
219
|
+
puts "\nš Next steps:"
|
|
220
|
+
puts '1. Log into Anvil: https://app.useanvil.com'
|
|
221
|
+
puts '2. Navigate to the Etch section'
|
|
222
|
+
puts '3. View your test packets'
|
|
223
|
+
puts '4. Get signing URLs for the signers'
|
|
224
|
+
puts "\nš” Note: Since we used isTest: true, no emails were sent"
|
|
225
|
+
else
|
|
226
|
+
puts "ā ļø Couldn't create a signature packet"
|
|
227
|
+
puts "\nš” Troubleshooting:"
|
|
228
|
+
puts '1. Check if your API key has e-signature permissions'
|
|
229
|
+
puts '2. Try creating a packet manually in the Anvil UI first'
|
|
230
|
+
puts '3. Check the Anvil documentation for required fields'
|
|
231
|
+
puts ' https://www.useanvil.com/docs/api/e-signatures'
|
|
232
|
+
end
|
data/debug_env.rb
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
$LOAD_PATH.unshift File.expand_path('lib', __dir__)
|
|
5
|
+
require 'anvil/env_loader'
|
|
6
|
+
|
|
7
|
+
puts 'Before loading .env:'
|
|
8
|
+
puts "ANVIL_API_KEY = #{ENV['ANVIL_API_KEY'].inspect}"
|
|
9
|
+
|
|
10
|
+
path = File.expand_path('.env', __dir__)
|
|
11
|
+
puts "\nLoading from: #{path}"
|
|
12
|
+
puts "File exists? #{File.exist?(path)}"
|
|
13
|
+
|
|
14
|
+
if File.exist?(path)
|
|
15
|
+
puts "\n.env contents:"
|
|
16
|
+
File.readlines(path).each_with_index do |line, i|
|
|
17
|
+
puts " Line #{i + 1}: #{line.inspect}"
|
|
18
|
+
if line =~ /\A([A-Z_][A-Z0-9_]*)\s*=\s*(.*)\z/
|
|
19
|
+
puts " -> Matched! Key: #{Regexp.last_match(1)}, Value: #{Regexp.last_match(2)[0..20]}..."
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
puts "\nCalling Anvil::EnvLoader.load..."
|
|
25
|
+
Anvil::EnvLoader.load(path)
|
|
26
|
+
|
|
27
|
+
puts "\nAfter loading .env:"
|
|
28
|
+
puts "ANVIL_API_KEY = #{ENV['ANVIL_API_KEY'] ? "#{ENV['ANVIL_API_KEY'][0..15]}..." : 'NOT SET'}"
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'bundler/setup'
|
|
5
|
+
require 'anvil'
|
|
6
|
+
|
|
7
|
+
# Example: Create and manage e-signature packets
|
|
8
|
+
#
|
|
9
|
+
# This example demonstrates how to:
|
|
10
|
+
# 1. Create an e-signature packet
|
|
11
|
+
# 2. Add signers
|
|
12
|
+
# 3. Generate signing URLs
|
|
13
|
+
# 4. Check signature status
|
|
14
|
+
|
|
15
|
+
# Configure Anvil
|
|
16
|
+
Anvil.configure do |config|
|
|
17
|
+
config.api_key = ENV.fetch('ANVIL_API_KEY', nil)
|
|
18
|
+
config.environment = :development
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Example: Create a signature packet for an employment agreement
|
|
22
|
+
def create_employment_agreement
|
|
23
|
+
puts 'š Creating e-signature packet for employment agreement...'
|
|
24
|
+
|
|
25
|
+
# Create the signature packet
|
|
26
|
+
packet = Anvil::Signature.create(
|
|
27
|
+
name: 'Employment Agreement - John Doe',
|
|
28
|
+
|
|
29
|
+
# Define signers
|
|
30
|
+
signers: [
|
|
31
|
+
{
|
|
32
|
+
name: 'John Doe',
|
|
33
|
+
email: 'john.doe@example.com',
|
|
34
|
+
role: 'employee',
|
|
35
|
+
signer_type: 'email' # Email-based signing
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'Jane Smith',
|
|
39
|
+
email: 'jane.smith@company.com',
|
|
40
|
+
role: 'hr_manager',
|
|
41
|
+
signer_type: 'email'
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
|
|
45
|
+
# Specify files to sign (using a PDF template)
|
|
46
|
+
files: [
|
|
47
|
+
{
|
|
48
|
+
type: :pdf,
|
|
49
|
+
id: 'your_template_id_here' # Replace with your PDF template ID
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
|
|
53
|
+
# Optional: Set as draft first (signers won't be notified yet)
|
|
54
|
+
is_draft: true,
|
|
55
|
+
|
|
56
|
+
# Optional: Custom email settings
|
|
57
|
+
email_subject: 'Please sign your employment agreement',
|
|
58
|
+
email_body: 'Dear {{signerName}}, Please review and sign the attached employment agreement. Thank you!',
|
|
59
|
+
|
|
60
|
+
# Optional: Webhook URL for status updates
|
|
61
|
+
webhook_url: 'https://yourapp.com/webhooks/anvil'
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
puts 'ā
Signature packet created!'
|
|
65
|
+
puts "š Packet ID: #{packet.eid}"
|
|
66
|
+
puts "š Status: #{packet.status}"
|
|
67
|
+
puts "š„ Signers: #{packet.signers.count}"
|
|
68
|
+
|
|
69
|
+
packet
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Example: Get signing URLs for signers
|
|
73
|
+
def generate_signing_urls(packet)
|
|
74
|
+
puts "\nš Generating signing URLs..."
|
|
75
|
+
|
|
76
|
+
packet.signers.each do |signer|
|
|
77
|
+
url = signer.signing_url(
|
|
78
|
+
client_user_id: "user_#{signer.email}" # Optional: Your internal user ID
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
puts "\nš¤ Signer: #{signer.name} (#{signer.email})"
|
|
82
|
+
puts "š Status: #{signer.status}"
|
|
83
|
+
puts "š Signing URL: #{url}"
|
|
84
|
+
puts ' Send this URL to the signer to complete their signature'
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Example: Check signature packet status
|
|
89
|
+
def check_packet_status(packet_eid)
|
|
90
|
+
puts "\nš Checking packet status..."
|
|
91
|
+
|
|
92
|
+
# Reload the packet to get latest status
|
|
93
|
+
packet = Anvil::Signature.find(packet_eid)
|
|
94
|
+
|
|
95
|
+
puts "š Packet: #{packet.name}"
|
|
96
|
+
puts "š Overall Status: #{packet.status}"
|
|
97
|
+
|
|
98
|
+
# Check individual signer status
|
|
99
|
+
packet.signers.each do |signer|
|
|
100
|
+
status_emoji = case signer.status
|
|
101
|
+
when 'complete' then 'ā
'
|
|
102
|
+
when 'sent' then 'š§'
|
|
103
|
+
when 'viewed' then 'š'
|
|
104
|
+
else 'ā³'
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
puts "#{status_emoji} #{signer.name}: #{signer.status}"
|
|
108
|
+
|
|
109
|
+
puts " Completed at: #{signer.completed_at}" if signer.complete?
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Check if entire packet is complete
|
|
113
|
+
if packet.complete?
|
|
114
|
+
puts "\nš All signatures collected!"
|
|
115
|
+
# You can now download the signed documents
|
|
116
|
+
elsif packet.partially_complete?
|
|
117
|
+
puts "\nā³ Waiting for remaining signatures..."
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
packet
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Example: List all signature packets
|
|
124
|
+
def list_signature_packets
|
|
125
|
+
puts "\nš Listing signature packets..."
|
|
126
|
+
|
|
127
|
+
packets = Anvil::Signature.list(
|
|
128
|
+
limit: 10,
|
|
129
|
+
status: 'sent' # Filter by status (optional)
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
if packets.empty?
|
|
133
|
+
puts 'No signature packets found'
|
|
134
|
+
else
|
|
135
|
+
packets.each do |packet|
|
|
136
|
+
puts "\nš #{packet.name}"
|
|
137
|
+
puts " ID: #{packet.eid}"
|
|
138
|
+
puts " Status: #{packet.status}"
|
|
139
|
+
puts " Created: #{packet.created_at}"
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Example: Send reminders (by recreating signing URLs)
|
|
145
|
+
def send_reminder(packet)
|
|
146
|
+
puts "\nš§ Sending reminders to incomplete signers..."
|
|
147
|
+
|
|
148
|
+
packet.signers.each do |signer|
|
|
149
|
+
next if signer.complete?
|
|
150
|
+
|
|
151
|
+
url = signer.signing_url
|
|
152
|
+
puts "š Reminder for #{signer.name} (#{signer.email})"
|
|
153
|
+
puts " Signing URL: #{url}"
|
|
154
|
+
|
|
155
|
+
# In a real application, you would send an email here
|
|
156
|
+
# using your email service (ActionMailer, SendGrid, etc.)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Run the example
|
|
161
|
+
begin
|
|
162
|
+
puts '=' * 50
|
|
163
|
+
puts 'Anvil E-Signature Example'
|
|
164
|
+
puts '=' * 50
|
|
165
|
+
|
|
166
|
+
# Create a new signature packet
|
|
167
|
+
packet = create_employment_agreement
|
|
168
|
+
|
|
169
|
+
# Generate signing URLs
|
|
170
|
+
generate_signing_urls(packet)
|
|
171
|
+
|
|
172
|
+
# Simulate checking status after some time
|
|
173
|
+
puts "\nā° (In a real app, you'd check this later...)"
|
|
174
|
+
check_packet_status(packet.eid)
|
|
175
|
+
|
|
176
|
+
# List all packets
|
|
177
|
+
list_signature_packets
|
|
178
|
+
|
|
179
|
+
# Send reminders if needed
|
|
180
|
+
send_reminder(packet) if packet.in_progress?
|
|
181
|
+
|
|
182
|
+
puts "\nā
E-signature example completed!"
|
|
183
|
+
rescue Anvil::ValidationError => e
|
|
184
|
+
puts "ā Validation error: #{e.message}"
|
|
185
|
+
puts "Errors: #{e.errors.inspect}" if e.errors.any?
|
|
186
|
+
rescue Anvil::AuthenticationError => e
|
|
187
|
+
puts "ā Authentication failed: #{e.message}"
|
|
188
|
+
puts 'Please check your API key'
|
|
189
|
+
rescue Anvil::Error => e
|
|
190
|
+
puts "ā Anvil error: #{e.message}"
|
|
191
|
+
rescue StandardError => e
|
|
192
|
+
puts "ā Unexpected error: #{e.message}"
|
|
193
|
+
puts e.backtrace.first(5)
|
|
194
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Add lib to the load path if running directly
|
|
5
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __dir__)
|
|
6
|
+
|
|
7
|
+
require 'anvil'
|
|
8
|
+
|
|
9
|
+
# Example: Fill a PDF template with data
|
|
10
|
+
#
|
|
11
|
+
# This example demonstrates how to fill a PDF template with JSON data.
|
|
12
|
+
# You'll need:
|
|
13
|
+
# 1. An Anvil API key (set as ANVIL_API_KEY environment variable)
|
|
14
|
+
# 2. A PDF template ID from your Anvil account
|
|
15
|
+
|
|
16
|
+
# Configure Anvil (optional if using ENV var)
|
|
17
|
+
Anvil.configure do |config|
|
|
18
|
+
config.api_key = ENV.fetch('ANVIL_API_KEY', nil)
|
|
19
|
+
config.environment = :development # Use development for testing
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Template ID - replace with your actual template ID
|
|
23
|
+
TEMPLATE_ID = 'your_template_id_here'
|
|
24
|
+
|
|
25
|
+
# Sample data to fill the PDF
|
|
26
|
+
# Keys should match the field aliases in your PDF template
|
|
27
|
+
pdf_data = {
|
|
28
|
+
# Basic fields
|
|
29
|
+
name: 'John Doe',
|
|
30
|
+
email: 'john.doe@example.com',
|
|
31
|
+
phone: '(555) 123-4567',
|
|
32
|
+
|
|
33
|
+
# Address
|
|
34
|
+
address: '123 Main Street',
|
|
35
|
+
city: 'San Francisco',
|
|
36
|
+
state: 'CA',
|
|
37
|
+
zip_code: '94102',
|
|
38
|
+
|
|
39
|
+
# Date fields
|
|
40
|
+
date: Date.today.strftime('%B %d, %Y'),
|
|
41
|
+
|
|
42
|
+
# Checkboxes (use true/false)
|
|
43
|
+
agree_to_terms: true,
|
|
44
|
+
subscribe_newsletter: false,
|
|
45
|
+
|
|
46
|
+
# Additional fields (customize based on your template)
|
|
47
|
+
company: 'Acme Corp',
|
|
48
|
+
position: 'Software Engineer',
|
|
49
|
+
salary: '$120,000',
|
|
50
|
+
start_date: '2024-02-01'
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
begin
|
|
54
|
+
puts "Filling PDF template: #{TEMPLATE_ID}"
|
|
55
|
+
puts "With data: #{pdf_data.keys.join(', ')}"
|
|
56
|
+
|
|
57
|
+
# Fill the PDF
|
|
58
|
+
pdf = Anvil::PDF.fill(
|
|
59
|
+
template_id: TEMPLATE_ID,
|
|
60
|
+
data: pdf_data,
|
|
61
|
+
# Optional parameters
|
|
62
|
+
title: 'Employment Agreement',
|
|
63
|
+
font_size: 10,
|
|
64
|
+
text_color: '#333333'
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# Save the filled PDF
|
|
68
|
+
filename = "filled_pdf_#{Time.now.to_i}.pdf"
|
|
69
|
+
pdf.save_as(filename)
|
|
70
|
+
|
|
71
|
+
puts 'ā
PDF filled successfully!'
|
|
72
|
+
puts "š Saved as: #{filename}"
|
|
73
|
+
puts "š Size: #{pdf.size_human}"
|
|
74
|
+
|
|
75
|
+
# You can also get the PDF as base64 for storing in a database
|
|
76
|
+
# base64_pdf = pdf.to_base64
|
|
77
|
+
# puts "Base64 length: #{base64_pdf.length}" if base64_pdf
|
|
78
|
+
rescue Anvil::ValidationError => e
|
|
79
|
+
puts "ā Validation error: #{e.message}"
|
|
80
|
+
puts "Errors: #{e.errors.inspect}" if e.errors.any?
|
|
81
|
+
rescue Anvil::AuthenticationError => e
|
|
82
|
+
puts "ā Authentication failed: #{e.message}"
|
|
83
|
+
puts 'Please check your API key'
|
|
84
|
+
rescue Anvil::Error => e
|
|
85
|
+
puts "ā Anvil error: #{e.message}"
|
|
86
|
+
rescue StandardError => e
|
|
87
|
+
puts "ā Unexpected error: #{e.message}"
|
|
88
|
+
puts e.backtrace.first(5)
|
|
89
|
+
end
|