https and sms job add
This commit is contained in:
174
app/Jobs/SendSmsJob.php
Normal file
174
app/Jobs/SendSmsJob.php
Normal file
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\EskizToken;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class SendSmsJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected string $phoneNumber;
|
||||
protected int $code;
|
||||
|
||||
public function __construct(string $phoneNumber, int $code)
|
||||
{
|
||||
$this->phoneNumber = $phoneNumber;
|
||||
$this->code = $code;
|
||||
}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
$phoneNumber = $this->normalizePhoneNumber($this->phoneNumber);
|
||||
|
||||
// Bazadagi tokenni olish
|
||||
$token = $this->getTokenFromDb();
|
||||
|
||||
// Token yo'q yoki expired bo'lsa yangilash
|
||||
if (!$token) {
|
||||
$token = $this->refreshToken();
|
||||
if (!$token) {
|
||||
Log::error('Eskiz token olish imkonsiz', ['phone' => $phoneNumber]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$postData = [
|
||||
'mobile_phone' => $phoneNumber,
|
||||
'message' => "DELGO hisobiga kirish uchun kod: {$this->code} Ushbu kodni ulashmang! #WBcz5ARFKcp",
|
||||
// 'message' => "DELGO hisobiga kirish uchun kod: {$this->code} Ushbu kodni ulashmang! #WBcz5ARFKcp",
|
||||
'from' => "4546"
|
||||
];
|
||||
|
||||
$response = $this->sendSmsRequest($token, $postData, $phoneNumber);
|
||||
|
||||
// Token eskirgan bo‘lsa qayta olish
|
||||
if ($response['http_code'] === 401) {
|
||||
Log::warning("Eskiz token muddati tugagan, yangidan olinmoqda...");
|
||||
|
||||
$token = $this->refreshToken();
|
||||
if ($token) {
|
||||
$this->sendSmsRequest($token, $postData, $phoneNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function sendSmsRequest(string $token, array $postData, string $phoneNumber): array
|
||||
{
|
||||
$curl = curl_init();
|
||||
curl_setopt_array($curl, [
|
||||
CURLOPT_URL => "https://notify.eskiz.uz/api/message/sms/send",
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => http_build_query($postData),
|
||||
CURLOPT_HTTPHEADER => [
|
||||
"Authorization: Bearer $token",
|
||||
"Content-Type: application/x-www-form-urlencoded"
|
||||
],
|
||||
]);
|
||||
|
||||
$response = curl_exec($curl);
|
||||
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||
$err = curl_error($curl);
|
||||
curl_close($curl);
|
||||
|
||||
if ($err) {
|
||||
Log::error("Eskiz SMS cURL Error: " . $err, [
|
||||
'phone' => $phoneNumber,
|
||||
'http_code' => $httpCode
|
||||
]);
|
||||
return ['http_code' => $httpCode];
|
||||
}
|
||||
|
||||
Log::debug("Eskiz SMS Response", [
|
||||
'phone' => $phoneNumber,
|
||||
'http_code' => $httpCode,
|
||||
'response' => $response
|
||||
]);
|
||||
|
||||
return ['http_code' => $httpCode, 'body' => $response];
|
||||
}
|
||||
|
||||
private function normalizePhoneNumber(string $phoneNumber): string
|
||||
{
|
||||
$phoneNumber = preg_replace('/[^0-9]/', '', $phoneNumber);
|
||||
|
||||
if (strlen($phoneNumber) === 9 && in_array(substr($phoneNumber, 0, 2), [
|
||||
'33', '77', '88', '90', '91', '93', '94', '95', '97', '98', '99'
|
||||
])) {
|
||||
$phoneNumber = '998' . $phoneNumber;
|
||||
} elseif (str_starts_with($phoneNumber, '+998')) {
|
||||
$phoneNumber = substr($phoneNumber, 1);
|
||||
}
|
||||
|
||||
return $phoneNumber;
|
||||
}
|
||||
|
||||
private function getTokenFromDb(): ?string
|
||||
{
|
||||
$record = EskizToken::latest()->first();
|
||||
|
||||
if (!$record) return null;
|
||||
|
||||
// Token muddati tugagan bo'lsa
|
||||
if ($record->expires_at && now()->greaterThan($record->expires_at)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $record->token;
|
||||
}
|
||||
|
||||
private function refreshToken(): ?string
|
||||
{
|
||||
$email = config('services.eskiz.email');
|
||||
$password = config('services.eskiz.password');
|
||||
|
||||
$postData = ['email' => $email, 'password' => $password];
|
||||
|
||||
$curl = curl_init();
|
||||
curl_setopt_array($curl, [
|
||||
CURLOPT_URL => "https://notify.eskiz.uz/api/auth/login",
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => http_build_query($postData),
|
||||
CURLOPT_HTTPHEADER => ["Content-Type: application/x-www-form-urlencoded"],
|
||||
]);
|
||||
|
||||
$response = curl_exec($curl);
|
||||
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||
$err = curl_error($curl);
|
||||
curl_close($curl);
|
||||
|
||||
if ($err) {
|
||||
Log::error("Eskiz Auth Error: " . $err, ['http_code' => $httpCode]);
|
||||
return null;
|
||||
}
|
||||
|
||||
$data = json_decode($response, true);
|
||||
|
||||
if (isset($data['message'], $data['data']['token']) && $data['message'] === 'token_generated') {
|
||||
$token = $data['data']['token'];
|
||||
$expiresAt = now()->addHour(); // Token 1 soatga amal qiladi
|
||||
|
||||
// Tokenni bazaga saqlash (update yoki create)
|
||||
EskizToken::updateOrCreate(
|
||||
['id' => 1], // har doim 1-row ishlatiladi
|
||||
[
|
||||
'token' => $token,
|
||||
'expires_at' => $expiresAt
|
||||
]
|
||||
);
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
Log::error("Eskiz Auth Response Invalid", ['response' => $response]);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
25
app/Models/EskizToken.php
Normal file
25
app/Models/EskizToken.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class EskizToken extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = ['token', 'expires_at'];
|
||||
|
||||
protected $dates = ['expires_at'];
|
||||
|
||||
/**
|
||||
* Token amal qiladimi?
|
||||
*/
|
||||
public function isValid(): bool
|
||||
{
|
||||
return $this->expires_at && Carbon::now()->lt($this->expires_at);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,6 +27,6 @@ class AppServiceProvider extends ServiceProvider
|
||||
public function boot()
|
||||
{
|
||||
Schema::defaultStringLength(191);
|
||||
URL::forceScheme('http');
|
||||
URL::forceScheme('https');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('eskiz_tokens', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->text('token');
|
||||
$table->timestamp('expires_at');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('eskiz_tokens');
|
||||
}
|
||||
};
|
||||
@@ -23,6 +23,42 @@ services:
|
||||
condition: service_healthy
|
||||
restart: unless-stopped
|
||||
|
||||
horizon:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
WWWGROUP: '${WWWGROUP:-1000}'
|
||||
container_name: ${DOCKER_CONTAINER_NAME}_horizon
|
||||
command: php artisan horizon
|
||||
volumes:
|
||||
- .:/var/www/html
|
||||
networks:
|
||||
- devituz
|
||||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
restart: unless-stopped
|
||||
|
||||
scheduler:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: ${DOCKER_CONTAINER_NAME}_scheduler
|
||||
command: sh -c "while [ true ]; do php artisan schedule:run --verbose --no-interaction; sleep 60; done"
|
||||
volumes:
|
||||
- .:/var/www/html
|
||||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- devituz
|
||||
restart: unless-stopped
|
||||
|
||||
nginx:
|
||||
image: nginx:1.25-alpine
|
||||
container_name: ${DOCKER_CONTAINER_NAME}_nginx
|
||||
|
||||
@@ -71,6 +71,7 @@ Route::group(['middleware' => ['auth:sanctum']], static function () {
|
||||
Route::post('logout', [ApiController::class, 'logout']);
|
||||
});
|
||||
|
||||
|
||||
/* Non Authenticated Routes */
|
||||
Route::get('user-exists', [ApiController::class, 'userExists']);
|
||||
Route::get('get-currencies', [ApiController::class, 'getCurrencies']);
|
||||
|
||||
Reference in New Issue
Block a user