Surface specific Jibit identity errors on profile update.
Map Shahkar mismatch, token, unreachable, and duplicate cases to clear Persian messages instead of a generic wait-for-admin toast. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -830,33 +830,60 @@ class Controller extends BaseController
|
|||||||
Storage::put('refreshTokenGibit', 'توکن رفرش اولیه');
|
Storage::put('refreshTokenGibit', 'توکن رفرش اولیه');
|
||||||
}
|
}
|
||||||
|
|
||||||
$apiData['refresh'] = Http::withoutVerifying()->withToken(Storage::get('refreshTokenGibit'))
|
$apiData['refresh'] = $this->jibitHttpJson(
|
||||||
->post('https://napi.jibit.ir/ide/v1/tokens/generate', [
|
Http::withoutVerifying()->withToken(Storage::get('refreshTokenGibit'))
|
||||||
'apiKey' => 'J5WxrPxPOg',
|
->post('https://napi.jibit.ir/ide/v1/tokens/generate', [
|
||||||
'secretKey' => '7dgeE70xQXsQL7r36j3wif6X9',
|
'apiKey' => 'J5WxrPxPOg',
|
||||||
])->json();
|
'secretKey' => '7dgeE70xQXsQL7r36j3wif6X9',
|
||||||
|
])
|
||||||
|
);
|
||||||
Storage::put('accessTokenGibit', $apiData['refresh']['accessToken'] ?? '');
|
Storage::put('accessTokenGibit', $apiData['refresh']['accessToken'] ?? '');
|
||||||
if (!empty($apiData['refresh']['refreshToken'])) {
|
if (!empty($apiData['refresh']['refreshToken'])) {
|
||||||
Storage::put('refreshTokenGibit', $apiData['refresh']['refreshToken']);
|
Storage::put('refreshTokenGibit', $apiData['refresh']['refreshToken']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = Http::withoutVerifying()->withToken(Storage::get('accessTokenGibit'))
|
if (empty($apiData['refresh']['accessToken'])) {
|
||||||
->get("https://napi.jibit.ir/ide/v1/services/matching?mobileNumber=$mobile&nationalCode=$nationalCode")
|
return [
|
||||||
->json();
|
'code' => 'token_failed',
|
||||||
|
'http_status' => $apiData['refresh']['http_status'] ?? null,
|
||||||
|
'message' => $apiData['refresh']['message'] ?? '',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
if ((isset($response['code'])) && $response['code'] == 'forbidden') {
|
$response = $this->jibitHttpJson(
|
||||||
$refreshToken = Http::withoutVerifying()->withToken(Storage::get('refreshTokenGibit'))
|
Http::withoutVerifying()->withToken(Storage::get('accessTokenGibit'))
|
||||||
->post('https://napi.jibit.ir/ide/v1/tokens/generate', [
|
->get('https://napi.jibit.ir/ide/v1/services/matching', [
|
||||||
'apiKey' => 'J5WxrPxPOg',
|
'mobileNumber' => $mobile,
|
||||||
'secretKey' => '7dgeE70xQXsQL7r36j3wif6X9',
|
'nationalCode' => $nationalCode,
|
||||||
])->json();
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
if (($response['code'] ?? null) == 'forbidden') {
|
||||||
|
$refreshToken = $this->jibitHttpJson(
|
||||||
|
Http::withoutVerifying()->withToken(Storage::get('refreshTokenGibit'))
|
||||||
|
->post('https://napi.jibit.ir/ide/v1/tokens/generate', [
|
||||||
|
'apiKey' => 'J5WxrPxPOg',
|
||||||
|
'secretKey' => '7dgeE70xQXsQL7r36j3wif6X9',
|
||||||
|
])
|
||||||
|
);
|
||||||
Storage::put('accessTokenGibit', $refreshToken['accessToken'] ?? '');
|
Storage::put('accessTokenGibit', $refreshToken['accessToken'] ?? '');
|
||||||
if (!empty($refreshToken['refreshToken'])) {
|
if (!empty($refreshToken['refreshToken'])) {
|
||||||
Storage::put('refreshTokenGibit', $refreshToken['refreshToken']);
|
Storage::put('refreshTokenGibit', $refreshToken['refreshToken']);
|
||||||
}
|
}
|
||||||
$response = Http::withoutVerifying()->withToken(Storage::get('accessTokenGibit'))
|
if (empty($refreshToken['accessToken'])) {
|
||||||
->get("https://napi.jibit.ir/ide/v1/services/matching?mobileNumber=$mobile&nationalCode=$nationalCode")
|
return [
|
||||||
->json();
|
'code' => 'token_failed',
|
||||||
|
'http_status' => $refreshToken['http_status'] ?? null,
|
||||||
|
'message' => $refreshToken['message'] ?? '',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$response = $this->jibitHttpJson(
|
||||||
|
Http::withoutVerifying()->withToken(Storage::get('accessTokenGibit'))
|
||||||
|
->get('https://napi.jibit.ir/ide/v1/services/matching', [
|
||||||
|
'mobileNumber' => $mobile,
|
||||||
|
'nationalCode' => $nationalCode,
|
||||||
|
])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$counter->value = (int) $counter->value + 1;
|
$counter->value = (int) $counter->value + 1;
|
||||||
@@ -865,6 +892,25 @@ class Controller extends BaseController
|
|||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Illuminate\Http\Client\Response $pending
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
protected function jibitHttpJson($pending): array
|
||||||
|
{
|
||||||
|
$decoded = $pending->json();
|
||||||
|
if (! is_array($decoded)) {
|
||||||
|
return [
|
||||||
|
'code' => 'empty_response',
|
||||||
|
'http_status' => $pending->status(),
|
||||||
|
'message' => '',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
$decoded['http_status'] = $pending->status();
|
||||||
|
|
||||||
|
return $decoded;
|
||||||
|
}
|
||||||
|
|
||||||
public static function jibit($method, $p1 = null, $p2 = null, $p3 = null)
|
public static function jibit($method, $p1 = null, $p2 = null, $p3 = null)
|
||||||
{
|
{
|
||||||
if (!app(ConfigService::class)->isJibitEnabled()) {
|
if (!app(ConfigService::class)->isJibitEnabled()) {
|
||||||
|
|||||||
@@ -18,9 +18,11 @@ use Rooyesh\Wallet\models\Transaction;
|
|||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Http\Controllers\Admin\TahesabController;
|
use App\Http\Controllers\Admin\TahesabController;
|
||||||
use App\Services\ConfigService;
|
use App\Services\ConfigService;
|
||||||
|
use App\Services\JibitIdentityService;
|
||||||
use App\Services\ReferralGiftService;
|
use App\Services\ReferralGiftService;
|
||||||
use App\Services\WalletBalanceService;
|
use App\Services\WalletBalanceService;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Database\QueryException;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
@@ -207,9 +209,30 @@ class CustomerController extends Controller
|
|||||||
// $tah->store(["customer_id" => $customer->id]);
|
// $tah->store(["customer_id" => $customer->id]);
|
||||||
$cfg = app(ConfigService::class);
|
$cfg = app(ConfigService::class);
|
||||||
if (!$wasLegal && $cfg->isRegisterJibitVerifyEnabled()) {
|
if (!$wasLegal && $cfg->isRegisterJibitVerifyEnabled()) {
|
||||||
$response = $this->jibitNcode($customer->n_code, $customer->mobile);
|
$nCodeError = JibitIdentityService::nationalCodeError($customer->n_code);
|
||||||
|
if ($nCodeError !== null) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => $nCodeError,
|
||||||
|
'code' => 'invalid_national_code',
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($response['matched']) and $response['matched'] == true) {
|
try {
|
||||||
|
$response = $this->jibitNcode($customer->n_code, $customer->mobile);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::error('customer updateMe jibit unreachable', [
|
||||||
|
'customer_id' => $customer->id,
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'ارتباط با سرویس احراز هویت جیبیت برقرار نشد. اطلاعات پروفایل ذخیره شد اما هویت تأیید نشد.',
|
||||||
|
'code' => 'jibit_unreachable',
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
$jibit = JibitIdentityService::interpretNationalMobileMatch($response);
|
||||||
|
if ($jibit['ok']) {
|
||||||
$customer->is_legal = 1;
|
$customer->is_legal = 1;
|
||||||
$customer->save();
|
$customer->save();
|
||||||
// واریز پاداش معرف مستقل از has_page_earn_money (آن فقط منوی اپ است)
|
// واریز پاداش معرف مستقل از has_page_earn_money (آن فقط منوی اپ است)
|
||||||
@@ -222,18 +245,18 @@ class CustomerController extends Controller
|
|||||||
true
|
true
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (isset($response['matched']) && $response['matched'] === false) {
|
Log::warning('customer updateMe jibit not verified', [
|
||||||
return response()->json([
|
'customer_id' => $customer->id,
|
||||||
'message' => 'کد ملی و شماره موبایل با یکدیگر مطابقت ندارند. لطفاً هر دو را با دقت بررسی کرده و دوباره ثبت کنید.',
|
'code' => $jibit['code'],
|
||||||
], 422);
|
'jibit_code' => is_array($response) ? ($response['code'] ?? null) : null,
|
||||||
}
|
'http_status' => is_array($response) ? ($response['http_status'] ?? null) : null,
|
||||||
|
]);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'کد ملی ثبت شد، اما در حال حاضر سیستم نتوانست آن را تأیید کند. لطفاً منتظر بررسی و تأیید مدیر بمانید.',
|
'message' => $jibit['message'],
|
||||||
|
'code' => $jibit['code'],
|
||||||
], 422);
|
], 422);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} elseif (!$customer->is_legal && !$cfg->isRegisterJibitVerifyEnabled()) {
|
} elseif (!$customer->is_legal && !$cfg->isRegisterJibitVerifyEnabled()) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'ok' => true,
|
'ok' => true,
|
||||||
@@ -242,13 +265,47 @@ class CustomerController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
return response()->json(true);
|
return response()->json(true);
|
||||||
|
} catch (QueryException $e) {
|
||||||
|
Log::error('customer updateMe failed', [
|
||||||
|
'customer_id' => auth('customer')->id(),
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
]);
|
||||||
|
$driverCode = (int) ($e->errorInfo[1] ?? 0);
|
||||||
|
$sqlMessage = (string) ($e->errorInfo[2] ?? $e->getMessage());
|
||||||
|
if ($driverCode === 1062) {
|
||||||
|
if (str_contains($sqlMessage, 'n_code')) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'این کد ملی قبلاً برای حساب دیگری ثبت شده است.',
|
||||||
|
'code' => 'duplicate_national_code',
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
if (str_contains($sqlMessage, 'mobile')) {
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'این شماره موبایل قبلاً برای حساب دیگری ثبت شده است.',
|
||||||
|
'code' => 'duplicate_mobile',
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'این مقدار قبلاً در سیستم ثبت شده و تکراری است.',
|
||||||
|
'code' => 'duplicate_value',
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'ذخیره اطلاعات در دیتابیس انجام نشد. جزئیات در لاگ سرور ثبت شد.',
|
||||||
|
'code' => 'db_error',
|
||||||
|
], 422);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
Log::error('customer updateMe failed', [
|
Log::error('customer updateMe failed', [
|
||||||
'customer_id' => auth('customer')->id(),
|
'customer_id' => auth('customer')->id(),
|
||||||
'message' => $e->getMessage(),
|
'message' => $e->getMessage(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return response()->json(['message' => 'خطا در ذخیره اطلاعات. لطفاً دوباره تلاش کنید.'], 422);
|
return response()->json([
|
||||||
|
'message' => 'خطا در ذخیره اطلاعات. لطفاً دوباره تلاش کنید.',
|
||||||
|
'code' => 'update_failed',
|
||||||
|
], 422);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,153 @@
|
|||||||
|
<?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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Unit;
|
||||||
|
|
||||||
|
use App\Services\JibitIdentityService;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class JibitIdentityServiceTest extends TestCase
|
||||||
|
{
|
||||||
|
public function test_matched_true_is_ok(): void
|
||||||
|
{
|
||||||
|
$result = JibitIdentityService::interpretNationalMobileMatch(['matched' => true]);
|
||||||
|
|
||||||
|
$this->assertTrue($result['ok']);
|
||||||
|
$this->assertSame('jibit_matched', $result['code']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_matched_false_explains_shahkar_mismatch(): void
|
||||||
|
{
|
||||||
|
$result = JibitIdentityService::interpretNationalMobileMatch(['matched' => false]);
|
||||||
|
|
||||||
|
$this->assertFalse($result['ok']);
|
||||||
|
$this->assertSame('jibit_mismatch', $result['code']);
|
||||||
|
$this->assertStringContainsString('شاهکار', $result['message']);
|
||||||
|
$this->assertStringContainsString('سیمکارت', $result['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_forbidden_mentions_token(): void
|
||||||
|
{
|
||||||
|
$result = JibitIdentityService::interpretNationalMobileMatch([
|
||||||
|
'code' => 'forbidden',
|
||||||
|
'message' => 'no access',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertFalse($result['ok']);
|
||||||
|
$this->assertSame('jibit_forbidden', $result['code']);
|
||||||
|
$this->assertStringContainsString('توکن', $result['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_unknown_payload_includes_jibit_code_and_message(): void
|
||||||
|
{
|
||||||
|
$result = JibitIdentityService::interpretNationalMobileMatch([
|
||||||
|
'code' => 'some.service.error',
|
||||||
|
'message' => 'provider down',
|
||||||
|
'http_status' => 503,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertFalse($result['ok']);
|
||||||
|
$this->assertSame('jibit_some.service.error', $result['code']);
|
||||||
|
$this->assertStringContainsString('some.service.error', $result['message']);
|
||||||
|
$this->assertStringContainsString('provider down', $result['message']);
|
||||||
|
$this->assertStringContainsString('503', $result['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_empty_response_is_not_generic_wait_for_admin(): void
|
||||||
|
{
|
||||||
|
$result = JibitIdentityService::interpretNationalMobileMatch(null);
|
||||||
|
|
||||||
|
$this->assertFalse($result['ok']);
|
||||||
|
$this->assertSame('jibit_no_response', $result['code']);
|
||||||
|
$this->assertStringNotContainsString('منتظر بررسی', $result['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_national_code_checksum(): void
|
||||||
|
{
|
||||||
|
$this->assertNull(JibitIdentityService::nationalCodeError('0452262615'));
|
||||||
|
$this->assertSame('کد ملی وارد نشده است.', JibitIdentityService::nationalCodeError(''));
|
||||||
|
$this->assertSame('کد ملی باید ۱۰ رقم باشد.', JibitIdentityService::nationalCodeError('123'));
|
||||||
|
$this->assertSame('کد ملی از نظر رقم کنترل نامعتبر است.', JibitIdentityService::nationalCodeError('0000000000'));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user