Woocommerce wc_create_order() not working - wordpress

I'm creating a website which handles payment from stripe using wp simple pay plugin.
I created a webhook that will allow me to know if the payment is successful or not. If it is success, I will create an order that has data in it but postman always returning 500 Internal Server Error and I cannot see the error from it.
If I remove the wc_create_order() and return the $address, it worked perfectly. I am suspecting that I've doing something wrong in my code.
Here's the code I'd created
add_action('woocommerce_checkout_process', 'pinion_add_order');
function pinion_add_order($m, $a) {
global $woocommerce;
$address = array(
'first_name' => 'Project Paid ',
'last_name' => $m
);
$order = wc_create_order();
$order->add_product(($a == '100000' ? get_product('2858') : get_product('2859')), 1);
$order->set_address($address, 'billing');
$order->set_address($address, 'shipping');
// $order->set_total($amount);
$order->calculate_totals();
$order->update_status("Completed", 'Imported order', TRUE);
return $order;
}
Any help would be appreciated. Thanks

Although LoicTheAztek is correct and there is probably a better way of doing this, the answer to your question is that you haven't saved the Order object.
So before your return statement, try adding $order->save();
This will actually save the values to the database.
If that doesn't work, you may also need to adding some additional properties, such as a payment method using $order->set_payment_method($string);
Hope that helps.

I hope the below code help you.
function pinion_add_order() {
global $current_user;
$a = '100000';
$order = wc_create_order();
$order->add_product(($a == '100000' ? get_product('2858') : get_product('2859')), 1);
//$order->add_product( $_product, $item_quantity );
$order->calculate_totals();
$fname = get_user_meta( $current_user->ID, 'first_name', true );
$lname = get_user_meta( $current_user->ID, 'last_name', true );
$email = $current_user->user_email;
$address_1 = get_user_meta( $current_user->ID, 'billing_address_1', true );
$address_2 = get_user_meta( $current_user->ID, 'billing_address_2', true );
$city = get_user_meta( $current_user->ID, 'billing_city', true );
$postcode = get_user_meta( $current_user->ID, 'billing_postcode', true );
$country = get_user_meta( $current_user->ID, 'billing_country', true );
$state = get_user_meta( $current_user->ID, 'billing_state', true );
$billing_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,
);
$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,
);
$shipping_cost = 5;
$shipping_method = 'Fedex';
$order->add_shipping($shipping_cost);
$order->set_address($billing_address,'billing');
$order->set_address($address,'shipping');
$order->set_payment_method('check');//
$order->shipping_method_title = $shipping_method;
$order->calculate_totals();
$order->update_status('on-hold');
$order->save();
}
add_action('woocommerce_checkout_process', 'pinion_add_order'); //it does not take any parameters.
For more help please see the file and class structure in file : \wp-content\plugins\woocommerce\includes\class-wc-checkout.php

Related

How to create a Woo commerce Subscription order by function or custom code? [duplicate]

