printful_api 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/Gemfile +6 -0
  4. data/LICENSE +21 -0
  5. data/README.md +211 -0
  6. data/VERSION +1 -0
  7. data/lib/printful_api.rb +65 -0
  8. data/lib/printful_api/address.rb +9 -0
  9. data/lib/printful_api/api_operations/create.rb +27 -0
  10. data/lib/printful_api/api_operations/delete.rb +29 -0
  11. data/lib/printful_api/api_operations/get.rb +30 -0
  12. data/lib/printful_api/api_operations/list.rb +35 -0
  13. data/lib/printful_api/api_operations/save.rb +25 -0
  14. data/lib/printful_api/api_operations/update.rb +24 -0
  15. data/lib/printful_api/api_resource.rb +104 -0
  16. data/lib/printful_api/card_info.rb +9 -0
  17. data/lib/printful_api/cost.rb +9 -0
  18. data/lib/printful_api/country.rb +34 -0
  19. data/lib/printful_api/file.rb +17 -0
  20. data/lib/printful_api/file_type.rb +9 -0
  21. data/lib/printful_api/gift_data.rb +9 -0
  22. data/lib/printful_api/item.rb +14 -0
  23. data/lib/printful_api/item_option.rb +11 -0
  24. data/lib/printful_api/option_type.rb +9 -0
  25. data/lib/printful_api/order.rb +39 -0
  26. data/lib/printful_api/packing_slip.rb +22 -0
  27. data/lib/printful_api/product.rb +48 -0
  28. data/lib/printful_api/product_variant.rb +14 -0
  29. data/lib/printful_api/shipment.rb +10 -0
  30. data/lib/printful_api/shipping_rate.rb +29 -0
  31. data/lib/printful_api/state.rb +9 -0
  32. data/lib/printful_api/store.rb +29 -0
  33. data/lib/printful_api/tax_rate.rb +21 -0
  34. data/lib/printful_api/variant.rb +16 -0
  35. data/lib/printful_api/version.rb +3 -0
  36. data/lib/printful_api/webhooks.rb +35 -0
  37. data/lib/printful_client.rb +144 -0
  38. data/printful_api.gemspec +18 -0
  39. metadata +81 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ab40c8602c1fed1d573a8fa4d72a4f30142534df
