Files
WooNooW/RAJAONGKIR_INTEGRATION.md
Dwindi Ramadhana 906ad38a36 docs(rajaongkir): update integration guide with correct code snippet
Based on deep analysis of Rajaongkir plugin:
- Destinations searched via RajaOngkir API (no local DB table)
- Uses Cekongkir_API::search_destination() for search
- Session 'selected_destination_id' required for rates
- Added SPA-aware checkout field injection

Code snippet includes:
1. REST endpoint /woonoow/v1/rajaongkir/destinations
2. Checkout field filter with REST context detection
3. Session bridge via woonoow/shipping/before_calculate
2026-01-08 14:17:58 +07:00

9.1 KiB

Rajaongkir Integration with WooNooW SPA

This guide explains how to integrate Rajaongkir's destination selector with WooNooW's customer checkout SPA.


Prerequisites

Before using this integration:

  1. Rajaongkir Plugin Installed & Active
  2. WooCommerce Shipping Zone Configured
    • Go to: WC → Settings → Shipping → Zones
    • Add Rajaongkir method to your Indonesia zone
  3. Valid API Key (Check in Rajaongkir settings)
  4. Couriers Selected (In Rajaongkir settings)

How It Works

┌─────────────────┐   ┌───────────────────┐   ┌──────────────────┐
│ Customer types  │ → │ /rajaongkir/      │ → │ SearchableSelect │
│ "Bandung"       │   │ destinations API  │   │ shows results    │
└─────────────────┘   └───────────────────┘   └──────────────────┘
                                                       │
                                                       ▼
┌─────────────────┐   ┌───────────────────┐   ┌──────────────────┐
│ Rajaongkir uses │ ← │ Hook sets WC      │ ← │ Customer selects │
│ session to get  │   │ session data      │   │ destination      │
│ shipping rates  │   │                   │   │                  │
└─────────────────┘   └───────────────────┘   └──────────────────┘

Code Snippet

Add this to Code Snippets or WPCodebox:

<?php
/**
 * Rajaongkir Bridge for WooNooW SPA Checkout
 * 
 * Enables searchable destination field in WooNooW checkout
 * and bridges data to Rajaongkir plugin.
 */

// ============================================================
// 1. REST API Endpoint: Search destinations via Rajaongkir API
// ============================================================
add_action('rest_api_init', function() {
    register_rest_route('woonoow/v1', '/rajaongkir/destinations', [
        'methods'             => 'GET',
        'callback'            => 'woonoow_rajaongkir_search_destinations',
        'permission_callback' => '__return_true',
        'args'                => [
            'search' => [
                'required' => false,
                'type'     => 'string',
            ],
        ],
    ]);
});

function woonoow_rajaongkir_search_destinations($request) {
    $search = sanitize_text_field($request->get_param('search') ?? '');
    
    if (strlen($search) < 2) {
        return [];
    }
    
    // Check if Rajaongkir plugin is active
    if (!class_exists('Cekongkir_API')) {
        return new WP_Error('rajaongkir_missing', 'Rajaongkir plugin not active', ['status' => 400]);
    }
    
    // Use Rajaongkir's API class for the search
    $api = Cekongkir_API::get_instance();
    $results = $api->search_destination(['keyword' => $search]);
    
    if (is_wp_error($results)) {
        return [];
    }
    
    // Format for WooNooW's SearchableSelect component
    $formatted = [];
    foreach ($results as $r) {
        $formatted[] = [
            'value' => (string) $r['id'],
            'label' => $r['label'], // "Province, City, District"
        ];
    }
    
    // Limit results
    return array_slice($formatted, 0, 50);
}

