printful_api 1.0.1

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.
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: []