Backend (CheckoutController): - Enhanced get_fields() API with custom_attributes, search_endpoint, search_param, min_chars, input_class, default - Supports new 'searchable_select' field type for API-backed search Customer SPA: - Created DynamicCheckoutField component for all field types - Checkout fetches fields from /checkout/fields API - Renders custom fields from PHP filters (billing + shipping) - searchable_select type with live API search - Custom field data included in checkout submission This enables: - Checkout Field Editor Pro compatibility - Rajaongkir destination_id via simple code snippet - Any plugin using woocommerce_checkout_fields filter Updated RAJAONGKIR_INTEGRATION.md with code snippet approach.
238 lines
8.0 KiB
Markdown
238 lines
8.0 KiB
Markdown
# Rajaongkir Integration with WooNooW
|
|
|
|
This guide explains how to add Rajaongkir's destination selector to WooNooW checkout using a **simple code snippet** (no bridge plugin required).
|
|
|
|
---
|
|
|
|
## How It Works
|
|
|
|
WooNooW now supports **dynamic checkout fields**:
|
|
|
|
1. You add fields via the standard `woocommerce_checkout_fields` filter
|
|
2. WooNooW's `/checkout/fields` API returns these fields
|
|
3. Customer-spa renders them automatically (including `searchable_select` type)
|
|
4. Field data is included in checkout submission
|
|
|
|
---
|
|
|
|
## Code Snippet (Add to Code Snippets or WPCodebox)
|
|
|
|
```php
|
|
<?php
|
|
/**
|
|
* Rajaongkir Destination Field for WooNooW
|
|
*
|
|
* Add this snippet to Code Snippets plugin or WPCodebox.
|
|
* Works with WooNooW's dynamic checkout field system.
|
|
*/
|
|
|
|
// 1. Add destination_id field to shipping checkout fields
|
|
add_filter('woocommerce_checkout_fields', function($fields) {
|
|
// Only add for Indonesia or when country not yet selected
|
|
$country = '';
|
|
if (function_exists('WC') && WC()->customer) {
|
|
$country = WC()->customer->get_shipping_country();
|
|
}
|
|
|
|
if ($country !== 'ID' && $country !== '') {
|
|
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 for search
|
|
'search_endpoint' => '/woonoow/v1/rajaongkir/destinations',
|
|
'search_param' => 'search',
|
|
'min_chars' => 2,
|
|
];
|
|
|
|
return $fields;
|
|
});
|
|
|
|
// 2. Register REST API endpoint for destination search
|
|
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',
|
|
'sanitize_callback' => 'sanitize_text_field',
|
|
],
|
|
],
|
|
]);
|
|
});
|
|
|
|
function woonoow_rajaongkir_search_destinations($request) {
|
|
$search = $request->get_param('search') ?? '';
|
|
|
|
if (strlen($search) < 2) {
|
|
return [];
|
|
}
|
|
|
|
// Get cached destinations
|
|
$destinations = get_transient('woonoow_rajaongkir_destinations');
|
|
|
|
if (!$destinations) {
|
|
$destinations = woonoow_rajaongkir_build_destinations();
|
|
set_transient('woonoow_rajaongkir_destinations', $destinations, DAY_IN_SECONDS);
|
|
}
|
|
|
|
// Filter by search term
|
|
$results = array_filter($destinations, function($d) use ($search) {
|
|
return stripos($d['label'], $search) !== false;
|
|
});
|
|
|
|
// Return max 50 results
|
|
return array_slice(array_values($results), 0, 50);
|
|
}
|
|
|
|
function woonoow_rajaongkir_build_destinations() {
|
|
$destinations = [];
|
|
|
|
// Try to get from Rajaongkir plugin's database
|
|
global $wpdb;
|
|
$table = $wpdb->prefix . 'cekongkir_subdistrict'; // Adjust table name
|
|
|
|
if ($wpdb->get_var("SHOW TABLES LIKE '$table'") === $table) {
|
|
$rows = $wpdb->get_results("
|
|
SELECT id, province, city, subdistrict
|
|
FROM $table
|
|
ORDER BY province, city, subdistrict
|
|
", ARRAY_A);
|
|
|
|
foreach ($rows as $row) {
|
|
$destinations[] = [
|
|
'value' => $row['id'],
|
|
'label' => $row['province'] . ', ' . $row['city'] . ', ' . $row['subdistrict'],
|
|
];
|
|
}
|
|
}
|
|
|
|
// Fallback: Try options storage
|
|
if (empty($destinations)) {
|
|
$stored = get_option('cekongkir_subdistricts', []);
|
|
foreach ($stored as $id => $data) {
|
|
$destinations[] = [
|
|
'value' => (string) $id,
|
|
'label' => is_array($data) ? ($data['label'] ?? $data['name'] ?? $id) : $data,
|
|
];
|
|
}
|
|
}
|
|
|
|
return $destinations;
|
|
}
|
|
|
|
// 3. Hook into shipping calculation to set Rajaongkir session
|
|
add_action('woonoow/shipping/before_calculate', function($shipping, $items) {
|
|
// Check for destination_id in shipping data
|
|
$destination_id = $shipping['destination_id'] ?? ($shipping['shipping_destination_id'] ?? '');
|
|
|
|
if (empty($destination_id)) {
|
|
WC()->session->__unset('selected_destination_id');
|
|
WC()->session->__unset('selected_destination_label');
|
|
return;
|
|
}
|
|
|
|
// Set Rajaongkir session variables
|
|
WC()->session->set('selected_destination_id', intval($destination_id));
|
|
WC()->session->set('selected_destination_label', sanitize_text_field(
|
|
$shipping['destination_id_label'] ?? $shipping['shipping_destination_id_label'] ?? ''
|
|
));
|
|
}, 10, 2);
|
|
```
|
|
|
|
---
|
|
|
|
## Field Configuration Options
|
|
|
|
WooNooW's `searchable_select` type supports these options:
|
|
|
|
| Option | Description |
|
|
|--------|-------------|
|
|
| `type` | `'searchable_select'` for API-backed search |
|
|
| `search_endpoint` | REST API endpoint for searching |
|
|
| `search_param` | Query param name (default: 'search') |
|
|
| `min_chars` | Minimum characters before searching (default: 2) |
|
|
| `placeholder` | Input placeholder text |
|
|
|
|
---
|
|
|
|
## Testing
|
|
|
|
1. Add the code snippet via Code Snippets plugin
|
|
2. Go to WooNooW checkout with a product in cart
|
|
3. Set country to Indonesia
|
|
4. A "Destination" field should appear
|
|
5. Type at least 2 characters to search
|
|
6. Select a destination from dropdown
|
|
7. Complete checkout - shipping rates should use selected destination
|
|
|
|
---
|
|
|
|
## How WooNooW Processes This
|
|
|
|
```
|
|
┌─────────────────┐ ┌───────────────────┐ ┌─────────────────┐
|
|
│ PHP Filter adds │ ──▶ │ /checkout/fields │ ──▶ │ Customer-spa │
|
|
│ shipping_ │ │ API returns field │ │ renders field │
|
|
│ destination_id │ │ with type/config │ │ (searchable) │
|
|
└─────────────────┘ └───────────────────┘ └─────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────┐ ┌───────────────────┐ ┌─────────────────┐
|
|
│ Rajaongkir uses │ ◀── │ Hook fires with │ ◀── │ User submits │
|
|
│ session data │ │ shipping data │ │ checkout │
|
|
└─────────────────┘ └───────────────────┘ └─────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Compatibility
|
|
|
|
This works with:
|
|
- **Standard WooCommerce filters** - no WooNooW-specific code needed
|
|
- **Checkout Field Editor Pro** - all its fields will render
|
|
- **Custom code snippets** - just use the filter
|
|
- **Other shipping plugins** - same hook pattern works
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Field not appearing?
|
|
```php
|
|
// Debug: Check if field is being added
|
|
add_action('wp_footer', function() {
|
|
$fields = WC()->checkout()->get_checkout_fields();
|
|
error_log('Checkout fields: ' . print_r(array_keys($fields['shipping'] ?? []), true));
|
|
});
|
|
```
|
|
|
|
### Search not working?
|
|
```
|
|
GET /wp-json/woonoow/v1/rajaongkir/destinations?search=jakarta
|
|
```
|
|
|
|
### Session not set?
|
|
```php
|
|
add_action('woonoow/shipping/before_calculate', function($shipping) {
|
|
error_log('Shipping data: ' . print_r($shipping, true));
|
|
}, 5);
|
|
```
|
|
|
|
---
|
|
|
|
## Related Documentation
|
|
|
|
- [SHIPPING_INTEGRATION.md](SHIPPING_INTEGRATION.md) - General shipping patterns
|
|
- [HOOKS_REGISTRY.md](HOOKS_REGISTRY.md) - All WooNooW hooks
|