skip to Main Content

I would like to get some Input a my problem I am trying to solve transferring my standalone php function and js script into a working WordPress format. I am stuck to transfer this into a working format for my WordPress page and need some input.

I have created a script for a chained API call to 2 different endpoints In php.

Call 1 to Endpoint a) is sending 3 static body params (api key, user id, password etc) to the API and 1 dynamic value, (userIP adress). In response the API POST a orderREF string and a url to a QR code which should be displayed on the screen. In addition to this, the QR code shall be refreshed every 5 secs.

Once the user scans the QR code successfully the Call 2 to Endpoint b) returns customer name and social security number and some other values which are not so relevant atm. For the user the authentication process has been completed and I want to transfer the obtained data into my customer database.

As you will see in my script I created a working prototype of this in a standalone script but need help to transfer it into a working WordPress (plugin or shortcode) so I can use this function on specific parts of our page. I would like to send the user to go through this process before signing up on our website in order to fully verify the identity of the user.

The code I created successfully to carry out the 2 chained API calls and to refresh the QR code by javascript. I have just for simplicity hardcoded the credentials for testing, these will be stored in a .env file

<?php
// Handle AJAX requests for the second API call
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['checkStatus'])) {
    $orderRef = $_POST['orderRef'];

    $apiUser = 'aaa';
    $password = ' xxx ';
    $companyApiGuid = 'yyy ';
    $url = 'https://url/endpoint/2';

    $requestData = array(
        'apiUser' => $apiUser,
        'password' => $password,
        'companyApiGuid' => $companyApiGuid,
        'orderRef' => $orderRef
    );

    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($requestData));
    curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
    $response = curl_exec($curl);
    curl_close($curl);
    echo $response;
    exit;
}

// Initial QR code generation if not a POST request
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    $apiUser = 'aaa';
    $password = 'xxx';
    $companyApiGuid = 'yyy';
    $url = 'https://url/endpoint1';

    $data = array(
        'apiUser' => $apiUser,
        'password' => $password,
        'companyApiGuid' => $companyApiGuid,
        'endUserIp' => $_SERVER['REMOTE_ADDR'],
        'getQr' => true
    );

    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
    curl_setopt($curl, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json'
    ));

    $response = curl_exec($curl);
    if (!$response) {
        die('Error: "' . curl_error($curl) . '" - Code: ' . curl_errno($curl));
    }
    curl_close($curl);
    $responseData = json_decode($response, true);

    $apiResponse = $responseData['apiCallResponse']['Response'] ?? [];
    $qrImageUrl = $apiResponse['QrImage'] ?? 'No QR code URL available.';
    $orderRef = $apiResponse['OrderRef'] ?? 'No order reference available.';
}
?>

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>QR Code and Status Check</title>
<script>
var refreshInterval; // Interval for refreshing the QR code

function refreshQRCode(qrImageUrl) {
    var qrImage = document.getElementById('qrImage');
    if (qrImage) {
        qrImage.src = qrImageUrl + '?' + new Date().getTime(); // Appending timestamp to avoid cache issues
    }
}

function checkStatus(orderRef) {
    fetch('index.php', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        body: 'checkStatus=true&orderRef=' + orderRef
    })
    .then(response => response.json())
    .then(data => {
        console.log(data); // For debugging purposes, log the data received from the server

        // Update the logs with detailed status from the second API call
        document.getElementById('detailedLogs').innerHTML = `
            <p>Auth Success: ${data.authResponse && data.authResponse.Success}</p>
            <p>Auth Error Message: ${data.authResponse && data.authResponse.ErrorMessage}</p>
            <p>API Call Success: ${data.apiCallResponse && data.apiCallResponse.Success}</p>
            <p>Status Message: ${data.apiCallResponse && data.apiCallResponse.StatusMessage}</p>
            <p>Order Reference: ${data.apiCallResponse && data.apiCallResponse.Response && data.apiCallResponse.Response.OrderRef}</p>
            <p>Completion Status: ${data.apiCallResponse && data.apiCallResponse.Response && data.apiCallResponse.Response.Status}</p>
            <p>Hint Code: ${data.apiCallResponse && data.apiCallResponse.Response && data.apiCallResponse.Response.HintCode}</p>
        `;

        if (data.apiCallResponse.Response.Status === "complete") {
            clearInterval(refreshInterval); // Stop refreshing the QR code
            var user = data.apiCallResponse.Response.CompletionData.user;
            document.getElementById('qrImageContainer').innerHTML = `
                <p>SUCCESS</p>
                <p>Personal Number: ${user.personalNumber}</p>
                <p>Name: ${user.name}</p>
                <p>Given Name: ${user.givenName}</p>
                <p>Surname: ${user.surname}</p>
            `;
        } else {
            // If conditions are not met, keep polling every 5 seconds
            setTimeout(function() { checkStatus(orderRef); }, 5000);
        }
    })
    .catch(error => {
        console.error('Error:', error);
        setTimeout(function() { checkStatus(orderRef); }, 5000);
    });
}

