mirror of
https://git.meshkee.com/cssd/cssd-back.git
synced 2026-10-10 19:31:07 +03:30
add rahyab notification service
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class FieldNotExistsException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Exceptions\FieldNotExistsException;
|
||||
// use App\Scopes\OrderByIdScope;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
trait BasicModel
|
||||
{
|
||||
private int $pageSizeLimit = 48;
|
||||
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
// if (! app()->runningInConsole()) {
|
||||
// static::addGlobalScope( new OrderByIdScope );
|
||||
// }
|
||||
}
|
||||
|
||||
public function getPerPage()
|
||||
{
|
||||
$pageSize = (int) request( 'per_page' , $this->perPage );
|
||||
return min( $pageSize , $this->pageSizeLimit );
|
||||
}
|
||||
|
||||
public function attributeExists( $attr ): bool
|
||||
{
|
||||
|
||||
return array_key_exists( $attr , $this->attributes );
|
||||
}
|
||||
|
||||
public function getField( $name )
|
||||
{
|
||||
$columnName = static::getColumn( $name );
|
||||
return $this->$columnName;
|
||||
}
|
||||
|
||||
public function setField( $name , $value ): void
|
||||
{
|
||||
$columnName = static::getColumn( $name );
|
||||
$this->$columnName = $value;
|
||||
}
|
||||
|
||||
public static function getColumnTable( $name ): string
|
||||
{
|
||||
return static::getTableName() . '.' . static::getColumn( $name );
|
||||
}
|
||||
|
||||
public static function getColumn( $name )
|
||||
{
|
||||
$fieldName = Arr::get( static::$maps , $name );
|
||||
|
||||
if ( is_null( $fieldName ) ) {
|
||||
throw new FieldNotExistsException( "field $name not exists" );
|
||||
}
|
||||
|
||||
return $fieldName;
|
||||
}
|
||||
|
||||
public function getTable()
|
||||
{
|
||||
return static::getTableName();
|
||||
}
|
||||
|
||||
public function fieldValue( $name )
|
||||
{
|
||||
return $this->$name;
|
||||
}
|
||||
|
||||
public function getAttributes()
|
||||
{
|
||||
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
public function isLoaded( $relationName ): bool
|
||||
{
|
||||
return isset( $this->relations[ $relationName ] ) and $this->$relationName != null;
|
||||
}
|
||||
|
||||
abstract public static function getTableName();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
|
||||
class Sms extends Model
|
||||
{
|
||||
|
||||
use BasicModel;
|
||||
|
||||
protected $fillable = [
|
||||
'client_id' , 'status_code' , 'status' , 'message' , 'rel_id' , 'rel_type' , 'cell_number' , 'segment_count' ,
|
||||
];
|
||||
|
||||
protected $hidden = [];
|
||||
|
||||
public static function getTableName(): string
|
||||
{
|
||||
return "sms";
|
||||
}
|
||||
|
||||
public function receiver(): MorphTo
|
||||
{
|
||||
return $this->morphTo( null , 'rel_type' , 'rel_id' );
|
||||
}
|
||||
|
||||
public function smsBatch(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo( SmsBatch::class );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class SmsBatch extends Model
|
||||
{
|
||||
|
||||
use SoftDeletes , BasicModel;
|
||||
|
||||
protected $fillable = [
|
||||
'category' , 'operator' , 'code' , 'fee' , 'type' , 'business_id' , 'is_admin' , 'is_systematic' , 'pattern' , 'from'
|
||||
];
|
||||
|
||||
protected $hidden = [];
|
||||
|
||||
public static function getTableName(): string
|
||||
{
|
||||
return "sms_batch";
|
||||
}
|
||||
|
||||
public function smsList(): HasMany
|
||||
{
|
||||
return $this->hasMany( Sms::class );
|
||||
}
|
||||
|
||||
public function scopeSingle( $query )
|
||||
{
|
||||
return $query->whereCategory( 'single' );
|
||||
}
|
||||
|
||||
public function scopeBatch( $query )
|
||||
{
|
||||
return $query->whereCategory( 'batch' );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Scopes;
|
||||
|
||||
use Illuminate\Database\Eloquent\Scope;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class OrderByIdScope implements Scope
|
||||
{
|
||||
public function apply(Builder $builder, Model $model)
|
||||
{
|
||||
$builder->orderBy($model->getTable().'.id', 'desc');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Notification\Batch;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class BatchTransmitter
|
||||
{
|
||||
|
||||
protected Collection $collection;
|
||||
protected mixed $config;
|
||||
protected $message;
|
||||
|
||||
public function __construct( Collection $collection )
|
||||
{
|
||||
$this->collection = $collection;
|
||||
$this->config = config( 'notification.drivers.rahyab_advertise' );
|
||||
$this->client = new \SoapClient( $this->config[ 'url' ] );
|
||||
}
|
||||
|
||||
public function send( string $message )
|
||||
{
|
||||
$this->message = $message;
|
||||
if ( $this->collection->count() <= config( 'notification.max_phone_size.do_send_sms' ) ) {
|
||||
return $result = $this->client->doSendSMS( $this->payload() );
|
||||
}
|
||||
}
|
||||
|
||||
protected function getPhones()
|
||||
{
|
||||
$phones = [];
|
||||
foreach ( $this->collection as $key => $item ) {
|
||||
$phones[] = $item->getPhone();
|
||||
}
|
||||
return array_unique( $phones );
|
||||
}
|
||||
|
||||
protected function payload()
|
||||
{
|
||||
return array(
|
||||
'uUsername' => $this->config[ 'username' ] ,
|
||||
'uPassword' => $this->config[ 'password' ] ,
|
||||
'uNumber' => $this->config[ 'from' ] ,
|
||||
'uCellphones' => implode( ';' , $this->getPhones() ) ,
|
||||
'uMessage' => $this->message ,
|
||||
'uFarsi' => true ,
|
||||
'uTopic' => false ,
|
||||
'uFlash' => false ,
|
||||
'uUDH' => ''
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Notification\Batch;
|
||||
|
||||
use App\Models\SmsBatch;
|
||||
use App\Services\Notification\Events\SmsSent;
|
||||
use App\Services\Notification\Events\SmsSentAgain;
|
||||
use App\Services\Notification\MessagePattern\Pattern;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use SoapClient;
|
||||
|
||||
class PeerToPeer
|
||||
{
|
||||
protected Collection $collection;
|
||||
protected array $config;
|
||||
protected Pattern $messagePatternClass;
|
||||
protected string $messagePattern;
|
||||
protected string $operator;
|
||||
protected bool $isAdmin = false;
|
||||
protected bool $isSystematic = false;
|
||||
protected int $price = -80;
|
||||
|
||||
public function __construct(string $message, Collection $collection, string $category, $uniqueCode, $operator = 'advertise')
|
||||
{
|
||||
if ($this->isValidCost() || $operator == 'service') {
|
||||
$this->operator = ($operator == 'advertise') ? 'rahyab_advertise' : 'rahyab_service';
|
||||
$this->collection = $collection;
|
||||
$this->messagePatternClass = new Pattern($message);
|
||||
$this->messagePattern = $this->messagePatternClass->getPattern();
|
||||
$this->config = array_merge($this->createExtra($category, $uniqueCode), config('notification.drivers.' . $this->operator));
|
||||
|
||||
if (isset($this->config['operator'])) {
|
||||
if (str_contains($this->config['operator'], 'advertise')) {
|
||||
$this->config['type'] = 'advertise';
|
||||
} else {
|
||||
$this->config['type'] = 'service';
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$this->client = new SoapClient( $this->config[ 'url' ] );
|
||||
} catch ( \SoapFault $e ) {
|
||||
dd($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function isValidCost(): bool
|
||||
{
|
||||
if ( $this->price > -50000.00) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function isSystematic($isSystematic = 0): static
|
||||
{
|
||||
$this->isSystematic = $isSystematic;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isAdmin($isAdmin = 0): static
|
||||
{
|
||||
$this->isAdmin = $isAdmin;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function send($userData): void
|
||||
{
|
||||
if ($this->collection->count() <= config('notification.max_phone_size.do_send_sms_array_c')) {
|
||||
$this->setIsAdminAndIsSystematicInConfig();
|
||||
$payload = $this->payload($userData);
|
||||
$response = $this->client->doSendSMSArrayC($payload)->doSendSMSArrayCResult->DataSendOut;
|
||||
$this->serializeToDatabase($payload['uDataSendIn'], $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function sendAgain($userData, SmsBatch $smsBatch): void
|
||||
{
|
||||
if ($this->collection->count() <= config('notification.max_phone_size.do_send_sms_array_c')) {
|
||||
$payload = $this->payload($userData);
|
||||
$response = $this->client->doSendSMSArrayC($payload)->doSendSMSArrayCResult->DataSendOut;
|
||||
$this->updateToDatabase($payload['uDataSendIn'], $response, $smsBatch);
|
||||
}
|
||||
}
|
||||
|
||||
protected function payload($userData): array
|
||||
{
|
||||
$data = [];
|
||||
foreach ($this->collection as $key => $item) {
|
||||
$data[$key] = $this->prepareData($item, $userData);
|
||||
}
|
||||
return array(
|
||||
'uUsername' => $this->config['username'],
|
||||
'uPassword' => $this->config['password'],
|
||||
'uDataSendIn' => $data
|
||||
);
|
||||
}
|
||||
|
||||
protected function prepareData(Model $model, $userData): array
|
||||
{
|
||||
$fillable = is_null($userData) ? $model : $userData;
|
||||
|
||||
return [
|
||||
'ClientID' => rand(1, 1000000000000000),
|
||||
'ShortCode' => $this->findFrom(),
|
||||
'Cellphone' => $model->getPhone(),
|
||||
'Message' => $this->messagePatternClass->fill($fillable),
|
||||
'Farsi' => true,
|
||||
'Flash' => false,
|
||||
'UDH' => '',
|
||||
'ServiceID' => ''
|
||||
];
|
||||
}
|
||||
|
||||
protected function findFrom()
|
||||
{
|
||||
$smsOperatorConfig = collect(config('notification.config_system'));
|
||||
|
||||
if (is_null($smsOperatorConfig) or $smsOperatorConfig->isEmpty()) {
|
||||
return $this->config['from'];
|
||||
}
|
||||
|
||||
$customConfig = $smsOperatorConfig->getConfig($this->operator);
|
||||
|
||||
if (is_null($customConfig)) {
|
||||
return $this->config['from'];
|
||||
}
|
||||
|
||||
return $customConfig['from'];
|
||||
}
|
||||
|
||||
protected function serializeToDatabase($payload, $response): void
|
||||
{
|
||||
$this->collection->count() > 1 ?: $response = [$response];
|
||||
event(new SmsSent($this->collection, json_decode(json_encode($response), true), $payload, $this->config));
|
||||
}
|
||||
|
||||
protected function updateToDatabase($payload, $response, $smsBatch): void
|
||||
{
|
||||
$this->collection->count() > 1 ?: $response = [$response];
|
||||
event(new SmsSentAgain($this->collection, json_decode(json_encode($response), true), $payload, $this->config, $smsBatch));
|
||||
}
|
||||
|
||||
protected function createExtra($category, $uniqueCode): array
|
||||
{
|
||||
$extra ['is_admin'] = $this->isAdmin;
|
||||
$extra ['is_systematic'] = $this->isSystematic;
|
||||
$extra ['category'] = $category;
|
||||
$extra ['operator'] = 'rahyab_advertise';
|
||||
$extra ['code'] = $uniqueCode;
|
||||
$extra ['messagePattern'] = $this->messagePattern;
|
||||
$extra['className'] = $this->collection->isEmpty() ? null : getNamespaceMap($this->collection->first());
|
||||
return $extra;
|
||||
}
|
||||
|
||||
private function setIsAdminAndIsSystematicInConfig(): void
|
||||
{
|
||||
$this->config['is_admin'] = $this->isAdmin;
|
||||
$this->config['is_systematic'] = $this->isSystematic;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Notification\Batch;
|
||||
|
||||
use App\Models\SmsBatch;
|
||||
use App\Services\Notification\Events\SmsSent;
|
||||
use App\Services\Notification\Events\SmsSentAgain;
|
||||
use App\Services\Notification\MessagePattern\Pattern;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class SimCard
|
||||
{
|
||||
|
||||
protected Collection $collection;
|
||||
protected array $config;
|
||||
protected Pattern $messagePatternClass;
|
||||
protected string $messagePattern;
|
||||
protected array $payload;
|
||||
protected bool $isAdmin = false;
|
||||
protected bool $isSystematic = false;
|
||||
|
||||
public function __construct( $message , Collection $collection , string $category , $uniqueCode )
|
||||
{
|
||||
|
||||
$this->collection = $collection;
|
||||
$this->messagePatternClass = new Pattern( $message );
|
||||
$this->messagePattern = $this->messagePatternClass->getPattern();
|
||||
$this->config = array_merge( $this->createExtra( $category , $uniqueCode ) , config( 'notification.drivers.simcard' ) );
|
||||
|
||||
if ( isset( $this->config[ 'operator' ] ) ) {
|
||||
$this->config[ 'type' ] = 'simcard';
|
||||
}
|
||||
|
||||
$this->client = new \SoapClient( $this->config[ 'url' ] , array( 'trace' => 1 ) );
|
||||
}
|
||||
|
||||
public function isSystematic( $isSystematic = 0 ): static
|
||||
{
|
||||
$this->isSystematic = $isSystematic;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isAdmin( $isAdmin = 0 ): static
|
||||
{
|
||||
$this->isAdmin = $isAdmin;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function send( $userData ): void
|
||||
{
|
||||
if ( $this->collection->count() <= config( 'notification.max_phone_size.do_send_sms_array_c' ) ) {
|
||||
$this->setIsAdminAndIsSystematicInConfig();
|
||||
$payload = $this->payload( $userData );
|
||||
$response = $this->client->SendSMS( $payload[ 'from' ] , $payload[ 'numbers' ] , $payload[ 'messages' ] , $payload[ 'username' ] , $payload[ 'password' ] , $payload[ 'time' ] , $payload[ 'op' ] );
|
||||
$response = json_decode( $response );
|
||||
$this->serializeToDatabase( json_decode( $response[ count( $response ) - 1 ] )[ 1 ] );
|
||||
}
|
||||
}
|
||||
|
||||
public function sendAgain( $userData , SmsBatch $smsBatch ): void
|
||||
{
|
||||
if ( $this->collection->count() <= config( 'notification.max_phone_size.do_send_sms_array_c' ) ) {
|
||||
$payload = $this->payload( $userData );
|
||||
$response = $this->client->SendSMS( $payload[ 'from' ] , $payload[ 'numbers' ] , $payload[ 'messages' ] , $payload[ 'username' ] , $payload[ 'password' ] , $payload[ 'time' ] , $payload[ 'op' ] );
|
||||
$response = json_decode( $response );
|
||||
$this->updateToDatabase( $response , $smsBatch );
|
||||
}
|
||||
}
|
||||
|
||||
protected function payload( $userData ): array
|
||||
{
|
||||
$data = [
|
||||
'username' => $this->config[ 'username' ] ,
|
||||
'password' => $this->config[ 'password' ] ,
|
||||
'from' => $this->config[ 'from' ] ,
|
||||
'op' => "pointtopoint" ,
|
||||
'time' => '' ,
|
||||
];
|
||||
|
||||
foreach ( $this->collection as $key => $item ) {
|
||||
$modelData = $this->prepareData( $item , $userData );
|
||||
$this->payload[] = $modelData;
|
||||
$data[ 'numbers' ][] = $modelData[ 'Cellphone' ];
|
||||
$data[ 'messages' ][] = $modelData[ 'Message' ];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function prepareData( Model $model , $userData ): array
|
||||
{
|
||||
$fillable = is_null( $userData ) ? $model : $userData;
|
||||
return [
|
||||
'Cellphone' => $model->getPhone() ,
|
||||
'Message' => $this->messagePatternClass->fill( $fillable ) ,
|
||||
];
|
||||
}
|
||||
|
||||
protected function serializeToDatabase( $response ): void
|
||||
{
|
||||
$response = $this->prepareResponse( $response );
|
||||
event( new SmsSent( $this->collection , json_decode( json_encode( $response ) , true ) , $this->payload , $this->config ) );
|
||||
}
|
||||
|
||||
|
||||
protected function updateToDatabase( $response , $smsBatch ): void
|
||||
{
|
||||
$response = $this->prepareResponse( $response );
|
||||
event( new SmsSentAgain( $this->collection , json_decode( json_encode( $response ) , true ) , $this->payload , $this->config , $smsBatch ) );
|
||||
}
|
||||
|
||||
protected function prepareResponse( $response ): array
|
||||
{
|
||||
$result = [];
|
||||
foreach ( $response as $value ) {
|
||||
$result[] = [
|
||||
'ClientID' => null ,
|
||||
'ServerID' => is_numeric( $value ) ? $value : -1 ,
|
||||
'Status' => is_numeric( $value ) ? 'Send OK.' : $value ,
|
||||
];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function createExtra( $category , $uniqueCode ): array
|
||||
{
|
||||
$extra [ 'is_admin' ] = $this->isAdmin;
|
||||
$extra [ 'is_systematic' ] = $this->isSystematic;
|
||||
$extra [ 'category' ] = $category;
|
||||
$extra [ 'operator' ] = 'simcard';
|
||||
$extra [ 'code' ] = $uniqueCode;
|
||||
$extra [ 'messagePattern' ] = $this->messagePattern;
|
||||
$extra [ 'className' ] = $this->collection->isEmpty() ? null : getNamespaceMap( $this->collection->first() );
|
||||
return $extra;
|
||||
}
|
||||
|
||||
private function setIsAdminAndIsSystematicInConfig(): void
|
||||
{
|
||||
$this->config[ 'is_admin' ] = $this->isAdmin;
|
||||
$this->config[ 'is_systematic' ] = $this->isSystematic;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Notification\Events;
|
||||
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SmsSent
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public Collection $collection;
|
||||
public array $response;
|
||||
public array $payload;
|
||||
public array $extra;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Collection $collection
|
||||
* @param array $response
|
||||
* @param array $payload
|
||||
* @param array $extra
|
||||
*/
|
||||
public function __construct( Collection $collection , array $response , array $payload , array $extra )
|
||||
{
|
||||
$this->collection = $collection;
|
||||
$this->response = $response;
|
||||
$this->payload = $payload;
|
||||
$this->extra = $extra;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Notification\Events;
|
||||
|
||||
use App\Models\SmsBatch;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SmsSentAgain
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public Collection $collection;
|
||||
public array $response;
|
||||
public array $payload;
|
||||
public array $extra;
|
||||
public SmsBatch $smsBatch;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Collection $collection
|
||||
* @param array $response
|
||||
* @param array $payload
|
||||
* @param array $extra
|
||||
* @param SmsBatch $smsBatch
|
||||
*/
|
||||
public function __construct( Collection $collection , array $response , array $payload , array $extra , SmsBatch $smsBatch )
|
||||
{
|
||||
$this->collection = $collection;
|
||||
$this->response = $response;
|
||||
$this->payload = $payload;
|
||||
$this->extra = $extra;
|
||||
$this->smsBatch = $smsBatch;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Notification\Listeners;
|
||||
|
||||
use App\Models\Sms;
|
||||
use App\Models\SmsBatch;
|
||||
use App\Services\Notification\Events\SmsSent;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class StoreSmsInDatabase
|
||||
{
|
||||
public function __construct()
|
||||
{}
|
||||
|
||||
public function handle( SmsSent $event ): void
|
||||
{
|
||||
$chars_in_every_sms_part = config( "sms.sms_length_calculator.chars_in_every_sms_part" ) > 0 ? : 60;
|
||||
$smsList = [];
|
||||
|
||||
foreach ( $event->collection as $key => $value ) {
|
||||
$smsList[ $key ] = new Sms( [
|
||||
'client_id' => $event->response[ $key ][ 'ClientID' ] ,
|
||||
'status' => $event->response[ $key ][ 'Status' ] ,
|
||||
'message' => $event->payload[ $key ][ 'Message' ] ,
|
||||
'rel_id' => $value->id ,
|
||||
'segment_count' => ceil( strlen( $event->extra[ 'messagePattern' ] ) / $chars_in_every_sms_part ) ,
|
||||
'cell_number' => $event->payload[ $key ][ 'Cellphone' ] ,
|
||||
'rel_type' => $event->extra[ 'className' ] ,
|
||||
'fee' => $event->extra[ 'fee' ] ,
|
||||
] );
|
||||
}
|
||||
|
||||
Log::alert( 'store SmsBatch' , [ 'hasSms' => SmsBatch::where( 'code' , $event->extra[ 'code' ] )->first() ] );
|
||||
|
||||
$smsBatch = SmsBatch::firstOrCreate(
|
||||
[
|
||||
'code' => $event->extra[ 'code' ]
|
||||
] ,
|
||||
[
|
||||
'category' => $event->extra[ 'category' ] ,
|
||||
'operator' => $event->extra[ 'operator' ] ,
|
||||
'type' => $event->extra[ 'type' ] ,
|
||||
'pattern' => $event->extra[ 'messagePattern' ] ,
|
||||
'is_admin' => $event->extra[ 'is_admin' ] ,
|
||||
'is_systematic' => $event->extra[ 'is_systematic' ] ,
|
||||
'from' => $event->extra[ 'from' ] ,
|
||||
]
|
||||
);
|
||||
|
||||
$smsBatch->smsList()->saveMany( $smsList );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Notification\MessagePattern;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Pattern
|
||||
{
|
||||
|
||||
protected string $pattern;
|
||||
|
||||
public function __construct( $pattern )
|
||||
{
|
||||
$this->pattern = $pattern;
|
||||
}
|
||||
|
||||
public function fill( $model ): string
|
||||
{
|
||||
$replacements = $this->findReplacements( $model );
|
||||
return strtr( $this->pattern , $replacements );
|
||||
}
|
||||
|
||||
protected function findReplacements( $model , $prefix = '{' , $postfix = '}' ): array
|
||||
{
|
||||
$replacements = [];
|
||||
foreach ( $model->messageFields as $field ) {
|
||||
list( $nickName , $value ) = $this->getFieldValue( $model , $field );
|
||||
$replacements[ $prefix . $nickName . $postfix ] = $value;
|
||||
}
|
||||
if ( config( 'notification.fields' ) ) {
|
||||
foreach ( config( 'notification.fields' ) as $name => $field ) {
|
||||
$replacements[ $prefix . $name . $postfix ] = $field;
|
||||
}
|
||||
}
|
||||
return $replacements;
|
||||
}
|
||||
|
||||
protected function getFieldValue( Model $model , string $messageField ): array
|
||||
{
|
||||
$parts = explode( ' as ' , $messageField );
|
||||
if ( count( $parts ) == 2 and $this->isRelation( $parts[ 0 ] ) ) {
|
||||
list( $relation , $field ) = $this->splitRelationField( $parts[ 0 ] );
|
||||
$model->loadMissing( $relation );
|
||||
$key = $parts[ 1 ];
|
||||
$value = $model->$relation ? $model->$relation->$field : '';
|
||||
} else {
|
||||
$key = $messageField;
|
||||
$value = $model->$messageField;
|
||||
}
|
||||
return [ $key , $value ];
|
||||
}
|
||||
|
||||
protected function isRelation( $field ): bool
|
||||
{
|
||||
return str_contains( $field , ':' );
|
||||
}
|
||||
|
||||
protected function splitRelationField( $field ): array
|
||||
{
|
||||
$parts = explode( ':' , $field );
|
||||
$partsCount = count( $parts );
|
||||
return [ implode( '.' , array_slice( $parts , 0 , $partsCount - 1 ) ) , $parts[ $partsCount - 1 ] ];
|
||||
}
|
||||
|
||||
public function getPattern(): string
|
||||
{
|
||||
return $this->pattern;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Notification;
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
class SendSmsToAdmins
|
||||
{
|
||||
protected array $mobiles;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->mobiles = [
|
||||
"09101526570",
|
||||
"09128529050"
|
||||
];
|
||||
}
|
||||
|
||||
public function sendRequestNotification($device_title, $smsUser)
|
||||
{
|
||||
$adminCollection = User::query()
|
||||
->orWhere('role', 'admin');
|
||||
|
||||
$adminText = "کاربر %s
|
||||
با شماره ی همراه %s
|
||||
درخواستی زیر را ثبت کرد\n
|
||||
%s\n";
|
||||
$adminText = sprintf($adminText, $smsUser->full_name, $smsUser->cell_number, $device_title);
|
||||
SmsNotification::to($adminCollection)->isSystematic()->send(
|
||||
$adminText,
|
||||
'service'
|
||||
);
|
||||
|
||||
|
||||
$userText = "%s عزیز\n
|
||||
درخواست شما را دریافت کردیم\n
|
||||
به زودی همکاران ما با شما تماس خواهند گرفت\n
|
||||
از اعتماد شما سپاسگزاریم\n";
|
||||
$userText = sprintf($userText, $smsUser->full_name);
|
||||
$userCollection = User::query()->where('id', $smsUser->id);
|
||||
$res = SmsNotification::to($userCollection)->isSystematic()->send(
|
||||
$userText,
|
||||
'service'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Notification;
|
||||
|
||||
use App\Models\SmsBatch;
|
||||
use App\Services\Notification\Batch\PeerToPeer;
|
||||
use App\Services\Notification\Batch\SimCard;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class SmsNotification
|
||||
{
|
||||
protected $builder;
|
||||
protected string $category;
|
||||
protected $userData;
|
||||
protected bool $isSystematic = false;
|
||||
protected bool $isAdmin = false;
|
||||
|
||||
protected static $self = null;
|
||||
|
||||
private function __construct($builder, $userData)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
$this->userData = $userData;
|
||||
$this->category = $this->builder->limit(2)->count() > 1 ? 'batch' : 'single';
|
||||
|
||||
}
|
||||
|
||||
public function setBuilder($builder): static
|
||||
{
|
||||
$this->builder = $builder;
|
||||
$this->category = $this->builder->limit(2)->count() > 1 ? 'batch' : 'single';
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setUserData($userData): static
|
||||
{
|
||||
$this->userData = $userData;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public static function to($builder, $userData = null)
|
||||
{
|
||||
if (static::$self === null) {
|
||||
static::$self = new static($builder, $userData);
|
||||
}
|
||||
return static::$self;
|
||||
}
|
||||
|
||||
public function isSystematic(): static
|
||||
{
|
||||
$this->isSystematic = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isAdmin(): static
|
||||
{
|
||||
$this->isAdmin = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function sendAgain(SmsBatch $smsBatch): void
|
||||
{
|
||||
$uniqueCode = Str::random(40);
|
||||
foreach ($this->chuncks() as $notification) {
|
||||
switch ($smsBatch->type) {
|
||||
case 'advertise':
|
||||
(new PeerToPeer($smsBatch->pattern, $notification, $this->category, $uniqueCode))->isAdmin($this->isAdmin)->isSystematic($this->isSystematic)->sendAgain($this->userData,
|
||||
$smsBatch);
|
||||
break;
|
||||
case 'simcard' :
|
||||
(new SimCard($smsBatch->pattern, $notification, $this->category, $uniqueCode))->isAdmin($this->isAdmin)->isSystematic($this->isSystematic)->sendAgain($this->userData, $smsBatch);
|
||||
break;
|
||||
case 'service':
|
||||
(new PeerToPeer($smsBatch->pattern, $notification, $this->category, $uniqueCode, 'service'))->isAdmin($this->isAdmin)->isSystematic($this->isSystematic)->sendAgain($this->userData,
|
||||
$smsBatch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function send($message, $method = 'advertise'): void
|
||||
{
|
||||
$uniqueCode = Str::random(40);
|
||||
foreach ($this->chuncks() as $notification) {
|
||||
switch ($method) {
|
||||
case 'advertise':
|
||||
(new PeerToPeer($message, $notification, $this->category, $uniqueCode))->isAdmin($this->isAdmin)->isSystematic($this->isSystematic)->send($this->userData);
|
||||
break;
|
||||
case 'simcard' :
|
||||
(new SimCard($message, $notification, $this->category, $uniqueCode))->isAdmin($this->isAdmin)->isSystematic($this->isSystematic)->send($this->userData);
|
||||
break;
|
||||
case 'service':
|
||||
(new PeerToPeer($message, $notification, $this->category, $uniqueCode, 'service'))->isAdmin($this->isAdmin)->isSystematic($this->isSystematic)->send($this->userData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function sendWithTemplate($template): void
|
||||
{
|
||||
if ( ! is_null($template)) {
|
||||
$this->send($template->template, $template->operator);
|
||||
}
|
||||
}
|
||||
|
||||
protected function chuncks(): \Generator
|
||||
{
|
||||
$limit = config('notification.max_phone_size.do_send_sms_array_c');
|
||||
$iteration = 0;
|
||||
while (true) {
|
||||
$offset = $iteration * $limit;
|
||||
$chunk = $this->builder->offset($offset)->limit($limit)->get();
|
||||
if ($chunk->isEmpty()) {
|
||||
break;
|
||||
}
|
||||
$iteration++;
|
||||
yield $chunk;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Sms;
|
||||
|
||||
return [
|
||||
|
||||
'db_name' => 'willaengine',
|
||||
|
||||
'morph_models' => [],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value determines which of drivers should be used.
|
||||
|
|
||||
*/
|
||||
'default' => 'advertise',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Notification Configs
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| These are the list of configs to use for sending sms.
|
||||
|
|
||||
*/
|
||||
|
||||
'drivers' => [
|
||||
'advertise' => [
|
||||
'url' => 'http://188.0.240.110/class/sms/wsdlservice/server.php?wsdl',
|
||||
'username' => env('SMS_USERNAME'),
|
||||
'password' => env('SMS_PASSWORD'),
|
||||
'from' => env('SMS_NUMBER_ADVERTISE'),
|
||||
],
|
||||
'service' => [
|
||||
'url' => 'http://188.0.240.110/class/sms/wsdlservice/server.php?wsdl',
|
||||
'username' => env('SMS_USERNAME'),
|
||||
'password' => env('SMS_PASSWORD'),
|
||||
'from' => env('SMS_NUMBER_SERVICE'),
|
||||
],
|
||||
'simcard' => [
|
||||
'url' => 'http://188.0.240.110/class/sms/wsdlservice/server.php?wsdl',
|
||||
'username' => env('SMS_USERNAME'),
|
||||
'password' => env('SMS_PASSWORD'),
|
||||
'from' => env('SMS_NUMBER_SIM_CARD'),
|
||||
'fee' => 150
|
||||
],
|
||||
'pattern' => [
|
||||
'url' => 'http://188.0.240.110/class/sms/wsdlservice/server.php?wsdl',
|
||||
'username' => env('SMS_USERNAME'),
|
||||
'password' => env('SMS_PASSWORD'),
|
||||
'from' => env('SMS_NUMBER_SERVICE'),
|
||||
],
|
||||
'rahyab_advertise' => [
|
||||
'url' => 'https://sms.igama.ir/webservice/sms.asmx?wsdl',
|
||||
'username' => env('RAHYAB_SMS_USERNAME'),
|
||||
'password' => env('RAHYAB_SMS_PASSWORD'),
|
||||
'from' => env('RAHYAB_SMS_NUMBER_ADVERTISE'),
|
||||
'fee' => 100
|
||||
],
|
||||
'rahyab_service' => [
|
||||
'url' => 'https://sms.igama.ir/webservice/sms.asmx?wsdl',
|
||||
'username' => env('RAHYAB_SMS_USERNAME'),
|
||||
'password' => env('RAHYAB_SMS_PASSWORD'),
|
||||
'from' => env('RAHYAB_SMS_NUMBER_SERVICE'),
|
||||
'fee' => 80
|
||||
],
|
||||
],
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Class Maps
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is the array of Classes that maps to Drivers above.
|
||||
|
|
||||
*/
|
||||
'map' => [
|
||||
'advertise' => Sms::class,
|
||||
'service' => Sms::class,
|
||||
'simcard' => Sms::class,
|
||||
'pattern' => SmsPattern::class,
|
||||
'rahyab_advertise' => HelloWorld::class,
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Fields Pattern
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is the array of fields that used in sms patterns.
|
||||
|
|
||||
*/
|
||||
|
||||
'fields' => [
|
||||
'time' => now('Asia/Tehran')->format('H:i:s'),
|
||||
'date' => now('Asia/Tehran')->format('Y/m/d')
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| MAXIMUM NUMBER OF PHONE NUMBERS IN ONE BATCH
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| CAUTION!! DONT TOUCH THESE NUMBERS
|
||||
|
|
||||
*/
|
||||
|
||||
'max_phone_size' => [
|
||||
'do_send_sms' => 83,
|
||||
'do_send_sms_array_c' => 100,
|
||||
],
|
||||
'max_update_devlivery_status_bulk_items' => 100,
|
||||
'sms_length_calculator' => [
|
||||
'encoding' => '8', //bit
|
||||
'chars_in_every_sms_part' => 63
|
||||
],
|
||||
|
||||
|
||||
'config_system' => [],
|
||||
|
||||
];
|
||||
@@ -0,0 +1,37 @@
|
||||
<?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('sms', function (Blueprint $table) {
|
||||
$table->increments( 'id' );
|
||||
$table->unsignedBigInteger( 'client_id' )->nullable();
|
||||
$table->string( 'status' );
|
||||
$table->string( 'message' , 100 );
|
||||
$table->unsignedInteger( 'rel_id' );
|
||||
$table->string( 'rel_type' , 50 );
|
||||
$table->string( 'cell_number' , 20 );
|
||||
$table->unsignedInteger( 'fee' )->default( 0 );
|
||||
$table->unsignedInteger( 'sms_batch_id' );
|
||||
$table->index( 'sms_batch_id' );
|
||||
$table->integer( 'segment_count' )->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('sms');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
<?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('sms_batch', function (Blueprint $table) {
|
||||
$table->increments( 'id' );
|
||||
$table->string( 'category' );
|
||||
$table->string( 'operator' , 100 );
|
||||
$table->enum( 'type' , [ 'service' , 'simcard' , 'advertise' ] );
|
||||
$table->string( 'code' , 40 );
|
||||
$table->string( 'pattern' )->nullable();
|
||||
$table->boolean( 'is_admin' )->default( 0 );
|
||||
$table->boolean( 'is_systematic' )->default( 0 );
|
||||
$table->string( 'from' )->nullable();
|
||||
$table->softDeletes();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('sms_batch');
|
||||
}
|
||||
};
|
||||
@@ -4,10 +4,11 @@ namespace Packages\Auth;
|
||||
|
||||
use App\Http\Controllers\Api\Auth\LoginController;
|
||||
use App\Models\User;
|
||||
use App\Services\Notification\SmsNotification;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Packages\Messaging\src\Facades\MessageResponse;
|
||||
use Packages\SMSSender\SMSSender;
|
||||
// use Packages\SMSSender\SMSSender;
|
||||
|
||||
trait SendsPasswordResetEmails
|
||||
{
|
||||
@@ -61,7 +62,13 @@ trait SendsPasswordResetEmails
|
||||
if ($user) {
|
||||
$code = rand(100000, 999999);
|
||||
\Cache::put($code, $user->id, Carbon::now()->addMinutes(30));
|
||||
SMSSender::instance()->patternSend($request->cell_number, 'jqomyn42wo', ["verification-code" => $code]);
|
||||
SmsNotification::to( $user )->isSystematic()->send(
|
||||
trans( 'sms.reset_password' , [
|
||||
'activation_code' => $code
|
||||
] ) ,
|
||||
'service'
|
||||
);
|
||||
// SMSSender::instance()->patternSend($request->cell_number, 'jqomyn42wo', ["verification-code" => $code]);
|
||||
return MessageResponse::success('Send Disposable Password');
|
||||
}
|
||||
return MessageResponse::error('User Not Found');
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'reset_password' => 'لطفا پس از ورود یک پسوورد جدید بذارید',
|
||||
];
|
||||
Reference in New Issue
Block a user