Files

154 lines
5.8 KiB
PHP
Raw Permalink Normal View History

<?php
namespace App\Services;
class JibitIdentityService
{
/**
* @param mixed $response
* @return array{ok: bool, code: string, message: string}
*/
public static function interpretNationalMobileMatch($response): array
{
if (! is_array($response) || $response === []) {
return [
'ok' => false,
'code' => 'jibit_no_response',
'message' => 'پاسخ سرویس احراز هویت دریافت نشد. اتصال سرور به جیبیت یا توکن را بررسی کنید.',
];
}
if (array_key_exists('matched', $response) && self::isTruthyMatch($response['matched'])) {
return [
'ok' => true,
'code' => 'jibit_matched',
'message' => '',
];
}
if (array_key_exists('matched', $response) && self::isFalseyMatch($response['matched'])) {
return [
'ok' => false,
'code' => 'jibit_mismatch',
'message' => 'کد ملی و شماره موبایل در سامانه شاهکار مطابقت ندارند. سیم‌کارت باید به نام صاحب همین کد ملی باشد.',
];
}
$apiCode = strtolower(trim((string) ($response['code'] ?? $response['errorCode'] ?? '')));
$mapped = self::mapApiCode($apiCode);
if ($mapped !== null) {
return [
'ok' => false,
'code' => $apiCode !== '' ? 'jibit_'.$apiCode : 'jibit_error',
'message' => $mapped,
];
}
$detail = trim(implode(' — ', array_filter([
$apiCode !== '' ? 'کد جیبیت: '.$apiCode : '',
self::stringifyApiMessage($response),
isset($response['http_status']) ? 'وضعیت HTTP: '.$response['http_status'] : '',
], fn ($part) => $part !== '' && $part !== null)));
return [
'ok' => false,
'code' => $apiCode !== '' ? 'jibit_'.$apiCode : 'jibit_unknown',
'message' => 'احراز هویت از طرف جیبیت تأیید نشد'
.($detail !== '' ? ' ('.$detail.')' : '.')
.' اطلاعات پروفایل ذخیره شد؛ تا تأیید مدیر امکان معامله نیست.',
];
}
public static function nationalCodeError(?string $nCode): ?string
{
$digits = preg_replace('/\D+/', '', (string) $nCode) ?? '';
if ($digits === '') {
return 'کد ملی وارد نشده است.';
}
if (strlen($digits) !== 10) {
return 'کد ملی باید ۱۰ رقم باشد.';
}
if (! self::isValidIranianNationalCode($digits)) {
return 'کد ملی از نظر رقم کنترل نامعتبر است.';
}
return null;
}
public static function isValidIranianNationalCode(string $digits): bool
{
if (! preg_match('/^\d{10}$/', $digits)) {
return false;
}
if (preg_match('/^(\d)\1{9}$/', $digits)) {
return false;
}
$sum = 0;
for ($i = 0; $i < 9; $i++) {
$sum += (int) $digits[$i] * (10 - $i);
}
$remainder = $sum % 11;
$check = (int) $digits[9];
return $remainder < 2 ? $check === $remainder : $check === (11 - $remainder);
}
private static function isTruthyMatch($value): bool
{
return $value === true || $value === 1 || $value === '1' || $value === 'true';
}
private static function isFalseyMatch($value): bool
{
return $value === false || $value === 0 || $value === '0' || $value === 'false';
}
private static function mapApiCode(string $apiCode): ?string
{
return match ($apiCode) {
'forbidden', 'unauthorized', 'unauthenticated' => 'اتصال به جیبیت مجاز نیست (توکن یا کلید API). با پشتیبانی فنی بررسی کنید.',
'empty_response', 'token_failed' => 'سرویس احراز هویت پاسخ معتبر نداد. چند دقیقه دیگر دوباره تلاش کنید.',
'too_many_requests', 'rate_limit', 'rate.limit' => 'تعداد استعلام احراز هویت بیش از حد مجاز است. کمی بعد دوباره تلاش کنید.',
'invalid_national_code', 'nationalcode.invalid', 'national_code.invalid' => 'کد ملی از نظر سرویس احراز هویت نامعتبر است.',
'invalid_mobile_number', 'mobilenumber.invalid', 'mobile.invalid' => 'شماره موبایل از نظر سرویس احراز هویت نامعتبر است.',
default => null,
};
}
/**
* @param array<string, mixed> $response
*/
private static function stringifyApiMessage(array $response): string
{
$message = $response['message'] ?? null;
if (is_string($message) && trim($message) !== '') {
return self::sanitizeDetail($message);
}
$errors = $response['errors'] ?? null;
if (is_array($errors)) {
foreach ($errors as $value) {
if (is_string($value) && trim($value) !== '') {
return self::sanitizeDetail($value);
}
if (is_array($value) && isset($value[0]) && is_string($value[0]) && trim($value[0]) !== '') {
return self::sanitizeDetail($value[0]);
}
}
}
return '';
}
private static function sanitizeDetail(string $text): string
{
$plain = trim(html_entity_decode(strip_tags($text), ENT_QUOTES | ENT_HTML5, 'UTF-8'));
if (mb_strlen($plain) > 180) {
$plain = mb_substr($plain, 0, 180).'…';
}
return $plain;
}
}