docs: Comprehensive shipping addon integration research
Added SHIPPING_ADDON_RESEARCH.md with findings on: ## Key Insights: 1. **Standard vs Indonesian Plugins** - Standard: Simple settings, no custom fields - Indonesian: Complex API, custom checkout fields, subdistrict 2. **How Indonesian Plugins Work** - Add custom checkout fields (subdistrict) - Require origin configuration in wp-admin - Make real-time API calls during checkout - Calculate rates based on origin-destination pairing 3. **Why They're Complex** - 7,000+ subdistricts in Indonesia - Each courier has different rates per subdistrict - Can't pre-calculate (must use API) - Origin + destination required ## WooNooW Strategy: ✅ DO: - Display all methods from WooCommerce API - Show enable/disable toggle - Show basic settings (title, cost, min_amount) - Link to WooCommerce for complex config ❌ DON'T: - Try to manage custom checkout fields - Try to calculate rates - Try to show all plugin settings - Interfere with plugin functionality ## Next Steps: 1. Detect complex shipping plugins 2. Show different UI for complex methods 3. Add "Configure in WooCommerce" button 4. Hide settings form for complex methods Result: Simplified UI for standard methods, full power for complex plugins!
This commit is contained in:
371
SHIPPING_ADDON_RESEARCH.md
Normal file
371
SHIPPING_ADDON_RESEARCH.md
Normal file
@@ -0,0 +1,371 @@
|
||||
# Shipping Addon Integration Research
|
||||
|
||||
## Problem Statement
|
||||
Indonesian shipping plugins (Biteship, Woongkir, etc.) have complex requirements:
|
||||
1. **Origin address** - configured in wp-admin
|
||||
2. **Subdistrict field** - custom checkout field
|
||||
3. **Real-time API calls** - during cart/checkout
|
||||
4. **Custom field injection** - modify checkout form
|
||||
|
||||
**Question:** How can WooNooW SPA accommodate these plugins without breaking their functionality?
|
||||
|
||||
---
|
||||
|
||||
## How WooCommerce Shipping Addons Work
|
||||
|
||||
### Standard WooCommerce Pattern
|
||||
```php
|
||||
class My_Shipping_Method extends WC_Shipping_Method {
|
||||
public function calculate_shipping($package = array()) {
|
||||
// 1. Get settings from $this->get_option()
|
||||
// 2. Calculate rates based on package
|
||||
// 3. Call $this->add_rate($rate)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points:**
|
||||
- ✅ Extends `WC_Shipping_Method`
|
||||
- ✅ Uses WooCommerce hooks: `woocommerce_shipping_init`, `woocommerce_shipping_methods`
|
||||
- ✅ Settings stored in `wp_options` table
|
||||
- ✅ Rates calculated during `calculate_shipping()`
|
||||
|
||||
---
|
||||
|
||||
## Indonesian Shipping Plugins (Biteship, Woongkir, etc.)
|
||||
|
||||
### How They Differ from Standard Plugins
|
||||
|
||||
#### 1. **Custom Checkout Fields**
|
||||
```php
|
||||
// They add custom fields to checkout
|
||||
add_filter('woocommerce_checkout_fields', function($fields) {
|
||||
$fields['billing']['billing_subdistrict'] = array(
|
||||
'type' => 'select',
|
||||
'label' => 'Subdistrict',
|
||||
'required' => true,
|
||||
'options' => get_subdistricts() // API call
|
||||
);
|
||||
return $fields;
|
||||
});
|
||||
```
|
||||
|
||||
#### 2. **Origin Configuration**
|
||||
- Stored in plugin settings (wp-admin)
|
||||
- Used for API calls to calculate distance/cost
|
||||
- Not exposed in standard WooCommerce shipping settings
|
||||
|
||||
#### 3. **Real-time API Calls**
|
||||
```php
|
||||
public function calculate_shipping($package) {
|
||||
// Get origin from plugin settings
|
||||
$origin = get_option('biteship_origin_subdistrict_id');
|
||||
|
||||
// Get destination from checkout field
|
||||
$destination = $package['destination']['subdistrict_id'];
|
||||
|
||||
// Call external API
|
||||
$rates = biteship_api_get_rates($origin, $destination, $weight);
|
||||
|
||||
foreach ($rates as $rate) {
|
||||
$this->add_rate($rate);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. **AJAX Updates**
|
||||
```javascript
|
||||
// Update shipping when subdistrict changes
|
||||
jQuery('#billing_subdistrict').on('change', function() {
|
||||
jQuery('body').trigger('update_checkout');
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Why Indonesian Plugins Are Complex
|
||||
|
||||
### 1. **Geographic Complexity**
|
||||
- Indonesia has **34 provinces**, **514 cities**, **7,000+ subdistricts**
|
||||
- Shipping cost varies by subdistrict (not just city)
|
||||
- Standard WooCommerce only has: Country → State → City → Postcode
|
||||
|
||||
### 2. **Multiple Couriers**
|
||||
- Each courier has different rates per subdistrict
|
||||
- Real-time API calls required (can't pre-calculate)
|
||||
- Some couriers don't serve all subdistricts
|
||||
|
||||
### 3. **Origin-Destination Pairing**
|
||||
- Cost depends on **origin subdistrict** + **destination subdistrict**
|
||||
- Origin must be configured in admin
|
||||
- Destination selected at checkout
|
||||
|
||||
---
|
||||
|
||||
## How WooNooW SPA Should Handle This
|
||||
|
||||
### ✅ **What WooNooW SHOULD Do**
|
||||
|
||||
#### 1. **Display Methods Correctly**
|
||||
```typescript
|
||||
// Our current approach is CORRECT
|
||||
const { data: zones } = useQuery({
|
||||
queryKey: ['shipping-zones'],
|
||||
queryFn: () => api.get('/settings/shipping/zones')
|
||||
});
|
||||
```
|
||||
- ✅ Fetch zones from WooCommerce API
|
||||
- ✅ Display all methods (including Biteship, Woongkir)
|
||||
- ✅ Show enable/disable toggle
|
||||
- ✅ Link to WooCommerce settings for advanced config
|
||||
|
||||
#### 2. **Expose Basic Settings Only**
|
||||
```typescript
|
||||
// Show only common settings
|
||||
- Display Name (title)
|
||||
- Cost (if applicable)
|
||||
- Min Amount (if applicable)
|
||||
```
|
||||
- ✅ Don't try to show ALL settings
|
||||
- ✅ Complex settings → "Edit in WooCommerce" button
|
||||
|
||||
#### 3. **Respect Plugin Behavior**
|
||||
- ✅ Don't interfere with checkout field injection
|
||||
- ✅ Don't modify `calculate_shipping()` logic
|
||||
- ✅ Let plugins handle their own API calls
|
||||
|
||||
---
|
||||
|
||||
### ❌ **What WooNooW SHOULD NOT Do**
|
||||
|
||||
#### 1. **Don't Try to Manage Custom Fields**
|
||||
```typescript
|
||||
// ❌ DON'T DO THIS
|
||||
const subdistrictField = {
|
||||
type: 'select',
|
||||
options: await fetchSubdistricts()
|
||||
};
|
||||
```
|
||||
- ❌ Subdistrict fields are managed by shipping plugins
|
||||
- ❌ They inject fields via WooCommerce hooks
|
||||
- ❌ WooNooW SPA doesn't control checkout page
|
||||
|
||||
#### 2. **Don't Try to Calculate Rates**
|
||||
```typescript
|
||||
// ❌ DON'T DO THIS
|
||||
const rate = await biteshipAPI.getRates(origin, destination);
|
||||
```
|
||||
- ❌ Rate calculation is plugin-specific
|
||||
- ❌ Requires API keys, origin config, etc.
|
||||
- ❌ Should happen during checkout, not in admin
|
||||
|
||||
#### 3. **Don't Try to Show All Settings**
|
||||
```typescript
|
||||
// ❌ DON'T DO THIS
|
||||
<Input label="Origin Subdistrict ID" />
|
||||
<Input label="API Key" />
|
||||
<Input label="Courier Selection" />
|
||||
```
|
||||
- ❌ Too complex for simplified UI
|
||||
- ❌ Each plugin has different settings
|
||||
- ❌ Better to link to WooCommerce settings
|
||||
|
||||
---
|
||||
|
||||
## Comparison: Global vs Indonesian Shipping
|
||||
|
||||
### Global Shipping Plugins (ShipStation, EasyPost, etc.)
|
||||
|
||||
**Characteristics:**
|
||||
- ✅ Standard address fields (Country, State, City, Postcode)
|
||||
- ✅ Pre-calculated rates or simple API calls
|
||||
- ✅ No custom checkout fields needed
|
||||
- ✅ Settings fit in standard WooCommerce UI
|
||||
|
||||
**Example: Flat Rate**
|
||||
```php
|
||||
public function calculate_shipping($package) {
|
||||
$rate = array(
|
||||
'label' => $this->title,
|
||||
'cost' => $this->get_option('cost')
|
||||
);
|
||||
$this->add_rate($rate);
|
||||
}
|
||||
```
|
||||
|
||||
### Indonesian Shipping Plugins (Biteship, Woongkir, etc.)
|
||||
|
||||
**Characteristics:**
|
||||
- ⚠️ Custom address fields (Province, City, District, **Subdistrict**)
|
||||
- ⚠️ Real-time API calls with origin-destination pairing
|
||||
- ⚠️ Custom checkout field injection
|
||||
- ⚠️ Complex settings (API keys, origin config, courier selection)
|
||||
|
||||
**Example: Biteship**
|
||||
```php
|
||||
public function calculate_shipping($package) {
|
||||
$origin_id = get_option('biteship_origin_subdistrict_id');
|
||||
$dest_id = $package['destination']['subdistrict_id'];
|
||||
|
||||
$response = wp_remote_post('https://api.biteship.com/v1/rates', array(
|
||||
'headers' => array('Authorization' => 'Bearer ' . $api_key),
|
||||
'body' => json_encode(array(
|
||||
'origin_area_id' => $origin_id,
|
||||
'destination_area_id' => $dest_id,
|
||||
'couriers' => $this->get_option('couriers'),
|
||||
'items' => $package['contents']
|
||||
))
|
||||
));
|
||||
|
||||
$rates = json_decode($response['body'])->pricing;
|
||||
foreach ($rates as $rate) {
|
||||
$this->add_rate(array(
|
||||
'label' => $rate->courier_name . ' - ' . $rate->courier_service_name,
|
||||
'cost' => $rate->price
|
||||
));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Recommendations for WooNooW SPA
|
||||
|
||||
### ✅ **Current Approach is CORRECT**
|
||||
|
||||
Our simplified UI is perfect for:
|
||||
1. **Standard shipping methods** (Flat Rate, Free Shipping, Local Pickup)
|
||||
2. **Simple third-party plugins** (basic rate calculators)
|
||||
3. **Non-tech users** who just want to enable/disable methods
|
||||
|
||||
### ✅ **For Complex Plugins (Biteship, Woongkir)**
|
||||
|
||||
**Strategy: "View-Only + Link to WooCommerce"**
|
||||
|
||||
```typescript
|
||||
// In the accordion, show:
|
||||
<AccordionItem>
|
||||
<AccordionTrigger>
|
||||
🚚 Biteship - JNE REG [On]
|
||||
Rp 15,000 (calculated at checkout)
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<Alert>
|
||||
This is a complex shipping method with advanced settings.
|
||||
<Button asChild>
|
||||
<a href={wcAdminUrl + '/admin.php?page=biteship-settings'}>
|
||||
Configure in WooCommerce
|
||||
</a>
|
||||
</Button>
|
||||
</Alert>
|
||||
|
||||
{/* Only show basic toggle */}
|
||||
<ToggleField
|
||||
label="Enable/Disable"
|
||||
value={method.enabled}
|
||||
onChange={handleToggle}
|
||||
/>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
```
|
||||
|
||||
### ✅ **Detection Logic**
|
||||
|
||||
```typescript
|
||||
// Detect if method is complex
|
||||
const isComplexMethod = (method: ShippingMethod) => {
|
||||
const complexPlugins = [
|
||||
'biteship',
|
||||
'woongkir',
|
||||
'anteraja',
|
||||
'shipper',
|
||||
// Add more as needed
|
||||
];
|
||||
|
||||
return complexPlugins.some(plugin =>
|
||||
method.id.includes(plugin)
|
||||
);
|
||||
};
|
||||
|
||||
// Render accordingly
|
||||
{isComplexMethod(method) ? (
|
||||
<ComplexMethodView method={method} />
|
||||
) : (
|
||||
<SimpleMethodView method={method} />
|
||||
)}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### ✅ **What to Test in WooNooW SPA**
|
||||
|
||||
1. **Method Display**
|
||||
- ✅ Biteship methods appear in zone list
|
||||
- ✅ Enable/disable toggle works
|
||||
- ✅ Method name displays correctly
|
||||
|
||||
2. **Settings Link**
|
||||
- ✅ "Edit in WooCommerce" button works
|
||||
- ✅ Opens correct settings page
|
||||
|
||||
3. **Don't Break Checkout**
|
||||
- ✅ Subdistrict field still appears
|
||||
- ✅ Rates calculate correctly
|
||||
- ✅ AJAX updates work
|
||||
|
||||
### ❌ **What NOT to Test in WooNooW SPA**
|
||||
|
||||
1. ❌ Rate calculation accuracy
|
||||
2. ❌ API integration
|
||||
3. ❌ Subdistrict field functionality
|
||||
4. ❌ Origin configuration
|
||||
|
||||
**These are the shipping plugin's responsibility!**
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
### **WooNooW SPA's Role:**
|
||||
✅ **Simplified management** for standard shipping methods
|
||||
✅ **View-only + link** for complex plugins
|
||||
✅ **Don't interfere** with plugin functionality
|
||||
|
||||
### **Shipping Plugin's Role:**
|
||||
✅ Handle complex settings (origin, API keys, etc.)
|
||||
✅ Inject custom checkout fields
|
||||
✅ Calculate rates via API
|
||||
✅ Manage courier selection
|
||||
|
||||
### **Result:**
|
||||
✅ Non-tech users can enable/disable methods easily
|
||||
✅ Complex configuration stays in WooCommerce admin
|
||||
✅ No functionality is lost
|
||||
✅ Best of both worlds! 🎯
|
||||
|
||||
---
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Phase 1: Detection (Current)
|
||||
- [x] Display all methods from WooCommerce API
|
||||
- [x] Show enable/disable toggle
|
||||
- [x] Show basic settings (title, cost, min_amount)
|
||||
|
||||
### Phase 2: Complex Method Handling (Next)
|
||||
- [ ] Detect complex shipping plugins
|
||||
- [ ] Show different UI for complex methods
|
||||
- [ ] Add "Configure in WooCommerce" button
|
||||
- [ ] Hide settings form for complex methods
|
||||
|
||||
### Phase 3: Documentation (Final)
|
||||
- [ ] Add help text explaining complex methods
|
||||
- [ ] Link to plugin documentation
|
||||
- [ ] Add troubleshooting guide
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** Nov 9, 2025
|
||||
**Status:** Research Complete ✅
|
||||
Reference in New Issue
Block a user