1
votes

Why can't I retrieve the data from a Woocommerce checkout field to update subscription data as the order processes?

I want to update the next renewal date based on the customers' frequency request on checkout. Here is my code:

1) Set up the checkout field:

add_action( 'woocommerce_after_order_notes', 'hgf_custom_checkout_field' );

function hgf_custom_checkout_field( $checkout ) {
global $woocommerce;

    woocommerce_form_field( 'frequency', array(
        'type'          => 'select',
        'required'          => true,
        'class'         => array('form-row-wide'),
        'label'         => __('Change this any time, just email.'),
        'options'     => array(
            'blank'     => __( 'Select frequency preference', 'woocommerce' ),              
            1 => __( 'Every Week', 'woocommerce' ),
            2 => __( 'Every Other Week' , 'woocommerce' ),
            3 => __( 'Once Per Month' , 'woocommerce' )
                )
            ), $checkout->get_value( 'frequency' ));
            echo '</div>';
}

2) Update the order meta. This creates two custom fields on the customer order, as well as updates the billing interval on the subscription:

add_action( 'woocommerce_checkout_update_order_meta', 'hgf_checkout_field_update_order_meta' );
function hgf_checkout_field_update_order_meta( $order_id ) {

    if ( ! empty( $_POST['frequency'] ) ) {

        update_post_meta( $order_id, 'frequency', $_POST['frequency'] );
        update_post_meta( $order_id, 'billing_interval', $_POST['frequency'] );
    }

}

3) Update the renewal date
For the last part, I can update the renewal date with a dummy date of my choosing (for instance: $renewal date = "2018-12-15", but when I try to get it to read the 'billing_interval' field, it reverts to the else default.

    add_action( 'woocommerce_checkout_create_subscription', 'hgf_next_renewal' );
    function hgf_next_renewal( $subscription, $timezone='site' ) {

        $billing_interval = get_post_meta( get_the_ID(), 'billing_interval', true); 

    if( $billing_interval == 2 ) {
        $renewal_date = date( 'Y-m-d H:i:s', strtotime( "2017-10-01" ) ) /* date( 'Y-m-d H:i:s', strtotime( "+2 weeks" ) ) */ ;
    } if( $billing_interval == 4 ) {
        $renewal_date = date( 'Y-m-d H:i:s', strtotime( "2017-12-01" ) ) /* date( 'Y-m-d H:i:s', strtotime( "+4 weeks" ) ) */ ;
    } else {
        $renewal_date = date( 'Y-m-d H:i:s' ) ) /* date( 'Y-m-d H:i:s', strtotime( $renewal_date) ) */ ;
    }

        $subscription->update_dates( array(
            'next_payment' => $renewal_date,
            ) );

        return $subscription;
    }

This is all the different ways I have tried:

1) $billing_interval = $subscription->get_billing_interval();
2) $billing_interval = get_post_meta( $subscription->get_ID(), 'billing_interval', true);
3) $billing_interval = get_post_meta( $order_id, 'billing_interval', true);
4) $subscriptions = wcs_get_users_subscriptions( $user_id );
     foreach ( $subscriptions as $sub ) {
      $billing_interval = get_post_meta( $sub->get_order_number(), '_billing_interval', true);
      }
5) $billing_interval = $checkout->get_value( 'frequency' );

Does anyone know why I can't retrieve a value from my checkout field while in the 'woocommerce_checkout_create_subscription' action?

1

1 Answers

2
votes

As you are saving your 'billing_interval' custom field in the Order meta data, you can't get this custom field through the subscription object or ID… You need to get first the Parent Order ID.

To get the parent Order ID from the subscription object you need to use the WC_Order method get_parent_id()

add_action( 'woocommerce_checkout_create_subscription', 'hgf_next_renewal' );
function hgf_next_renewal( $subscription, $timezone='site' ) {
    
    // MISSING!: The parent order ID to set below
    $order_parent_id = $subscription->get_parent_id();
    
    $billing_interval = get_post_meta( $order_parent_id, 'billing_interval', true);

    if( $billing_interval == 2 ) {
        $renewal_date = date( 'Y-m-d H:i:s', strtotime( "2017-10-01" ) ) /* date( 'Y-m-d H:i:s', strtotime( "+2 weeks" ) ) */ ;
    } elseif( $billing_interval == 4 ) {
        $renewal_date = date( 'Y-m-d H:i:s', strtotime( "2017-12-01" ) ) /* date( 'Y-m-d H:i:s', strtotime( "+4 weeks" ) ) */ ;
    } else {
        $renewal_date = date( 'Y-m-d H:i:s', strtotime( "2017-09-01" ) ) /* date( 'Y-m-d H:i:s' ) */ ;
    }

    $subscription->update_dates( array(
        'next_payment' => $renewal_date,
    ) );

    return $subscription;
}

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

I haven't tested your code for real, but it doesn't throw any error and should work for you this time.