From 0e561d9e8c5ac41b1bfb057ee5c820ce03215d35 Mon Sep 17 00:00:00 2001 From: Dwindi Ramadhana Date: Thu, 8 Jan 2026 23:04:31 +0700 Subject: [PATCH] fix: checkout issues - hidden fields, coupons, shipping in order totals 1. Hidden fields now properly hidden in SPA - Added billing_postcode and shipping_postcode to isFieldHidden checks - Fields with type='hidden' from PHP now conditionally rendered 2. Coupons now applied to order total - Added coupons array to order submission payload - CartController now calls calculate_totals() before reading discounts - Returns per-coupon discount amounts {code, discount, type} 3. Shipping now applied to order total - Already handled in submit() via find_shipping_rate_for_order - Frontend now sends shipping_method in payload 4. Order details now include shipping/tracking info - checkout/order/{id} API includes shipping_lines, tracking_number, tracking_url - account/orders/{id} API includes same shipping/tracking fields - Tracking info read from multiple plugin meta keys 5. Thank you/OrderDetails page shows shipping method and AWB - Shipping Method section with courier name and cost - AWB tracking for processing/completed orders with Track Shipment button --- RAJAONGKIR_INTEGRATION.md | 8 ++++ customer-spa/src/pages/Checkout/index.tsx | 47 +++++++++++++---------- includes/Api/CheckoutController.php | 32 +++++++++++++++ includes/Frontend/AccountController.php | 31 +++++++++++++++ 4 files changed, 98 insertions(+), 20 deletions(-) diff --git a/RAJAONGKIR_INTEGRATION.md b/RAJAONGKIR_INTEGRATION.md index 047c69f..d48c274 100644 --- a/RAJAONGKIR_INTEGRATION.md +++ b/RAJAONGKIR_INTEGRATION.md @@ -122,6 +122,10 @@ add_filter('woocommerce_checkout_fields', function($fields) { $fields['billing']['billing_city']['type'] = 'hidden'; $fields['billing']['billing_city']['required'] = false; } + if (isset($fields['billing']['billing_postcode'])) { + $fields['billing']['billing_postcode']['type'] = 'hidden'; + $fields['billing']['billing_postcode']['required'] = false; + } // Hide shipping fields if (isset($fields['shipping']['shipping_country'])) { @@ -137,6 +141,10 @@ add_filter('woocommerce_checkout_fields', function($fields) { $fields['shipping']['shipping_city']['type'] = 'hidden'; $fields['shipping']['shipping_city']['required'] = false; } + if (isset($fields['shipping']['shipping_postcode'])) { + $fields['shipping']['shipping_postcode']['type'] = 'hidden'; + $fields['shipping']['shipping_postcode']['required'] = false; + } } // Destination field definition (reused for billing and shipping) diff --git a/customer-spa/src/pages/Checkout/index.tsx b/customer-spa/src/pages/Checkout/index.tsx index ccc741c..2efe0ac 100644 --- a/customer-spa/src/pages/Checkout/index.tsx +++ b/customer-spa/src/pages/Checkout/index.tsx @@ -532,6 +532,7 @@ export default function Checkout() { }, payment_method: paymentMethod, shipping_method: selectedShippingRate || undefined, // Selected shipping rate ID + coupons: appliedCoupons.map(c => c.code), // Send applied coupon codes customer_note: orderNotes, // Include all custom field data for backend processing custom_fields: customFieldData, @@ -771,16 +772,19 @@ export default function Checkout() { )} )} -
- - setBillingData({ ...billingData, postcode: e.target.value })} - className="w-full border rounded-lg px-4 py-2" - /> -
+ {/* Postcode field - hidden if PHP sets type to 'hidden' */} + {!isFieldHidden('billing_postcode') && ( +
+ + setBillingData({ ...billingData, postcode: e.target.value })} + className="w-full border rounded-lg px-4 py-2" + /> +
+ )} {/* Custom billing fields from plugins */} {billingCustomFields.map(field => ( @@ -962,16 +966,19 @@ export default function Checkout() { )} )} -
- - setShippingData({ ...shippingData, postcode: e.target.value })} - className="w-full border rounded-lg px-4 py-2" - /> -
+ {/* Postcode field - hidden if PHP sets type to 'hidden' */} + {!isFieldHidden('shipping_postcode') && ( +
+ + setShippingData({ ...shippingData, postcode: e.target.value })} + className="w-full border rounded-lg px-4 py-2" + /> +
+ )} {/* Custom shipping fields from plugins */} {shippingCustomFields.map(field => ( diff --git a/includes/Api/CheckoutController.php b/includes/Api/CheckoutController.php index 0822920..a582c6d 100644 --- a/includes/Api/CheckoutController.php +++ b/includes/Api/CheckoutController.php @@ -197,6 +197,33 @@ class CheckoutController { 'image' => $product ? wp_get_attachment_image_url($product->get_image_id(), 'thumbnail') : null, ]; } + + // Build shipping lines + $shipping_lines = []; + foreach ($order->get_shipping_methods() as $shipping_item) { + $shipping_lines[] = [ + 'id' => $shipping_item->get_id(), + 'method_title' => $shipping_item->get_method_title(), + 'method_id' => $shipping_item->get_method_id(), + 'total' => wc_price($shipping_item->get_total()), + ]; + } + + // Get tracking info from order meta (various plugins use different keys) + $tracking_number = $order->get_meta('_tracking_number') + ?: $order->get_meta('_wc_shipment_tracking_items') + ?: $order->get_meta('_rajaongkir_awb_number') + ?: ''; + $tracking_url = $order->get_meta('_tracking_url') + ?: $order->get_meta('_rajaongkir_tracking_url') + ?: ''; + + // Check for shipment tracking plugin format (array of tracking items) + if (is_array($tracking_number) && !empty($tracking_number)) { + $first_tracking = reset($tracking_number); + $tracking_number = $first_tracking['tracking_number'] ?? ''; + $tracking_url = $first_tracking['tracking_url'] ?? $tracking_url; + } return [ 'ok' => true, @@ -204,12 +231,17 @@ class CheckoutController { 'number' => $order->get_order_number(), 'status' => $order->get_status(), 'subtotal' => (float) $order->get_subtotal(), + 'discount_total' => (float) $order->get_discount_total(), 'shipping_total' => (float) $order->get_shipping_total(), 'tax_total' => (float) $order->get_total_tax(), 'total' => (float) $order->get_total(), 'currency' => $order->get_currency(), 'currency_symbol' => get_woocommerce_currency_symbol($order->get_currency()), 'payment_method' => $order->get_payment_method_title(), + 'needs_shipping' => count($shipping_lines) > 0 || $order->needs_shipping_address(), + 'shipping_lines' => $shipping_lines, + 'tracking_number' => $tracking_number, + 'tracking_url' => $tracking_url, 'billing' => [ 'first_name' => $order->get_billing_first_name(), 'last_name' => $order->get_billing_last_name(), diff --git a/includes/Frontend/AccountController.php b/includes/Frontend/AccountController.php index 5718e46..15da31b 100644 --- a/includes/Frontend/AccountController.php +++ b/includes/Frontend/AccountController.php @@ -521,6 +521,37 @@ class AccountController { $data['shipping_total'] = html_entity_decode(strip_tags(wc_price($order->get_shipping_total()))); $data['tax_total'] = html_entity_decode(strip_tags(wc_price($order->get_total_tax()))); $data['discount_total'] = html_entity_decode(strip_tags(wc_price($order->get_discount_total()))); + + // Shipping lines with method details + $shipping_lines = []; + foreach ($order->get_shipping_methods() as $shipping_item) { + $shipping_lines[] = [ + 'id' => $shipping_item->get_id(), + 'method_title' => $shipping_item->get_method_title(), + 'method_id' => $shipping_item->get_method_id(), + 'total' => html_entity_decode(strip_tags(wc_price($shipping_item->get_total()))), + ]; + } + $data['shipping_lines'] = $shipping_lines; + + // Tracking info (from various shipping tracking plugins) + $tracking_number = $order->get_meta('_tracking_number') + ?: $order->get_meta('_wc_shipment_tracking_items') + ?: $order->get_meta('_rajaongkir_awb_number') + ?: ''; + $tracking_url = $order->get_meta('_tracking_url') + ?: $order->get_meta('_rajaongkir_tracking_url') + ?: ''; + + // Handle WooCommerce Shipment Tracking plugin format (array) + if (is_array($tracking_number) && !empty($tracking_number)) { + $first_tracking = reset($tracking_number); + $tracking_number = $first_tracking['tracking_number'] ?? ''; + $tracking_url = $first_tracking['tracking_url'] ?? $tracking_url; + } + + $data['tracking_number'] = $tracking_number; + $data['tracking_url'] = $tracking_url; } return $data;