I want to create an order (programmatically) of a Subscription Product. I found code from this question: Programmatically creating new order in Woocommerce, which I used to try make it work.
I was not able to make it work neither with a "Simple Subscription" nor a "Simple Product".
function create_vip_order() {
global $woocommerce;
$product_id = 123;
$address = array(
'first_name' => '111Joe',
'last_name' => 'Conlin',
'company' => 'Speed Society',
'email' => 'joe#testing.com',
'phone' => '760-555-1212',
'address_1' => '123 Main st.',
'address_2' => '104',
'city' => 'San Diego',
'state' => 'Ca',
'postcode' => '92121',
'country' => 'US'
);
// Now we create the order
$order = wc_create_order();
// The add_product() function below is located in /plugins/woocommerce/includes/abstracts/abstract_wc_order.php
$order->add_product( get_product( $product_id ), 1 ); // This is an existing SIMPLE product
$order->set_address( $address, 'billing' );
//
$order->calculate_totals();
$order->update_status("Completed", 'Imported order', TRUE);
}
add_action( 'woocommerce_checkout_process', 'create_vip_order' );
If you have any solution I would really appreciate it. :)
Best Regards, Ledung
EDIT: It seem the way my Product were set up was causing the function not to work. I am currently using a Simple Subscription Product, with the "Virtual" parameter checked and a subscription length of 3 months.
Here you can see the current code that work with my setup:
function create_test_sub() {
$email = 'test#test.se';
$start_date = date( "Y-m-d H:i:s", strtotime( "now" ) );
$address = array(
'first_name' => 'Firstname',
'last_name' => 'Secondname',
'company' => 'Company',
'email' => $email,
'phone' => '',
'address_1' => 'Streetname 123',
'address_2' => '',
'city' => 'City',
'postcode' => '12345',
'country' => 'Country'
);
$default_password = wp_generate_password();
if ( ! $user = get_user_by( 'login', $email ) ) $user = wp_create_user( $email, $default_password, $email );
// I've used one product with multiple variations
$parent_product = wc_get_product( 3901 );
$args = array(
'attribute_billing-period' => 'Yearly',
'attribute_subscription-type' => 'Both'
);
$product_variation = $parent_product->get_matching_variation( $args );
$product = wc_get_product( $product_variation );
$product_month_length = $parent_product->subscription_length;
$end_date = date( "Y-m-d H:i:s", strtotime( $product_month_length . "months" ) );
$quantity = 1;
// As far as I can see, you need to create the order first, then the sub
$order = wc_create_order( array( 'customer_id' => $user->id ) );
$order->add_product( $parent_product, $quantity, $args );
$order->set_address( $address, 'billing' );
$order->set_address( $address, 'shipping' );
$order->calculate_totals();
$order->update_status( "completed", 'Imported order', TRUE );
// Order created, now create sub attached to it -- optional if you're not creating a subscription, obvs
// Each variation has a different subscription period
$period = WC_Subscriptions_Product::get_period( $parent_product );
$interval = WC_Subscriptions_Product::get_interval( $product );
$sub = wcs_create_subscription( array( 'status' => 'active', 'order_id' => $order->id, 'billing_period' => $period, 'billing_interval' => $interval, 'start_date' => $start_date, 'end' => $end_date ) );
if ( ! is_wp_error( $sub ) ){
$sub->add_product( $parent_product, $quantity, $args );
$sub->set_address( $address, 'billing' );
$sub->set_address( $address, 'shipping' );
$dates = array(
'end' => $end_date,
);
$sub->update_dates( $dates );
$sub->calculate_totals();
}
WC_Subscriptions_Manager::activate_subscriptions_for_order( $order );
print "<a href='/wp-admin/post.php?post=" . $sub->id . "&action=edit'>Sub created! Click here to edit</a>";
$returnarray = array(
'subscription_id' => $sub->id,
'order_id' => $order->id,
);
return $returnarray;
}
$test = create_test_sub();
Here's my custom function I built based on all the answers I found on SO and digging through subscriptions code base.
Tested with
WordPress 5.2.5
WooCommerce 3.8.0
WooCommerce Subscriptions 2.6.1
https://gist.github.com/tripflex/a3123052f36daf18f7cb05391d752223
function give_user_subscription( $product, $user_id, $note = '' ){
// 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;
}
$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 );
$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 )
));
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 ),
);
$sub->update_dates( $dates );
$sub->calculate_totals();
// 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;
}

Add woocommerce variation GTIN to structured data

