ecwid_api 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +8 -0
- data/Gemfile +2 -0
- data/README.md +228 -144
- data/ecwid_api.gemspec +1 -0
- data/lib/ecwid_api/api/base.rb +17 -0
- data/lib/ecwid_api/api/categories.rb +57 -0
- data/lib/ecwid_api/api/orders.rb +36 -0
- data/lib/ecwid_api/api/product_combinations.rb +51 -0
- data/lib/ecwid_api/api/products.rb +64 -0
- data/lib/ecwid_api/api.rb +31 -0
- data/lib/ecwid_api/category.rb +59 -4
- data/lib/ecwid_api/client.rb +65 -94
- data/lib/ecwid_api/entity.rb +138 -26
- data/lib/ecwid_api/error.rb +12 -2
- data/lib/ecwid_api/o_auth.rb +106 -0
- data/lib/ecwid_api/order.rb +82 -0
- data/lib/ecwid_api/order_item.rb +17 -0
- data/lib/ecwid_api/paged_ecwid_response.rb +55 -0
- data/lib/ecwid_api/paged_enumerator.rb +66 -0
- data/lib/ecwid_api/person.rb +7 -0
- data/lib/ecwid_api/product.rb +77 -0
- data/lib/ecwid_api/product_combination.rb +34 -0
- data/lib/ecwid_api/version.rb +1 -1
- data/lib/ecwid_api.rb +25 -39
- data/lib/ext/string.rb +12 -4
- data/spec/api/categories_spec.rb +31 -0
- data/spec/api/orders_spec.rb +30 -0
- data/spec/api/products_spec.rb +20 -0
- data/spec/category_spec.rb +33 -38
- data/spec/client_spec.rb +20 -48
- data/spec/entity_spec.rb +90 -5
- data/spec/fixtures/categories.json +28 -22
- data/spec/fixtures/order.json +162 -0
- data/spec/fixtures/orders.json +302 -0
- data/spec/fixtures/products.json +141 -0
- data/spec/helpers/client.rb +32 -0
- data/spec/oauth_spec.rb +40 -0
- data/spec/order_item_spec.rb +12 -0
- data/spec/order_spec.rb +71 -0
- data/spec/paged_enumerator_spec.rb +38 -0
- data/spec/spec_helper.rb +24 -23
- metadata +53 -9
- data/lib/ecwid_api/category_api.rb +0 -62
- data/spec/category_api_spec.rb +0 -36
- data/spec/ecwid_api_spec.rb +0 -15
- data/spec/helpers/faraday.rb +0 -30
@@ -0,0 +1,31 @@
|
|
1
|
+
module EcwidApi
|
2
|
+
# Internal: A base class for common API functionality
|
3
|
+
module Api
|
4
|
+
autoload :Base, "ecwid_api/api/base"
|
5
|
+
autoload :Orders, "ecwid_api/api/orders"
|
6
|
+
autoload :Products, "ecwid_api/api/products"
|
7
|
+
autoload :Categories, "ecwid_api/api/categories"
|
8
|
+
autoload :ProductCombinations, "ecwid_api/api/product_combinations"
|
9
|
+
|
10
|
+
# Private: Gets the Client
|
11
|
+
attr_reader :client
|
12
|
+
private :client
|
13
|
+
|
14
|
+
# Private: Raises an Error if a request failed, otherwise it will
|
15
|
+
# yield the block
|
16
|
+
#
|
17
|
+
# response - a Faraday::Response object
|
18
|
+
#
|
19
|
+
# Yield if the response was successful
|
20
|
+
#
|
21
|
+
# Raises an error with the status code and reason if the response failed
|
22
|
+
#
|
23
|
+
def raise_on_failure(response)
|
24
|
+
if response.success?
|
25
|
+
yield(response) if block_given?
|
26
|
+
else
|
27
|
+
raise ResponseError.new(response)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/ecwid_api/category.rb
CHANGED
@@ -1,14 +1,69 @@
|
|
1
|
+
require "open-uri"
|
2
|
+
|
1
3
|
module EcwidApi
|
2
4
|
class Category < Entity
|
5
|
+
self.url_root = "categories"
|
6
|
+
|
7
|
+
ecwid_reader :id, :parentId, :orderBy, :thumbnailUrl, :originalImageUrl,
|
8
|
+
:name, :url, :productCount, :description, :enabled, :productIds
|
9
|
+
|
10
|
+
ecwid_writer :name, :parentId, :orderBy, :description, :enabled, :productIds
|
11
|
+
|
3
12
|
# Public: Returns an Array of sub categories for the Category
|
4
|
-
def sub_categories
|
5
|
-
@sub_categories ||= client.categories.all(id)
|
13
|
+
def sub_categories(params = {})
|
14
|
+
@sub_categories ||= client.categories.all(params.merge(parent: id))
|
15
|
+
end
|
16
|
+
|
17
|
+
# Public: Returns an Array of all of the sub categories (deep) for the
|
18
|
+
# Category
|
19
|
+
def all_sub_categories(params = {})
|
20
|
+
@all_sub_categories ||= sub_categories(params) + sub_categories.flat_map do |sub|
|
21
|
+
sub.all_sub_categories(params)
|
22
|
+
end
|
6
23
|
end
|
7
24
|
|
8
25
|
# Public: Returns the parent EcwidApi::Category, or nil if there isn't one
|
9
26
|
def parent
|
10
|
-
|
11
|
-
|
27
|
+
@parent ||= begin
|
28
|
+
parent_id = data["parentId"]
|
29
|
+
client.categories.find(parent_id) if parent_id
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def parents
|
34
|
+
if parent
|
35
|
+
parent.parents + [parent]
|
36
|
+
else
|
37
|
+
[]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Public: Returns the Products that belong to the Category
|
42
|
+
#
|
43
|
+
# params - a Hash of values that can be used for a Prdocut search
|
44
|
+
#
|
45
|
+
# Returns an Enumeration of Products
|
46
|
+
def products(params = {})
|
47
|
+
@products ||= product_ids.map do |product_id|
|
48
|
+
client.products.find(product_id)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def product_ids
|
53
|
+
super || []
|
54
|
+
end
|
55
|
+
|
56
|
+
# Public: Uploads an image for the Category
|
57
|
+
#
|
58
|
+
# filename - a String that is the path to a local file or a URL
|
59
|
+
#
|
60
|
+
# Returns a Faraday::Response object
|
61
|
+
def upload_image!(filename)
|
62
|
+
client.post("categories/#{id}/image") do |req|
|
63
|
+
req.body = open(filename).read
|
64
|
+
end.tap do |response|
|
65
|
+
raise_on_failure(response)
|
66
|
+
end
|
12
67
|
end
|
13
68
|
end
|
14
69
|
end
|
data/lib/ecwid_api/client.rb
CHANGED
@@ -1,95 +1,66 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
# Public:
|
22
|
-
|
23
|
-
|
24
|
-
#
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
# # => #<Faraday::Response>
|
67
|
-
#
|
68
|
-
# Returns a Faraday::Response
|
69
|
-
def get(path, params={})
|
70
|
-
connection.get(path, params)
|
71
|
-
end
|
72
|
-
|
73
|
-
# Public: Returns the Category API
|
74
|
-
def categories
|
75
|
-
@categories ||= CategoryApi.new(self)
|
76
|
-
end
|
77
|
-
|
78
|
-
private
|
79
|
-
|
80
|
-
# Private: Resets the connection.
|
81
|
-
#
|
82
|
-
# Should be used if the base URL to the Ecwid API changes
|
83
|
-
def reset_connection
|
84
|
-
@connection = nil
|
85
|
-
end
|
86
|
-
|
87
|
-
# Private: Returns a Faraday connection to interface with the Ecwid API
|
88
|
-
def connection
|
89
|
-
@connection ||= Faraday.new store_url do |conn|
|
90
|
-
conn.response :json, content_type: /\bjson$/
|
91
|
-
conn.adapter Faraday.default_adapter
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
1
|
+
module EcwidApi
|
2
|
+
# Public: Client objects manage the connection and interface to a single Ecwid
|
3
|
+
# store.
|
4
|
+
#
|
5
|
+
# Examples
|
6
|
+
#
|
7
|
+
# client = EcwidApi::Client.new(store_id: '12345', token: 'the access_token')
|
8
|
+
# client.get "/products"
|
9
|
+
#
|
10
|
+
class Client
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
# The default base URL for the Ecwid API
|
14
|
+
DEFAULT_URL = "https://app.ecwid.com/api/v3"
|
15
|
+
|
16
|
+
# Public: Returns the Ecwid Store ID
|
17
|
+
attr_reader :store_id
|
18
|
+
attr_reader :token
|
19
|
+
attr_reader :adapter
|
20
|
+
|
21
|
+
# Public: Initializes a new Client to interact with the API
|
22
|
+
#
|
23
|
+
# store_id - the Ecwid store_id to interact with
|
24
|
+
# token - the authorization token provided by oAuth. See the
|
25
|
+
# Authentication class
|
26
|
+
#
|
27
|
+
def initialize(store_id, token, adapter = Faraday.default_adapter)
|
28
|
+
@store_id, @token, @adapter = store_id, token, adapter
|
29
|
+
end
|
30
|
+
|
31
|
+
# Public: The URL of the API for the Ecwid Store
|
32
|
+
def store_url
|
33
|
+
"#{DEFAULT_URL}/#{store_id}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def_delegators :connection, :get, :post, :put, :delete
|
37
|
+
|
38
|
+
# Public: Returns the Category API
|
39
|
+
def categories
|
40
|
+
@categories ||= Api::Categories.new(self)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Public: Returns the Order API
|
44
|
+
def orders
|
45
|
+
@orders ||= Api::Orders.new(self)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Public: Returns the Products API
|
49
|
+
def products
|
50
|
+
@products ||= Api::Products.new(self)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Private: Returns a Faraday connection to interface with the Ecwid API
|
54
|
+
def connection
|
55
|
+
@connection ||= Faraday.new store_url do |conn|
|
56
|
+
conn.request :oauth2, token, param_name: :token
|
57
|
+
conn.request :json
|
58
|
+
|
59
|
+
conn.response :json, content_type: /\bjson$/
|
60
|
+
conn.response :logger
|
61
|
+
|
62
|
+
conn.adapter adapter
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
95
66
|
end
|
data/lib/ecwid_api/entity.rb
CHANGED
@@ -1,12 +1,86 @@
|
|
1
1
|
module EcwidApi
|
2
2
|
class Entity
|
3
|
-
|
4
|
-
attr_reader :client
|
5
|
-
private :client
|
3
|
+
include Api
|
6
4
|
|
7
5
|
# Private: Gets the Hash of data
|
8
6
|
attr_reader :data
|
9
|
-
|
7
|
+
protected :data
|
8
|
+
|
9
|
+
class << self
|
10
|
+
attr_accessor :url_root
|
11
|
+
|
12
|
+
def define_accessor(attribute, &block)
|
13
|
+
if const_defined?(:Accessors, false)
|
14
|
+
mod = const_get(:Accessors)
|
15
|
+
else
|
16
|
+
mod = const_set(:Accessors, Module.new)
|
17
|
+
include mod
|
18
|
+
end
|
19
|
+
|
20
|
+
mod.module_eval do
|
21
|
+
define_method(attribute, &block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private :define_accessor
|
26
|
+
|
27
|
+
# Public: Creates a snake_case access method from an Ecwid property name
|
28
|
+
#
|
29
|
+
# Example
|
30
|
+
#
|
31
|
+
# class Product < Entity
|
32
|
+
# ecwid_reader :id, :inStock
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# product = client.products.find(12)
|
36
|
+
# product.in_stock
|
37
|
+
#
|
38
|
+
def ecwid_reader(*attrs)
|
39
|
+
attrs.map(&:to_s).each do |attribute|
|
40
|
+
method = attribute.underscore
|
41
|
+
define_accessor(method) do
|
42
|
+
self[attribute]
|
43
|
+
end unless method_defined?(attribute.underscore)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Public: Creates a snake_case writer method from an Ecwid property name
|
48
|
+
#
|
49
|
+
# Example
|
50
|
+
#
|
51
|
+
# class Product < Entity
|
52
|
+
# ecwid_writer :inStock
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# product = client.products.find(12)
|
56
|
+
# product.in_stock = true
|
57
|
+
#
|
58
|
+
def ecwid_writer(*attrs)
|
59
|
+
attrs.map(&:to_s).each do |attribute|
|
60
|
+
method = "#{attribute.underscore}="
|
61
|
+
define_accessor(method) do |value|
|
62
|
+
@new_data[attribute] = value
|
63
|
+
end unless method_defined?(method)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Public: Creates a snake_case accessor method from an Ecwid property name
|
68
|
+
#
|
69
|
+
# Example
|
70
|
+
#
|
71
|
+
# class Product < Entity
|
72
|
+
# ecwid_accessor :inStock
|
73
|
+
# end
|
74
|
+
#
|
75
|
+
# product = client.products.find(12)
|
76
|
+
# product.in_stock
|
77
|
+
# product.in_stock = true
|
78
|
+
#
|
79
|
+
def ecwid_accessor(*attrs)
|
80
|
+
ecwid_reader(*attrs)
|
81
|
+
ecwid_writer(*attrs)
|
82
|
+
end
|
83
|
+
end
|
10
84
|
|
11
85
|
# Public: Initialize a new entity with a reference to the client and data
|
12
86
|
#
|
@@ -16,6 +90,7 @@ module EcwidApi
|
|
16
90
|
#
|
17
91
|
def initialize(data, opts={})
|
18
92
|
@client, @data = opts[:client], data
|
93
|
+
@new_data = {}
|
19
94
|
end
|
20
95
|
|
21
96
|
# Public: Returns a property of the data (actual property name)
|
@@ -31,37 +106,74 @@ module EcwidApi
|
|
31
106
|
#
|
32
107
|
# Returns the value of the property, or nil if it doesn't exist
|
33
108
|
def [](key)
|
34
|
-
data[key.to_s]
|
109
|
+
@new_data[key.to_s] || data[key.to_s]
|
35
110
|
end
|
36
111
|
|
37
|
-
# Public:
|
38
|
-
#
|
39
|
-
# This is used as a helper to allow easy access to the data. It will work
|
40
|
-
# with both CamelCased and snake_case keys. For example, if the data
|
41
|
-
# contains a "parentId" key, then calling `entity.parent_id` should work.
|
42
|
-
#
|
43
|
-
# This will NOT return null of the property doesn't exist on the data!
|
112
|
+
# Public: The URL of the entity
|
44
113
|
#
|
45
|
-
#
|
114
|
+
# Returns a String that is the URL of the entity
|
115
|
+
def url
|
116
|
+
url_root = self.class.url_root
|
117
|
+
raise Error.new("Please specify a url_root for the #{self.class.to_s}") unless url_root
|
118
|
+
|
119
|
+
if url_root.respond_to?(:call)
|
120
|
+
url_root = instance_exec(&url_root)
|
121
|
+
end
|
122
|
+
|
123
|
+
url_root + "/#{id}"
|
124
|
+
end
|
125
|
+
|
126
|
+
def assign_attributes(attributes)
|
127
|
+
attributes.each do |key, val|
|
128
|
+
send("#{key}=", val)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def assign_raw_attributes(attributes)
|
133
|
+
attributes.each do |key, val|
|
134
|
+
@new_data[key.to_s] = val
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def update_attributes(attributes)
|
139
|
+
assign_attributes(attributes)
|
140
|
+
save
|
141
|
+
end
|
142
|
+
|
143
|
+
def update_raw_attributes(attributes)
|
144
|
+
assign_raw_attributes(attributes)
|
145
|
+
save
|
146
|
+
end
|
147
|
+
|
148
|
+
# Public: Saves the Entity
|
46
149
|
#
|
47
|
-
#
|
150
|
+
# Saves anything stored in the @new_data hash
|
48
151
|
#
|
49
|
-
#
|
50
|
-
# return a property if it doesn't have a null value. An example of this are
|
51
|
-
# the top level categories. They don't have a parentId, so that property
|
52
|
-
# is ommitted from the API response. Calling `category.parent_id` will
|
53
|
-
# result in an "undefined method `parent_id'". However, calling `#parent_id`
|
54
|
-
# on any other category will work.
|
152
|
+
# path - the URL of the entity
|
55
153
|
#
|
56
|
-
|
57
|
-
|
58
|
-
|
154
|
+
def save
|
155
|
+
unless @new_data.empty?
|
156
|
+
client.put(url, @new_data).tap do |response|
|
157
|
+
raise_on_failure(response)
|
158
|
+
@data.merge!(@new_data)
|
159
|
+
@new_data.clear
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
59
163
|
|
60
|
-
|
61
|
-
|
164
|
+
# Public: Destroys the Entity
|
165
|
+
def destroy!
|
166
|
+
client.delete(url).tap do |response|
|
167
|
+
raise_on_failure(response)
|
62
168
|
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def to_hash
|
172
|
+
data
|
173
|
+
end
|
63
174
|
|
64
|
-
|
175
|
+
def to_json(*args)
|
176
|
+
data.to_json(*args)
|
65
177
|
end
|
66
178
|
end
|
67
179
|
end
|
data/lib/ecwid_api/error.rb
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
-
module EcwidApi
|
2
|
-
class Error < StandardError; end;
|
1
|
+
module EcwidApi
|
2
|
+
class Error < StandardError; end;
|
3
|
+
|
4
|
+
class ResponseError < Error
|
5
|
+
def initialize(response)
|
6
|
+
if response.respond_to?(:reason_phrase)
|
7
|
+
super("#{response.reason_phrase} (#{response.status})")
|
8
|
+
else
|
9
|
+
super "The Ecwid API responded with an error (#{response.status})"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
3
13
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require "cgi"
|
2
|
+
require "ostruct"
|
3
|
+
|
4
|
+
module EcwidApi
|
5
|
+
# Public: Authentication objects manage OAuth authentication with an Ecwid
|
6
|
+
# store.
|
7
|
+
#
|
8
|
+
# Examples
|
9
|
+
#
|
10
|
+
# app = EcwidApi::Authentication.new do |config|
|
11
|
+
# # see initialize for configuration
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# app.oauth_url # send the user here to authorize the app
|
15
|
+
#
|
16
|
+
# token = app.access_token(params[:code]) # this is the code they provide
|
17
|
+
# # to the redirect_uri
|
18
|
+
# token.access_token
|
19
|
+
# token.store_id # these are what you need to access the API
|
20
|
+
#
|
21
|
+
class OAuth
|
22
|
+
CONFIG = %w(client_id client_secret scope redirect_uri)
|
23
|
+
attr_accessor *CONFIG
|
24
|
+
|
25
|
+
# Public: Initializes a new Ecwid Authentication for OAuth
|
26
|
+
#
|
27
|
+
# Examples
|
28
|
+
#
|
29
|
+
# app = EcwidApi::Authentication.new do |config|
|
30
|
+
# config.client_id = "some client id"
|
31
|
+
# config.client_secret = "some client secret"
|
32
|
+
# config.scope "this_is_what_i_want_to_do oh_and_that_too"
|
33
|
+
# config.redirect_uri = "https://example.com/oauth"
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
def initialize
|
37
|
+
yield(self) if block_given?
|
38
|
+
CONFIG.each do |method|
|
39
|
+
raise Error.new("#{method} is required to initialize a new EcwidApi::Authentication") unless send(method)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Public: The URL for OAuth authorization.
|
44
|
+
#
|
45
|
+
# This is the URL that the user will need to go to to authorize the app
|
46
|
+
# with the Ecwid store.
|
47
|
+
#
|
48
|
+
def oauth_url
|
49
|
+
"https://my.ecwid.com/api/oauth/authorize?" + oauth_query
|
50
|
+
end
|
51
|
+
|
52
|
+
# Public: Obtain the access token in order to use the API
|
53
|
+
#
|
54
|
+
# code - the temporary code obtained from the authorization callback
|
55
|
+
#
|
56
|
+
# Examples
|
57
|
+
#
|
58
|
+
# token = app.access_token(params[:code])
|
59
|
+
# token.access_token # the access token that authenticates each API request
|
60
|
+
# token.store_id # the authenticated Ecwid store_id
|
61
|
+
#
|
62
|
+
# Returns an OpenStruct which responds with the information needed to
|
63
|
+
# access the API for a store.
|
64
|
+
def access_token(code)
|
65
|
+
response = connection.post("/api/oauth/token",
|
66
|
+
client_id: client_id,
|
67
|
+
client_secret: client_secret,
|
68
|
+
code: code,
|
69
|
+
redirect_uri: redirect_uri,
|
70
|
+
grant_type: "authorization_code"
|
71
|
+
)
|
72
|
+
|
73
|
+
if response.success?
|
74
|
+
OpenStruct.new(response.body)
|
75
|
+
else
|
76
|
+
raise Error.new(response.body["error_description"])
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
# Private: The query parameters for the OAuth authorization request
|
83
|
+
#
|
84
|
+
# Returns a String of query parameters
|
85
|
+
def oauth_query
|
86
|
+
{
|
87
|
+
client_id: client_id,
|
88
|
+
scope: scope,
|
89
|
+
response_type: "code",
|
90
|
+
redirect_uri: redirect_uri
|
91
|
+
}.map do |key, val|
|
92
|
+
"#{CGI.escape(key.to_s)}=#{CGI.escape(val.to_s)}"
|
93
|
+
end.join(?&)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Private: Returns a connection for obtaining an access token from Ecwid
|
97
|
+
#
|
98
|
+
def connection
|
99
|
+
@connection ||= Faraday.new "https://my.ecwid.com" do |conn|
|
100
|
+
conn.request :url_encoded
|
101
|
+
conn.response :json, content_type: /\bjson$/
|
102
|
+
conn.adapter Faraday.default_adapter
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module EcwidApi
|
2
|
+
# Public: This is an Ecwid Order
|
3
|
+
class Order < Entity
|
4
|
+
self.url_root = "orders"
|
5
|
+
|
6
|
+
ecwid_reader :orderNumber, :vendorOrderNumber, :subtotal, :total, :email,
|
7
|
+
:paymentMethod, :paymentModule, :tax, :ipAddress,
|
8
|
+
:couponDiscount, :paymentStatus, :fulfillmentStatus,
|
9
|
+
:refererUrl, :orderComments, :volumeDiscount, :customerId,
|
10
|
+
:membershipBasedDiscount, :totalAndMembershipBasedDiscount,
|
11
|
+
:discount, :usdTotal, :globalReferer, :createDate, :updateDate,
|
12
|
+
:customerGroup, :discountCoupon, :items, :billingPerson,
|
13
|
+
:shippingPerson, :shippingOption, :additionalInfo,
|
14
|
+
:paymentParams, :discountInfo, :trackingNumber,
|
15
|
+
:paymentMessage, :extTransactionId, :affiliateId,
|
16
|
+
:creditCardStatus
|
17
|
+
|
18
|
+
|
19
|
+
ecwid_writer :subtotal, :total, :email, :paymentMethod, :paymentModule,
|
20
|
+
:tax, :ipAddress, :couponDiscount, :paymentStatus,
|
21
|
+
:fulfillmentStatus, :refererUrl, :orderComments,
|
22
|
+
:volumeDiscount, :customerId, :membershipBasedDiscount,
|
23
|
+
:totalAndMembershipBasedDiscount, :discount, :globalReferer,
|
24
|
+
:createDate, :updateDate, :customerGroup, :discountCoupon,
|
25
|
+
:items, :billingPerson, :shippingPerson, :shippingOption,
|
26
|
+
:additionalInfo, :paymentParams, :discountInfo,
|
27
|
+
:trackingNumber, :paymentMessage, :extTransactionId,
|
28
|
+
:affiliateId, :creditCardStatus
|
29
|
+
|
30
|
+
VALID_FULFILLMENT_STATUSES = %w(
|
31
|
+
AWAITING_PROCESSING
|
32
|
+
PROCESSING
|
33
|
+
SHIPPED
|
34
|
+
DELIVERED
|
35
|
+
WILL_NOT_DELIVER
|
36
|
+
RETURNED
|
37
|
+
)
|
38
|
+
|
39
|
+
# Public: Gets the unique ID of the order
|
40
|
+
def id
|
41
|
+
order_number
|
42
|
+
end
|
43
|
+
|
44
|
+
# Public: Returns the billing person
|
45
|
+
def billing_person
|
46
|
+
return unless data["billingPerson"] || data["shippingPerson"]
|
47
|
+
|
48
|
+
@billing_person ||= if data["billingPerson"]
|
49
|
+
Person.new(data["billingPerson"])
|
50
|
+
else
|
51
|
+
shipping_person
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Public: Returns the shipping person
|
56
|
+
def shipping_person
|
57
|
+
return unless data["shippingPerson"] || data["billingPerson"]
|
58
|
+
@shipping_person ||= if data["shippingPerson"]
|
59
|
+
Person.new(data["shippingPerson"])
|
60
|
+
else
|
61
|
+
billing_person
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Public: Returns a Array of `OrderItem` objects
|
66
|
+
def items
|
67
|
+
@items ||= data["items"].map { |item| OrderItem.new(item) }
|
68
|
+
end
|
69
|
+
|
70
|
+
def fulfillment_status=(status)
|
71
|
+
status = status.to_s.upcase
|
72
|
+
unless VALID_FULFILLMENT_STATUSES.include?(status)
|
73
|
+
raise Error("#{status} is an invalid fullfillment status")
|
74
|
+
end
|
75
|
+
super(status)
|
76
|
+
end
|
77
|
+
|
78
|
+
def fulfillment_status
|
79
|
+
super && super.downcase.to_sym
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module EcwidApi
|
2
|
+
class OrderItem < Entity
|
3
|
+
ecwid_reader :id, :productId, :categoryId, :price, :productPrice, :weight,
|
4
|
+
:sku, :quantity, :shortDescription, :tax, :shipping,
|
5
|
+
:quantityInStock, :name, :tangible, :trackQuantity,
|
6
|
+
:fixedShippingRateOnly, :imageId, :fixedShippingRate,
|
7
|
+
:digital, :productAvailable, :couponApplied, :selectedOptions,
|
8
|
+
:taxes, :files
|
9
|
+
|
10
|
+
# Public: Returns the default `Category` that the product belongs to
|
11
|
+
def category
|
12
|
+
client.categories.find(data["categoryId"])
|
13
|
+
end
|
14
|
+
|
15
|
+
# TODO: get the product
|
16
|
+
end
|
17
|
+
end
|