Link to home
Start Free TrialLog in
Avatar of Netty Admin
Netty AdminFlag for United States of America

asked on

Wordpress - Javascript - JQuery - AJAX - Need assistance with creating error handling for a Jquery script

Need to add some error handling to the following set of functions:

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',
                beforeSend: function() {
                  //  spinner and please wait code here
                  let pleaseWait = `
                  <div id="pleasewait" style="text-align:center">
                      <br><br><p>Retrieving Secure Window</p>
                      <img src="path/to/gif" 
                      style="display:inline-block">
                  </div>
                  `
                  $('#cc_card_iframe').before(pleaseWait)
              },
               }).done(function(response) {
                  // remove the please wait message
                  $('#pleasewait').remove()
                  $('#cc_card_iframe').prop('src', response.data.secureURL)
               }).fail(function(error) {
                  console.log("ERROR", error)
               })        
            });
    });
})

Open in new window




/**
 * 
 * Validates if card is inputted and then displays success message and unhides the place order button and if the trasaction is canceled
 * Also if the trasaction is canceled it displays a Credit Card Not Saved message 
 */
jQuery( function( $ ) {
   $(document).ready( function() {

                  $(window).on('message', function(e) {
                   console.log("MESSAGE DATA", e)
                   if (e.originalEvent.origin !== "https://api-east.pestpac.com")
                   return;
                 
                   let ccInfo = JSON.parse(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><p>Credit Card Not Saved<br><br><br></p>`)
                     }
});

        });
})

Open in new window




this is the function.php file


<?php

/*

 * Custom PHP code for child theme will be here

 */













/**

 *  the AJAX handler

 */

add_action('wp_ajax_get_order_url', 'get_order_url');

function get_order_url()

{

    check_ajax_referer('security_matters', 'security');

    $user = get_user_data();

    $curl = curl_init();



    curl_setopt_array($curl, [

        CURLOPT_URL => 'azure_url',
        CURLOPT_TIMEOUT => 0,

        CURLOPT_RETURNTRANSFER => true,

        CURLOPT_POSTFIELDS => json_encode($user),

        CURLOPT_HTTPHEADER => ['Content-Type:application/json'],

    ]);



    $response = curl_exec($curl);



    if (!curl_errno($curl)) {

        wp_send_json_success(json_decode($response));

    } else {

        $response = ['error' => curl_error($curl)];

        wp_send_json_error($response);

    }

}





/**

 * Get the User data

 */

function get_user_data() : array

{

    $user = wp_get_current_user();



    $data = [

        'UserId' => $user->ID,

        'Email' => $user->user_email,

        'Username' => $user->user_login,

    ];



    return $data;

}







/*

 * Enqueue scripts for cc button on checkout page

 */







add_action( 'wp_enqueue_scripts', 'setup_order_scripts', 15 );



 function setup_order_scripts() {

    $params = [

        'url' => admin_url( 'admin-ajax.php' ),

        'nonce' => wp_create_nonce('security_matters'),

    ];



    wp_register_script( 'cc_order_scripts', get_stylesheet_directory_uri() . '/order-scripts.js', array('jquery'), null, true);

    wp_localize_script( 'cc_order_scripts', 'ccOrderParams', $params);

    wp_enqueue_script( 'cc_order_scripts' );

}











/** Adding child theme's style.css **/

function tm_fixology_child_style_css(){

	wp_enqueue_style( 'fixology-child-style', get_stylesheet_directory_uri() . '/style.css' );

}

add_action( 'wp_enqueue_scripts', 'tm_fixology_child_style_css', 18 );













// Disable auto-complete on form.

add_filter( 'gform_form_tag', function( $form_tag ) {

	return str_replace( '>', ' autocomplete="off">', $form_tag );

}, 11 );



// Diable auto-complete on each field.

add_filter( 'gform_field_content', function( $input ) {

	return preg_replace( '/<(input|textarea)/', '<${1} autocomplete="off" ', $input );

}, 11 );

Open in new window



The problem is that sometimes the response comes back with no secureURL property...At this moment I would like it to display a message that says "Please Try Again" so the user knows to click the button again


User generated imageAnnotation-2020-06-30-104947.png
Annotation-2020-06-30-105100.png
Annotation-2020-06-30-105257.png
Avatar of Netty Admin
Netty Admin
Flag of United States of America image

ASKER

I can also talk with my coworker and have him send me error codes, etc
^^^^^^updated the question ^^^^
Avatar of Chris Stanyon
Hey Netty,

You have a couple of options here, depending on what data does come back from the API call. My preference would be to handle the logic in the PHP file. If you look at that we have this:

if (!curl_errno($curl)) {
    wp_send_json_success(json_decode($response));
} else {
    $response = ['error' => curl_error($curl)];
    wp_send_json_error($response);
}

Open in new window

When call wp_send_json_success(), the AJAX response receives a success:true property. When we call wp_send_json_error(), the AJAX response receive a success:false property, so in your AJAX handler, you can do this:

}).done(function(response) {
    // remove the please wait message
    $('#pleasewait').remove()

    if (response.success) {
        // we have the secureUrl
        $('#cc_card_iframe').prop('src', response.data.secureURL)
    } else {
        // we don't have the secureUrl
        // code your error message here
    }
})

Open in new window

You now just need to add your logic into the PHP file to make sure you have actually received a secureUrl - if you have use wp_send_json_success(), if you haven't use wp_send_json_error().
Thank you Chris,

I put it in place but have not had it hit on it yet. Once I get an error and see the message display I will report back on here..
It does not seem to display the "Please Try Again" message when there is an error. I spoke with my coworker about it and he said he can have it send me a JSON response for all errors, we agreed on the JSON property {URL_error=""}......I do not know exactly how he is setting this to be the catch-all response for all errors but I think that is what he now has setup. Strange though, because even though there are times when I am not receiving the secureURL property it does not seem to display the message, unless he is still sending me that property and it is empty and that is why.

Now when he sends the URL_error it may indeed be empty in some cases but he says I will at least get that property back so maybe we could add a line or two to cover this condition as well.
So what we have already set up will cover instances when we do not get back a JSON success response from the request, which is great but now we want also include the condition when we do receive a response but instead of it being secureURL it will be URL_error    

And his script is coded to send back this URL_error to mine if his script gets either  200, 400, 500, etc. errors on his call for the URL
Also for the method you first suggested for the wp_send_json_error

Since we already are hiding the iframe before and/or it is not showed yet, I would need to create another element to select in order to display the message in the follow error you showed above,  where you have "code your message here" correct?


User generated image

Or can I still select the iframe and hide it even though it may have already been hidden, this could still work, right?
                  $('#cc_status_canceled').hide()
                  $('#cc_status_success').hide()
            
                  $('#cc_card_iframe').hide().before(pleaseWait)
              },
               }).done(function(response) {
                  // removes the please wait message
                  $('#pleasewait').remove()
                  console.log(response)
                  if (response.success) {
                    // we have a successful JSON response from the Azure Logic Script
                  $('#cc_card_iframe').prop('src', response.data.secureURL).show()
                  } else {
                    //  we do not have a successful JSON response from the Azure Logic Script
                    
                    $('#cc_card_iframe').hide().after('<br><br><p>Please Try Again</p>')


                  }



Open in new window

Or maybe it would be best to do it like this
if (response.data.secureURL) {
                 //we have a successful JSON Secure URL response from the Azure Logic Script
                  $('#cc_card_iframe').prop('src', response.data.secureURL).show()
                  } else if (response.data.URL_error){
                    //  we have as successful response from the Azure Logic Script but with an error message forwarded from the parent call to worldpay
                    
                    $('#cc_card_iframe').after('<br><br><p>Please Try Again</p>')
                } else {
                

                console.log("Error No JSON Data Returned")
$('#cc_card_iframe').after('<br><br><p>Please Try Again</p>')
                       }


Open in new window

And since the beforeSend function hides the iframe already I would  remove the .hide() from those lines like I did. ^^^This should accomplish my goals, correct?

ASKER CERTIFIED SOLUTION
Avatar of Chris Stanyon
Chris Stanyon
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hey Chris, thank you for responding, I updated the PHP file and
Its failing every time now.
User generated image
<?php

/*

 * Custom PHP code for child theme will be here

 */













/**

 *  the AJAX handler

 */

add_action('wp_ajax_get_order_url', 'get_order_url');

function get_order_url()

{

    check_ajax_referer('security_matters', 'security');

    $user = get_user_data();

    $curl = curl_init();



    curl_setopt_array($curl, [

        CURLOPT_URL => 'CustomURL',

        CURLOPT_TIMEOUT => 0,

        CURLOPT_RETURNTRANSFER => true,

        CURLOPT_POSTFIELDS => json_encode($user),

        CURLOPT_HTTPHEADER => ['Content-Type:application/json'],

    ]);



    $response = curl_exec($curl);

    $response_data = json_decode($response);
if (isset($response_data['secureUrl'])) {
    wp_send_json_success($response_data);
} else {
    wp_send_json_error($response_data);
}


 /**
  *    if (!curl_errno($curl)) {
  *
  *      wp_send_json_success(json_decode($response));
  *
  *  } else {
  * 
  *      $response = ['error' => curl_error($curl)];
  *
  *      wp_send_json_error($response);
  *
  *  }
  */
}





/**

 * Get the User data

 */

function get_user_data() : array

{

    $user = wp_get_current_user();



    $data = [

        'UserId' => $user->ID,

        'Email' => $user->user_email,

        'Username' => $user->user_login,

    ];



    return $data;

}







/*

 * Enqueue scripts for cc button on checkout page

 */







add_action( 'wp_enqueue_scripts', 'setup_order_scripts', 15 );



 function setup_order_scripts() {

    $params = [

        'url' => admin_url( 'admin-ajax.php' ),

        'nonce' => wp_create_nonce('security_matters'),

    ];



    wp_register_script( 'cc_order_scripts', get_stylesheet_directory_uri() . '/order-scripts.js', array('jquery'), null, true);

    wp_localize_script( 'cc_order_scripts', 'ccOrderParams', $params);

    wp_enqueue_script( 'cc_order_scripts' );

}











/** Adding child theme's style.css **/

function tm_fixology_child_style_css(){

    wp_enqueue_style( 'fixology-child-style', get_stylesheet_directory_uri() . '/style.css' );

}

add_action( 'wp_enqueue_scripts', 'tm_fixology_child_style_css', 18 );













// Disable auto-complete on form.

add_filter( 'gform_form_tag', function( $form_tag ) {

    return str_replace( '>', ' autocomplete="off">', $form_tag );

}, 11 );



// Diable auto-complete on each field.

add_filter( 'gform_field_content', function( $input ) {

    return preg_replace( '/<(input|textarea)/', '<${1} autocomplete="off" ', $input );

}, 11 );



Open in new window

I changed $data to $response_data because to see if it would help because it was already defined in this file for the user data. Can the same variable name be defined in multiple functions within a single file? as long as they are in different functions? or do we need to change it like I did here? I know that is not solving the failing of the AJAX but another side learning piece for me...……..as far as the call failing every time now, it did shed light on the fact that I also needed to add the "Try Again" message to when it completely fails like it is doing now which I did so it says "Try Again" when this complete fail condition is met as well...…..but I think there is a syntax error or the code is not written right on the 'secureURL' parse of the response. Can you take a look and see what needs to be changed? Thank you
Are you sure it would not be a good idea to do it how I presented above within the order_scripts.js file? I figure that way down the road I can parse other messages he sends me and create additional error handling if need be. This way in the future we can have people report to us what they are seeing in the console when there is certain errors sent to their browser. What do you think?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Chris,

I updated the PHP code with what you wrote above. Now it is getting the URL but giving a false on success.

User generated image
Nevermind, All good, Its Working!!  me and my coworker have it coded secureURL with the URL in caps and I forgot to change it when copy/pasting.

Thank you so Much! Monday is launch day and when the execs are going to be testing it all. Crossing my fingers. This has been great and I have once again learned a lot. 
Excellent work Netty. Good luck with the launch :)
Always on point.
^^That was my feedback, dont know why when on the mobile app it doesnt actually register and go to the testimonials. I am sure you could figure it out for them..... the mobile app on here has a few more bugs as well..speaking of mobile versions, I opened another question regarding resizing the iframe perfectly for mobile devices, please take a look if you get a chance