If a webshop has variable products, in some cases the variations have unique GTINs. In our case, it is EAN.
How to add these different GTINS to the structured data? I made a function to insert multiple "offer" in "offers", but the GTIN is not recognized here.
This is the function:
//add structured data to the markup
function set_structured_data( $markup, $product ) {
if ($product->is_type('simple')){
$markup['brand'] = array('#type' => 'Brand', 'name' => get_post_meta( $product->get_id(), '_brand', true ) );
$markup['gtin8'] = get_post_meta( $product->get_id(), '_EAN', true );
}
if ($product->is_type('variable')){
$available_variations = $product->get_available_variations();
foreach ($available_variations as $variation) {
$variation_id = $variation['variation_id'];
$variproduct = wc_get_product($variation_id);
$i++;
$stock = $product->get_stock_status();
$offers[] = array(
'type' => 'Offer',
'price' => $variproduct->get_price(),
'priceValidUntil' => $priceuntil,
'priceSpecification' => array(
'price' => $variproduct->get_price(),
'priceCurrency' => get_woocommerce_currency(),
'valueAddedTaxIncluded' => 'http://schema.org/True'
),
'priceCurrency' => get_woocommerce_currency(),
'availability' => 'http://schema.org/'.$stock.'',
'url' => get_the_permalink(),
'seller' => array (
'type' => 'Organization',
'name' => 'HeatPerformance®',
'url' => get_the_permalink(),
));
}
$markup['offers'] = $offers;
$markup['brand'] = array('#type' => 'Brand', 'name' => get_post_meta( $product->get_id(), '_brand', true ) );
}
return $markup;
}
add_filter( 'woocommerce_structured_data_product', 'set_structured_data', 99, 2 );
Any ideas?
Ok after a couple of days puzzling i found the path to a solution here:
https://support.google.com/merchants/answer/6386198?hl=en
Result is that i corrected the standardized method from woocommerce and made each variation a unique product.
So first remove the markup in case of a variable product like this:
function set_structured_data( $markup, $product ) {
if ($product->is_type('variable')) {
$markup = array();
}
return $markup;
}
add_filter( 'woocommerce_structured_data_product', 'set_structured_data', 99, 2 );
And then build up the ld+json script again, but then the desired way:
function set_structured_data_variable() {
global $product;
if (isset($product)){
if ($product->is_type('variable') && !empty($product)){
$available_variations = $product->get_available_variations();
$date = date("Y-m-d",strtotime(" + 3months"));
$commenttext = '';
$commentauthor = '';
$commentdate = '';
$comments = get_comments(array( 'post_id' => $product->get_id(), 'number' => '1' ));
foreach($comments as $comment) {
$commenttext = $comment->comment_content;
$commentauthor = $comment->comment_author;
$commentdate = $comment->comment_date;
}
foreach ($available_variations as $variation) {
$variation_id = $variation['variation_id'];
$variproduct = wc_get_product($variation_id);
$i++;
$gtin = 0000000000001;
if (!empty(get_post_meta( $variation_id, '_EAN', true ))){
$gtin = get_post_meta( $variation_id, '_EAN', true );
}
$stock = $product->get_stock_status();
$arrays[$i] = array(
'#context' => 'https://schema.org/',
'#type' => 'Product',
'sku' => $variproduct->get_sku(),
'gtin13' => $gtin,
'image' => get_the_post_thumbnail_url($product->get_id()),
'name' => implode(" / ", $variproduct->get_variation_attributes()),
'description' => wp_strip_all_tags(get_the_excerpt($product->get_id())),
'brand' => array('#type' => 'Brand', 'name' => get_post_meta( $product->get_id(), '_brand', true ) ),
'review' => array(
'#type' => 'Review',
'reviewRating' => array (
'#type' => 'Rating',
'ratingValue' => $product->get_review_count(),
'bestRating' => '5',
'worstRating' => '1',
),
'author' => array(
'#type' => 'person',
'name' => $commentauthor,
'reviewBody' => $commenttext,
'datePublished' => $commentdate,
)),
'aggregateRating' => array (
'#type' => 'AggregateRating',
'ratingValue'=> $product->get_average_rating(),
'reviewCount' => $product->get_rating_count(),
),
'inProductGroupWithID' => $product->get_sku(),
'offers' => array(
'#type' => 'Offer',
'price' => $variproduct->get_price(),
'priceValidUntil' => $date,
'priceSpecification' => array(
'price' => $variproduct->get_price(),
'priceCurrency' => get_woocommerce_currency(),
'valueAddedTaxIncluded' => 'http://schema.org/True'
),
'priceCurrency' => get_woocommerce_currency(),
'availability' => 'http://schema.org/'.$stock.'',
'url' => get_the_permalink(),
'seller' => array (
'type' => 'Organization',
'name' => 'HeatPerformance®',
'url' => get_the_permalink(),
)));
}
echo '<script type="application/ld+json" class="buronoort">[';
$i = 0;
foreach ($arrays as $array){
$i++;
echo json_encode($array);
if ($i < array_key_last($arrays)){
echo ',';
}
}
echo ']</script>';
}
}
}
add_action('wp_head','set_structured_data_variable', 19);
Tested in the test tool for structured data and it is working.
A little concern is the product review however, i have to look into that what happens after multiple reviews.
Another concern is the EAN, i have set it standard to "0000000000001" as not all EANS are inputted yet. So this is a debatle solution, but if someone has a better idea, keep me posted.

Custom Checkout Field for Woocommerce with dynamic options

