muffin_man 1.0.2 → 1.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 01a263a02506880dbfef45399e3294486b858cc72d5a9fc370f155128de17d0a
4
- data.tar.gz: d8fdd99a82562bcc2c354fb8c59d2c7c366802fbdf41b8b45c1f9f0ab9b596d8
3
+ metadata.gz: 82c3118e9e61b82872329714fbfbaf80fd7613ff98ce126992f2ac3b834e3a51
4
+ data.tar.gz: 201afe55ba25967d8e519ff5f6a0ac9a66e452462cc4fe805ab2a34b61edec9a
5
5
  SHA512:
6
- metadata.gz: ad0248e2f1020a243bdb2901d7c0331d377733c01490875a64e2e92f380702fabfd34abc5aafcaf6c39244891380551d0d9e20b35197d969ed09d93ab551a06e
7
- data.tar.gz: cac4177e290055336395d095936236f48449df8f56cee789a4201c5dd6e3eb9afecae7f2923c4ec6964515eb6a492ac5bbc597f1fcd35bda0d6fab56cf392e11
6
+ metadata.gz: 9411d153ce20efc02882b456a9b6be233cf88e691472d35bbca5b8890fc422395d5a925a66996c129a1a5835883ac66153415043a94e37ad2d9c6e7e3b17baf5
7
+ data.tar.gz: 7859bc864e708516ce37087a32791a1fbbae140af2307fbc8d7c530933517e1d914faf704151b7269c290853cfa3a44c741c552a8aadf06bf605cc5ba2745d28
data/.rubocop.yml CHANGED
@@ -11,3 +11,6 @@ Style/StringLiteralsInInterpolation:
11
11
 
12
12
  Layout/LineLength:
13
13
  Max: 120
14
+
15
+ Metrics/MethodLength:
16
+ Max: 30
data/CODE_OF_CONDUCT.md CHANGED
@@ -39,7 +39,7 @@ This Code of Conduct applies within all community spaces, and also applies when
39
39
 
40
40
  ## Enforcement
41
41
 
42
- Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at gavin@iserve.com. All complaints will be reviewed and investigated promptly and fairly.
42
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at opensource@pattern.com. All complaints will be reviewed and investigated promptly and fairly.
43
43
 
44
44
  All community leaders are obligated to respect the privacy and security of the reporter of any incident.
