When I call webservices and response convert into jsonp format, at that time response come correctly but it is download as a file. File format is not displayed. Just download file. I try below code.
$result = array(
'Result'=>'Error',
'ErrorMessage'=>'Please enter valid Data
);
header('Content-type: application/jsonp');
return json_encode($result);
I also try with echo and print replace of return keyword.
$result = array(
'Result'=>'Error',
'ErrorMessage'=>'Please enter valid Data
);
$this->output->set_content_type('application/json')->set_output(json_encode($result ));
Related
We are using Woocommerce for our ecom website and in order to automatically generate government-approved invoices for customers we use a certified online invoicing software.
I am making an API request to this invoicing software in order to retrieve the generated invoice document from their database, this is the code:
// On Order complete > Get document ID from order > access Moloni invoicing API > get document link GETPDFLINK > Sanitize the string and get Hash > generate the final document link > access it and download the PDF
function download_moloni_document_id( $order_id, $order ) {
// Retreive from the Database table moloni_api the access token from column main_token
global $wpdb;
$table_name = "db_invoicing_api";
$retrieve_data = $wpdb->get_results( "SELECT * FROM $table_name WHERE id = 1" );
foreach ($retrieve_data as $retrieved_data) {
$maintoken = $retrieved_data->main_token;
}
// Get document ID from the order
$documentid = get_post_meta($order->id, '_moloni_sent', true);
// Connect to moloni API and getpdflink
$url = "https://api.moloni.pt/v1/documents/getPDFLink/?access_token=$maintoken";
$postData = array(
'company_id' => '12345',
'document_id' => $documentid );
$arguments = array(
'method' => 'POST',
'headers' => array(
'Content-type: application/x-www-form-urlencoded'
),
'body' => $postData,
);
$response = wp_remote_post( $url, $arguments );
if ( is_wp_error( $response ) ) {
$error_message = $response->get_error_message();
return "Something went wrong: $error_message";
} else {
echo '<pre>';
var_dump( wp_remote_retrieve_body( $response ) );
echo '</pre>';
// jsondecode the string received by the API to remove backslashes, get and parse the URL and extract the HASH key
$response2 = wp_remote_retrieve_body($response);
parse_str(parse_url(json_decode($response2, true)['url'], PHP_URL_QUERY), $result);
$hash = $result['h'];
// Assemble the Invoice HTML download URL with the Hash and document ID
$fileUrlpdf = "https://www.moloni.pt/downloads/index.php?action=getDownload&h=$hash&d=$documentid&e=$loginmail&i=1&t=n";
$pdforderid = $order->id;
// Save the file with document id name to server location
$saveTopdf = "ftp://myserver/INVOICES/evo-$pdforderid.PDF";
file_put_contents(
$saveTopdf,
file_get_contents($fileUrlpdf)
);
} }
add_action( 'woocommerce_order_status_completed', 'download_moloni_document_id', 20, 2 );
In the end you can see I use
file_put_contents(
$saveTopdf,
file_get_contents($fileUrlpdf) );
in order to visit the link, retrieve the PDF and download it.
This works well then the link is generated successfully and sends to a direct download of the invoice PDF
The problem I have is is, sometimes there is an issue and the invoice PDF is not generated, this makes it so that the final link $fileUrlpdf does not lead to a download but instead to a web page with an error message saying something like "No Documents Found" which leads this code to download a PDF of dozens of pages containing the source code/HTML of that page. This is a problem because the PDFs (invoices) are later automatically printed by our system, so we sometimes end up with hundreds of pages of HTML code instead of the invoices.
I have tried to solve this in the following way through conditions:
to check if the download/PDF file exists
if (file_exists($fileUrlpdf)) {
file_put_contents(
$saveTopdf,
file_get_contents($fileUrlpdf)); }
one that would check the $response array for the error message and not proceed (because
$invalid = 'No Documents Found'; if (strpos($response, $valid) !== false) {echo 'No Documents found'; else { *download the PDF* } }
I have also considered the possibility of
checking if the page $fileUrlpdf would contain "No Documents Found", to not download it but I haven't been able to figure this one out either.
Bear with me as you can see my experience with PHP is limited so I would like to ask, what would be the best practice here? What approach would you suggest?
Thank you very much in advance for the attention and advice.
Either look at using the API to fetch the invoice/document and handle errors that way moloni.pt/dev
Or you could look at checking the Content-Type of the response headers as shown below
get_headers
$fileUrlpdf = "https://www.moloni.pt/downloads/index.php?action=getDownload&h=$hash&d=$documentid&e=$loginmail&i=1&t=n";
$fileHeaders = get_headers($fileUrlpdf, true)
if($fileHeaders['Content-Type'] === 'application/pdf') {
// PDF response
}
The API documentation shows this example:
$fileId = '1ZdR3L3qP4Bkq8noWLJHSr_iBau0DNT4Kli4SxNc2YEo';
$content = $driveService->files->export($fileId,
'application/pdf',
array('alt' => 'media')
);
How do I show the image in my HTML?
(I've already figured out how authorization with the Google API works.)
You can embed the raw image data using base64_encode
Your API call is returning a GuzzleHttp Response object, so you can get the raw data by calling:
$rawData = $response->getBody()->getContents();
// Alternatively, you should be able to cast it to a string (I would try the first method then this alternative if you want)
$rawData = (string) $response->getBody();
To embed that raw data as an html <img /> you can do something like:
// Convert to base64 encoding
$imageData = base64_encode($rawData);
// Get the content-type of the image from the response
$contentType = $response->getHeader("content-type");
// Format the image src: data:{mime};base64,{data}
$src = 'data: '.$contentType.';base64,'.$imageData;
// Echo out a sample image
echo '<img src="'.$src.'" />';
Source
I have download a file from the link & has to save in my local system folder or in a remote server folder. The scenario is that: I have a mailgun domain, when I send a mail to it, Mailgun store function (store()) stores it with all attachments & notifies me. The response from mailgun is catched in catch_email_attachment(), I'm able fetch the response & got the link of attached files. When I run the link directly in browser it gives me the attached file, no problem on that. But I need to download the file inside catch_email_attachment() & to save it in a folder.
The downloadable file is as: "https://API:<API-KEY>#api.mailgun.net/v2/domains/sandboxa6e6ebce3f68475aa3xxxxxxxd60.mailgun.org/messages/eyJwIjogZmFsc2UsICJrIjogImQ0MmZjxxxxxxxxxxxxxxDQwNy1iYzhlLTA2OWMxY2U3MDg2NCIsIxxxxxxxxxxxxxx1Y2UiLCAiYyI6ICJpYWR0cmFpbGVycyJ9/attachments/0"
My codes are below:
public function catch_email_attachment()
{
$data = $this->input->post(null, true);
if (!empty($data)) {
if (isset($data['attachments'])) {
/*
Output of $data['attachments'] is below:
[{"url": "https://api.mailgun.net/v2/domains/sandboxa6e6ebce3f68475aa3xxxxxxxd60.mailgun.org/messages/eyJwIjogZmFsc2UsICJrIjogImQ0MmZjxxxxxxxxxxxxxxDQwNy1iYzhlLTA2OWMxY2U3MDg2NCIsIxxxxxxxxxxxxxx1Y2UiLCAiYyI6ICJpYWR0cmFpbGVycyJ9/attachments/0", "content-type": "image/jpeg", "name": "xxxxxxx.jpeg", "size": 9498}]
*/
copy('https://API:key-e5ae9afab1fa9xxxxxxxxxxxxxxa95a#api.mailgun.net/v2/domains/sandboxa6e6ebce3f68475axxxxxxxxxxxxxxxxxxxxxxxxxxxx.mailgun.org/messages/eyJwIjogZmFsc2UxxxxxxxxxxxxxxxxxxxxxxxxxxxxmUtNDQwNy1iYzhlLTA2OWMxY2U3MDg2NCIxxxxxxxxxxxxxxxxxxxxxxxxxxxx1Y2UiLCAiYyI6ICJpYWR0cmFpbGVycyJ9/attachments/0', '/var/www/download_loc/');
}
}
}
I have refered:
https://stackoverflow.com/a/26330976/4229270
https://stackoverflow.com/a/6594030/4229270
https://stackoverflow.com/a/724449/4229270
Can you help me to solve the issue... Thanking in advance.
It looks like $data['attachments'] is a json array so you need something like:
$attachments = json_decode($data['attachments']);
$api_key = 'APIKEY';
if ($attachments) {
foreach ($attachments as $attachment) {
$context = stream_context_create(array(
'http' => array(
'header' => "Authorization: Basic " . base64_encode("API:$api_key")
)
));
file_put_contents('/var/www/download_loc/' . $attachment->name, file_get_contents($attachment->url, false, $context));
}
}
The above answer is surly helpful for me. What I have done & got is:
Mailgun will give response to our hook function which we set in our maingun domain. Catch the response from Mailgun as:
$data = $this->input->post(null, true);
$attachments = json_decode($data['attachments']);
$apikey = 'API:<API_KEY>#';
foreach ($attachments as $attachment) {
$st = strpos($attachment->url, 'https://');
if ($st !== false) {
$attachment->url = str_replace('https://', 'https://'.$apikey, $attachment->url);
$temp_name = $attachment->name;
$file_path = '<PATH_TO_DOWNLOAD>'.$temp_name;
copy($attachment->url, $file_path); // Downloading file to our path
}
}
You have to check endpoint from Mailgun response. And, have to set respective in or code. Also, we have to set API KEY & PATH TO DOWNLOAD.
The storage link from Mailgun will be to "xx.api.mailgun.net" over "api.mailgun.net". It will be like "si.api.mailgun.net", "so.api.mailgun.net", "se.api.mailgun.net", "sw.api.mailgun.net", etc.. The URL to obtain the attachment data would be
Eg: https://API:key-60mvxxxxxxxxxxxxxxxx#sw.api.mailgun.net/v3/domains/YOUR_MAILGUN_DOMAIN/messages/xxxxxxxxxxxxxxxxxxxxxxxxxxx=/attachments/0
The data returned from the API will return the URL to obtain the stored message : (items > attachments > url)
Please refer: https://documentation.mailgun.com/en/latest/api-sending.html#retrieving-stored-messages
PHP
<?php
header('Content-type: application/json');
$return['ip'] = $_SERVER['REMOTE_ADDR'];
$results[] = array(
'ip' => $return['ip']
);
echo json_encode($results);
?>
jQuery
$.getJSON("http://domain.com/json/",
function(data){
console.log(data.ip);
});
});
But when I run the jQuery I've checked Fire bug and it says the following
GET http://domain.com/json/ 200 OK 81ms
And doesn't respond with the IP that I requested for. Have I missed something?
UPDATED CODE
PHP
<?php
header('Content-type: application/json');
$return['ip'] = $_SERVER['REMOTE_ADDR'];
$results = array(
'ip' => $return['ip']
);
echo json_encode($results);
?>
jQuery
$.getJSON("http://domain.com/json/", function(data){
console.log(data.ip);
});
Firebug Error
SyntaxError: invalid label {"ip":"XXX.XXX.XXX.X"}
An arrow points at the first quotation mark just before the word ip.
You are returning:
[{'ip': 'XXX.XXX.XXX.XXX'}]
But you are treating it as if you are returning:
{'ip': 'XXX.XXX.XXX.XXX'}
You either need to change your JavaScript to console.log(data[0].ip) or change your PHP to: $results = array( ... ); rather than $results[] = array( ... );
Either will fix your problem. :)
I have PHP generating JSON data but I am having a problem making a example.json file from it. What am I doing wrong? I just get a blank screen.
<?php
require('wp-load.php');
$EM_Events = EM_Events::get( array(
'scope'=>'future',
'orderby'=>'event_start_date,event_start_time',
'limit'=>1,
'owner'=>false,
'category'=>'6,7,8,10,11,12,13,14')
);
foreach ($EM_Events as $event) {
//Event Detail
$event_id = esc_html($event->event_id);
$event_name = esc_html($event->name);
$events[] = array(
'event_id'=> $event_id,
'event_name'=> $event_name,
);
}
$response['events'] = $events;
$fp = fopen('example.json', 'w');
fwrite($fp, json_encode($response));
fclose($fp);
?>
Try using a response sniffing tool like Fiddler http://www.fiddler2.com/ or use the network tab of the browser's developer tools like Firebug http://getfirebug.com/ Maybe the content came down just fine, it's just that your browser doesn't know how to render it.