Fetch xml data from API response - php

Request:
$headers = array( 'Content-Type:application/xml' );
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://example.com',
CURLOPT_POST => 1,
CURLOPT_HEADER => $headers,
CURLOPT_USERPWD=>'test:test',
CURLOPT_POSTFIELDS => $XMLData
));
$APIResponse = curl_exec($curl);
curl_close($curl);
And I get this response from an API
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: ----
X-AspNet-Version: -----
X-Powered-By: ASP.NET
Date: ---- GMT
Content-Length: 100
<?xml version="1.0" encoding="utf-8"?><response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.example.com"><ID>12345</ID></response>
I want to fetch ID from xml ID tag. How can I get that in my php code?

You're getting the HTTP header data included within your response from cURL, which is making it hard to extract the XML part.
However this is happening due to a simple misunderstanding - the CURLOPT_HEADER option doesn't do what you think it does.
That doesn't include your request headers in the request (as your code seems to be trying to do), instead it sets an option telling cURL whether or not the response headers should be included in the main output or not. If you set
CURLOPT_HEADER => 0
in your code, your problem should go away - then only the response body (in your case, just the XML) will included in the output from curl_exec.
In the meantime, if you need to set custom HTTP headers in your request, you can do it via the CURLOPT_HTTPHEADER option - a detailed example can be found here and in many other places online.
P.S. Admittedly these option names are not, in themselves, very clear about the difference between them, but the PHP manual does describe what they do in more detail.

Related

How to send raw data with curl GET in PHP?

I am developing REST API and while it is easy to set raw JSON data for request in cURL for POST
$payload = json_encode(array("user" => $data));
//attach encoded JSON string to the POST fields
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
I cannot figure out how to send such data with GET requests.
Is there something like CURLOPT_GETFIELDS or CURLOPT_RAWDATA? The purpose of sending JSON with GET request is to pass in some params.
I do not wish to add formdata to the request, I wish to post JSON so that it can be parsed on the receiver.
Thanks!
EDIT:
based on comments I want to avoid confusion, so the resulting request should look like:
GET / HTTP/1.1
Host: 127.0.0.1:3000
Content-Type: application/json
Accept: application/json
Host: 127.0.0.1:3000
content-length: 13
Connection: keep-alive
cache-control: no-cache
{
"a": "b"
}
as you can see, GET request here has data and it is parsed and works perfectly by web server. How do I achieve this with cURL?
GET requests do not have a body, that's the whole idea: you're just getting something from the server, as opposed to posting something to it. From RFC 7231:
A payload within a GET request message has no defined semantics;
sending a payload body on a GET request might cause some existing
implementations to reject the request.
In other words, a GET request can have data, but it should not. From earlier in the spec, where GET is defined as a safe method:
Request methods are considered "safe" if their defined semantics are
essentially read-only; i.e., the client does not request, and does
not expect, any state change on the origin server as a result of
applying a safe method to a target resource.
...
Of the request methods defined by this specification, the GET, HEAD,
OPTIONS, and TRACE methods are defined to be safe.
If you really want to have JSON in your GET request (and send it to a reasonably implemented server resource) the only place it can go is in the URI as part of the query string. For GET requests I find using file_get_contents to be much easier than dealing with cURL.
<?php
$payload = json_encode(["user" => $data]);
$url_data = http_build_query([
"json" => $payload
]);
$url = "https://some.example/endpoint.php?" . $url_data;
$result = file_get_contents($url);
If you want to send it to an unreasonably implemented server resource, and violate the spirit of the HTTP RFCs, you could do this:
<?php
$url = "https://some.example/endpoint.php";
$payload = json_encode(["user" => $data]);
$ctx = stream_context_create(["http" => [
"header"=>"Content-Type: application/json",
"content"=>$payload
]]);
$result = file_get_contents($url, false, $ctx);
If you're determined to do this specifically with cURL, you might have luck with the CURLOPT_CUSTOMREQUEST option set to "GET" and CURLOPT_POSTDATA with your data.

Payfast payment gateway ITN request not working in Laravel 5.1

I have integrate payfast payment gateway in our Laravel 5.1 website, it is working perfect on our development server but when we move site on live server it give error in ITN request step, here is the error which I am getting:
HTTP/1.1 500 Internal Server Error
Date: Wed, 09 Nov 2016 14:10:09 GMT
Server: Apache
Cache-Control: no-cache, private
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
When I am searching for solution I got below option to enable ITN request without CSRF token
protected $except = [
//
'/itn'
];
but this also not working, I put sample code folder on my website root folder and try to do payment and that will working.
Also when I try to write notify response in text file it print success in response to the file.
After debugging my code I found there is problem with the CURL post.
// Base settings
$curlOpts = array(
// Base options
CURLOPT_USERAGENT => USER_AGENT, // Set user agent
CURLOPT_RETURNTRANSFER => true, // Return output as string rather than outputting it
CURLOPT_HEADER => false, // Don't include header in output
CURLOPT_SSL_VERIFYHOST => true,
CURLOPT_SSL_VERIFYPEER => false,
// Standard settings
CURLOPT_URL => 'https://' . $pfHost . '/eng/query/validate',
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $pfParamString,
);
curl_setopt_array($ch, $curlOpts);
// Execute CURL
$res = curl_exec($ch);
curl_close($ch);
Main issue occurs because of these two line code
CURLOPT_SSL_VERIFYHOST => true,
CURLOPT_SSL_VERIFYPEER => false,
I change its value and it start working
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_SSL_VERIFYPEER => true,
This will fix my problem and payfast working perfect after doing these changes.