window.onload = function() {
    var orderRef = '<?php echo $orderRef; ?>';
    var qrImageUrl = '<?php echo $qrImageUrl; ?>';
    refreshQRCode(qrImageUrl);
    refreshInterval = setInterval(function() { refreshQRCode(qrImageUrl); }, 5000); // Set up the interval to refresh QR code every 5 seconds
    checkStatus(orderRef);
}
</script>
</head>
<body>
    <h1>QR Code</h1>
    <div id="qrImageContainer">
        <?php if (isset($qrImageUrl) && $qrImageUrl !== 'No QR code URL available.') { ?>
            <img id="qrImage" src="<?php echo $qrImageUrl; ?>" alt="QR Code"><br>
        <?php } else { ?>
            <p>QR Code URL not available.</p>
        <?php } ?>
    </div>
    <div id="logs"></div>
    <h2>Log Call Endpoint 1</h2>
    <p>Auth Success: <?php echo $responseData['authResponse']['Success'] ?? 'No data'; ?></p>
    <p>Auth Error Message: <?php echo $responseData['authResponse']['ErrorMessage'] ?? 'No error message'; ?></p>
    <p>API Call Success: <?php echo $responseData['apiCallResponse']['Success'] ?? 'No data'; ?></p>
    <p>Status Message: <?php echo $responseData['apiCallResponse']['StatusMessage'] ?? 'No status message'; ?></p>
    <p>Order Reference: <?php echo $orderRef; ?></p>
    <div id="messageContainer"></div>
    <h2>Log Call Endpoint 2</h2>
    <div id="detailedLogs"></div>
</body>
</html>

For getting this functionality into WordPress I thought about creating a simple plugin and populate the script so WordPress can process it (also in regards to JS and AJAX functionality)

I created a simple plugin structure with

  • main plugin-index.php
  • api-handler.php for the actuals calls.
  • template.php for the output
    and a /js folder where I locate the js script file for refreshing the QR code.
    I call all of this with a shortcode function on the actual page and part needed on the page.

plugin-index.php file

<?php
/*
Plugin Name: Plugin Name 
Description: Integrates QR code generation and status check verification.
Version: 1.0
Author: me.
*/

function ba_bank_enqueue_scripts() {
    wp_enqueue_script('ba_bank-ajax', plugin_dir_url(__FILE__) . 'js/bankid-ajax.js', array('jquery'), null, true);
    wp_localize_script('bba_bank-ajax', 'bankidAjax', array('ajaxurl' => admin_url('admin-ajax.php')));
}
add_action('wp_enqueue_scripts', 'ba_bank_enqueue_scripts');

include_once plugin_dir_path(__FILE__) . 'api-handler.php';

function byggauktion_bankid_shortcode() {
    $response = get_initial_qr_code_data();
    $responseData = json_decode($response, true);
    $qrImageUrl = $responseData['apiCallResponse']['Response']['QrImage'] ?? 'No QR code URL available.';
    $orderRef = $responseData['OrderRef'] ?? 'No order reference available.';

    ob_start();
    ?>
    <div id="qrImageContainer">
        <?php if ($qrImageUrl !== 'No QR code URL available.'): ?>
            <img id="qrImage" src="<?php echo esc_url($qrImageUrl); ?>" alt="QR Code"><br>
        <?php else: ?>
            <p>QR code URL not available.</p>
        <?php endif; ?>
        <div id="updateArea">
            <p>Scan the QR code above. Updates will appear here once available.</p>
        </div>
    </div>
    <input type="hidden" id="orderRef" value="<?php echo esc_attr($orderRef); ?>">
    <?php
    echo ob_get_clean();
}
add_shortcode('ba_bank', 'ba_bank_shortcode');

