Multiple PayPal accounts linked to ONE installation of Woocommerce - php

My issue: The client has 12 locations, each location is a different corporation hence a different PayPal account per business. By default woocommerce only supports one email to be entered to process the payment. The goal is to use one installation of wordpress / woocommerce then direct the user to the PayPal account associated with the location they have selected upon checkout.
My Theory / Attempt: originally I thought of implementing this feature by setting up a variation so the user can select a location which will then pass a parameter to the URL. The parameter would later be used within the PHP to overwrite the default email.
My Problem: I am having trouble with overwriting the default email that is entered within the admin settings, I cant seem to locate this email in the database. I am assuming the file pertaining this modification is located at: wp-content/plugins/woocommerce/includes/gateways/paypal but would prefer doing this the wordpress way vs editing core files, for obvious reasons. After doing some research I have found the following action shown below, but this is for the proceed to checkout button, I am looking to interact with the proceed to PayPal button. I am fluent in PHP but not the best with WordPress development. I would think this is a popular issue since majority of franchises would deal with such a scenario, but I am unpleasantly surprised on the amount of information regarding this topic. If someone could point me in the right direction of conquering this task it would be greatly appreciated!
remove_action('woocommerce_proceed_to_checkout','woocommerce_button_proceed_to_checkout', 20);
add_action('woocommerce_proceed_to_checkout', 'change_url_to_checkout', 20);
function change_url_to_checkout(){
$extra_url = 'put_your_extra_page_url_here';
?>
<?php _e( 'Proceed to Checkout', 'woocommerce' ); ?>
<?php
}

I can see two functions to be written here.
1. To alter the order data when an order is created. This is where we save the email needed.
add_action( 'woocommerce_checkout_update_order_meta', 'woocommerce_checkout_update_order_meta' );
function woocommerce_checkout_update_order_meta( $order_id ) {
$email = 'paypal#location1.com';
// do something here as to use the right email.
// you have $order_id.
// can be used as:
// $order = wc_get_order( $order_id );
// $order->get_billing_address_1() to get the address to check order address.
// or use $_POST['location'] if ever you posted some data.
update_post_meta( $order_id, '_alternative_paypal_email', $email );
}
2. Then use woocommerce_paypal_args to alter the args that is being passed to paypal.
add_filter( 'woocommerce_paypal_args', 'woocommerce_paypal_args', 10, 2 );
function woocommerce_paypal_args( $paypal_args, $order ) {
$email = get_post_meta( $order->get_id(), '_alternative_paypal_email', true );
if ( !empty( $email ) ) {
$paypal_args['business'] = $email;
}
return $paypal_args;
}
To summarize, this is just an example. But these two hooks is enough to get what you need.

Related

Add custom fields to Stripe checkout information and send via webhook

I am using wordpress to build a website that uses Stripe as its payment gateway.
Through the Paid Membership Pro plugin I have configured my Stripe connection.
The issue I am faced with is that I need to append a custom field, in this case a unique identifier for the customer, to the payment information for it to be available to send via my webhook to my server for processing.
I have come across a load of answers but none seem to be doing exactly what I am looking for.
I noticed in the PMPro plugin it allows you to add User Fields which I presumed would be a way to add custom data to the information but after checking the JSON payloads in Stripe none of the user field information is available.
I then tried adding the code from this answer to my functions.php file in word press just using a test meta key but again this information was not available in the payloads.
I am not using woocommerce.
How can I achieve this?
So I was able to crack this using a php script that intercepts the Stripe checkout event.
I added this as a snippet to my Wordpress site and to read in a custom field from the post submit.
Stripe allows you to add custom filed data to the metadata block and once populated this was successfully sent to my webhook.
function my_pmpro_stripe_params_send_user_id( $params, $order = null ) {
global $my_pmpro_checkout_order;
if ( empty( $params['metadata'] ) ) {
$params['metadata'] = array();
}
if ( empty ( $order ) ) {
// Save order while creating payment intent.
$order = $my_pmpro_checkout_order;
} else {
// Use saved order while creating subscription.
$my_pmpro_checkout_order = $order;
}
$params['metadata']['my_custom_field'] = $_POST['my_custom_value'];
return $params;
}
add_filter( 'pmpro_stripe_payment_intent_params', 'my_pmpro_stripe_params_send_user_id', 10, 2 );
add_filter( 'pmpro_stripe_create_subscription_array', 'my_pmpro_stripe_params_send_user_id', 10, 1 );

woocommerce Client city to be sent on ‘new order’ email