// ============================================================
// 2. Add destination field to checkout fields (SPA-aware)
// ============================================================
add_filter('woocommerce_checkout_fields', function($fields) {
    // Check if Rajaongkir is active
    if (!class_exists('Cekongkir_API')) {
        return $fields;
    }
    
    // Get country from various sources
    $country = '';
    
    // From WC customer object
    if (WC()->customer) {
        $country = WC()->customer->get_shipping_country();
    }
    
    // From REST API request body (for SPA context)
    if (defined('REST_REQUEST') && REST_REQUEST) {
        $json = file_get_contents('php://input');
        if ($json) {
            $data = json_decode($json, true);
            if (isset($data['shipping']['country'])) {
                $country = $data['shipping']['country'];
            }
        }
    }
    
    // Only add field for Indonesia or when country not yet determined
    if ($country && $country !== 'ID') {
        return $fields;
    }
    
    // Add searchable destination field
    $fields['shipping']['shipping_destination_id'] = [
        'type'            => 'searchable_select',
        'label'           => __('Destination (Province, City, Subdistrict)', 'woonoow'),
        'required'        => true,
        'priority'        => 85, // After country/state, before postcode
        'class'           => ['form-row-wide'],
        'placeholder'     => __('Search destination...', 'woonoow'),
        // WooNooW-specific: API endpoint configuration
        'search_endpoint' => '/woonoow/v1/rajaongkir/destinations',
        'search_param'    => 'search',
        'min_chars'       => 2,
    ];
    
    return $fields;
}, 20); // Priority 20 to run after Rajaongkir's own filter

// ============================================================
// 3. Bridge WooNooW shipping data to Rajaongkir session
// ============================================================
add_action('woonoow/shipping/before_calculate', function($shipping, $items) {
    // Set country in WC customer
    if (!empty($shipping['country'])) {
        WC()->customer->set_shipping_country($shipping['country']);
        WC()->customer->set_billing_country($shipping['country']);
    }
    
    // Only process for Indonesia
    $country = $shipping['country'] ?? WC()->customer->get_shipping_country();
    if ($country !== 'ID') {
        // Clear destination for non-Indonesia
        WC()->session->__unset('selected_destination_id');
        WC()->session->__unset('selected_destination_label');
        return;
    }
    
    // Get destination_id from shipping data (various possible keys)
    $destination_id = $shipping['destination_id'] 
                   ?? $shipping['shipping_destination_id']
                   ?? null;
    
    if (empty($destination_id)) {
        // No destination selected yet
        return;
    }
    
    // Set session for Rajaongkir
    WC()->session->set('selected_destination_id', intval($destination_id));
    
    // Also set label if provided (for display purposes)
    $label = $shipping['destination_label'] 
          ?? $shipping['shipping_destination_id_label']
          ?? '';
    if ($label) {
        WC()->session->set('selected_destination_label', sanitize_text_field($label));
    }
    
    // Clear shipping cache to force recalculation
    WC()->session->set('shipping_for_package_0', false);
    
}, 10, 2);

Field Configuration Options

The searchable_select field type supports:

Option Description
type 'searchable_select' for API-backed search
search_endpoint REST API endpoint path
search_param Query parameter name (default: 'search')
min_chars Minimum characters before search (default: 2)
placeholder Input placeholder text

Testing

1. Test the API Endpoint

curl "https://yoursite.com/wp-json/woonoow/v1/rajaongkir/destinations?search=bandung"

Should return:

[
  {"value": "1234", "label": "Jawa Barat, Bandung, Kota"},
  {"value": "1235", "label": "Jawa Barat, Bandung, Kabupaten"}
]

2. Test Checkout Flow

  1. Add product to cart
  2. Go to SPA checkout: /store/checkout
  3. Set country to Indonesia
  4. "Destination" field should appear
  5. Type 2+ characters to search
  6. Select a destination
  7. Click "Calculate Shipping" or proceed
  8. Rajaongkir rates should appear

Troubleshooting

Destination field not appearing?

Check if:

  • Country is set to Indonesia
  • Rajaongkir plugin is active
  • Snippet has no syntax errors

Debug in PHP:

add_action('woocommerce_checkout_init', function() {
    $fields = WC()->checkout()->get_checkout_fields();
    error_log('Shipping fields: ' . print_r(array_keys($fields['shipping'] ?? []), true));
});

Search returns empty?

// Add to the search endpoint
error_log('Rajaongkir search: ' . $search);
error_log('Results: ' . print_r($results, true));

Rajaongkir rates not appearing?

  1. Check session is set:
add_action('woonoow/shipping/before_calculate', function($shipping) {
    error_log('Destination ID in shipping data: ' . print_r($shipping, true));
    error_log('Session destination: ' . WC()->session->get('selected_destination_id'));
}, 5);
  1. Check Rajaongkir debug:
  • Enable debug in Rajaongkir settings
  • Check debug.log for Rajaongkir messages