I want to have dynamic options for my checkout dropdown field. The options must be users of specific roles that are in WordPress users. How can I achieve it? Below is the code that I am working with. In the first function, we can get all administrator users. I want users to be in options of the dropdown in the select field of checkout.
**User Roles**
function get_users_by_role($role, $orderby, $order) {
$args = array(
'role' => 'administrator',
'orderby' => 'user_nicename',
'order' => 'ASC'
);
$users = get_users( $args );
return $users;
}
**Dropdown Field**
function everest_custom_dropdown_fields( $fields ) {
$fields['everestmerchant_extra_dropdown_fields']['dropdown'] = array(
'label' => __('Leader Name', 'woocommerce'),
'placeholder' => _x('Leader Name', 'placeholder', 'woocommerce'),
'required' => true,
'class' => array( 'wps-drop' ),
'clear' => true,
'type' => 'select',
'options' => array(
'option 1' => __('option 1', 'woocommerce' ),
'option 2' => __('option 2', 'woocommerce'
)//end of options
);
return $fields;
}
add_filter( 'woocommerce_checkout_fields', 'everest_custom_dropdown_fields' );
Get All Leaders
function get_leaders($role) {
$args = array(
'role' => $role,
'orderby' => 'user_nicename',
'order' => 'ASC'
);
$leaders = ['' => 'Please Select'];
$users = get_users( $args );
if($users){
foreach($users as $user){
$leaders[$user->data->ID] = $user->data->display_name;
}
}
return $leaders;
}
Add Leader field in checkout page
function leader_name_select_field( $checkout ){
woocommerce_form_field( 'leader_name', array(
'type' => 'select',
'required' => true,
'class' => array('form-row-wide'),
'label' => 'Leader Name',
'options' => get_leaders('administrator')
), $checkout->get_value( 'leader_name' ) );
}
add_action( 'woocommerce_after_checkout_billing_form', 'leader_name_select_field' );
Save Selected field in database.
function save_leader_name_of_order( $order_id ){
if( !empty( $_POST['leader_name'] ) )
update_post_meta( $order_id, 'leader_name', sanitize_text_field( $_POST['leader_name'] ) );
}
add_action( 'woocommerce_checkout_update_order_meta', 'save_leader_name_of_order' );
Show saved field in order page in dashboard
function leader_name_show_on_order_detail_page($order){
$leader_id = get_post_meta($order->get_id(), 'leader_name', true );
$leader = get_user_by( 'ID', $leader_id );
if($leader_id && $leader){
echo '<p class="form-field form-field-wide">';
echo '<label>Leader Name</label>';
echo '<p> ' . $leader->data->display_name . '</p>';
echo '</p>';
}
}
add_action( 'woocommerce_admin_order_data_after_order_details', 'leader_name_show_on_order_detail_page', 10, 1 );

$order->get_checkout_payment_url() different behavior for product and subscription

I'm trying to create subscription order by code. I'm using the latest version of Woocommerce and Woocommerce Subscription plugins. It's working fine, but I got different order-pay page when the order contains subscription product.
When the order contains a subscription, I got all the billing and the shipping fields. If the order only contains simple products, I got a summary about the order and the payment methods. I would like the same behavior for subscriptions.
Example link:
https://test.eu/hu/cart/order-pay/4467/?pay_for_order=true&key=wc_order_161651fdsf56
I generate the link with the method get_checkout_payment_url and I got similar link in both cases, but if the order contains a subscription, I 'm redirected to the cart page immediately.
Does anybody faced with same problem?
Thank you for any help!
Best regards,
Mark
$start_date = $order_data['created_at'];
$billing_address = array(
'first_name' => $order_data['first_name'],
'last_name' => $order_data['last_name'],
'company' => $order_data['company_name'],
'email' => $order_data['email'],
'phone' => $order_data['phone_number'],
'address_1' => $order_data['street_address'],
'address_2' => $order_data['apartment_suite_unit'],
'city' => $order_data['town'],
'postcode' => $order_data['zip_code'],
'country' => $order_data['country']
);
$shipping_address = array(
'first_name' => $order_data['shipping_first_name'],
'last_name' => $order_data['shipping_last_name'],
'company' => $order_data['shipping_company_name'],
'address_1' => $order_data['shipping_street_address'],
'address_2' => $order_data['shipping_apartment_suite_unit'],
'city' => $order_data['shipping_town'],
'postcode' => $order_data['shipping_zip_code'],
'country' => $order_data['shipping_country']
);
$email = $order_data['email'];
if (!$user = get_user_by('email', $email)) $user = get_user_by('id', wc_create_new_customer($email));
$order = wc_create_order(array('customer_id' => $user->ID));
update_post_meta($order->ID, "phone_order", true);
foreach ($order_data['ordered_items'] as $item) {
$product = wce_get_product($item, $currency);
$order->add_product( $product, $item['quantity']);
}
$order->set_address( $billing_address, 'billing' );
$order->set_address( $shipping_address, 'shipping' );
$order->set_currency( $currency );
$order->set_payment_method( $order_data['payment_method'] );
$order->calculate_totals();
$order->calculate_taxes();
// Előfizetés
foreach ($order_data['ordered_items'] as $item) {
if (WC_Subscriptions_Product::is_subscription($item['id'])) {
$product = wce_get_product($item, $currency);
$sub = wcs_create_subscription(array('order_id' => $order->id, 'billing_period' => $period, 'billing_interval' => $interval, 'start_date' => $start_date));
$sub->add_product( $product, $item['quantity']/*, $args*/);
$sub->set_address( $billing_address, 'billing' );
$sub->set_address( $shipping_address, 'shipping' );
$sub->calculate_totals();
}
}
$payment_link = $order->get_checkout_payment_url();
return $payment_link;
}

