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.
@@ -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
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+ script.rb
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,6 @@
1
+ ---
2
+ language: ruby
3
+ cache: bundler
4
+ rvm:
5
+ - 2.6.3
6
+ before_install: gem install bundler -v 2.1.4
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
@@ -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
@@ -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.
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -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__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -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
@@ -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
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CatalogAPI
4
+ VERSION = '0.1.0rc1'
5
+ 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: []