catalogapi 0.1.0rc1
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/.gitignore +12 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +74 -0
- data/README.md +136 -0
- data/Rakefile +6 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/catalogapi.gemspec +33 -0
- data/lib/catalogapi.rb +48 -0
- data/lib/catalogapi/catalog.rb +73 -0
- data/lib/catalogapi/category.rb +18 -0
- data/lib/catalogapi/item.rb +64 -0
- data/lib/catalogapi/order.rb +116 -0
- data/lib/catalogapi/request.rb +114 -0
- data/lib/catalogapi/version.rb +5 -0
- metadata +91 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c9c28867fd78f2bf1b6e7d6b057d53a4fd471af73a0476e36b6dc48c459b6862
|
4
|
+
data.tar.gz: 8ba13d73491d7c3dd241f6a4be279637a70f79267cea4f05e39330105d360f44
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 17b9fc60b840d8681866eeb58ee62c3ca419bf5d22336f50907ac7fac20534fc4ceafca7679b6750e58af338ecb726b143d8ad490316cca8e62fd34d44c4d506
|
7
|
+
data.tar.gz: 258662e822644bfa46291eff01d1a048f837d39bbcb1a6af62adecd24a9f84edde02e6f51d16cc17b9a84cbd0668aec2d92b80655580ae36e27ef3ed26b318bd
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in catalogapi.gemspec
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
gem 'rake', '~> 12.0'
|
9
|
+
|
10
|
+
group :development, :test do
|
11
|
+
gem 'pry'
|
12
|
+
gem 'rspec', '~> 3.0'
|
13
|
+
gem 'webmock'
|
14
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
catalogapi (0.1.0rc1)
|
5
|
+
http (~> 4.0)
|
6
|
+
openssl (~> 2.2)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
addressable (2.7.0)
|
12
|
+
public_suffix (>= 2.0.2, < 5.0)
|
13
|
+
coderay (1.1.3)
|
14
|
+
crack (0.4.3)
|
15
|
+
safe_yaml (~> 1.0.0)
|
16
|
+
diff-lcs (1.4.4)
|
17
|
+
domain_name (0.5.20190701)
|
18
|
+
unf (>= 0.0.5, < 1.0.0)
|
19
|
+
ffi (1.13.1)
|
20
|
+
ffi-compiler (1.0.1)
|
21
|
+
ffi (>= 1.0.0)
|
22
|
+
rake
|
23
|
+
hashdiff (1.0.1)
|
24
|
+
http (4.4.1)
|
25
|
+
addressable (~> 2.3)
|
26
|
+
http-cookie (~> 1.0)
|
27
|
+
http-form_data (~> 2.2)
|
28
|
+
http-parser (~> 1.2.0)
|
29
|
+
http-cookie (1.0.3)
|
30
|
+
domain_name (~> 0.5)
|
31
|
+
http-form_data (2.3.0)
|
32
|
+
http-parser (1.2.1)
|
33
|
+
ffi-compiler (>= 1.0, < 2.0)
|
34
|
+
method_source (1.0.0)
|
35
|
+
openssl (2.2.0)
|
36
|
+
pry (0.13.1)
|
37
|
+
coderay (~> 1.1)
|
38
|
+
method_source (~> 1.0)
|
39
|
+
public_suffix (4.0.5)
|
40
|
+
rake (12.3.3)
|
41
|
+
rspec (3.9.0)
|
42
|
+
rspec-core (~> 3.9.0)
|
43
|
+
rspec-expectations (~> 3.9.0)
|
44
|
+
rspec-mocks (~> 3.9.0)
|
45
|
+
rspec-core (3.9.2)
|
46
|
+
rspec-support (~> 3.9.3)
|
47
|
+
rspec-expectations (3.9.2)
|
48
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
49
|
+
rspec-support (~> 3.9.0)
|
50
|
+
rspec-mocks (3.9.1)
|
51
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
52
|
+
rspec-support (~> 3.9.0)
|
53
|
+
rspec-support (3.9.3)
|
54
|
+
safe_yaml (1.0.5)
|
55
|
+
unf (0.1.4)
|
56
|
+
unf_ext
|
57
|
+
unf_ext (0.0.7.7)
|
58
|
+
webmock (3.8.3)
|
59
|
+
addressable (>= 2.3.6)
|
60
|
+
crack (>= 0.3.2)
|
61
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
62
|
+
|
63
|
+
PLATFORMS
|
64
|
+
ruby
|
65
|
+
|
66
|
+
DEPENDENCIES
|
67
|
+
catalogapi!
|
68
|
+
pry
|
69
|
+
rake (~> 12.0)
|
70
|
+
rspec (~> 3.0)
|
71
|
+
webmock
|
72
|
+
|
73
|
+
BUNDLED WITH
|
74
|
+
2.1.4
|
data/README.md
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
# CatalogAPI
|
2
|
+
|
3
|
+
Ruby wrapper around the http://catalogapi.com/ API
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'catalogapi'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle install
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install catalogapi
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
### Setup your CatalogAPI
|
24
|
+
|
25
|
+
```
|
26
|
+
CatalogAPI.key = 'test-key' # provided by CatalogAPI.com
|
27
|
+
CatalogAPI.token = 'test-token' # provided by CatalogAPI.com
|
28
|
+
CatalogAPI.environment = 'development' # or production, default is development
|
29
|
+
CatalogAPI.username = 'username' # provided by CatalogAPI.com (subdomain)
|
30
|
+
```
|
31
|
+
|
32
|
+
### Catalogs
|
33
|
+
|
34
|
+
#### List Available Catalogs
|
35
|
+
|
36
|
+
```
|
37
|
+
CatalogAPI::Catalog.list_available.data
|
38
|
+
=> [
|
39
|
+
#<CatalogAPI::Catalog @currency="USD", @export_uri=...,
|
40
|
+
#<CatalogAPI::Catalog @currency="USD", @export_uri=...,
|
41
|
+
]
|
42
|
+
```
|
43
|
+
|
44
|
+
#### List the item categories available in a catalog
|
45
|
+
|
46
|
+
```
|
47
|
+
CatalogAPI::Catalog.new(socket_id: '123').breakdown.data
|
48
|
+
=> [
|
49
|
+
#<CatalogAPI::Category
|
50
|
+
@category_id="99",
|
51
|
+
@children=[#<CatalogAPI::Category @category_id="11"...>],
|
52
|
+
...
|
53
|
+
>,
|
54
|
+
...
|
55
|
+
]
|
56
|
+
```
|
57
|
+
|
58
|
+
#### Searches a catalog by keyword, category, or price range.
|
59
|
+
|
60
|
+
```
|
61
|
+
CatalogAPI::Catalog.new(socket_id: '123').search(search: 'ipod').data
|
62
|
+
=> [
|
63
|
+
#<CatalogAPI::Item
|
64
|
+
@brand="Apple",
|
65
|
+
@catalog_item_id=1234
|
66
|
+
...
|
67
|
+
>,
|
68
|
+
...
|
69
|
+
]
|
70
|
+
```
|
71
|
+
|
72
|
+
__Note the `paginated` option will paginate over all pages and aggregate the result__
|
73
|
+
|
74
|
+
### Items
|
75
|
+
|
76
|
+
#### View the full details of a single item.
|
77
|
+
|
78
|
+
```
|
79
|
+
CatalogAPI::Item.new(catalog_item_id: 1, socket_id: 2).view.data
|
80
|
+
=> #<CatalogAPI::Item
|
81
|
+
...
|
82
|
+
@catalog_item_id="1",
|
83
|
+
...
|
84
|
+
@description=
|
85
|
+
...
|
86
|
+
>
|
87
|
+
```
|
88
|
+
|
89
|
+
### Orders
|
90
|
+
|
91
|
+
#### List all orders
|
92
|
+
|
93
|
+
```
|
94
|
+
CatalogAPI::Order.list(external_user_id).data
|
95
|
+
=> [
|
96
|
+
#<CatalogAPI::Order
|
97
|
+
external_user_id=1
|
98
|
+
...
|
99
|
+
>,
|
100
|
+
...
|
101
|
+
]
|
102
|
+
```
|
103
|
+
__Note the `paginated` option will paginate over all pages and aggregate the result__
|
104
|
+
|
105
|
+
#### Place an order
|
106
|
+
```
|
107
|
+
CatalogAPI::Order.new(
|
108
|
+
items: CatalogAPI::Item.new,
|
109
|
+
first_name: "Test",
|
110
|
+
last_name: "Testman",
|
111
|
+
address_1: "123 Test Street",
|
112
|
+
city: "Cincinnati",
|
113
|
+
state_province: "OH",
|
114
|
+
postal_code: "00000",
|
115
|
+
country: "US"
|
116
|
+
).place.data
|
117
|
+
=> #<CatalogAPI::Order @order_number="XXXX-XXXXX-XXXXX-XXXX" ...>
|
118
|
+
```
|
119
|
+
|
120
|
+
#### Track an order
|
121
|
+
|
122
|
+
```
|
123
|
+
CatalogAPI::Order.new(order_number: '4004-20883-04361-0098').track.data
|
124
|
+
=> #<CatalogAPI::Item:0x00007f92d6430948 @order_number="4004-20883-04361-0098" ...>
|
125
|
+
```
|
126
|
+
|
127
|
+
|
128
|
+
## Development
|
129
|
+
|
130
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
131
|
+
|
132
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
133
|
+
|
134
|
+
## Contributing
|
135
|
+
|
136
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/catalogapi.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'catalogapi'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/catalogapi.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/catalogapi/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'catalogapi'
|
7
|
+
spec.version = CatalogAPI::VERSION
|
8
|
+
spec.authors = ['davidrichey']
|
9
|
+
spec.email = ['david.richey@memberhub.com']
|
10
|
+
|
11
|
+
spec.summary = 'Ruby gem that wraps http://catalogapi.com/ API'
|
12
|
+
spec.description = 'Simple ruby library to interact with the http://catalogapi.com/ API'
|
13
|
+
spec.homepage = 'http://github.com/memberhubteam/catalogapi'
|
14
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
|
15
|
+
|
16
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org/'
|
17
|
+
|
18
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
19
|
+
spec.metadata['source_code_uri'] = 'http://github.com/memberhubteam/catalogapi'
|
20
|
+
spec.metadata['changelog_uri'] = 'http://github.com/memberhubteam/catalogapi/blob/master/CHANGELOG.md'
|
21
|
+
|
22
|
+
# Specify which files should be added to the gem when it is released.
|
23
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
24
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
25
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
|
+
end
|
27
|
+
spec.bindir = 'exe'
|
28
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
29
|
+
spec.require_paths = ['lib']
|
30
|
+
|
31
|
+
spec.add_dependency 'http', '~> 4.0'
|
32
|
+
spec.add_dependency 'openssl', '~> 2.2'
|
33
|
+
end
|
data/lib/catalogapi.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'catalogapi/request'
|
4
|
+
require 'catalogapi/catalog'
|
5
|
+
require 'catalogapi/category'
|
6
|
+
require 'catalogapi/item'
|
7
|
+
require 'catalogapi/order'
|
8
|
+
require 'catalogapi/version'
|
9
|
+
|
10
|
+
require 'pry'
|
11
|
+
|
12
|
+
module CatalogAPI
|
13
|
+
class Error < StandardError; end
|
14
|
+
|
15
|
+
class << self
|
16
|
+
attr_accessor :environment, :key, :token, :username
|
17
|
+
|
18
|
+
def development?
|
19
|
+
!production?
|
20
|
+
end
|
21
|
+
|
22
|
+
def production?
|
23
|
+
environment == 'production'
|
24
|
+
end
|
25
|
+
|
26
|
+
def request
|
27
|
+
CatalogAPI::Request
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Services::OnlineRewards::Request] request to the list_available_catalogs endpoint
|
32
|
+
def list_available_catalogs
|
33
|
+
request.new(:list_available_catalogs).get
|
34
|
+
end
|
35
|
+
|
36
|
+
# @param socket_id [String] the Socket ID from the list_available_catalogs
|
37
|
+
# @return [Services::OnlineRewards::Request]
|
38
|
+
def catalog_breakdown(socket_id)
|
39
|
+
request.new(:catalog_breakdown).get(socket_id: socket_id)
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param socket_id [String] the Socket ID from the list_available_catalogs
|
43
|
+
# @param search [String] keywork to search for
|
44
|
+
# @return [Services::OnlineRewards::Request]
|
45
|
+
def search_catalog(socket_id, search)
|
46
|
+
request.new(:search_catalog).get(socket_id: socket_id, search: search)
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CatalogAPI
|
4
|
+
class Catalog
|
5
|
+
class << self
|
6
|
+
# @return [Array[CatalogAPI::Catalog]] Returns a list of the catalog sockets you have available on your account.
|
7
|
+
def list_available
|
8
|
+
request = CatalogAPI.request.new(:list_available_catalogs).get
|
9
|
+
sockets = request.json.dig(
|
10
|
+
:list_available_catalogs_response, :list_available_catalogs_result,
|
11
|
+
:domain, :sockets, :Socket
|
12
|
+
).to_a
|
13
|
+
request.data = sockets.map { |socket| new(socket) }
|
14
|
+
request
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :currency, :export_uri, :language, :point_to_currency_ratio,
|
19
|
+
:region, :socket_id, :socket_name
|
20
|
+
def initialize(opts)
|
21
|
+
@currency = opts[:currency]
|
22
|
+
@export_uri = opts[:export_uri]
|
23
|
+
@language = opts[:language]
|
24
|
+
@point_to_currency_ratio = opts[:point_to_currency_ratio]
|
25
|
+
@region = opts[:region]
|
26
|
+
@socket_id = opts[:socket_id]
|
27
|
+
@socket_name = opts[:socket_name]
|
28
|
+
end
|
29
|
+
|
30
|
+
# @return [Array[CatalogAPI::Category]] Returns a list of item categories available in a catalog
|
31
|
+
def breakdown(is_flat: 0)
|
32
|
+
raise CatalogAPI::Error, 'No Socket ID' if socket_id.nil?
|
33
|
+
|
34
|
+
request = CatalogAPI.request.new(:catalog_breakdown).get(socket_id: socket_id, is_flat: is_flat)
|
35
|
+
catgories = request.json.dig(
|
36
|
+
:catalog_breakdown_response, :catalog_breakdown_result, :categories,
|
37
|
+
:Category
|
38
|
+
).to_a
|
39
|
+
request.data = catgories.map { |cateogry| CatalogAPI::Category.new(cateogry) }
|
40
|
+
request
|
41
|
+
end
|
42
|
+
|
43
|
+
# @option options [String] :name Searches the names of items.
|
44
|
+
# @option options [String] :search Search the name, description and model of items.
|
45
|
+
# @option options [String] :category_id Returns only items within this category_id. (This includes any child categories of the category_id.) The category_id comes from the catalog_breakdown method.
|
46
|
+
# @option options [String] :min_points Return only items that have a point value of at least this value.
|
47
|
+
# @option options [String] :max_points Return only items that have a point value of no more than this value.
|
48
|
+
# @option options [String] :min_price Return only items that have a price of at least this value.
|
49
|
+
# @option options [String] :max_price Return only items that have a price of no more than this value.
|
50
|
+
# @option options [String] :max_rank Do not return items with a rank higher than this value.
|
51
|
+
# @option options [String] :tag We have the ability to "tag" certain items based on custom criteria that is unique to our clients. If we setup these tags on your catalog, you can pass a tag name with your search.
|
52
|
+
# @option options [String] :page The page number. Defaults to 1.
|
53
|
+
# @option options [String] :paginated Whether to paginate the call or return the first page result default: nil
|
54
|
+
# @option options [String] :per_page The number of items to return, per page. Can be from 1 to 50. Defaults to 10.
|
55
|
+
# @option options [String] :sort The following sort values are supported: 'points desc', 'points asc', 'rank asc', 'score desc', 'random asc'
|
56
|
+
# @option options [String] :catalog_item_ids Return only items in the given list.
|
57
|
+
# @return [Array[CatalogAPI::Item]] Searches a catalog by keyword, category, or price range.
|
58
|
+
def search(options = {}, request = nil)
|
59
|
+
raise CatalogAPI::Error, 'No Socket ID' if socket_id.nil?
|
60
|
+
|
61
|
+
request ||= CatalogAPI.request.new(:search_catalog)
|
62
|
+
request = request.get(options.to_h.merge(socket_id: socket_id))
|
63
|
+
items = request.json.dig(
|
64
|
+
:search_catalog_response, :search_catalog_result, :items, :CatalogItem
|
65
|
+
).to_a
|
66
|
+
request.data += items.map { |item| CatalogAPI::Item.new(item.merge(socket_id: socket_id)) }
|
67
|
+
# Pagination
|
68
|
+
next_page = options[:paginated] ? request.next_page : nil
|
69
|
+
request = search(options.merge(page: next_page), request) if next_page
|
70
|
+
request
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CatalogAPI
|
4
|
+
class Category
|
5
|
+
attr_reader :category_id, :children, :depth, :item_count, :name,
|
6
|
+
:parent_category_id
|
7
|
+
def initialize(opts)
|
8
|
+
@category_id = opts[:category_id]
|
9
|
+
@children = opts.dig(:children, :Category).to_a.map do |child|
|
10
|
+
CatalogAPI::Category.new(child)
|
11
|
+
end
|
12
|
+
@depth = opts[:depth]
|
13
|
+
@item_count = opts[:item_count]
|
14
|
+
@name = opts[:name]
|
15
|
+
@parent_category_id = opts[:parent_category_id]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CatalogAPI
|
4
|
+
class Item
|
5
|
+
attr_accessor :description
|
6
|
+
|
7
|
+
attr_reader :brand, :catalog_item_id, :catalog_price, :categories,
|
8
|
+
:currency, :has_options, :image_150, :image_300,
|
9
|
+
:image_75, :model, :name, :options, :original_points,
|
10
|
+
:original_price, :points, :rank, :retail_price,
|
11
|
+
:shipping_estimate, :socket_id, :tags,
|
12
|
+
:quantity, :option_id
|
13
|
+
def initialize(opts)
|
14
|
+
@brand = opts[:brand]
|
15
|
+
@catalog_item_id = opts[:catalog_item_id]
|
16
|
+
@catalog_price = opts[:catalog_price]
|
17
|
+
@categories = opts[:categories].to_h[:integer]
|
18
|
+
@currency = opts[:currency] || 'USD'
|
19
|
+
@description = opts[:description]
|
20
|
+
@has_options = opts[:has_options]
|
21
|
+
@image_150 = opts[:image_150]
|
22
|
+
@image_300 = opts[:image_300]
|
23
|
+
@image_75 = opts[:image_75]
|
24
|
+
@model = opts[:model]
|
25
|
+
@name = opts[:name]
|
26
|
+
@options = opts[:options]
|
27
|
+
@original_points = opts[:original_points]
|
28
|
+
@original_price = opts[:original_price]
|
29
|
+
@points = opts[:points]
|
30
|
+
@rank = opts[:rank]
|
31
|
+
@retail_price = opts[:retail_price]
|
32
|
+
@shipping_estimate = opts[:shipping_estimate]
|
33
|
+
@socket_id = opts[:socket_id]
|
34
|
+
@tags = opts[:tags].to_h[:string]
|
35
|
+
@quantity = opts[:quantity] || 1
|
36
|
+
@option_id = opts[:option_id]
|
37
|
+
end
|
38
|
+
|
39
|
+
def order_params
|
40
|
+
{
|
41
|
+
catalog_item_id: catalog_item_id,
|
42
|
+
quantity: quantity,
|
43
|
+
currency: currency,
|
44
|
+
catalog_price: catalog_price.to_f,
|
45
|
+
option_id: option_id
|
46
|
+
}.reject { |_k, v| v.nil? }.to_h
|
47
|
+
end
|
48
|
+
|
49
|
+
def orderable?
|
50
|
+
!catalog_item_id.nil? && !catalog_price.nil?
|
51
|
+
end
|
52
|
+
|
53
|
+
def view
|
54
|
+
raise CatalogAPI::Error, 'No Socket ID' if socket_id.nil?
|
55
|
+
raise CatalogAPI::Error, 'No Catalog Item ID' if catalog_item_id.nil?
|
56
|
+
|
57
|
+
request = CatalogAPI.request.new(:view_item)
|
58
|
+
.get(socket_id: socket_id, catalog_item_id: catalog_item_id)
|
59
|
+
fields = request.json.dig(:view_item_response, :view_item_result, :item)
|
60
|
+
request.data = self.class.new(fields)
|
61
|
+
request
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CatalogAPI
|
4
|
+
class Order
|
5
|
+
attr_reader :date_placed, :external_user_id, :order_number,
|
6
|
+
:external_order_number, :first_name, :last_name,
|
7
|
+
:address_1, :address_2, :address_3, :city, :state_province,
|
8
|
+
:postal_code, :country, :phone_number, :email, :items
|
9
|
+
|
10
|
+
def initialize(opts)
|
11
|
+
@date_placed = nil
|
12
|
+
if opts[:date_placed] && !opts[:date_placed].empty?
|
13
|
+
@date_placed = Time.parse(opts[:date_placed]).to_time
|
14
|
+
end
|
15
|
+
@external_user_id = opts[:external_user_id]
|
16
|
+
@order_number = opts[:order_number]
|
17
|
+
|
18
|
+
@external_user_id = opts[:external_user_id]
|
19
|
+
@external_order_number = opts[:external_order_number]
|
20
|
+
@first_name = opts[:first_name]
|
21
|
+
@last_name = opts[:last_name]
|
22
|
+
@address_1 = opts[:address_1]
|
23
|
+
@address_2 = opts[:address_2]
|
24
|
+
@address_3 = opts[:address_3]
|
25
|
+
@city = opts[:city]
|
26
|
+
@state_province = opts[:state_province]
|
27
|
+
@postal_code = opts[:postal_code]
|
28
|
+
@country = opts[:country]
|
29
|
+
@email = opts[:email]
|
30
|
+
@phone_number = opts[:phone_number]
|
31
|
+
@items = opts[:items].to_a
|
32
|
+
end
|
33
|
+
|
34
|
+
class << self
|
35
|
+
# @option options [String] :external_user_id external user id used placing the order
|
36
|
+
# @option options [String] :page page number of results to return when there are more than per_page results.
|
37
|
+
# @option options [String] :per_page number of orders to return. Defaults to 10. Can be increased to a maximum of 50.
|
38
|
+
# @option options [String] :paginated return all orders by paginating over all pages
|
39
|
+
# @return [Array[CatalogAPI::Order]] return all orders placed by that user.
|
40
|
+
def list(options = {}, request = nil)
|
41
|
+
external_user_id = options[:external_user_id]
|
42
|
+
raise CatalogAPI::Error, 'No External User ID' if external_user_id.nil?
|
43
|
+
|
44
|
+
request ||= CatalogAPI.request.new(:order_list)
|
45
|
+
request = request.get(options.merge(external_user_id: external_user_id))
|
46
|
+
orders = request.json.dig(
|
47
|
+
:order_list_response, :order_list_result, :orders, :OrderSummary
|
48
|
+
).to_a
|
49
|
+
request.data += orders.map { |item| CatalogAPI::Order.new(item.merge(external_user_id: external_user_id)) }
|
50
|
+
# Pagination
|
51
|
+
next_page = options[:paginated] ? request.next_page : nil
|
52
|
+
request = list(options.merge(page: next_page), request) if next_page
|
53
|
+
request
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Place an order without requiring a cart.
|
58
|
+
# @return [CatalogAPI::Order]
|
59
|
+
def place
|
60
|
+
raise CatalogAPI::Error, 'No Items' if items.nil? || items.length.zero?
|
61
|
+
raise CatalogAPI::Error, 'No Socket ID' if items.first.socket_id.nil?
|
62
|
+
raise CatalogAPI::Error, 'No First Name' if first_name.nil?
|
63
|
+
raise CatalogAPI::Error, 'No Last Name' if last_name.nil?
|
64
|
+
raise CatalogAPI::Error, 'No Adress1' if address_1.nil?
|
65
|
+
raise CatalogAPI::Error, 'No City' if city.nil?
|
66
|
+
raise CatalogAPI::Error, 'No State' if state_province.nil?
|
67
|
+
raise CatalogAPI::Error, 'No Postal Code' if postal_code.nil?
|
68
|
+
raise CatalogAPI::Error, 'No Country' if country.nil?
|
69
|
+
raise CatalogAPI::Error, 'No Items' if items.nil?
|
70
|
+
|
71
|
+
request = CatalogAPI.request.new(:order_place)
|
72
|
+
request.post(place_params(request))
|
73
|
+
json = request.json.dig(:order_place_response, :order_place_result)
|
74
|
+
request.data = CatalogAPI::Order.new(json)
|
75
|
+
request
|
76
|
+
end
|
77
|
+
|
78
|
+
# @return [CatalogAPI::Order] Return the details of a previously placed order, including any shipment information.
|
79
|
+
def track
|
80
|
+
raise CatalogAPI::Error, 'No Order Number' if order_number.nil?
|
81
|
+
|
82
|
+
request = CatalogAPI.request.new(:order_track).get(order_number: order_number)
|
83
|
+
json = request.json.dig(:order_track_response, :order_track_result, :order)
|
84
|
+
items = json.dig(:items, :OrderItem).to_a.map { |i| CatalogAPI::Item.new(i) }
|
85
|
+
request.data = CatalogAPI::Order.new(json.merge(items: items))
|
86
|
+
request
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def place_params(request)
|
92
|
+
{
|
93
|
+
order_place: {
|
94
|
+
order_place_request: {
|
95
|
+
credentials: request.required_params(''),
|
96
|
+
socket_id: items.first.socket_id,
|
97
|
+
external_user_id: external_user_id,
|
98
|
+
external_order_number: external_order_number,
|
99
|
+
first_name: first_name,
|
100
|
+
last_name: last_name,
|
101
|
+
address_1: address_1,
|
102
|
+
address_2: address_2,
|
103
|
+
address_3: address_3,
|
104
|
+
city: city,
|
105
|
+
state_province: state_province,
|
106
|
+
postal_code: postal_code,
|
107
|
+
country: country,
|
108
|
+
phone_number: phone_number,
|
109
|
+
email: email,
|
110
|
+
items: items.map(&:order_params)
|
111
|
+
}.reject { |_k, v| v.nil? }.to_h
|
112
|
+
}
|
113
|
+
}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'base64'
|
4
|
+
require 'openssl'
|
5
|
+
require 'securerandom'
|
6
|
+
require 'time'
|
7
|
+
|
8
|
+
module CatalogAPI
|
9
|
+
class Request
|
10
|
+
attr_accessor :method_name, :path, :response, :json, :data, :body
|
11
|
+
def initialize(method_name, path: nil)
|
12
|
+
@data = []
|
13
|
+
@method_name = method_name
|
14
|
+
@path = path || method_name
|
15
|
+
end
|
16
|
+
|
17
|
+
def base_url
|
18
|
+
env = CatalogAPI.production? ? 'prod' : 'dev'
|
19
|
+
username = CatalogAPI.username
|
20
|
+
"https://#{username}.#{env}.catalogapi.com/v1"
|
21
|
+
end
|
22
|
+
|
23
|
+
def get(params = {})
|
24
|
+
url = "#{base_url}/rest/#{path}"
|
25
|
+
self.response = HTTP.get(url, { params: params.merge(required_params) })
|
26
|
+
json_response
|
27
|
+
end
|
28
|
+
|
29
|
+
def post(params = {})
|
30
|
+
url = "#{base_url}/json/#{path}"
|
31
|
+
puts params
|
32
|
+
self.response = HTTP.post(url, { json: params })
|
33
|
+
json_response
|
34
|
+
end
|
35
|
+
|
36
|
+
def json_response
|
37
|
+
check_status!
|
38
|
+
self.json = JSON.parse(response.body.to_s, symbolize_names: true)
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
# CatalogAPI Error
|
43
|
+
class Error < StandardError
|
44
|
+
attr_accessor :code, :body
|
45
|
+
def initialize(response)
|
46
|
+
puts response.inspect
|
47
|
+
puts response.body
|
48
|
+
@body = response.body
|
49
|
+
@code = response.code
|
50
|
+
end
|
51
|
+
|
52
|
+
def message
|
53
|
+
"#{code} #{body}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def first
|
58
|
+
data.first
|
59
|
+
end
|
60
|
+
|
61
|
+
def each(&block)
|
62
|
+
data.each(&block)
|
63
|
+
end
|
64
|
+
|
65
|
+
def map(&block)
|
66
|
+
data.map(&block)
|
67
|
+
end
|
68
|
+
|
69
|
+
def next_page
|
70
|
+
page_info = json.dig(
|
71
|
+
"#{method_name}_response".to_sym, "#{method_name}_result".to_sym, :pager
|
72
|
+
).to_h
|
73
|
+
return nil unless page_info[:has_next].to_i == 1
|
74
|
+
|
75
|
+
page_info[:page] + 1
|
76
|
+
end
|
77
|
+
|
78
|
+
def required_params(prepend = 'creds_')
|
79
|
+
{
|
80
|
+
"#{prepend}datetime".to_sym => time,
|
81
|
+
"#{prepend}uuid".to_sym => uuid,
|
82
|
+
"#{prepend}checksum".to_sym => checksum,
|
83
|
+
"#{prepend}method".to_sym => method_name.to_s
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
# http://memberhub.catalogapi.com/docs/checksums/
|
90
|
+
def checksum
|
91
|
+
Base64.encode64(OpenSSL::HMAC.digest('sha1', CatalogAPI.key, concatted))
|
92
|
+
.gsub("\n", '')
|
93
|
+
end
|
94
|
+
|
95
|
+
def check_status!
|
96
|
+
case response.code.to_i
|
97
|
+
when 200 then response
|
98
|
+
else raise Error, response
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def concatted
|
103
|
+
@concatted ||= "#{method_name}#{uuid}#{time}"
|
104
|
+
end
|
105
|
+
|
106
|
+
def time
|
107
|
+
@time ||= Time.now.utc.iso8601
|
108
|
+
end
|
109
|
+
|
110
|
+
def uuid
|
111
|
+
@uuid ||= SecureRandom.uuid
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: catalogapi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0rc1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- davidrichey
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-08-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: http
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: openssl
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.2'
|
41
|
+
description: Simple ruby library to interact with the http://catalogapi.com/ API
|
42
|
+
email:
|
43
|
+
- david.richey@memberhub.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- ".rspec"
|
50
|
+
- ".travis.yml"
|
51
|
+
- Gemfile
|
52
|
+
- Gemfile.lock
|
53
|
+
- README.md
|
54
|
+
- Rakefile
|
55
|
+
- bin/console
|
56
|
+
- bin/setup
|
57
|
+
- catalogapi.gemspec
|
58
|
+
- lib/catalogapi.rb
|
59
|
+
- lib/catalogapi/catalog.rb
|
60
|
+
- lib/catalogapi/category.rb
|
61
|
+
- lib/catalogapi/item.rb
|
62
|
+
- lib/catalogapi/order.rb
|
63
|
+
- lib/catalogapi/request.rb
|
64
|
+
- lib/catalogapi/version.rb
|
65
|
+
homepage: http://github.com/memberhubteam/catalogapi
|
66
|
+
licenses: []
|
67
|
+
metadata:
|
68
|
+
allowed_push_host: https://rubygems.org/
|
69
|
+
homepage_uri: http://github.com/memberhubteam/catalogapi
|
70
|
+
source_code_uri: http://github.com/memberhubteam/catalogapi
|
71
|
+
changelog_uri: http://github.com/memberhubteam/catalogapi/blob/master/CHANGELOG.md
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 2.3.0
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">"
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 1.3.1
|
86
|
+
requirements: []
|
87
|
+
rubygems_version: 3.0.3
|
88
|
+
signing_key:
|
89
|
+
specification_version: 4
|
90
|
+
summary: Ruby gem that wraps http://catalogapi.com/ API
|
91
|
+
test_files: []
|