how to delete all users and posts based on 'user_meta'?

I have developed a small wordpress application where It has Institutes(wp user), Trainers(wp user), Trainees(wp user), courses(custom post) and notifications(custom post). All the application is working fine but If I delete an institute all the information belongs to that institute like Trainers, Trainee, notifications & courses should also be deleted. While I was creating the 'institute' user I am storing the all the related info like first name, last name in wordpress table 'wp_users' and 'institute name' is storing as 'user meta' with key 'inistitute_name' in 'wp_usermeta' table like below is my code:
$user_data = array(
'ID' => '',
'user_pass' => '',
'user_login' => $first_name,
'user_email' => $user_email,
'first_name' => $first_name,
'last_name' => $last_name,
'role' => 'admin'//get_option('default_option')
);
$random_password = wp_generate_password(8,false);
$user_id = wp_insert_user( $user_data );
update_user_meta( $user_id, 'inistitute_name',$insititute_name );
While creating Trainer (or) Trainee my code is like below:
$user_data = array(
'ID' => '',
'user_pass' => '',
'user_login' => $first_name,
'user_email' => $trainer_email,
'first_name' => $first_name,
'last_name' => $last_name,
'role' => 'trainer'
);
$random_password = wp_generate_password(8,false);
$user_id = wp_insert_user( $user_data );
update_user_meta( $user_id, 'inistitute_name',$this->institute_name[0] );
wp_set_password($random_password, $user_id);
While creating courses my code is like below:
$user_ID = get_current_user_id();
$institute_name = get_user_meta($user_ID, 'inistitute_name', true);
$post = array(
'post_title' => $title,
'post_content' => $description,
'post_status' => 'publish',
'post_type' => "courses"
);
$id = wp_insert_post($post);
update_post_meta( $id, 'inistitute_name', $institute_name );
Suppose let us say if a institute 'abcd' is deleted then all the information like 'trainer', 'trainee', 'courses' & 'notifications' associated with that institute should also be deleted based on a 'user_meta' field. Is it possible to delete? (or) did I do any mistake? can anyone tell me what was I doing wrong?
Try this code:
$user_args = array(
'meta_key' => 'inistitute_name',
'meta_value' => 'your_value', //<-- replace it by your user_meta value.
'meta_compare' => '=',
'orderby' => 'ID',
'number' => -1
);
// Custom query.
$user_query = new WP_User_Query($user_args);
// Get query results.
$users = $user_query->get_results();
//print_r($users);
// Check for users
if (!empty($users))
{
// Loop over users.
foreach ($users as $user)
{
$user_id = $user->ID;
// Get each user's data.
$user_info = get_userdata($user->ID);
$user_display_name = $user_info->display_name;
$args = array(
'numberposts' => -1,
'post_type' => 'any', //<-- you can Specific type by array('post', 'my_custom_post')
'author' => $user_id
);
// get all posts by this user: posts, pages, attachments, etc..
$user_posts = get_posts($args);
if (!empty($user_posts))
{
// delete all the user posts
foreach ($user_posts as $user_post)
{
wp_delete_post($user_post->ID, true);
}
}
wp_delete_user( $user_id, $reassign );
}
}
else
{
//"no user found"
}
I haven't tested this code, out form my WP knowledge.
Please note before testing this code do take a Database backup.
I got the solution form wordpress.stackexchange.com link to that question is here
https://wordpress.stackexchange.com/questions/249435/how-to-delete-all-users-and-posts-based-on-user-meta/

Resources