Create a woocommerce subscription programatically

Recently i am working on woocommerce project where i need to forcefully create a subscription using woocommerce subscription plugin after an order is placed successfully.
This will happen only when the admin creates an order and it will find the subscription product in the cart and then create a subscription for the subscription typed product.

There was a requirement and I found a solution for that you can read this article and it will be very useful if you want to achieve similar requirements.
So I am going to add my thoughts here:

Creating an automatic renewal subscription programmatically with the WooCommerce Subscription plugin requires custom code to handle the subscription creation and setup. Below is an example of how you can achieve this using WordPress hooks and the WooCommerce Subscription API:

  1. Add a product with the “Subscription” product type: First, make sure you have a product created with the “Subscription” product type in WooCommerce. This can be done manually via the WordPress dashboard.
  2. Add code to create a subscription when a new order is placed: You can use the woocommerce_new_order  OR
    woocommerce_payment_complete  hook to create a new subscription when a customer places an order for the subscription product. Add the following code to your theme’s functions.php file or create a custom plugin:
function create_subscription_after_order( $product, $user_id, $note = '', $order ){

// First make sure all required functions and classes exist
if( ! function_exists( 'wc_create_order' ) || ! function_exists( 'wcs_create_subscription' ) || ! class_exists( 'WC_Subscriptions_Product' ) ){
return false;
}

// $order = wc_create_order( array( 'customer_id' => $user_id ) );

if( is_wp_error( $order ) ){
return false;
}
$order_id = $order->get_id();
$user = get_user_by( 'ID', $user_id );

$fname = $user->first_name;
$lname = $user->last_name;
$email = $user->user_email;


$address_1 = get_user_meta( $user_id, 'billing_address_1', true );
$address_2 = get_user_meta( $user_id, 'billing_address_2', true );
$city = get_user_meta( $user_id, 'billing_city', true );
$postcode = get_user_meta( $user_id, 'billing_postcode', true );
$country = get_user_meta( $user_id, 'billing_country', true );
$state = get_user_meta( $user_id, 'billing_state', true );

$address = array(
'first_name' => $fname,
'last_name' => $lname,
'email' => $email,
'address_1' => $address_1,
'address_2' => $address_2,
'city' => $city,
'state' => $state,
'postcode' => $postcode,
'country' => $country,
);

$order->set_address( $address, 'billing' );
$order->set_address( $address, 'shipping' );
$order->add_product( $product, 1 );

$payment_method = $order->get_payment_method();
$payment_title = $order->get_payment_method_title();
$payment_token = $order->get_payment_tokens();
$payment_gateways = WC()->payment_gateways->payment_gateways();


$sub = wcs_create_subscription(array(
'order_id' => $order->get_id(),
'status' => 'pending', // Status should be initially set to pending to match how normal checkout process goes
'billing_period' => WC_Subscriptions_Product::get_period( $product ),
'billing_interval' => WC_Subscriptions_Product::get_interval( $product )
));
$sub_id = $sub->get_id();

if( is_wp_error( $sub ) ){
return false;
}

// Modeled after WC_Subscriptions_Cart::calculate_subscription_totals()
$start_date = gmdate( 'Y-m-d H:i:s' );
// Add product to subscription
$sub->add_product( $product, 1 );

$dates = array(
'trial_end' => WC_Subscriptions_Product::get_trial_expiration_date( $product, $start_date ),
'next_payment' => WC_Subscriptions_Product::get_first_renewal_payment_date( $product, $start_date ),
'end' => WC_Subscriptions_Product::get_expiration_date( $product, $start_date ),
);

$auto_renewal = true;
$sub->set_requires_manual_renewal( false );
$sub->update_meta_data('_subscription_renewal', $auto_renewal);

$sub->update_dates( $dates );
$sub->calculate_totals();

$cardDetails = getPaymentCardDetails ($order_id);

$payment_method=$cardDetails['payment_method'];
$p_key = '_'.$payment_method;

$sub->update_meta_data('_payment_method', $cardDetails['payment_method']);
$sub->update_meta_data('_payment_method_title', $cardDetails['payment_title']);
$sub->update_meta_data($p_key.'_customer_id', $cardDetails['customer_id']);
$sub->update_meta_data($p_key.'_card_id', $cardDetails['customer_id']);
$billing_details_ar=array(
'_billing_first_name',
'_billing_last_name',
'_billing_address_1',
'_billing_address_2',
'_billing_city',
'_billing_state',
'_billing_postcode',
'_billing_country',
'_billing_phone',
'_billing_company',
'_shipping_first_name',
'_shipping_last_name',
'_shipping_address_1',
'_shipping_address_2',
'_shipping_city',
'_shipping_state',
'_shipping_postcode',
'_shipping_country',
'_shipping_company'
);

/* Add billing and shipping info to subscription */
foreach($billing_details_ar as $key){
$getVal = get_post_meta($order_id,$key,true);
update_post_meta($sub_id, $key, $getVal);
}
/* Add billing and shipping info to subscription */

update_post_meta($sub_id, $p_key.'_card', $cardDetails['card']);

// Update order status with custom note
$note = ! empty( $note ) ? $note : __( 'Programmatically added order and subscription.' );
$order->update_status( 'completed', $note, true );
// Also update subscription status to active from pending (and add note)
$sub->update_status( 'active', $note, true );

return $sub;
}

3. Now we need to use the above function to create a subscription using woocommerce_payment_complete hook.
This hook will call just after when payment is completed. So again open functions.php or your plugin file just add this code that will find the subscription products from the order and create a subscription respectively.


/* After order payment completed*/
add_action( 'woocommerce_payment_complete', 'create_subscription_on_order' );

function create_subscription_on_order($order_id ){

$user = wp_get_current_user();
// $allowed_roles = array('editor', 'administrator');
$allowed_roles = array('administrator');
if(! array_intersect($allowed_roles, $user->roles ) ) {
return;
}
$order = wc_get_order( $order_id );
// Get the user ID associated with the order
$user_id = $order->get_customer_id();

$subscriptions_ids = wcs_get_subscriptions_for_order( $order_id, array( 'order_type' => 'any' ) );
// We get all related subscriptions for this order

$has_subscription = false;
if($subscriptions_ids){
foreach( $subscriptions_ids as $subscription_id => $subscription_obj ){
if($subscription_obj->order->id == $order_id){
$has_subscription = true;
break; // Stop the loop
}
}
}


if(!$has_subscription){
// check if the order is already paid
if($order->is_paid())
{
foreach ( $order->get_items() as $item_id => $item ) {

if( $item['variation_id'] > 0 ){
$product_id = $item['variation_id']; // variable product
} else {
$product_id = $item['product_id']; // simple product
}

// Get the product object
$product = wc_get_product( $product_id );

//$user_id = $order->get_user_id();
// you can add variable subscription product as well
if ( $product->is_type( 'subscription' ) ) {
// call subscrtion function to create the subscription programatically
create_subscription_after_order( $product, $user_id, $note = '',$order );
}

}
}
}

}

 

Now our script is ready to use.
I hope you like this article.
Thanks and Happy Coding.

Related Blog

Sign up for our newsletter to stay up to
date with tech news!