muffin_man 1.2.0 → 1.4.1
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 +4 -4
- data/.gitignore +3 -0
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +3 -0
- data/README.md +27 -3
- data/lib/muffin_man/authorization/v1.rb +0 -1
- data/lib/muffin_man/finances/v0.rb +14 -9
- data/lib/muffin_man/lwa/auth_helper.rb +27 -0
- data/lib/muffin_man/reports/v20210630.rb +12 -1
- data/lib/muffin_man/solicitations/v1.rb +4 -2
- data/lib/muffin_man/sp_api_client.rb +38 -28
- data/lib/muffin_man/version.rb +1 -1
- data/lib/muffin_man.rb +1 -0
- data/muffin_man.gemspec +1 -0
- metadata +23 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70bef5fd30926ae053d7a8e2cb36b85b5ad763e0c9ef540254a68d14d90e790d
|
4
|
+
data.tar.gz: d7762e45d0663c1f6305dd41eed16fe3eed9265469f11c031a52de1f6dbae4c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4be6ad20196556290c59054fc3216e8723e25c0c02c8bfb8fef4f78207a885c1e97b07027a41c06279fe83fa816b413a24c9155e13d2f2f76b78f24ab558d4c1
|
7
|
+
data.tar.gz: 46fcfc5c8d8007b2c4a552516a65bc8c4cb8fe2a07f6d48c17237a77ae4521dc2f5121bfb329ba21e9ef8a7186355d89b7d88c8657cda8856599982241559a67
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -40,6 +40,7 @@ credentials = {
|
|
40
40
|
aws_secret_access_key: AWS_SECRET_ACCESS_KEY,
|
41
41
|
region: REGION, # This can be one of ['na', 'eu', 'fe'] and defaults to 'na'
|
42
42
|
sts_iam_role_arn: STS_IAM_ROLE_ARN, # Optional
|
43
|
+
access_token_cache_key: SELLING_PARTNER_ID, # Optional if you want access token caching
|
43
44
|
}
|
44
45
|
client = MuffinMan::Solicitations::V1.new(credentials)
|
45
46
|
response = client.create_product_review_and_seller_feedback_solicitation(amazon_order_id, marketplace_ids)
|
@@ -48,6 +49,8 @@ JSON.parse(response.body)
|
|
48
49
|
|
49
50
|
You can optionally use Amazon's sandbox environment by specifying `client = MuffinMan::Solicitations.new(credentials, sandbox = true)`
|
50
51
|
|
52
|
+
### Access Token Caching
|
53
|
+
|
51
54
|
You can save and retrieve the LWA refresh token by defining a lambda in your initializers.
|
52
55
|
|
53
56
|
For example, if you are using Redis as your cache you could define:
|
@@ -55,14 +58,35 @@ For example, if you are using Redis as your cache you could define:
|
|
55
58
|
```ruby
|
56
59
|
@@redis = Redis.new
|
57
60
|
MuffinMan.configure do |config|
|
58
|
-
config.save_access_token = -> (
|
59
|
-
@@redis.set("SP-TOKEN-#{
|
61
|
+
config.save_access_token = -> (access_token_cache_key, token) do
|
62
|
+
@@redis.set("SP-TOKEN-#{access_token_cache_key}", token['access_token'], ex: token['expires_in'])
|
60
63
|
end
|
61
64
|
|
62
|
-
config.get_access_token = -> (
|
65
|
+
config.get_access_token = -> (access_token_cache_key) { @@redis.get("SP-TOKEN-#{access_token_cache_key}") }
|
63
66
|
end
|
64
67
|
```
|
65
68
|
|
69
|
+
### Retrieiving the refresh token
|
70
|
+
|
71
|
+
To retrieve the refresh token from an LWA Website authorization workflow, you can use the LWA helper:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
# Get your auth code first, either through the Website oauth flow or Authorization API
|
75
|
+
credentials = {
|
76
|
+
client_id: CLIENT_ID,
|
77
|
+
client_secret: CLIENT_SECRET,
|
78
|
+
aws_access_key_id: AWS_ACCESS_KEY_ID,
|
79
|
+
aws_secret_access_key: AWS_SECRET_ACCESS_KEY,
|
80
|
+
sts_iam_role_arn: STS_IAM_ROLE_ARN, # Optional
|
81
|
+
scope: 'sellingpartnerapi::migration' # Grantless scope for MWS migration
|
82
|
+
}
|
83
|
+
client = MuffinMan::Authorization::V1.new(credentials)
|
84
|
+
resp = JSON.parse(client.get_authorization_code(seller_id, developer_id, mws_auth_token).body)
|
85
|
+
auth_code = resp['payload']['authorizationCode']
|
86
|
+
# Then query retrieve the refresh token to store
|
87
|
+
refresh_token = MuffinMan::Lwa::AuthHelper.get_refresh_token(CLIENT_ID, CLIENT_SECRET, auth_code)
|
88
|
+
```
|
89
|
+
|
66
90
|
## Contributing
|
67
91
|
|
68
92
|
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).
|
@@ -1,14 +1,19 @@
|
|
1
1
|
module MuffinMan
|
2
2
|
module Finances
|
3
3
|
class V0 < SpApiClient
|
4
|
-
|
5
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)
|
6
5
|
@local_var_path = "/finances/v0/financialEventGroups"
|
7
6
|
@query_params = {}
|
8
|
-
@query_params[
|
9
|
-
|
10
|
-
|
11
|
-
|
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?
|
12
17
|
@request_type = "GET"
|
13
18
|
call_api
|
14
19
|
end
|
@@ -16,10 +21,10 @@ module MuffinMan
|
|
16
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)
|
17
22
|
@local_var_path = "/finances/v0/financialEventGroups/#{event_group_id}/financialEvents"
|
18
23
|
@query_params = {}
|
19
|
-
@query_params[
|
20
|
-
@query_params[
|
21
|
-
@query_params[
|
22
|
-
@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?
|
23
28
|
@request_type = "GET"
|
24
29
|
call_api
|
25
30
|
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
|
@@ -44,7 +44,7 @@ module MuffinMan
|
|
44
44
|
@local_var_path = "/reports/2021-06-30/reports"
|
45
45
|
@request_body = {
|
46
46
|
"reportType" => report_type,
|
47
|
-
"marketplaceIds" => marketplace_ids
|
47
|
+
"marketplaceIds" => marketplace_ids
|
48
48
|
}
|
49
49
|
@request_body["dataStartTime"] = start_time unless start_time.nil?
|
50
50
|
@request_body["dataEndTime"] = end_time unless end_time.nil?
|
@@ -73,6 +73,17 @@ module MuffinMan
|
|
73
73
|
@request_type = "GET"
|
74
74
|
call_api
|
75
75
|
end
|
76
|
+
|
77
|
+
def get_report_document_body(report_document_id)
|
78
|
+
response = get_report_document(report_document_id)
|
79
|
+
parsed_response=JSON.parse(response.body)
|
80
|
+
report=Net::HTTP.get(URI.parse(parsed_response['url']))
|
81
|
+
unless (parsed_response['compressionAlgorithm']).nil?
|
82
|
+
input = StringIO.new(report)
|
83
|
+
report = Zlib::GzipReader.new(input).read
|
84
|
+
end
|
85
|
+
report
|
86
|
+
end
|
76
87
|
end
|
77
88
|
end
|
78
89
|
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 =
|
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 =
|
18
|
+
@request_type = "POST"
|
17
19
|
call_api
|
18
20
|
end
|
19
21
|
end
|
@@ -1,20 +1,22 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
:aws_secret_access_key, :sts_iam_role_arn, :sandbox, :config,
|
11
|
+
:region, :request_type, :local_var_path, :query_params,
|
12
|
+
:request_body, :scope, :access_token_cache_key
|
13
|
+
|
14
|
+
ACCESS_TOKEN_URL = "https://api.amazon.com/auth/o2/token".freeze
|
15
|
+
SERVICE_NAME = "execute-api".freeze
|
14
16
|
AWS_REGION_MAP = {
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
"na" => "us-east-1",
|
18
|
+
"eu" => "eu-west-1",
|
19
|
+
"fe" => "us-west-2"
|
18
20
|
}.freeze
|
19
21
|
|
20
22
|
def initialize(credentials, sandbox = false)
|
@@ -24,10 +26,11 @@ module MuffinMan
|
|
24
26
|
@aws_access_key_id = credentials[:aws_access_key_id]
|
25
27
|
@aws_secret_access_key = credentials[:aws_secret_access_key]
|
26
28
|
@sts_iam_role_arn = credentials[:sts_iam_role_arn]
|
27
|
-
@region = credentials[:region] ||
|
29
|
+
@region = credentials[:region] || "na"
|
28
30
|
@scope = credentials[:scope]
|
31
|
+
@access_token_cache_key = credentials[:access_token_cache_key]
|
29
32
|
@sandbox = sandbox
|
30
|
-
Typhoeus::Config.user_agent =
|
33
|
+
Typhoeus::Config.user_agent = ""
|
31
34
|
@config = MuffinMan.configuration
|
32
35
|
end
|
33
36
|
|
@@ -39,9 +42,7 @@ module MuffinMan
|
|
39
42
|
|
40
43
|
def request_opts
|
41
44
|
opts = { headers: headers }
|
42
|
-
if request_body
|
43
|
-
opts[:body] = request_body.to_json
|
44
|
-
end
|
45
|
+
opts[:body] = request_body.to_json if request_body
|
45
46
|
opts
|
46
47
|
end
|
47
48
|
|
@@ -64,20 +65,25 @@ module MuffinMan
|
|
64
65
|
end
|
65
66
|
|
66
67
|
def retrieve_lwa_access_token
|
67
|
-
return request_lwa_access_token[
|
68
|
-
|
68
|
+
return request_lwa_access_token["access_token"] unless use_cache?
|
69
|
+
|
70
|
+
stored_token = config.get_access_token.call(access_token_cache_key)
|
69
71
|
if stored_token.nil?
|
70
72
|
new_token = request_lwa_access_token
|
71
|
-
config.save_access_token.call(
|
72
|
-
|
73
|
+
config.save_access_token.call(access_token_cache_key, new_token)
|
74
|
+
new_token["access_token"]
|
73
75
|
else
|
74
|
-
|
76
|
+
stored_token
|
75
77
|
end
|
76
78
|
end
|
77
79
|
|
80
|
+
def use_cache?
|
81
|
+
defined?(config.save_access_token) && defined?(config.get_access_token) && access_token_cache_key
|
82
|
+
end
|
83
|
+
|
78
84
|
def request_lwa_access_token
|
79
85
|
body = {
|
80
|
-
grant_type:
|
86
|
+
grant_type: "refresh_token",
|
81
87
|
refresh_token: refresh_token,
|
82
88
|
client_id: client_id,
|
83
89
|
client_secret: client_secret
|
@@ -86,7 +92,7 @@ module MuffinMan
|
|
86
92
|
ACCESS_TOKEN_URL,
|
87
93
|
body: URI.encode_www_form(body),
|
88
94
|
headers: {
|
89
|
-
|
95
|
+
"Content-Type" => "application/x-www-form-urlencoded;charset=UTF-8"
|
90
96
|
}
|
91
97
|
)
|
92
98
|
JSON.parse(response.body)
|
@@ -142,16 +148,20 @@ module MuffinMan
|
|
142
148
|
def headers
|
143
149
|
access_token = scope ? retrieve_grantless_access_token : retrieve_lwa_access_token
|
144
150
|
headers = {
|
145
|
-
|
146
|
-
|
147
|
-
|
151
|
+
"x-amz-access-token" => access_token,
|
152
|
+
"user-agent" => "MuffinMan/#{VERSION} (Language=Ruby)",
|
153
|
+
"content-type" => "application/json"
|
148
154
|
}
|
149
155
|
signed_request.headers.merge(headers)
|
150
156
|
end
|
151
157
|
|
152
158
|
def derive_aws_region
|
153
159
|
@aws_region ||= AWS_REGION_MAP[region]
|
154
|
-
|
160
|
+
unless @aws_region
|
161
|
+
raise MuffinMan::Error,
|
162
|
+
"#{region} is not supported or does not exist. Region must be one of the following: #{AWS_REGION_MAP.keys.join(", ")}"
|
163
|
+
end
|
164
|
+
|
155
165
|
@aws_region
|
156
166
|
end
|
157
167
|
end
|
data/lib/muffin_man/version.rb
CHANGED
data/lib/muffin_man.rb
CHANGED
data/muffin_man.gemspec
CHANGED
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_development_dependency "rspec", "~> 3.2"
|
22
22
|
spec.add_development_dependency 'webmock', '~> 2.1'
|
23
|
+
spec.add_development_dependency 'byebug'
|
23
24
|
spec.add_development_dependency 'mock_redis', '>=0.14'
|
24
25
|
spec.add_runtime_dependency 'typhoeus', '~> 1.0', '>= 1.0.1'
|
25
26
|
spec.add_runtime_dependency 'aws-sigv4', '>= 1.1'
|
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: muffin_man
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gavin
|
8
8
|
- Jason
|
9
9
|
- Nate
|
10
|
-
autorequire:
|
10
|
+
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2022-
|
13
|
+
date: 2022-06-30 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
@@ -40,6 +40,20 @@ dependencies:
|
|
40
40
|
- - "~>"
|
41
41
|
- !ruby/object:Gem::Version
|
42
42
|
version: '2.1'
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: byebug
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
type: :development
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
43
57
|
- !ruby/object:Gem::Dependency
|
44
58
|
name: mock_redis
|
45
59
|
requirement: !ruby/object:Gem::Requirement
|
@@ -102,7 +116,7 @@ dependencies:
|
|
102
116
|
- - ">="
|
103
117
|
- !ruby/object:Gem::Version
|
104
118
|
version: 2.4.4
|
105
|
-
description:
|
119
|
+
description:
|
106
120
|
email:
|
107
121
|
- gavin@pattern.com
|
108
122
|
- jason@pattern.com
|
@@ -115,6 +129,7 @@ files:
|
|
115
129
|
- ".gitignore"
|
116
130
|
- ".rspec"
|
117
131
|
- ".rubocop.yml"
|
132
|
+
- CHANGELOG.md
|
118
133
|
- CODE_OF_CONDUCT.md
|
119
134
|
- Gemfile
|
120
135
|
- LICENSE.txt
|
@@ -126,6 +141,7 @@ files:
|
|
126
141
|
- lib/muffin_man/authorization/v1.rb
|
127
142
|
- lib/muffin_man/catalog_items/v20201201.rb
|
128
143
|
- lib/muffin_man/finances/v0.rb
|
144
|
+
- lib/muffin_man/lwa/auth_helper.rb
|
129
145
|
- lib/muffin_man/reports/v20210630.rb
|
130
146
|
- lib/muffin_man/solicitations/v1.rb
|
131
147
|
- lib/muffin_man/sp_api_client.rb
|
@@ -135,7 +151,7 @@ homepage: https://github.com/patterninc/muffin_man
|
|
135
151
|
licenses:
|
136
152
|
- MIT
|
137
153
|
metadata: {}
|
138
|
-
post_install_message:
|
154
|
+
post_install_message:
|
139
155
|
rdoc_options: []
|
140
156
|
require_paths:
|
141
157
|
- lib
|
@@ -150,8 +166,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
150
166
|
- !ruby/object:Gem::Version
|
151
167
|
version: '0'
|
152
168
|
requirements: []
|
153
|
-
rubygems_version: 3.
|
154
|
-
signing_key:
|
169
|
+
rubygems_version: 3.0.3
|
170
|
+
signing_key:
|
155
171
|
specification_version: 4
|
156
172
|
summary: Amazon Selling Partner API client
|
157
173
|
test_files: []
|