i want to sent a file from my server to my rest api on another server, but for some reason it is not getting the data i sent..
rest api php using slim framework:
$app->post
(
'/api/upload',
function () use ($app)
{
$logs = '/home/logs';
//error_log(print_r($_FILES, 1), 3, $logs . '/export16.log');
try
{
$data = file_get_contents('php://input'); // EMPTY!!!!
error_log(print_r(count($data), 1), 3, $logs . '/export16.log');
}
catch(Exception $e)
{
error_log(print_r($data, 1), 3, $logs . '/export16err.log');
}
}
);
nodejs using request module:
fs.createReadStream('myfile.zip')
.pipe
(
request.post
(
UPLOAD_URL,
function (error, response, body)
{
//console.log(response);
if (!error && response.statusCode == 200)
{
//console.log(repons);
}
}
)
);
also tried with this code: using form-data module as explained in the docs
var r = request.post(UPLOAD_URL, function optionalCallback (err, httpResponse, body) {
if (err) {
return console.error('upload failed:', err);
}
console.log(httpResponse);
console.log('Upload successful! Server responded with:', body);
})
var form = r.form();
form.append('my_file', fs.createReadStream('file.zip') );
they both don't work and i get not data in my php:input,
i see the header content type: application/zip is set, but nothing else, somethign is missing maybe?
_header: 'POST /api/upload HTTP/1.1\r\nhost: xyz.com\r\ncontent-type: a
pplication/zip\r\nConnection: keep-alive\r\nTransfer-Encoding: chunked\r\n\r\n',
any ideas what i'm doing wrong?
Turns out i had to set the content length :)
Related
Trying to implement the Checkout-PHP-SDK paypal API to createOrder JS call.As far as I understand I have to send the data from php file to js approval form. But I am getting an error when I press the "PayPal Pay" button.
The JS codes are like below :
<div id="paypal-button-container"></div>
<script>
function loadAsync(url, callback) {
var s = document.createElement('script');
s.setAttribute('src', url); s.onload = callback;
document.head.insertBefore(s, document.head.firstElementChild);
}
// Usage -- callback is inlined here, but could be a named function
loadAsync('https://www.paypal.com/sdk/js?client-id=AQgUM6x3URK1A-rcNIq56covuc0CYGv3pb5sYeL6-cqsO1HYV2CV6h4ur6BCly_1YYd3-UOMTNGtwQXd¤cy=USD&disable-funding=card', function() {
paypal.Buttons({
// Call your server to set up the transaction
createOrder: function(data, actions) {
return fetch('https://example.com/TESTS.php', {
method: 'post'
}).then(function(res) {
return res.json();
}).then(function(orderData) {
return orderData.id;
});
},
// Call your server to finalize the transaction
onApprove: function(data, actions) {
return fetch('/demo/checkout/api/paypal/order/' + data.orderID + '/capture/', {
method: 'post'
}).then(function(res) {
return res.json();
}).then(function(orderData) {
// (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()
// (2) Other non-recoverable errors -> Show a failure message
// (3) Successful transaction -> Show confirmation or thank you
// This example reads a v2/checkout/orders capture response, propagated from the server
// You could use a different API or structure for your 'orderData'
var errorDetail = Array.isArray(orderData.details) && orderData.details[0];
if (errorDetail && errorDetail.issue === 'INSTRUMENT_DECLINED') {
return actions.restart(); // Recoverable state, per:
// https://developer.paypal.com/docs/checkout/integration-features/funding-failure/
}
if (errorDetail) {
var msg = 'Sorry, your transaction could not be processed.';
if (errorDetail.description) msg += '\n\n' + errorDetail.description;
if (orderData.debug_id) msg += ' (' + orderData.debug_id + ')';
return alert(msg); // Show a failure message (try to avoid alerts in production environments)
}
// Successful capture! For demo purposes:
console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
var transaction = orderData.purchase_units[0].payments.captures[0];
alert('Transaction '+ transaction.status + ': ' + transaction.id + '\n\nSee console for all available details');
// Replace the above to show a success message within this page, e.g.
// const element = document.getElementById('paypal-button-container');
// element.innerHTML = '';
// element.innerHTML = '<h3>Thank you for your payment!</h3>';
// Or go to another URL: actions.redirect('thank_you.html');
});
}
}).render('#paypal-button-container');
})
</script>
The php file is like this :
<?php
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
use PayPalCheckoutSdk\Core\PayPalHttpClient;
use PayPalCheckoutSdk\Core\SandboxEnvironment;
use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
require __DIR__ . '/Checkout-PHP-SDK-develop/vendor/autoload.php';
// Creating an environment
$clientId = "AQgUM7x3URK1A-rcNIq56covuc0CYGv3pb5sYeL6-cqsO1HYV2CV6h4ur6BCly_1YYd3-UOMTNGtwQXd";
$clientSecret = "EDm88hmcFd6arhd7vaJ6d9AWjIvCScR6E6s0eM3OKqwf1uZt0G0KlLNUXG057vesyXR4eYP3RKDLJBz8";
$environment = new SandboxEnvironment($clientId, $clientSecret);
$client = new PayPalHttpClient($environment);
$request = new OrdersCreateRequest();
$request->prefer('return=representation');
$request->body = [
"intent" => "CAPTURE",
"purchase_units" => [[
//"reference_id" => "test_ref_id1",
"amount" => [
"value" => "100.00",
"currency_code" => "USD"
]
]],
"application_context" => [
"cancel_url" => "https://example.com/cancelled",
"return_url" => "https://example.com/success"
]
];
try {
$response = $client->execute($request);
print_r($response);
}catch (HttpException $ex) {
// echo $ex->statusCode;
print_r($ex->getMessage());
}
if(isset($_POST['id'])) {
$od_id = $response->result->id;
//echo $od_id;
$request1 = new OrdersCaptureRequest($od_id);
$request1->prefer('return=representation');
try {
// Call API with your client and get a response for your call
$response1 = json_encode($client->execute($request1));
return $response1;
// If call returns body in response, you can get the deserialized version from the result attribute of the response
return $request1;
}catch (HttpException $ex) {
echo $ex->statusCode;
// print_r($ex->getMessage());
}
}
Should I create, and catch the order in php file and then send it to JS? Actually is it the proper way to send the data? Any help would be highly appreciated. Thanks.
I have added CAPTURE method to the php file. and now it looks like above.
Each of your routes (the create route, and the capture route) must return a response that is a JSON string, and no other text nor HTML. print_r is not suitable.
I am posting data to Laravel and expect a success response, but it catches the exception TypeError: Network request failed. Using get methods and login post methods using Laravel passport works all fine.
Adding 'Content-Type': 'application/json' to headers creates Network request failed for the login methods.
Postman returns valid errors or success, so works totally as expected.
Debugging showed that the request has been sent to Laravel and routing is correct as Visual Studio Code debugger stops at a breakpoint at return response.
public function postMessages()
{
...
return response()->json(['success' => 'success'], 200);
}
Route::middleware('auth:api')->group(function () {
Route::post('messages', 'Api\ChatController#postMessages');
});
export const fetchApi = async (endPoint, method = 'get', body = {}) => {
const accessToken = authSelectors.get().tokens.access.value;
const accessType = authSelectors.get().tokens.access.type;
let headers = {
...(accessToken &&
{
Authorization: `${accessType} ${accessToken}`
}
)
};
let response;
if (method=='get' || Object.keys(body)==0 ) {
response = await fetch(`${apiConfig.url}${endPoint}`, {
method: method,
headers: headers
});
} else {
var formData = new FormData();
Object.keys(body).forEach(type => {
formData.append(type, body[type]);
});
response = await fetch(`${apiConfig.url}${endPoint}`, {
method: method,
headers: headers,
body: formData
});
console.log('fetch response: ' + JSON.stringify(response));
}
let responseJsonData = await response.json();
return responseJsonData;
}
export const postMessages = (eidug, type, name, messages) => fetchApi('/message', 'post', {
'eidug': eidug,
'type': type,
'name': name,
'messages': messages
});
I expect a response without any exception like Postman. What can be going wrong?
Have you enabled CORS in the backend? Once open inspect->network and then run fetch. Show if there are any errors.
I am using Laravel apis for my project. The API is working fine when I use curl to access it.
curl -H "Content-Type: application/json" -X POST -d '{"username":"xyz","password":"xyz", "filterZip":"123123"}' http://localhost:8080/api/signup {"error":{"message":"User with specified email address already started sign up process, but did not finished it. Please sign in regulary to continue sign up process.","errorCode":"020102"}}
However when I call if from nodejs app. I am unable to access the error Json Object from the response.
From Nodejs I am calling my laravel API
fetch(API_URI + '/signup', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(requestBody)
}).then(checkResponse)
.then(response => {
userData = response.data;
req.session.user = {
username: userData.displayName || userData.email,
data: userData,
auth: authData
};
req.session.resession = true; // tell ssrCache to act
return res.status(200).json(req.session);
})
.catch(status,error) => {
console.log('Request failed', error);
req.session.user = null;
req.session.resession = true; // tell ssrCache to act
return res.status(200).json(req.session);
});
});
const checkResponse = (response) => {
if (response.status >= 200 && response.status < 300) {
return response.json();
}
var error = new Error(response);
error.code = object.error.errorCode;
throw error;
}
On the Laravel API end following code is used to return response.
public function respondError($errorId, $statusCode, $message = 'Unknown') {
$this->setHttpStatusCode($statusCode);
$errorCode = ErrorHelper::generateErrorCode($this->controllerErrorId, $this->methodErrorId, $errorId);
if (API_LOG_ERROR_CODES) { ErrorHelper::logErrorCode($errorCode, $message); }
return $this->respond([
'error' => [
'message' => $message,
'errorCode' => $errorCode
]
]);
}
public function respond($dataForJson, $headers = []) {
return response()->json($dataForJson, $this->getHttpStatusCode(), $headers);
}
OK I figured it out.
The issue was with my handling of response. In the response I was not converting the response to response.json() whenever the response.status was greater than 300. once I did that I was able to extract the required json object. Following is a better approach for handling response.
const checkResponse = (response) => {
if (response.status >= 200 && response.status < 300) {
return response.json();
}
return reject(response.status, response.json());
}
I am using JS Engage sdk to call saveEmail API. I am getting an error in API response call back but not able to get the response.
ibmIMCIntegration.oAuthClientId = value["IBMIMC"].oAuthClientId;
ibmIMCIntegration.oAuthClientSecret = value["IBMIMC"].oAuthClientSecret;
ibmIMCIntegration.oAuthRefreshToken = value["IBMIMC"].oAuthRefreshToken;
// var arrOfClickThroughs = [{clickThroughName:"ingagechatbutton",clickThroughType:2,clickThroughURL:$scope.messangerID}];
var parameters = {
header:{
mailingName:$scope.mailingName,
subject: $scope.subject,
listId: 85326,
fromName: $scope.fromName,
fromAddress: $scope.fromAddress,
replyTo: $scope.replyTo,
visibility: 1,
encoding: 6,
trackingLevel: 2,
clickHereMessage: false
},
messageBodies:{
htmlBody:newSource
},
// clickThroughs:{
// clickThrough:arrOfClickThroughs
// },
forwardToFriend:{
forwardType:0
}
};
ibmIMCIntegration.parameters = JSON.stringify(parameters);
var userJson = {
type:"saveMailing",
options:ibmIMCIntegration,
};
console.info("List IBM Template | User JSON:" +
JSON.stringify(userJson));
var url = 'api/db/invokeIBMIMCOperation.php';
$http.post(url, userJson)
.success(function(res) {
if (res) {
if(res.isSuccess === true) {
swal("", "Your template has been created successfully", "success");
document.getElementById("form1").reset();
}
else {
swal("", "Please try again", "error");
}
console.info(res);
}else{
swal("", "Please try again", "error");
}
});
Here is my API funciton call:
function saveMailing(engage,parameters,ctx){
engage.saveMailing(parameters,function(err, result) {
if (err) {
console.log('Failed to load Save aMailing: ' + err);
} else {
console.log(JSON.stringify(result));
}
});
}
where I am now getting result array. If I am sending wrong parameter then it print the error console but if I got success to save template then it just print "{}".
Is there anyway I can get the response. ?
I found the solution for getting response from the Engage node.js sdk.
The reason behind getting the null response is Sdk tries to delete the response. I don't know why they are deleting the response. sdk only sends error message response in call back.
For getting the success response :
Open the file engage-xml-api.js from engage-api/lib folder.
find delete(response.Envelope.Body.RESULT.SUCCESS); line and comment it.
You will get the successful response if your query is correct.
Thanks
I have the following:
YUI().use("io-form",
function(Y) {
var cfg = {
method: 'POST',
form: {
id: 'subscribe-form',
useDisabled: false
}
};
function login() {
Y.io('process.php', cfg);
Y.on('io:success', onSuccess, this);
Y.on('io:failure', onFailure, this);
};
function onSuccess(id,response,args) {
document.getElementById('myformmsg').innerHTML = response.responseText;
document.forms['myform'].reset();
};
function onFailure(id,response,args) {
document.getElementById('myformmsg').innerHTML = "Error, retry...";
document.forms['myform'].reset();
};
Y.on('click', login, '#myformbutton', this, true);
});
How does yui know whether to go into onSucces of onFailure. What do I have to return from PHP?
It depends on the header returned http status code.
let say status code 200, it will goes to onSuccess.
let say status code 500 (internal server error), it will goes to onFailure.
List of HTTP status code here: http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
If you have some fatal error in php, it will still returns status 200 because the request is successful.
If you would like to handle php errors, I would suggest you to have an json return like everytime on success:
{
status: 0, // Let say 0 for OK, -1 for Error, you can define more by yourself
results: <anything you want here>,
errors: <errors message/errors code for your ajax handler to handle>
}
it can be done in php like this:
$response = array(
'status' => 0,
'results' => 'something good ...',
'errors' => 'error message if status is -1'
);
echo json_encode($response);
In your javascript, you will be handling like this:
function onSuccess(id,response,args) {
var responseObj = Y.JSON.parse(response);
if (responseObj.status === 0) {
// Request and process by php successful
}
else {
// Error handling
alert(responseObj.errors);
}
};
Remember, if you wanted to use Y.JSON, you need to include 'json-parse', example:
YUI().use('json-parse', , function (Y) {
// JSON is available and ready for use. Add implementation
// code here.
});