45
45
 
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Ruby CI](https://github.com/patterninc/muffin_man/actions/workflows/ci.yml/badge.svg)](https://github.com/patterninc/muffin_man/actions)
4
4
 
5
- MuffinMan is a ruby interface to the Amazon Selling Partner API. For more information on registering to use the Selling Partner API, see [Amazon's documentation](https://github.com/amzn/selling-partner-api-docs/blob/main/guides/developer-guide/SellingPartnerApiDeveloperGuide.md)
5
+ MuffinMan is a ruby interface to the Amazon Selling Partner API. For more information on registering to use the Selling Partner API, see [Amazon's documentation](https://github.com/amzn/selling-partner-api-docs/blob/main/guides/en-US/developer-guide/SellingPartnerApiDeveloperGuide.md)
6
6
 
7
7
  As of now, this gem only supports portions of the following APIs with more to come:
8
8
 
@@ -63,6 +63,27 @@ MuffinMan.configure do |config|
63
63
  end
64
64
  ```
65
65
 
66
+ ### Retrieiving the refresh token
67
+
68
+ To retrieve the refresh token from an LWA Website authorization workflow, you can use the LWA helper:
69
+
70
+ ```ruby
71
+ # Get your auth code first, either through the Website oauth flow or Authorization API
72
+ credentials = {
73
+ client_id: CLIENT_ID,
74
+ client_secret: CLIENT_SECRET,
75
+ aws_access_key_id: AWS_ACCESS_KEY_ID,
76
+ aws_secret_access_key: AWS_SECRET_ACCESS_KEY,
77
+ sts_iam_role_arn: STS_IAM_ROLE_ARN, # Optional
78
+ scope: 'sellingpartnerapi::migration' # Grantless scope for MWS migration
79
+ }
80
+ client = MuffinMan::Authorization::V1.new(credentials)
81
+ resp = JSON.parse(client.get_authorization_code(seller_id, developer_id, mws_auth_token).body)
82
+ auth_code = resp['payload']['authorizationCode']
83
+ # Then query retrieve the refresh token to store
84
+ refresh_token = MuffinMan::Lwa::AuthHelper.get_refresh_token(CLIENT_ID, CLIENT_SECRET, auth_code)
85
+ ```
86
+
66
87
  ## Contributing
67
88
 
68
89
  Bug reports and pull requests are welcome on GitHub at https://github.com/patterninc/muffin_man. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/patterninc/muffin_man/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,16 @@
1
+ module MuffinMan
2
+ module Authorization
3
+ class V1 < SpApiClient
4
+ def get_authorization_code(selling_partner_id, developer_id, mws_auth_token)
5
+ @query_params = {
6
+ "sellingPartnerId" => selling_partner_id,
7
+ "developerId" => developer_id,
8
+ "mwsAuthToken" => mws_auth_token
9
+ }
10
+ @request_type = "GET"
11
+ @local_var_path = "/authorization/v1/authorizationCode"
12
+ call_api
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,33 @@
1
+ module MuffinMan
2
+ module Finances
3
+ class V0 < SpApiClient
4
+ def list_financial_event_groups(max_results_per_page = nil, financial_event_group_started_before = nil, financial_event_group_started_after = nil, next_token = nil)
5
+ @local_var_path = "/finances/v0/financialEventGroups"
6
+ @query_params = {}
7
+ @query_params["MaxResultsPerPage"] = max_results_per_page unless max_results_per_page.nil?
8
+ unless financial_event_group_started_before.nil?
9
+ @query_params["FinancialEventGroupStartedBefore"] =
10
+ financial_event_group_started_before
11
+ end
12
+ unless financial_event_group_started_after.nil?
13
+ @query_params["FinancialEventGroupStartedAfter"] =
14
+ financial_event_group_started_after
15
+ end
16
+ @query_params["NextToken"] = next_token unless next_token.nil?
17
+ @request_type = "GET"
18
+ call_api
19
+ end
20
+
21
+ def list_financial_events_by_group_id(event_group_id, max_results_per_page = nil, posted_after = nil, posted_before = nil, next_token = nil)
22
+ @local_var_path = "/finances/v0/financialEventGroups/#{event_group_id}/financialEvents"
23
+ @query_params = {}
24
+ @query_params["MaxResultsPerPage"] = max_results_per_page unless max_results_per_page.nil?
25
+ @query_params["PostedAfter"] = posted_after unless posted_after.nil?
26
+ @query_params["PostedBefore"] = posted_before unless posted_before.nil?
27
+ @query_params["NextToken"] = next_token unless next_token.nil?
28
+ @request_type = "GET"
29
+ call_api
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,27 @@
1
+ module MuffinMan::Lwa
2
+ class AuthHelper
3
+ ACCESS_TOKEN_URL = "https://api.amazon.com/auth/o2/token".freeze
4
+
5
+ def self.get_refresh_token(client_id, client_secret, auth_code)
6
+ body = {
7
+ grant_type: "authorization_code",
8
+ code: auth_code,
9
+ client_id: client_id,
10
+ client_secret: client_secret
11
+ }
12
+ response = Typhoeus.post(
13
+ ACCESS_TOKEN_URL,
14
+ body: URI.encode_www_form(body),
15
+ headers: {
16
+ "Content-Type" => "application/x-www-form-urlencoded;charset=UTF-8"
17
+ }
18
+ )
19
+ if response.code != 200
20
+ error_body = JSON.parse(response.body)
21
+ error = "#{error_body["error"]}: #{error_body["error_description"]}"
22
+ raise MuffinMan::Error, error
23
+ end
24
+ JSON.parse(response.body)["refresh_token"]
25
+ end
26
+ end
27
+ end
@@ -1,12 +1,40 @@
1
1
  module MuffinMan
2
2
  module Reports
3
3
  class V20210630 < SpApiClient
4
- SANDBOX_REPORT_TYPE = "GET_MERCHANT_LISTINGS_ALL_DATA"
5
- SANDBOX_START_TIME = "2019-12-10T20:11:24.000Z"
6
- SANDBOX_MARKETPLACE_IDS = [
7
- "A1PA6795UKMFR9",
8
- "ATVPDKIKX0DER"
9
- ]
4
+ SANDBOX_REPORT_TYPES = "FEE_DISCOUNTS_REPORT,GET_AFN_INVENTORY_DATA".freeze
5
+ SANDBOX_PROCESSING_STATUSES = "IN_QUEUE,IN_PROGRESS".freeze
6
+ SANDBOX_REPORT_TYPE = "GET_MERCHANT_LISTINGS_ALL_DATA".freeze
7
+ SANDBOX_START_TIME = "2019-12-10T20:11:24.000Z".freeze
8
+ SANDBOX_CANCEL_REPORT_ID = "ID".freeze
9
+ SANDBOX_MARKETPLACE_IDS = %w[
10
+ A1PA6795UKMFR9
11
+ ATVPDKIKX0DER
12
+ ].freeze
13
+ SANDBOX_REPORT_ID = "ID323".freeze
14
+ SANDBOX_REPORT_DOCUMENT_ID = "0356cf79-b8b0-4226-b4b9-0ee058ea5760".freeze
15
+
16
+ GET_REPORTS_PARAMS = %w[
17
+ reportTypes
18
+ processingStatuses
19
+ marketplaceIds
20
+ pageSize
21
+ createdSince
22
+ createdUntil
23
+ nextToken
24
+ ].freeze
25
+
26
+ def get_reports(params = {})
27
+ @local_var_path = "/reports/2021-06-30/reports"
28
+ if sandbox
29
+ params = {
30
+ "reportTypes" => SANDBOX_REPORT_TYPES,
31
+ "processingStatuses" => SANDBOX_PROCESSING_STATUSES
32
+ }
33
+ end
34
+ @query_params = params.slice(*GET_REPORTS_PARAMS)
35
+ @request_type = "GET"
36
+ call_api
37
+ end
10
38
 
11
39
  def create_report(report_type, marketplace_ids, start_time = nil, end_time = nil, report_options = {})
12
40
  report_type = sandbox ? SANDBOX_REPORT_TYPE : report_type
@@ -16,12 +44,33 @@ module MuffinMan
16
44
  @local_var_path = "/reports/2021-06-30/reports"
17
45
  @request_body = {
18
46
  "reportType" => report_type,
19
- "marketplaceIds" => marketplace_ids,
47
+ "marketplaceIds" => marketplace_ids
20
48
  }
21
49
  @request_body["dataStartTime"] = start_time unless start_time.nil?
22
50
  @request_body["dataEndTime"] = end_time unless end_time.nil?
23
51
  @request_body["reportOptions"] = report_options unless report_options.empty?
24
- @request_type = 'POST'
52
+ @request_type = "POST"
53
+ call_api
54
+ end
55
+
56
+ def get_report(report_id)
57
+ report_id = sandbox ? SANDBOX_REPORT_ID : report_id
58
+ @local_var_path = "/reports/2021-06-30/reports/#{report_id}"
59
+ @request_type = "GET"
60
+ call_api
61
+ end
62
+
63
+ def cancel_report(report_id)
64
+ report_id = sandbox ? SANDBOX_CANCEL_REPORT_ID : report_id
65
+ @local_var_path = "/reports/2021-06-30/reports/#{report_id}"
66
+ @request_type = "DELETE"
67
+ call_api
68
+ end
69
+
70
+ def get_report_document(report_document_id)
71
+ report_document_id = sandbox ? SANDBOX_REPORT_DOCUMENT_ID : report_document_id
72
+ @local_var_path = "/reports/2021-06-30/documents/#{report_document_id}"
73
+ @request_type = "GET"
25
74
  call_api
26
75
  end
27
76
  end
@@ -11,9 +11,11 @@ module MuffinMan
11
11
  def create_product_review_and_seller_feedback_solicitation(amazon_order_id, marketplace_ids)
12
12
  @amazon_order_id = sandbox ? SANDBOX_AMAZON_ORDER_ID : amazon_order_id
13
13
  @marketplace_ids = sandbox ? SANDBOX_MARKETPLACE_IDS : marketplace_ids
14
- @local_var_path = '/solicitations/v1/orders/{amazonOrderId}/solicitations/productReviewAndSellerFeedback'.sub('{' + 'amazonOrderId' + '}', @amazon_order_id)
14
+ @local_var_path = "/solicitations/v1/orders/{amazonOrderId}/solicitations/productReviewAndSellerFeedback".sub(
15
+ "{" + "amazonOrderId" + "}", @amazon_order_id
16
+ )
15
17
  @query_params = { "marketplaceIds" => @marketplace_ids }
16
- @request_type = 'POST'
18
+ @request_type = "POST"
17
19
  call_api
18
20
  end
19
21
  end
@@ -1,20 +1,21 @@
1
- require 'aws-sigv4'
2
- require 'uri'
3
- require 'aws-sdk-core'
4
- require 'typhoeus'
5
- require 'securerandom'
1
+ require "aws-sigv4"
2
+ require "uri"
3
+ require "aws-sdk-core"
4
+ require "typhoeus"
5
+ require "securerandom"
6
6
 
7
7
  module MuffinMan
8
8
  class SpApiClient
9
9
  attr_reader :refresh_token, :client_id, :client_secret, :aws_access_key_id,
10
- :aws_secret_access_key, :sts_iam_role_arn, :sandbox, :config, :region, :request_type,
11
- :local_var_path, :query_params, :request_body
12
- ACCESS_TOKEN_URL = 'https://api.amazon.com/auth/o2/token'.freeze
13
- SERVICE_NAME = 'execute-api'.freeze
10
+ :aws_secret_access_key, :sts_iam_role_arn, :sandbox, :config, :region, :request_type,
11
+ :local_var_path, :query_params, :request_body, :scope
12
+
13
+ ACCESS_TOKEN_URL = "https://api.amazon.com/auth/o2/token".freeze
14
+ SERVICE_NAME = "execute-api".freeze
14
15
  AWS_REGION_MAP = {
15
- 'na' => 'us-east-1',
16
- 'eu' => 'eu-west-1',
17
- 'fe' => 'us-west-2'
16
+ "na" => "us-east-1",
17
+ "eu" => "eu-west-1",
18
+ "fe" => "us-west-2"
18
19
  }.freeze
19
20
 
20
21
  def initialize(credentials, sandbox = false)
@@ -24,9 +25,10 @@ module MuffinMan
24
25
  @aws_access_key_id = credentials[:aws_access_key_id]
25
26
  @aws_secret_access_key = credentials[:aws_secret_access_key]
26
27
  @sts_iam_role_arn = credentials[:sts_iam_role_arn]
27
- @region = credentials[:region] || 'na'
28
+ @region = credentials[:region] || "na"
29
+ @scope = credentials[:scope]
28
30
  @sandbox = sandbox
29
- Typhoeus::Config.user_agent = ''
31
+ Typhoeus::Config.user_agent = ""
30
32
  @config = MuffinMan.configuration
31
33
  end
32
34
 
@@ -38,9 +40,7 @@ module MuffinMan
38
40
 
39
41
  def request_opts
40
42
  opts = { headers: headers }
41
- if request_body
42
- opts[:body] = request_body.to_json
43
- end
43
+ opts[:body] = request_body.to_json if request_body
44
44
  opts
45
45
  end
46
46
 
@@ -63,20 +63,21 @@ module MuffinMan
63
63
  end
64
64
 
65
65
  def retrieve_lwa_access_token
66
- return request_lwa_access_token['access_token'] unless defined?(config.get_access_token)
66
+ return request_lwa_access_token["access_token"] unless defined?(config.get_access_token)
67
+
67
68
  stored_token = config.get_access_token.call(client_id)
68
69
  if stored_token.nil?
69
70
  new_token = request_lwa_access_token
70
71
  config.save_access_token.call(client_id, new_token) if defined?(config.save_access_token)
71
- return new_token['access_token']
72
+ new_token["access_token"]
72
73
  else
73
- return stored_token
74
+ stored_token
74
75
  end
75
76
  end
76
77
 
77
78
  def request_lwa_access_token
78
79
  body = {
79
- grant_type: 'refresh_token',
80
+ grant_type: "refresh_token",
80
81
  refresh_token: refresh_token,
81
82
  client_id: client_id,
82
83
  client_secret: client_secret
@@ -85,7 +86,29 @@ module MuffinMan
85
86
  ACCESS_TOKEN_URL,
86
87
  body: URI.encode_www_form(body),
87
88
  headers: {
88
- 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8'
89
+ "Content-Type" => "application/x-www-form-urlencoded;charset=UTF-8"
90
+ }
91
+ )
92
+ JSON.parse(response.body)
93
+ end
94
+
95
+ def retrieve_grantless_access_token
96
+ # No storage of this type for now
97
+ request_grantless_access_token["access_token"]
98
+ end
99
+
100
+ def request_grantless_access_token
101
+ body = {
102
+ grant_type: "client_credentials",
103
+ scope: scope,
104
+ client_id: client_id,
105
+ client_secret: client_secret
106
+ }
107
+ response = Typhoeus.post(
108
+ ACCESS_TOKEN_URL,
109
+ body: URI.encode_www_form(body),
110
+ headers: {
111
+ "Content-Type" => "application/x-www-form-urlencoded;charset=UTF-8"
89
112
  }
90
113
  )
91
114
  JSON.parse(response.body)
@@ -117,17 +140,22 @@ module MuffinMan
117
140
  end
118
141
 
119
142
  def headers
143
+ access_token = scope ? retrieve_grantless_access_token : retrieve_lwa_access_token
120
144
  headers = {
121
- 'x-amz-access-token' => retrieve_lwa_access_token,
122
- 'user-agent' => "MuffinMan/#{VERSION} (Language=Ruby)",
123
- 'content-type' => "application/json"
145
+ "x-amz-access-token" => access_token,
146
+ "user-agent" => "MuffinMan/#{VERSION} (Language=Ruby)",
147
+ "content-type" => "application/json"
124
148
  }
125
149
  signed_request.headers.merge(headers)
126
150
  end
127
151
 
128
152
  def derive_aws_region
129
153
  @aws_region ||= AWS_REGION_MAP[region]
130
- raise MuffinMan::Error.new("#{region} is not supported or does not exist. Region must be one of the following: #{AWS_REGION_MAP.keys.join(', ')}") unless @aws_region
154
+ unless @aws_region
155
+ raise MuffinMan::Error,
156
+ "#{region} is not supported or does not exist. Region must be one of the following: #{AWS_REGION_MAP.keys.join(", ")}"
157
+ end
158
+
131
159
  @aws_region
132
160
  end
133
161
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MuffinMan
4
- VERSION = "1.0.2"
4
+ VERSION = "1.3.0"
5
5
  end
data/lib/muffin_man.rb CHANGED
@@ -1,8 +1,11 @@
1
1
  require "muffin_man/version"
2
2
  require "muffin_man/sp_api_client"
3
+ require "muffin_man/lwa/auth_helper"
3
4
  require "muffin_man/solicitations/v1"
4
5
  require "muffin_man/reports/v20210630"
5
6
  require "muffin_man/catalog_items/v20201201"
7
+ require "muffin_man/finances/v0"
8
+ require "muffin_man/authorization/v1"
6
9
 
7
10
  module MuffinMan
8
11
  class Error < StandardError; end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: muffin_man
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gavin
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2022-02-03 00:00:00.000000000 Z
13
+ date: 2022-05-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
@@ -123,7 +123,10 @@ files:
123
123
  - bin/console
124
124
  - bin/setup
125
125
  - lib/muffin_man.rb
126
+ - lib/muffin_man/authorization/v1.rb
126
127
  - lib/muffin_man/catalog_items/v20201201.rb
128
+ - lib/muffin_man/finances/v0.rb
129
+ - lib/muffin_man/lwa/auth_helper.rb
127
130
  - lib/muffin_man/reports/v20210630.rb
128
131
  - lib/muffin_man/solicitations/v1.rb
129
132
  - lib/muffin_man/sp_api_client.rb