What I am trying to do is show a breakdown of the Woocommerce transaction fee being applied after the order total:
It would something like this:
A visual of where it should go, I have highlighted it and as you see it's just an error at the moment:
The code in my functions .php
// Calculate and save transaction fee after order is created/paid
add_action('woocommerce_order_status_changed', 'add_transaction_fee_to_order_meta', 10, 3);
function add_transaction_fee_to_order_meta($order_id, $old_status, $new_status) {
if ($new_status == 'processing' || $new_status == 'completed') {
$order = wc_get_order($order_id);
if (get_post_meta($order_id, '_transaction_fee', true) == '') {
$order_total = $order->get_total();
$transaction_fee = ($order_total * 0.015) + 0.25;
update_post_meta($order_id, '_transaction_fee', $transaction_fee);
}
}
}
// Display transaction fee in admin order details *after* "Paid" line
add_action('woocommerce_admin_order_totals_after_total', 'display_transaction_fee_in_admin_order_details', 10, 2);
function display_transaction_fee_in_admin_order_details($order_id, $order) {
$transaction_fee = get_post_meta($order_id, '_transaction_fee', true);
if ($transaction_fee) {
if (is_object($order) && is_a($order, 'WC_Order')) {
?> <tr>
<td class="label">Transaction Fee:</td>
<td width="1%"></td>
<td class="total">
<?php echo wc_price($transaction_fee); ?>
</td>
</tr>
<tr>
<td class="label">Total (after fee):</td>
<td width="1%"></td>
<td class="total">
<?php echo wc_price($order->get_total() - $transaction_fee); ?>
</td>
</tr>
<?php
} else {
error_log("WC_Order object not available in display_transaction_fee_in_admin_order_details for order ID: " . $order_id);
}
}
}
Your code is not compatible High-Performance Order Storage (HPOS) and there are multiple mistakes, like:
woocommerce_order_status_changed
has already $order
available via its 4th argument,woocommerce_admin_order_totals_after_total
has only $order_id
as available argument, but not any $order
as 2nd argument…Try the following instead:
// Calculate and save transaction fee after order is created/paid
add_action('woocommerce_order_status_changed', 'add_transaction_fee_to_order_meta', 10, 4 );
function add_transaction_fee_to_order_meta( $order_id, $old_status, $new_status, $order ) {
$targeted_statuses = array('processing', 'completed');
if ( in_array( $new_status, $targeted_statuses) && ! $order->get_meta('_transaction_fee') && $order->get_total() > 0 ) {
$order->update_meta_data('_transaction_fee', ($order->get_total() * 0.015) + 0.25 );
$order->save();
}
}
// Display transaction fee in admin order details *after* "Paid" line
add_action('woocommerce_admin_order_totals_after_total', 'display_transaction_fee_in_admin_order_details' );
function display_transaction_fee_in_admin_order_details( $order_id ) {
$order = wc_get_order($order_id);
$args = array( 'currency' => $order->get_currency() );
if ( $transaction_fee = $order->get_meta('_transaction_fee') ) {
printf('<tr>
<td class="label">%s</td>
<td width="%s"></td>
<td class="total">%s</td>
</tr>', esc_html__('Transaction Fee:'), '1%', wc_price($transaction_fee, $args ) );
printf('<tr>
<td class="label">%s</td>
<td width="%s"></td>
<td class="total">%s</td>
</tr>', esc_html__('Total (after fee):'), '1%', wc_price( $order->get_total() - $transaction_fee, $args ) );
}
}
It should better work without errors, and will be compatible with HPOS.
You may need to target the concerned payment gateway(s) in your first function, as actually your code is executed on all processing or completed orders, no matter what payment method has been used.