
All deposit / split / partial payment plugins generate an additional order for paying the balance. Today, we change that.
Hosted by Rodolfo Melogli
Masterclass overview
It may happen you need to enable deposit payments, partial payments, multiple payment methods per order (e.g. half PayPal, half Bank), installments, split an order between more customers, or whatever requires the customer to pay a percentage of the order total and then come back to pay the difference, possibly with a different payment method.
Most, maybe all, plugins out there, complete the current order upon partial payment and create another order for the balance (a “sub-order” i.e. an order linked to the one that was partially paid), so that the customer can complete that one at a given date.
This is because WooCommerce requires a 1:1 relationship between orders and payments, and does not allow you to use multiple “transactions” for the same order.
Speaking of which, welcome to the world of “transactions“. By using this custom post type, we can save each payment on its own (partial, deposit, partial refund, installment), and then associate multiple transactions to a single order, so that the order status and total are dynamically set based on the outstanding balance.
A customer can then pay for the same orders multiple times, and each time the order amount will be defined by the total sum of its associated transactions.
In this class, we will take a look at some PHP code and demo it live, so that you can get the full picture of this – really! – revolutionary WooCommerce customization.
This is an amazing opportunity to see how a simple yet effective functionality can be coded, so that you can learn a new thing or two for your WooCommerce website or your WooCommerce clients. It’s also a great opportunity to hang out with like-minded professionals during the live class.
Recording & Materials
Video recording
If you are a member, please log in.
Otherwise, here is why you should join the Club.
Code used during the class
add_action( 'init', function() {
$supports_array = array( 'title' );
$args = array(
'labels' => array(
'name' => 'Payments',
'singular_name' => 'Payments'
),
'capability_type' => 'shop_order',
'public' => false,
'supports' => $supports_array,
'rewrite' => false,
'show_ui' => true,
'show_in_menu' => current_user_can( 'edit_others_shop_orders' ) ? 'woocommerce' : false,
'menu_position' => 3,
);
register_post_type( 'payment', $args );
});
add_action( 'woocommerce_order_after_calculate_totals', function( $and_taxes, $order ) {
$payments = get_posts( [ 'post_type' => 'payment', 'post_status' => 'publish', 'numberposts' => -1, 'title' => $order->get_id(), 'fields' => 'ids' ] );
if ( $payments ) {
$total = $order->get_total();
$paid = 0.00;
foreach ( $payments as $payment_id ) {
$amount = get_field( "amount", $payment_id );
$paid += $amount;
}
$new_total = $total - $paid;
$order->set_total( $new_total );
if ( $new_total > 0 ) $order->set_status( 'pending' );
$order->save();
}
}, 9999, 2 );
add_action( 'acf/save_post', function( $post_id ) {
if ( get_post_type( $post_id ) !== 'payment' && get_post_status( $post_id ) !== 'publish' ) return;
$order = wc_get_order( get_the_title( $post_id ) );
if ( ! $order ) return;
$order->calculate_totals();
});
add_action( 'woocommerce_thankyou', function( $order_id ) {
$order = wc_get_order( $order_id );
if ( $order->has_status( 'failed' ) ) return;
$my_post = array(
'post_title' => $order_id,
'post_status' => 'publish',
'post_type' => 'payment',
);
$new_post_id = wp_insert_post( $my_post );
update_field( 'amount', $order->get_total(), $new_post_id );
$order->calculate_totals();
});
add_action( 'woocommerce_review_order_before_payment', function() {
$chosen = WC()->session->get( 'deposit_chosen' );
$chosen = empty( $chosen ) ? WC()->checkout->get_value( 'deposit' ) : $chosen;
$chosen = empty( $chosen ) ? '100' : $chosen;
$args = array(
'type' => 'radio',
'class' => array( 'form-row-wide', 'update_totals_on_change' ),
'options' => array(
'100' => 'Pay 100%',
'30' => 'Pay 30% Deposit',
),
'default' => $chosen,
);
echo '<p><b>Payment Option</b></p>';
woocommerce_form_field( 'deposit', $args, $chosen );
}, 1 );
add_action( 'woocommerce_checkout_update_order_review', function( $posted_data ) {
parse_str( $posted_data, $output );
if ( isset( $output['deposit'] ) ) {
WC()->session->set( 'deposit_chosen', $output['deposit'] );
}
});
add_filter( 'woocommerce_calculated_total', function( $total, $cart ) {
if ( ! WC()->session->get( 'deposit_chosen' ) || WC()->session->get( 'deposit_chosen' ) == '100' ) return $total;
return $total * 0.3;
}, 9999, 2 );
add_action( 'woocommerce_admin_order_totals_after_total', function ( $order_id ) {
echo '<tr><td class="label">Payments:</td><td width="1%"></td><td class="total"><ul style="margin:0">';
$payments = get_posts( [ 'post_type' => 'payment', 'post_status' => 'publish', 'numberposts' => -1, 'title' => $order_id, 'fields' => 'ids' ] );
if ( $payments ) {
foreach ( $payments as $payment_id ) {
$amount = get_field( "amount", $payment_id );
echo '<li style="margin:0"><a href="' . get_edit_post_link( $payment_id ) . '">' . wc_price( $amount ) . '</a> (' . get_the_time( 'd-m-y', $payment_id ) . ')</li>';
}
}
echo '</ul></td></tr>';
});
What you’ll learn
Requirements
Upcoming masterclasses
Classic vs Block: Add, Remove & Edit WooCommerce Checkout Fields
Let’s dive into the ins and outs of customizing WooCommerce checkout fields,…
Available recordings
Supercharge WooCommerce With Custom Product Options
Custom product options (“add-ons”) in WooCommerce can do much more than just add text boxes or checkboxes to the product…
Send These 7 WooCommerce Emails & Watch Sales Grow
Think email marketing is too complicated? Think again… If you’re only sending WooCommerce order emails, you’re leaving money on the…
Spotting WooCommerce Conversion Rate Killers: A Live Audit
In this class, I’ll be auditing several live WooCommerce stores to identify and analyze conversion rate optimization (CRO) issues. Whether…
How to Sync WooCommerce & Google Sheets Without Plugins!
Want to connect WooCommerce with Google Sheets without relying on plugins, Zapier, Make, or third-party connectors? In this class, you’ll…
Preventing WooCommerce Checkout Carding Attacks
Carding attacks can wreak havoc on your WooCommerce store, leading to fraudulent transactions, chargebacks, spam orders, and financial loss. In…
Generate WooCommerce Test Data: Products, Orders, Users
To properly test or develop a WooCommerce site, you need a large dataset of fake products, orders, customers, and taxonomies….
Live Migrating a WooCommerce Site to HPOS
Migrating a WooCommerce site to HPOS can be complex, especially with 30,000+ orders. In this case, we’ll use the terminal…
How to Spin Up WooCommerce Test Websites For Free
Testing WooCommerce snippets, plugins, themes shouldn’t be a hassle. Let’s discover free tools to spin up test websites in minutes—no…
Log Events & Debug Custom Code with WooCommerce Logger
WooCommerce provides a simple way to log your custom events and debug your custom code and plugins. By using this…
Optimize WooCommerce Performance with WordPress Transients
Discover how WordPress transients can boost WooCommerce speed! We’ll explain what transients are, their pros and cons, and when and…
Unlocking the Power of WooCommerce Featured Products
Many developers and store owners find themselves unsure about how to effectively use featured products. Let’s change that – and…
Buying a WooCommerce Store: All You Need to Know
A guide to valuation, negotiation, and acquisition strategies – along with post-acquisition tips for optimizing and growing an existing WooCommerce…
1-Hour WooCommerce Challenge: Let’s Recreate the Nike Product Page
Join me for a live coding challenge, where I’ll customize the WooCommerce Single Product page to resemble the Nike website…
Live Coding a WooCommerce Mini-Plugin
Join me for a live coding session, while I try to develop a custom, commercial WooCommerce plugin in less than…
WooCommerce AMA with Rodolfo Melogli
Join me for an ‘Ask Me Anything About WooCommerce’ session – covering customization, development, plugins, analytics, marketing, forking, and more!…
Maximize Your WooCommerce Potential: Understanding User Behavior with Clarity
Learn how to use the free Microsoft Clarity plugin to record and analyze user behavior on your WooCommerce site, so…
Mastering WooCommerce Thank You Page Customization: A Plugin-Free Approach
Let’s learn how to personalize the WooCommerce Thank You page with simple code, so that you can enhance the customer…
Conversion-Focused Redesign Of The WooCommerce Single Product Page
Let’s improve the boring WooCommerce Single Product page and encourage MORE users to convert. Hosted by Rodolfo Melogli Masterclass overview…
Allow Multiple Payments In The Same WooCommerce Order
All deposit / split / partial payment plugins generate an additional order for paying the balance. Today, we change that….
Live Coding a Simple WooCommerce Checkout Currency Switcher
I definitely need a EUR/USD switcher in my Woo shop, and I’d love to try implementing it without a plugin….
How to Find and Fix Slow Database Queries in WooCommerce
Learn how to resolve slow database queries in WordPress / WooCommerce websites. Use the right tools to boost performance and…
Live Coding a “Deal of the Week” Functionality For WooCommerce
I’ve always wanted to set up an automatic promotion on a different Woo product each week. Let’s code it together?…
Web Accessibility Basics for WooCommerce
Accessibility in ecommerce is increasingly a legal requirement, but it also helps you expand your audience. Hosted by Bet Hannon…
How to Avoid Timeouts When Running Millions of WooCommerce Tasks
Meet Action Scheduler – a scalable processor of large queues of PHP jobs. Learn how to run bulk actions without…
WooCommerce Reimagined: Powering Up with the AI Advantage
Say goodbye to the same old, boring WooCommerce experience. Let’s dive in and see what AI can do for your…
Live Coding a WooCommerce LMS Plugin
Watch me code a simple WooCommerce plugin for selling and managing online courses. Masterclass overview My business relies on creating…
WooCommerce No-Code Automations Make* Simple
* Not a spelling mistake. Here’s how you can build entire workflows and connect WooCommerce to other apps via Make,…
Better Than Subscriptions: Building a Re-order Page in WooCommerce
Transform WooCommerce re-ordering into a seamless, customer-centric experience that goes beyond the ordinary. Hosted by Patrick Rauland Masterclass overview Join…
How to Contribute to WooCommerce Core
Learn how to contribute to the WooCommerce plugin code by submitting your first pull request (PR). Hosted by Rodolfo Melogli…
Behind the Woo Scenes: How I Run Business Bloomer
Find out how I sell, support and manage the whole business via WooCommerce, some custom code, and a handful of…
– BACKED BY –
Is your WooCommerce store prepared for traffic spikes? Improve speeds up to 200% with our
managed WooCommerce hosting. Enjoy scalable server resources, rock-solid security, and 24/7 support.
That’s awesome. I was on clueless how to accept multiple payments.
Thank you mate
Great!
Great tutorial, Rodolfo!
Thank you!
This was helpful, but felt like it was missing the major piece to tie it all together, which would be to send a order request to a customer with a preset deposit amount. While this accomplished the deposit by first using the checkout page, it doesn’t let shop owners send a pay order request (invoice) to a customer with the down payment request.
I would have loved to see the deposit radio fields added to the order page on possibly the ‘before_woocommerce_pay_form’ hook, or even better allow the site owner to choose the deposit amount to send the order, instead of requiring a end user checkout to trigger this.
Any advice on how to achieve this? Overall great video.
Thank you Bryan!
Good point! My solution only applies to checkout orders and not orders created via admin. However, you can always display the radio buttons (“Pay deposit” / “Pay in full”) on the Order Pay page as well, and that will let the customer choose between a set amount and a 100% payment.
I’m sure there’s also a way to implement the preset deposit amount right from the admin edit order page – this can be custom coded: you enter an amount, click “request payment”, and the Order Pay page asks for the preset deposit instead of the full amount.
The smooth alternative may be a URL parameter! Let’s say you want to force a $5 deposit – simply add “&dep=5” to the Order Pay URL (e.g. example.com/checkout/order-pay/123456/?pay_for_order=true&key=wc_order_xyz&dep=5) and install this snippet:
Let me know!