function ba_bank_handle_ajax() {
    check_status_update();
    wp_die();
}
add_action('wp_ajax_ba_check_status', 'ba_bank_handle_ajax');
add_action('wp_ajax_nopriv_ba_check_status', 'ba_bank__handle_ajax');

The api-handler.php

<?php
function get_initial_qr_code_data() {
    $data = [
        'apiUser' => 'aaa',
        'password' => 'xxx',
        'companyApiGuid' => 'zzz',
        'endUserIp' => $_SERVER['REMOTE_ADDR'],
        'getQr' => true
    ];
    return make_bank_api_call('https://url/endpoint1', $data);
}

function check_status_update() {
    $orderRef = isset($_POST['orderRef']) ? sanitize_text_field($_POST['orderRef']) : '';
    $data = [
        'apiUser' => 'aaa',
        'password' => 'xxx',
        'companyApiGuid' => 'zzz',
        'orderRef' => $orderRef
    ];
    $response = make_bank_api_call('https://url/endpoint2', $data);
    echo $response;
}

function make_bank_api_call($url, $data) {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data));
    curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
    $response = curl_exec($curl);
    curl_close($curl);
    return $response ? $response : json_encode(['error' => 'No response from API']);
}

template.php file for the html output

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>QR Code and Status Check</title>
</head>
<body>
    <h1>QR Code</h1>
    <div id="qrImageContainer">
        <?php if (isset($qrImageUrl) && $qrImageUrl !== 'No QR code URL available.') : ?>
            <img id="qrImage" src="<?php echo $qrImageUrl; ?>" alt="QR Code">
        <?php else : ?>
            <p>QR Code URL not available.</p>
        <?php endif; ?>
    </div>
    <div id="logs"></div>
    <h2>Log Call Endpoint 1</h2>
    <p>Order Reference: <?php echo isset($orderRef) ? $orderRef : 'No order reference available.'; ?></p>

    <p>Auth Success: <?php echo $responseData['authResponse']['Success'] ?? 'No data'; ?></p>
    <p>Auth Error Message: <?php echo $responseData['authResponse']['ErrorMessage'] ?? 'No error message'; ?></p>
    <p>API Call Success: <?php echo $responseData['apiCallResponse']['Success'] ?? 'No data'; ?></p>
    <p>Status Message: <?php echo $responseData['apiCallResponse']['StatusMessage'] ?? 'No status message'; ?></p>
    <p>Order Reference: <?php echo $orderRef; ?></p>
    <div id="messageContainer"></div>
    <h2>Log Call Endpoint 2</h2>
    <div id="detailedLogs"></div>
    <script src="<?php echo plugin_dir_url(__FILE__) . 'js/bankid-ajax.js'; ?>"></script>
</body>
</html>

Finally the bankid-ajax,js

document.addEventListener('DOMContentLoaded', function() {
    var qrImage = document.getElementById('qrImage');
    var orderRef = document.getElementById('orderRef').value;
    var updateArea = document.getElementById('updateArea');

    function checkStatus(orderRef) {
        fetch(bankidAjax.ajaxurl, {
            method: 'POST',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            body: 'action=byggauktion_check_status&orderRef=' + encodeURIComponent(orderRef)
        })
        .then(response => response.json())
        .then(data => {
            // Dynamically update content
            if (data.status === 'complete') {
                updateArea.innerHTML = '<p>Verification completed successfully for user ' + data.user.name + '</p>';
            } else {
                updateArea.innerHTML = '<p>Status: ' + data.status + '</p>';
            }
            if (data.newQrImage) {
                qrImage.src = data.newQrImage + '?refresh=' + new Date().getTime();
            }
        })
        .catch(error => {
            console.error('Error:', error);
            updateArea.innerHTML = '<p>Error checking status. Please try again.</p>';
        });
    }

    setInterval(() => checkStatus(orderRef), 5000);
});

I am not able to connect to the API on this way and the QR cant be displayed. I have tried to simplify it more. Could try to give me an advice how to streamline my script more for my WordPress use-case?