We get constant fake orders from our competition, we need to see the real city behind the IP the client placed the order, so we would like to see some field called ‘real city’ on the email that we received on each order. Until now we managed to get the IP by adding this line on function.php but its time consuming to open browser and manually search the city to see if match the client order city. As you may notice we added the real city line but its only extracting what the client selects so its not good, could I get the city name based on IP ? Thank you !
function send_customer_city( $order, $sent_to_admin, $plain_text, $email ){
if( ‘new_order’ == $email->id ){
echo ‘<br>
<p>‘.__(‘Client IP’).’: ‘. get_post_meta( $order->id, ‘_customer_ip_address’, true ).'</p>
<p>‘.__(‘Real City’).’: ‘. get_post_meta( $order->get_id(), ‘_billing_city’, true ).'</p>’;
}
}
In place of doing this You can do one thing
You can place a hidden filed on the checkout form and set the city according to IP/LAT-LONG
using any API. using woocommerce hooks woocommerce_after_checkout_billing_form
AT the time of placing an order You can get this filed data as well to check that Is This Real order Or fake?
OR
You can also check this before placing an order to avoid fake orders creations using woocommerce_review_order_before_submit or any other hook

Add custom checkout field as Order custom-meta data in Woocommerce 3

before WooCommerce 3.0 came out my code had worked like a charm to save custom values from the cart into the order on checkout. But since then I'm not able to create custom meta for orders.
Environment: Wordpress 4.9.4 & WooCommerce 3.3.3
Hooks
add_action('woocommerce_checkout_update_order_meta', 'custom_meta_to_order', 20, 1);
add_action('woocommerce_checkout_create_order', 'custom_meta_to_order', 20, 1);
The Hook number 1 is the one I tried the most, the 2 one was just an experiment with some literal changes mentioned in this topic.
Function
The following functions-code is related to hook number 1:
if (!function_exists('custom_meta_to_order')) {
function custom_meta_to_order($order_id, $values) {
$order = wc_get_order( $order_id );
$order->update_meta_data('_TESTKEYstart', 'Hello');
if (isset($values['myValue'])) {
$myValue = $values['myValue'];
if (!empty($myValue)) $order->update_meta_data('_myKey', $myValue);
}
$order->update_meta_data('_TESTKEYend', 'Bye');
$order->save();
}
}
I've checked also in the mySQL table table wp_woocommerce_order_itemmeta if at least the two _TESTKEY*-meta-entrys will be created (because they don't have a condition).
But it seems that the meta-keys and values don't getting created via this hook and function.
The function itself getting called, so at least the hooks itselfs are working.
So my question is: "What am I doing wrong?"
UPDATED: There is some errors in your code…
Both hooks have only 1 argument (not 2, so $values doesn't exist)
To get your custom field you should use $_POST['myValue'] instead.
and other things like each hook has a different argument:
$order_id for woocommerce_checkout_update_order_meta
$order for woocommerce_checkout_create_order
Below I have replaced $_POST['myValue'] by $_POST['billing_country'] as you don't give the code for this custom checkout field…
So here are both ways:
1) The best way for me, as explained here:
if ( ! function_exists('custom_meta_to_order') ) {
add_action( 'woocommerce_checkout_create_order', 'custom_meta_to_order', 20, 1 );
function custom_meta_to_order( $order ) {
$order->update_meta_data('_TESTKEYstart', 'Hello');
if (isset($_POST['billing_country'])) {
$myValue = $_POST['billing_country'];
if (!empty($myValue)) $order->update_meta_data('_my_key', $myValue);
}
$order->update_meta_data('_TESTKEYend', 'Bye');
}
}
Code goes in function.php file of your active child theme (or theme). Tested and works.
2) The other way:
if ( ! function_exists('custom_meta_to_order') ) {
add_action('woocommerce_checkout_update_order_meta', 'custom_meta_to_order', 20, 1);
function custom_meta_to_order( $order_id ) {
// get an instance of the WC_Order object
$order = wc_get_order( $order_id );
$order->update_meta_data('_TESTKEYstart', 'Hello');
if (isset($_POST['billing_country'])) {
$myValue = $_POST['billing_country'];
if (!empty($myValue)) $order->update_meta_data('_my_key', $myValue);
}
$order->update_meta_data('_TESTKEYend', 'Bye');
// Save the order data and meta data
$order->save();
}
}
Code goes in function.php file of your active child theme (or theme). Tested and works.
The proof:
And (in database wp_postmeta table for this order ID):
Tested in WooCommerce version 3.3+
You can use the old way too (which works):
if ( ! function_exists('custom_meta_to_order') ) {
add_action('woocommerce_checkout_update_order_meta', 'custom_meta_to_order', 20, 1);
function custom_meta_to_order( $order_id ) {
update_post_meta( $order_id, '_TESTKEYstart', 'Hello' );
if ( isset( $_POST['billing_country'] ) ) {
$myValue = $_POST['billing_country'];
if (!empty($myValue))
update_post_meta( $order_id, '_my_key', $myValue);
}
update_post_meta( $order_id, '_TESTKEYend', 'Bye');
}
}
Code goes in function.php file of your active child theme (or theme). Tested and works.
Related: Add extra meta for orders in Woocommerce
Because comments are really hard to read (because of to much restricted formatation), this answer is just a response to the answer from LoicTheAztec.
I wrote a longer answer but it seems gone, so I sorry now for the much shorter one!
First our misunderstanding
You understood that I would like to use custom values from products but in my case it was a little bit other. I wrote an external application which included the wp-load.php and posted then data back to the product-page into the cart.
So the problem showed up here was the attempt to write the data from the cart into the order on checkout.
Recommend ways doesn't worked at first
The recommend ways you suggested all doesn't worked. I also stripped them so much down that they have should work and just write something into the meta. I've no clue which plugin/theme-function pranked me this time here.
But I was able to solve the problem
And many more! Just because I found the blog-post where I found out in the past, how to do this and as addition to my personal luck the author wrote already the changes for WP3.0, related to this process.
Still your post helped me
The errors you showed me bugged me since then and because it was hard to follow and inspect everything with Sublime and CodeIntel (and my start with Symfony itself) I decided to buy PHPStorm which showed and allowed me to fix all of my deprecated (legacy-using) functions by updating them properly.
( Finally no more global-variables: Yay. )
I mean, showing up parameters inline and deprecation-strokes already did a great job. But a bug-free working code-intel/reference which doesn't dies on big projects is just awesome.
That's why I marked your answer now as solution, thanks. Otherwise I would have just fixed the problem maybe (thanks to the authors blog-post) but still would sit on a ticking time bomb.

