I'm trying to do an AJAX POST request to an external domain from a post metabox in WordPress.
I know that it's not possible to do it directly because of cross domain access errors. As far as I know it's also not possible to do it simply by using PHP code like
if ( isset ( $_POST( 'button_name' ) ) ) { .. }
since all the metaboxes are inside the wordpress post form.
So this is what I came up with:
I use the wp_localize_script() function to make the php variables available in the js-file (this works). The localized variable is ajax_request_args.
The javascript file looks like this:
jQuery(document).ready(function($) {
$('#button').click( function() {
$.ajax({
type: "POST",
url: php_post.php,
data: ajax_request_args,
success: function(data) {
alert(data["success"] + " " + data["code"]);
},
dataType: 'json'
});
});
});
The php_post.php looks similar to this:
if (is_ajax()) {
...
if (isset($_POST["arg_1"]) && !empty($_POST["arg_1"])) {
$response = wp_remote_post( $external_url, array(
'method' => 'POST',
'body' => $args,
'headers' => array( 'Content-Type' => 'application/x-www-form-urlencoded' ),
'timeout' => 90,
'blocking' => true
) );
$return = $_POST;
$return['success_message'] = $response['success_message'];
$return['code'] = $response['code'];
$return["json"] = json_encode($return);
echo json_encode($return);
}
}
The AJAX request works without the POST request in the php file, for example when I set
$response['success_message'] = 'success';
$response['code'] = '1234';
and delete the wp_remote_post()part.
The POST request to the external domain also works when I call it directly using a button click like
<?php
if (isset( $_POST['test-maintenance-btn'])){
...
$response = wp_remote_post( $external_url, array(
'method' => 'POST',
'body' => $args,
'headers' => array( 'Content-Type' => 'application/x-www-form-urlencoded' ),
'timeout' => 90,
'blocking' => true
) );
}
?>
<form method="post">
<input type="submit" id="test-btn" name="test-btn" value="<?php _e('Execute', 'textdomain'); ?>">
</form>
The weird thing is that it doesn't work in connection. The Javascript should post to the php file which posts to the external server and returns the result to the ajax post request.
When I try to do the wp_remote_post (even if I don't use the result) I always get "NetworkError: 500 Internal Server Error" in the console.
Could you help me find the problem and help me with the correct approach? Thanks in advance for your help.
Related
This question already has answers here:
What is the difference between client-side and server-side programming?
(3 answers)
Closed 1 year ago.
this is my code:
<script>
jQuery(function() {
jQuery.getJSON('lessons.json', function(data) {
var lessonID = data.t["sfwd-lessons"];
$.each(lessonID, function(i, val) {
lessonID = val;
console.log(lessonID);
})
});
});
</script>
I get a list of IDs that I can use for different curl api call.
So, what's the best way to pass these jquery variables to PHP for an api call?
It should be something like this:
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://website.com/wp-json/ldlms/v2/sfwd-lessons/'.lessonID,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => array(
'Authorization: Bearer '.$token.'',
'Cookie: cookie'
),
));
Thank you all.
There are three steps: (1) Retrieving DOM data: inputs, textarea, etc, (2) Sending via AJAX, (3) Retrieving it in PHP:
1 - DOM Data with jQuery: build a single object (easier to send)
let myData = {
name: $('#name').val(),
description: $('#description').val(),
...
}
2 - Send it via Ajax:
jQuery.ajax({
data: myData,
url: PHPurl,
type: "post",
method: "POST",
success: function (response) {
// whatever
},
error: function (e) {
// whatever
}
});
3 - Retrieve it in PHP
$name = isset($_POST['name']) ? $_POST['name'] : '';
$description = isset($_POST['description']) ? $_POST['description'] : 'default description';
... more data
Now if you need to make a cURL call using that data, you have two options:
Pass an array and use header Content-Type 'multipart/form-data':
$data = array(
'name' => $name,
'description' => $description,
...
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
Or encode the same array as json, and use header Content-Type 'application/json':
$data = array(...);
$data = json_encode($data);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
---- EDIT
(Relative to your question below) I see you read a 'lessons.json'. So you get a list of lessons from there. In that case you need to keep the relation between each lesson object, and the DOM elements. For example:
for(let lesson of lessons) {
// Create your HTML inputs to edit the lesson
let container = $("<div class='lesson-editor'></div>");
container.append(...);
container.append(...);
// Now add a reference to the ID of the lesson
container.attr("lessonId", lesson.ID);
}
Now you have an editor for each lesson, and each "container" has the ID of the lesson it's editing.
Later in Javascript, when you want to build your list of lessons and send it with AJAX:
let lessons = [];
let containers = $(".lesson-editor");
containers.each(function() {
let ID = $(this).attr("lessonId");
let lesson = {
ID: ID,
name: $(this).find("#nameInput"),
description: $(this).find("#descInput"),
....
}
lessons.push(lesson);
});
// -> ajax, data: { lessons: lessons }
Then remember that in PHP you have $_POST['lessons'] that is an array of objects (associative arrays).
I have task for school. I need to make Wordpress login-form plugin
I stuck in this part:
"On login you should send data to 3rd party login service, that will happen on server side.
*Login should be done on server side by using WP API functionality.
*This is external API service that needs to be called with CURL, here is example URL:
Request URL: http://example.com/wp-json/example/login/?
Request Method: POST
Content-Type: application/json; charset=UTF-8
Post body object:
{
"username": "usernameinput",
"password": "passwordinput"
}"
I write some code:
test_plugin.php
<form action="wp-admin/admin-post.php" method="post">
<input type="hidden" name="action" value="test_login">
add_action( 'admin_post_test_login', 'identify_user' );
function identify_user() {
$response = wp_remote_post( 'http://wordpress.test/wp-admin/', array(
'method' => 'POST',
'headers' => array('Content-Type' => 'application/json; charset=utf-8', 'Authorization' => 'XaxHyiIwhR06isYQGKHiei6J2ZuRsFzsgCJ4NucC',),
'body' => json_encode($user)
)
);
if ( is_wp_error( $response ) ) {
$error_message = $response->get_error_message();
echo "Something went wrong: $error_message";
} else {
print_r( $response );
}
}
Like I understand from the task text rather, submit username/password to WP backend, then I need to make an authentication request to 3rd party site from WP backend (with CURL or similar)...
Can someone give me instructions how to make that, or some tutorial or example.
I am trying to get the ajax data in PHP variable. The code is working fine and I am able to get the ajax data in PHP variable.
My question is : Can I use the PHP variable for file_get_contents function again ?
My PHP code is like this
<?php
$html = file_get_contents('https://someurl.com');
if (isset($_POST['job']))
{
$job = $_POST['job'];
$attrb = $_POST['attrb'];
echo $job;
echo $attrb;
$htmlcontents = file_get_contents($attrb);
}
?>
And the Ajax code is as below
$(document).ready(function(){
$.post("test.php",
{
job: exactdatainner,
attrb: getattr
},
function(data,status){
var obj = data.split('http');
var title = obj[0];
var link = 'http' + obj[1];
$(".job").html(title);
$(".attribute").html(link);
});
});
This code works fine for the first step, sending data from ajax and receiving response and print the result in a Div.
Now I am trying to fetch the URL (this URL was created in first step and stored in a PHP variable. Code is : $attrb = $_POST['attrb'];)
As you can see that I am able to print the value in first step, but when I am trying to get the contents of URL again, it gives me the error.
Try below code, I tested and it's working. Returning a 404 response <h1>Sorry This Page is Not Available Now</h1> and I also verified the response by hitting the same url in the browser, so it's working.
file_get_contents() stops with a warning errors for non-2xx status codes.
You just need to fetch the contents even on failure status code maybe 404 or 500, for that you need to set ignore_errors => true,default is false.
echo file_get_contents(
'https://www.sarkariresult.com/force/navy-sst',
false,
stream_context_create([
'http' => [
'ignore_errors' => true
],
]) );
More information have a look on this question, second answer. here
Update
$url = 'https://html5andcss3.org/';
$opts = array(
'http'=>array(
'method'=>"GET",
'header'=>"Accept-language: en\r\n",
'ignore_errors' => true, //set to true for non 2XXX reponse codes
)
);
$context = stream_context_create($opts);
// Open the file using the HTTP headers set above
$file = file_get_contents($a, false, $context);//pass the variable $url
echo $file;
Any POST request to the wp rest api yields 404 responses, yet when switched to GET everything works fine.
The react component's method to handle a form submit with fetch:
handleFormSubmit(){
event.preventDefault();
const data = new FormData(event.target);
fetch('sfg/wp-json/sfg/v1/login', {
method : 'POST',
body: data
})
.then( (res) => {
console.log(res);
} );
}
The register route function:
register_rest_route( 'sfg/v1', '/login/', array(
'methods' => 'POST',
'callback' => 'json_login'
));
The callback:
function json_login(){
$credentials = array();
$credentials['user_name'] = $_POST['username'];
$credentials['password'] = $_POST['password'];
$status = wp_signon($credentials, false);
return $status;
}
App is sending the request from a different port - 8081 rather than 8080.
According to this URL. Can you try adding index.php after your project url.
Since moving my site to https, the mailchimp api no longer works with the standard json ajax calls. These calls now render a same origin policy error. I don't know why this is the case though, because I'm calling a url on my own server. After some investigating, I've surmised that JSONP is my only option. The following script posts correctly to mailchimp but Im unable to get a successful response.
$.ajax({
type:"GET",
url:"https://mysite/book_subscription_process.php?jsonp=?",
data:{fname: $('#fNBookId').val(), lname: $('#lNBookId').val(), email: $('#eBookId').val()},//only input
dataType: "jsonp",
cache: false,
async: false,
jsonp: false,
success: function(data){
console.log('success');
if(data.message == 'failure')
{
alert('Error','There was an error processing your subscription. Please try again.');
}else if(data.message == 'success')
{
alert('success');
}else{
console.log(data.message);
}
},
error: function (xhr, ajaxOptions, thrownError, data) {
// console.log(data.message);
console.log('failure');
alert(xhr.status);
alert(thrownError);
}
});
Server side:
<?php
header("content-type: text/javascript");
if(isset($_GET['jsonp']))
{
$obj->fname = $_GET['fname'];
$obj->lname = $_GET['lname'];
$obj->email = $_GET['email'];
$obj->success = 'success';
$obj->failure = 'failure';
}
header("Content-type: application/json");
$MailChimp = new \Drewm\MailChimp($api_key);
$book = array('id' => $group_id, 'groups' => array('Book'));
$merge_vars = array('FNAME'=> $obj->fname,
'LNAME'=>$obj->lname,
'GROUPINGS'=>array($book)
);
$result = $MailChimp->call('lists/subscribe', array(
'id' => $list_id,
'email' => array('email'=>$obj->email),
'merge_vars' => $merge_vars,
'double_optin' => false,
'update_existing' => true,
'replace_interests' => false,
'send_welcome' => false,
));
if ( ! empty( $result['leid'] ) ) {
echo json_encode($obj->success);
}
else{
echo json_encode($obj->failure);
}
?>
As I said above the info is correctly posted to mailchimp. Each time however, the ajax call errors. I get a 200 OK but get a Jquery[bunch of numbers] not called. The json_encode success statement is executed on the server. Is there a special way that I'm supposed to handle the server side response? Or am I supposed to do something differently on the client side? Thanks in advance.
Same Origin means that the page making the request and the destination server need to have identical protocol, server, and port. For this particular situation, MailChimp isn't either of those -- the page making the request is your HTML page and the server is https://mysite/book_subscription_process.php.
Since you said this corresponds to your move to HTTPS, my guess is that you've moved one end but not the other. Since the code above looks like the front-end page is calling https://mysite, I'd triple check to make sure that the HTML and all scripts are also being served from https://mysite.
I don't think you should need JSONP in this scenario -- it sounds like you are attempting to work from the same origin, you just need to be sure you're doing that properly.