Thank you

2

Answers


  1. Chosen as BEST ANSWER

    To elaborate on my answer in the comment, I incorporated the JS now int the main file. I am still not really coming to the right solution that the img is refreshing. Any suggestings from you on this function below?

    function byggauktion_bankid_enqueue_scripts() {
    wp_register_script('byggauktion-bankid-ajax', ''); 
    $bankcheck_nonce   = wp_create_nonce( 'bankcheck_nonce' );
    wp_localize_script( 'byggauktion-bankid-ajax', 'bankidAjax',
        array(
            'ajaxurl'           => admin_url( 'admin-ajax.php' ),
            'bankcheck_nonce'   => $bankcheck_nonce
        )
    );
    
    $js_code = <<<JS
    setInterval(function() {
        jQuery.ajax({
            url: bankidAjax.ajaxurl,
            type: 'POST',
            data: {
                action: 'byggauktion_check_status',
                security: bankidAjax.bankcheck_nonce,
                OrderRef: jQuery('#OrderRef').val()
            },
            success: function(response) {
                console.log(response);
                if (response.Success) {
                    jQuery('#messageContainer').html('<p>API Call Success: ' + response.Success + '</p><p>Status Message: ' + response.StatusMessage + '</p>');
                } else {
                    jQuery('#messageContainer').html('<p>API Call Success: ' + response.Success + '</p><p>Status Message: ' + response.StatusMessage + '</p>');
                }
            },  
            
                error: function(response) {
                console.log(response);
                jQuery('#messageContainer').html('<p>API Call Error: ' + response + '</p>');
            }
    
        });
    }, 5000);
    JS;
    
    wp_add_inline_script('byggauktion-bankid-ajax', $js_code, 'after');
    

    } add_action('wp_enqueue_scripts', 'byggauktion_bankid_enqueue_scripts');


  2. To expand on my comment, you’re missing a couple of key things in your code.

    First, lets generate a nonce and pass it across to your JS.

    function ba_bank_enqueue_scripts() {
        wp_enqueue_script('ba_bank-ajax', plugin_dir_url(__FILE__) . 'js/bankid-ajax.js', array('jquery'), null, true);
        $bankcheck_nonce   = wp_create_nonce( 'bankcheck_nonce' );
        wp_localize_script( 'bba_bank-ajax', 'bankidAjax',
            array(
                'ajaxurl'           => admin_url( 'admin-ajax.php' ),
                'bankcheck_nonce'   => $bankcheck_nonce
            )
        );
    }
    add_action( 'wp_enqueue_scripts', 'ba_bank_enqueue_scripts' );
    

    Now, in your JS file you’ll want to call that alongside the ajaxurl

    //add the nonce value to a variable & add it to your action string
    var security = bankidAjax.bankcheck_nonce;
    function checkStatus( orderRef ) {
        fetch( bankidAjax.ajaxurl {
            method: 'POST',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            body: 'action=byggauktion_check_status&security='+security+'&orderRef=' + encodeURIComponent(orderRef)
        } )
    

    Now we have to make sure that your callback function matches the action name you used in your JS and also check your AJAX referer:

    function check_status_update() {
        //this checks the ajax referer to make sure it's permitted
        check_ajax_referer( 'bankcheck_nonce', 'security' );
        $orderRef = isset($_POST['orderRef']) ? sanitize_text_field($_POST['orderRef']) : '';
        $data = [
            'apiUser' => 'aaa',
            'password' => 'xxx',
            'companyApiGuid' => 'zzz',
            'orderRef' => $orderRef
        ];
        $response = make_bank_api_call( 'https://url/endpoint2', $data );
        echo $response;
        //stops AJAX from returning a 0 as a response, basically ends the process for you
        wp_die();
    }
    //this next bit is key, you have to add an action and use the action name from your JS
    //in your JS you used byggauktion_check_status
    //for logged in users
    add_action( 'wp_ajax_byggauktion_check_status',  'check_status_update' );
    //for logged out users, if this needs to function on the front end
    add_action( 'wp_ajax_nopriv_byggauktion_check_status',  'check_status_update' );
    

    Obviously this is untested, but with those added elements you should be able to debug the rest yourself. 🙂 Best of luck.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search