We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x
Private

Wordpress - Javascript - JQuery - AJAX - PHP - need assitance with scripts

High Priority
18 Views
Last Modified: 2020-06-29
Need assistance pulling the whole user object from WordPress and also have a question about where I should put my last JavaScript for this process.
Comment
Watch Question

Netty AdminNetwork Administrator

Author

Commented:
Currently I have a script that is pulling particular user data from a WordPress user's profile with the following function

 
    function get_user_data() : array
{
    $user = wp_get_current_user();

    $data = [
        'UserId' => $user->ID,
        'Email' => $user->user_email,
        'Username' => $user->user_login,
    ];

    return $data;
}
Netty AdminNetwork Administrator

Author

Commented:
{

     "id": 438,

     "date_created": "2020-06-25T09:53:56",

     "date_created_gmt": "2020-06-25T13:53:56",

     "date_modified": "2020-06-25T09:53:56",

     "date_modified_gmt": "2020-06-25T13:53:56",

     "email": "testingwebhook@email.com",

     "first_name": "testing",

     "last_name": "newwebhookdata",

     "role": "subscriber",

     "username": "customer1593093203",

     "billing": {

         "first_name": "testing",

         "last_name": "newwebhookdata",

         "company": "",

         "address_1": "4015 Starfish Lane",

         "address_2": "",

         "city": "Tampa",

         "postcode": "33615",

         "country": "",

         "state": "Florida",

         "email": "testingwebhook@email.com",

         "phone": "(111) 444-7777"

     },

     "shipping": {

         "first_name": "",

         "last_name": "",

         "company": "",

         "address_1": "",

         "address_2": "",

         "city": "",

         "postcode": "",

         "country": "",

         "state": ""

     },

     "is_paying_customer": false,

     "avatar_url": "https://secure.gravatar.com/avatar/f2d79",

     "meta_data": [

         {

             "id": 19605,

             "key": "entry_id",

             "value": "1228"

         },

         {

             "id": 19606,

             "key": "_gform-entry-id",

             "value": "1228"

         },

         {

             "id": 19615,

             "key": "gfID",

             "value": "3"

         },

         {

             "id": 19616,

             "key": "ServiceRequested",

             "value": "Bundle"

         },

         {

             "id": 19617,

             "key": "twitter",

             "value": ""

         },

         {

             "id": 19618,

             "key": "facebook",

             "value": ""

         },

         {

             "id": 19619,

             "key": "linkedin",

             "value": ""

         },

         {

             "id": 19620,

             "key": "gplus",

             "value": ""

         },

         {

             "id": 19622,

             "key": "wc_last_active",

             "value": "1593043200"

         }

     ],

     "_links": {

         "self": [

             {

                 "href": "https://blabla/wp-json/wc/v3/customers/438"

             }

         ],

         "collection": [

             {

                 "href": "https://blabla.com//wp-json/wc/v3/customers"

             }

         ]

     }

 }


^^^This is all the data he wants and in JSON form
Netty AdminNetwork Administrator

Author

