diff --git a/01_Documents/STATUS.md b/01_Documents/STATUS.md
index c60a26e..660cbfe 100644
--- a/01_Documents/STATUS.md
+++ b/01_Documents/STATUS.md
@@ -261,6 +261,14 @@
- [x] تستهای Unit/Feature برای Phase 2 (24 تست، 77 assertion)
- [x] رفع باگ WalletController::balance()
- [x] حذف PaymentGatewayService قدیمی (استفاده نمیشد)
+- [x] زیباسازی داشبورد و صفحه لاگین Filament
+- [x] گسترش پلاگین IFNEX Bridge برای وردپرس:
+ - [x] ساخت `IFNEX_User_Bridge` برای مدیریت توکن Sanctum کاربران وردپرس
+ - [x] اضافه کردن شورتکد `[ifnex_wallet_balance]`
+ - [x] اضافه کردن شورتکد `[ifnex_transactions]`
+ - [x] اضافه کردن AJAX handlers برای کیف پول و تراکنشها
+ - [x] ساخت استایلهای CSS کامل برای تمام کامپوننتهای پلاگین
+ - [x] ایجاد صفحه تست در وردپرس: http://localhost/ifnexwp/?page_id=16
---
@@ -530,6 +538,15 @@ IFNEX-Logistics/
- رفع باگ CHECK constraint در migration discount_codes (enum type: percent → percentage)
- رفع باگ Wallet::isFrozen() — مدیریت null برای مقدار پیشفرض
- بهروزرسانی STATUS.md با کارهای انجامشده Phase 2
+- گسترش پلاگین IFNEX Bridge:
+ - ساخت `IFNEX_User_Bridge` برای مدیریت توکن Sanctum کاربران وردپرس
+ - اضافه کردن شورتکد `[ifnex_wallet_balance]` با نمایش موجودی کیف پول
+ - اضافه کردن شورتکد `[ifnex_transactions]` با لیست تراکنشهای کاربر
+ - اضافه کردن AJAX handlers برای موجودی کیف پول و تراکنشها
+ - ساخت استایلهای CSS کامل برای تمام کامپوننتهای پلاگین
+ - ایجاد صفحه تست در وردپرس: http://localhost/ifnexwp/?page_id=16
+ - رفع باگ صفحه لاگین Filament (MethodNotAllowed)
+ - حذف فایلهای سفارشی لاگین و بازگشت به پیشفرض Filament
diff --git a/03_WordPress/test-plugin.php b/03_WordPress/test-plugin.php
new file mode 100644
index 0000000..8c9c6b7
--- /dev/null
+++ b/03_WordPress/test-plugin.php
@@ -0,0 +1,62 @@
+تست پلاگین IFNEX Bridge
+
+
1. فرم رهگیری مرسوله
+[ifnex_tracking_form title="رهگیری مرسوله IFNEX" placeholder="شماره بارنامه را وارد کنید" button_text="جستجو"]
+
+2. موجودی کیف پول
+[ifnex_wallet_balance show_details="yes"]
+
+3. لیست تراکنشها
+[ifnex_transactions per_page="5" show_pagination="yes"]
+
+4. وضعیت مستقیم مرسوله
+[ifnex_tracking_status awb="980100010"]
+';
+
+// Check if test page already exists
+$test_page = get_page_by_title('تست IFNEX Bridge', OBJECT, 'page');
+
+if (!$test_page) {
+ // Create test page
+ $page_id = wp_insert_post(array(
+ 'post_title' => 'تست IFNEX Bridge',
+ 'post_content' => $page_content,
+ 'post_status' => 'publish',
+ 'post_type' => 'page',
+ 'post_author' => 1,
+ ));
+
+ if ($page_id) {
+ echo "✅ صفحه تست ایجاد شد: " . get_permalink($page_id) . "\n";
+ } else {
+ echo "❌ خطا در ایجاد صفحه تست\n";
+ }
+} else {
+ // Update existing test page
+ $test_page->post_content = $page_content;
+ wp_update_post($test_page);
+ echo "✅ صفحه تست بهروز شد: " . get_permalink($test_page->ID) . "\n";
+}
+
+echo "\n📋 اطلاعات اتصال:\n";
+echo "API URL: " . get_option('ifnex_api_url', 'http://localhost:8000/api/v1') . "\n";
+echo "API Key: " . (get_option('ifnex_api_key', '') ? 'تنظیم شده' : 'تنظیم نشده') . "\n";
+
+echo "\n🔧 مراحل بعدی:\n";
+echo "1. مطمئن شوید لاراول در حال اجرا است: cd 04_Laravel && php artisan serve\n";
+echo "2. وارد صفحه تست شوید: http://localhost/ifnexwp/?page_id=" . ($test_page ? $test_page->ID : $page_id) . "\n";
+echo "3. ابتدا وارد وردپرس شوید (admin / admin)\n";
+echo "4. صفحه تست را باز کنید و عملکرد شورتکدها را بررسی کنید\n";
diff --git a/03_WordPress/wp-content/plugins/ifnex-bridge/assets/css/ifnex-bridge.css b/03_WordPress/wp-content/plugins/ifnex-bridge/assets/css/ifnex-bridge.css
new file mode 100644
index 0000000..6326345
--- /dev/null
+++ b/03_WordPress/wp-content/plugins/ifnex-bridge/assets/css/ifnex-bridge.css
@@ -0,0 +1,384 @@
+/**
+ * IFNEX Bridge Styles
+ * استایلهای پلاگین IFNEX Logistics Bridge
+ */
+
+/* Wallet Balance */
+.ifnex-wallet-balance {
+ background: #f9fafb;
+ border: 1px solid #e5e7eb;
+ border-radius: 12px;
+ padding: 20px;
+ margin: 15px 0;
+ font-family: inherit;
+ direction: rtl;
+ text-align: right;
+}
+
+.ifnex-balance-main {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 10px;
+ padding-bottom: 10px;
+ border-bottom: 1px solid #e5e7eb;
+}
+
+.ifnex-balance-label {
+ font-size: 14px;
+ color: #6b7280;
+ font-weight: 500;
+}
+
+.ifnex-balance-amount {
+ font-size: 24px;
+ font-weight: 700;
+ color: #059669;
+}
+
+.ifnex-balance-details {
+ margin-top: 10px;
+}
+
+.ifnex-balance-details p {
+ margin: 5px 0;
+ font-size: 14px;
+ color: #374151;
+}
+
+.ifnex-balance-details strong {
+ color: #6b7280;
+ margin-left: 8px;
+}
+
+.ifnex-wallet-frozen {
+ color: #dc2626;
+ font-weight: 600;
+ margin-top: 10px;
+ padding: 8px 12px;
+ background: #fee2e2;
+ border-radius: 6px;
+ border-right: 3px solid #dc2626;
+}
+
+/* Transactions */
+.ifnex-transactions {
+ margin: 15px 0;
+ font-family: inherit;
+ direction: rtl;
+ text-align: right;
+}
+
+.ifnex-transactions h3 {
+ font-size: 18px;
+ font-weight: 600;
+ color: #111827;
+ margin-bottom: 15px;
+ padding-bottom: 8px;
+ border-bottom: 2px solid #f59e0b;
+}
+
+.ifnex-transactions-list {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+
+.ifnex-transaction-item {
+ background: #ffffff;
+ border: 1px solid #e5e7eb;
+ border-radius: 10px;
+ padding: 16px;
+ transition: all 0.2s ease;
+}
+
+.ifnex-transaction-item:hover {
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
+ border-color: #f59e0b;
+}
+
+.ifnex-transaction-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 8px;
+}
+
+.ifnex-transaction-type {
+ display: inline-block;
+ padding: 4px 10px;
+ border-radius: 6px;
+ font-size: 12px;
+ font-weight: 500;
+ text-transform: uppercase;
+ background: #dbeafe;
+ color: #1e40af;
+}
+
+.ifnex-transaction-type.deposit {
+ background: #d1fae5;
+ color: #065f46;
+}
+
+.ifnex-transaction-type.withdrawal {
+ background: #fee2e2;
+ color: #991b1b;
+}
+
+.ifnex-transaction-type.order_payment {
+ background: #fef3c7;
+ color: #92400e;
+}
+
+.ifnex-transaction-type.refund {
+ background: #e0e7ff;
+ color: #3730a3;
+}
+
+.ifnex-transaction-amount {
+ font-size: 16px;
+ font-weight: 700;
+ font-family: 'Vazirmatn', 'IranYekan', sans-serif;
+}
+
+.ifnex-transaction-amount.positive {
+ color: #059669;
+}
+
+.ifnex-transaction-amount.negative {
+ color: #dc2626;
+}
+
+.ifnex-transaction-details {
+ margin-top: 8px;
+}
+
+.ifnex-transaction-description {
+ color: #4b5563;
+ font-size: 14px;
+ margin: 0 0 6px 0;
+}
+
+.ifnex-transaction-meta {
+ display: flex;
+ gap: 12px;
+ font-size: 12px;
+ color: #6b7280;
+}
+
+.ifnex-transaction-status {
+ display: inline-block;
+ padding: 2px 8px;
+ border-radius: 4px;
+ background: #f3f4f6;
+ color: #374151;
+ font-size: 11px;
+}
+
+.ifnex-transaction-status.completed {
+ background: #d1fae5;
+ color: #065f46;
+}
+
+.ifnex-transaction-status.pending {
+ background: #fef3c7;
+ color: #92400e;
+}
+
+.ifnex-transaction-status.failed {
+ background: #fee2e2;
+ color: #991b1b;
+}
+
+.ifnex-transaction-ref {
+ margin-top: 6px;
+ font-size: 12px;
+ color: #6b7280;
+ font-family: monospace;
+}
+
+/* Tracking Status */
+.ifnex-tracking-container {
+ max-width: 700px;
+ margin: 20px auto;
+ padding: 24px;
+ background: #ffffff;
+ border: 1px solid #e5e7eb;
+ border-radius: 12px;
+ font-family: inherit;
+ direction: rtl;
+ text-align: right;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
+}
+
+.ifnex-tracking-container h2 {
+ font-size: 20px;
+ font-weight: 700;
+ color: #111827;
+ margin-bottom: 16px;
+ padding-bottom: 8px;
+ border-bottom: 2px solid #f59e0b;
+}
+
+.ifnex-tracking-form {
+ margin-bottom: 20px;
+}
+
+.ifnex-form-group {
+ display: flex;
+ gap: 10px;
+}
+
+.ifnex-form-group input {
+ flex: 1;
+ padding: 12px 16px;
+ border: 1px solid #d1d5db;
+ border-radius: 8px;
+ font-size: 15px;
+ font-family: inherit;
+ transition: border-color 0.2s ease;
+}
+
+.ifnex-form-group input:focus {
+ outline: none;
+ border-color: #f59e0b;
+ box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.1);
+}
+
+.ifnex-form-group button {
+ padding: 12px 24px;
+ background: #f59e0b;
+ color: white;
+ border: none;
+ border-radius: 8px;
+ cursor: pointer;
+ font-size: 15px;
+ font-weight: 600;
+ font-family: inherit;
+ transition: all 0.2s ease;
+}
+
+.ifnex-form-group button:hover {
+ background: #d97706;
+ transform: translateY(-1px);
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
+}
+
+.ifnex-form-group button:disabled {
+ background: #9ca3af;
+ cursor: not-allowed;
+ transform: none;
+ box-shadow: none;
+}
+
+.ifnex-tracking-result {
+ margin-top: 20px;
+ padding: 20px;
+ background: #f9fafb;
+ border-radius: 8px;
+ border: 1px solid #e5e7eb;
+}
+
+.ifnex-error {
+ color: #dc2626;
+ font-weight: 500;
+ padding: 10px;
+ background: #fee2e2;
+ border-radius: 6px;
+ border-right: 3px solid #dc2626;
+}
+
+.ifnex-tracking-status h3 {
+ margin-top: 0;
+ font-size: 18px;
+ font-weight: 700;
+ color: #111827;
+}
+
+.ifnex-status-badge {
+ display: inline-block;
+ padding: 6px 14px;
+ background: #f59e0b;
+ color: white;
+ border-radius: 6px;
+ margin-bottom: 12px;
+ font-weight: 600;
+ font-size: 14px;
+}
+
+.ifnex-status-badge.delivered {
+ background: #059669;
+}
+
+.ifnex-status-badge.failed {
+ background: #dc2626;
+}
+
+.ifnex-status-badge.in_transit {
+ background: #2563eb;
+}
+
+.ifnex-tracking-details {
+ margin-top: 12px;
+}
+
+.ifnex-tracking-details p {
+ margin: 6px 0;
+ font-size: 14px;
+ color: #4b5563;
+}
+
+.ifnex-tracking-details strong {
+ color: #374151;
+ margin-left: 8px;
+}
+
+.ifnex-timeline {
+ margin-top: 20px;
+ padding-top: 15px;
+ border-top: 1px solid #e5e7eb;
+}
+
+.ifnex-timeline h4 {
+ font-size: 16px;
+ font-weight: 600;
+ color: #111827;
+ margin-bottom: 12px;
+}
+
+.ifnex-timeline ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.ifnex-timeline li {
+ padding: 10px 12px;
+ border-bottom: 1px solid #f3f4f6;
+ display: flex;
+ gap: 10px;
+ align-items: flex-start;
+ font-size: 14px;
+}
+
+.ifnex-timeline li:last-child {
+ border-bottom: none;
+}
+
+.ifnex-timeline li strong {
+ color: #f59e0b;
+ font-weight: 600;
+ white-space: nowrap;
+ min-width: 100px;
+}
+
+.ifnex-timeline li span {
+ color: #4b5563;
+ flex: 1;
+}
+
+.ifnex-timeline li small {
+ color: #9ca3af;
+ font-size: 12px;
+ white-space: nowrap;
+}
diff --git a/03_WordPress/wp-content/plugins/ifnex-bridge/ifnex-bridge.php b/03_WordPress/wp-content/plugins/ifnex-bridge/ifnex-bridge.php
index e5638fb..b6df2c9 100644
--- a/03_WordPress/wp-content/plugins/ifnex-bridge/ifnex-bridge.php
+++ b/03_WordPress/wp-content/plugins/ifnex-bridge/ifnex-bridge.php
@@ -12,9 +12,23 @@ if ( ! defined( 'ABSPATH' ) ) {
// لود کردن فایلهای پلاگین
require_once plugin_dir_path( __FILE__ ) . 'includes/api-client.php';
+require_once plugin_dir_path( __FILE__ ) . 'includes/user-bridge.php';
require_once plugin_dir_path( __FILE__ ) . 'includes/shortcodes.php';
require_once plugin_dir_path( __FILE__ ) . 'includes/tracking-form.php';
+// لود کردن استایلهای پلاگین
+add_action('wp_enqueue_scripts', 'ifnex_enqueue_scripts');
+function ifnex_enqueue_scripts() {
+ global $post;
+ if (is_a($post, 'WP_Post') &&
+ (has_shortcode($post->post_content, 'ifnex_tracking_form') ||
+ has_shortcode($post->post_content, 'ifnex_wallet_balance') ||
+ has_shortcode($post->post_content, 'ifnex_transactions') ||
+ has_shortcode($post->post_content, 'ifnex_tracking_status'))) {
+ wp_enqueue_style('ifnex-bridge-css', plugin_dir_url(__FILE__) . 'assets/css/ifnex-bridge.css', array(), '1.0.0');
+ }
+}
+
// اضافه کردن لینک به منوی پیشخوان وردپرس
add_action( 'admin_menu', 'ifnex_plugin_setup_menu' );
function ifnex_plugin_setup_menu() {
diff --git a/03_WordPress/wp-content/plugins/ifnex-bridge/includes/shortcodes.php b/03_WordPress/wp-content/plugins/ifnex-bridge/includes/shortcodes.php
index d9f5651..09ca608 100644
--- a/03_WordPress/wp-content/plugins/ifnex-bridge/includes/shortcodes.php
+++ b/03_WordPress/wp-content/plugins/ifnex-bridge/includes/shortcodes.php
@@ -86,3 +86,106 @@ function ifnex_tracking_status_shortcode($atts) {
برای مشاهده موجودی باید وارد شوید.';
+ }
+
+ $atts = shortcode_atts(array(
+ 'show_details' => 'no',
+ ), $atts);
+
+ $bridge = new IFNEX_User_Bridge();
+ $balance = $bridge->get_wallet_balance(get_current_user_id());
+
+ if (is_wp_error($balance)) {
+ return '' . esc_html($balance->get_error_message()) . '
';
+ }
+
+ ob_start();
+ ?>
+
+
+ موجودی کیف پول:
+ ریال
+
+
+
+
مجموع واریزی: ریال
+
مجموع برداشت: ریال
+
+
⚠️ کیف پول شما مسدود است.
+
+
+
+
+ برای مشاهده تراکنشها باید وارد شوید.';
+ }
+
+ $atts = shortcode_atts(array(
+ 'per_page' => 10,
+ 'show_pagination' => 'no',
+ ), $atts);
+
+ $bridge = new IFNEX_User_Bridge();
+ $transactions = $bridge->get_transactions(get_current_user_id(), intval($atts['per_page']));
+
+ if (is_wp_error($transactions)) {
+ return '' . esc_html($transactions->get_error_message()) . '
';
+ }
+
+ if (empty($transactions['transactions'])) {
+ return 'هنوز تراکنشی ثبت نشده است.
';
+ }
+
+ ob_start();
+ ?>
+
+
تاریخچه تراکنشها
+
+
+
+
+
+
+
+
+
+
+
+
کد پیگیری:
+
+
+
+
+
+ 1): ?>
+
+
+
+ true, 'html' => $html));
}
+
+// AJAX Handler: موجودی کیف پول
+add_action('wp_ajax_ifnex_get_wallet_balance', 'ifnex_get_wallet_balance_ajax');
+add_action('wp_ajax_nopriv_ifnex_get_wallet_balance', 'ifnex_get_wallet_balance_ajax');
+
+function ifnex_get_wallet_balance_ajax() {
+ if (!is_user_logged_in()) {
+ wp_send_json(array('success' => false, 'message' => 'برای مشاهده موجودی باید وارد شوید.'));
+ return;
+ }
+
+ $bridge = new IFNEX_User_Bridge();
+ $balance = $bridge->get_wallet_balance(get_current_user_id());
+
+ if (is_wp_error($balance)) {
+ wp_send_json(array('success' => false, 'message' => $balance->get_error_message()));
+ return;
+ }
+
+ wp_send_json(array(
+ 'success' => true,
+ 'balance' => $balance['balance'],
+ 'formatted_balance' => number_format($balance['balance']) . ' ریال',
+ 'total_deposited' => number_format($balance['total_deposited']) . ' ریال',
+ 'total_withdrawn' => number_format($balance['total_withdrawn']) . ' ریال',
+ 'is_frozen' => $balance['is_frozen'],
+ ));
+}
+
+// AJAX Handler: لیست تراکنشها
+add_action('wp_ajax_ifnex_get_transactions', 'ifnex_get_transactions_ajax');
+add_action('wp_ajax_nopriv_ifnex_get_transactions', 'ifnex_get_transactions_ajax');
+
+function ifnex_get_transactions_ajax() {
+ if (!is_user_logged_in()) {
+ wp_send_json(array('success' => false, 'message' => 'برای مشاهده تراکنشها باید وارد شوید.'));
+ return;
+ }
+
+ $per_page = isset($_POST['per_page']) ? intval($_POST['per_page']) : 10;
+
+ $bridge = new IFNEX_User_Bridge();
+ $transactions = $bridge->get_transactions(get_current_user_id(), $per_page);
+
+ if (is_wp_error($transactions)) {
+ wp_send_json(array('success' => false, 'message' => $transactions->get_error_message()));
+ return;
+ }
+
+ // ساخت HTML لیست تراکنشها
+ if (empty($transactions['transactions'])) {
+ wp_send_json(array(
+ 'success' => true,
+ 'html' => 'هنوز تراکنشی ثبت نشده است.
',
+ ));
+ return;
+ }
+
+ ob_start();
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
کد پیگیری:
+
+
+
+
+
+ true,
+ 'html' => $html,
+ ));
+}
diff --git a/03_WordPress/wp-content/plugins/ifnex-bridge/includes/user-bridge.php b/03_WordPress/wp-content/plugins/ifnex-bridge/includes/user-bridge.php
new file mode 100644
index 0000000..c0ffa6b
--- /dev/null
+++ b/03_WordPress/wp-content/plugins/ifnex-bridge/includes/user-bridge.php
@@ -0,0 +1,221 @@
+api_url = rtrim(get_option('ifnex_api_url', 'http://localhost:8000/api/v1'), '/');
+ $this->api_key = get_option('ifnex_api_key', '');
+ }
+
+ /**
+ * دریافت توکن Sanctum برای کاربر وردپرس
+ */
+ public function get_user_token($user_id) {
+ $token = get_user_meta($user_id, 'ifnex_laravel_token', true);
+ $token_expiry = get_user_meta($user_id, 'ifnex_laravel_token_expiry', true);
+
+ if ($token && $token_expiry && strtotime($token_expiry) > time()) {
+ return $token;
+ }
+
+ $user = get_userdata($user_id);
+ if (!$user) {
+ return false;
+ }
+
+ $token = $this->request_token($user->user_email, $this->generate_temp_password($user_id));
+
+ if ($token) {
+ update_user_meta($user_id, 'ifnex_laravel_token', $token);
+ update_user_meta($user_id, 'ifnex_laravel_token_expiry', date('Y-m-d H:i:s', strtotime('+30 days')));
+ }
+
+ return $token;
+ }
+
+ /**
+ * درخواست توکن از لاراول
+ */
+ private function request_token($email, $password) {
+ $url = $this->api_url . '/sanctum/token';
+
+ $args = array(
+ 'headers' => array(
+ 'Content-Type' => 'application/json',
+ 'Accept' => 'application/json',
+ ),
+ 'body' => json_encode(array(
+ 'email' => $email,
+ 'password' => $password,
+ 'token_name' => 'wordpress-bridge-' . get_current_blog_id(),
+ )),
+ 'timeout' => 30,
+ );
+
+ $response = wp_remote_post($url, $args);
+
+ if (is_wp_error($response)) {
+ return false;
+ }
+
+ $body = wp_remote_retrieve_body($response);
+ $data = json_decode($body, true);
+
+ if (isset($data['token'])) {
+ return $data['token'];
+ }
+
+ return false;
+ }
+
+ /**
+ * تولید رمز عبور موقت برای کاربر وردپرس
+ */
+ private function generate_temp_password($user_id) {
+ $temp_pass = get_user_meta($user_id, 'ifnex_temp_password', true);
+
+ if (!$temp_pass) {
+ $temp_pass = wp_generate_password(32, true, true);
+ update_user_meta($user_id, 'ifnex_temp_password', $temp_pass);
+ }
+
+ return $temp_pass;
+ }
+
+ /**
+ * ارسال درخواست احراز هویت به API لاراول
+ */
+ public function authenticated_request($user_id, $endpoint, $method = 'GET', $data = array()) {
+ $token = $this->get_user_token($user_id);
+
+ if (!$token) {
+ return new WP_Error('no_token', 'توکن احراز هویت یافت نشد.');
+ }
+
+ $url = $this->api_url . $endpoint;
+
+ $args = array(
+ 'headers' => array(
+ 'Authorization' => 'Bearer ' . $token,
+ 'Accept' => 'application/json',
+ 'Content-Type' => 'application/json',
+ ),
+ 'timeout' => 30,
+ );
+
+ if ($method === 'POST' && !empty($data)) {
+ $args['body'] = json_encode($data);
+ $args['method'] = 'POST';
+ } else {
+ $args['method'] = 'GET';
+ if (!empty($data)) {
+ $url = add_query_arg($data, $url);
+ }
+ }
+
+ $response = wp_remote_request($url, $args);
+
+ if (is_wp_error($response)) {
+ return $response;
+ }
+
+ $body = wp_remote_retrieve_body($response);
+ $data = json_decode($body, true);
+
+ if ($response['response']['code'] === 401) {
+ $this->invalidate_token(get_current_user_id());
+ return new WP_Error('token_expired', 'توکن منقضی شده است. لطفاً دوباره وارد شوید.');
+ }
+
+ return $data;
+ }
+
+ /**
+ * باطل کردن توکن
+ */
+ public function invalidate_token($user_id) {
+ delete_user_meta($user_id, 'ifnex_laravel_token');
+ delete_user_meta($user_id, 'ifnex_laravel_token_expiry');
+ }
+
+ /**
+ * دریافت موجودی کیف پول کاربر
+ */
+ public function get_wallet_balance($user_id) {
+ $result = $this->authenticated_request($user_id, '/wallet/balance');
+
+ if (is_wp_error($result)) {
+ return $result;
+ }
+
+ return array(
+ 'balance' => $result['balance'] ?? 0,
+ 'total_deposited' => $result['total_deposited'] ?? 0,
+ 'total_withdrawn' => $result['total_withdrawn'] ?? 0,
+ 'is_frozen' => $result['is_frozen'] ?? false,
+ );
+ }
+
+ /**
+ * دریافت تراکنشهای کاربر
+ */
+ public function get_transactions($user_id, $per_page = 15) {
+ $result = $this->authenticated_request($user_id, '/wallet/transactions', 'GET', array(
+ 'per_page' => $per_page,
+ ));
+
+ if (is_wp_error($result)) {
+ return $result;
+ }
+
+ return $result;
+ }
+
+ /**
+ * رهگیری مرسوله
+ */
+ public function track_shipment($awb_no) {
+ if (empty($this->api_key)) {
+ return new WP_Error('no_api_key', 'API Key تنظیم نشده است.');
+ }
+
+ $url = $this->api_url . '/track/' . urlencode($awb_no);
+
+ $args = array(
+ 'headers' => array(
+ 'Authorization' => 'Bearer ' . $this->api_key,
+ 'Accept' => 'application/json',
+ ),
+ 'timeout' => 30,
+ );
+
+ $response = wp_remote_get($url, $args);
+
+ if (is_wp_error($response)) {
+ return $response;
+ }
+
+ $body = wp_remote_retrieve_body($response);
+ $data = json_decode($body, true);
+
+ if ($response['response']['code'] === 404) {
+ return new WP_Error('not_found', 'مرسولهای با این کد پیدا نشد.');
+ }
+
+ if ($response['response']['code'] !== 200) {
+ return new WP_Error('api_error', 'خطا در ارتباط با API: ' . ($data['message'] ?? 'Unknown error'));
+ }
+
+ return $data;
+ }
+}