token !== ''; } /** * تطبیق کد ملی با موبایل (شاهکار). true یعنی هر دو متعلق به یک نفر است. */ public function shahkarMatch(string $nationalCode, string $mobile): bool { // پاسخ: {"data": true|false, "success": true, "code": 0, "message": "..."} $data = $this->post('/api/sw1/ShahkarLite', [ 'nationalCode' => $nationalCode, 'mobile' => $mobile, ]); return $this->extractMatched($data); } /** * تطبیق شبا با کد ملی و تاریخ تولد. * * پاسخ سرویس فقط نتیجه‌ی boolean (`data`) می‌دهد و نام بانک/صاحب حساب را برنمی‌گرداند. * * @param string $birthDate تاریخ تولد شمسی به فرمت Y/m/d (مثلاً 1370/01/01) * @return array{matched: bool, bank_name: ?string, owner_name: ?string} */ public function ibanMatch(string $iban, string $nationalCode, string $birthDate): array { $data = $this->post('/api/sw1/IbanMatch', [ 'iban' => $iban, 'nationalCode' => $nationalCode, 'birthDate' => $birthDate, ]); return [ 'matched' => $this->extractMatched($data), 'bank_name' => null, 'owner_name' => null, ]; } /** * استعلام هویت شخص از روی کد ملی و تاریخ تولد (PersonInfo). * * @param string $birthDateJalali تاریخ تولد شمسی به فرمت Y/m/d (مثلاً 1371/1/1) * @return array{firstName: string, lastName: string, alive: bool}|null null یعنی رکوردی مطابقت نکرد. */ public function personInfo(string $nationalCode, string $birthDateJalali): ?array { $data = $this->post('/api/sw1/PersonInfo', [ 'nationalCode' => $nationalCode, 'birthDate' => $birthDateJalali, ]); $person = $data['data'] ?? null; if (!is_array($person) || ($person['nationalCode'] ?? '') === '') { return null; } return [ 'firstName' => (string) ($person['firstName'] ?? ''), 'lastName' => (string) ($person['lastName'] ?? ''), 'alive' => filter_var($person['alive'] ?? false, FILTER_VALIDATE_BOOLEAN), ]; } /** * @param array $payload * @return array */ private function post(string $path, array $payload): array { if (!$this->isConfigured()) { throw new AppException(ErrorCodes::ERR_EXTERNAL_NOT_CONFIGURED, null, 503); } try { $response = $this->httpClient->request('POST', rtrim($this->baseUrl, '/') . $path, [ 'json' => $payload, 'headers' => ['Authorization' => 'Bearer ' . $this->token], 'timeout' => 10, ]); $status = $response->getStatusCode(); if ($status >= 500) { throw new AppException(ErrorCodes::ERR_EXTERNAL_001, null, 502); } return $response->toArray(false); } catch (AppException $e) { throw $e; } catch (\Throwable $e) { $this->logger->error(sprintf('api.ir inquiry failed: %s @ %s:%d', $e->getMessage(), $e->getFile(), $e->getLine()), ['exception' => $e, 'path' => $path]); throw new AppException(ErrorCodes::ERR_EXTERNAL_001, null, 502); } } /** * استخراج نتیجه‌ی boolean از پاسخ api.ir. * * قالب پاسخ: {"data": true|false, "success": true, "code": 0, "message": "..."} * - success=false یعنی ورودی نامعتبر/خطای درخواست → نتیجه «عدم تطبیق». * - data همان نتیجه‌ی boolean تطبیق است. * * @param array $data */ private function extractMatched(array $data): bool { if (($data['success'] ?? false) !== true) { return false; } return filter_var($data['data'] ?? false, FILTER_VALIDATE_BOOLEAN); } }