- Add ModuleRegistry for managing built-in modules (newsletter, wishlist, affiliate, subscription, licensing) - Add ModulesController REST API for module enable/disable - Create Modules settings page with category grouping and toggle controls - Integrate module checks across admin-spa and customer-spa - Add useModules hook for both SPAs to check module status - Hide newsletter from footer builder when module disabled - Hide wishlist features when module disabled (product cards, account menu, wishlist page) - Protect wishlist API endpoints with module checks - Auto-update navigation tree when modules toggled - Clean up obsolete documentation files - Add comprehensive documentation: - MODULE_SYSTEM_IMPLEMENTATION.md - MODULE_INTEGRATION_SUMMARY.md - ADDON_MODULE_INTEGRATION.md (proposal) - ADDON_MODULE_DESIGN_DECISIONS.md (design doc) - FEATURE_ROADMAP.md - SHIPPING_INTEGRATION.md Module system provides: - Centralized enable/disable for all features - Automatic navigation updates - Frontend/backend integration - Foundation for addon-module unification
8.0 KiB
8.0 KiB
Shipping Integration Guide
This document consolidates shipping integration patterns and addon specifications for WooNooW.
Overview
WooNooW supports flexible shipping integration through:
- Standard WooCommerce Shipping Methods - Works with any WC shipping plugin
- Custom Shipping Addons - Build shipping addons using WooNooW addon bridge
- Indonesian Shipping - Special handling for Indonesian address systems
Indonesian Shipping Challenges
RajaOngkir Integration Issue
Problem: RajaOngkir plugin doesn't use standard WooCommerce address fields.
How RajaOngkir Works:
- Removes Standard Fields:
// class-cekongkir.php
public function customize_checkout_fields($fields) {
unset($fields['billing']['billing_state']);
unset($fields['billing']['billing_city']);
unset($fields['shipping']['shipping_state']);
unset($fields['shipping']['shipping_city']);
return $fields;
}
- Adds Custom Destination Dropdown:
<select id="cart-destination" name="cart_destination">
<option>Search and select location...</option>
</select>
- Stores in Session:
WC()->session->set('selected_destination_id', $destination_id);
WC()->session->set('selected_destination_label', $destination_label);
- Triggers Shipping Calculation:
WC()->cart->calculate_shipping();
WC()->cart->calculate_totals();
Why Standard Implementation Fails:
- WooNooW OrderForm uses standard fields:
city,state,postcode - RajaOngkir ignores these fields
- RajaOngkir only reads from session:
selected_destination_id
Solution:
Use Biteship instead (see below) or create custom RajaOngkir addon that:
- Hooks into WooNooW OrderForm
- Adds Indonesian address selector
- Syncs with RajaOngkir session
Biteship Integration Addon
Plugin Specification
Plugin Name: WooNooW Indonesia Shipping
Description: Indonesian shipping integration using Biteship Rate API
Version: 1.0.0
Requires: WooNooW 1.0.0+, WooCommerce 8.0+
Features
- ✅ Indonesian address fields (Province, City, District, Subdistrict)
- ✅ Real-time shipping rate calculation
- ✅ Multiple courier support (JNE, SiCepat, J&T, AnterAja, etc.)
- ✅ Works in frontend checkout AND admin order form
- ✅ No subscription required (uses free Biteship Rate API)
Implementation Phases
Phase 1: Core Functionality
- WooCommerce Shipping Method integration
- Biteship Rate API integration
- Indonesian address database (Province → Subdistrict)
- Frontend checkout integration
- Admin settings page
Phase 2: SPA Integration
- REST API endpoints for address data
- REST API for rate calculation
- React components (SubdistrictSelector, CourierSelector)
- Hook integration with WooNooW OrderForm
- Admin order form support
Phase 3: Advanced Features
- Rate caching (reduce API calls)
- Custom rate markup
- Free shipping threshold
- Multi-origin support
- Shipping label generation (optional, requires paid Biteship plan)
Plugin Structure
woonoow-indonesia-shipping/
├── woonoow-indonesia-shipping.php
├── includes/
│ ├── class-shipping-method.php
│ ├── class-biteship-api.php
│ ├── class-address-database.php
│ └── class-rest-controller.php
├── admin/
│ ├── class-settings.php
│ └── views/
├── assets/
│ ├── js/
│ │ ├── checkout.js
│ │ └── admin-order.js
│ └── css/
└── data/
└── indonesia-addresses.json
API Integration
Biteship Rate API Endpoint
POST https://api.biteship.com/v1/rates/couriers
Request:
{
"origin_area_id": "IDNP6IDNC148IDND1820IDZ16094",
"destination_area_id": "IDNP9IDNC235IDND3256IDZ41551",
"couriers": "jne,sicepat,jnt",
"items": [
{
"name": "Product Name",
"value": 100000,
"weight": 1000,
"quantity": 1
}
]
}
Response:
{
"success": true,
"object": "courier_pricing",
"pricing": [
{
"courier_name": "JNE",
"courier_service_name": "REG",
"price": 15000,
"duration": "2-3 days"
}
]
}
React Components
SubdistrictSelector Component
interface SubdistrictSelectorProps {
value: {
province_id: string;
city_id: string;
district_id: string;
subdistrict_id: string;
};
onChange: (value: any) => void;
}
export function SubdistrictSelector({ value, onChange }: SubdistrictSelectorProps) {
// Cascading dropdowns: Province → City → District → Subdistrict
// Uses WooNooW API: /woonoow/v1/shipping/indonesia/provinces
}
CourierSelector Component
interface CourierSelectorProps {
origin: string;
destination: string;
items: CartItem[];
onSelect: (courier: ShippingRate) => void;
}
export function CourierSelector({ origin, destination, items, onSelect }: CourierSelectorProps) {
// Fetches rates from Biteship
// Displays courier options with prices
// Uses WooNooW API: /woonoow/v1/shipping/indonesia/rates
}
Hook Integration
// Register shipping addon
add_filter('woonoow/shipping/address_fields', function($fields) {
if (get_option('woonoow_indonesia_shipping_enabled')) {
return [
'province' => [
'type' => 'select',
'label' => 'Province',
'required' => true,
],
'city' => [
'type' => 'select',
'label' => 'City',
'required' => true,
],
'district' => [
'type' => 'select',
'label' => 'District',
'required' => true,
],
'subdistrict' => [
'type' => 'select',
'label' => 'Subdistrict',
'required' => true,
],
];
}
return $fields;
});
// Register React component
add_filter('woonoow/checkout/shipping_selector', function($component) {
if (get_option('woonoow_indonesia_shipping_enabled')) {
return 'IndonesiaShippingSelector';
}
return $component;
});
General Shipping Integration
Standard WooCommerce Shipping
WooNooW automatically supports any WooCommerce shipping plugin that uses standard shipping methods:
- WooCommerce Flat Rate
- WooCommerce Free Shipping
- WooCommerce Local Pickup
- Table Rate Shipping
- Distance Rate Shipping
- Any third-party shipping plugin
Custom Shipping Addons
To create a custom shipping addon:
- Create WooCommerce Shipping Method
class Custom_Shipping_Method extends WC_Shipping_Method {
public function calculate_shipping($package = []) {
// Your shipping calculation logic
$this->add_rate([
'id' => $this->id,
'label' => $this->title,
'cost' => $cost,
]);
}
}
- Register with WooCommerce
add_filter('woocommerce_shipping_methods', function($methods) {
$methods['custom_shipping'] = 'Custom_Shipping_Method';
return $methods;
});
- Add SPA Integration (Optional)
// REST API for frontend
register_rest_route('woonoow/v1', '/shipping/custom/rates', [
'methods' => 'POST',
'callback' => 'get_custom_shipping_rates',
]);
// React component hook
add_filter('woonoow/checkout/shipping_fields', function($fields) {
// Add custom fields if needed
return $fields;
});
Best Practices
- Use Standard WC Fields - Whenever possible, use standard WooCommerce address fields
- Cache Rates - Cache shipping rates to reduce API calls
- Error Handling - Always provide fallback rates if API fails
- Mobile Friendly - Ensure shipping selectors work well on mobile
- Admin Support - Make sure shipping works in admin order form too