- 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
323 lines
8.0 KiB
Markdown
323 lines
8.0 KiB
Markdown
# Shipping Integration Guide
|
|
|
|
This document consolidates shipping integration patterns and addon specifications for WooNooW.
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
WooNooW supports flexible shipping integration through:
|
|
1. **Standard WooCommerce Shipping Methods** - Works with any WC shipping plugin
|
|
2. **Custom Shipping Addons** - Build shipping addons using WooNooW addon bridge
|
|
3. **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:
|
|
|
|
1. **Removes Standard Fields:**
|
|
```php
|
|
// 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;
|
|
}
|
|
```
|
|
|
|
2. **Adds Custom Destination Dropdown:**
|
|
```php
|
|
<select id="cart-destination" name="cart_destination">
|
|
<option>Search and select location...</option>
|
|
</select>
|
|
```
|
|
|
|
3. **Stores in Session:**
|
|
```php
|
|
WC()->session->set('selected_destination_id', $destination_id);
|
|
WC()->session->set('selected_destination_label', $destination_label);
|
|
```
|
|
|
|
4. **Triggers Shipping Calculation:**
|
|
```php
|
|
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:**
|
|
```json
|
|
{
|
|
"origin_area_id": "IDNP6IDNC148IDND1820IDZ16094",
|
|
"destination_area_id": "IDNP9IDNC235IDND3256IDZ41551",
|
|
"couriers": "jne,sicepat,jnt",
|
|
"items": [
|
|
{
|
|
"name": "Product Name",
|
|
"value": 100000,
|
|
"weight": 1000,
|
|
"quantity": 1
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"object": "courier_pricing",
|
|
"pricing": [
|
|
{
|
|
"courier_name": "JNE",
|
|
"courier_service_name": "REG",
|
|
"price": 15000,
|
|
"duration": "2-3 days"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### React Components
|
|
|
|
#### SubdistrictSelector Component
|
|
```tsx
|
|
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
|
|
```tsx
|
|
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
|
|
|
|
```php
|
|
// 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:
|
|
|
|
1. **Create WooCommerce Shipping Method**
|
|
```php
|
|
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,
|
|
]);
|
|
}
|
|
}
|
|
```
|
|
|
|
2. **Register with WooCommerce**
|
|
```php
|
|
add_filter('woocommerce_shipping_methods', function($methods) {
|
|
$methods['custom_shipping'] = 'Custom_Shipping_Method';
|
|
return $methods;
|
|
});
|
|
```
|
|
|
|
3. **Add SPA Integration (Optional)**
|
|
```php
|
|
// 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
|
|
|
|
1. **Use Standard WC Fields** - Whenever possible, use standard WooCommerce address fields
|
|
2. **Cache Rates** - Cache shipping rates to reduce API calls
|
|
3. **Error Handling** - Always provide fallback rates if API fails
|
|
4. **Mobile Friendly** - Ensure shipping selectors work well on mobile
|
|
5. **Admin Support** - Make sure shipping works in admin order form too
|
|
|
|
---
|
|
|
|
## Resources
|
|
|
|
- [WooCommerce Shipping Method Tutorial](https://woocommerce.com/document/shipping-method-api/)
|
|
- [Biteship API Documentation](https://biteship.com/docs)
|
|
- [WooNooW Addon Development Guide](ADDON_DEVELOPMENT_GUIDE.md)
|
|
- [WooNooW Hooks Registry](HOOKS_REGISTRY.md)
|