PayPal WooCommerce - payment_complete hook to capture email used - php

I'm having an issue that's driving me absolutely insane with the payment complete hook because it works perfectly with the PayPal Sandbox, but not when I go live.
I require all new customers to verify the PayPal email used with their first purchase. I believe the problem I'm having is that the hook and function is firing off before WordPress has written the paypal email to the post meta.
I can't post the whole function, but here's what's relevant:
add_action('woocommerce_payment_complete', 'preapproved_api_order', 10, 1);
function preapproved_api_order($order_id){
if ( ! empty( $gateway->id ) && 'paypal' == $gateway->id ) {
$order = new WC_Order( $order_id );
$user_id = $order->get_user_id();
$gateway = wc_get_payment_gateway_by_order( $order );
$paypal_email = get_post_meta( $order_id, 'Payer PayPal address', true );
$error = 'paypal email used for payment '.$paypal_email;
send_test_mail($error);
}
I added some quick error checking and that email does get sent without an email address included, which is why I'm thinking WP hasn't written the email address to the post meta.
If anyone can think of an alternative way to get the paypal email address so that it works with this hook it would be greatly appreciated. Very strange that it works in the sandbox and not live, I'm not sure what can be causing the delay. Thanks in advance.

I couldn't figure out what was causing the delay posting to the post_meta, but I did find the IPN hook that captures all the order and payment details being sent back from PayPal. Just an alternative way for a payment complete hook for PayPal in WooCommerce. Hopefully it helps others experiencing the same issue:
add_action('valid-paypal-standard-ipn-request', 'preapproved_api_order', 10, 1);
function preapproved_api_order($details){
global $woocommerce, $wpdb;
$order_id = $details['item_number1'];
$order = new WC_Order( $order_id );
}

Related

Use user phone number as auto generated password

I want a code that the password generated by woocommerce will be taken from the phone field on the checkout page when the user fills in the details for the billing
I tried the following code and it did not work
I would love a code that works. thanks.
<?php
//Use user phone number as auto-generated password
function wcs_filter_password_phone_number( $args ) {
$args['user_pass'] = $args['dbem_phone'];
return $args;
}
add_filter( 'woocommerce_new_customer_data', 'wcs_filter_password_phone_number' );
It's not really secure setting the password based on the customer's phone number. Anyone could find a way in to be honest.
Having said that, the task is interesting, and based on WooCommerce: Update Order Field Value After a Successful Order it is possible indeed to alter an order/user field after a successful checkout.
You could hook into "woocommerce_thankyou" as per the article, or even into "woocommerce_payment_complete" if you wanted to do that in the background and only for paid/completed orders.
Also, you should look into https://developer.wordpress.org/reference/functions/wp_set_password/ which is the WP function to set a new password programmatically.
Here's my attempt:
add_action( 'woocommerce_thankyou', 'bbloomer_alter_password_after_order' );
function bbloomer_alter_password_after_order( $order_id ) {
$order = wc_get_order( $order_id );
$phone = $order->get_billing_phone();
$user_id = $order->get_user_id();
if ( $phone && $user_id ) {
wp_set_password( $phone, $user_id );
}
}

Change Woocommerce checkout end points to show order summary details

I have a woocommerce website & using PayU payment system. As of now when customer order fails, then the redirection is happening to order-pay endpoint & when order is success, page is redirecting to order-received endpoint. I need customer to redirect to a specific custom url when order fails and for success order, instead of redirecting to order-received endpoint, I would like to show the order summary details & prevent user from redirecting to home page.
I tried the below in functions.php
add_action( 'woocommerce_thankyou', 'test_func');
function test_func( $order_id ) {
$order = wc_get_order( $order_id );
$url1 = 'https://yoursite.com/custom-url-1';
$url2 = 'https://yoursite.com/custom-url-2';
if ( ! $order->has_status( 'failed' ) ) {
wp_safe_redirect( $url1 );
exit;
} else {
wp_safe_redirect( $url2 );
exit;
}
}
But still it is redirecting to the checkout end points mentioned.
I know that it is taking from the woocommerce checkout endpoints mentioned in the Advance Section, but can somebody please help me to find a workaround for this?
Any help would be really appreciated.
Thanks in Advance.
I have prepared a solution for your problem. I have tested your code and it looks like woocommerce has changed something or I don't know and this kind of code is not working anymore. But no worries. I have searched over the internet and found a good solution for you which I have prepared and tested on my staging website and it works great.
You need to use template_redirect and set it for checkout endpoint url (your case - order-received). Then you need to do the rest with the right functionality to make it work as you expect. Put my code bellow into the functions.php file of your theme and your problem should be solved. Do not forget to change endpoint url with the endpoint url of your website (order-received) and then change the url for failed order status (google.com) and other statuses (yahoo.com)
add_action( 'template_redirect', 'wc_thank_you_redirect' );
function wc_thank_you_redirect(){
if( isset( $_GET['key'] ) && is_wc_endpoint_url( 'order-received' ) ) { //change order-received to your endpoint if you will change it in the future
$order_id = wc_get_order_id_by_order_key( $_GET['key'] );
if ( ! empty( $order_id ) ) {
$order = wc_get_order( $order_id );
$order_status = $order->get_status();
if ('failed' == $order_status ) { //failed order status
wp_redirect( 'https://google.com' ); //change url here
exit;
} else {
wp_redirect( 'https://yahoo.com' ); //change url here for other statuses redirect
exit;
}
}
}
}
To do this with order-pay you could easily modify my function and change your endpoint url to order-pay and remove else from the function. To display order summary you need to set template for your new URL. Maybe it is better to redirect only failed orders and modify existing woocommerce template for your thank you page.

Add custom script in woocommerce refund hook

I'm trying to execute a tracking script every time a refund gets processed in woocommerce but for some reason it's not working.
add_action( 'woocommerce_order_refunded', 'custom_order_refunded', 10, 2 );
function custom_order_refunded( $order_id, $refund_id ) {
if ( $order_id > 0 ) {
$order = wc_get_order( $order_id );
$order_number = $order->get_id();?>
<script>
gtag('event', 'refund', { "transaction_id": <?php echo $order_number;?> });
</script>
<?
}
}
I tried executing it with a static value instead of the $order_number variable to see if it was running and nothing... I'm lost
Might be a little late to answer this question, but...
You are adding javascript to an action that is only executed in the back-end of PHP and not on a page like the thankyou page.
For Google Analytics to work you need to add your script to a page where the customer can refund their order on the front-end. So for example on their account page.
Here is a nice explanation of creating a refund page in WooCommerce on which you can add your Google Analytics script: https://jilt.com/blog/add-refund-requests-woocommerce-customers/

WooCommerce Paypal Standard Gateway - IPN Received but order status stuck on 'processing'

I have a Wordpress setup with WooCommerce using the standard Paypal Gateway. Payments are being received and going through fine. Paypal IPN is being received by the site and marked as "Completed" for an order, but the order status remains unchanged in WooCommerce and still reads as "Processing".
10-04-2016 # 11:04:18 - Received valid response from PayPal
10-04-2016 # 11:04:18 - Found order #1303
10-04-2016 # 11:04:18 - Payment status: completed
Other things entered into Paypal gateway settings:
Paypal API Details
Paypal Identity Token
Clients Paypal login email as the receiver email and paypal email
Payment set to capture
Paypal Return URL:
http://[URL]/checkout/order-received/
Paypal Notification URL:
http://[URL]/?wc-api=WC_Gateway_Paypal
Other Related Woo Plugins installed:
https://woocommerce.com/products/woocommerce-bookings/
https://woocommerce.com/products/smart-coupons/
I'm a little stumped as what else to try, as the IPN is obviously being recieved but for whatever reason the WooCommerce is not updating the order status with this information. There are some PHP Notices regarding unrelated points in other templates but not anything that should be interfering with WooCommerce. Any help or ideas to try would be much appreciated!
I was having the same issue and discovered this is probably normal for WooCommerce since the product is supposed to be shipped out and then set to Completed. You can use a plugin to autocomplete the orders.
WooCommerce Autocomplete Orders
https://wordpress.org/plugins/woocommerce-autocomplete-order/
How To Automatically Set WooCommerce PayPal Orders as Completed
http://biostall.com/how-to-automatically-set-woocommerce-paypal-orders-as-completed/
Note: You have to make sure your product is Virtual and set the Mode to "Paid orders of virtual products only" under WooCommerce > Settings > Extra Options
Thanks for the reply, I did see the auto complete plugin but the client In hand required this to be a manual method. I managed to figure out a method that works for Paypal standard payment, based off the below resource:
http://codecharismatic.com/run-your-own-damn-code-after-paypal-calls-woocommerce-back/
<?php
/**
* Auto Complete Woocommerce 'processing' orders
*/
add_action( 'valid-paypal-standard-ipn-request', 'handle_paypal_ipn_response', 50, 1 );
function handle_paypal_ipn_response( $formdata ) {
if ( !empty( $formdata['invoice'] ) && !empty( $formdata['custom'] ) ) {
if( $formdata['payment_status'] == 'Completed' ) {
// decode data
$order_data = json_decode($formdata['custom'], true);
// get order
$order_id = ($order_data) ? $order_data['order_id'] : '';
$order = new WC_Order( $order_id );
// got something to work with?
if ( $order ) {
if ($order->post->post_status == 'wc-processing'){
// Status success
WC_Gateway_Paypal::log( 'Changing order #' . $order->id . ' status from processing to completed');
$order->update_status( 'completed' );
} else {
// Status fail
WC_Gateway_Paypal::log( 'Status fail, order #' . $order->id . ' status is set to ' . $order->post->post_status . ', not processing');
}
} else {
// Order fail
WC_Gateway_Paypal::log( 'Fail, no order found');
}
} else {
// Payment fail
WC_Gateway_Paypal::log( 'Payment status fail, not completed');
}
}
}

Woocommerce Gateway Integration Payment Status not updating

I have set up a custom Woocommerce off-side payment gateway, the communication from my website to the Gateway works fine. The user gets redirected to the gateway and after the payment he gets returned to the (by Woocommerce) defined return URL.
In the API documentation of the gateway, it says that the payment gateway will add a query string variable to the return url. This variable can have the following values:
response=approved
response=declined
response=error
In the documentation is this exampple:
If backURL = http://www.test.com/return.asp
Then the response will be http://www.test.com/return.asp?response=approved
To process the order I have created the code below (first just for the state of response=approved)
However, the order status does not get updated, when I test it. I hope somebody can point me in the right direction to find the error.
On top of the gateway I have extended query_vars with:
function add_query_vars_filter( $vars ){
$vars[] = "response";
return $vars;
}
add_filter( 'query_vars', 'add_query_vars_filter' );
After sending the user to the gateway I have this function to handle and process the query string in the return URL:
function check_example_response(){
global $woocommerce;
$transaction_id = get_query_var( 'response' );
$order = new WC_Order( $order_id );
// check if payment was successful
if ($transaction_id == 'approved') {
//Update order status
$order->update_status( 'processing', 'Payment received, your order is currently being processed.' );
//Add admin order noote
$order->add_order_note('Payment Via Example Gateway<br />Transaction ID: '.$order);
//Add customer order note
$order->add_order_note('Payment Received.<br />Your order is currently being processed.<br />We will be shipping your order to you soon.<br />Transaction ID: '.$order, 1);
$message = 'Thank you for shopping with us.<br />Your transaction was successful, payment was received.<br />Your order is currently being processed.';
$message_type = 'success';
}
// Reduce stock levels
$order->reduce_order_stock();
// Empty cart
WC()->cart->empty_cart();
}}
I have also registered this function with:
add_action( 'woocommerce_api_wc_example', array( $this, 'check_example_response' ) );
Wordpress also does not give any hints in DEBUG mode, so I am right now quite frustrated and hope somebody can help me.
Thank you!

Categories