1

In PayPal standard gateway of Woocommerce, I want to make Woocommerce sends only "order number" as the only item in the cart, instead of the itemized product list.

For that, I tried to edit the class which is responsible for making a PayPal request here: woocommerce/includes/gateways/paypal/includes/class-wc-gateway-paypal-request.php

I tried to edit get_order_item_names() function to return "invoice" . $order->get_order_number() as the name of the only item, but it wasn't successful since if there would be several items, Only the first one was returned with the order number, and other items remained.

Also, I nailed the add_line_item() function because to approach the purpose, practically there should be only "item_name_1" with the amount of total amount of the card.

$this->line_items[ 'item_name_' . $index ]   = $this->limit_length( $item['item_name'], 127 );
$this->line_items[ 'quantity_' . $index ]    = $item['quantity'];
$this->line_items[ 'amount_' . $index ]      = $item['amount'];
$this->line_items[ 'item_number_' . $index ] = $this->limit_length( $item['item_number'], 127 );

No success here too.

I'd appreciate your assistance.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
DummyBeginner
  • 411
  • 10
  • 34

2 Answers2

4

Recommendation: You should really avoid overriding woocommerce core files.

Instead you could use in this particular case the filter hook woocommerce_paypal_args, where you will be able to manipulate the arguments that are used in get_request_url() function (that will get the PayPal request URL for an order).

1) TESTING AND GETTING THE DATA SENT

Just to register and get the arguments sent to paypal, I have used the hook this way:

add_filter('woocommerce_paypal_args', 'custom_paypal_args', 10, 2 );
function custom_paypal_args ( $args, $order ) {
    // Saving the data to order meta data (custom field)
    update_post_meta( $order->get_id(), '_test_paypal', $args );
    return $args;
}

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

Now I can get the data simply using this (setting the correct order ID):

$order_id = 648;
$data_sent_to_paypal = get_post_meta( $order_id, '_test_paypal' );
echo '<pre>'; print_r( $data_sent_to_paypal ); echo '</pre>'; 

Or in a hook ( visible in shop pages in this example only for admins ):

// Only visible on shop pages by admins
add_action( 'woocommerce_before_main_content', function(){
    // Only visible by admins
    if( ! current_user_can( 'manage_options' ) ) return;

    $order_id = 648;
    $data_sent_to_paypal = get_post_meta( $order_id, '_test_paypal' );
    echo '<pre>'; print_r( $data_sent_to_paypal ); echo '</pre>';
}, 10, 0 );

This gives me an output like that (for 2 products and different quantities):

Array
(
    [0] => Array
    (
        [cmd] => _cart
        [business] => email@example.com
        [no_note] => 1
        [currency_code] => EUR
        [charset] => utf-8
        [rm] => 2
        [upload] => 1
        [return] => https://example.com/checkout/order-received/8877?key=wc_order_55445ndfgbulfdf&utm_nooverride=1
        [cancel_return] => https://example.com/cart/?cancel_order=true&order=wc_order_55445ndfgbulfdf&order_id=8877&redirect&_wpnonce=34m7kl83455
        [page_style] => 
        [image_url] => https://example.com/wp-content/uploads/2012/06/logo.png
        [paymentaction] => sale
        [bn] => WooThemes_Cart
        [invoice] => pp-8877
        [custom] => {"order_id":8877,"order_key":"wc_order_55445ndfgbulfdf"}
        [notify_url] => https://example.com/wc-api/WC_Gateway_Paypal/
        [first_name] => John
        [last_name] => Doe
        [address1] => Test st.
        [address2] => 
        [city] => wef
        [state] => AR
        [zip] => 43242
        [country] => US
        [email] => myemail@example.com
        [night_phone_a] => 078
        [night_phone_b] => 653
        [night_phone_c] => 6216
        [no_shipping] => 1
        [tax_cart] => 16.55
        [item_name_1] => Test Product - Service
        [quantity_1] => 1
        [amount_1] => 71
        [item_number_1] => 
        [item_name_2] => Test Product 1
        [quantity_2] => 1
        [amount_2] => 66
        [item_number_2] => 
        [item_name_3] => Test Product 2
        [quantity_3] => 1
        [amount_3] => 120
        [item_number_3] => 
        [item_name_4] => Test Product 3
        [quantity_4] => 1
        [amount_4] => 45
        [item_number_4] => 
    )

)