Commented:
or he specifically needs the following but would rather have it all if I can give it to him


  • firstname    
  • lastname    
  • billing address (just address, unless there is address_2 [ste.# apt.#], )    
  • zipcode


CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
Hi Netty,

That data looks like a WooCommerce Customer, not a WordPress User - they're 2 different objects.

And as for your Javascript, based on our previous conversations, it makes sense to put Javascript in your JS file (the one in your theme folder), and any PHP in your function.php file.
Netty AdminNetwork Administrator

Author

Commented:
Ok so put the final function that validates the iframe postmessages via the event listener in the same JScript file that I have in the child theme folder?
Netty AdminNetwork Administrator

Author

Commented:
Yes I meant the woocommerce customer data that is pulled with:
wp_get_current_user()
CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview
Netty AdminNetwork Administrator

Author

Commented:
Chris,

this is the listener we setup before. It does a couple other things that we need to validate and unhide the Place Order button, going to put it in the JScript file we put in the child theme


 window.addEventListener("message", (event) => {
    if (event.origin !== "https://api-east.pestpac.com")
        return;
  
    let ccInfo = JSON.parse(event.data)
    
 if (ccInfo.BillToID) {
 
    jQuery(document).ready(function($) {
    $('#cc_frame').hide().after(`<br><br><br><p>Credit Card Saved Successfully<br><br><br></p>`)
 $("#payment #place_order.button.alt").fadeIn('slow')
});
 
 } else if (ccInfo.Error) { 
 
  jQuery(document).ready(function($) {
    $('#cc_frame').hide().after(`<br><br><br><hr class="redrule"><p style="color:red">Credit card not saved. Blablabla.</p><hr class="redrule"><br><br><br>`)
 
});
  
 }
  
}, false);
Netty AdminNetwork Administrator

Author

Commented:
He is asking if I can send it all or if not send just
  • firstname    
  • lastname    
  • billing address (just address, unless there is address_2 [ste.# apt.#], )    
  • zipcode


It would be nice if I had the ability to do either in case he wants to switch back, vice versa
CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
Hi Netty,

For your listener, you'd want something like this:

/**
 * Listen for the window.message event
 */
$(window).on('message', function(e) {
    if (e.originalEvent.origin !== 'https://api-east.pestpac.com') return;

    let ccInfo = e.originalEvent.data

    if (ccInfo.BillToID) {
        $('#cc_frame').hide().after(`<br><br><br><p>Credit Card Saved Successfully<br><br><br></p>`)
        $("#payment #place_order.button.alt").fadeIn('slow')
    } else if (ccInfo.Error) {
        $('#cc_frame').hide().after(`<br><br><br><hr class="redrule"><p style="color:red">Credit card not saved. Blablabla.</p><hr class="redrule"><br><br><br>`)
    }
})

Open in new window

Because we're in jQuery here, you'll want to use originalEvent.data, rather than just event.data
CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
Hey Netty,

How you get your customer info will depend on how your site is setup. Judging by the data you posted earlier, you're dealing with registered customers here, so you can grab their details as long as they're logged into your site.

As for what data you want to send - I would highly recommend you only send the data that is needed for any given operation. The full JSON data you posted ealier contains a lot of information, and most of it is actually useless. If the endpoint just needs firstname, lastname and billing address (including zip code), then just send that. Have a look at this:

/**
 * Get the User data
 */
function get_user_data() : array
{
    $userId = get_current_user_id();
    $customer = new WC_Customer($userId);

    $data = [
        'FirstName' => $customer->get_first_name(),
        'LastName' => $customer->get_last_name(),
        'Billing' => $customer->get_billing(),
    ];

    return $data;
}

Open in new window

Netty AdminNetwork Administrator

Author

Commented:
is this line supposed to have a space because "new" is doing something or does it also need an underscore

$customer = new WC_Customer($userId);
CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
That's right as it is. In Object Oriented Programming, we instantiate a class by calling new ClassName(). WP_Customer is the class. The constructor for the class (the ctor) takes the ID as an argument, so we need:

new WC_Customer($userId);
Netty AdminNetwork Administrator

Author

Commented:
ok thank you for explaining it......I am still learning....hopefully by the next month or so I will understand the basics of programming language because I am watching videos and going to follow Harvard's online CS50 class as well so forgive me for not knowing how it works yet and I really appreciate the explanations.  
CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
No worries Netty - you're doing great. Stick at it - you'll have plenty of Eureka! moments where something that you've been struggling with will suddenly make perfect sense :)

To be fair - WordPress is not a great example to use when learning development - it does a lot of things in a really weird, non-standard way. As well as that, you're having to figure out programming in PHP (including some OOP) at the same time as learning Javascript, HTML and CSS, so it can be quite a challenge.
Netty AdminNetwork Administrator

Author

Commented:
for some reason the billing info comes back with nothing in the fields
Netty AdminNetwork Administrator

Author

Commented:
the current user works with wp though and gets the user info but not pulling the billing.
Netty AdminNetwork Administrator

Author

Commented:
all the billing fields come back but with no data in fields

Netty AdminNetwork Administrator

Author

Commented:


Netty AdminNetwork Administrator

Author

Commented:
this works with the top results
this gives the second result


Netty AdminNetwork Administrator

Author

Commented:
have it this way and still all the billing comes back with nothing in the fields


Netty AdminNetwork Administrator

Author

Commented:
this one works though


with this result:



Netty AdminNetwork Administrator

Author

Commented:
I tried replacing this

$userId = get_current_user_id();
with this

$userId = get_current_user();
Netty AdminNetwork Administrator

Author

Commented:
If I cannot figure this out soon then I am going to revert to the first solution that give this result and he is going to have to pull the rest of the needed data with another call on the backend because today is the deadline on this part and we are having a meeting about it soon....I haven't even got a valid test url to test the listener yet either so I am hoping the event listener will work as we have it


I really appreciate your help....lmk if there is a way we can figure out why the billing data is not getting pulled

Netty AdminNetwork Administrator

Author

Commented:
also, I had him put a test valid URL in the response and the event listener does not seem to be working
Netty AdminNetwork Administrator

Author

Commented:
you sure we would set ccInfo to e.originalEvent.data ??
 

We do not get that info back from the third party until after the CC in inputted. 
CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
OK.

Couple of points - if you're getting Cannot read property 'secureUrl' of undefined, then the Curl request is not returning any valid data. You'll need to log that and see what's coming back from your Curl request. I'm guessing something has changed, because you had this part working previously.

As for the WooCommerce customer data - are you using the standard WooCommerce checkout for this. The way it works is that a user registered on your site is logged in and they work there way through the WooCommerce checkout process. This creates a Customer record linked to their User account. By grabbing the UserId of the currently logged in user, we can use that to get at their Customer record. It seems from the data you're dumping that the User doesn't have a standard WooCommerce Customer record, which is why the data is coming back empty. If you're not using the standard WooCommerce process (or the currently logged in user is not the Customer, then you may need to grab the data from the user_meta instead, but that will depend on your setup.
CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
We do not get that info back from the third party until after the CC in inputted.  

Your event listener (message) is only set up to listen for the postMessage event which fires AFTER the CC info has been input, so I'm not sure what you're referring to here.
Netty AdminNetwork Administrator

Author

Commented:
Ok how would I get the zipcode from the user meta? and also the reason I was getting the "cannot read property" error was because he wasn't handing me the response the same way as before.....fixed that and now I have a manual test URL that we are using but the listener is not working and displaying the "Credit Card Saved Successfully" message or the "Credit card not saved" message
Netty AdminNetwork Administrator

Author

Commented:
as for now my concern is to get the listener working.. Any suggestions on how to debug this part or try something else
CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
Something else to check on - make sure you've removed the original event listener that you'd added in your snippets plugin. By putting it in the JS file, you should no longer include it in the snippets plugin
Netty AdminNetwork Administrator

Author

Commented:
yes it has been disabled from the snippets
CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
For debugging the event listener, just dump the response get and see what that contains:

/**
 * Listen for the window.message event
 */
$(window).on('message', function(e) {
    console.log("MESSAGE DATA", e)
    if (e.originalEvent.origin !== 'https://api-east.pestpac.com') return;

    ...
}

Open in new window

Look at your console and see what comes after the MESSAGE DATE bit.
CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
In particular, pay attention to either data.origin or originalEvent.origin and make sure the remote server URL hasn't change. If it's not exactly as your if() statement, then the function will just quit before handling the data.
Netty AdminNetwork Administrator

Author

Commented:
it is not logging anything for that

Netty AdminNetwork Administrator

Author

Commented:
anything wrong here

Netty AdminNetwork Administrator

Author

Commented:
jQuery( function( $ ) {
    $(document).ready( function() {

        /**
         * AJAX Call to grab the Order URL from the server via the custom url created in Azure logics
         */
        $( document.body ).on( "click", "#payment #get_cc_order_url.get_cc_order_url", function(e) {
            e.preventDefault();
            $.ajax({
                url  : ccOrderParams.url,
                data : {
                  action : 'get_order_url',
                  security : ccOrderParams.nonce,
               },
               type : 'post',
               }).done(function(response) {
                  $('#cc_card_iframe').prop('src', response.data.secureURL)
               }).fail(function(error) {
                  console.log("ERROR", error)
               })        
            });
    
            $(window).on('message', function(e) {
               if (e.originalEvent.origin !== 'https://api-east.pestpac.com') return;
               console.log("MESSAGE DATA", e)
               let ccInfo = e.originalEvent.data
           
               if (ccInfo.BillToID) {
                   $('#cc_card_iframe').hide().after(`<br><br><br><p>Credit Card Saved Successfully<br><br><br></p>`)
                   $("#payment #place_order.button.alt").fadeIn('slow')
               } else if (ccInfo.Error) {
                   $('#cc_card_iframe').hide().after(`<br><br><br><hr class="redrule"><p style="color:red">Credit card not saved. blabla.</p><hr class="redrule"><br><br><br>`)
               }
           })
    
    
    
         });
})



CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview
CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
And put your console.log BEFORE the if() statement. If for some reason the origin doesn't match, then you function will exit before ever running the consol.e.log() line so you'll be left with no output:

$(window).on('message', function(e) {
    // see what's coming in first!
    console.log("MESSAGE DATA", e)

    if (e.originalEvent.origin !== 'https://api-east.pestpac.com') return;

Open in new window

Netty AdminNetwork Administrator

Author

Commented:
ok also I need to add a third condition....when the link times out it displays this and this is what is shown...….does not appear to have a post message like the other events




Netty AdminNetwork Administrator

Author

Commented:
we do not need to addEventListener?



Netty AdminNetwork Administrator

Author

Commented:
I need to create that third condition as well.....now that the link is not giving me a postmessage event as I put above because it is timed out it looks much different......so this is def an issue for testing as of now, I am asking him for a new URL now

^^^this is why I am not getting anything in the console.log even before the "if" because this third condition seems not to give a postMessage like the other two conditions
CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
We are adding an Event Listener - we're just doing it the jQuery way:

$(window).on('message', function(e) {
    ...
})

Open in new window

When we originally discussed this, you said there was a message sent when the window timed out - if that doesn't happen then you can't use a listener - there's no event to listen to.
Netty AdminNetwork Administrator

Author

Commented:
ok I got it.....Ok its working now!!!
after I added antoher document ready and put the function under that it worked.


Now two final things......need to add the one more condition and also need to display a small spinning icon  a message that says" Retreiving Secure URL" for the time between when the button is clicked and the iframe is displayed
Netty AdminNetwork Administrator

Author

Commented:
And is there any way to get the zip code from the user meta?? I have been googling and can not seem to find it
CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
Right - you don't need a second document ready - you should ony have one, and both your functions go inside that:

jQuery( function( $ ) {
    $(document).ready( function() {

        /**
         * AJAX Call to grab the Order URL from the server via the custom url created in Azure logics
         */
        $( document.body ).on( "click", "#payment #get_cc_order_url.get_cc_order_url", function(e) {
            ...
        });


        /**
         * Message listener
         */
        $(window).on('message', function(e) {
            ...    
         });


    })
})

Open in new window

How you get the ZipCode will depend on how your data i sstored in the database. Like I said ealier, it seems that you're not using the standard WooCommerce customer process, so I don't know how you're storing that data. Generally, to get a Users meta data, you do this:

$data = get_user_meta( $userId, $key );

Open in new window

But you'd need to know the key (could be zipcode ???) . That is entirely dependent on your own system and how it's set up. I don't know that so I can't give you a specific answer on that.

As for the spinner - the jQuery AJAX method has an beforeSend property that allows you to run some code just before the AJAX call is made - that would be the best place to add some code to insert your spinner:

$.ajax({
    url  : ccOrderParams.url,
    type : 'post',
    data : {
        action: 'get_order_url',
        security: ccOrderParams.nonce,
    },
    beforeSend: function() {
        // add in your spinner and please wait code here
    },
}).done(function(response) {
    // hide your spinner and please wait message here
    $("#cc_card_iframe").prop('src', response.data.secureUrl)
}).fail(function(error) {
    console.log("ERROR", error)
})

Open in new window

Netty AdminNetwork Administrator

Author

Commented:
cool been trying to find out how to get the zip code......I am going to try this other code and get report back...much appreciated. 
Netty AdminNetwork Administrator

Author

Commented:
Success!
no need for the zip code anymore.....we got brand new URLs being returned every time now with the current config......only issue is for some odd reason when the postMessage gives the "Error" attribute for when the customer clicks cancel the "Credit Card Not Saved" message does not appear...…but when a card is entered correctly and postMessage has a "BillToID" attribute the script works fine and displays the "Credit Card Saved Successfully" message

^^^Will not display the Card not saved message

^^^^Does display the "Credit Card Saved Successfully" message correctly



This is really getting to me as it seems to be coded the same as the first message and it is listening for the same postMessage event
Netty AdminNetwork Administrator

Author

Commented:
Ok, I know why one was working and the other wasn't, It is because I had turned back on the snippet and only had one of the iframe ids changed to match the new id and that was the success message.....so it appears using the snippet works but the function inside the child theme jscript is not working at all.
Netty AdminNetwork Administrator

Author

Commented:
Got it working! I know you said that it should not need another jquery document ready but the only way that the console.log dumps data from the postMessage is only if I wrap the function in its own doc ready wrapper...
Netty AdminNetwork Administrator

Author

Commented:
also had to add the json parse

Netty AdminNetwork Administrator

Author

Commented:
All good on this!!! thank you. I am going to make a new question about the "message while waiting" and spinning icon.….
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a free trial preview!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.