I have a Woocommerce site running Woocommerce Subscriptions plugin.
The site only has one simple subscription, limited to one per user. I want to allow the user to set their own start time and subscription frequency, based on selections made in a dropdown box added during the checkout process.
I have added the checkout fields correctly, and they are simple select boxes:
<select name="frequency" id="choose_frequency">
<option value="week">Weekly</option>
<option value="2week">Fortnightly</option>
<option value="monthly">Monthly</option>
</select>
<select name="start-date" id="sub_start_date">
<option value="22 Apr 2021">Thursday, 22 April 2021</option>
<option value="29 Apr 2021">Thursday, 29 April 2021</option>
<option value="6 May 2021">Thursday, 6 May 2021</option>
</select>
I need to get the value, convert it to the correct meta, and then update the subscription before it has been created.
I've tried to update the meta using woocommerce_checkout_update_order_meta
:
//Update the order meta with custom fields values
add_action('woocommerce_checkout_update_order_meta', 'customise_checkout_field_update_order_meta');
function customise_checkout_field_update_order_meta($order_id){
$subscriptions_ids = wcs_get_subscriptions_for_order( $order_id );
foreach( $subscriptions_ids as $subscription_id => $subscription_obj ){
update_post_meta($subscription_id, '_schedule_start',date('Y-m-d h:i:s',$_POST['sub_start_date']));
}
}
and also tried wcs_create_subscription
:
// set start subscription date on checkout page
add_action('wcs_create_subscription', 'cc_wcs_create_subscription');
function cc_wcs_create_subscription($subscription){
$order_id = $subscription->order->id;
$subscription_id = $subscription->get_id();
if($subscription_id && $_POST['sub_start_date']){
update_post_meta($subscription_id, '_schedule_start',date('Y-m-d h:i:s',$_POST['sub_start_date']));
}
}
... I've even tried updating the frequency with AJAX:
jQuery(document).on('change','select#choose_frequency',function(){
var cur_val = jQuery(this).val();
jQuery.ajax({
type:'post',
url:woocommerce_params.ajax_url,
data:{'action':'cc_update_product_subscription','productid':1086,'cur_val':cur_val},
success:function(result){
jQuery(document.body).trigger("update_checkout");
}
});
});
// update subscription frequency on checkout page
add_action('wp_ajax_cc_update_product_subscription','cc_update_product_subscription');
add_action('wp_ajax_nopriv_cc_update_product_subscription','cc_update_product_subscription');
function cc_update_product_subscription(){
if($_POST['cur_val'] == 'week'){
update_post_meta($_POST['productid'],'_billing_interval','1');
update_post_meta($_POST['productid'],'_billing_period','week');
}
if($_POST['cur_val'] == '2week'){
update_post_meta($_POST['productid'],'_billing_interval','2');
update_post_meta($_POST['productid'],'_billing_period','week');
}
if($_POST['cur_val'] == 'monthly'){
update_post_meta($_POST['productid'],'_billing_interval','1');
update_post_meta($_POST['productid'],'_billing_period','month');
}
die();
}
Nothing seems to be working. The checkout is still processing through to completion, but the subscription details are not updated to reflect those selected by the user. What am I doing wrong?
EDIT:
Following Loic's suggestion,I played around the code a little further. I realised that the fields I added to the checkout were not done correctly, so let's take that scenario out for a bit, and try to hard-code a date as a test...
So, I tried this code:
add_action( 'woocommerce_checkout_create_subscription', 'checkout_custom_fields_update_subscription_meta', 10, 3 );
function checkout_custom_fields_update_subscription_meta( $subscription, $order, $recurring_cart ) {
$date_types = array('start', 'trial_end', 'next_payment', 'last_payment', 'end'); // Subscription date types
$dates = array(); // Initializing
// Loop through subscription date types
foreach( $date_types as $date_type ) {
$date = $subscription->get_date($date_type); // Get current date from type
// For "start" date type (or "schedule start")
if ( 'start' === $date_type ) {
$dates[$date_type] = '2021-05-20 00:00:00';
}
// For other date types (keep original data)
else {
$dates[$date_type] = $date;
}
}
$subscription->update_dates($dates); // Update dates
$subscription->save(); // Save to database and refresh caches
}
And I got the error message: "The next_payment date must occur after the start date."
So I tried this:
add_action( 'woocommerce_checkout_create_subscription', 'checkout_custom_fields_update_subscription_meta', 10, 3 );
function checkout_custom_fields_update_subscription_meta( $subscription, $order, $recurring_cart ) {
$date_types = array('start', 'trial_end', 'next_payment', 'last_payment', 'end'); // Subscription date types
$dates = array(); // Initializing
// Loop through subscription date types
foreach( $date_types as $date_type ) {
$date = $subscription->get_date($date_type); // Get current date from type
// For "start" date type (or "schedule start")
if ( 'start' === $date_type ) {
$dates[$date_type] = '2021-05-20 00:00:00';
}
// For "next_payment" date type
elseif ( 'next_payment' === $date_type ) {
$dates[$date_type] = '2021-05-29 00:00:00';
}
// For other date types (keep original data)
else {
$dates[$date_type] = $date;
}
}
$subscription->update_dates($dates); // Update dates
$subscription->save(); // Save to database and refresh caches
}
This processed the checkout, however neither start date or next payment date was saved, it defaulted back to start date being today (when ordered) and payment date being 2 weeks after that (default setting).
Any ideas?