Stripe - partial refund with PHP, iOS and Alamofire - php

Hi I get an error of responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength) I guess this is caused by the amount I passed to my backend server. But, I couldn't find out why. If I process full refund (not using amount and currency), everything works fine.
Below code is in iOS.
print(countOrders)
var requestString = "http://xxxxx.com/fullRefund.php"
var params = ["chargeId": chargeId]
let amountStr = String(Int(sellingPrice * Double(quantity)))
if countOrders > 1 {
requestString = "http://xxxxx.com/partialRefund.php"
params = ["chargeId": chargeId, "amount": amountStr, "currency": currency]
}
print(requestString)
print(chargeId)
print(amountStr)
print(currency)
Alamofire.request(requestString, method: .post, parameters: params).responseJSON { (response) in
switch response.result {
case .success(_):
break
case .failure(let error):
print(error)
break
}
}
Every input should be correct as it prints
2
http://xxxxx.com/partialRefund.php
ch_1BDdTTLYXQrQQLvfRzXnzLsh
4083
CNY
responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength)
Here is the charge detail from Stripe
ID: ch_1BDdTTLYXQrQQLvfRzXnzLsh
Amount: ¥6,366.00 CNY → $7,391.84 HKD
Below code is partialRefund.php. I guess something wrong in amount since error shows inputDataNilOrZeroLength
<?php
require_once('stripe-php/init.php');
\Stripe\Stripe::setApiKey('sk_test_keyyyyyyyyyyyyyyyy');
$chargeId = $_POST['chargeId'];
$amount = $_POST['amount']; // this line is deleted in fullRefund.php
$currency = $_POST['currency']; // this line is deleted in fullRefund.php
try {
$re = \Stripe\Refund::create(
array(
"charge" => $chargeId,
"amount" => $amount*100, // this line is deleted in fullRefund.php
"currency" => $currency // this line is deleted in fullRefund.php
)
);
$json = array(
'status' => 'Success'
);
echo json_encode($json);
} catch(\Stripe\Error\Card $e) {
$json = array(
'status' => 'Failure',
'message' => $e->getMessage()
);
echo json_encode($json);
}
?>

That looks like you're getting an error in your response to the iOS app, rather than in something coming into your PHP script. You might want to try switching to responseString to see if that fixes it, or try adding a Content-Type header before you echo your JSON:
header('Content-Type: application/json');

Related

How to verify discord endpoint using php?

