fix(bridge): resolve corrupted PDF downloads and improve token handling
Relocate PDF and commitment form download logic from shortcode execution to the `template_redirect` hook to prevent HTML output from corrupting binary streams. Key improvements: - Moved download interception to `template_redirect` to ensure clean headers and prevent partial file downloads caused by early buffer output. - Replaced direct `get_user_meta` calls with `IFNEX_User_Bridge::get_user_token` to support automatic token renewal and improved authentication reliability. - Added PDF signature validation (`%PDF` header check) to ensure integrity of remote file responses. - Updated Laravel base controller to include standard `AuthorizesRequests` and `ValidatesRequests` traits.
This commit is contained in:
parent
91984dbde3
commit
e5cc6a9d15
@ -1069,22 +1069,9 @@ function ifnex_order_detail_shortcode($atts) {
|
||||
}
|
||||
|
||||
|
||||
// Handle PDF download
|
||||
|
||||
$download_type = sanitize_text_field($_GET['download'] ?? '');
|
||||
if ($download_type && in_array($download_type, ['awb', 'invoice', 'label', 'import-invoice'])) {
|
||||
ifnex_handle_pdf_download($order_id, $download_type);
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
// Handle commitment form downloads (template / signed) — proxied با توکن لاراول
|
||||
if (in_array($download_type, ['commitment-template', 'commitment-signed'], true)) {
|
||||
$form_id = intval($_GET['form_id'] ?? 0);
|
||||
$type = ($download_type === 'commitment-signed') ? 'signed' : 'template';
|
||||
ifnex_handle_commitment_download($order_id, $form_id, $type);
|
||||
return '';
|
||||
}
|
||||
// ⚠️ هندلر دانلودها (PDF و تعهدنامه) به template_redirect منتقل شده —
|
||||
// اجرای آن داخل شورتکد یعنی بعد از چاپ HTML هدر قالب؛ خروجی باینری به
|
||||
// HTML میچسبد و با Content-Length ناهمخوان، PDF نیمهتمام دانلود میشود.
|
||||
|
||||
$bridge = new IFNEX_User_Bridge();
|
||||
$user_id = get_current_user_id();
|
||||
@ -1411,6 +1398,32 @@ function uploadCommitmentForm(orderId, formId, input) {
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// رهگیری درخواستهای دانلود قبل از هر خروجی صفحه (template_redirect)
|
||||
// اجرای دانلود داخل شورتکد یعنی بعد از چاپ HTML هدر قالب — بایتهای HTML
|
||||
// به ابتدای فایل میچسبند و با Content-Length ناهمخوان، فایل ناقص میرسد.
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
|
||||
add_action('template_redirect', 'ifnex_intercept_download_request', 1);
|
||||
|
||||
function ifnex_intercept_download_request(): void {
|
||||
$download = sanitize_text_field($_GET['download'] ?? '');
|
||||
$order_id = intval($_GET['order_id'] ?? 0);
|
||||
if (!$download || !$order_id) return;
|
||||
|
||||
if (in_array($download, ['awb', 'invoice', 'label', 'import-invoice'], true)) {
|
||||
ifnex_handle_pdf_download($order_id, $download); // exit داخل تابع
|
||||
}
|
||||
|
||||
if (in_array($download, ['commitment-template', 'commitment-signed'], true)) {
|
||||
ifnex_handle_commitment_download(
|
||||
$order_id,
|
||||
intval($_GET['form_id'] ?? 0),
|
||||
$download === 'commitment-signed' ? 'signed' : 'template'
|
||||
); // exit داخل تابع
|
||||
}
|
||||
}
|
||||
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
// آیکونهای SVG مدرن (سبک Heroicons)
|
||||
// ══════════════════════════════════════════════════════════════
|
||||
@ -1426,8 +1439,8 @@ function ifnex_handle_pdf_download($order_id, $download_type) {
|
||||
$api_url = get_option('ifnex_api_url', 'http://localhost:8000/api/v1');
|
||||
$download_url = rtrim($api_url, '/') . "/customer/orders/{$order_id}/pdf/{$download_type}";
|
||||
|
||||
$token = get_user_meta($user_id, 'ifnex_laravel_token', true);
|
||||
if (!$token) wp_die('توکن احراز هویت یافت نشد.');
|
||||
$token = $bridge->get_user_token($user_id); // با تجدید خودکار در صورت انقضا/حذف
|
||||
if (!$token) wp_die('توکن احراز هویت در دسترس نیست — لطفاً دوباره وارد شوید.');
|
||||
|
||||
$response = wp_remote_get($download_url, array(
|
||||
'headers' => array(
|
||||
@ -1443,8 +1456,17 @@ function ifnex_handle_pdf_download($order_id, $download_type) {
|
||||
if ($status_code !== 200) wp_die('خطا در دانلود فایل.');
|
||||
|
||||
$file_content = wp_remote_retrieve_body($response);
|
||||
|
||||
// پاسخ باید PDF خام باشد؛ وگرنه بهجای فایل خراب، پیام واضح نمایش بده
|
||||
if (substr($file_content, 0, 4) !== '%PDF') {
|
||||
wp_die('پاسخ سرور یک فایل PDF معتبر نبود — لطفاً دوباره تلاش کنید.');
|
||||
}
|
||||
|
||||
$filename = strtoupper($download_type) . '-' . $order['data']['awb_no'] . '.pdf';
|
||||
|
||||
// پاکسازی همه بافرهای خروجی تا جریان فایل تمیز و همطول با Content-Length ارسال شود
|
||||
while (ob_get_level()) { ob_end_clean(); }
|
||||
|
||||
nocache_headers();
|
||||
header('Content-Type: application/pdf');
|
||||
header('Content-Disposition: attachment; filename="' . $filename . '"');
|
||||
@ -1471,8 +1493,8 @@ function ifnex_handle_commitment_download($order_id, $form_id, $type = 'template
|
||||
$endpoint = ($type === 'signed') ? 'download' : 'template';
|
||||
$download_url = rtrim($api_url, '/') . "/customer/orders/{$order_id}/commitment-forms/{$form_id}/{$endpoint}";
|
||||
|
||||
$token = get_user_meta($user_id, 'ifnex_laravel_token', true);
|
||||
if (!$token) wp_die('توکن احراز هویت یافت نشد.');
|
||||
$token = $bridge->get_user_token($user_id); // با تجدید خودکار در صورت انقضا/حذف
|
||||
if (!$token) wp_die('توکن احراز هویت در دسترس نیست — لطفاً دوباره وارد شوید.');
|
||||
|
||||
$response = wp_remote_get($download_url, array(
|
||||
'headers' => array(
|
||||
@ -1493,6 +1515,12 @@ function ifnex_handle_commitment_download($order_id, $form_id, $type = 'template
|
||||
}
|
||||
|
||||
$file_content = wp_remote_retrieve_body($response);
|
||||
|
||||
// پاسخ باید فایل باینری باشد؛ شروع با '<' یعنی HTML/خطا برگشته
|
||||
if ($file_content === '' || $file_content[0] === '<') {
|
||||
wp_die('پاسخ سرور یک فایل معتبر نبود — لطفاً دوباره تلاش کنید.');
|
||||
}
|
||||
|
||||
$awb = $order['data']['awb_no'] ?? ('order-' . $order_id);
|
||||
|
||||
// تشخیص نوع محتوا و نام فایل از روی هدر Laravel
|
||||
@ -1511,6 +1539,9 @@ function ifnex_handle_commitment_download($order_id, $form_id, $type = 'template
|
||||
$filename .= '.' . $ext;
|
||||
}
|
||||
|
||||
// پاکسازی همه بافرهای خروجی تا جریان فایل تمیز و همطول با Content-Length ارسال شود
|
||||
while (ob_get_level()) { ob_end_clean(); }
|
||||
|
||||
nocache_headers();
|
||||
header('Content-Type: ' . $ctype);
|
||||
header('Content-Disposition: attachment; filename="' . $filename . '"');
|
||||
|
||||
@ -855,8 +855,8 @@ function ifnex_download_order_pdf_ajax() {
|
||||
$download_url = rtrim($api_url, '/') . "/customer/orders/{$order_id}/pdf/{$download_type}";
|
||||
|
||||
// ارسال درخواست به لاراول با توکن احراز هویت
|
||||
$token = get_user_meta($user_id, 'ifnex_laravel_token', true);
|
||||
if (!$token) wp_send_json_error('توکن احراز هویت یافت نشد.');
|
||||
$token = $bridge->get_user_token($user_id); // با تجدید خودکار در صورت انقضا/حذف
|
||||
if (!$token) wp_send_json_error('توکن احراز هویت در دسترس نیست — لطفاً دوباره وارد شوید.');
|
||||
|
||||
$response = wp_remote_get($download_url, array(
|
||||
'headers' => array(
|
||||
@ -908,8 +908,8 @@ function ifnex_get_commitment_forms_ajax() {
|
||||
$api_url = get_option('ifnex_api_url', 'http://localhost:8000/api/v1');
|
||||
$url = rtrim($api_url, '/') . "/customer/orders/{$order_id}/commitment-forms";
|
||||
|
||||
$token = get_user_meta($user_id, 'ifnex_laravel_token', true);
|
||||
if (!$token) wp_send_json_error('توکن احراز هویت یافت نشد.');
|
||||
$token = $bridge->get_user_token($user_id); // با تجدید خودکار در صورت انقضا/حذف
|
||||
if (!$token) wp_send_json_error('توکن احراز هویت در دسترس نیست — لطفاً دوباره وارد شوید.');
|
||||
|
||||
$response = wp_remote_get($url, array(
|
||||
'headers' => array(
|
||||
@ -973,8 +973,8 @@ function ifnex_upload_commitment_form_ajax() {
|
||||
$api_url = get_option('ifnex_api_url', 'http://localhost:8000/api/v1');
|
||||
$url = rtrim($api_url, '/') . "/customer/orders/{$order_id}/commitment-forms/{$form_id}/upload";
|
||||
|
||||
$token = get_user_meta($user_id, 'ifnex_laravel_token', true);
|
||||
if (!$token) wp_send_json_error('توکن احراز هویت یافت نشد.');
|
||||
$token = $bridge->get_user_token($user_id); // با تجدید خودکار در صورت انقضا/حذف
|
||||
if (!$token) wp_send_json_error('توکن احراز هویت در دسترس نیست — لطفاً دوباره وارد شوید.');
|
||||
|
||||
$multipart = new CURLFile($upload['file'], $file['type'], $file['name']);
|
||||
$post_fields = array(
|
||||
|
||||
@ -2,12 +2,10 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
|
||||
abstract class Controller
|
||||
{
|
||||
//
|
||||
use AuthorizesRequests, ValidatesRequests;
|
||||
}
|
||||
|
||||
class CustomerOrderController
|
||||
{
|
||||
// ...
|
||||
}
|
||||
BIN
04_Laravel/storage/real-invoice.pdf
Normal file
BIN
04_Laravel/storage/real-invoice.pdf
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user