Skip to content

Shipping System

Checkout Service
Shipping Provider Factory
├── Weight-Based Provider
├── Manual Provider
├── DHL Provider
├── FedEx Provider
└── UPS Provider
Shipping Rates → Client selects → Order finalized
#[async_trait]
pub trait ShippingProvider: Send + Sync {
fn id(&self) -> &str;
fn name(&self) -> &str;
fn is_available(&self) -> bool;
async fn get_rates(&self, from: &Address, to: &Address, package: &Package, options: &RateOptions) -> Result<Vec<ShippingRate>>;
// ...
}

Default provider. Calculates rates based on:

  • Total cart weight (from product weights)
  • Destination country
  • Zone-based rates per 0.5kg

Weight rounds up to nearest 0.5kg.

ZoneRate/0.5kg
US$5 (base $5)
EU$4.50 + VAT
CNFree
HK/TW/MO/SG$2.50
Default$5

Full zone table in Shipping guide.

For EU destinations, VAT is calculated on underdeclared values:

  • Wheels: $10/item → $2 VAT
  • Bushings: $2/item → $0.40 VAT
  • Rate: 20%

Product weights are fetched from the database. Products without weight default to 0.5kg.

let weights = cart_service.get_product_weights(&product_ids).await?;
let total_weight: Decimal = items.iter()
.map(|item| {
let w = weights.get(&item.product_id).copied().unwrap_or(dec!(0.5));
Decimal::from(item.quantity) * w
})
.sum();

The ShippingProviderFactory must be cloned for the rate aggregator. Each provider is re-created in the clone (providers are stateless).