WooCommerce add_to_cart metadata not sticking

I am a WP noob but very comfortable in PHP.
I am working with a client and we have built a product customization tool as an Angular.js single page application. When the product is finished being customized we are seeking to inject it into a WooCommerce cart so the client can check out. To do this we are $_POSTing the data to a PHP file in the root directory of the WP install. The code to catch it looks like:
require_once('./wp-load.php' );
global $woocommerce;
$woocommerce->session->set_customer_session_cookie(true);
$woocommerce->cart->empty_cart();
$id_arr = $_GET['productID'];
$pdfName = $_GET['pdfName'];
for($i=0; $i<count($id_arr); $i++){
$id = $id_arr[$i];
if ($id==0) continue;
if ($i==0){
$ret = $woocommerce->cart->add_to_cart($id, 1, '', '', array('pdfName'=>$pdfName));
}else{
$ret = $woocommerce->cart->add_to_cart($id);
}
}
wp_redirect(site_url().'/cart/');
The products are all correctly added to the cart but after checkout there is no sign of the metadata. After extensive research, I have found an article here: https://wpml.org/forums/topic/woocommerce-add-to-cart-does-not-work-with-wpml-activated/ that shows me that plugins can cause this behavior. So I have two specific questions?
Does my code make sense, am I creating the metadata array correctly?
Do I need to create something in WooCommerce called pdfName before I can do this?
Is there another way that metadata can be added to an order in
WooCommerce that may work around this problem?
It looks like you are adding the metadata correctly. However, as soon as you refresh, WooCommerce re-creates the cart data. Therefore you have to tell WooCommerce to maintain the metadata when it is pulling the cart from the stored session. Well, at least that is my understanding of it. So I think you need to filter thee $cart_item as it is run through the woocommerce_get_cart_item_from_session filter:
add_filter( 'woocommerce_get_cart_item_from_session', 'so_29660316_get_cart_item_from_session', 11, 2 );
function so_29660316_get_cart_item_from_session( $cart_item, $values ) {
if ( isset( $values['pdfName'] ) ) {
$cart_item['pdfName'] = $values['pdfName'];
}
return $cart_item;
}

Wordpress WooCommerce - Adding Order Details in Email

I am trying to customize the "Order Complete" email. Specifically, I have some products (software) that require license keys. So far, I've finished my algorithm for generating and storing the license keys (as well as verification) in a database.
In my child theme, under /woocommerce/order/order-details.php, I've added the corresponding code to add the license keys to the database. I don't want to display them on the order-details page, because the user could close this webpage and then lose the keys. So, I want to send them in an email (or display the keys in both the email and the order-details page). I want to use the "Order-Completed" email, because I don't want to send multiple emails.
I figured out how to add on to the order-details.php template because there was the pre-existing WC_ORDER instance: $order = new WC_Order( $order_id ). After that, I just looked through the documentation to find the correct methods that I needed, and I came up with this:
foreach( $order->get_items() as $item ) {
$_product = apply_filters( 'woocommerce_order_item_product', $order->get_product_from_item( $item ), $item );
$item_meta = new WC_Order_Item_Meta( $item['item_meta'] );
?>
// some code that was already included
if ( $_product && $_product->exists() && $_product->is_downloadable() && $order->is_download_permitted() ) {
if ($_product->get_attribute('needs_license_key') == "True") { // custom attribute for my software
// generate and store license keys
I only had to add in the if ($_product->get_attribute('needs_license_key')... part, so it was not very complex.
However, this is not present in the Order-Completed template, so I'm not sure where this goes. I'd need to iterate through all the products, check if they are downloadable (I have the code for that already), and then locate the product keys (I know how to do that as well). My main question is: How do I find out what order number the email is being sent for, as well as other stats for that order (such as products listed and their attributes, so I can iterate over them as seen above)? I'm not sure how to do this exactly with WooCommerce.

Categories