Files
WooNooW/RAJAONGKIR_INTEGRATION.md
Dwindi Ramadhana f6b778c7fc fix(rajaongkir): correct API method name and remove premature country check
Root causes fixed:
1. API method: search_destination_api() not search_destination()
2. Field filter: removed country check that failed before user selection
3. Field now always added if store sells to Indonesia

The woocommerce_checkout_fields filter now:
- Checks if Rajaongkir is active
- Checks if Indonesia is in allowed countries
- Always adds field (frontend will show/hide based on country)
2026-01-08 14:38:52 +07:00

7.2 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)

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
    // NOTE: Method is search_destination_api() not search_destination()
    $api = Cekongkir_API::get_instance();
    $results = $api->search_destination_api($search);
    
    if (is_wp_error($results)) {
        error_log('Rajaongkir search error: ' . $results->get_error_message());
        return [];
    }
    
    if (!is_array($results)) {
        error_log('Rajaongkir search returned non-array: ' . print_r($results, true));
        return [];
    }
    
    // Format for WooNooW's SearchableSelect component
    $formatted = [];
    foreach ($results as $r) {
        $formatted[] = [
            'value' => (string) ($r['id'] ?? ''),
            'label' => $r['label'] ?? $r['text'] ?? '',
        ];
    }
    
    // Limit results
    return array_slice($formatted, 0, 50);
}

// ============================================================
// 2. Add destination field to checkout fields
//    Always add for Indonesia zone (no premature country check)
// ============================================================
add_filter('woocommerce_checkout_fields', function($fields) {
    // Check if Rajaongkir is active
    if (!class_exists('Cekongkir_API')) {
        return $fields;
    }
    
    // Check if store sells to Indonesia (check allowed countries)
    $allowed = WC()->countries->get_allowed_countries();
    if (!isset($allowed['ID'])) {
        return $fields;
    }
    
    // Add searchable destination field
    // The frontend will show/hide based on selected country
    $fields['shipping']['shipping_destination_id'] = [
        'type'            => 'searchable_select',
        'label'           => __('Destination (Province, City, Subdistrict)', 'woonoow'),
        'required'        => false, // Not required initially, SPA will manage this
        'priority'        => 85,
        '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,
        // Custom attribute to indicate this is for Indonesia only
        'custom_attributes' => [
            'data-show-for-country' => 'ID',
        ],
    ];
    
    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)) {
        return;
    }
    
    // Set session for Rajaongkir
    WC()->session->set('selected_destination_id', intval($destination_id));
    
    // Also set label if provided
    $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);

Testing

1. Test the API Endpoint

After adding the snippet:

GET /wp-json/woonoow/v1/rajaongkir/destinations?search=bandung

Should return:

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

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. Rajaongkir rates should appear

Troubleshooting

API returns empty?

Check debug.log for errors:

// Added logging in the search function
error_log('Rajaongkir search error: ...');

Common issues:

  • Invalid Rajaongkir API key
  • Rajaongkir plugin not active
  • API quota exceeded

Field not appearing?

  1. Ensure snippet is active
  2. Check if store sells to Indonesia
  3. Check browser console for JS errors

Rajaongkir rates not showing?

  1. Check session is set:
add_action('woonoow/shipping/before_calculate', function($shipping) {
    error_log('Shipping data: ' . print_r($shipping, true));
}, 5);
  1. Check Rajaongkir is enabled in shipping zone

Known Limitations

  1. Field visibility: Currently field always shows for checkout. Future improvement: hide in React when country ≠ ID.

  2. Session timing: Must select destination before calculating shipping.