4
+ data.tar.gz: c5f7c5ba10a4096a227fb446dd4977dd1dc2ea08
5
+ SHA512:
6
+ metadata.gz: 255311dbf606b5cf05ddb6b3b5a22dc2fd1854491bc57332952dfa5f78b80d8bb540cd65db6764a06daa72df963ea50bbc21eea5e390758fb6e2fe85d3120375
7
+ data.tar.gz: 294b885561272ac8aa28ea013baef04f7c006aaf2357629a292d6752b7f02495483c1af97eba857a224b022160eec61e0c0f149647b41db3b2d992068bc43371
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2017- Groundswell Enterprises (http://www.groundswellenterprises.com)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,211 @@
1
+ # Printful API Ruby Bindings
2
+
3
+ The Printful API gem provides a ruby bindings SDK for quick and easy access to
4
+ the Printful service. Printful is a online company that will print custom
5
+ designs onto a variety of different apparel/accessories, then ship that item
6
+ with custom packaging directly to your customer. Printful make custom:
7
+
8
+ * T-shirts
9
+ * Sweatshirts
10
+ * Wall art (prints, posters, canvas, ...)
11
+ * Mugs
12
+ * Pillows
13
+ * Totes
14
+ * Hats
15
+ * Leggings
16
+ * Phone Cases
17
+ * Socks
18
+ * Dresses
19
+ * Skirts
20
+ * and more
21
+
22
+ [Sign up here](https://printful.com/a/amrap) to explore the full list of products, start creating,
23
+ previewing, and selling your designs.
24
+
25
+ We provide a comprehensive list of classes which map to the Printful data model,
26
+ allowing developers to pull and manipulate data with ease. This gem wraps
27
+ [the official Printful client library](https://www.printful.com/docs/libraries).
28
+
29
+
30
+ ## Installation
31
+
32
+ You don't need this source code unless you want to modify the gem. If you just
33
+ want to use the Printful API Ruby bindings, you should run:
34
+
35
+ gem install printful_api
36
+
37
+ If you want to build the gem from source:
38
+
39
+ gem build printful_api.gemspec
40
+
41
+ ### Requirements
42
+
43
+ * Ruby 1.9.3 or above.
44
+ * A Printful account, and api key. [Sign up here](https://printful.com/a/amrap)
45
+
46
+ ### Bundler
47
+
48
+ If you are installing via bundler, you should be sure to use the https rubygems
49
+ source in your Gemfile, as any gems fetched over http could potentially be
50
+ compromised in transit and alter the code of gems fetched securely over https:
51
+
52
+ ``` ruby
53
+ source 'https://rubygems.org'
54
+
55
+ gem 'rails'
56
+ gem 'printful_api'
57
+ ```
58
+
59
+ ## Usage
60
+
61
+ In order to access the Printful API you must first have an api key, which get
62
+ after creating [a Printful account](https://printful.com/a/amrap). After signing in, go to your
63
+ [store dashboard](https://www.printful.com/dashboard/store). If you haven't yet
64
+ create a store, otherwise click on the store to get to the "Update Store" screen.
65
+ Click on the "API" tab, to get to the "API Access" view. In a box below, there
66
+ will be a random set of letters and numbers, this is your api key. You will
67
+ need to assign the api to `PrintfulAPI.api_key` so the gem can give you access
68
+ to your store.
69
+
70
+ Or you can set the api key into the `PRINTFUL_API_KEY` environment variable.
71
+
72
+ ``` ruby
73
+ require "printful_api"
74
+ PrintfulAPI.api_key = "g1n1h..."
75
+
76
+ # list all products
77
+ PrintfulAPI::Product.all
78
+
79
+ # get a single order by external ID (your order id)
80
+ PrintfulAPI::Order.get( '@YOUR_ORDER_ID' )
81
+
82
+
83
+ # get a single order by Printful's order ID
84
+ PrintfulAPI::Order.get( 342342 )
85
+ ```
86
+
87
+ Once assigned, the gem will use it as necessary to authenticate requests for your
88
+ store.
89
+
90
+ ## Products / Variations
91
+
92
+ ``` ruby
93
+
94
+ # get a single product, in this case a T-SHIRT
95
+ product = PrintfulAPI::Product.get(5)
96
+
97
+ product.type # "T-SHIRT"
98
+ product.brand # "American Apparel"
99
+ product.model # "2001 Fine Jersey Short Sleeve Men T-Shirt"
100
+ product.image # "https://d1yg28hrivmbqm.cloudfront.net/products/5/product_1483514498.jpg"
101
+ product.variant_count # 270
102
+
103
+ # a list of different file types you can provide for printing, and the cost for using them
104
+ product.files # FileType[]
105
+
106
+ # list the various, some 260+ variations, cut, color, etc
107
+ product.variants # Variant[]
108
+
109
+ # list the different options, options for configuring the process
110
+ product.options # OptionType[]
111
+
112
+ # a list of dimensions for the product
113
+ product.dimensions # Hash
114
+
115
+ ```
116
+
117
+
118
+ ## Orders
119
+
120
+ ``` ruby
121
+
122
+ order = PrintfulAPI::Order.create( {
123
+ "recipient": {
124
+ "name": "John Doe",
125
+ "address1": "19749 Dearborn St",
126
+ "city": "Chatsworth",
127
+ "state_code": "CA",
128
+ "country_code": "US",
129
+ "zip": "91311"
130
+ },
131
+ "external_id": 'order_1112',
132
+ "items": [{
133
+ "variant_id": 1,
134
+ "quantity": 1,
135
+ "files": [{
136
+ "url": "http://example.com/files/posters/poster_1.jpg"
137
+ }]
138
+ }]
139
+ } )
140
+
141
+ order.id # 2071687
142
+ order.external_id # "order_1112"
143
+ order.status # "draft"
144
+ order.shipping # "FEDEX_SMART_POST"
145
+ order.created # 1485550869
146
+ order.updated # 1485550869
147
+ order.recipient # PrintfulAPI::Address
148
+ order.items # PrintfulAPI::Item[]
149
+ order.costs # PrintfulAPI::Cost
150
+ order.retail_costs # PrintfulAPI::Cost
151
+ order.shipments # []
152
+ order.gift # nil
153
+ order.packing_slip # nil
154
+
155
+ # once all order information is confirmed and correct, run the confirm command
156
+ # and the store owner will be charged, and the printing begins.
157
+ order.confirm_for_fulfillment()
158
+
159
+ # didn't mean to process the order? delete it and the order will be canceled,
160
+ # and money returned to the store owner.
161
+ order.delete()
162
+
163
+ ```
164
+
165
+ ## Shipping and Tax Rates
166
+
167
+ ``` ruby
168
+
169
+ # shipping options available for a set of items
170
+ shipping_rates = PrintfulAPI::ShippingRate.list( { address1: '12372 Carmel Country Rd', city: 'San Diego', country_code: 'US', state_code: 'CA', zip: 92130}, [{quantity: 2, variant_id: PrintfulAPI::Product.get(1).variants.first.id}], 'USD' )
171
+
172
+ shipping_rate = shipping_rates.first
173
+
174
+ shipping_rate.id # "USPS_FIRST"
175
+ shipping_rate.name # "USPS First Class Mail (3-5 business days after fulfillment)"
176
+ shipping_rate.rate # "3.05"
177
+ shipping_rate.currency # "USD"
178
+
179
+ ```
180
+
181
+ ``` ruby
182
+
183
+ # tax rates Printful will charge on orders to a specific location
184
+ tax_rate = PrintfulAPI::TaxRate.get( country_code: 'US', state_code: 'CA', city: 'San Diego', zip: 92130 )
185
+ tax_rate.required # true
186
+ tax_rate.rate # 0.775
187
+ tax_rate.shipping_taxable # false
188
+
189
+ ```
190
+
191
+ ## Country/State Lists
192
+
193
+ ``` ruby
194
+
195
+ # list all countries that are valid for Printful shipping. A country and State
196
+ # core a required for orders, when available from this api.
197
+ countries = PrintfulAPI::Country.list()
198
+ country = countries.find{|country| country.code == 'US' }
199
+
200
+ # use the code values when referencing a country or state in an order
201
+
202
+ country.code # "US"
203
+ country.name # "United States"
204
+
205
+ # a list of states/provinces/regions for that country
206
+ country.states # State[]
207
+
208
+ country.states.first.code # "AA"
209
+ country.states.first.name # "Armed Forces Americas (except Canada)"
210
+
211
+ ```
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.1
@@ -0,0 +1,65 @@
1
+ # Printful Ruby bindings
2
+ # API spec at https://www.printful.com/docs
3
+
4
+ require 'printful_api/version'
5
+
6
+ require 'printful_client'
7
+
8
+ require 'printful_api/api_resource'
9
+ require 'printful_api/api_operations/create'
10
+ require 'printful_api/api_operations/delete'
11
+ require 'printful_api/api_operations/get'
12
+ require 'printful_api/api_operations/list'
13
+ require 'printful_api/api_operations/save'
14
+ require 'printful_api/api_operations/update'
15
+ require 'printful_api/address'
16
+ require 'printful_api/card_info'
17
+ require 'printful_api/country'
18
+ require 'printful_api/cost'
19
+ require 'printful_api/file'
20
+ require 'printful_api/file_type'
21
+ require 'printful_api/gift_data'
22
+ require 'printful_api/item'
23
+ require 'printful_api/item_option'
24
+ require 'printful_api/option_type'
25
+ require 'printful_api/order'
26
+ require 'printful_api/packing_slip'
27
+ require 'printful_api/product'
28
+ require 'printful_api/product_variant'
29
+ require 'printful_api/shipping_rate'
30
+ require 'printful_api/state'
31
+ require 'printful_api/store'
32
+ require 'printful_api/tax_rate'
33
+ require 'printful_api/variant'
34
+ require 'printful_api/webhooks'
35
+
36
+
37
+
38
+ module PrintfulAPI
39
+
40
+ @@client = PrintfulClient.new( ENV['PRINTFUL_API_KEY'] )
41
+
42
+ def self.api_key=( api_key )
43
+ @@client = PrintfulClient.new( api_key )
44
+ end
45
+
46
+ def self.request( method, path, opts = {} )
47
+
48
+ # puts "#{method}, #{path}, #{opts}"
49
+
50
+ case method.to_s.upcase
51
+ when "GET"
52
+ @@client.get(path, opts[:params])
53
+ when "DELETE"
54
+ @@client.delete(path, opts[:params])
55
+ when "POST"
56
+ @@client.post(path, opts[:data], opts[:params])
57
+ when "PUT"
58
+ @@client.put(path, opts[:data], opts[:params])
59
+ else
60
+ die()
61
+ end
62
+
63
+ end
64
+
65
+ end
@@ -0,0 +1,9 @@
1
+ module PrintfulAPI
2
+
3
+ class Address < APIResource
4
+
5
+ api_attributes :name, :company, :address1, :address2, :city, :state_code, :country_code, :zip, :phone, :email, :state_name, :country_name
6
+
7
+ end
8
+
9
+ end
@@ -0,0 +1,27 @@
1
+ module PrintfulAPI
2
+
3
+ module APIOperations
4
+
5
+ module Create
6
+
7
+ def self.included(base)
8
+ base.extend(ClassMethods)
9
+ end
10
+
11
+ module ClassMethods
12
+
13
+ def create( data={}, params={} )
14
+
15
+ result = PrintfulAPI.request( :POST, params.delete(:resource_path) || self.resource_path, params: params, data: data )
16
+
17
+ self.new.load_data( result )
18
+
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,29 @@
1
+ module PrintfulAPI
2
+
3
+ module APIOperations
4
+
5
+ module Delete
6
+
7
+ def self.included(base)
8
+ base.extend(ClassMethods)
9
+ end
10
+
11
+ module ClassMethods
12
+
13
+ def delete( id, opts={} )
14
+
15
+ PrintfulAPI.request( :DELETE, "#{opts.delete(:resource_path) || self.resource_path}/#{id}" )
16
+
17
+ end
18
+
19
+ end
20
+
21
+ def delete()
22
+ self.class.delete( self.id )
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,30 @@
1
+ module PrintfulAPI
2
+
3
+ module APIOperations
4
+
5
+ module Get
6
+
7
+ def self.included(base)
8
+ base.extend(ClassMethods)
9
+ end
10
+
11
+ module ClassMethods
12
+
13
+ def get( id, opts={} )
14
+
15
+ data = PrintfulAPI.request( :GET, "#{opts.delete(:resource_path) || self.resource_path}/#{id}" )
16
+
17
+ model = self.new
18
+ model.load_data( data )
19
+
20
+ model
21
+
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,35 @@
1
+ module PrintfulAPI
2
+
3
+ module APIOperations
4
+
5
+ module List
6
+
7
+ def self.included(base)
8
+ base.extend(ClassMethods)
9
+ end
10
+
11
+ module ClassMethods
12
+
13
+ def list( filters={}, opts={} )
14
+
15
+ data_list = PrintfulAPI.request( :GET, opts.delete(:resource_path) || self.resource_path, params: filters )
16
+
17
+ data_list.collect do |data|
18
+
19
+ model = self.new
20
+ model.load_data( data )
21
+
22
+ model
23
+
24
+ end
25
+ end
26
+
27
+ alias :all :list
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,25 @@
1
+ module PrintfulAPI
2
+
3
+ module APIOperations
4
+
5
+ module Save
6
+
7
+ def save( opts = {} )
8
+
9
+ if self.id.present?
10
+
11
+ self.class.update( self.to_h, opts )
12
+
13
+ else
14
+
15
+ self.class.create( self.to_h, opts )
16
+
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,24 @@
1
+ module PrintfulAPI
2
+
3
+ module APIOperations
4
+
5
+ module Update
6
+
7
+ def self.included(base)
8
+ base.extend(ClassMethods)
9
+ end
10
+
11
+ module ClassMethods
12
+
13
+ def update( id, data={}, params={} )
14
+
15
+ PrintfulAPI.request( :PUT, "#{self.resource_path}/#{id}", params: params, data: data )
16
+
17
+ end
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+
24
+ end
@@ -0,0 +1,104 @@
1
+ module PrintfulAPI
2
+ class APIResource
3
+
4
+ attr_accessor :raw_data
5
+
6
+ class << self; attr_accessor :api_attribute_list end
7
+
8
+
9
+ def self.api_attributes( *args )
10
+ self.api_attribute_list = (self.api_attribute_list || []).concat(args)
11
+
12
+ attr_accessor *args
13
+ end
14
+
15
+ def self.has_many( attribute_name, args = {} )
16
+ args[:class] = args[:class] if args[:class].is_a? String
17
+ args[:class] ||= "PrintfulAPI::#{APIResource.singularize( APIResource.camelize(attribute_name.to_s ) )}"
18
+
19
+ self.api_attributes *[attribute_name.to_sym]
20
+
21
+ define_method("#{attribute_name}=") do |array|
22
+ if array.present?
23
+ array = array.collect do |data|
24
+ args[:class].constantize.new.load_data(data)
25
+ end
26
+ end
27
+ self.instance_variable_set("@#{attribute_name}", array)
28
+ end
29
+ end
30
+
31
+ def self.belongs_to( attribute_name, args = {} )
32
+ args[:class] = args[:class] if args[:class].is_a? String
33
+ args[:class] ||= "PrintfulAPI::#{APIResource.camelize( attribute_name.to_s )}"
34
+ args[:foreign_key] ||= "#{attribute_name}_id"
35
+
36
+ self.api_attributes *[attribute_name.to_sym]
37
+
38
+ define_method("#{attribute_name}") do
39
+ attribute_value = self.instance_variable_get( "@#{attribute_name}" )
40
+ attribute_value ||= args[:class].new.get( args[:foreign_key] ) if self.respond_to?( args[:foreign_key] )
41
+ self.instance_variable_set( "@#{attribute_name}", attribute_value )
42
+ end
43
+
44
+ define_method("#{attribute_name}=") do |data|
45
+ if data.is_a?(PrintfulAPI::APIResource)
46
+ self.instance_variable_set("@#{attribute_name}", data)
47
+ else
48
+ model = args[:class].constantize.new.load_data(data) if data.present?
49
+ self.instance_variable_set( "@#{attribute_name}", model )
50
+ end
51
+ end
52
+ end
53
+
54
+ def load_data( data )
55
+ self.raw_data = data
56
+ data.each do |key,value|
57
+
58
+ if self.respond_to? "#{key}="
59
+ self.send("#{key}=", value)
60
+ else
61
+ puts "Accessor doesn't exist #{self.class.name}\##{"#{key}="}"
62
+ end
63
+
64
+ end
65
+
66
+ self
67
+
68
+ end
69
+
70
+ def to_h()
71
+ hash = {}
72
+ self.class.api_attribute_list.each do |attribute_name|
73
+ value = self.send(attribute_name)
74
+ if value.is_a? Array
75
+
76
+ hash[attribute_name] = value.collect do |array_item|
77
+ if array_item.is_a? APIResource
78
+ hash[attribute_name] = array_item.to_h
79
+ else
80
+ hash[attribute_name] = array_item
81
+ end
82
+ end
83
+
84
+ elsif value.is_a? APIResource
85
+ hash[attribute_name] = value.to_h
86
+ else
87
+ hash[attribute_name] = value
88
+ end
89
+ end
90
+
91
+ hash
92
+ end
93
+
94
+ def self.camelize( str )
95
+ str.split('_').map {|w| w.capitalize}.join
96
+ end
97
+
98
+ def self.singularize( str )
99
+ str = str[0..-2] if str[-1] == 's'
100
+ str
101
+ end
102
+
103
+ end
104
+ end
@@ -0,0 +1,9 @@
1
+ module PrintfulAPI
2
+
3
+ class CardInfo < APIResource
4
+
5
+ api_attributes :type, :number_mask, :expires
6
+
7
+ end
8
+
9
+ end
@@ -0,0 +1,9 @@
1
+ module PrintfulAPI
2
+
3
+ class Cost < APIResource
4
+
5
+ api_attributes :discount, :shipping, :tax, :subtotal, :total, :digitization
6
+
7
+ end
8
+
9
+ end
@@ -0,0 +1,34 @@
1
+ module PrintfulAPI
2
+
3
+ class Country < APIResource
4
+ include PrintfulAPI::APIOperations::List
5
+
6
+ api_attributes :code, :name
7
+ has_many :states
8
+
9
+ def self.list( filters={}, opts={} )
10
+ taxable = filters.delete(:taxable)
11
+
12
+ puts "Country.list taxable: #{taxable}, #{filters}, #{opts}"
13
+
14
+ if taxable
15
+ super( filters, opts.merge( resource_path: '/tax/countries' ) )
16
+ else
17
+ super( filters, opts )
18
+ end
19
+ end
20
+
21
+ def states
22
+ @states
23
+ end
24
+
25
+ def self.resource_path
26
+ '/countries'
27
+ end
28
+
29
+
30
+
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,17 @@
1
+ module PrintfulAPI
2
+
3
+ class File < APIResource
4
+ include PrintfulAPI::APIOperations::List
5
+ include PrintfulAPI::APIOperations::Create
6
+ include PrintfulAPI::APIOperations::Get
7
+
8
+ api_attributes :id, :type, :hash, :url, :filename, :mime_type, :size, :width, :height, :dpi, :status, :created, :thumbnail_url, :preview_url, :visible
9
+
10
+
11
+ def self.resource_path
12
+ '/files'
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,9 @@
1
+ module PrintfulAPI
2
+
3
+ class FileType < APIResource
4
+
5
+ api_attributes :id, :title, :additional_price
6
+
7
+ end
8
+
9
+ end
@@ -0,0 +1,9 @@
1
+ module PrintfulAPI
2
+
3
+ class GiftData < APIResource
4
+
5
+ api_attributes :subject, :message
6
+
7
+ end
8
+
9
+ end
@@ -0,0 +1,14 @@
1
+ module PrintfulAPI
2
+
3
+ class Item < APIResource
4
+
5
+
6
+ api_attributes :id, :external_id, :variant_id, :quantity, :price, :retail_price, :name, :sku
7
+ has_many :files
8
+ has_many :options, class: 'PrintfulAPI::ItemOption'
9
+ belongs_to :product, class: 'PrintfulAPI::ProductVariant'
10
+ # belongs_to :variant
11
+
12
+ end
13
+
14
+ end
@@ -0,0 +1,11 @@
1
+ module PrintfulAPI
2
+
3
+ class ItemOption < APIResource
4
+
5
+
6
+ api_attributes :id, :value
7
+
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,9 @@
1
+ module PrintfulAPI
2
+
3
+ class OptionType < APIResource
4
+
5
+ api_attributes :id, :title, :type, :values, :additional_price
6
+
7
+ end
8
+
9
+ end
@@ -0,0 +1,39 @@
1
+ module PrintfulAPI
2
+
3
+ class Order < APIResource
4
+ include PrintfulAPI::APIOperations::Create
5
+ include PrintfulAPI::APIOperations::Delete
6
+ include PrintfulAPI::APIOperations::Get
7
+ include PrintfulAPI::APIOperations::List
8
+ include PrintfulAPI::APIOperations::Update
9
+ include PrintfulAPI::APIOperations::Save
10
+
11
+ api_attributes :id, :external_id, :status, :created, :updated, :costs, :shipping, :currency
12
+ belongs_to :recipient, class: 'PrintfulAPI::Address'
13
+ has_many :items
14
+ belongs_to :costs, class: 'PrintfulAPI::Cost'
15
+ belongs_to :retail_costs, class: 'PrintfulAPI::Cost'
16
+ belongs_to :gift, class: 'PrintfulAPI::GiftData'
17
+ belongs_to :packing_slip
18
+ has_many :shipments
19
+
20
+
21
+ def self.resource_path
22
+ '/orders'
23
+ end
24
+
25
+ # Confirm draft for fulfillment
26
+ # Approves for fulfillment an order that was saved as a draft. Store owner's credit card is charged when the order is submitted for fulfillment.
27
+ def confirm_for_fulfillment
28
+
29
+ result = PrintfulAPI.request( :POST, "/orders/#{self.id}/confirm", {} )
30
+
31
+ self.load_data( result )
32
+
33
+ return true
34
+
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,22 @@
1
+ module PrintfulAPI
2
+
3
+ class PackingSlip < APIResource
4
+ include APIOperations::Create
5
+
6
+ api_attributes :email, :phone, :message
7
+
8
+ def self.get( opts={} )
9
+
10
+ store = Store.get()
11
+
12
+ store.packing_slip
13
+
14
+ end
15
+
16
+ def self.resource_path
17
+ '/store/packing-slip'
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,48 @@
1
+ module PrintfulAPI
2
+
3
+ class Product < APIResource
4
+ include PrintfulAPI::APIOperations::List
5
+ include PrintfulAPI::APIOperations::Get
6
+
7
+ api_attributes :id, :type, :brand, :model, :image, :variant_count, :dimensions
8
+
9
+ # has_many :allowed_files, class: 'PrintfulAPI::FileType'
10
+ has_many :files, class: 'PrintfulAPI::FileType'
11
+ # has_many :allowed_options, class: 'PrintfulAPI::OptionType'
12
+ has_many :options, class: 'PrintfulAPI::OptionType'
13
+
14
+ def variants
15
+ @variants ||= PrintfulAPI::Variant.list( product_id: self.id )
16
+ @variants
17
+ end
18
+
19
+ def self.resource_path
20
+ '/products'
21
+ end
22
+
23
+ def load_data( data )
24
+
25
+ if data['product'].present?
26
+
27
+ super(data['product'])
28
+
29
+ @variants = data['variants'].collect do |variant_data|
30
+ variant = PrintfulAPI::Variant.new.load_data( variant_data )
31
+ variant.product = self
32
+ variant
33
+ end
34
+
35
+ else
36
+
37
+ super( data )
38
+
39
+ end
40
+
41
+ end
42
+
43
+
44
+
45
+
46
+ end
47
+
48
+ end
@@ -0,0 +1,14 @@
1
+ module PrintfulAPI
2
+
3
+ class ProductVariant < APIResource
4
+
5
+
6
+ api_attributes :variant_id, :product_id, :image, :name
7
+
8
+ belongs_to :variant
9
+ belongs_to :product
10
+
11
+
12
+ end
13
+
14
+ end
@@ -0,0 +1,10 @@
1
+ module PrintfulAPI
2
+
3
+ class GiftData < APIResource
4
+
5
+ api_attributes :id, :carrier, :service, :tracking_number, :tracking_url, :created, :ship_date, :reshipment
6
+ has_many :items
7
+
8
+ end
9
+
10
+ end
@@ -0,0 +1,29 @@
1
+ module PrintfulAPI
2
+
3
+ class ShippingRate < APIResource
4
+
5
+ api_attributes :id, :name, :rate, :currency
6
+
7
+ # PrintfulAPI::ShippingRate.list( { address1: '12372 Carmel Country Rd', city: 'San Diego', country_code: 'US', state_code: 'CA', zip: 92130}, [{quantity: 2, variant_id: PrintfulAPI::Product.get(1).variants.first.id}], 'USD' )
8
+ def self.list( recipient = {}, items = [], currency = 'USD', opts = {} )
9
+
10
+ request_data = {
11
+ recipient: recipient,
12
+ items: items,
13
+ currency: currency
14
+ }
15
+
16
+ results = PrintfulAPI.request( :POST, "/shipping/rates", data: request_data, params: opts )
17
+
18
+ results.collect do |data|
19
+ model = self.new
20
+ model.load_data( data )
21
+
22
+ model
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,9 @@
1
+ module PrintfulAPI
2
+
3
+ class State < APIResource
4
+
5
+ api_attributes :code, :name, :shipping_taxable
6
+
7
+ end
8
+
9
+ end
@@ -0,0 +1,29 @@
1
+ module PrintfulAPI
2
+
3
+ class Store < APIResource
4
+
5
+ api_attributes :id, :name, :website, :created
6
+ belongs_to :packing_slip
7
+ belongs_to :return_address, class: 'PrintfulAPI::Address'
8
+ belongs_to :billing_address, class: 'PrintfulAPI::Address'
9
+ belongs_to :payment_card, class: 'PrintfulAPI::CardInfo'
10
+
11
+
12
+ def self.get( opts={} )
13
+
14
+ data = PrintfulAPI.request( :GET, self.resource_path )
15
+
16
+ model = self.new
17
+ model.load_data( data )
18
+
19
+ model
20
+
21
+ end
22
+
23
+ def self.resource_path
24
+ '/store'
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,21 @@
1
+ module PrintfulAPI
2
+
3
+ class TaxRate < APIResource
4
+
5
+ api_attributes :required, :rate, :shipping_taxable
6
+
7
+ # PrintfulAPI::TaxRate.get( country_code: 'US', state_code: 'CA', city: 'San Diego', zip: 92130 )
8
+ def self.get( recipient = {}, opts = {} )
9
+
10
+ data = PrintfulAPI.request( :POST, "/tax/rates", data: { recipient: recipient }, params: opts )
11
+
12
+ model = self.new
13
+ model.load_data( data )
14
+
15
+ model
16
+
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,16 @@
1
+ module PrintfulAPI
2
+
3
+ class Variant < APIResource
4
+ include PrintfulAPI::APIOperations::Get
5
+
6
+ api_attributes :id, :product_id, :name, :size, :color, :color_code, :image, :price, :in_stock
7
+
8
+ belongs_to :product
9
+
10
+ def self.resource_path
11
+ '/products/variant'
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,3 @@
1
+ module PrintfulAPI
2
+ VERSION = '1.0.1'
3
+ end
@@ -0,0 +1,35 @@
1
+ module PrintfulAPI
2
+
3
+ class Webhook < APIResource
4
+ include PrintfulAPI::APIOperations::Create
5
+
6
+ api_attributes :url, :types, :params
7
+
8
+ def self.get( opts={} )
9
+
10
+ data = PrintfulAPI.request( :GET, self.resource_path )
11
+
12
+ model = self.new
13
+ model.load_data( data )
14
+
15
+ model
16
+
17
+ end
18
+
19
+ def self.delete( opts={} )
20
+
21
+ PrintfulAPI.request( :DELETE, self.resource_path )
22
+
23
+ end
24
+
25
+ def delete
26
+ self.class.delete()
27
+ end
28
+
29
+ def self.resource_path
30
+ '/webhooks'
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,144 @@
1
+ ##
2
+ #
3
+ # This class helps to use the Printful API
4
+ #
5
+ # version 1.0
6
+ # copyright 2014 Idea Bits LLC
7
+ #
8
+ ##
9
+
10
+ require 'net/http'
11
+ require 'json'
12
+ require 'uri'
13
+
14
+ module PrintfulClientModule
15
+
16
+ API_URL = 'https://api.theprintful.com/'
17
+ USER_AGENT = 'Printful API Ruby Library 1.0'
18
+
19
+ @api_key
20
+ @last_response_raw
21
+ @last_response
22
+
23
+
24
+ # Initialize API library
25
+ # key - Printful Store API key
26
+ def initialize(key)
27
+ @api_key = key
28
+ end
29
+
30
+
31
+ # Returns total available item count from the last request if it supports paging (e.g order list) or nil otherwise
32
+ def item_count
33
+ return last_response && last_response.key?('paging') ? last_response['paging']['total'] : nil
34
+ end
35
+
36
+ # Perform a GET request to the API
37
+ # path - Request path (e.g. 'orders' or 'orders/123')
38
+ # params - Additional GET parameters as a hash
39
+ def get(path, params=nil)
40
+ request('GET', path, params)
41
+ end
42
+
43
+
44
+ # Perform a DELETE request to the API
45
+ # path - Request path (e.g. 'orders' or 'orders/123')
46
+ # params - Additional GET parameters as a hash
47
+ def delete(path, params=nil)
48
+ request('DELETE', path, params)
49
+ end
50
+
51
+
52
+ # Perform a POST request to the API
53
+ # path - Request path (e.g. 'orders' or 'orders/123')
54
+ # data - Request body data as a hash
55
+ # params - Additional GET parameters as a hash
56
+ def post(path, data=nil, params=nil)
57
+ request('POST', path, params, data)
58
+ end
59
+
60
+
61
+ # Perform a PUT request to the API
62
+ # path - Request path (e.g. 'orders' or 'orders/123')
63
+ # data - Request body data as a hash
64
+ # params - Additional GET parameters as a hash
65
+ def put(path, data=nil, params=nil)
66
+ request('PUT', path, params, data)
67
+ end
68
+
69
+ # Internal generic request wrapper
70
+ def request (method, path, params=nil, data=nil)
71
+
72
+ @last_response_raw = nil
73
+ @last_response = nil
74
+
75
+ uri = URI.join(API_URL, path)
76
+ if params
77
+ query = URI.encode_www_form(params)
78
+ uri.query = query
79
+ end
80
+
81
+ body = data ? JSON.generate(data) : nil
82
+
83
+ headers = {
84
+ 'User-Agent' => USER_AGENT
85
+ }
86
+ begin
87
+ http = Net::HTTP.start(
88
+ uri.host,
89
+ uri.port,
90
+ :use_ssl => uri.scheme=='https',
91
+ :open_timeout => 10,
92
+ :read_timeout => 20
93
+ ) do |http|
94
+
95
+ request = Net::HTTPGenericRequest.new(method,(body ? true : false), true, uri.request_uri ,headers)
96
+ request.basic_auth @api_key, ''
97
+ response = http.request(request, body)
98
+
99
+ @last_response_raw = response.body
100
+
101
+ begin
102
+ result = JSON.parse(response.body)
103
+ @last_response = result
104
+ rescue JSON::ParserError
105
+ raise PrintfulException, "API response was not valid JSON"
106
+ end
107
+
108
+ if !result.key?('code') || !result.key?('result')
109
+ raise PrintfulException, "Invalid API response"
110
+ end
111
+
112
+ status = result['code']
113
+ if status<200 || status >=300
114
+ raise PrintfulApiException.new(status), result['result']
115
+ end
116
+
117
+ result['result']
118
+ end
119
+ rescue PrintfulException
120
+ raise
121
+ rescue Exception => e
122
+ raise PrintfulException, 'API request failed: ' + e.message
123
+ end
124
+ end
125
+
126
+ private :request
127
+ attr_accessor :last_response, :last_response_raw
128
+ end
129
+
130
+ class PrintfulClient
131
+ include PrintfulClientModule
132
+ end
133
+
134
+ # Generic Printful exception
135
+ class PrintfulException < RuntimeError
136
+ end
137
+
138
+ # Printful exception returned from the API
139
+ class PrintfulApiException < PrintfulException
140
+ def initialize(code)
141
+ @code = code
142
+ end
143
+ attr_accessor :code
144
+ end
@@ -0,0 +1,18 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
+
3
+ require 'printful_api/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'printful_api'
7
+ s.version = PrintfulAPI::VERSION
8
+ s.date = '2017-01-25'
9
+ s.summary = "Ruby bindings for the Printful API"
10
+ s.description = "Printful is the easiest way to sell, print and ship custom posters, shirts, mugs, pillows, leggings, totes ..."
11
+ s.authors = ["Michael Ferguson"]
12
+ s.email = 'meister@spacekace.com'
13
+ s.files = `git ls-files`.split("\n")
14
+ s.require_paths = ['lib']
15
+ s.homepage = 'https://github.com/Groundswell/printful-ruby'
16
+ s.license = 'MIT'
17
+ s.required_ruby_version = '>= 1.9.3'
18
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: printful_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Michael Ferguson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-01-25 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Printful is the easiest way to sell, print and ship custom posters, shirts,
14
+ mugs, pillows, leggings, totes ...
15
+ email: meister@spacekace.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - Gemfile
22
+ - LICENSE
23
+ - README.md
24
+ - VERSION
25
+ - lib/printful_api.rb
26
+ - lib/printful_api/address.rb
27
+ - lib/printful_api/api_operations/create.rb
28
+ - lib/printful_api/api_operations/delete.rb
29
+ - lib/printful_api/api_operations/get.rb
30
+ - lib/printful_api/api_operations/list.rb
31
+ - lib/printful_api/api_operations/save.rb
32
+ - lib/printful_api/api_operations/update.rb
33
+ - lib/printful_api/api_resource.rb
34
+ - lib/printful_api/card_info.rb
35
+ - lib/printful_api/cost.rb
36
+ - lib/printful_api/country.rb
37
+ - lib/printful_api/file.rb
38
+ - lib/printful_api/file_type.rb
39
+ - lib/printful_api/gift_data.rb
40
+ - lib/printful_api/item.rb
41
+ - lib/printful_api/item_option.rb
42
+ - lib/printful_api/option_type.rb
43
+ - lib/printful_api/order.rb
44
+ - lib/printful_api/packing_slip.rb
45
+ - lib/printful_api/product.rb
46
+ - lib/printful_api/product_variant.rb
47
+ - lib/printful_api/shipment.rb
48
+ - lib/printful_api/shipping_rate.rb
49
+ - lib/printful_api/state.rb
50
+ - lib/printful_api/store.rb
51
+ - lib/printful_api/tax_rate.rb
52
+ - lib/printful_api/variant.rb
53
+ - lib/printful_api/version.rb
54
+ - lib/printful_api/webhooks.rb
55
+ - lib/printful_client.rb
56
+ - printful_api.gemspec
57
+ homepage: https://github.com/Groundswell/printful-ruby
58
+ licenses:
59
+ - MIT
60
+ metadata: {}
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 1.9.3
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project:
77
+ rubygems_version: 2.5.2
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: Ruby bindings for the Printful API
81
+ test_files: []