# Rajaongkir Integration with WooNooW This guide explains how to bridge the Rajaongkir shipping plugin with WooNooW's admin order form and checkout flow. --- ## The Challenge Rajaongkir doesn't use standard WooCommerce address fields. Instead of using `city` and `state`, it requires a **destination ID** from its own Indonesian location database. **Standard WooCommerce Flow:** ``` Country → State → City → Postcode ``` **Rajaongkir Flow:** ``` Country (ID) → Destination ID (subdistrict level) ``` --- ## WooNooW Integration Hook WooNooW provides a hook that fires **before** shipping calculation. This allows plugins like Rajaongkir to set session variables or prepare any data they need. ### Hook: `woonoow/shipping/before_calculate` ```php do_action( 'woonoow/shipping/before_calculate', $shipping_data, $items ); ``` **Parameters:** - `$shipping_data` (array) - The shipping address from frontend: - `country` - Country code (e.g., 'ID') - `state` - State code - `city` - City name - `postcode` - Postal code - `address_1` - Street address - `destination_id` - Custom field for Rajaongkir (added via addon) - + Any custom fields added by addons - `$items` (array) - Cart items being shipped --- ## Complete Integration: Searchable Destination Selector This is a complete code solution that adds a searchable Rajaongkir destination selector to WooNooW checkout. ### Plugin File: `woonoow-rajaongkir-bridge.php` Create this as a new plugin or add to your theme's functions.php: ```php session->__unset( 'selected_destination_id' ); WC()->session->__unset( 'selected_destination_label' ); return; } // Set destination from frontend if ( ! empty( $shipping['destination_id'] ) ) { WC()->session->set( 'selected_destination_id', intval( $shipping['destination_id'] ) ); WC()->session->set( 'selected_destination_label', sanitize_text_field( $shipping['destination_label'] ?? '' ) ); } }, 10, 2 ); /** * 2. REST API: Search Rajaongkir destinations */ add_action( 'rest_api_init', function() { register_rest_route( 'woonoow/v1', '/rajaongkir/destinations', [ 'methods' => 'GET', 'callback' => 'woonoow_search_rajaongkir_destinations', 'permission_callback' => '__return_true', 'args' => [ 'search' => [ 'required' => true, 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', ], ], ]); }); function woonoow_search_rajaongkir_destinations( $request ) { $search = $request->get_param( 'search' ); if ( strlen( $search ) < 2 ) { return new WP_REST_Response( [], 200 ); } // Get Rajaongkir destinations from transient/cache $destinations = get_transient( 'cekongkir_all_destinations' ); if ( ! $destinations ) { // Fetch from Rajaongkir API or database $destinations = woonoow_fetch_rajaongkir_destinations(); set_transient( 'cekongkir_all_destinations', $destinations, DAY_IN_SECONDS ); } // Filter by search term $results = array_filter( $destinations, function( $dest ) use ( $search ) { return stripos( $dest['label'], $search ) !== false; }); // Limit to 50 results $results = array_slice( array_values( $results ), 0, 50 ); return new WP_REST_Response( $results, 200 ); } /** * 3. Fetch destinations from Rajaongkir database */ function woonoow_fetch_rajaongkir_destinations() { global $wpdb; $destinations = []; // Try to get from Rajaongkir plugin's stored data $table = $wpdb->prefix . 'cekongkir_destinations'; if ( $wpdb->get_var( "SHOW TABLES LIKE '$table'" ) === $table ) { $rows = $wpdb->get_results( "SELECT * FROM $table", ARRAY_A ); foreach ( $rows as $row ) { $destinations[] = [ 'value' => $row['id'], 'label' => $row['province'] . ', ' . $row['city'] . ', ' . $row['subdistrict'], 'province' => $row['province'], 'city' => $row['city'], 'subdistrict' => $row['subdistrict'], ]; } } // Fallback: Use options storage if ( empty( $destinations ) ) { $stored = get_option( 'cekongkir_destinations', [] ); foreach ( $stored as $id => $label ) { $destinations[] = [ 'value' => $id, 'label' => $label, ]; } } return $destinations; } /** * 4. Enqueue scripts for checkout */ add_action( 'wp_enqueue_scripts', function() { if ( ! is_checkout() && ! is_wc_endpoint_url() ) { return; } wp_enqueue_script( 'woonoow-rajaongkir-bridge', plugin_dir_url( __FILE__ ) . 'rajaongkir-bridge.js', [], '1.0.0', true ); wp_localize_script( 'woonoow-rajaongkir-bridge', 'WNW_RAJAONGKIR', [ 'apiUrl' => rest_url( 'woonoow/v1/rajaongkir/destinations' ), 'nonce' => wp_create_nonce( 'wp_rest' ), ]); }); ``` ### JavaScript: `rajaongkir-bridge.js` This script adds a searchable destination selector to the checkout: ```javascript /** * Rajaongkir Destination Selector for WooNooW * * Adds a searchable dropdown to select Indonesian subdistrict */ (function() { 'use strict'; // Only run on checkout if (!document.querySelector('.woonoow-checkout, .woocommerce-checkout')) { return; } // Wait for DOM document.addEventListener('DOMContentLoaded', function() { initRajaongkirSelector(); }); function initRajaongkirSelector() { // Find the city/state fields in shipping form const countryField = document.querySelector('[name="shipping_country"], [name="billing_country"]'); if (!countryField) return; // Check if Indonesia is selected const checkCountry = () => { const country = countryField.value; if (country === 'ID') { showDestinationSelector(); } else { hideDestinationSelector(); } }; countryField.addEventListener('change', checkCountry); checkCountry(); } function showDestinationSelector() { // Create searchable destination field if not exists if (document.querySelector('#rajaongkir-destination-wrapper')) { document.querySelector('#rajaongkir-destination-wrapper').style.display = 'block'; return; } const wrapper = document.createElement('div'); wrapper.id = 'rajaongkir-destination-wrapper'; wrapper.className = 'form-group md:col-span-2'; wrapper.innerHTML = `
Selected: {label}
)}