As you can see now, with woocommerce_paypal_args you will be able to alter or remove any arguments.

There is always only one: 'item_name_1', 'quantity_1', 'amount_1' and 'item_number_1' with always index 1 sent to paypal.


2 MANIPULATING THE DATA SENT (example):

We can still use woocommerce_paypal_args, filter hook for example on 'item_name_1' key, to replace the items names by the order number, just as you want:

add_filter('woocommerce_paypal_args', 'custom_paypal_args', 10, 2 );
function custom_paypal_args ( $args, $order ) {
    $$args_keys = array_keys($args);
    $i = 0;
    // Iterating through order items
    foreach( $order->get_items() as $item_id => $item_product ){
        $i++; // updating count.
        if( ! empty($args["item_name_$i"]) ){
            // Returning the order invoice in the item name
            $args["item_name_$i"] = "invoice #" . $order->get_id();
        }
    }
    return $args;
}

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

The code is tested and works on WooCommerce 3+

To finish: As you get the WC_Order object as argument in your hooked function, you can use it to get any data from the order, and manipulate as you like the data sent to paypal gateway.

See this related answer: How to get WooCommerce order details

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • Thanks Dear Loic, About manipulating the `$args`, it's needed to remove all other items in the card after the first item. Also, set the price of the first item equal to the whole price of the cart (because there's only one single item). So this is the edited custom function. you could add that in your answer: [***Custom function to modify `$args`***](https://paste.ubuntu.com/25567534/) – DummyBeginner Sep 18 '17 at 19:39
  • **1.** Where did you run the code above (in **testing section**) that gave you the array? Which file inside WordPress/Woocommerce could I place the code to retrieve post_meta and print that array you've shown? **2.** If there wasn't `woocommerce_paypal_args` filter hook, How could we override the `get_request_url()` in our written plugin or theme's function.php? My question is general for overriding a function of any plugin, in our custom plugin or theme's function.php – DummyBeginner Sep 18 '17 at 19:58
  • Thanks, About the answer **2** : I wanted to know how to override a function in a plugin (e.g woocommerce) if there wasn't a hook available. How could we override the function and change its functionality without changing the core of the plugin which will be lost after a plugin update? ... About the answer **3** : When I have more than one item in the cart, there would be also _item_name_2_, _item_name_3_, _item_name_4_ ... . Woocommerce Version : `3.1.2` – DummyBeginner Sep 18 '17 at 20:24
  • I have updated the answer regarding (point 1) … **2.** There is always a hook or a trick to do to override everything. For third party plugins that are closed, that is another thing. Additionally, you can extend classes … **3.** The names are added in the same string, and the amounts are summed and the index is always `1` … It doesn't send each items, but merged items data. You will see … test it. – LoicTheAztec Sep 18 '17 at 20:38
  • Thanks. About the item with index `1` that includes the summed price of the order, It isn't the case for me. I tested that with an order had 4 items, and saved the arguments in the post_meta (the procedure you gave for testing in your answer); this is the output with four items which have up to index `4`: **https://paste.ubuntu.com/25568072/** and each item has its particular price. ... Another thing is, in the latest version of Woocommerce, there's a `- Service` keyword added at the end of my product. what's the matter? – DummyBeginner Sep 18 '17 at 21:16
  • @DummyBeginner I have updated my code… So now this will work correctly anyway, taking in account if there is many order items in the arguments sent to Paypal. You should add your final code at the end of your answer (as an edit). To finish I have replaced the array by yours in my answer… – LoicTheAztec Sep 18 '17 at 22:29
  • @LoicTheAztec I have implemented the 2 MANIPULATING THE DATA SENT (example). It works good with simple orders but When I want to send the data of subscription items it is not changing the order/item names. Can you please help me for subscription item names to paypal? – Ali May 12 '20 at 10:06
-1

I'm using below function for getting Order ID, You can edit and use below function for your needs.

public function process_payment( $order_id ) {
    global $woocommerce;
    $order = new WC_Order( $order_id );
    return array(
        'result'  => 'success',
        'redirect' => $order->get_checkout_payment_url( true )
    );
Gokturk
  • 47
  • 1
  • 7
  • This response is completely useless: the problem is not how to get the order ID but how to pass the order ID instead of items to PayPal. – Mauro Mascia Jun 28 '18 at 15:49