peddler 2.1.1 → 2.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +45 -41
- data/lib/mws.rb +2 -1
- data/lib/mws/easy_ship.rb +3 -0
- data/lib/mws/easy_ship/client.rb +93 -0
- data/lib/mws/fulfillment_outbound_shipment/client.rb +1 -1
- data/lib/mws/orders/client.rb +7 -9
- data/lib/mws/shipment_invoicing.rb +3 -0
- data/lib/mws/shipment_invoicing/client.rb +74 -0
- data/lib/mws/subscriptions/client.rb +2 -2
- data/lib/peddler/client.rb +17 -13
- data/lib/peddler/errors/builder.rb +7 -2
- data/lib/peddler/errors/class_generator.rb +9 -4
- data/lib/peddler/errors/error.rb +6 -2
- data/lib/peddler/errors/parser.rb +1 -1
- data/lib/peddler/flat_file_parser.rb +5 -3
- data/lib/peddler/headers.rb +6 -1
- data/lib/peddler/marketplace.rb +25 -19
- data/lib/peddler/operation.rb +17 -11
- data/lib/peddler/parser.rb +1 -1
- data/lib/peddler/structured_list.rb +1 -1
- data/lib/peddler/vcr_matcher.rb +7 -7
- data/lib/peddler/version.rb +1 -1
- data/lib/peddler/xml_parser.rb +1 -1
- data/lib/peddler/xml_response_parser.rb +3 -2
- metadata +15 -152
- data/lib/mws/off_amazon_payments/client.rb +0 -362
- data/lib/peddler/content.rb +0 -69
- data/lib/peddler/mws.rb +0 -58
- data/test/credentials.rb +0 -23
- data/test/helper.rb +0 -15
- data/test/integration/internals/test_errors.rb +0 -17
- data/test/integration/internals/test_multibyte_queries.rb +0 -17
- data/test/integration/internals/test_mws_headers.rb +0 -21
- data/test/integration/internals/test_string_encodings.rb +0 -38
- data/test/integration/test_feeds.rb +0 -37
- data/test/integration/test_fulfillment_inbound_shipment.rb +0 -35
- data/test/integration/test_fulfillment_inventory.rb +0 -20
- data/test/integration/test_fulfillment_outbound_shipment.rb +0 -13
- data/test/integration/test_merchant_fulfillment.rb +0 -69
- data/test/integration/test_off_amazon_payments.rb +0 -13
- data/test/integration/test_orders.rb +0 -30
- data/test/integration/test_products.rb +0 -97
- data/test/integration/test_recommendations.rb +0 -20
- data/test/integration/test_reports.rb +0 -51
- data/test/integration/test_sellers.rb +0 -13
- data/test/integration/test_subscriptions.rb +0 -27
- data/test/integration_helper.rb +0 -53
- data/test/mws.yml +0 -36
- data/test/mws.yml.example +0 -32
- data/test/null_client.rb +0 -25
- data/test/recorder.rb +0 -39
- data/test/unit/mws/test_feeds_client.rb +0 -103
- data/test/unit/mws/test_finances_client.rb +0 -74
- data/test/unit/mws/test_fulfillment_inbound_shipment_client.rb +0 -426
- data/test/unit/mws/test_fulfillment_inventory_client.rb +0 -48
- data/test/unit/mws/test_fulfillment_outbound_shipment_client.rb +0 -202
- data/test/unit/mws/test_merchant_fulfillment_client.rb +0 -109
- data/test/unit/mws/test_off_amazon_payments_client.rb +0 -286
- data/test/unit/mws/test_orders_client.rb +0 -111
- data/test/unit/mws/test_products_client.rb +0 -248
- data/test/unit/mws/test_recommendations_client.rb +0 -62
- data/test/unit/mws/test_reports_client.rb +0 -209
- data/test/unit/mws/test_sellers_client.rb +0 -47
- data/test/unit/mws/test_subscriptions_client.rb +0 -182
- data/test/unit/peddler/errors/test_builder.rb +0 -65
- data/test/unit/peddler/errors/test_class_generator.rb +0 -18
- data/test/unit/peddler/errors/test_error.rb +0 -33
- data/test/unit/peddler/errors/test_parser.rb +0 -44
- data/test/unit/peddler/test_client.rb +0 -203
- data/test/unit/peddler/test_flat_file_parser.rb +0 -111
- data/test/unit/peddler/test_headers.rb +0 -103
- data/test/unit/peddler/test_marketplace.rb +0 -47
- data/test/unit/peddler/test_operation.rb +0 -87
- data/test/unit/peddler/test_parser.rb +0 -36
- data/test/unit/peddler/test_structured_list.rb +0 -39
- data/test/unit/peddler/test_vcr_matcher.rb +0 -55
- data/test/unit/peddler/test_xml_parser.rb +0 -37
- data/test/unit/peddler/test_xml_response_parser.rb +0 -39
- data/test/unit/test_mws.rb +0 -11
- data/test/vcr_cassettes/CartInformation.yml +0 -433
- data/test/vcr_cassettes/CustomerInformation.yml +0 -433
- data/test/vcr_cassettes/Errors.yml +0 -444
- data/test/vcr_cassettes/Feeds.yml +0 -9957
- data/test/vcr_cassettes/FulfillmentInboundShipment.yml +0 -6166
- data/test/vcr_cassettes/FulfillmentInventory.yml +0 -850
- data/test/vcr_cassettes/FulfillmentOutboundShipment.yml +0 -433
- data/test/vcr_cassettes/MWSHeaders.yml +0 -2964
- data/test/vcr_cassettes/MerchantFulfillment.yml +0 -753
- data/test/vcr_cassettes/MultibyteQueries.yml +0 -437
- data/test/vcr_cassettes/OffAmazonPayments.yml +0 -433
- data/test/vcr_cassettes/Orders.yml +0 -4740
- data/test/vcr_cassettes/PeddlerVCRMatcher.yml +0 -41
- data/test/vcr_cassettes/Products.yml +0 -7139
- data/test/vcr_cassettes/Recommendations.yml +0 -3145
- data/test/vcr_cassettes/Reports.yml +0 -5549
- data/test/vcr_cassettes/Sellers.yml +0 -433
- data/test/vcr_cassettes/Subscriptions.yml +0 -1529
data/lib/peddler/content.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Peddler
|
4
|
-
# Parses content metadata provided in the headers of a response
|
5
|
-
class Content
|
6
|
-
# @api private
|
7
|
-
attr_reader :headers
|
8
|
-
|
9
|
-
# @api private
|
10
|
-
def initialize(headers)
|
11
|
-
@headers = headers.select { |key| key.start_with?('Content') }
|
12
|
-
end
|
13
|
-
|
14
|
-
# The size of the response body in bytes
|
15
|
-
# @return [String, nil]
|
16
|
-
def length
|
17
|
-
return unless headers['Content-Length']
|
18
|
-
|
19
|
-
headers['Content-Length'].to_i
|
20
|
-
end
|
21
|
-
|
22
|
-
# The MD5 digest of the response body
|
23
|
-
# @return [String, nil]
|
24
|
-
def md5
|
25
|
-
headers['Content-MD5']
|
26
|
-
end
|
27
|
-
|
28
|
-
# The MIME type of the response
|
29
|
-
# @return [String, nil]
|
30
|
-
def media_type
|
31
|
-
return unless headers['Content-Type']
|
32
|
-
|
33
|
-
headers['Content-Type'].split(';').first
|
34
|
-
end
|
35
|
-
|
36
|
-
# The general category into which the MIME type falls
|
37
|
-
# @return [String, nil]
|
38
|
-
def type
|
39
|
-
return unless media_type
|
40
|
-
|
41
|
-
media_type.split('/').first
|
42
|
-
end
|
43
|
-
|
44
|
-
# The exact kind of data of the specified type the MIME type represents
|
45
|
-
# @return [String, nil]
|
46
|
-
def subtype
|
47
|
-
return unless media_type
|
48
|
-
|
49
|
-
media_type.split('/').last
|
50
|
-
end
|
51
|
-
|
52
|
-
# The character encoding of the response
|
53
|
-
# @return [Encoding, nil]
|
54
|
-
def charset
|
55
|
-
match_data = headers['Content-Type']&.match(/charset=(.*);?/)
|
56
|
-
return unless match_data
|
57
|
-
|
58
|
-
Encoding.find(match_data[1])
|
59
|
-
end
|
60
|
-
|
61
|
-
# Whether the response is an XML document
|
62
|
-
# @return [Boolean, nil]
|
63
|
-
def xml?
|
64
|
-
return unless subtype
|
65
|
-
|
66
|
-
subtype == 'xml'
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
data/lib/peddler/mws.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Peddler
|
4
|
-
# Parses MWS metadata provided in the headers of a response
|
5
|
-
class MWS
|
6
|
-
# @api private
|
7
|
-
attr_reader :headers
|
8
|
-
|
9
|
-
# @api private
|
10
|
-
def initialize(headers)
|
11
|
-
@headers = headers.select { |key| key.start_with?('x-mws') }
|
12
|
-
end
|
13
|
-
|
14
|
-
# The max hourly request quota for the requested operation
|
15
|
-
# @return [Integer, nil]
|
16
|
-
def quota_max
|
17
|
-
return unless headers['x-mws-quota-max']
|
18
|
-
|
19
|
-
headers['x-mws-quota-max'].to_i
|
20
|
-
end
|
21
|
-
|
22
|
-
# The remaining hourly request quota for the requested operation
|
23
|
-
# @return [Integer, nil]
|
24
|
-
def quota_remaining
|
25
|
-
return unless headers['x-mws-quota-remaining']
|
26
|
-
|
27
|
-
headers['x-mws-quota-remaining'].to_i
|
28
|
-
end
|
29
|
-
|
30
|
-
# When the hourly request quota for the requested operation resets
|
31
|
-
# @return [Time, nil]
|
32
|
-
def quota_resets_on
|
33
|
-
return unless headers['x-mws-quota-resetsOn']
|
34
|
-
|
35
|
-
Time.parse(headers['x-mws-quota-resetsOn'])
|
36
|
-
end
|
37
|
-
|
38
|
-
# The ID of the request
|
39
|
-
# @return [String, nil]
|
40
|
-
def request_id
|
41
|
-
headers['x-mws-request-id']
|
42
|
-
end
|
43
|
-
|
44
|
-
# The timestamp of the request
|
45
|
-
# @return [Time, nil]
|
46
|
-
def timestamp
|
47
|
-
return unless headers['x-mws-timestamp']
|
48
|
-
|
49
|
-
Time.parse(headers['x-mws-timestamp'])
|
50
|
-
end
|
51
|
-
|
52
|
-
# The context of the response
|
53
|
-
# @return [String, nil]
|
54
|
-
def response_context
|
55
|
-
headers['x-mws-response-context']
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
data/test/credentials.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'forwardable'
|
4
|
-
require 'yaml'
|
5
|
-
|
6
|
-
module Credentials
|
7
|
-
class <<self
|
8
|
-
extend Forwardable
|
9
|
-
include Enumerable
|
10
|
-
|
11
|
-
attr_reader :all
|
12
|
-
|
13
|
-
def_delegators :all, :each
|
14
|
-
end
|
15
|
-
|
16
|
-
%w[mws.yml mws.yml.example].each do |path|
|
17
|
-
file = File.expand_path("../#{path}", __FILE__)
|
18
|
-
if File.exist?(file)
|
19
|
-
@all = YAML.load_file(file)
|
20
|
-
break
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/test/helper.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'integration_helper'
|
4
|
-
require 'mws/orders'
|
5
|
-
|
6
|
-
class TestErrors < IntegrationTest
|
7
|
-
use 'Orders'
|
8
|
-
|
9
|
-
def test_invalid_key
|
10
|
-
clients.each do |client|
|
11
|
-
assert_raises Peddler::Errors::InvalidAccessKeyId do
|
12
|
-
client.aws_access_key_id = 'foo'
|
13
|
-
client.get_order('bar')
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'integration_helper'
|
4
|
-
require 'mws/products'
|
5
|
-
|
6
|
-
class TestMultibyteQueries < IntegrationTest
|
7
|
-
use 'Products'
|
8
|
-
|
9
|
-
def test_posting_multibyte_queries_properly
|
10
|
-
ret = clients.map do |client|
|
11
|
-
res = client.list_matching_products(client.marketplace.id, 'félix guattari machinic eros')
|
12
|
-
res.body.force_encoding 'UTF-8' if defined? Ox # Ox workaround
|
13
|
-
res.parse
|
14
|
-
end
|
15
|
-
assert ret.map(&:to_s).join.include?('Félix')
|
16
|
-
end
|
17
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'integration_helper'
|
4
|
-
require 'mws/products'
|
5
|
-
|
6
|
-
class TestMWSHeaders < IntegrationTest
|
7
|
-
use 'Products'
|
8
|
-
|
9
|
-
def test_parsing_headers
|
10
|
-
clients.each do |client|
|
11
|
-
res = client.get_lowest_priced_offers_for_asin(client.marketplace.id,
|
12
|
-
'1780935374', 'New')
|
13
|
-
refute_nil res.mws_quota_max
|
14
|
-
refute_nil res.mws_quota_remaining
|
15
|
-
refute_nil res.mws_quota_resets_on
|
16
|
-
refute_nil res.mws_request_id
|
17
|
-
refute_nil res.mws_timestamp
|
18
|
-
refute_nil res.mws_response_context
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'integration_helper'
|
4
|
-
require 'mws/reports'
|
5
|
-
|
6
|
-
class TestStringEncodings < IntegrationTest
|
7
|
-
use 'Reports'
|
8
|
-
|
9
|
-
def setup
|
10
|
-
skip unless ENV['LIVE']
|
11
|
-
end
|
12
|
-
|
13
|
-
def test_flat_file_responses
|
14
|
-
get_report('_GET_SELLER_FEEDBACK_DATA_') do |res|
|
15
|
-
assert_equal res.content_charset, res.body.encoding
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def get_report(report_type, start_date: Date.today - 30)
|
22
|
-
clients.each do |client|
|
23
|
-
res = client.request_report(report_type, start_date: start_date)
|
24
|
-
report_request_id = res.dig('ReportRequestInfo', 'ReportRequestId')
|
25
|
-
loop do
|
26
|
-
sleep 15
|
27
|
-
res = client.get_report_request_list(report_request_id_list:
|
28
|
-
report_request_id)
|
29
|
-
status = res.dig('ReportRequestInfo', 'ReportProcessingStatus')
|
30
|
-
next unless status.include?('_DONE_')
|
31
|
-
|
32
|
-
report_id = res.dig('ReportRequestInfo', 'GeneratedReportId')
|
33
|
-
yield client.get_report(report_id)
|
34
|
-
break
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'integration_helper'
|
4
|
-
require 'mws/feeds'
|
5
|
-
|
6
|
-
class TestFeeds < IntegrationTest
|
7
|
-
def test_getting_feed_submission_count
|
8
|
-
clients.each do |client|
|
9
|
-
res = client.get_feed_submission_count
|
10
|
-
refute_empty res.parse
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_getting_feed_submission_list
|
15
|
-
clients.each do |client|
|
16
|
-
res = client.get_feed_submission_list
|
17
|
-
refute_empty res.parse
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_submitting_feeds
|
22
|
-
feed_content = "sku\tprice\tquantity\nwidget\t\t0\n"
|
23
|
-
feed_type = '_POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA_'
|
24
|
-
|
25
|
-
clients.each do |client|
|
26
|
-
res = client.submit_feed(feed_content, feed_type)
|
27
|
-
feed_submission_id = res.dig('FeedSubmissionInfo', 'FeedSubmissionId')
|
28
|
-
assert feed_submission_id
|
29
|
-
|
30
|
-
# Clean up
|
31
|
-
client.cancel_feed_submissions(
|
32
|
-
feed_submission_id: feed_submission_id,
|
33
|
-
feed_type_list: feed_type
|
34
|
-
)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'integration_helper'
|
4
|
-
require 'mws/fulfillment_inbound_shipment'
|
5
|
-
|
6
|
-
class TestFulfillmentInboundShipment < IntegrationTest
|
7
|
-
Address = Struct.new(:name, :address_line_1, :city, :state_or_province_code,
|
8
|
-
:postal_code, :country_code)
|
9
|
-
Item = Struct.new(:seller_sku, :quantity)
|
10
|
-
|
11
|
-
def test_creating_inbound_shipment_plan
|
12
|
-
address = Address.new('John', '1 Main St', 'New York', 'NY', '10001', 'US')
|
13
|
-
item = Item.new('123', 1)
|
14
|
-
clients.each do |client|
|
15
|
-
res = client.create_inbound_shipment_plan(address, [item])
|
16
|
-
refute_empty res.parse
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_getting_service_status
|
21
|
-
clients.each do |client|
|
22
|
-
res = client.get_service_status
|
23
|
-
refute_empty res.parse
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def test_handling_large_requests
|
28
|
-
address = Address.new('John', '1 Main St', 'New York', 'NY', '10001', 'US')
|
29
|
-
items = Array.new(100) { |i| Item.new(i, 1) }
|
30
|
-
clients.each do |client|
|
31
|
-
res = client.create_inbound_shipment_plan(address, items)
|
32
|
-
assert_equal 200, res.status
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'integration_helper'
|
4
|
-
require 'mws/fulfillment_inventory'
|
5
|
-
|
6
|
-
class TestFulfillmentInventory < IntegrationTest
|
7
|
-
def test_listing_inventory_supply
|
8
|
-
clients.each do |client|
|
9
|
-
res = client.list_inventory_supply(query_start_date_time: Date.today - 30)
|
10
|
-
refute_empty res.parse
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_getting_service_status
|
15
|
-
clients.each do |client|
|
16
|
-
res = client.get_service_status
|
17
|
-
refute_empty res.parse
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'integration_helper'
|
4
|
-
require 'mws/fulfillment_outbound_shipment'
|
5
|
-
|
6
|
-
class TestFulfillmentOutboundShipment < IntegrationTest
|
7
|
-
def test_getting_service_status
|
8
|
-
clients.each do |client|
|
9
|
-
res = client.get_service_status
|
10
|
-
refute_empty res.parse
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'integration_helper'
|
4
|
-
require 'mws/merchant_fulfillment'
|
5
|
-
|
6
|
-
class TestMerchantFulfillment < IntegrationTest
|
7
|
-
def test_getting_eligible_shipments_in_the_us
|
8
|
-
client = clients.us
|
9
|
-
res = client.get_eligible_shipping_services(shipment_request_details)
|
10
|
-
refute res.dig('ShippingServiceList', 'ShippingService').count.zero?
|
11
|
-
end
|
12
|
-
|
13
|
-
def test_shipping_in_the_us
|
14
|
-
client = clients.us
|
15
|
-
res = client.create_shipment(shipment_request_details, 'UPS_PTP_GND')
|
16
|
-
label = res.dig('Shipment', 'Label')
|
17
|
-
data_compressed = Base64.decode64(label['FileContents']['Contents'])
|
18
|
-
# data = Zlib.gunzip(data_compressed)
|
19
|
-
data = Zlib::GzipReader.new(StringIO.new(data_compressed)).read
|
20
|
-
assert_equal label['FileContents']['Checksum'], Digest::MD5.base64digest(data)
|
21
|
-
res = client.cancel_shipment(res.dig('Shipment', 'ShipmentId'))
|
22
|
-
assert_equal 'RefundPending', res.dig('Shipment', 'Status')
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_getting_service_status
|
26
|
-
clients.each do |client|
|
27
|
-
res = client.get_service_status
|
28
|
-
refute_empty res.parse
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def shipment_request_details
|
35
|
-
{
|
36
|
-
amazon_order_id: '123-1234567-1234567',
|
37
|
-
item_list: [
|
38
|
-
{
|
39
|
-
order_item_id: '12345678901234',
|
40
|
-
quantity: 1
|
41
|
-
}
|
42
|
-
],
|
43
|
-
ship_from_address: {
|
44
|
-
name: 'John Doe',
|
45
|
-
address_line_1: '10 Jay St',
|
46
|
-
email: 'john@example.com',
|
47
|
-
city: 'Brooklyn',
|
48
|
-
state_or_province_code: 'NY',
|
49
|
-
postal_code: '11201',
|
50
|
-
country_code: 'US',
|
51
|
-
phone: '7181231234'
|
52
|
-
},
|
53
|
-
package_dimensions: {
|
54
|
-
length: 40,
|
55
|
-
width: 30,
|
56
|
-
height: 10,
|
57
|
-
unit: 'centimeters'
|
58
|
-
},
|
59
|
-
weight: {
|
60
|
-
value: 1000,
|
61
|
-
unit: 'grams'
|
62
|
-
},
|
63
|
-
shipping_service_options: {
|
64
|
-
carrier_will_pick_up: false,
|
65
|
-
delivery_experience: 'DeliveryConfirmationWithoutSignature'
|
66
|
-
}
|
67
|
-
}
|
68
|
-
end
|
69
|
-
end
|