amazon_spapi/client_apis/
product_fees_v0.rs1use crate::client::{ApiEndpoint, ApiMethod, SpapiClient};
2use crate::models::product_fees_v0::{
3 FeesEstimateByIdRequest, FeesEstimateRequest, FeesEstimateResult, GetMyFeesEstimateRequest,
4 GetMyFeesEstimateResponse, IdType, MoneyType, OptionalFulfillmentProgram, PriceToEstimateFees,
5};
6use anyhow::Result;
7
8impl SpapiClient {
9 pub async fn get_my_fees_estimate_for_sku(
11 &self,
12 sku: &str,
13 request: GetMyFeesEstimateRequest,
14 ) -> Result<GetMyFeesEstimateResponse> {
15 let endpoint = ApiEndpoint {
16 version: "product_fees_v0",
17 path: "/products/fees/v0/listings/{sku}/feesEstimate",
18 path_params: Some(vec![("sku", sku.to_string())]),
19 method: ApiMethod::Post,
20 rate: 1.0,
21 burst: 2,
22 };
23 let body = serde_json::to_string(&request)?;
24
25 let res = self.request(&endpoint, None, None, Some(&body)).await?;
26 Self::from_json(&res)
27 }
28
29 pub async fn get_my_fees_estimate_for_asin(
31 &self,
32 asin: &str,
33 request: GetMyFeesEstimateRequest,
34 ) -> Result<GetMyFeesEstimateResponse> {
35 let endpoint = ApiEndpoint {
36 version: "product_fees_v0",
37 path: "/products/fees/v0/items/{asin}/feesEstimate",
38 path_params: Some(vec![("asin", asin.to_string())]),
39 method: ApiMethod::Post,
40 rate: 1.0,
41 burst: 2,
42 };
43 let body = serde_json::to_string(&request)?;
44 let res = self.request(&endpoint, None, None, Some(&body)).await?;
45 Self::from_json(&res)
46 }
47
48 pub async fn get_my_fees_estimates(
50 &self,
51 requests: Vec<FeesEstimateByIdRequest>,
52 ) -> Result<Vec<FeesEstimateResult>> {
53 let endpoint = ApiEndpoint {
54 version: "product_fees_v0",
55 path: "/products/fees/v0/feesEstimate",
56 path_params: None,
57 method: ApiMethod::Post,
58 rate: 0.5,
59 burst: 1,
60 };
61
62 let body = serde_json::to_string(&requests)?;
64
65 let res = self.request(&endpoint, None, None, Some(&body)).await?;
66 Self::from_json(&res)
67 }
68
69 pub async fn get_fee_for_asin(
71 &self,
72 asin: &str,
73 price: f64,
74 is_amazon_fulfilled: bool,
75 ) -> Result<f64> {
76 let request = GetMyFeesEstimateRequest {
77 fees_estimate_request: Some(Box::new(FeesEstimateRequest {
78 marketplace_id: self.get_marketplace_id().to_string(),
79 is_amazon_fulfilled: Some(is_amazon_fulfilled),
80 price_to_estimate_fees: Box::new(PriceToEstimateFees {
81 listing_price: Box::new(MoneyType {
82 currency_code: Some("USD".to_string()),
83 amount: Some(price),
84 }),
85 shipping: None,
86 points: None,
87 }),
88 identifier: asin.to_string(),
89 optional_fulfillment_program: Some(OptionalFulfillmentProgram::FbaCore),
90 })),
91 };
92
93 let response = self.get_my_fees_estimate_for_asin(asin, request).await?;
94
95 if let Some(payload) = response.payload {
96 if let Some(result) = payload.fees_estimate_result {
97 if result.status == Some("Success".to_string()) {
98 if let Some(estimate) = result.fees_estimate {
99 if let Some(total_fees) = estimate.total_fees_estimate {
100 return Ok(total_fees.amount.unwrap_or(0.0));
101 }
102 }
103 }
104 }
105 }
106
107 Err(anyhow::anyhow!(
108 "Failed to get fee estimate for ASIN: {}",
109 asin
110 ))
111 }
112
113 pub async fn get_fees_for_asins(
115 &self,
116 asins_with_prices: Vec<(String, f64)>,
117 is_amazon_fulfilled: bool,
118 ) -> Result<Vec<(String, f64)>> {
119 let requests: Vec<FeesEstimateByIdRequest> = asins_with_prices
120 .iter()
121 .map(|(asin, price)| FeesEstimateByIdRequest {
122 fees_estimate_request: Some(Box::new(FeesEstimateRequest {
123 marketplace_id: self.get_marketplace_id().to_string(),
124 is_amazon_fulfilled: Some(is_amazon_fulfilled),
125 price_to_estimate_fees: Box::new(PriceToEstimateFees {
126 listing_price: Box::new(MoneyType {
127 currency_code: Some("USD".to_string()),
128 amount: Some(*price),
129 }),
130 shipping: None,
131 points: None,
132 }),
133 identifier: asin.clone(),
134 optional_fulfillment_program: None,
135 })),
136 id_type: IdType::Asin,
137 id_value: asin.clone(),
138 })
139 .collect();
140
141 let results = self.get_my_fees_estimates(requests).await?;
142
143 let mut fees: Vec<(String, f64)> = Vec::new();
144 for result in results {
145 if let Some(identifier) = result.fees_estimate_identifier {
146 let asin = identifier.id_value.unwrap_or_default();
147 let fee = if result.status == Some("Success".to_string()) {
148 if let Some(estimate) = result.fees_estimate {
149 if let Some(total_fees) = estimate.total_fees_estimate {
150 total_fees.amount.unwrap_or(0.0)
151 } else {
152 0.0
153 }
154 } else {
155 0.0
156 }
157 } else {
158 0.0
159 };
160 fees.push((asin, fee));
161 }
162 }
163
164 Ok(fees)
165 }
166
167 pub async fn get_fee_for_sku(
169 &self,
170 sku: &str,
171 price: f64,
172 is_amazon_fulfilled: bool,
173 ) -> Result<f64> {
174 let request = GetMyFeesEstimateRequest {
175 fees_estimate_request: Some(Box::new(FeesEstimateRequest {
176 marketplace_id: self.get_marketplace_id().to_string(),
177 is_amazon_fulfilled: Some(is_amazon_fulfilled),
178 price_to_estimate_fees: Box::new(PriceToEstimateFees {
179 listing_price: Box::new(MoneyType {
180 currency_code: Some("USD".to_string()),
181 amount: Some(price),
182 }),
183 shipping: None,
184 points: None,
185 }),
186 identifier: sku.to_string(),
187 optional_fulfillment_program: Some(OptionalFulfillmentProgram::FbaCore),
188 })),
189 };
190
191 let response = self.get_my_fees_estimate_for_sku(sku, request).await?;
192
193 if let Some(payload) = response.payload {
194 if let Some(result) = payload.fees_estimate_result {
195 if result.status == Some("Success".to_string()) {
196 if let Some(estimate) = result.fees_estimate {
197 if let Some(total_fees) = estimate.total_fees_estimate {
198 return Ok(total_fees.amount.unwrap_or(0.0));
199 }
200 }
201 }
202 }
203 }
204
205 Err(anyhow::anyhow!(
206 "Failed to get fee estimate for SKU: {}",
207 sku
208 ))
209 }
210
211 pub async fn get_fees_for_skus(
213 &self,
214 skus_with_prices: Vec<(String, f64)>,
215 is_amazon_fulfilled: bool,
216 ) -> Result<Vec<(String, f64)>> {
217 let requests: Vec<FeesEstimateByIdRequest> = skus_with_prices
218 .iter()
219 .map(|(sku, price)| FeesEstimateByIdRequest {
220 fees_estimate_request: Some(Box::new(FeesEstimateRequest {
221 marketplace_id: self.get_marketplace_id().to_string(),
222 is_amazon_fulfilled: Some(is_amazon_fulfilled),
223 price_to_estimate_fees: Box::new(PriceToEstimateFees {
224 listing_price: Box::new(MoneyType {
225 currency_code: Some("USD".to_string()),
226 amount: Some(*price),
227 }),
228 shipping: None,
229 points: None,
230 }),
231 identifier: sku.clone(),
232 optional_fulfillment_program: None,
233 })),
234 id_type: IdType::SellerSku,
235 id_value: sku.clone(),
236 })
237 .collect();
238 let results = self.get_my_fees_estimates(requests).await?;
239 let mut fees: Vec<(String, f64)> = Vec::new();
240 for result in results {
241 if let Some(identifier) = result.fees_estimate_identifier {
242 let sku = identifier.id_value.unwrap_or_default();
243 let fee = if result.status == Some("Success".to_string()) {
244 if let Some(estimate) = result.fees_estimate {
245 if let Some(total_fees) = estimate.total_fees_estimate {
246 total_fees.amount.unwrap_or(0.0)
247 } else {
248 0.0
249 }
250 } else {
251 0.0
252 }
253 } else {
254 0.0
255 };
256 fees.push((sku, fee));
257 }
258 }
259 Ok(fees)
260 }
261}