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()
|
public function boot()
|
||||||
{
|
{
|
||||||
Schema::defaultStringLength(191);
|
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
|
condition: service_healthy
|
||||||
restart: unless-stopped
|
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:
|
nginx:
|
||||||
image: nginx:1.25-alpine
|
image: nginx:1.25-alpine
|
||||||
container_name: ${DOCKER_CONTAINER_NAME}_nginx
|
container_name: ${DOCKER_CONTAINER_NAME}_nginx
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ Route::group(['middleware' => ['auth:sanctum']], static function () {
|
|||||||
Route::post('logout', [ApiController::class, 'logout']);
|
Route::post('logout', [ApiController::class, 'logout']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/* Non Authenticated Routes */
|
/* Non Authenticated Routes */
|
||||||
Route::get('user-exists', [ApiController::class, 'userExists']);
|
Route::get('user-exists', [ApiController::class, 'userExists']);
|
||||||
Route::get('get-currencies', [ApiController::class, 'getCurrencies']);
|
Route::get('get-currencies', [ApiController::class, 'getCurrencies']);
|
||||||
|
|||||||
Reference in New Issue
Block a user