montzar added

This commit is contained in:
2026-05-25 12:47:04 +03:30
parent 7f0f91701e
commit b84ea8aabe
5 changed files with 232 additions and 428 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ class ConfigService
public function UpdateConfig($name, $value)
{
return Setting::updateOrCreate(
return \App\Models\Setting::updateOrCreate(
['key' => $name],
['value' => $value]
);
@@ -6,15 +6,20 @@ use App\Models\Cnt;
use App\Models\Order;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
class LimanService
class MontzarService
{
private function config(): ConfigService
{
return app(ConfigService::class);
}
private function baseUrl(): string
{
return rtrim(
app(ConfigService::class)->Config('liman_base_url') ?: 'https://montpar.ir',
$this->config()->Config('montzar_base_url') ?: 'https://montpar.ir',
'/'
);
}
@@ -23,37 +28,36 @@ class LimanService
{
return $this->baseUrl() . '/' . ltrim($path, '/');
}
public function liman_login()
public function montzarLogin(): string
{
$config = app(ConfigService::class);
$response = Http::timeout(10)
->acceptJson()
->post($this->endpoint('/server/auth/login'), [
'mobile' => $this->config()->Config('montzar_mobile'),
'password' => $this->config()->Config('montzar_password'),
'provider' => 'customer',
'type_app' => 'client',
])
->json();
$mobile = $config->Config('liman_mobile');
$password = $config->Config('liman_password');
$liman = Http::timeout(10)->post($this->endpoint('/server/auth/login'), [
'mobile' => $mobile,
'password' => $password,
'provider' => 'customer',
'type_app' => 'client',
])->json();
$token = $liman['access_token'] ?? $liman['token'] ?? null;
$token = $response['access_token'] ?? $response['token'] ?? null;
if (!$token) {
throw new \Exception('Liman login failed: ' . json_encode($liman, JSON_UNESCAPED_UNICODE));
throw new \Exception('Montzar login failed: ' . json_encode($response, JSON_UNESCAPED_UNICODE));
}
$config->UpdateConfig('liman_token', $token);
$this->config()->UpdateConfig('montzar_token', $token);
return $token;
}
public function getToken(): string
{
$token = trim((string) app(ConfigService::class)->Config('liman_token'));
$token = trim((string) $this->config()->Config('montzar_token'));
if (!$token) {
$token = $this->liman_login();
$token = $this->montzarLogin();
}
return $token;
@@ -64,27 +68,29 @@ class LimanService
$token = $this->getToken();
$response = Http::timeout(7)
->acceptJson()
->withOptions([
'curl' => [
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
CURLOPT_TCP_FASTOPEN => 1,
]
],
])
->withToken($token)
->get($this->endpoint('/server/customer/product/list'))
->json();
if ((isset($response['message']) && $response['message'] === 'no authorised') || $response === null) {
$token = $this->liman_login();
$token = $this->montzarLogin();
$response = Http::timeout(7)
->acceptJson()
->withToken($token)
->get($this->endpoint('/server/customer/product/list'))
->json();
}
if (!is_array($response)) {
throw new \Exception('Provider product list response is not array');
throw new \Exception('Montzar product list response is not array');
}
return $response;
@@ -93,35 +99,34 @@ class LimanService
public function sendOrder(array &$data)
{
$payload = $this->makeOrderPayload($data);
$token = $this->getToken();
$httpResponse = $this->postToLiman(
$httpResponse = $this->postToMontzar(
$this->endpoint('/server/customer/order'),
$token,
$payload
);
$body = $this->decodeLimanHttpBody($httpResponse);
$body = $this->decodeMontzarHttpBody($httpResponse);
if (is_array($body) && ($body['message'] ?? null) === 'no authorised') {
$token = $this->liman_login();
$token = $this->montzarLogin();
$httpResponse = $this->postToLiman(
$httpResponse = $this->postToMontzar(
$this->endpoint('/server/customer/order'),
$token,
$payload
);
$body = $this->decodeLimanHttpBody($httpResponse);
$body = $this->decodeMontzarHttpBody($httpResponse);
}
$this->logLimanOrderResponse($httpResponse, $body);
$this->logMontzarOrderResponse($httpResponse, $body);
$parsed = $this->parseLimanOrderResponse($body, (int) $data['direction']);
$parsed = $this->parseMontzarOrderResponse($body, (int) $data['direction']);
if (!$parsed['ok']) {
Log::warning('Liman order rejected', [
Log::warning('Montzar order rejected', [
'base_url' => $this->baseUrl(),
'status' => $httpResponse->status(),
'body' => $body,
@@ -131,11 +136,11 @@ class LimanService
]);
throw new UnprocessableEntityHttpException(
$this->formatLimanErrorMessage($parsed['error'], $httpResponse)
$this->formatMontzarErrorMessage($parsed['error'], $httpResponse)
);
}
$this->syncOrderWithLimanResponse($data, $parsed);
$this->syncOrderWithMontzarResponse($data, $parsed);
return $body;
}
@@ -143,13 +148,13 @@ class LimanService
private function makeOrderPayload(array $data): array
{
$mazaneh = ((int) $data['direction'] === 1)
? Cnt::where('key', 'liman_truly_buy_mazaneh')->value('value')
: Cnt::where('key', 'liman_truly_sell_mazaneh')->value('value');
? $this->config()->Config('montzar_truly_buy_mazaneh')
: $this->config()->Config('montzar_truly_sell_mazaneh');
$limanPrice = (float) Cnt::where('key', 'liman_price')->value('value');
$montzarPrice = (float) $this->config()->Config('montzar_price');
$cash = (int) round(
$data['total_price'] ?? ($limanPrice * (float) $data['amount'])
$data['total_price'] ?? ($montzarPrice * (float) $data['amount'])
);
$customerName = auth('customer')->check()
@@ -159,15 +164,15 @@ class LimanService
return [
'mazaneh' => (int) $mazaneh,
'amount' => (float) $data['amount'],
'description' => app(ConfigService::class)->Config('name_fa') . ' - ' . $customerName,
'description' => $this->config()->Config('name_fa') . ' - ' . $customerName,
'direction' => (int) $data['direction'],
'product_id' => (int) (app(ConfigService::class)->Config('liman_product_id') ?: 25),
'product_id' => (int) ($this->config()->Config('montzar_product_id') ?: 25),
'cash' => $cash,
'input_mode' => 'gold',
];
}
private function postToLiman(string $url, string $token, array $payload)
private function postToMontzar(string $url, string $token, array $payload)
{
return Http::timeout(15)
->acceptJson()
@@ -175,7 +180,7 @@ class LimanService
->post($url, $payload);
}
private function decodeLimanHttpBody($httpResponse): ?array
private function decodeMontzarHttpBody($httpResponse): ?array
{
$body = $httpResponse->json();
@@ -198,25 +203,28 @@ class LimanService
return null;
}
private function logLimanOrderResponse($httpResponse, $body): void
private function logMontzarOrderResponse($httpResponse, $body): void
{
try {
$value = $body === null
? $httpResponse->body()
: json_encode($body, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
Cnt::where('key', 'liman_order_response')->update(['value' => $value]);
// مربوط به منتزر: settings
$this->config()->UpdateConfig('montzar_order_response', $value);
// عمومی: اگر در const/Cnt داری همان‌جا بماند
Cnt::where('key', 'last_order_log')->update(['value' => $value]);
} catch (\Exception $e) {
Log::warning('Could not persist liman order response', [
Log::warning('Could not persist montzar order response', [
'error' => $e->getMessage(),
]);
}
}
private function formatLimanErrorMessage(?string $error, $httpResponse): string
private function formatMontzarErrorMessage(?string $error, $httpResponse): string
{
if ($error && $error !== 'پاسخ نامعتبر از سرور لیمان (اتصال یا فرمت JSON)') {
if ($error && $error !== 'پاسخ نامعتبر از سرور منتظر (اتصال یا فرمت JSON)') {
return $error;
}
@@ -224,38 +232,27 @@ class LimanService
$raw = trim((string) $httpResponse->body());
if ($raw === '') {
return "خطا در ارتباط با لیمان (HTTP {$status})";
return "خطا در ارتباط با منتظر (HTTP {$status})";
}
if (stripos($raw, '<!DOCTYPE') !== false || stripos($raw, '<html') !== false) {
return "خطا از سرویس لیمان (HTTP {$status}). پاسخ JSON دریافت نشد.";
return "خطا از سرویس منتظر (HTTP {$status}). پاسخ JSON دریافت نشد.";
}
return mb_substr($raw, 0, 300);
}
/**
* @return array{ok: bool, provider_id: ?int, error: ?string}
*/
private function parseLimanOrderResponse($body, int $direction): array
private function parseMontzarOrderResponse($body, int $direction): array
{
if (!is_array($body)) {
return [
'ok' => false,
'provider_id' => null,
'error' => 'پاسخ نامعتبر از سرور لیمان (اتصال یا فرمت JSON)',
'error' => 'پاسخ نامعتبر از سرور منتظر (اتصال یا فرمت JSON)',
];
}
if (!empty($body['message']) && is_string($body['message'])) {
if ($body['message'] === 'no authorised') {
return [
'ok' => false,
'provider_id' => null,
'error' => 'no authorised',
];
}
return [
'ok' => false,
'provider_id' => null,
@@ -330,20 +327,18 @@ class LimanService
return (int) $body['order']['id'];
}
if (isset($body[1]) && is_array($body[1])) {
if (!empty($body[1]['id'])) {
return (int) $body[1]['id'];
}
foreach ([1, 2] as $index) {
if (isset($body[$index]) && is_array($body[$index])) {
if (!empty($body[$index]['id'])) {
return (int) $body[$index]['id'];
}
if (!empty($body[1]['order']['id'])) {
return (int) $body[1]['order']['id'];
if (!empty($body[$index]['order']['id'])) {
return (int) $body[$index]['order']['id'];
}
}
}
if (isset($body[2]) && is_array($body[2]) && !empty($body[2]['id'])) {
return (int) $body[2]['id'];
}
foreach (['buy', 'sell'] as $sideKey) {
if (!isset($body[$sideKey]) || !is_array($body[$sideKey])) {
continue;
@@ -361,14 +356,14 @@ class LimanService
return null;
}
private function syncOrderWithLimanResponse(array &$data, array $parsed): void
private function syncOrderWithMontzarResponse(array &$data, array $parsed): void
{
$limanDiff = (float) Cnt::where('key', 'liman_diff')->value('value');
$limanPrice = (float) Cnt::where('key', 'liman_price')->value('value');
$montzarDiff = (float) $this->config()->Config('montzar_diff');
$montzarPrice = (float) $this->config()->Config('montzar_price');
$totalPriceLiman = ((int) $data['direction'] === 1)
? ($limanPrice + $limanDiff)
: ($limanPrice - $limanDiff);
$totalPriceMontzar = ((int) $data['direction'] === 1)
? ($montzarPrice + $montzarDiff)
: ($montzarPrice - $montzarDiff);
$providerOrderId = $parsed['provider_id'] ?? null;
@@ -377,11 +372,14 @@ class LimanService
$data['order']->provider_id = $providerOrderId;
}
$data['order']->total_price_liman = $totalPriceLiman;
if (Schema::hasColumn('orders', 'total_price_montzar')) {
$data['order']->total_price_montzar = $totalPriceMontzar;
}
$data['order']->save();
}
$data['total_price_liman'] = $totalPriceLiman;
$data['total_price_montzar'] = $totalPriceMontzar;
if ($providerOrderId !== null) {
$data['provider_id'] = $providerOrderId;