sync = $sync; $this->client = $client; } public function healthCheck() { $result = $this->client->healthCheck(); $status = ! empty($result['ok']) ? 200 : 422; return response()->json([ 'ok' => ! empty($result['ok']), 'message' => $result['message'] ?? null, 'http_status' => $result['http_status'] ?? null, 'timeout' => ! empty($result['timeout']), // never echo Config passwords 'body' => $this->sanitizeBodyForAdmin($result['body'] ?? null), ], $status); } /** * @param array $data */ public function storeTrade(array $data) { return $this->sync->recordTrade($data); } /** * @param array $data */ public function wallet(array $data) { return $this->sync->recordWalletCash($data); } /** * @param array $data */ public function walletGold(array $data) { return $this->sync->recordWalletGold($data); } public function table(Request $request) { if (! Schema::hasTable('shayegan')) { return response()->json(['data' => [], 'total' => 0]); } $q = Shayegan::query()->orderByDesc('id'); if ($request->filled('sync_status')) { $q->where('sync_status', $request->get('sync_status')); } if ($request->filled('type')) { $q->where('type', $request->get('type')); } $perPage = min(100, max(10, (int) $request->get('per_page', 20))); $page = $q->paginate($perPage); return response()->json([ 'data' => $page->items(), 'total' => $page->total(), 'current_page' => $page->currentPage(), 'per_page' => $page->perPage(), ]); } public function show($id) { $row = Shayegan::findOrFail($id); return response()->json($row); } /** * Manual retry — refuses timeout rows unless force=1 after operator verified remote. */ public function retrySanad(Request $request, $id) { $row = Shayegan::findOrFail($id); if ($row->sync_status === ShayeganSyncService::STATUS_SUCCESS) { return response()->json(['ok' => true, 'message' => 'already synced', 'row' => $row]); } if ($row->sync_status === ShayeganSyncService::STATUS_TIMEOUT && ! $request->boolean('force')) { return response()->json([ 'ok' => false, 'message' => 'این سند timeout شده؛ بدون بررسی نتیجه در حسابگر دوباره ارسال نکنید. در صورت تایید force=1 بفرستید.', ], 422); } $payload = json_decode((string) $row->data, true); $put = is_array($payload) ? ($payload['PutObject'] ?? null) : null; $endpoint = (string) ($row->endpoint ?: 'Document/Put'); if (! is_array($put) || $put === []) { return response()->json(['ok' => false, 'message' => 'payload خالی است'], 422); } // Clear timeout lock only when force retry requested if ($row->sync_status === ShayeganSyncService::STATUS_TIMEOUT) { $row->sync_status = ShayeganSyncService::STATUS_PENDING; $row->save(); } $result = $this->client->put($endpoint, $put); if (! empty($result['timeout'])) { $row->sync_status = ShayeganSyncService::STATUS_TIMEOUT; $row->sync_log = (string) ($result['message'] ?? 'timeout'); $row->res = json_encode(['timeout' => true], JSON_UNESCAPED_UNICODE); $row->save(); return response()->json(['ok' => false, 'message' => 'timeout', 'row' => $row], 422); } if (! empty($result['ok'])) { $row->sync_status = ShayeganSyncService::STATUS_SUCCESS; $row->sync_log = null; $row->shayegan_number = $result['number'] ?? null; $row->shayegan_guid = $result['guid'] ?? null; $row->res = json_encode($result['body'] ?? [], JSON_UNESCAPED_UNICODE); $row->save(); return response()->json(['ok' => true, 'row' => $row]); } $row->sync_status = ShayeganSyncService::STATUS_FAILED; $row->sync_log = (string) ($result['message'] ?? 'failed'); $row->res = json_encode($result['body'] ?? [], JSON_UNESCAPED_UNICODE); $row->save(); return response()->json(['ok' => false, 'message' => $row->sync_log, 'row' => $row], 422); } /** * @param mixed $body * @return mixed */ private function sanitizeBodyForAdmin($body) { if (! is_array($body)) { return $body; } // Drop huge Result lists from health if present if (isset($body['Result']) && is_array($body['Result'])) { $body['Result'] = array_slice($body['Result'], 0, 3); } return $body; } }