I am having some issues in creating a Discord bot. I want it to be able to respond to slash commands, but to do so I need to verify an endpoint.
I am using PHP 7.4, and can't use any external libraries (hosting on a server that does not allow them).
I have found documents for PHP, but they do require libraries to work.
I tried taking the documents from Node.JS and "converting" them to PHP.
Here's my code:
<?php
$public_key = "shh-it's-a-seekrit";
$headers = getallheaders();
$signature = $headers["X-Signature-Ed25519"];
$timestamp = $headers["X-Signature-Timestamp"];
$raw_body = file_get_contents('php://input');
/* To compute the signature, we need the following
* 1. Message ($timestamp + $body)
* 2. $signature
* 3. $public_key
* The algorythm is SHA-512
*/
$message = $timestamp . $raw_body;
$hash_signature = hash_hmac('sha512', $message, $public_key);
if (!hash_equals($signature, $hash_signature)) {
header("HTTP/1.1 401 Unauthorized", true, 401);
die("Request is not properly authorized!");
}
$return_array = [
'type' => 1,
];
echo json_encode($return_array);
?>
When I put the address the file is uploaded to and try to save the changes, Discord says the following:
Validation errors:
interactions_endpoint_url: The specified interactions endpoint URL could not be verified.
This is a method that works for me on PHP 8.1.
Pass in the headers and raw JSON body, and it returns an array with the response code and payload to send back through whatever you are using to handle the response. Note the response must be JSON encoded.
$discord_public is the public key from the Discord app.
public function authorize(array $headers, string $body, string $discord_public): array
{
$res = [
'code' => 200,
'payload' => []
];
if (!isset($headers['x-signature-ed25519']) || !isset($headers['x-signature-timestamp'])) {
$res['code'] = 401;
return $res;
}
$signature = $headers['x-signature-ed25519'];
$timestamp = $headers['x-signature-timestamp'];
if (!trim($signature, '0..9A..Fa..f') == '') {
$res['code'] = 401;
return $res;
}
$message = $timestamp . $body;
$binary_signature = sodium_hex2bin($signature);
$binary_key = sodium_hex2bin($discord_public);
if (!sodium_crypto_sign_verify_detached($binary_signature, $message, $binary_key)) {
$res['code'] = 401;
return $res;
}
$payload = json_decode($body, true);
switch ($payload['type']) {
case 1:
$res['payload']['type'] = 1;
break;
case 2:
$res['payload']['type'] = 2;
break;
default:
$res['code'] = 400;
return $res;
}
return $res;
}
For completeness, adding the missing code to #Coder1 answer:
<?php
$payload = file_get_contents('php://input');
$result = endpointVerify($_SERVER, $payload, 'discord app public key');
http_response_code($result['code']);
echo json_encode($result['payload']);
function endpointVerify(array $headers, string $payload, string $publicKey): array
{
if (
!isset($headers['HTTP_X_SIGNATURE_ED25519'])
|| !isset($headers['HTTP_X_SIGNATURE_TIMESTAMP'])
)
return ['code' => 401, 'payload' => null];
$signature = $headers['HTTP_X_SIGNATURE_ED25519'];
$timestamp = $headers['HTTP_X_SIGNATURE_TIMESTAMP'];
if (!trim($signature, '0..9A..Fa..f') == '')
return ['code' => 401, 'payload' => null];
$message = $timestamp . $payload;
$binarySignature = sodium_hex2bin($signature);
$binaryKey = sodium_hex2bin($publicKey);
if (!sodium_crypto_sign_verify_detached($binarySignature, $message, $binaryKey))
return ['code' => 401, 'payload' => null];
$payload = json_decode($payload, true);
switch ($payload['type']) {
case 1:
return ['code' => 200, 'payload' => ['type' => 1]];
case 2:
return ['code' => 200, 'payload' => ['type' => 2]];
default:
return ['code' => 400, 'payload' => null];
}
}
According to Discord documentation, interactions endpoint must do two things:
Your endpoint must be prepared to ACK a PING message
Your endpoint must be set up to properly handle signature headers--more on that in Security and Authorization
The first part is very simple:
So, to properly ACK the payload, return a 200 response with a payload of type: 1:
Thus, you need to return JSON object and not an array (maybe that's one of the problems with your code).
Additionally, endpoint must be able to respond to invalid requests as:
We will also do automated, routine security checks against your endpoint, including purposefully sending you invalid signatures. If you fail the validation, we will remove your interactions URL in the future and alert you via email and System DM.
One thing I noticed is that Discord sends their headers lowercased! Another problem is that you use:
$raw_body = file_get_contents('php://input'); that doesn't look right.
Finally, if you know node.JS take a look at my working example: https://github.com/iaforek/discord-interactions

Converting PHP response string to JSON in Android, always says JSON string is Malformed

I am trying to send data from MSSQL table on server to Android app via PHP. I am using Volley to send the request for data.
The issue is that no matter what I try, Android says the returned JSON encoded string is "Malformed".
I have put the returned JSON string "response" into online JSON decoders and it displays perfectly, yet Andoid says: "Syntax error, malformed JSON{"data":[{"claimNumber":"f265e5e.....}]".
However, if I hardcode a copy and paste of the returned "response" string into a variable "input" in the Android
response function, it works perfectly.
JSONObject jObj = new JSONObject(response); ** Fails - Android says Malformed.
JSONObject jObj = new JSONObject(input); ** Android uses it with no issues.
The following is the method in Android used to receive the PHP response. Have included Log outputs of both the "response" string and
the manually entered "input" string. They are identical, yet Android won't use the actual "response" string.
public void onResponse(String response) {
if (response.equals("failed")) {
Log.d("failed", "failed");
callback.onResponse(null);
return;
}
try {
// Android sees the response returned from the PHP function as always Malformed.
Log.d("response", response);
D/response: - Syntax error, malformed JSON {"data":[{"claimNumber":"f265e5e6513070abd1f711232cfd3a491075f15bc9714cf723e373f02e71a214","xlsLine":"8b3490231cd923c133989dd93574de131b6c388a86153a74eb6ae2507193a008c9d3d0264452cc1bd1113d5a722f3ea7975f322461f486be96e789424459e20bcbaf878f5d0efe09426b90c046d881100e166ef0bfcf8721266383aabf3837a213854e8425e92b722791640576d3c0ce7722ff3de2e6005c85df840bea3b10982b7bcf8bec3398ea03e08e6a2879cb29e0e6c3c05370e1c2cf819e6156991c762b2247e8a5b51edb852bb371aca011eccaa581ed577e74d6bf0f2a71e43e7751e3fa6e5f68c2a6e4ccd4fc338fc2a2ea4a9d98018c52fe5953741a53d7f7a6f1c1e57901d64c957dc1776ab0ed28f5754f7d44008ebc5864cfd34dd3b1f1bf82db49674b8e7a3e381882f7cc1035bfdba114280f6c173e337d1813fb47a9b1aaf1d52faac197f90cced9eea754cf441cb262b3117444ad3a265cefb9593d40cdb8a3ae0235cc06baffbcac493bf45852908b014f063c29d85347e808e7ed4be8688327bf3280759ea1ff187287dcabaaee8859a6da782cd2451e2911fe16ca7d","markerColor":"0","edited":"0"}]}
// If I copy the returned "response" string manually into a variable "input", Android says it's fine.
String input = "{\"data\":[{\"claimNumber\":\"f265e5e6513070abd1f711232cfd3a491075f15bc9714cf723e373f02e71a214\",\"xlsLine\":\"8b3490231cd923c133989dd93574de131b6c388a86153a74eb6ae2507193a008c9d3d0264452cc1bd1113d5a722f3ea7975f322461f486be96e789424459e20bcbaf878f5d0efe09426b90c046d881100e166ef0bfcf8721266383aabf3837a213854e8425e92b722791640576d3c0ce7722ff3de2e6005c85df840bea3b10982b7bcf8bec3398ea03e08e6a2879cb29e0e6c3c05370e1c2cf819e6156991c762b2247e8a5b51edb852bb371aca011eccaa581ed577e74d6bf0f2a71e43e7751e3fa6e5f68c2a6e4ccd4fc338fc2a2ea4a9d98018c52fe5953741a53d7f7a6f1c1e57901d64c957dc1776ab0ed28f5754f7d44008ebc5864cfd34dd3b1f1bf82db49674b8e7a3e381882f7cc1035bfdba114280f6c173e337d1813fb47a9b1aaf1d52faac197f90cced9eea754cf441cb262b3117444ad3a265cefb9593d40cdb8a3ae0235cc06baffbcac493bf45852908b014f063c29d85347e808e7ed4be8688327bf3280759ea1ff187287dcabaaee8859a6da782cd2451e2911fe16ca7d\",\"markerColor\":\"0\",\"edited\":\"0\"}]}";
// Log showing Androids interpretation of the manually entered "input" string
// It matches the "response" string exactly yet "response" string fails.
Log.d("input", input);
D/input: {"data":[{"claimNumber":"f265e5e6513070abd1f711232cfd3a491075f15bc9714cf723e373f02e71a214","xlsLine":"8b3490231cd923c133989dd93574de131b6c388a86153a74eb6ae2507193a008c9d3d0264452cc1bd1113d5a722f3ea7975f322461f486be96e789424459e20bcbaf878f5d0efe09426b90c046d881100e166ef0bfcf8721266383aabf3837a213854e8425e92b722791640576d3c0ce7722ff3de2e6005c85df840bea3b10982b7bcf8bec3398ea03e08e6a2879cb29e0e6c3c05370e1c2cf819e6156991c762b2247e8a5b51edb852bb371aca011eccaa581ed577e74d6bf0f2a71e43e7751e3fa6e5f68c2a6e4ccd4fc338fc2a2ea4a9d98018c52fe5953741a53d7f7a6f1c1e57901d64c957dc1776ab0ed28f5754f7d44008ebc5864cfd34dd3b1f1bf82db49674b8e7a3e381882f7cc1035bfdba114280f6c173e337d1813fb47a9b1aaf1d52faac197f90cced9eea754cf441cb262b3117444ad3a265cefb9593d40cdb8a3ae0235cc06baffbcac493bf45852908b014f063c29d85347e808e7ed4be8688327bf3280759ea1ff187287dcabaaee8859a6da782cd2451e2911fe16ca7d","markerColor":"0","edited":"0"}]}
JSONObject jObj = new JSONObject(input);
jArray = jObj.getJSONArray("data");
} catch (JSONException e) {
e.printStackTrace();
}
}
// GSON print of JSON Object from the manually entered "input" variable.
I/System.out: {
"nameValuePairs": {
"data": {
"values": [
{
"nameValuePairs": {
"claimNumber": "f265e5e6513070abd1f711232cfd3a491075f15bc9714cf723e373f02e71a214",
"xlsLine": "8b3490231cd923c133989dd93574de131b6c388a86153a74eb6ae2507193a008c9d3d0264452cc1bd1113d5a722f3ea7975f322461f486be96e789424459e20bcbaf878f5d0efe09426b90c046d881100e166ef0bfcf8721266383aabf3837a213854e8425e92b722791640576d3c0ce7722ff3de2e6005c85df840bea3b10982b7bcf8bec3398ea03e08e6a2879cb29e0e6c3c05370e1c2cf819e6156991c762b2247e8a5b51edb852bb371aca011eccaa581ed577e74d6bf0f2a71e43e7751e3fa6e5f68c2a6e4ccd4fc338fc2a2ea4a9d98018c52fe5953741a53d7f7a6f1c1e57901d64c957dc1776ab0ed28f5754f7d44008ebc5864cfd34dd3b1f1bf82db49674b8e7a3e381882f7cc1035bfdba114280f6c173e337d1813fb47a9b1aaf1d52faac197f90cced9eea754cf441cb262b3117444ad3a265cefb9593d40cdb8a3ae0235cc06baffbcac493bf45852908b014f063c29d85347e808e7ed4be8688327bf3280759ea1ff187287dcabaaee8859a6da782cd2451e2911fe16ca7d",
"markerColor": "0",
"edited": "0"
}
}
]
}
}
}
Have tried php output with and without slashes. No change... still malformed.
Have tried stripping non-standard chars. There are none.
Have forced charset "UTF-8". No difference.
Have searched and tried every conceivable solution for this on Google. Nothing works.
I'm at a loss as to what to try next. Totally confused on why Android can't use the returned Json string,
but can use it if you manually take the same string and put it in a variable in the code directly.
Can someone tell me if this is a known bug, if the JSON really is malformed or if something else comes to mind?
Thank you
EDIT
Here is the PHP that creates the json to return to Android.
$options = array( "Scrollable" => SQLSRV_CURSOR_KEYSET );
$stmt2 = sqlsrv_query( $conn3, $tsql1, $params, $options);
$row_count = sqlsrv_num_rows($stmt2);
if ($row_count === false) {
echo("failed");
} else {
while( $userClaims = sqlsrv_fetch_array($stmt2, SQLSRV_FETCH_ASSOC) ) {
$claimNum = $userClaims['ClaimNumber'];
$xls = $userClaims['XLS'];
$color = $userClaims['Color'];
$edited = "0";
$keyvals = (object) array("claimNumber" => $claimNum, "xlsLine" => $xls, "markerColor" => $color, "edited" => $edited);
array_push($response,$keyvals);
}
$encoded = json_encode(array('data' => $response));
EDIT 2
The following is the complete php section of code that creates the json return string. The array is initialized at the top. Have written the php json string to a text file on server and copied the text to a json checker and it works fine.
$response = array();
$i = 0;
$param1 = $token;
$params = array( &$param1);
$tsql1 = "SELECT * FROM Claims WHERE Token = ? AND DeletionFlag = 0";
$options = array( "Scrollable" => SQLSRV_CURSOR_KEYSET );
$stmt2 = sqlsrv_query( $conn3, $tsql1, $params, $options);
$row_count = sqlsrv_num_rows($stmt2);
if ($row_count === false) {
echo("failed");
} else {
while( $userClaims = sqlsrv_fetch_array($stmt2, SQLSRV_FETCH_ASSOC) ) {
$claimNum = $userClaims['ClaimNumber'];
$xls = $userClaims['XLS'];
$color = $userClaims['Color'];
$edited = "0";
$keyvals = (object) array("claimNumber" => $claimNum, "xlsLine" => $xls, "markerColor" => $color, "edited" => $edited);
array_push($response,$keyvals);
}
$encoded = json_encode(array('data' => $response));
echo $encoded;
}
sqlsrv_close($conn3);
Thank you for your help Andy. I finally figured it out. I found a line of code in the php file that was out of place. It was trying to json_decode an empty string. This is what was generating the extra 36 chars about the malformed string in my actual response. Once I moved it to the correct place, everything started working beautifully. Should have known better, most likely a blasted copy/paste error. Should teach me not to be lazy and actually type ALL my code. Thanks, again!!

PHP script receives GET instead of POST REQUEST

I am using PHP with XAMPP and Dialogflow to create a chat interface. In a simple intent(question) in Dialogflow, I have created a webhook to XAMPP regarding the question 'Who is X' (e.g. Paul, George). Therefore , I place a POST REQUEST in order to have access to the json form of this question in DIalogflow so that I can answer it as I want to. Specifically, the ultimate goal of this is to retrieve some data from a MySQL database in phpMyAdmin about this question and respond for example that 'X is a developer' or 'X is a financial analyst'. This is why wrote a php script which is the following:
<?php
$method = $_SERVER['REQUEST_METHOD'];
// Process when it is POST method
if ($method == 'POST') {
$requestBody = file_get_contents('php://input');
$json = json_decode($requestBody);
$text = $json->result->parameters;
switch($text) {
case 'given-name':
$name = $text->given-name;
$speech = $name . 'is a developer';
break;
default:
$speech = 'Sorry I did not get this. Can you repeat please?';
}
$response = new \stdClass();
$response->speech = "";
$response->displayText = "";
$respone->source = "webhook";
echo json_encode($response);
}
else
{
echo "Method not allowed";
}
?>
However, the output of this program is: Method not allowed.
Paradoxically enough $method has the value 'GET' so it identifies a GET REQUEST while Dialogflow explicitly states at the webhook page that
Your web service will receive a POST request from Dialogflow in the
form of the response to a user query matched by intents with webhook
enabled.
Hence I am wondering: why my php script cannot see and process the POST REQUEST from Dialogflow?
P.S. Questions close to mine are the following: Form sends GET instead of POST, Why is $_SERVER['REQUEST_METHOD'] always GET?.
It doesn't work because $_SERVER['REQUEST_METHOD'] == "GET" by default.
So you program execute the 'else' condition.
You need to submit a request with the POST method to change this value.
You can use
<form method="POST">
[...]
</form>
in your HTML, or
$.ajax({
url : "ajax_url.php",
type : 'POST',
data : 'data='+data,
[...]
});
in your AJAX JS code for example
Here i am doing same like you from below code your Query will be resolved,
index.php
<?php
require 'get_enews.php';
function processMessage($input) {
$action = $input["result"]["action"];
switch($action){
case 'getNews':
$param = $input["result"]["parameters"]["number"];
getNews($param);
break;
default :
sendMessage(array(
"source" => "RMC",
"speech" => "I am not able to understand. what do you want ?",
"displayText" => "I am not able to understand. what do you want ?",
"contextOut" => array()
));
}
}
function sendMessage($parameters) {
header('Content-Type: application/json');
$data = str_replace('\/','/',json_encode($parameters));
echo $data;
}
$input = json_decode(file_get_contents('php://input'), true);
if (isset($input["result"]["action"])) {
processMessage($input);
}
?>
get_enews.php
<?php
function getNews($param){
require 'config.php';
$getNews="";
$Query="SELECT link FROM public.news WHERE year='$param'";
$Result=pg_query($con,$Query);
if(isset($Result) && !empty($Result) && pg_num_rows($Result) > 0){
$row=pg_fetch_assoc($Result);
$getNews= "Here is details that you require - Link: " . $row["link"];
$arr=array(
"source" => "RMC",
"speech" => $getNews,
"displayText" => $getNews,
);
sendMessage($arr);
}else{
$arr=array(
"source" => "RMC",
"speech" => "No year matched in database.",
"displayText" => "No year matched in database.",
);
sendMessage($arr);
}
}
?>
php://input is a read-only stream that allows you to read raw data from the request body. In the case of POST requests, it is preferable to use php://input

Checking values of Json array using PHP

I have a json respond that I want to check and return values accordingly:
the Json code is:
{
"success": "true",
"result": "ok"
}
And I need to check the success status and return an array to the controller accordingly.
I was trying to decode and ask questions on the value as follow:
$obj = json_decode($response,true);
if ($obj['success'] =='true')
return array(
'error' => 0,
'msg' => sprintf("successfully")
);
I am not sure what i am doing wrong since I can't get the 0 in the error on array returns.
There is another json code that I need to deal with and it is this:
Negative Response:
{
“success” : “false” ,
“error”:{
“code”:"MANDATORY_FIELDS_MISSING",
"message”: “Phone number is a mandatory field"
}
}
The same goes with this.
I would be happy if you couls assist me with gettin it to work properly.
Thank you.
Arye
Actually your code working fine. You are confused with printing and returning.
Please check this:--
<?php
$response = '{"success": "true","result": "ok"}';
$obj = json_decode($response,true);
if ($obj['success'] =='true')
print_r (array(
'error' => 0,
'msg' => sprintf("successfully")
));
?>
Output:-- http://prntscr.com/729h1o
So i think instead of return you need to print it out.
And you can use var_dump as well as echo <pre/>;print_r(your array inside if) just for look a bit good.
code:
$json = '
{
"success": "true",
"result": "ok"
}';
$obj = json_decode($json, true);
if ($obj['success'] == 'true')
var_dump(array(
'error' => 0,
'msg' => 'successfully'
));
output:
array(2) {
'error' =>
int(0)
'msg' =>
string(12) "successfully"
}
When you run the code above, do you get the same output I see?

Why is Easyuniv REST API not Handling Errors?

I am writing a REST API and currently testing some things. I am trying to make it send an error response when it does not find anything in the database.
The part that is running (because i am testing currently by just entering the url into my browser) is below:
else if ($request->getHttpAccept() === 'xml')
{
if(isset($data['s']) && isset($data['n'])) {
$id = $db->getAlcoholIDByNameSize($data['n'], $data['s']);
$prices = $db->pricesByAlcohol($id);
}
if(isset($id)) {
$resData = array();
if(!empty($prices)) {
foreach($prices as $p) {
$store = $db->store($p['store']);
array_push($resData, array('storeID' => $p['store'], 'store_name' => $store['name'], 'store_gps' => $store['gps'], 'price' => round($p['price'], 2)));
}
RestUtils::sendResponse(200, json_encode($resData), 'application/json');
} else {
RestUtils::sendResponse(204, 'error', 'application/json');
}
} else {
RestUtils::sendResponse(204, 'error', 'application/json');
}
//RestUtils::sendResponse(501, "xml response not implemented", 'application/xml');
}
everything works fine if the queries return something to be stored in $id and $prices. If they do not exist in the database, however, it tries to load the page, and then goes back to the previous page you were on. You can see the behavior by going to:
http://easyuniv.com/API/alc/coorsa/2 <-- works
http://easyuniv.com/API/alc/coors/3 <-- works
http://easyuniv.com/API/alc/coorsa/5 <-- doesn't work(or anything else, the two above are the only ones)
here is my sendResponse function:
public static function sendResponse($status = 200, $body = '', $content_type = 'text/html')
{
$status_header = 'HTTP/1.1 ' . $status . ' ' . RestUtils::getStatusCodeMessage($status);
// set the status
header($status_header);
// set the content type
header('Content-type: ' . $content_type);
// pages with body are easy
if($body !== '')
{
$temp = json_decode($body);
$body = json_encode(array('result' => array('status' => $status, 'message' => RestUtils::getStatusCodeMessage($status)), 'data' => $temp));
// send the body
echo $body;
exit;
}
// we need to create the body if none is passed
else
{
$body = "else".json_encode(array('result' => array('status' => $status, 'message' => RestUtils::getStatusCodeMessage($status))));
echo $body;
exit;
}
}
I have tried debugging using echos but I cant seem to narrow down what the issue is. Any help would be appreciated, thanks.
The problem is that when there is no appropriate data found in the data base you are returning HTTP 204 which is telling the browser there is absolutely nothing for it to display. This is not true in your case.
You still want to output the message that there was nothing found.
To fix you need to replace the two instances of 204 in your code with 200.
I modified tested your code using: Note, nothing will display as is. To get the message to display change 204 to 200 in the $status_header variable.
<?php
$status_header = 'HTTP/1.1 204';
// set the status
header($status_header);
// set the content type
header('Content-type: text/html');
echo "Can you see me???";
?>
Note: When testing this always close the tab and use a fresh tab for each call or else it will look like it is loading data from the previous call, like you have explained.

Categories