Files
WooNooW/SHIPPING_INTEGRATION.md
Dwindi Ramadhana 07020bc0dd feat: Implement centralized module management system
- 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
2025-12-26 19:19:49 +07:00

8.0 KiB

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:
// 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;
}
  1. Adds Custom Destination Dropdown:
<select id="cart-destination" name="cart_destination">
    <option>Search and select location...</option>
</select>
  1. Stores in Session:
WC()->session->set('selected_destination_id', $destination_id);
WC()->session->set('selected_destination_label', $destination_label);
  1. 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:

  1. 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,
        ]);
    }
}
  1. Register with WooCommerce
add_filter('woocommerce_shipping_methods', function($methods) {
    $methods['custom_shipping'] = 'Custom_Shipping_Method';
    return $methods;
});
  1. 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

  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