file_get_contents Default headers

I was wondering what is the default Content-Type header option when requesting a json string from an API.
I've noticed even if the requested Content-Type is application/json the response header Content-Type will be text/html
Does file_get_contents set the headers automatically based on what it is requesting or does it have a default one that is used always?
Does file_get_contents set the headers automatically based on what it is requesting or does it have a default one that is used always?
I think no defaults. For the context parameter you read below and see the 4-th example in docs:
A valid context resource created with stream_context_create(). If you don't need to use a custom context, you can skip this parameter by NULL.
Tested with Wireshark.
PHP 5.5.8 sends:
POST /path HTTP/1.0
Host: example.com
Content-Length: [appropriate number]
Content-Type: application/x-www-form-urlencoded
For the following context:
$options = array(
'http' => array(
'method' => 'POST',
'content' => $content
)
);
$context = stream_context_create($options);

Requesting JSON from PHP

I am trying to retrieve data from a server which usually returns it in XML, however I trying to request it in a JSON format (if requested correctly it will return the data in JSON).
$header = array(
'http' => array(
'header'=>"Content-type: application/json"
),
);
$response = file_get_contents($query, false, $header);
print_r($response);
This approach was taken from here. Currently the program does not return anything.
Does anyone spot any potential problems with this?
You need to set the HTTP Accept header to tell the server that you want it to give you JSON:
Accept: application/json
(assuming that the remote server is correctly implemented to read the header)
The Content-Type request header indicates the type of the payload that you are POSTing.
In your case, it does not apply, since you're sending a GET request.

Scraping ASP.Net website with POST variables in PHP

For the past few days I have been trying to scrape a website but so far with no luck.
The situation is as following:
The website I am trying to scrape requires data from a form submitted previously. I have recognized the variables that are required by the web app and have investigated what HTTP headers are sent by the original web app.
Since I have pretty much zero knowledge in ASP.net, thought I'd just ask whether I am missing something here.
I have tried different methods (CURL, get contents and the Snoopy class), here's my code of the curl method:
<?php
$url = 'http://www.urltowebsite.com/Default.aspx';
$fields = array('__VIEWSTATE' => 'averylongvar',
'__EVENTVALIDATION' => 'anotherverylongvar',
'A few' => 'other variables');
$fields_string = http_build_query($fields);
$curl = curl_init($url);
curl_setopt_array
(
$curl,
array
(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => 0, // Not supported in PHP
CURLOPT_SSL_VERIFYHOST => 0, // at this time.
CURLOPT_HTTPHEADER =>
array
(
'Content-type: application/x-www-form-urlencoded; charset=utf-8',
'Set-Cookie: ASP.NET_SessionId='.uniqid().'; path: /; HttpOnly'
),
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $fields_string,
CURLOPT_FOLLOWLOCATION => 1
)
);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
?>
The following headers were requested:
Request URL:
http://www.urltowebsite.com/default.aspx
Request Method:POST
Status Code: 200 OK
Request Headers
Accept:application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,/;q=0.5
Content-Type:application/x-www-form-urlencoded
User-Agent:Mozilla/5.0 (Macintosh; U;
Intel Mac OS X 10_6_4; en-us)
AppleWebKit/533.18.1 (KHTML, like
Gecko) Version/5.0.2 Safari/533.18.5
Form Data
A lot of form fields
Response Headers
Cache-Control:private
Content-Length:30168
Content-Type:text/html; charset=utf-8
Date:Thu, 09 Sep 2010 17:22:29 GMT
Server:Microsoft-IIS/6.0
X-Aspnet-Version:2.0.50727
X-Powered-By:ASP.NET
When I investigate the headers of the CURL script that I wrote, somehow does not generate the Form data request. Neither is the request method set to POST. This is where it seems to me where things go wrong, but dunno.
Any help is appreciated!!!
EDIT: I forgot to mention that the result of the scraping is a custom session expired page of the remote website.
Since __VIEWSTATE and __EVENTVALIDATION are base 64 char arrays, I've used urlencode() for those fields:
$fields = array('__VIEWSTATE' => urlencode( $averylongvar ),
'__EVENTVALIDATION' => urlencode( $anotherverylongvar),
'A few' => 'other variables');
And worked fine for me.
Since VIEWSTATE contains the state of the page in a particular situation (and all this state is encoded into a big, apparently messy, string), you cannot be sure that the param you are scraping can be the same for your "mock" request (I'm quite sure that it cannot be the same ;) ).
If you really have to deal with VIEWSTATE and EVENTVALIDATION params my advice is to follow another approach, that is to scrape content via Selenium or with an HtmlUnit like library (but unfortunately I don't know if there's something similar in PHP).

Categories