I have successfully used the following code to create a woocommerce order after gravity form submission.
add_action( 'gform_after_submission_56', 'post_to_third_party', 10, 2 ); function post_to_third_party( $entry, $form ) { global $woocommerce; // use this to find out $entry output var_dump($entry);
// set some variables
$user_id =rgar( $entry, '97' );
$product_id = rgar( $entry, '71' );
$quantity = rgar( $entry, '73' );
$note = rgar( $entry, '53' );
$product = wc_get_product($product_id);
$address = array( 'first_name' => rgar( $entry, '98' ), 'last_name' => rgar( $entry, '99' ), 'company' => rgar( $entry, '' ), 'email' => rgar( $entry, '83' ), 'phone' => rgar( $entry, '84' ), 'address_1' => rgar( $entry, '88.1' ), 'address_2' => rgar( $entry, '88.2' ), 'city' => rgar( $entry, '88.3' ), 'state' => rgar( $entry, '88.4' ), 'postcode' => rgar( $entry, '88.5' ), 'country' => rgar( $entry, '88.6' ), );
$order = wc_create_order(); $order->set_customer_id( $user_id ); $order->add_product( wc_get_product($product_id), $quantity, $prices); foreach ($order->get_items() as $item_key => $item ) { $item->add_meta_data( 'Booking Request', $note, true ); } $order->set_address( $address, 'billing' ); $order->calculate_totals(); $order->update_status( 'pending payment', 'pending', TRUE); $order->add_order_note( $note );
$coupon_code = rgar( $entry, '105' ); $order->apply_coupon($coupon_code);
The issue I am faced with is that I need a different form to also create a woocommerce order upon submission. I don't know how to do this as when I create a code reflecting the correct form id it tells me it cannot call the function more than once.
What should I do? is there another function or do I somehow add to this original code?
The problem isn't the hook (gform_after_submission) being recycled, but the second part, "post_to_third_party."
That function can't be redefined. You can either rename that, or just make your after_submission a bit more modular for all forms.
add_action( 'gform_after_submission', 'post_to_third_party', 10, 2 );
function post_to_third_party( $entry, $form ) {
switch ($form['id']) {
case 56:
// do your code for form 56.
break;
case 12:
// do stuff if form id is 12... or whatever.
break;
}
}
Related
I'm a newbie in PHP, I use this PHP code that works like a charm. It's a custom form that sends to Woocommerce different fields. I want to add a "preg_match" check for each of those fields so the user can only enter:
function custom_multi_step_form_first_handler() {
$email = sanitize_text_field( strval( $_POST['email'] ) );
$first_name = sanitize_text_field( strval( $_POST['first_name'] ) );
$last_name = sanitize_text_field( strval( $_POST['last_name'] ) );
$phone = sanitize_text_field( strval( $_POST['phone'] ) );
$street = sanitize_text_field( strval( $_POST['street'] ) );
$city = sanitize_text_field( strval( $_POST['city'] ) );
$postcode = sanitize_text_field( strval( $_POST['postcode'] ) );
$person_id = sanitize_text_field( strval( $_POST['person_id'] ) );
$country = 'UK';
global $woocommerce;
$address = array(
'first_name' => $first_name,
'last_name' => $last_name,
'company' => '',
'email' => $email,
'phone' => $phone,
'address_1' => $street,
'city' => $city,
'state' => '',
'postcode' => $postcode,
'country' => $country,
);
$order = wc_create_order();
$order->set_address( $address, 'billing' );
$order->calculate_totals();
$_SESSION['current_order_id'] = $order->get_id();
update_post_meta( $order->get_id(), 'person_id', $person_id );
wp_die();
}
function custom_get_building_data_for_postcode( $postcode ) {
$building = get_page_by_title( $postcode, null, 'building' );
$building_meta = get_post_meta( $building->ID );
if ( is_null( $building ) ) {
return array();
}
return array(
'name' => get_post_meta( $building->ID, 'building_name', true ),
'city' => get_post_meta( $building->ID, 'building_city', true ),
'address' => get_post_meta( $building->ID, 'building_address', true ),
);
}
In the phone field: numbers, "+", spaces; (22 chars total)
In the postcode field: postcodes are contained in a custom post type "Buildings" with their titles as values. Only those values. How do I do that?
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;
}
I'm trying to store custom shipping and billing fields in order and then to be print in emails ( admin & customer ) but with no success , is there anyone with big heart to help me ?
So as you can see i removed some fields , added other fields in Shipping & Billing then i try to store data of order and at the last i try to send my extra fields in order_email .
Here is my code in functions.php
// Replace billing_email with shipping_email " This because custome don recieve email notification if don't ask invoice "
add_action('woocommerce_checkout_update_order_meta', 'set_billing_email_from_shipping_email', 50, 2 );
function set_billing_email_from_shipping_email( $order_id, $data ) {
// Get customer shipping email
$email = get_post_meta( $order_id, '_shipping_email', true );
// Set billing email from shipping email
update_post_meta( $order_id, '_billing_email', $email );
}
// Remove fields
add_filter( 'woocommerce_checkout_fields', 'wc_remove_checkout_fields' );
function wc_remove_checkout_fields( $fields ) {
// Billing fields
unset( $fields['billing']['billing_first_name'] );
unset( $fields['billing']['billing_last_name'] );
unset( $fields['billing']['billing_address_2'] );
// Shipping fields
unset( $fields['shipping']['shipping_address_2'] );
unset( $fields['shipping']['shipping_company'] );
// Order fields
unset( $fields['order']['order_comments'] );
return $fields;
}
//Add custom fields
add_filter( 'woocommerce_shipping_fields' , 'custom_shipping_fields' );
function custom_shipping_fields( $fields ) {
$fields['shipping_email'] = array(
'label' => __( 'Email', 'woocommerce' ),
'required' =>true,
'class' => array( 'form-row-last' ),
'validate' => array( 'email' ),
);
$fields['shipping_phone'] = array(
'label' => __( 'Telefono', 'woocommerce' ),
'required' => true,
'class' => array( 'form-row-first' ),
'clear' => true,
'validate' => array( 'phone' ),
);
$fields['shipping_invoice'] =array(
'type' => 'checkbox',
'class' => array('form-row-four'),
'label' => __(' Fattura ?'),
'label_class' => array('woocommerce-form__label l_checkbox'),
'input_class' => array('woocommerce-form__input woocommerce-form__input-checkbox i_checkbox'),
);
return $fields;
}
add_filter( 'woocommerce_billing_fields' , 'custom_billing_fields' );
function custom_billing_fields( $fields ) {
$fields['billing_vat'] = array(
'label' => __( 'P.Iva/CF', 'woocommerce' ),
'required' =>false,
'class' => array( 'form-row-last' ),
);
return $fields;
};
function custom_shipping_save_extra_checkout_fields( $order_id, $posted ){
if( isset( $posted['custom_shipping_fields'] ) ) {
update_post_meta( $order_id, '_custom_shipping_fields', sanitize_text_field( $posted['_custom_shipping_fields'] ) );
}
}
function custom_billing_save_extra_checkout_fields( $order_id, $posted ){
if( isset( $posted['custom_shipping_fields'] ) ) {
update_post_meta( $order_id, '_custom_shipping_fields', sanitize_text_field( $posted['_custom_shipping_fields'] ) );
}
}
add_action( 'woocommerce_checkout_update_order_meta', 'custom_save_extra_checkout_fields', 10, 2 );
function custom_email_order_meta_fields( $fields, $sent_to_admin, $order ) {
$fields['custom_shipping_fields'] = array(
'label' => __( 'Custom Siping Fields' ),
'value' => get_post_meta( $order->id, '_custom_shipping_fields', true ),
);
return $fields;
}
add_filter('woocommerce_email_order_meta_fields', 'custom_email_order_meta_fields', 10, 3 );
Thank you!
I'm trying to add two buttons to Woocommerce / MyAccount / View Order Details (Not in orders list) (ORDER AGAIN | CANCEL) but I only see the 'Order Again' in completed orders but not in other statuses. Thank you!
function cs_add_order_again_to_my_orders_details( $actions, $order ) {
if ( $order->has_status( array( 'completed','pending', 'processing', 'on-hold', 'failed' ) ) ) {
$actions['order-again'] = array(
'url' => wp_nonce_url( add_query_arg( 'order_again', $order->id ) , 'woocommerce-order_again' ),
'name' => __( 'Order Again', 'woocommerce' )
);
// cancel button
$actions['cancel'] = array(
'url' => NO_IDEA,
'name' => NO_IDEA
);
}
return $actions;
}
add_filter( 'woocommerce_my_account_my_orders_details', 'cs_add_order_again_to_my_orders_details', 50, 2 );
By default, only orders with completed status can be reordered. You can add other statuses with the following hook:
add_filter( 'woocommerce_valid_order_statuses_for_order_again', 'ywp_filter_order_again' );
function ywp_filter_order_again( $statuses ) {
return array( 'completed', 'pending', 'processing', 'on-hold', 'failed' );
}
And for cancel order button:
$actions['cancel'] = array(
'url' => $order->get_cancel_order_url( wc_get_page_permalink( 'myaccount' ) ),
'name' => __( 'Cancel', 'woocommerce' ),
);
By default, only orders with pending status can be canceled. You can add other situations with the following hook:
add_filter( 'woocommerce_valid_order_statuses_for_cancel', 'ywp_filter_cancel_order' );
function ywp_filter_cancel_order( $statuses ) {
return array( 'completed', 'pending', 'processing', 'on-hold', 'failed' );
}
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