Introduce a comprehensive set of commercial features including a multi-step order approval workflow, customer credit management, and specialized import service invoicing. Key changes: - Implement `pending_approval` and `approved` shipment statuses to allow staff verification before customer payment. - Add a credit system to `User` model with `credit_limit` and `credit_used` to manage customer balances and debts. - Develop a new `importInvoice` PDF generation service following the "Sheet ENG Invoice" specification for import services. - Add Filament resources for managing Audit Logs, Commitment Forms, Customer Credits, and Shipment Checklists. - Implement staff-specific APIs for order approval/rejection and customer financial status monitoring. - Integrate Kavenegar SMS service for mobile verification and notifications. - Add bulk tracking import functionality via CSV/Excel. - Update WordPress bridge assets (CSS/JS) to support the new multi-step order form UI and updated redirection logic. - Update deployment configurations and documentation to reflect new production domains and feature sets.
170 lines
5.1 KiB
PHP
170 lines
5.1 KiB
PHP
<?php
|
||
|
||
namespace App\Services;
|
||
|
||
use Illuminate\Support\Facades\Http;
|
||
use Illuminate\Support\Facades\Cache;
|
||
use Illuminate\Support\Str;
|
||
|
||
class KavenegarSmsService
|
||
{
|
||
private string $apiKey;
|
||
private string $sender;
|
||
|
||
public function __construct()
|
||
{
|
||
$this->apiKey = config('services.kavenegar.api_key', '');
|
||
$this->sender = config('services.kavenegar.sender', '');
|
||
}
|
||
|
||
/**
|
||
* ارسال کد تأیید به شماره موبایل
|
||
*/
|
||
public function sendVerificationCode(string $phone): array
|
||
{
|
||
$code = Str::random(5, '0123456789');
|
||
$cacheKey = "sms_verify_{$phone}";
|
||
|
||
// ذخیره کد در cache به مدت ۱۰ دقیقه
|
||
Cache::put($cacheKey, $code, now()->addMinutes(10));
|
||
|
||
$message = "کد تأیید IFNEX: {$code}";
|
||
|
||
return $this->send($phone, $message);
|
||
}
|
||
|
||
/**
|
||
* بررسی کد تأیید
|
||
*/
|
||
public function verifyCode(string $phone, string $code): bool
|
||
{
|
||
$cacheKey = "sms_verify_{$phone}";
|
||
$storedCode = Cache::get($cacheKey);
|
||
|
||
if ($storedCode && $storedCode === $code) {
|
||
Cache::forget($cacheKey);
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* ارسال پیامک
|
||
*/
|
||
public function send(string $receptor, string $message): array
|
||
{
|
||
if (empty($this->apiKey)) {
|
||
return [
|
||
'success' => false,
|
||
'message' => 'API Key Kavenegar تنظیم نشده است',
|
||
];
|
||
}
|
||
|
||
try {
|
||
$response = Http::timeout(10)
|
||
->post("https://api.kavenegar.com/v1/{$this->apiKey}/sms/send.json", [
|
||
'receptor' => $receptor,
|
||
'sender' => $this->sender,
|
||
'message' => $message,
|
||
]);
|
||
|
||
$data = $response->json();
|
||
|
||
if ($response->successful() && isset($data['return']['status']) && $data['return']['status'] == 200) {
|
||
return [
|
||
'success' => true,
|
||
'message' => 'پیامک با موفقیت ارسال شد',
|
||
'cost' => $data['entries'][0]['cost'] ?? 0,
|
||
];
|
||
}
|
||
|
||
return [
|
||
'success' => false,
|
||
'message' => $data['return']['message'] ?? 'خطا در ارسال پیامک',
|
||
];
|
||
} catch (\Exception $e) {
|
||
return [
|
||
'success' => false,
|
||
'message' => 'خطا در اتصال به سرور Kavenegar: ' . $e->getMessage(),
|
||
];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* ارسال پیامک گروهی
|
||
*/
|
||
public function sendBulk(array $receptors, string $message): array
|
||
{
|
||
if (empty($this->apiKey)) {
|
||
return [
|
||
'success' => false,
|
||
'message' => 'API Key Kavenegar تنظیم نشده است',
|
||
];
|
||
}
|
||
|
||
try {
|
||
$response = Http::timeout(30)
|
||
->post("https://api.kavenegar.com/v1/{$this->apiKey}/sms/send.json", [
|
||
'receptor' => $receptors,
|
||
'sender' => $this->sender,
|
||
'message' => $message,
|
||
]);
|
||
|
||
$data = $response->json();
|
||
|
||
if ($response->successful() && isset($data['return']['status']) && $data['return']['status'] == 200) {
|
||
return [
|
||
'success' => true,
|
||
'message' => 'پیامک با موفقیت ارسال شد',
|
||
'cost' => collect($data['entries'])->sum('cost'),
|
||
];
|
||
}
|
||
|
||
return [
|
||
'success' => false,
|
||
'message' => $data['return']['message'] ?? 'خطا در ارسال پیامک',
|
||
];
|
||
} catch (\Exception $e) {
|
||
return [
|
||
'success' => false,
|
||
'message' => 'خطا در اتصال به سرور Kavenegar: ' . $e->getMessage(),
|
||
];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* بررسی وضعیت پیامک ارسال شده
|
||
*/
|
||
public function checkStatus(string $messageId): array
|
||
{
|
||
try {
|
||
$response = Http::timeout(10)
|
||
->get("https://api.kavenegar.com/v1/{$this->apiKey}/select.json", [
|
||
'messageid' => $messageId,
|
||
]);
|
||
|
||
$data = $response->json();
|
||
|
||
if ($response->successful() && isset($data['return']['status']) && $data['return']['status'] == 200) {
|
||
$entry = $data['entries'][0] ?? null;
|
||
return [
|
||
'success' => true,
|
||
'status' => $entry['status'] ?? 'unknown',
|
||
'status_text' => $entry['statustext'] ?? 'نامشخص',
|
||
];
|
||
}
|
||
|
||
return [
|
||
'success' => false,
|
||
'message' => $data['return']['message'] ?? 'خطا در بررسی وضعیت',
|
||
];
|
||
} catch (\Exception $e) {
|
||
return [
|
||
'success' => false,
|
||
'message' => 'خطا در اتصال به سرور Kavenegar: ' . $e->getMessage(),
|
||
];
|
||
}
|
||
}
|
||
}
|